@songsid/agend 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/agent-cli.js +0 -0
- package/dist/cli.js +105 -32
- package/dist/cli.js.map +1 -1
- package/dist/fleet-manager.js +4 -1
- package/dist/fleet-manager.js.map +1 -1
- package/dist/general-knowledge/skills.md +95 -0
- package/dist/logger.d.ts +0 -2
- package/dist/logger.js +2 -16
- package/dist/logger.js.map +1 -1
- package/package.json +3 -5
- package/dist/fleet-dashboard-html.d.ts +0 -6
- package/dist/fleet-dashboard-html.js +0 -443
- package/dist/fleet-dashboard-html.js.map +0 -1
- package/dist/fleet-health-server.d.ts +0 -35
- package/dist/fleet-health-server.js +0 -290
- package/dist/fleet-health-server.js.map +0 -1
- package/dist/fleet-instructions.d.ts +0 -5
- package/dist/fleet-instructions.js +0 -161
- package/dist/fleet-instructions.js.map +0 -1
- package/dist/fleet-rpc-handlers.d.ts +0 -42
- package/dist/fleet-rpc-handlers.js +0 -356
- package/dist/fleet-rpc-handlers.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-dashboard-html.js","sourceRoot":"","sources":["../src/fleet-dashboard-html.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAob5B,CAAC"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { type Server } from "node:http";
|
|
2
|
-
import type { Logger } from "./logger.js";
|
|
3
|
-
import type { FleetConfig, InstanceConfig } from "./types.js";
|
|
4
|
-
import type { Scheduler } from "./scheduler/index.js";
|
|
5
|
-
import type { EventLog } from "./event-log.js";
|
|
6
|
-
import type { SysInfo } from "./fleet-context.js";
|
|
7
|
-
/**
|
|
8
|
-
* Extract a web token from a request, accepting (in order):
|
|
9
|
-
* 1. `?token=` query string
|
|
10
|
-
* 2. `Authorization: Bearer <token>` header (standard)
|
|
11
|
-
* 3. `X-Agend-Token: <token>` header (legacy compatibility)
|
|
12
|
-
*/
|
|
13
|
-
export declare function extractWebToken(parsedUrl: URL, headers: Record<string, string | string[] | undefined>): string | null;
|
|
14
|
-
export interface UiStatusContext {
|
|
15
|
-
readonly fleetConfig: FleetConfig | null;
|
|
16
|
-
readonly logger: Logger;
|
|
17
|
-
getInstanceDir(name: string): string;
|
|
18
|
-
getInstanceStatus(name: string): "running" | "stopped" | "crashed";
|
|
19
|
-
}
|
|
20
|
-
export interface HealthServerContext extends UiStatusContext {
|
|
21
|
-
readonly dataDir: string;
|
|
22
|
-
readonly scheduler: Scheduler | null;
|
|
23
|
-
readonly eventLog: EventLog | null;
|
|
24
|
-
getSysInfo(): SysInfo;
|
|
25
|
-
lastActivityMs(name: string): number;
|
|
26
|
-
startInstance(name: string, config: InstanceConfig, topicMode: boolean): Promise<void>;
|
|
27
|
-
restartSingleInstance(name: string): Promise<void>;
|
|
28
|
-
emitSseEvent(event: string, data: unknown): void;
|
|
29
|
-
}
|
|
30
|
-
export declare function startHealthServer(ctx: HealthServerContext, port: number): {
|
|
31
|
-
server: Server;
|
|
32
|
-
webToken: string;
|
|
33
|
-
startedAt: number;
|
|
34
|
-
};
|
|
35
|
-
export declare function getUiStatus(ctx: UiStatusContext, startedAt: number): unknown;
|
|
@@ -1,290 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Health / dashboard HTTP server for the daemon.
|
|
3
|
-
*
|
|
4
|
-
* Exposes:
|
|
5
|
-
* - GET /health (public, no auth)
|
|
6
|
-
* - GET /status (basic per-instance snapshot)
|
|
7
|
-
* - GET /api/fleet (enriched fleet snapshot for the UI)
|
|
8
|
-
* - GET /api/activity (event log entries; ?since= ?limit=)
|
|
9
|
-
* - GET /activity (HTML viewer; served from fleet-dashboard-html.ts)
|
|
10
|
-
* - POST /api/instance/:name/start
|
|
11
|
-
* - POST /restart/:name
|
|
12
|
-
* - POST /agent (forwarded to handleAgentRequest)
|
|
13
|
-
* - GET /ui/* (forwarded to handleWebRequest)
|
|
14
|
-
*
|
|
15
|
-
* All endpoints except /health require a Bearer / ?token= match against
|
|
16
|
-
* the per-process web token written to <dataDir>/web.token (mode 0600).
|
|
17
|
-
*
|
|
18
|
-
* Extracted from fleet-manager.ts (P4.1 step 4 of 4).
|
|
19
|
-
*/
|
|
20
|
-
import { existsSync, readFileSync, writeFileSync, chmodSync } from "node:fs";
|
|
21
|
-
import { createServer } from "node:http";
|
|
22
|
-
import { randomBytes } from "node:crypto";
|
|
23
|
-
import { join } from "node:path";
|
|
24
|
-
import { ACTIVITY_VIEWER_HTML } from "./fleet-dashboard-html.js";
|
|
25
|
-
import { handleAgentRequest } from "./agent-endpoint.js";
|
|
26
|
-
import { handleWebRequest } from "./web-api.js";
|
|
27
|
-
/**
|
|
28
|
-
* Extract a web token from a request, accepting (in order):
|
|
29
|
-
* 1. `?token=` query string
|
|
30
|
-
* 2. `Authorization: Bearer <token>` header (standard)
|
|
31
|
-
* 3. `X-Agend-Token: <token>` header (legacy compatibility)
|
|
32
|
-
*/
|
|
33
|
-
export function extractWebToken(parsedUrl, headers) {
|
|
34
|
-
const queryToken = parsedUrl.searchParams.get("token");
|
|
35
|
-
if (queryToken)
|
|
36
|
-
return queryToken;
|
|
37
|
-
const auth = headers["authorization"];
|
|
38
|
-
const authStr = Array.isArray(auth) ? auth[0] : auth;
|
|
39
|
-
if (authStr && /^Bearer\s+/i.test(authStr)) {
|
|
40
|
-
return authStr.replace(/^Bearer\s+/i, "").trim();
|
|
41
|
-
}
|
|
42
|
-
const headerToken = headers["x-agend-token"];
|
|
43
|
-
if (typeof headerToken === "string")
|
|
44
|
-
return headerToken;
|
|
45
|
-
if (Array.isArray(headerToken) && headerToken.length > 0)
|
|
46
|
-
return headerToken[0];
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
export function startHealthServer(ctx, port) {
|
|
50
|
-
let server;
|
|
51
|
-
const startedAt = Date.now();
|
|
52
|
-
// Generate web token before server starts so auth is enforced from the first request.
|
|
53
|
-
const webToken = randomBytes(24).toString("hex");
|
|
54
|
-
const tokenPath = join(ctx.dataDir, "web.token");
|
|
55
|
-
writeFileSync(tokenPath, webToken, { mode: 0o600 });
|
|
56
|
-
// Defensive: if file existed previously with looser perms, tighten it.
|
|
57
|
-
try {
|
|
58
|
-
chmodSync(tokenPath, 0o600);
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
// best-effort
|
|
62
|
-
}
|
|
63
|
-
server = createServer((req, res) => {
|
|
64
|
-
res.setHeader("Content-Type", "application/json");
|
|
65
|
-
// Public health probe — no auth required.
|
|
66
|
-
if (req.method === "GET" && req.url === "/health") {
|
|
67
|
-
// fallthrough to existing handler below
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
// All other endpoints require a valid token. Accepts ?token= query,
|
|
71
|
-
// Authorization: Bearer <token>, or legacy X-Agend-Token header.
|
|
72
|
-
// /ui/* will also re-check in web-api.ts, which is harmless.
|
|
73
|
-
const parsedUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
74
|
-
const providedToken = extractWebToken(parsedUrl, req.headers);
|
|
75
|
-
if (!webToken || providedToken !== webToken) {
|
|
76
|
-
res.writeHead(401);
|
|
77
|
-
res.end(JSON.stringify({ error: "Unauthorized" }));
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (req.method === "GET" && req.url === "/health") {
|
|
82
|
-
const instanceCount = ctx.fleetConfig?.instances
|
|
83
|
-
? Object.keys(ctx.fleetConfig.instances).length
|
|
84
|
-
: 0;
|
|
85
|
-
res.writeHead(200);
|
|
86
|
-
res.end(JSON.stringify({
|
|
87
|
-
status: "ok",
|
|
88
|
-
instances: instanceCount,
|
|
89
|
-
uptime: Math.floor((Date.now() - startedAt) / 1000),
|
|
90
|
-
}));
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
if (req.method === "GET" && req.url === "/status") {
|
|
94
|
-
const instances = Object.keys(ctx.fleetConfig?.instances ?? {}).map(name => {
|
|
95
|
-
const statusFile = join(ctx.getInstanceDir(name), "statusline.json");
|
|
96
|
-
let context_pct = 0;
|
|
97
|
-
let cost = 0;
|
|
98
|
-
try {
|
|
99
|
-
const data = JSON.parse(readFileSync(statusFile, "utf-8"));
|
|
100
|
-
context_pct = data.context_window?.used_percentage ?? 0;
|
|
101
|
-
cost = data.cost?.total_cost_usd ?? 0;
|
|
102
|
-
}
|
|
103
|
-
catch (err) {
|
|
104
|
-
ctx.logger.debug({ err, name }, "statusline.json read failed (/status)");
|
|
105
|
-
}
|
|
106
|
-
return {
|
|
107
|
-
name,
|
|
108
|
-
status: ctx.getInstanceStatus(name),
|
|
109
|
-
context_pct,
|
|
110
|
-
cost,
|
|
111
|
-
};
|
|
112
|
-
});
|
|
113
|
-
res.writeHead(200);
|
|
114
|
-
res.end(JSON.stringify({ instances }));
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
// Fleet API (enriched for agent board)
|
|
118
|
-
if (req.method === "GET" && req.url === "/api/fleet") {
|
|
119
|
-
const sysInfo = ctx.getSysInfo();
|
|
120
|
-
const enriched = sysInfo.instances.map(inst => {
|
|
121
|
-
const config = ctx.fleetConfig?.instances[inst.name];
|
|
122
|
-
// Find claimed tasks for this instance
|
|
123
|
-
let currentTask = null;
|
|
124
|
-
try {
|
|
125
|
-
const tasks = ctx.scheduler?.db.listTasks({ assignee: inst.name, status: "claimed" });
|
|
126
|
-
if (tasks?.length)
|
|
127
|
-
currentTask = tasks[0].title;
|
|
128
|
-
}
|
|
129
|
-
catch (err) {
|
|
130
|
-
ctx.logger.debug({ err, name: inst.name }, "Scheduler listTasks failed (/api/fleet)");
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
...inst,
|
|
134
|
-
description: config?.description ?? null,
|
|
135
|
-
backend: config?.backend ?? "claude-code",
|
|
136
|
-
tool_set: config?.tool_set ?? "full",
|
|
137
|
-
general_topic: config?.general_topic ?? false,
|
|
138
|
-
lastActivity: ctx.lastActivityMs(inst.name) || null,
|
|
139
|
-
currentTask,
|
|
140
|
-
};
|
|
141
|
-
});
|
|
142
|
-
// Same-origin only — token-bearing requests come from the dashboard
|
|
143
|
-
// served by this same daemon, so no CORS allowance is needed.
|
|
144
|
-
res.writeHead(200);
|
|
145
|
-
res.end(JSON.stringify({
|
|
146
|
-
...sysInfo,
|
|
147
|
-
instances: enriched,
|
|
148
|
-
}));
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
// Activity API
|
|
152
|
-
if (req.method === "GET" && req.url?.startsWith("/api/activity")) {
|
|
153
|
-
const url = new URL(req.url, `http://localhost:${port}`);
|
|
154
|
-
const sinceParam = url.searchParams.get("since") ?? "2h";
|
|
155
|
-
const limitParam = url.searchParams.get("limit") ?? "500";
|
|
156
|
-
const match = sinceParam.match(/^(\d+)(m|h|d)$/);
|
|
157
|
-
let sinceIso;
|
|
158
|
-
if (match) {
|
|
159
|
-
const val = parseInt(match[1], 10);
|
|
160
|
-
const unit = match[2] === "d" ? 86400000 : match[2] === "h" ? 3600000 : 60000;
|
|
161
|
-
sinceIso = new Date(Date.now() - val * unit).toISOString();
|
|
162
|
-
}
|
|
163
|
-
const rows = ctx.eventLog?.listActivity({ since: sinceIso, limit: parseInt(limitParam, 10) }) ?? [];
|
|
164
|
-
// Same-origin only — see /api/fleet rationale.
|
|
165
|
-
res.writeHead(200);
|
|
166
|
-
res.end(JSON.stringify(rows));
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
// Activity viewer
|
|
170
|
-
if (req.method === "GET" && (req.url === "/activity" || req.url === "/activity/")) {
|
|
171
|
-
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
172
|
-
res.writeHead(200);
|
|
173
|
-
res.end(ACTIVITY_VIEWER_HTML);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
// Instance start via API
|
|
177
|
-
if (req.method === "POST" && req.url?.startsWith("/api/instance/") && req.url.endsWith("/start")) {
|
|
178
|
-
const name = decodeURIComponent(req.url.slice("/api/instance/".length, -"/start".length));
|
|
179
|
-
const config = ctx.fleetConfig?.instances[name];
|
|
180
|
-
if (!config) {
|
|
181
|
-
res.writeHead(404);
|
|
182
|
-
res.end(JSON.stringify({ error: `Instance not found: ${name}` }));
|
|
183
|
-
return;
|
|
184
|
-
}
|
|
185
|
-
(async () => {
|
|
186
|
-
try {
|
|
187
|
-
const topicMode = ctx.fleetConfig?.channel?.mode === "topic";
|
|
188
|
-
await ctx.startInstance(name, config, topicMode ?? false);
|
|
189
|
-
ctx.emitSseEvent("status", getUiStatus(ctx, startedAt));
|
|
190
|
-
res.writeHead(200);
|
|
191
|
-
res.end(JSON.stringify({ ok: true }));
|
|
192
|
-
}
|
|
193
|
-
catch (err) {
|
|
194
|
-
res.writeHead(500);
|
|
195
|
-
res.end(JSON.stringify({ error: `Start failed: ${err.message}` }));
|
|
196
|
-
}
|
|
197
|
-
})();
|
|
198
|
-
return;
|
|
199
|
-
}
|
|
200
|
-
// Instance restart (immediate, no idle wait)
|
|
201
|
-
if (req.method === "POST" && req.url?.startsWith("/restart/")) {
|
|
202
|
-
const name = decodeURIComponent(req.url.slice("/restart/".length));
|
|
203
|
-
ctx.logger.info({ name }, "Instance restart requested via HTTP");
|
|
204
|
-
(async () => {
|
|
205
|
-
try {
|
|
206
|
-
await ctx.restartSingleInstance(name);
|
|
207
|
-
ctx.logger.info({ name }, "Instance restarted");
|
|
208
|
-
ctx.emitSseEvent("status", getUiStatus(ctx, startedAt));
|
|
209
|
-
res.writeHead(200);
|
|
210
|
-
res.end(JSON.stringify({ restarted: name }));
|
|
211
|
-
}
|
|
212
|
-
catch (err) {
|
|
213
|
-
ctx.logger.error({ err, name }, "Instance restart failed");
|
|
214
|
-
const status = err.message.includes("not found") ? 404 : 500;
|
|
215
|
-
res.writeHead(status);
|
|
216
|
-
res.end(JSON.stringify({ error: `Restart failed: ${err.message}` }));
|
|
217
|
-
}
|
|
218
|
-
})();
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
|
-
// ── Agent CLI endpoint ─────
|
|
222
|
-
if (req.url === "/agent" && req.method === "POST") {
|
|
223
|
-
handleAgentRequest(req, res, ctx);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
// ── Web UI endpoints (delegated to web-api.ts) ─────
|
|
227
|
-
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
228
|
-
if (handleWebRequest(req, res, url, ctx))
|
|
229
|
-
return;
|
|
230
|
-
res.writeHead(404);
|
|
231
|
-
res.end(JSON.stringify({ error: "not found" }));
|
|
232
|
-
});
|
|
233
|
-
server.on("error", (err) => {
|
|
234
|
-
if (err.code === "EADDRINUSE") {
|
|
235
|
-
ctx.logger.warn({ port }, "Health port in use — attempting takeover");
|
|
236
|
-
const pidPath = join(ctx.dataDir, "fleet.pid");
|
|
237
|
-
try {
|
|
238
|
-
if (existsSync(pidPath)) {
|
|
239
|
-
const oldPid = parseInt(readFileSync(pidPath, "utf-8").trim(), 10);
|
|
240
|
-
if (oldPid && oldPid !== process.pid) {
|
|
241
|
-
process.kill(oldPid, "SIGTERM");
|
|
242
|
-
ctx.logger.info({ oldPid }, "Killed old fleet process");
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
catch (err) {
|
|
247
|
-
ctx.logger.debug({ err }, "Old fleet process kill skipped (already gone or no permission)");
|
|
248
|
-
}
|
|
249
|
-
setTimeout(() => {
|
|
250
|
-
if (!server)
|
|
251
|
-
return;
|
|
252
|
-
server.listen(port, "127.0.0.1", () => {
|
|
253
|
-
ctx.logger.info({ port }, "Health endpoint listening (after takeover)");
|
|
254
|
-
}).on("error", () => {
|
|
255
|
-
ctx.logger.warn({ port }, "Health port still in use — skipping health endpoint");
|
|
256
|
-
});
|
|
257
|
-
}, 1500);
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
ctx.logger.error({ err, port }, "Health server error");
|
|
261
|
-
});
|
|
262
|
-
server.listen(port, "127.0.0.1", () => {
|
|
263
|
-
ctx.logger.info({ port }, "Health endpoint listening");
|
|
264
|
-
});
|
|
265
|
-
ctx.logger.info({ url: `http://localhost:${port}/ui?token=${webToken}` }, "Web UI available");
|
|
266
|
-
return { server, webToken, startedAt };
|
|
267
|
-
}
|
|
268
|
-
export function getUiStatus(ctx, startedAt) {
|
|
269
|
-
const instances = Object.keys(ctx.fleetConfig?.instances ?? {}).map(name => {
|
|
270
|
-
const statusFile = join(ctx.getInstanceDir(name), "statusline.json");
|
|
271
|
-
let context_pct = 0;
|
|
272
|
-
let cost = 0;
|
|
273
|
-
let model = "";
|
|
274
|
-
try {
|
|
275
|
-
const data = JSON.parse(readFileSync(statusFile, "utf-8"));
|
|
276
|
-
context_pct = data.context_window?.used_percentage ?? 0;
|
|
277
|
-
cost = data.cost?.total_cost_usd ?? 0;
|
|
278
|
-
model = data.model?.display_name ?? "";
|
|
279
|
-
}
|
|
280
|
-
catch (err) {
|
|
281
|
-
ctx.logger.debug({ err, name }, "statusline.json read failed (getUiStatus)");
|
|
282
|
-
}
|
|
283
|
-
return { name, status: ctx.getInstanceStatus(name), context_pct, cost, model };
|
|
284
|
-
});
|
|
285
|
-
return {
|
|
286
|
-
instances,
|
|
287
|
-
uptime: Math.floor((Date.now() - startedAt) / 1000),
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
//# sourceMappingURL=fleet-health-server.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-health-server.js","sourceRoot":"","sources":["../src/fleet-health-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Logger } from "./logger.js";
|
|
2
|
-
export declare const INSTRUCTIONS_FILENAME: Record<string, string>;
|
|
3
|
-
export declare const GENERAL_INSTRUCTIONS = "# Fleet Coordinator\n\nYou are the fleet coordinator \u2014 the central entry point for this AgEnD fleet.\nYou route tasks, manage instances, enforce policies, and synthesize results.\nDo NOT modify project files directly \u2014 delegate file changes to the project's instance.\nYou CAN write code snippets, explain code, and answer technical questions directly.\n\n-----\n\n## Task Classification\n\nClassify every incoming request before acting.\n\n### Handle Directly (ALL conditions must be true)\n\n- No file system access needed\n- No external execution needed\n- Answerable from static knowledge\n- \u2264 2 reasoning steps\n\nExamples: Q&A, translation, fleet status queries, explaining a concept, writing code snippets.\n\n### Delegate to 1 Instance\n\n- Task scoped to a single project or repo\n- Requires file access, code changes, or execution\n\n### Coordinate Multiple Instances\n\n- Task spans multiple repos or domains\n- Requires outputs from one instance to feed into another\n- Benefits from parallel execution (max 3 instances per task)\n\n-----\n\n## Instance Discovery (in this order)\n1. list_teams() \u2192 reuse existing teams first\n2. list_instances() \u2192 find by working_directory, description, or tags\n3. describe_instance() \u2192 confirm capabilities before delegating\n4. create_instance() \u2192 only if no suitable instance exists\n\nRules: prefer reuse over creation. Do NOT create duplicates of running instances.\n\n-----\n\n## Delegation Protocol\n\nEvery delegation via send_to_instance() MUST include:\n\n1. Task scope \u2014 what exactly to do, bounded clearly\n2. Expected output \u2014 what to return and in what form\n3. Policy reminder \u2014 \"Follow Development Workflow policy\" (for code tasks)\n\n### Loop Prevention\n\n- Never re-delegate a task back to the instance that sent it to you\n- If a task has bounced 3 times, stop and solve locally or reduce scope\n\n### Execution Strategy\n\nParallel \u2014 use only when tasks are independent with no shared state\nSequential \u2014 use when one task's output feeds into the next\n\n-----\n\n## Result Handling\n\nWhen an instance reports back, classify the outcome:\n\n- Success \u2192 Summarize key results for user. Omit internal coordination noise.\n- Partial \u2192 State what succeeded, what remains, proposed next steps.\n- Failure \u2192 Retry up to 2 times. If still failing: try alternative instance, reduce scope, or return partial result clearly marked.\n- No response \u2192 Ping again after reasonable wait. If still silent: report to user with options.\n\n### Output to User\n\nEvery final response to the user should contain:\n\n- Result \u2014 the actual answer or deliverable\n- Gaps \u2014 anything incomplete or unresolved (omit if none)\n\n-----\n\n## Shared Decisions\n\nUse post_decision() / list_decisions() for any choice that affects more than 1 instance, changes an API contract, introduces a new dependency, or alters deployment process.\n\nWhen instances disagree, collect both viewpoints, make a decision, and record it via post_decision.\n\n-----\n\n## Context Rotation Bootstrap\n\nAfter your context rotates, run this sequence BEFORE processing any new messages:\n1. list_instances() \u2192 rebuild fleet awareness\n2. list_teams() \u2192 restore team structure\n3. list_decisions() \u2192 reload policies and conventions\n\nOnly then handle incoming requests.\n\n-----\n\n## Development Workflow Policy\n\nAll code changes across the fleet should follow this workflow.\nThe coordinator enforces compliance but does not perform these steps directly.\nRemind instances of this policy when delegating code tasks.\n\n### Workflow Stages\nDesign Proposed \u2192 Design Approved \u2192 Implementation \u2192 Submit for Review \u2192 Under Review \u2192 Approved \u2192 Merge\n\n### Policy Rules\n\n1. Design before code \u2014 developer sends design proposal to reviewer before implementation. Consensus required before proceeding.\n2. Challenger pairing \u2014 every code task should have a developer + reviewer. Reviewer actively questions decisions and finds risks.\n3. Verify by execution \u2014 backend/CLI changes must be tested by running them. Do not trust documentation alone.\n4. Independent review \u2014 every merge requires code review from someone other than the author.\n5. Root cause first \u2014 bug fixes require confirmed root cause before proposing a fix.\n6. Merge conditions: tests pass, reviewer approved, branch and worktree cleaned up.\n\n### Specialist Instance Rules\n\n- Execute within defined scope only\n- Return structured output: result, assumptions, uncertainties, verification status\n- Do NOT create new instances without coordinator approval\n\n-----\n\n## Team Management\n\n- Always check existing teams before creating new ones\n- Default to ephemeral teams (created for a specific task, dissolved after completion)\n- Clean up ephemeral teams and instances after task completion\n";
|
|
4
|
-
/** Ensure the general (coordinator) instance has its project instructions file. */
|
|
5
|
-
export declare function ensureGeneralInstructions(workDir: string, backendName?: string, logger?: Logger): void;
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* General coordinator instance — system prompt + helpers for ensuring the
|
|
3
|
-
* coordinator's working directory has the per-backend instructions file.
|
|
4
|
-
* Extracted from fleet-manager.ts (P4.1).
|
|
5
|
-
*/
|
|
6
|
-
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
|
7
|
-
import { join, dirname } from "node:path";
|
|
8
|
-
export const INSTRUCTIONS_FILENAME = {
|
|
9
|
-
"claude-code": "CLAUDE.md",
|
|
10
|
-
"codex": "AGENTS.md",
|
|
11
|
-
"gemini-cli": "GEMINI.md",
|
|
12
|
-
"opencode": "AGENTS.md",
|
|
13
|
-
"kiro-cli": ".kiro/steering/project.md",
|
|
14
|
-
"mock": "CLAUDE.md",
|
|
15
|
-
};
|
|
16
|
-
export const GENERAL_INSTRUCTIONS = `# Fleet Coordinator
|
|
17
|
-
|
|
18
|
-
You are the fleet coordinator — the central entry point for this AgEnD fleet.
|
|
19
|
-
You route tasks, manage instances, enforce policies, and synthesize results.
|
|
20
|
-
Do NOT modify project files directly — delegate file changes to the project's instance.
|
|
21
|
-
You CAN write code snippets, explain code, and answer technical questions directly.
|
|
22
|
-
|
|
23
|
-
-----
|
|
24
|
-
|
|
25
|
-
## Task Classification
|
|
26
|
-
|
|
27
|
-
Classify every incoming request before acting.
|
|
28
|
-
|
|
29
|
-
### Handle Directly (ALL conditions must be true)
|
|
30
|
-
|
|
31
|
-
- No file system access needed
|
|
32
|
-
- No external execution needed
|
|
33
|
-
- Answerable from static knowledge
|
|
34
|
-
- ≤ 2 reasoning steps
|
|
35
|
-
|
|
36
|
-
Examples: Q&A, translation, fleet status queries, explaining a concept, writing code snippets.
|
|
37
|
-
|
|
38
|
-
### Delegate to 1 Instance
|
|
39
|
-
|
|
40
|
-
- Task scoped to a single project or repo
|
|
41
|
-
- Requires file access, code changes, or execution
|
|
42
|
-
|
|
43
|
-
### Coordinate Multiple Instances
|
|
44
|
-
|
|
45
|
-
- Task spans multiple repos or domains
|
|
46
|
-
- Requires outputs from one instance to feed into another
|
|
47
|
-
- Benefits from parallel execution (max 3 instances per task)
|
|
48
|
-
|
|
49
|
-
-----
|
|
50
|
-
|
|
51
|
-
## Instance Discovery (in this order)
|
|
52
|
-
1. list_teams() → reuse existing teams first
|
|
53
|
-
2. list_instances() → find by working_directory, description, or tags
|
|
54
|
-
3. describe_instance() → confirm capabilities before delegating
|
|
55
|
-
4. create_instance() → only if no suitable instance exists
|
|
56
|
-
|
|
57
|
-
Rules: prefer reuse over creation. Do NOT create duplicates of running instances.
|
|
58
|
-
|
|
59
|
-
-----
|
|
60
|
-
|
|
61
|
-
## Delegation Protocol
|
|
62
|
-
|
|
63
|
-
Every delegation via send_to_instance() MUST include:
|
|
64
|
-
|
|
65
|
-
1. Task scope — what exactly to do, bounded clearly
|
|
66
|
-
2. Expected output — what to return and in what form
|
|
67
|
-
3. Policy reminder — "Follow Development Workflow policy" (for code tasks)
|
|
68
|
-
|
|
69
|
-
### Loop Prevention
|
|
70
|
-
|
|
71
|
-
- Never re-delegate a task back to the instance that sent it to you
|
|
72
|
-
- If a task has bounced 3 times, stop and solve locally or reduce scope
|
|
73
|
-
|
|
74
|
-
### Execution Strategy
|
|
75
|
-
|
|
76
|
-
Parallel — use only when tasks are independent with no shared state
|
|
77
|
-
Sequential — use when one task's output feeds into the next
|
|
78
|
-
|
|
79
|
-
-----
|
|
80
|
-
|
|
81
|
-
## Result Handling
|
|
82
|
-
|
|
83
|
-
When an instance reports back, classify the outcome:
|
|
84
|
-
|
|
85
|
-
- Success → Summarize key results for user. Omit internal coordination noise.
|
|
86
|
-
- Partial → State what succeeded, what remains, proposed next steps.
|
|
87
|
-
- Failure → Retry up to 2 times. If still failing: try alternative instance, reduce scope, or return partial result clearly marked.
|
|
88
|
-
- No response → Ping again after reasonable wait. If still silent: report to user with options.
|
|
89
|
-
|
|
90
|
-
### Output to User
|
|
91
|
-
|
|
92
|
-
Every final response to the user should contain:
|
|
93
|
-
|
|
94
|
-
- Result — the actual answer or deliverable
|
|
95
|
-
- Gaps — anything incomplete or unresolved (omit if none)
|
|
96
|
-
|
|
97
|
-
-----
|
|
98
|
-
|
|
99
|
-
## Shared Decisions
|
|
100
|
-
|
|
101
|
-
Use post_decision() / list_decisions() for any choice that affects more than 1 instance, changes an API contract, introduces a new dependency, or alters deployment process.
|
|
102
|
-
|
|
103
|
-
When instances disagree, collect both viewpoints, make a decision, and record it via post_decision.
|
|
104
|
-
|
|
105
|
-
-----
|
|
106
|
-
|
|
107
|
-
## Context Rotation Bootstrap
|
|
108
|
-
|
|
109
|
-
After your context rotates, run this sequence BEFORE processing any new messages:
|
|
110
|
-
1. list_instances() → rebuild fleet awareness
|
|
111
|
-
2. list_teams() → restore team structure
|
|
112
|
-
3. list_decisions() → reload policies and conventions
|
|
113
|
-
|
|
114
|
-
Only then handle incoming requests.
|
|
115
|
-
|
|
116
|
-
-----
|
|
117
|
-
|
|
118
|
-
## Development Workflow Policy
|
|
119
|
-
|
|
120
|
-
All code changes across the fleet should follow this workflow.
|
|
121
|
-
The coordinator enforces compliance but does not perform these steps directly.
|
|
122
|
-
Remind instances of this policy when delegating code tasks.
|
|
123
|
-
|
|
124
|
-
### Workflow Stages
|
|
125
|
-
Design Proposed → Design Approved → Implementation → Submit for Review → Under Review → Approved → Merge
|
|
126
|
-
|
|
127
|
-
### Policy Rules
|
|
128
|
-
|
|
129
|
-
1. Design before code — developer sends design proposal to reviewer before implementation. Consensus required before proceeding.
|
|
130
|
-
2. Challenger pairing — every code task should have a developer + reviewer. Reviewer actively questions decisions and finds risks.
|
|
131
|
-
3. Verify by execution — backend/CLI changes must be tested by running them. Do not trust documentation alone.
|
|
132
|
-
4. Independent review — every merge requires code review from someone other than the author.
|
|
133
|
-
5. Root cause first — bug fixes require confirmed root cause before proposing a fix.
|
|
134
|
-
6. Merge conditions: tests pass, reviewer approved, branch and worktree cleaned up.
|
|
135
|
-
|
|
136
|
-
### Specialist Instance Rules
|
|
137
|
-
|
|
138
|
-
- Execute within defined scope only
|
|
139
|
-
- Return structured output: result, assumptions, uncertainties, verification status
|
|
140
|
-
- Do NOT create new instances without coordinator approval
|
|
141
|
-
|
|
142
|
-
-----
|
|
143
|
-
|
|
144
|
-
## Team Management
|
|
145
|
-
|
|
146
|
-
- Always check existing teams before creating new ones
|
|
147
|
-
- Default to ephemeral teams (created for a specific task, dissolved after completion)
|
|
148
|
-
- Clean up ephemeral teams and instances after task completion
|
|
149
|
-
`;
|
|
150
|
-
/** Ensure the general (coordinator) instance has its project instructions file. */
|
|
151
|
-
export function ensureGeneralInstructions(workDir, backendName, logger) {
|
|
152
|
-
const backend = backendName ?? "claude-code";
|
|
153
|
-
const filename = INSTRUCTIONS_FILENAME[backend] ?? "CLAUDE.md";
|
|
154
|
-
const filePath = join(workDir, filename);
|
|
155
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
156
|
-
if (!existsSync(filePath)) {
|
|
157
|
-
writeFileSync(filePath, GENERAL_INSTRUCTIONS, "utf-8");
|
|
158
|
-
logger?.info({ filePath }, "Created general instance instructions file");
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
//# sourceMappingURL=fleet-instructions.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fleet-instructions.js","sourceRoot":"","sources":["../src/fleet-instructions.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,CAAC,MAAM,qBAAqB,GAA2B;IAC3D,aAAa,EAAE,WAAW;IAC1B,OAAO,EAAE,WAAW;IACpB,YAAY,EAAE,WAAW;IACzB,UAAU,EAAE,WAAW;IACvB,UAAU,EAAE,2BAA2B;IACvC,MAAM,EAAE,WAAW;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqInC,CAAC;AAEF,mFAAmF;AACnF,MAAM,UAAU,yBAAyB,CACvC,OAAe,EACf,WAAoB,EACpB,MAAe;IAEf,MAAM,OAAO,GAAG,WAAW,IAAI,aAAa,CAAC;IAC7C,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC;IAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,aAAa,CAAC,QAAQ,EAAE,oBAAoB,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,EAAE,IAAI,CAAC,EAAE,QAAQ,EAAE,EAAE,4CAA4C,CAAC,CAAC;IAC3E,CAAC;AACH,CAAC"}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RPC / CRUD handlers for fleet-side actions invoked by instances over IPC
|
|
3
|
-
* or by the agent CLI over HTTP.
|
|
4
|
-
*
|
|
5
|
-
* Pattern follows outbound-handlers.ts: a `RpcHandlersContext` interface +
|
|
6
|
-
* a `rpcHandlers` dispatch dictionary. FleetManager implements the context
|
|
7
|
-
* and forwards each call so external surfaces (AgentEndpointContext, IPC
|
|
8
|
-
* dispatch) keep their existing shape.
|
|
9
|
-
*
|
|
10
|
-
* Extracted from fleet-manager.ts (P4.1 step 3 of 4).
|
|
11
|
-
*/
|
|
12
|
-
import type { Logger } from "./logger.js";
|
|
13
|
-
import type { Scheduler } from "./scheduler/index.js";
|
|
14
|
-
import type { IpcClient } from "./channel/ipc-bridge.js";
|
|
15
|
-
import type { EventLog } from "./event-log.js";
|
|
16
|
-
import type { FleetConfig } from "./types.js";
|
|
17
|
-
export interface RpcHandlersContext {
|
|
18
|
-
readonly scheduler: Scheduler | null;
|
|
19
|
-
readonly fleetConfig: FleetConfig | null;
|
|
20
|
-
readonly logger: Logger;
|
|
21
|
-
readonly eventLog: EventLog | null;
|
|
22
|
-
readonly instanceIpcClients: Map<string, IpcClient>;
|
|
23
|
-
saveFleetConfig(): void;
|
|
24
|
-
}
|
|
25
|
-
/** Resolve display name for an instance, fallback to instance name. */
|
|
26
|
-
export declare function resolveDisplayName(ctx: {
|
|
27
|
-
fleetConfig: FleetConfig | null;
|
|
28
|
-
}, instanceName: string): string;
|
|
29
|
-
/** One-line description of a fleet tool call for activity logs. */
|
|
30
|
-
export declare function summarizeToolCall(tool: string, args: Record<string, unknown>): string;
|
|
31
|
-
export declare const rpcHandlers: {
|
|
32
|
-
handleScheduleCrud(ctx: RpcHandlersContext, instanceName: string, msg: Record<string, unknown>): void;
|
|
33
|
-
handleDecisionCrud(ctx: RpcHandlersContext, instanceName: string, msg: Record<string, unknown>): void;
|
|
34
|
-
handleSetDisplayName(ctx: RpcHandlersContext, instanceName: string, msg: Record<string, unknown>): void;
|
|
35
|
-
handleSetDescription(ctx: RpcHandlersContext, instanceName: string, msg: Record<string, unknown>): void;
|
|
36
|
-
handleScheduleCrudHttp(ctx: RpcHandlersContext, instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
|
|
37
|
-
handleDecisionCrudHttp(ctx: RpcHandlersContext, instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
|
|
38
|
-
handleTaskCrudHttp(ctx: RpcHandlersContext, instance: string, args: Record<string, unknown>): Promise<unknown>;
|
|
39
|
-
handleSetDisplayNameHttp(ctx: RpcHandlersContext, instance: string, name: string): Promise<unknown>;
|
|
40
|
-
handleSetDescriptionHttp(ctx: RpcHandlersContext, instance: string, description: string): Promise<unknown>;
|
|
41
|
-
handleTaskCrud(ctx: RpcHandlersContext, instanceName: string, msg: Record<string, unknown>): void;
|
|
42
|
-
};
|