@evo-dev/core 0.0.1-alpha.1 → 0.0.1-alpha.10
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/assets/skills/coding/knowledge-distillation/SKILL.md +117 -114
- package/assets/skills/coding/knowledge-distillation/references/knowledge-distillation-methods.md +11 -7
- package/assets/team/agents/code-reviewer.md +48 -0
- package/assets/team/agents/docs-maintainer.md +51 -0
- package/assets/team/agents/implementation-engineer.md +51 -0
- package/assets/team/agents/product-scope-analyst.md +58 -0
- package/assets/team/agents/release-engineer.md +55 -0
- package/assets/team/agents/security-boundary-reviewer.md +50 -0
- package/assets/team/agents/solution-architect.md +51 -0
- package/assets/team/agents/verification-engineer.md +51 -0
- package/assets/team/team.md +102 -0
- package/dist/config/index.js +925 -97
- package/dist/index.js +13107 -5618
- package/package.json +5 -1
- package/src/agents/index.ts +56 -264
- package/src/code-agent-traces/index.ts +520 -0
- package/src/config/index.ts +5 -0
- package/src/config/paths.ts +1 -1
- package/src/config/settings.ts +149 -0
- package/src/config/store.ts +2 -0
- package/src/daemon/index.ts +99 -50
- package/src/evolution/candidates/index.ts +564 -0
- package/src/evolution/control/index.ts +20 -0
- package/src/evolution/evidence/analysis.ts +533 -0
- package/src/evolution/evidence/index.ts +3 -0
- package/src/evolution/evidence/session-memory/analysis.ts +281 -0
- package/src/evolution/evidence/session-memory/constants.ts +9 -0
- package/src/evolution/evidence/session-memory/index.ts +7 -0
- package/src/evolution/evidence/session-memory/paths.ts +29 -0
- package/src/evolution/evidence/session-memory/policy.ts +39 -0
- package/src/evolution/evidence/session-memory/segment.ts +202 -0
- package/src/evolution/evidence/session-memory/sensitivity.ts +335 -0
- package/src/evolution/evidence/session-memory/state-machine.ts +249 -0
- package/src/evolution/evidence/session-memory/storage.ts +379 -0
- package/src/evolution/evidence/session-memory/types.ts +221 -0
- package/src/evolution/evidence/session-memory/updater.ts +191 -0
- package/src/evolution/formatters.ts +169 -0
- package/src/evolution/index.ts +16 -2356
- package/src/evolution/knowledge/index.ts +5427 -0
- package/src/evolution/paths.ts +44 -0
- package/src/evolution/processor/distillation.ts +518 -0
- package/src/evolution/processor/index.ts +3 -0
- package/src/evolution/processor/process.ts +528 -0
- package/src/{learning → evolution/review}/index.ts +10 -14
- package/src/evolution/schema.ts +568 -0
- package/src/evolution/shared.ts +758 -0
- package/src/evolution/triggers/classification.ts +102 -0
- package/src/evolution/triggers/index.ts +295 -0
- package/src/hooks/index.ts +438 -179
- package/src/index.ts +12 -3
- package/src/projects/index.ts +453 -0
- package/src/runtime-logs/index.ts +490 -24
- package/src/team/index.ts +1429 -185
- package/src/team/mcp.ts +9 -5
- package/src/team/prompts.ts +141 -0
- package/src/utils/errors.ts +13 -0
- package/src/utils/fs.ts +40 -0
- package/src/utils/hash.ts +9 -0
- package/src/utils/ids.ts +12 -0
- package/src/utils/index.ts +7 -0
- package/src/utils/parsing.ts +11 -0
- package/src/utils/text.ts +18 -0
- package/src/utils/time.ts +5 -0
- package/src/workflow/index.ts +3 -21
- package/src/project/index.ts +0 -507
- package/src/task/index.ts +0 -840
package/src/config/settings.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import {
|
|
3
|
+
type SessionMemoryPolicySnapshot,
|
|
4
|
+
createDefaultSessionMemoryPolicy,
|
|
5
|
+
parseSessionMemoryPolicy,
|
|
6
|
+
} from "../evolution/evidence/session-memory/index.ts";
|
|
1
7
|
import { type HookSettings, createDefaultHookSettings, parseHookSettings } from "../hooks/index.ts";
|
|
2
8
|
import { EvoDevConfigError, describeType } from "./errors.ts";
|
|
9
|
+
import { resolveEvoDevPaths } from "./paths.ts";
|
|
3
10
|
|
|
4
11
|
export interface PluginSettings {
|
|
5
12
|
enabled: boolean;
|
|
@@ -7,6 +14,22 @@ export interface PluginSettings {
|
|
|
7
14
|
autoSyncAgents?: boolean;
|
|
8
15
|
}
|
|
9
16
|
|
|
17
|
+
export interface MemorySettings {
|
|
18
|
+
autoAccept: boolean;
|
|
19
|
+
runtimeInjection: boolean;
|
|
20
|
+
staleReview: boolean;
|
|
21
|
+
lexicalIndex: boolean;
|
|
22
|
+
sessionMemory: SessionMemoryPolicySnapshot;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface EvolutionSettings {
|
|
26
|
+
automation: {
|
|
27
|
+
knowledge: boolean;
|
|
28
|
+
semanticKnowledge: boolean;
|
|
29
|
+
recommendations: boolean;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
10
33
|
export interface EvoDevSettings {
|
|
11
34
|
version: 1;
|
|
12
35
|
platform: {
|
|
@@ -29,6 +52,8 @@ export interface EvoDevSettings {
|
|
|
29
52
|
};
|
|
30
53
|
hooks: HookSettings;
|
|
31
54
|
teamRuntime: TeamRuntimeSettings;
|
|
55
|
+
memory: MemorySettings;
|
|
56
|
+
evolution: EvolutionSettings;
|
|
32
57
|
}
|
|
33
58
|
|
|
34
59
|
export type SettingsInput = Partial<{
|
|
@@ -45,6 +70,10 @@ export type SettingsInput = Partial<{
|
|
|
45
70
|
doctor: Partial<EvoDevSettings["doctor"]>;
|
|
46
71
|
hooks: unknown;
|
|
47
72
|
teamRuntime: Partial<TeamRuntimeSettings>;
|
|
73
|
+
memory: Partial<MemorySettings>;
|
|
74
|
+
evolution: Partial<{
|
|
75
|
+
automation: Partial<EvolutionSettings["automation"]>;
|
|
76
|
+
}>;
|
|
48
77
|
}>;
|
|
49
78
|
|
|
50
79
|
export interface TeamRuntimeSettings {
|
|
@@ -52,6 +81,7 @@ export interface TeamRuntimeSettings {
|
|
|
52
81
|
defaultModel: string | null;
|
|
53
82
|
defaultThinkingLevel: string | null;
|
|
54
83
|
recordTranscript: boolean;
|
|
84
|
+
displayMode: "normal" | "development";
|
|
55
85
|
}
|
|
56
86
|
|
|
57
87
|
export function createDefaultSettings(os: string = process.platform): EvoDevSettings {
|
|
@@ -83,6 +113,8 @@ export function createDefaultSettings(os: string = process.platform): EvoDevSett
|
|
|
83
113
|
},
|
|
84
114
|
hooks: createDefaultHookSettings(),
|
|
85
115
|
teamRuntime: createDefaultTeamRuntimeSettings(),
|
|
116
|
+
memory: createDefaultMemorySettings(),
|
|
117
|
+
evolution: createDefaultEvolutionSettings(),
|
|
86
118
|
};
|
|
87
119
|
}
|
|
88
120
|
|
|
@@ -92,6 +124,27 @@ export function createDefaultTeamRuntimeSettings(): TeamRuntimeSettings {
|
|
|
92
124
|
defaultModel: null,
|
|
93
125
|
defaultThinkingLevel: null,
|
|
94
126
|
recordTranscript: false,
|
|
127
|
+
displayMode: "normal",
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createDefaultMemorySettings(): MemorySettings {
|
|
132
|
+
return {
|
|
133
|
+
autoAccept: true,
|
|
134
|
+
runtimeInjection: true,
|
|
135
|
+
staleReview: true,
|
|
136
|
+
lexicalIndex: true,
|
|
137
|
+
sessionMemory: createDefaultSessionMemoryPolicy(),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function createDefaultEvolutionSettings(): EvolutionSettings {
|
|
142
|
+
return {
|
|
143
|
+
automation: {
|
|
144
|
+
knowledge: true,
|
|
145
|
+
semanticKnowledge: false,
|
|
146
|
+
recommendations: false,
|
|
147
|
+
},
|
|
95
148
|
};
|
|
96
149
|
}
|
|
97
150
|
|
|
@@ -135,11 +188,33 @@ export function mergeSettings(
|
|
|
135
188
|
...defaults.teamRuntime,
|
|
136
189
|
...existing.teamRuntime,
|
|
137
190
|
},
|
|
191
|
+
memory: {
|
|
192
|
+
...defaults.memory,
|
|
193
|
+
...existing.memory,
|
|
194
|
+
},
|
|
195
|
+
evolution: {
|
|
196
|
+
...defaults.evolution,
|
|
197
|
+
...existing.evolution,
|
|
198
|
+
automation: {
|
|
199
|
+
...defaults.evolution.automation,
|
|
200
|
+
...existing.evolution?.automation,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
138
203
|
};
|
|
139
204
|
|
|
140
205
|
return parseSettings(merged);
|
|
141
206
|
}
|
|
142
207
|
|
|
208
|
+
export async function readRuntimeInjectionSettings(homeDir?: string): Promise<MemorySettings> {
|
|
209
|
+
const paths = resolveEvoDevPaths(homeDir);
|
|
210
|
+
try {
|
|
211
|
+
return parseSettings(JSON.parse(await readFile(paths.settingsPath, "utf8"))).memory;
|
|
212
|
+
} catch (error) {
|
|
213
|
+
if (isNotFoundError(error)) return createDefaultMemorySettings();
|
|
214
|
+
throw error;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
143
218
|
export function parseSettings(value: unknown): EvoDevSettings {
|
|
144
219
|
const root = expectRecord(value, "settings");
|
|
145
220
|
const version = root.version;
|
|
@@ -184,11 +259,64 @@ export function parseSettings(value: unknown): EvoDevSettings {
|
|
|
184
259
|
root.teamRuntime ?? createDefaultTeamRuntimeSettings(),
|
|
185
260
|
"settings.teamRuntime",
|
|
186
261
|
),
|
|
262
|
+
memory: parseMemorySettings(root.memory ?? createDefaultMemorySettings(), "settings.memory"),
|
|
263
|
+
evolution: parseEvolutionSettings(
|
|
264
|
+
root.evolution ?? createDefaultEvolutionSettings(),
|
|
265
|
+
"settings.evolution",
|
|
266
|
+
),
|
|
187
267
|
};
|
|
188
268
|
|
|
189
269
|
return parsed;
|
|
190
270
|
}
|
|
191
271
|
|
|
272
|
+
function parseEvolutionSettings(value: unknown, path: string): EvolutionSettings {
|
|
273
|
+
const input = expectRecord(value, path);
|
|
274
|
+
const defaults = createDefaultEvolutionSettings();
|
|
275
|
+
const automation = expectRecord(input.automation ?? defaults.automation, `${path}.automation`);
|
|
276
|
+
return {
|
|
277
|
+
automation: {
|
|
278
|
+
knowledge:
|
|
279
|
+
automation.knowledge === undefined
|
|
280
|
+
? defaults.automation.knowledge
|
|
281
|
+
: expectBoolean(automation.knowledge, `${path}.automation.knowledge`),
|
|
282
|
+
semanticKnowledge:
|
|
283
|
+
automation.semanticKnowledge === undefined
|
|
284
|
+
? defaults.automation.semanticKnowledge
|
|
285
|
+
: expectBoolean(automation.semanticKnowledge, `${path}.automation.semanticKnowledge`),
|
|
286
|
+
recommendations:
|
|
287
|
+
automation.recommendations === undefined
|
|
288
|
+
? defaults.automation.recommendations
|
|
289
|
+
: expectBoolean(automation.recommendations, `${path}.automation.recommendations`),
|
|
290
|
+
},
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function parseMemorySettings(value: unknown, path: string): MemorySettings {
|
|
295
|
+
const input = expectRecord(value, path);
|
|
296
|
+
const defaults = createDefaultMemorySettings();
|
|
297
|
+
return {
|
|
298
|
+
autoAccept:
|
|
299
|
+
input.autoAccept === undefined
|
|
300
|
+
? defaults.autoAccept
|
|
301
|
+
: expectBoolean(input.autoAccept, `${path}.autoAccept`),
|
|
302
|
+
runtimeInjection:
|
|
303
|
+
input.runtimeInjection === undefined
|
|
304
|
+
? defaults.runtimeInjection
|
|
305
|
+
: expectBoolean(input.runtimeInjection, `${path}.runtimeInjection`),
|
|
306
|
+
staleReview:
|
|
307
|
+
input.staleReview === undefined
|
|
308
|
+
? defaults.staleReview
|
|
309
|
+
: expectBoolean(input.staleReview, `${path}.staleReview`),
|
|
310
|
+
lexicalIndex:
|
|
311
|
+
input.lexicalIndex === undefined
|
|
312
|
+
? defaults.lexicalIndex
|
|
313
|
+
: expectBoolean(input.lexicalIndex, `${path}.lexicalIndex`),
|
|
314
|
+
sessionMemory: parseSessionMemoryPolicy(
|
|
315
|
+
isPlainRecord(input.sessionMemory) ? input.sessionMemory : defaults.sessionMemory,
|
|
316
|
+
),
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
192
320
|
function parseTeamRuntimeSettings(value: unknown, path: string): TeamRuntimeSettings {
|
|
193
321
|
const input = expectRecord(value, path);
|
|
194
322
|
const defaults = createDefaultTeamRuntimeSettings();
|
|
@@ -211,9 +339,20 @@ function parseTeamRuntimeSettings(value: unknown, path: string): TeamRuntimeSett
|
|
|
211
339
|
input.recordTranscript === undefined
|
|
212
340
|
? defaults.recordTranscript
|
|
213
341
|
: expectBoolean(input.recordTranscript, `${path}.recordTranscript`),
|
|
342
|
+
displayMode: parseTeamRuntimeDisplayMode(input.displayMode, defaults.displayMode, path),
|
|
214
343
|
};
|
|
215
344
|
}
|
|
216
345
|
|
|
346
|
+
function parseTeamRuntimeDisplayMode(
|
|
347
|
+
value: unknown,
|
|
348
|
+
fallback: TeamRuntimeSettings["displayMode"],
|
|
349
|
+
path: string,
|
|
350
|
+
): TeamRuntimeSettings["displayMode"] {
|
|
351
|
+
if (value === undefined) return fallback;
|
|
352
|
+
if (value === "normal" || value === "development") return value;
|
|
353
|
+
throw new EvoDevConfigError(`Invalid ${path}.displayMode; expected normal or development`);
|
|
354
|
+
}
|
|
355
|
+
|
|
217
356
|
function parsePluginSettings(value: unknown, path: string): PluginSettings {
|
|
218
357
|
const input = expectRecord(value, path);
|
|
219
358
|
const parsed: PluginSettings = {
|
|
@@ -239,6 +378,16 @@ function expectRecord(value: unknown, path: string): Record<string, unknown> {
|
|
|
239
378
|
return value as Record<string, unknown>;
|
|
240
379
|
}
|
|
241
380
|
|
|
381
|
+
function isPlainRecord(value: unknown): value is Record<string, unknown> {
|
|
382
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
function isNotFoundError(error: unknown): boolean {
|
|
386
|
+
return (
|
|
387
|
+
error instanceof Error && "code" in error && (error as NodeJS.ErrnoException).code === "ENOENT"
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
242
391
|
function expectString(value: unknown, path: string): string {
|
|
243
392
|
if (typeof value !== "string" || value.length === 0) {
|
|
244
393
|
throw new EvoDevConfigError(`Invalid ${path}; expected non-empty string`);
|
package/src/config/store.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
2
|
import { dirname } from "node:path";
|
|
3
|
+
import { ensureOkfKnowledgeBase } from "../evolution/knowledge/index.ts";
|
|
3
4
|
import { EvoDevConfigError } from "./errors.ts";
|
|
4
5
|
import { type EvoDevPaths, resolveEvoDevPaths } from "./paths.ts";
|
|
5
6
|
import { type EvoDevRegistry, createDefaultRegistry, parseRegistry } from "./registry.ts";
|
|
@@ -102,6 +103,7 @@ export async function initializeCoreConfig(homeDir?: string): Promise<CoreConfig
|
|
|
102
103
|
export async function ensureKnowledgeBaseFiles(paths: EvoDevPaths): Promise<void> {
|
|
103
104
|
await mkdir(paths.knowledgeDir, { recursive: true });
|
|
104
105
|
await mkdir(paths.evosCasesDir, { recursive: true });
|
|
106
|
+
await ensureOkfKnowledgeBase(paths.homeDir);
|
|
105
107
|
await writeTextIfMissing(
|
|
106
108
|
`${paths.knowledgeDir}/README.md`,
|
|
107
109
|
[
|
package/src/daemon/index.ts
CHANGED
|
@@ -2,16 +2,23 @@ import { randomBytes } from "node:crypto";
|
|
|
2
2
|
import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
3
3
|
import { type IncomingMessage, createServer } from "node:http";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
|
-
import { listEvolutionTriggers, processEvolutionTriggers } from "../evolution/index.ts";
|
|
5
|
+
import { listEvolutionTriggers, processEvolutionTriggers } from "../evolution/control/index.ts";
|
|
6
6
|
import { listObservabilityEvents } from "../observability/index.ts";
|
|
7
7
|
import {
|
|
8
8
|
type TeamRuntimeAdapter,
|
|
9
|
+
isActiveTeamAgentStatus,
|
|
10
|
+
isIdleTeamAgentStatus,
|
|
11
|
+
isMidTurnTeamAgentStatus,
|
|
9
12
|
listTeamRuns,
|
|
13
|
+
markTeamMessagesDelivered,
|
|
14
|
+
readPendingTeamMessagesForRole,
|
|
10
15
|
reconcileTeamRun,
|
|
11
16
|
resumeTeamRun,
|
|
17
|
+
schedulePendingTeamMessageDelivery,
|
|
12
18
|
sendTeamMessage,
|
|
13
19
|
spawnTeamRole,
|
|
14
20
|
stopTeamRole,
|
|
21
|
+
updateTeamAgentHookState,
|
|
15
22
|
} from "../team/index.ts";
|
|
16
23
|
|
|
17
24
|
export interface DaemonPaths {
|
|
@@ -182,12 +189,42 @@ export async function handleDaemonRequest(
|
|
|
182
189
|
const removed = await cleanupDaemonState(input.homeDir, input.token ?? "");
|
|
183
190
|
return ok({ stopped: true, removed }, warnings);
|
|
184
191
|
}
|
|
185
|
-
if (
|
|
192
|
+
if (
|
|
193
|
+
(input.path === "/team/message/enqueue" || input.path === "/teams/send") &&
|
|
194
|
+
input.method === "POST"
|
|
195
|
+
) {
|
|
186
196
|
return dashboardMutation(
|
|
187
197
|
await sendDashboardTeamMessage(input.homeDir, input.body, input.runtimeAdapter),
|
|
188
198
|
warnings,
|
|
189
199
|
);
|
|
190
200
|
}
|
|
201
|
+
if (input.path === "/team/agent/state" && input.method === "POST") {
|
|
202
|
+
return dashboardMutation(
|
|
203
|
+
await updateDashboardTeamAgentState(input.homeDir, input.body),
|
|
204
|
+
warnings,
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (input.path === "/team/message/claim" && input.method === "POST") {
|
|
208
|
+
return ok(await claimDashboardTeamMessages(input.homeDir, input.body), warnings);
|
|
209
|
+
}
|
|
210
|
+
if (input.path === "/team/message/delivered" && input.method === "POST") {
|
|
211
|
+
return dashboardMutation(
|
|
212
|
+
await markDashboardTeamMessagesDelivered(input.homeDir, input.body),
|
|
213
|
+
warnings,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
if (
|
|
217
|
+
(input.path === "/team/reconcile" || input.path === "/teams/reconcile") &&
|
|
218
|
+
input.method === "POST"
|
|
219
|
+
) {
|
|
220
|
+
await schedulePendingTeamMessageDelivery({
|
|
221
|
+
homeDir: input.homeDir,
|
|
222
|
+
runtimeAdapter: input.runtimeAdapter,
|
|
223
|
+
}).catch((error) =>
|
|
224
|
+
warnings.push(`Team delivery scheduling unavailable: ${describeError(error)}`),
|
|
225
|
+
);
|
|
226
|
+
return ok(await collectTeamStatus(input.homeDir, warnings, input.runtimeAdapter), warnings);
|
|
227
|
+
}
|
|
191
228
|
if (input.path === "/teams/spawn" && input.method === "POST") {
|
|
192
229
|
return dashboardMutation(
|
|
193
230
|
await spawnDashboardTeamRole(input.homeDir, input.body, input.runtimeAdapter),
|
|
@@ -206,9 +243,6 @@ export async function handleDaemonRequest(
|
|
|
206
243
|
warnings,
|
|
207
244
|
);
|
|
208
245
|
}
|
|
209
|
-
if (input.path === "/teams/reconcile" && input.method === "POST") {
|
|
210
|
-
return ok(await collectTeamStatus(input.homeDir, warnings, input.runtimeAdapter), warnings);
|
|
211
|
-
}
|
|
212
246
|
if (input.path === "/evolution/process" && input.method === "POST") {
|
|
213
247
|
return dashboardMutation(
|
|
214
248
|
await processDashboardEvolutionTriggers(input.homeDir, input.body),
|
|
@@ -217,8 +251,6 @@ export async function handleDaemonRequest(
|
|
|
217
251
|
}
|
|
218
252
|
if (input.method !== "GET") return notFound(warnings);
|
|
219
253
|
|
|
220
|
-
if (input.path === "/tasks")
|
|
221
|
-
return ok(await collectTaskSummaries(input.homeDir, warnings), warnings);
|
|
222
254
|
if (input.path === "/observability/events")
|
|
223
255
|
return ok(await collectObservabilitySummaries(input.homeDir, warnings), warnings);
|
|
224
256
|
if (input.path === "/memory/candidates")
|
|
@@ -373,33 +405,6 @@ function isAllowedLocalOrigin(origin: string | null): boolean {
|
|
|
373
405
|
}
|
|
374
406
|
}
|
|
375
407
|
|
|
376
|
-
async function collectTaskSummaries(homeDir: string, warnings: string[]): Promise<unknown[]> {
|
|
377
|
-
const root = join(homeDir, ".evodev", "STATE", "tasks");
|
|
378
|
-
if (!(await pathExists(root))) {
|
|
379
|
-
warnings.push("Task store not found; returning empty tasks.");
|
|
380
|
-
return [];
|
|
381
|
-
}
|
|
382
|
-
const contracts = await collectNamedFiles(root, "contract.json");
|
|
383
|
-
const summaries: unknown[] = [];
|
|
384
|
-
for (const file of contracts) {
|
|
385
|
-
try {
|
|
386
|
-
const contract = JSON.parse(await readFile(file, "utf8"));
|
|
387
|
-
summaries.push(
|
|
388
|
-
sanitizeMetadata({
|
|
389
|
-
taskId: contract.taskId,
|
|
390
|
-
status: contract.status,
|
|
391
|
-
mode: contract.route?.mode ?? null,
|
|
392
|
-
workflowId: contract.route?.workflowId ?? null,
|
|
393
|
-
verificationStatus: contract.verification?.status ?? null,
|
|
394
|
-
}),
|
|
395
|
-
);
|
|
396
|
-
} catch {
|
|
397
|
-
warnings.push(`Skipped unreadable task contract: ${file}`);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
return summaries;
|
|
401
|
-
}
|
|
402
|
-
|
|
403
408
|
async function collectObservabilitySummaries(
|
|
404
409
|
homeDir: string,
|
|
405
410
|
warnings: string[],
|
|
@@ -541,10 +546,9 @@ async function collectTeamStatus(
|
|
|
541
546
|
thinkingLevel: agent.thinkingLevel,
|
|
542
547
|
status: agent.status,
|
|
543
548
|
paneId: agent.tmux.paneId,
|
|
544
|
-
canReceiveMessages:
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
agent.status === "recreated",
|
|
549
|
+
canReceiveMessages: isActiveTeamAgentStatus(agent.status),
|
|
550
|
+
isIdle: isIdleTeamAgentStatus(agent.status),
|
|
551
|
+
isMidTurn: isMidTurnTeamAgentStatus(agent.status),
|
|
548
552
|
nativeSessionRecorded: agent.nativeSession.sessionId !== null,
|
|
549
553
|
updatedAt: agent.updatedAt,
|
|
550
554
|
})),
|
|
@@ -552,7 +556,8 @@ async function collectTeamStatus(
|
|
|
552
556
|
notifications: status.notifications.map((notification) => ({
|
|
553
557
|
ok: notification.ok,
|
|
554
558
|
error: notification.error ?? null,
|
|
555
|
-
|
|
559
|
+
delivery: notification.delivery ?? null,
|
|
560
|
+
queuedFor: notification.queuedFor ?? null,
|
|
556
561
|
})),
|
|
557
562
|
}) as DaemonTeamStatusSummary;
|
|
558
563
|
} catch (error) {
|
|
@@ -577,6 +582,61 @@ async function sendDashboardTeamMessage(
|
|
|
577
582
|
});
|
|
578
583
|
}
|
|
579
584
|
|
|
585
|
+
async function updateDashboardTeamAgentState(homeDir: string, body: unknown): Promise<unknown> {
|
|
586
|
+
const input = expectRequestBody(body);
|
|
587
|
+
const result = await updateTeamAgentHookState({
|
|
588
|
+
homeDir,
|
|
589
|
+
runId: expectBodyString(input, "runId"),
|
|
590
|
+
roleId: expectBodyString(input, "roleId"),
|
|
591
|
+
hookEvent: expectBodyString(input, "hookEvent"),
|
|
592
|
+
});
|
|
593
|
+
return {
|
|
594
|
+
ok: true,
|
|
595
|
+
roleId: result.agent.roleId,
|
|
596
|
+
status: result.agent.status,
|
|
597
|
+
statusPath: result.statusPath,
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
async function claimDashboardTeamMessages(homeDir: string, body: unknown): Promise<unknown> {
|
|
602
|
+
const input = expectRequestBody(body);
|
|
603
|
+
const runId = expectBodyString(input, "runId");
|
|
604
|
+
const roleId = expectBodyString(input, "roleId");
|
|
605
|
+
const messages = await readPendingTeamMessagesForRole({
|
|
606
|
+
homeDir,
|
|
607
|
+
runId,
|
|
608
|
+
roleId,
|
|
609
|
+
limit: optionalBodyNumber(input.limit),
|
|
610
|
+
});
|
|
611
|
+
return {
|
|
612
|
+
runId,
|
|
613
|
+
roleId,
|
|
614
|
+
messages,
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
async function markDashboardTeamMessagesDelivered(
|
|
619
|
+
homeDir: string,
|
|
620
|
+
body: unknown,
|
|
621
|
+
): Promise<unknown> {
|
|
622
|
+
const input = expectRequestBody(body);
|
|
623
|
+
const messageIdsValue = input.messageIds;
|
|
624
|
+
if (!Array.isArray(messageIdsValue)) throw new Error("Expected body.messageIds array.");
|
|
625
|
+
const messageIds = messageIdsValue.map((value) => {
|
|
626
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
627
|
+
throw new Error("Expected body.messageIds to contain non-empty strings.");
|
|
628
|
+
}
|
|
629
|
+
return value;
|
|
630
|
+
});
|
|
631
|
+
await markTeamMessagesDelivered({
|
|
632
|
+
homeDir,
|
|
633
|
+
runId: expectBodyString(input, "runId"),
|
|
634
|
+
roleId: expectBodyString(input, "roleId"),
|
|
635
|
+
messageIds,
|
|
636
|
+
});
|
|
637
|
+
return { ok: true, delivered: messageIds };
|
|
638
|
+
}
|
|
639
|
+
|
|
580
640
|
async function spawnDashboardTeamRole(
|
|
581
641
|
homeDir: string,
|
|
582
642
|
body: unknown,
|
|
@@ -752,17 +812,6 @@ function describeError(error: unknown): string {
|
|
|
752
812
|
return error instanceof Error ? error.message : String(error);
|
|
753
813
|
}
|
|
754
814
|
|
|
755
|
-
async function collectNamedFiles(root: string, name: string): Promise<string[]> {
|
|
756
|
-
const entries = await readdir(root, { withFileTypes: true });
|
|
757
|
-
const files: string[] = [];
|
|
758
|
-
for (const entry of entries) {
|
|
759
|
-
const path = join(root, entry.name);
|
|
760
|
-
if (entry.isDirectory()) files.push(...(await collectNamedFiles(path, name)));
|
|
761
|
-
else if (entry.isFile() && entry.name === name) files.push(path);
|
|
762
|
-
}
|
|
763
|
-
return files;
|
|
764
|
-
}
|
|
765
|
-
|
|
766
815
|
function ok(data: unknown, warnings: string[]): { status: number; body: DaemonResponseBody } {
|
|
767
816
|
return { status: 200, body: { ok: true, data: sanitizeMetadata(data), warnings } };
|
|
768
817
|
}
|