@kb-labs/agent-entry 2.93.0 → 2.96.0
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/dist/cli/commands/diff.js +4 -4
- package/dist/cli/commands/diff.js.map +1 -1
- package/dist/cli/commands/history.js +6 -6
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/quality-report.js +3 -3
- package/dist/cli/commands/quality-report.js.map +1 -1
- package/dist/cli/commands/rollback.js +1 -1
- package/dist/cli/commands/rollback.js.map +1 -1
- package/dist/cli/commands/run.js +24 -7
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/trace-context.js +3 -3
- package/dist/cli/commands/trace-context.js.map +1 -1
- package/dist/cli/commands/trace-diagnose.js +3 -3
- package/dist/cli/commands/trace-diagnose.js.map +1 -1
- package/dist/cli/commands/trace-stats.js +3 -3
- package/dist/cli/commands/trace-stats.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +40 -35
- package/dist/index.js.map +1 -1
- package/dist/manifest.d.ts +62 -7
- package/dist/manifest.js +40 -35
- package/dist/manifest.js.map +1 -1
- package/dist/rest/handlers/approve-handler.js +51 -47
- package/dist/rest/handlers/approve-handler.js.map +1 -1
- package/dist/rest/handlers/approve-session-plan-handler.js +38 -34
- package/dist/rest/handlers/approve-session-plan-handler.js.map +1 -1
- package/dist/rest/handlers/correct-handler.js +49 -45
- package/dist/rest/handlers/correct-handler.js.map +1 -1
- package/dist/rest/handlers/create-session-handler.js +17 -13
- package/dist/rest/handlers/create-session-handler.js.map +1 -1
- package/dist/rest/handlers/execute-session-plan-handler.js +216 -208
- package/dist/rest/handlers/execute-session-plan-handler.js.map +1 -1
- package/dist/rest/handlers/generate-spec-handler.js +103 -98
- package/dist/rest/handlers/generate-spec-handler.js.map +1 -1
- package/dist/rest/handlers/get-file-diff-handler.js +35 -31
- package/dist/rest/handlers/get-file-diff-handler.js.map +1 -1
- package/dist/rest/handlers/get-session-handler.js +15 -11
- package/dist/rest/handlers/get-session-handler.js.map +1 -1
- package/dist/rest/handlers/get-session-plan-handler.js +28 -24
- package/dist/rest/handlers/get-session-plan-handler.js.map +1 -1
- package/dist/rest/handlers/get-session-turns-handler.js +27 -23
- package/dist/rest/handlers/get-session-turns-handler.js.map +1 -1
- package/dist/rest/handlers/get-spec-handler.js +22 -18
- package/dist/rest/handlers/get-spec-handler.js.map +1 -1
- package/dist/rest/handlers/list-file-changes-handler.js +25 -21
- package/dist/rest/handlers/list-file-changes-handler.js.map +1 -1
- package/dist/rest/handlers/list-sessions-handler.js +16 -12
- package/dist/rest/handlers/list-sessions-handler.js.map +1 -1
- package/dist/rest/handlers/rollback-handler.js +73 -69
- package/dist/rest/handlers/rollback-handler.js.map +1 -1
- package/dist/rest/handlers/run-handler.js +151 -147
- package/dist/rest/handlers/run-handler.js.map +1 -1
- package/dist/rest/handlers/sessions-handler.js +47 -35
- package/dist/rest/handlers/sessions-handler.js.map +1 -1
- package/dist/rest/handlers/status-handler.js +33 -29
- package/dist/rest/handlers/status-handler.js.map +1 -1
- package/dist/rest/handlers/stop-handler.js +37 -33
- package/dist/rest/handlers/stop-handler.js.map +1 -1
- package/dist/widgets/117.js +24 -1
- package/dist/widgets/{300.js → 215.js} +1 -1
- package/dist/widgets/370.js +1 -1
- package/dist/widgets/{805.js → 46.js} +92 -92
- package/dist/widgets/50.js +1 -1
- package/dist/widgets/62.js +96 -0
- package/dist/widgets/648.js +1 -0
- package/dist/widgets/669.js +1 -1
- package/dist/widgets/775.js +1 -1
- package/dist/widgets/78.js +1 -0
- package/dist/widgets/968.js +2 -2
- package/dist/widgets/__federation_expose_AgentsPage.js +1 -1
- package/dist/widgets/mf-manifest.json +31 -31
- package/dist/widgets/mf-stats.json +39 -39
- package/dist/widgets/remoteEntry.js +2 -2
- package/dist/ws/session-stream-handler.js +17 -6
- package/dist/ws/session-stream-handler.js.map +1 -1
- package/package.json +16 -15
- package/dist/widgets/418.js +0 -38
- package/dist/widgets/451.js +0 -1
- package/dist/widgets/694.js +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineHandler } from '@kb-labs/sdk';
|
|
1
|
+
import { defineHandler, rethrowForRest } from '@kb-labs/sdk';
|
|
2
2
|
import { SessionManager } from '@kb-labs/agent-core';
|
|
3
3
|
import { ChangeStore } from '@kb-labs/agent-history';
|
|
4
4
|
import { promises } from 'fs';
|
|
@@ -7,82 +7,86 @@ import path from 'path';
|
|
|
7
7
|
// src/rest/handlers/rollback-handler.ts
|
|
8
8
|
var rollback_handler_default = defineHandler({
|
|
9
9
|
async execute(ctx, input) {
|
|
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
|
-
|
|
10
|
+
try {
|
|
11
|
+
const params = input.params;
|
|
12
|
+
const sessionId = params?.sessionId;
|
|
13
|
+
if (!sessionId) {
|
|
14
|
+
throw new Error("Session ID is required");
|
|
15
|
+
}
|
|
16
|
+
const body = input.body ?? {};
|
|
17
|
+
const sessionManager = new SessionManager(ctx.cwd);
|
|
18
|
+
const session = await sessionManager.loadSession(sessionId);
|
|
19
|
+
if (!session) {
|
|
20
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
21
|
+
}
|
|
22
|
+
const workingDir = session.workingDir || ctx.cwd;
|
|
23
|
+
const store = new ChangeStore(workingDir);
|
|
24
|
+
let changes;
|
|
25
|
+
if (body.runId) {
|
|
26
|
+
changes = await store.listRun(sessionId, body.runId);
|
|
27
|
+
} else if (body.changeIds?.length) {
|
|
28
|
+
const ids = new Set(body.changeIds);
|
|
29
|
+
const all = await store.listSession(sessionId);
|
|
30
|
+
changes = all.filter((c) => ids.has(c.id));
|
|
31
|
+
} else {
|
|
32
|
+
changes = await store.listSession(sessionId);
|
|
33
|
+
}
|
|
34
|
+
if (changes.length === 0) {
|
|
35
|
+
return { rolledBack: 0, skipped: 0, conflicts: [], success: true };
|
|
36
|
+
}
|
|
37
|
+
const sorted = [...changes].sort(
|
|
38
|
+
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
39
|
+
);
|
|
40
|
+
const fullHistory = await store.listSession(sessionId);
|
|
41
|
+
const rollbackIds = new Set(sorted.map((c) => c.id));
|
|
42
|
+
const conflicts = [];
|
|
43
|
+
let rolledBack = 0;
|
|
44
|
+
let skipped = 0;
|
|
45
|
+
for (const change of sorted) {
|
|
46
|
+
if (!body.skipConflicts) {
|
|
47
|
+
const laterChanges = fullHistory.filter(
|
|
48
|
+
(c) => c.filePath === change.filePath && new Date(c.timestamp).getTime() > new Date(change.timestamp).getTime() && !rollbackIds.has(c.id)
|
|
49
|
+
);
|
|
50
|
+
if (laterChanges.length > 0) {
|
|
51
|
+
const laterAgents = [...new Set(laterChanges.map((c) => c.agentId))].join(", ");
|
|
52
|
+
conflicts.push({
|
|
53
|
+
filePath: change.filePath,
|
|
54
|
+
changeId: change.id,
|
|
55
|
+
reason: `File was modified after this change by: ${laterAgents}. Use skipConflicts: true to force.`
|
|
56
|
+
});
|
|
57
|
+
skipped++;
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const fullPath = path.join(workingDir, change.filePath);
|
|
62
|
+
try {
|
|
63
|
+
if (change.before) {
|
|
64
|
+
await promises.mkdir(path.dirname(fullPath), { recursive: true });
|
|
65
|
+
await promises.writeFile(fullPath, change.before.content, "utf-8");
|
|
66
|
+
} else {
|
|
67
|
+
await promises.unlink(fullPath).catch((e) => {
|
|
68
|
+
if (e.code !== "ENOENT") {
|
|
69
|
+
throw e;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
rolledBack++;
|
|
74
|
+
} catch (e) {
|
|
51
75
|
conflicts.push({
|
|
52
76
|
filePath: change.filePath,
|
|
53
77
|
changeId: change.id,
|
|
54
|
-
reason: `
|
|
78
|
+
reason: `Write failed: ${e instanceof Error ? e.message : String(e)}`
|
|
55
79
|
});
|
|
56
80
|
skipped++;
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const fullPath = path.join(workingDir, change.filePath);
|
|
61
|
-
try {
|
|
62
|
-
if (change.before) {
|
|
63
|
-
await promises.mkdir(path.dirname(fullPath), { recursive: true });
|
|
64
|
-
await promises.writeFile(fullPath, change.before.content, "utf-8");
|
|
65
|
-
} else {
|
|
66
|
-
await promises.unlink(fullPath).catch((e) => {
|
|
67
|
-
if (e.code !== "ENOENT") {
|
|
68
|
-
throw e;
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
81
|
}
|
|
72
|
-
rolledBack++;
|
|
73
|
-
} catch (e) {
|
|
74
|
-
conflicts.push({
|
|
75
|
-
filePath: change.filePath,
|
|
76
|
-
changeId: change.id,
|
|
77
|
-
reason: `Write failed: ${e instanceof Error ? e.message : String(e)}`
|
|
78
|
-
});
|
|
79
|
-
skipped++;
|
|
80
82
|
}
|
|
83
|
+
ctx.platform.logger.info(
|
|
84
|
+
`[rollback-handler] Session ${sessionId}: rolled back ${rolledBack}, skipped ${skipped}`
|
|
85
|
+
);
|
|
86
|
+
return { rolledBack, skipped, conflicts, success: skipped === 0 };
|
|
87
|
+
} catch (err) {
|
|
88
|
+
rethrowForRest(err);
|
|
81
89
|
}
|
|
82
|
-
ctx.platform.logger.info(
|
|
83
|
-
`[rollback-handler] Session ${sessionId}: rolled back ${rolledBack}, skipped ${skipped}`
|
|
84
|
-
);
|
|
85
|
-
return { rolledBack, skipped, conflicts, success: skipped === 0 };
|
|
86
90
|
}
|
|
87
91
|
});
|
|
88
92
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/rest/handlers/rollback-handler.ts"],"names":["fsp"],"mappings":";;;;;;;AA+BA,IAAO,2BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAA8D;AAChG,IAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,
|
|
1
|
+
{"version":3,"sources":["../../../src/rest/handlers/rollback-handler.ts"],"names":["fsp"],"mappings":"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","file":"rollback-handler.js","sourcesContent":["/**\n * POST /sessions/:sessionId/rollback — Rollback file changes.\n * Body: { runId?: string; changeIds?: string[]; skipConflicts?: boolean }\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport { ChangeStore } from '@kb-labs/agent-history';\nimport type { FileChange } from '@kb-labs/agent-history';\nimport { promises as fsp } from 'node:fs';\nimport path from 'node:path';\n\ninterface RollbackRequest {\n runId?: string;\n changeIds?: string[];\n skipConflicts?: boolean;\n}\n\ninterface ConflictEntry {\n filePath: string;\n changeId: string;\n reason: string;\n}\n\ninterface RollbackResponse {\n rolledBack: number;\n skipped: number;\n conflicts: ConflictEntry[];\n success: boolean;\n}\n\nexport default defineHandler({\n async execute(ctx: PluginContextV3, input: RestInput<RollbackRequest>): Promise<RollbackResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n if (!sessionId) {throw new Error('Session ID is required');}\n\n const body = (input.body ?? {}) as RollbackRequest;\n\n const sessionManager = new SessionManager(ctx.cwd);\n const session = await sessionManager.loadSession(sessionId);\n if (!session) {throw new Error(`Session not found: ${sessionId}`);}\n\n const workingDir = session.workingDir || ctx.cwd;\n const store = new ChangeStore(workingDir);\n\n let changes: FileChange[];\n if (body.runId) {\n changes = await store.listRun(sessionId, body.runId);\n } else if (body.changeIds?.length) {\n const ids = new Set(body.changeIds);\n const all = await store.listSession(sessionId);\n changes = all.filter((c) => ids.has(c.id));\n } else {\n changes = await store.listSession(sessionId);\n }\n\n if (changes.length === 0) {\n return { rolledBack: 0, skipped: 0, conflicts: [], success: true };\n }\n\n // Reverse-chronological: undo latest first\n const sorted = [...changes].sort(\n (a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n );\n\n // For conflict detection: full session history\n const fullHistory = await store.listSession(sessionId);\n const rollbackIds = new Set(sorted.map((c) => c.id));\n\n const conflicts: ConflictEntry[] = [];\n let rolledBack = 0;\n let skipped = 0;\n\n for (const change of sorted) {\n // Conflict: newer changes to same file NOT in our rollback set\n if (!body.skipConflicts) {\n const laterChanges = fullHistory.filter(\n (c) =>\n c.filePath === change.filePath &&\n new Date(c.timestamp).getTime() > new Date(change.timestamp).getTime() &&\n !rollbackIds.has(c.id),\n );\n if (laterChanges.length > 0) {\n const laterAgents = [...new Set(laterChanges.map((c) => c.agentId))].join(', ');\n conflicts.push({\n filePath: change.filePath,\n changeId: change.id,\n reason: `File was modified after this change by: ${laterAgents}. Use skipConflicts: true to force.`,\n });\n skipped++;\n continue;\n }\n }\n\n const fullPath = path.join(workingDir, change.filePath);\n try {\n if (change.before) {\n await fsp.mkdir(path.dirname(fullPath), { recursive: true });\n await fsp.writeFile(fullPath, change.before.content, 'utf-8');\n } else {\n await fsp.unlink(fullPath).catch((e: NodeJS.ErrnoException) => {\n if (e.code !== 'ENOENT') {throw e;}\n });\n }\n rolledBack++;\n } catch (e) {\n conflicts.push({\n filePath: change.filePath,\n changeId: change.id,\n reason: `Write failed: ${e instanceof Error ? e.message : String(e)}`,\n });\n skipped++;\n }\n }\n\n ctx.platform.logger.info(\n `[rollback-handler] Session ${sessionId}: rolled back ${rolledBack}, skipped ${skipped}`,\n );\n\n return { rolledBack, skipped, conflicts, success: skipped === 0 };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineHandler, useAnalytics, useCache, useConfig, usePlatform } from '@kb-labs/sdk';
|
|
1
|
+
import { defineHandler, useAnalytics, useCache, useConfig, rethrowForRest, usePlatform } from '@kb-labs/sdk';
|
|
2
2
|
import { bootstrapAgentSDK, SessionManager, createSessionMemoryBridge, createCoreToolPack } from '@kb-labs/agent-core';
|
|
3
3
|
import { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';
|
|
4
4
|
import { IncrementalTraceWriter } from '@kb-labs/agent-tracing';
|
|
@@ -353,161 +353,165 @@ async function inferFollowUpWorkingDir(sessionManager, sessionId, baseWorkingDir
|
|
|
353
353
|
}
|
|
354
354
|
var run_handler_default = defineHandler({
|
|
355
355
|
async execute(ctx, input) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
const analytics = useAnalytics();
|
|
361
|
-
const runId = RunManager.generateRunId();
|
|
362
|
-
const startTime = Date.now();
|
|
363
|
-
let sessionId = body.sessionId;
|
|
364
|
-
let workingDir = body.workingDir || ctx.cwd;
|
|
365
|
-
let sessionManager = new SessionManager(workingDir);
|
|
366
|
-
if (!sessionId) {
|
|
367
|
-
const session = await sessionManager.createSession({
|
|
368
|
-
mode: "execute",
|
|
369
|
-
task: body.task,
|
|
370
|
-
agentId: body.agentId ?? "orchestrator"
|
|
371
|
-
});
|
|
372
|
-
sessionId = session.id;
|
|
373
|
-
ctx.platform.logger.info(`[run-handler] Created new session ${sessionId}`);
|
|
374
|
-
} else {
|
|
375
|
-
const existingSession = await sessionManager.loadSession(sessionId);
|
|
376
|
-
let resolvedSession = existingSession;
|
|
377
|
-
if (!resolvedSession && pathExists(ctx.cwd)) {
|
|
378
|
-
const fallbackManager = new SessionManager(ctx.cwd);
|
|
379
|
-
const fallbackSession = await fallbackManager.loadSession(sessionId);
|
|
380
|
-
if (fallbackSession) {
|
|
381
|
-
sessionManager = fallbackManager;
|
|
382
|
-
resolvedSession = fallbackSession;
|
|
383
|
-
}
|
|
356
|
+
try {
|
|
357
|
+
const body = input.body;
|
|
358
|
+
if (!body?.task) {
|
|
359
|
+
throw new Error("Task is required");
|
|
384
360
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
361
|
+
const analytics = useAnalytics();
|
|
362
|
+
const runId = RunManager.generateRunId();
|
|
363
|
+
const startTime = Date.now();
|
|
364
|
+
let sessionId = body.sessionId;
|
|
365
|
+
let workingDir = body.workingDir || ctx.cwd;
|
|
366
|
+
let sessionManager = new SessionManager(workingDir);
|
|
367
|
+
if (!sessionId) {
|
|
368
|
+
const session = await sessionManager.createSession({
|
|
369
|
+
mode: "execute",
|
|
370
|
+
task: body.task,
|
|
371
|
+
agentId: body.agentId ?? "orchestrator"
|
|
372
|
+
});
|
|
373
|
+
sessionId = session.id;
|
|
374
|
+
ctx.platform.logger.info(`[run-handler] Created new session ${sessionId}`);
|
|
375
|
+
} else {
|
|
376
|
+
const existingSession = await sessionManager.loadSession(sessionId);
|
|
377
|
+
let resolvedSession = existingSession;
|
|
378
|
+
if (!resolvedSession && pathExists(ctx.cwd)) {
|
|
379
|
+
const fallbackManager = new SessionManager(ctx.cwd);
|
|
380
|
+
const fallbackSession = await fallbackManager.loadSession(sessionId);
|
|
381
|
+
if (fallbackSession) {
|
|
382
|
+
sessionManager = fallbackManager;
|
|
383
|
+
resolvedSession = fallbackSession;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (!resolvedSession) {
|
|
387
|
+
throw new Error(`Session not found: ${sessionId} (cwd=${ctx.cwd})`);
|
|
388
|
+
}
|
|
389
|
+
workingDir = body.workingDir || resolvedSession.workingDir || workingDir;
|
|
390
|
+
if (!body.workingDir && isLikelyFollowUpScopeTask(body.task)) {
|
|
391
|
+
const inferred = await inferFollowUpWorkingDir(sessionManager, sessionId, resolvedSession.workingDir || ctx.cwd);
|
|
392
|
+
if (inferred && inferred !== workingDir) {
|
|
393
|
+
ctx.platform.logger.info(`[run-handler] Follow-up scope inferred: ${workingDir} -> ${inferred}`);
|
|
394
|
+
workingDir = inferred;
|
|
395
|
+
}
|
|
394
396
|
}
|
|
397
|
+
sessionManager = new SessionManager(workingDir);
|
|
398
|
+
ctx.platform.logger.info(`[run-handler] Continuing session ${sessionId} (workingDir=${workingDir})`);
|
|
395
399
|
}
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
const seqEvent = RunManager.broadcast(runId, event);
|
|
438
|
-
void sessionManager.addEvent(finalSessionId, {
|
|
439
|
-
...seqEvent,
|
|
440
|
-
sessionId: finalSessionId,
|
|
441
|
-
runId,
|
|
442
|
-
metadata: {
|
|
443
|
-
...seqEvent.metadata,
|
|
400
|
+
ctx.platform.logger.info(`[run-handler] Starting run ${runId} for task: ${body.task}`);
|
|
401
|
+
await sessionManager.createUserTurn(sessionId, body.task, runId);
|
|
402
|
+
await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STARTED, {
|
|
403
|
+
runId,
|
|
404
|
+
sessionId,
|
|
405
|
+
taskLength: body.task.length,
|
|
406
|
+
tier: body.tier ?? "medium",
|
|
407
|
+
enableEscalation: body.enableEscalation ?? true,
|
|
408
|
+
responseMode: body.responseMode ?? "auto",
|
|
409
|
+
verbose: body.verbose ?? false
|
|
410
|
+
});
|
|
411
|
+
const sessionMemory = createSessionMemoryBridge(workingDir, sessionId);
|
|
412
|
+
const responseRequirementsSelector = createDefaultResponseRequirementsSelector();
|
|
413
|
+
const toolRegistry = createToolRegistry({
|
|
414
|
+
workingDir,
|
|
415
|
+
currentTask: body.task,
|
|
416
|
+
sessionId,
|
|
417
|
+
verbose: body.verbose,
|
|
418
|
+
cache: useCache(),
|
|
419
|
+
sessionMemory,
|
|
420
|
+
responseRequirementsResolver: async ({ task, kernel }) => responseRequirementsSelector.select({
|
|
421
|
+
state: kernel,
|
|
422
|
+
messages: [],
|
|
423
|
+
task: task ?? body.task
|
|
424
|
+
})
|
|
425
|
+
});
|
|
426
|
+
const agentsConfig = await useConfig();
|
|
427
|
+
const finalSessionId = sessionId;
|
|
428
|
+
const traceDir = path.join(workingDir, ".kb", "traces", "incremental");
|
|
429
|
+
const traceWriter = new IncrementalTraceWriter(runId, {}, traceDir);
|
|
430
|
+
const agent = new AgentSDK().register(createCoreToolPack(toolRegistry)).createRunner({
|
|
431
|
+
sessionId: finalSessionId,
|
|
432
|
+
workingDir,
|
|
433
|
+
maxIterations: 50,
|
|
434
|
+
temperature: 0.1,
|
|
435
|
+
tier: body.tier ?? "medium",
|
|
436
|
+
tokenBudget: agentsConfig?.tokenBudget,
|
|
437
|
+
onEvent: (event) => {
|
|
438
|
+
const seqEvent = RunManager.broadcast(runId, event);
|
|
439
|
+
void sessionManager.addEvent(finalSessionId, {
|
|
440
|
+
...seqEvent,
|
|
444
441
|
sessionId: finalSessionId,
|
|
445
442
|
runId,
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
void (async () => {
|
|
454
|
-
try {
|
|
455
|
-
const result = await agent.execute(body.task);
|
|
456
|
-
const durationMs = Date.now() - startTime;
|
|
457
|
-
const detailedTrace = traceWriter.getEntries();
|
|
458
|
-
await traceWriter.finalize?.();
|
|
459
|
-
if (detailedTrace.length > 0) {
|
|
460
|
-
await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);
|
|
461
|
-
}
|
|
462
|
-
if (result.fileChanges && result.fileChanges.length > 0) {
|
|
463
|
-
await sessionManager.attachFileChangesToTurn(finalSessionId, runId, result.fileChanges);
|
|
443
|
+
metadata: {
|
|
444
|
+
...seqEvent.metadata,
|
|
445
|
+
sessionId: finalSessionId,
|
|
446
|
+
runId,
|
|
447
|
+
workingDir
|
|
448
|
+
}
|
|
449
|
+
});
|
|
464
450
|
}
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
451
|
+
});
|
|
452
|
+
const run = await RunManager.register(runId, body.task, agent, sessionManager, finalSessionId);
|
|
453
|
+
await RunManager.updateStatus(runId, "running");
|
|
454
|
+
void (async () => {
|
|
455
|
+
try {
|
|
456
|
+
const result = await agent.execute(body.task);
|
|
457
|
+
const durationMs = Date.now() - startTime;
|
|
458
|
+
const detailedTrace = traceWriter.getEntries();
|
|
459
|
+
await traceWriter.finalize?.();
|
|
460
|
+
if (detailedTrace.length > 0) {
|
|
461
|
+
await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);
|
|
462
|
+
}
|
|
463
|
+
if (result.fileChanges && result.fileChanges.length > 0) {
|
|
464
|
+
await sessionManager.attachFileChangesToTurn(finalSessionId, runId, result.fileChanges);
|
|
465
|
+
}
|
|
466
|
+
await RunManager.updateStatus(runId, result.success ? "completed" : "failed", {
|
|
467
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
475
468
|
durationMs,
|
|
476
|
-
|
|
477
|
-
|
|
469
|
+
summary: result.summary,
|
|
470
|
+
error: result.error
|
|
471
|
+
});
|
|
472
|
+
await analytics?.track(
|
|
473
|
+
result.success ? AGENT_ANALYTICS_EVENTS.RUN_COMPLETED : AGENT_ANALYTICS_EVENTS.RUN_FAILED,
|
|
474
|
+
{
|
|
475
|
+
runId,
|
|
476
|
+
durationMs,
|
|
477
|
+
success: result.success,
|
|
478
|
+
summary: result.summary?.slice(0, 200)
|
|
479
|
+
}
|
|
480
|
+
);
|
|
481
|
+
ctx.platform.logger.info(`[run-handler] Run ${runId} completed: ${result.success}`);
|
|
482
|
+
} catch (error) {
|
|
483
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
484
|
+
const durationMs = Date.now() - startTime;
|
|
485
|
+
const detailedTrace = traceWriter.getEntries();
|
|
486
|
+
await traceWriter.finalize?.();
|
|
487
|
+
if (detailedTrace.length > 0) {
|
|
488
|
+
await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);
|
|
478
489
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
490
|
+
await RunManager.updateStatus(runId, "failed", {
|
|
491
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
492
|
+
durationMs,
|
|
493
|
+
error: errorMsg
|
|
494
|
+
});
|
|
495
|
+
await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_FAILED, {
|
|
496
|
+
runId,
|
|
497
|
+
durationMs,
|
|
498
|
+
error: errorMsg.slice(0, 200)
|
|
499
|
+
});
|
|
500
|
+
ctx.platform.logger.error(`[run-handler] Run ${runId} failed: ${errorMsg}`);
|
|
488
501
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
}
|
|
502
|
-
const wsPath = AGENTS_WS_CHANNELS.SESSION_STREAM.replace(":sessionId", finalSessionId);
|
|
503
|
-
const eventsPath = `${AGENTS_WS_BASE_PATH}${wsPath}`;
|
|
504
|
-
return {
|
|
505
|
-
runId,
|
|
506
|
-
sessionId: finalSessionId,
|
|
507
|
-
eventsPath,
|
|
508
|
-
status: "started",
|
|
509
|
-
startedAt: run.startedAt
|
|
510
|
-
};
|
|
502
|
+
})();
|
|
503
|
+
const wsPath = AGENTS_WS_CHANNELS.SESSION_STREAM.replace(":sessionId", finalSessionId);
|
|
504
|
+
const eventsPath = `${AGENTS_WS_BASE_PATH}${wsPath}`;
|
|
505
|
+
return {
|
|
506
|
+
runId,
|
|
507
|
+
sessionId: finalSessionId,
|
|
508
|
+
eventsPath,
|
|
509
|
+
status: "started",
|
|
510
|
+
startedAt: run.startedAt
|
|
511
|
+
};
|
|
512
|
+
} catch (err) {
|
|
513
|
+
rethrowForRest(err);
|
|
514
|
+
}
|
|
511
515
|
}
|
|
512
516
|
});
|
|
513
517
|
|