blob: d2ab20a2a80c7c1e60ca216980d2a9099fb0741b (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/**
* Type definitions for the Makima Cloudflare Agent.
*
* These types mirror the daemon-server WebSocket protocol defined in
* makima/src/daemon/ws/protocol.rs. Only the subset relevant to the
* edge relay is included here.
*/
// ---------------------------------------------------------------------------
// Worker Environment
// ---------------------------------------------------------------------------
export interface Env {
/** Durable Object binding for MakimaAgent instances. */
MAKIMA_AGENT: DurableObjectNamespace;
/** Makima server WebSocket URL (e.g. wss://api.makima.jp). */
MAKIMA_SERVER_URL: string;
/** API key for authenticating with the Makima server. */
MAKIMA_API_KEY: string;
/** Optional: human-readable name for this edge agent. */
MAKIMA_AGENT_NAME?: string;
}
// ---------------------------------------------------------------------------
// Agent State (persisted in Durable Object SQLite)
// ---------------------------------------------------------------------------
export interface AgentState {
/** Whether the upstream WebSocket is currently connected. */
connected: boolean;
/** ISO-8601 timestamp of last successful connection. */
lastConnectedAt: string | null;
/** ISO-8601 timestamp of last heartbeat sent. */
lastHeartbeatAt: string | null;
/** Number of consecutive reconnect failures. */
reconnectAttempts: number;
/** Daemon ID assigned by the server after authentication. */
daemonId: string | null;
/** Active task IDs being tracked through this relay. */
activeTasks: string[];
}
export const DEFAULT_AGENT_STATE: AgentState = {
connected: false,
lastConnectedAt: null,
lastHeartbeatAt: null,
reconnectAttempts: 0,
daemonId: null,
activeTasks: [],
};
// ---------------------------------------------------------------------------
// Daemon → Server Messages (subset used by the relay)
// ---------------------------------------------------------------------------
export type DaemonMessage =
| { type: "authenticate"; apiKey: string; machineId: string; hostname: string; maxConcurrentTasks: number }
| { type: "heartbeat"; activeTasks: string[] }
| { type: "taskOutput"; taskId: string; output: string; isPartial: boolean }
| { type: "taskStatusChange"; taskId: string; oldStatus: string; newStatus: string }
| { type: "taskProgress"; taskId: string; summary: string }
| { type: "taskComplete"; taskId: string; success: boolean; error?: string };
// ---------------------------------------------------------------------------
// Server → Daemon Commands (subset relevant to the relay)
// ---------------------------------------------------------------------------
export type DaemonCommand =
| { type: "authenticated"; daemonId: string }
| { type: "spawnTask"; taskId: string; taskName: string; plan: string; repoUrl?: string; baseBranch?: string; targetBranch?: string; contractId?: string; depth: number; isOrchestrator: boolean }
| { type: "pauseTask"; taskId: string }
| { type: "resumeTask"; taskId: string }
| { type: "interruptTask"; taskId: string; graceful: boolean }
| { type: "sendMessage"; taskId: string; message: string };
// ---------------------------------------------------------------------------
// Task History Record (stored in SQLite)
// ---------------------------------------------------------------------------
export interface TaskRecord {
/** UUID of the task. */
taskId: string;
/** Human-readable task name. */
taskName: string;
/** Current status: pending | dispatched | completed | failed. */
status: string;
/** Which downstream daemon received this task. */
dispatchedTo: string | null;
/** ISO-8601 timestamp when the task was received. */
receivedAt: string;
/** ISO-8601 timestamp when the task was dispatched downstream. */
dispatchedAt: string | null;
/** ISO-8601 timestamp when the task completed. */
completedAt: string | null;
/** Error message if failed. */
error: string | null;
}
// ---------------------------------------------------------------------------
// Connected Downstream Daemon
// ---------------------------------------------------------------------------
export interface DownstreamDaemon {
/** Unique ID for this downstream connection. */
id: string;
/** WebSocket connection to this daemon. */
ws: WebSocket;
/** Human-readable hostname. */
hostname: string;
/** Maximum concurrent tasks this daemon supports. */
maxConcurrentTasks: number;
/** Currently active task IDs on this daemon. */
activeTasks: Set<string>;
/** ISO-8601 timestamp of last heartbeat received. */
lastHeartbeat: string;
}
// ---------------------------------------------------------------------------
// HTTP API Response Types
// ---------------------------------------------------------------------------
export interface StatusResponse {
status: "ok" | "degraded" | "disconnected";
agentName: string;
upstreamConnected: boolean;
daemonId: string | null;
lastHeartbeat: string | null;
connectedDaemons: number;
activeTasks: number;
totalTasksProcessed: number;
}
export interface TaskHistoryResponse {
tasks: TaskRecord[];
total: number;
limit: number;
offset: number;
}
// ---------------------------------------------------------------------------
// RPC method types for the Agent
// ---------------------------------------------------------------------------
export interface AgentRPC {
getStatus: () => StatusResponse;
getTaskHistory: (limit?: number, offset?: number) => TaskHistoryResponse;
reconnect: () => { success: boolean; message: string };
}
|