@kb-labs/agent-entry 2.118.2 → 2.119.0-canary.85d060ea6
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/rest/handlers/correct-handler.js +29 -112
- package/dist/rest/handlers/correct-handler.js.map +1 -1
- package/dist/rest/handlers/execute-session-plan-handler.js +56 -118
- package/dist/rest/handlers/execute-session-plan-handler.js.map +1 -1
- package/dist/rest/handlers/generate-spec-handler.js +50 -116
- package/dist/rest/handlers/generate-spec-handler.js.map +1 -1
- package/dist/rest/handlers/run-handler.js +56 -118
- package/dist/rest/handlers/run-handler.js.map +1 -1
- package/dist/rest/handlers/status-handler.js +29 -112
- package/dist/rest/handlers/status-handler.js.map +1 -1
- package/dist/rest/handlers/stop-handler.js +29 -112
- package/dist/rest/handlers/stop-handler.js.map +1 -1
- package/dist/widgets/117.js +10 -3
- package/dist/widgets/165.js +1 -1
- package/dist/widgets/370.js +1 -1
- package/dist/widgets/46.js +20 -20
- package/dist/widgets/50.js +1 -1
- package/dist/widgets/546.js +1 -1
- package/dist/widgets/648.js +1 -1
- package/dist/widgets/669.js +1 -1
- package/dist/widgets/775.js +1 -1
- package/dist/widgets/78.js +1 -1
- package/dist/widgets/832.js +96 -0
- package/dist/widgets/875.js +4 -4
- package/dist/widgets/__federation_expose_AgentsPage.js +1 -1
- package/dist/widgets/mf-manifest.json +2 -2
- package/dist/widgets/mf-stats.json +2 -2
- package/dist/widgets/remoteEntry.js +7 -7
- package/dist/ws/session-stream-handler.js +70 -180
- package/dist/ws/session-stream-handler.js.map +1 -1
- package/package.json +6 -6
- package/dist/widgets/62.js +0 -96
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineHandler, useAnalytics, useCache, useConfig, rethrowForRest
|
|
1
|
+
import { defineHandler, useAnalytics, useCache, useConfig, rethrowForRest } 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';
|
|
@@ -10,15 +10,12 @@ import { AGENT_ANALYTICS_EVENTS, AGENTS_WS_CHANNELS, AGENTS_WS_BASE_PATH } from
|
|
|
10
10
|
|
|
11
11
|
// src/rest/handlers/run-handler.ts
|
|
12
12
|
var CACHE_PREFIX = "agent:run:";
|
|
13
|
-
var EVENT_TOPIC_PREFIX = "agent:events:";
|
|
14
13
|
var CACHE_TTL = 36e5;
|
|
15
14
|
var RunManagerImpl = class {
|
|
16
|
-
/** Live agents
|
|
15
|
+
/** Live agents (not cacheable) */
|
|
17
16
|
activeRuns = /* @__PURE__ */ new Map();
|
|
18
|
-
/** Session-level listeners: sessionId → Set<callback> — receive
|
|
17
|
+
/** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */
|
|
19
18
|
sessionListeners = /* @__PURE__ */ new Map();
|
|
20
|
-
/** sessionId per runId — set when run is registered */
|
|
21
|
-
runSessionMap = /* @__PURE__ */ new Map();
|
|
22
19
|
/**
|
|
23
20
|
* Generate unique run ID
|
|
24
21
|
*/
|
|
@@ -28,7 +25,7 @@ var RunManagerImpl = class {
|
|
|
28
25
|
/**
|
|
29
26
|
* Register a new run
|
|
30
27
|
*/
|
|
31
|
-
async register(runId, task, agent, sessionManager
|
|
28
|
+
async register(runId, task, agent, sessionManager) {
|
|
32
29
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
33
30
|
const run = {
|
|
34
31
|
runId,
|
|
@@ -36,15 +33,9 @@ var RunManagerImpl = class {
|
|
|
36
33
|
status: "pending",
|
|
37
34
|
agent,
|
|
38
35
|
sessionManager,
|
|
39
|
-
startedAt: now
|
|
40
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
41
|
-
lastSeq: 0,
|
|
42
|
-
eventBuffer: []
|
|
36
|
+
startedAt: now
|
|
43
37
|
};
|
|
44
38
|
this.activeRuns.set(runId, run);
|
|
45
|
-
if (sessionId) {
|
|
46
|
-
this.runSessionMap.set(runId, sessionId);
|
|
47
|
-
}
|
|
48
39
|
await this.saveToCache(run);
|
|
49
40
|
return run;
|
|
50
41
|
}
|
|
@@ -107,101 +98,42 @@ var RunManagerImpl = class {
|
|
|
107
98
|
};
|
|
108
99
|
await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);
|
|
109
100
|
}
|
|
110
|
-
/** Track subscriptions for cleanup */
|
|
111
|
-
subscriptions = /* @__PURE__ */ new Map();
|
|
112
101
|
/**
|
|
113
|
-
*
|
|
102
|
+
* Broadcast turn deltas to all session-level listeners. Callers MUST await
|
|
103
|
+
* persistence (sessionManager.addEvent) before calling this, so listeners
|
|
104
|
+
* never observe a delta whose underlying turn state isn't on disk yet —
|
|
105
|
+
* that ordering is what makes gap-recovery / reconnect resume correct.
|
|
114
106
|
*/
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const run2 = this.activeRuns.get(runId);
|
|
119
|
-
if (run2) {
|
|
120
|
-
run2.listeners.add(callback);
|
|
121
|
-
return true;
|
|
122
|
-
}
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
const topic = `${EVENT_TOPIC_PREFIX}${runId}`;
|
|
126
|
-
const unsubscribe = platform.eventBus.subscribe(topic, async (event) => {
|
|
127
|
-
try {
|
|
128
|
-
callback(event);
|
|
129
|
-
} catch {
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
if (!this.subscriptions.has(runId)) {
|
|
133
|
-
this.subscriptions.set(runId, /* @__PURE__ */ new Map());
|
|
134
|
-
}
|
|
135
|
-
this.subscriptions.get(runId).set(callback, unsubscribe);
|
|
136
|
-
const run = this.activeRuns.get(runId);
|
|
137
|
-
if (run) {
|
|
138
|
-
run.listeners.add(callback);
|
|
107
|
+
broadcastSessionDeltas(sessionId, deltas) {
|
|
108
|
+
if (deltas.length === 0) {
|
|
109
|
+
return;
|
|
139
110
|
}
|
|
140
|
-
|
|
111
|
+
this.notifySessionListeners(sessionId, { kind: "deltas", deltas });
|
|
141
112
|
}
|
|
142
113
|
/**
|
|
143
|
-
*
|
|
114
|
+
* Broadcast a run's terminal outcome to session-level listeners. Called
|
|
115
|
+
* directly from the run's own completion handler (after `agent.execute()`
|
|
116
|
+
* resolves) rather than derived reactively from an `agent:end` event —
|
|
117
|
+
* the completion handler already has definitive success/summary/duration,
|
|
118
|
+
* and this guarantees the message fires exactly once, deterministically.
|
|
144
119
|
*/
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
if (runSubs) {
|
|
148
|
-
const unsubscribe = runSubs.get(callback);
|
|
149
|
-
if (unsubscribe) {
|
|
150
|
-
unsubscribe();
|
|
151
|
-
runSubs.delete(callback);
|
|
152
|
-
}
|
|
153
|
-
if (runSubs.size === 0) {
|
|
154
|
-
this.subscriptions.delete(runId);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
const run = this.activeRuns.get(runId);
|
|
158
|
-
if (run) {
|
|
159
|
-
run.listeners.delete(callback);
|
|
160
|
-
}
|
|
120
|
+
broadcastRunCompleted(sessionId, payload) {
|
|
121
|
+
this.notifySessionListeners(sessionId, { kind: "run:completed", ...payload });
|
|
161
122
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
*/
|
|
167
|
-
broadcast(runId, event) {
|
|
168
|
-
const platform = usePlatform();
|
|
169
|
-
const run = this.activeRuns.get(runId);
|
|
170
|
-
let seqEvent = event;
|
|
171
|
-
if (run) {
|
|
172
|
-
run.lastSeq++;
|
|
173
|
-
seqEvent = { ...event, seq: run.lastSeq, runId };
|
|
174
|
-
run.eventBuffer.push(seqEvent);
|
|
175
|
-
}
|
|
176
|
-
if (platform?.eventBus) {
|
|
177
|
-
const topic = `${EVENT_TOPIC_PREFIX}${runId}`;
|
|
178
|
-
platform.eventBus.publish(topic, seqEvent).catch(() => {
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
if (run) {
|
|
182
|
-
for (const listener of run.listeners) {
|
|
183
|
-
try {
|
|
184
|
-
listener(seqEvent);
|
|
185
|
-
} catch {
|
|
186
|
-
}
|
|
187
|
-
}
|
|
123
|
+
notifySessionListeners(sessionId, payload) {
|
|
124
|
+
const listeners = this.sessionListeners.get(sessionId);
|
|
125
|
+
if (!listeners) {
|
|
126
|
+
return;
|
|
188
127
|
}
|
|
189
|
-
const
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
for (const listener of sListeners) {
|
|
194
|
-
try {
|
|
195
|
-
listener(seqEvent);
|
|
196
|
-
} catch {
|
|
197
|
-
}
|
|
198
|
-
}
|
|
128
|
+
for (const listener of listeners) {
|
|
129
|
+
try {
|
|
130
|
+
listener(payload);
|
|
131
|
+
} catch {
|
|
199
132
|
}
|
|
200
133
|
}
|
|
201
|
-
return seqEvent;
|
|
202
134
|
}
|
|
203
135
|
/**
|
|
204
|
-
* Add a session-level listener — receives
|
|
136
|
+
* Add a session-level listener — receives updates from ALL runs in this session.
|
|
205
137
|
*/
|
|
206
138
|
addSessionListener(sessionId, callback) {
|
|
207
139
|
if (!this.sessionListeners.has(sessionId)) {
|
|
@@ -221,21 +153,6 @@ var RunManagerImpl = class {
|
|
|
221
153
|
}
|
|
222
154
|
}
|
|
223
155
|
}
|
|
224
|
-
/**
|
|
225
|
-
* Get replay buffer for a run (all events emitted since start).
|
|
226
|
-
* Used by WS handler to send missed events on late connection.
|
|
227
|
-
* Optionally filter by afterSeq to only get events the client hasn't seen.
|
|
228
|
-
*/
|
|
229
|
-
getEventBuffer(runId, afterSeq) {
|
|
230
|
-
const run = this.activeRuns.get(runId);
|
|
231
|
-
if (!run) {
|
|
232
|
-
return [];
|
|
233
|
-
}
|
|
234
|
-
if (afterSeq != null) {
|
|
235
|
-
return run.eventBuffer.filter((e) => e.seq != null && e.seq > afterSeq);
|
|
236
|
-
}
|
|
237
|
-
return [...run.eventBuffer];
|
|
238
|
-
}
|
|
239
156
|
/**
|
|
240
157
|
* List all active runs
|
|
241
158
|
*/
|
|
@@ -398,7 +315,7 @@ var run_handler_default = defineHandler({
|
|
|
398
315
|
ctx.platform.logger.info(`[run-handler] Continuing session ${sessionId} (workingDir=${workingDir})`);
|
|
399
316
|
}
|
|
400
317
|
ctx.platform.logger.info(`[run-handler] Starting run ${runId} for task: ${body.task}`);
|
|
401
|
-
await sessionManager.createUserTurn(sessionId, body.task, runId);
|
|
318
|
+
const userTurn = await sessionManager.createUserTurn(sessionId, body.task, runId, body.clientId);
|
|
402
319
|
await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STARTED, {
|
|
403
320
|
runId,
|
|
404
321
|
sessionId,
|
|
@@ -435,21 +352,22 @@ var run_handler_default = defineHandler({
|
|
|
435
352
|
tier: body.tier ?? "medium",
|
|
436
353
|
tokenBudget: agentsConfig?.tokenBudget,
|
|
437
354
|
onEvent: (event) => {
|
|
438
|
-
const seqEvent = RunManager.broadcast(runId, event);
|
|
439
355
|
void sessionManager.addEvent(finalSessionId, {
|
|
440
|
-
...
|
|
356
|
+
...event,
|
|
441
357
|
sessionId: finalSessionId,
|
|
442
358
|
runId,
|
|
443
359
|
metadata: {
|
|
444
|
-
...
|
|
360
|
+
...event.metadata,
|
|
445
361
|
sessionId: finalSessionId,
|
|
446
362
|
runId,
|
|
447
363
|
workingDir
|
|
448
364
|
}
|
|
365
|
+
}).then((deltas) => {
|
|
366
|
+
RunManager.broadcastSessionDeltas(finalSessionId, deltas);
|
|
449
367
|
});
|
|
450
368
|
}
|
|
451
369
|
});
|
|
452
|
-
const run = await RunManager.register(runId, body.task, agent, sessionManager
|
|
370
|
+
const run = await RunManager.register(runId, body.task, agent, sessionManager);
|
|
453
371
|
await RunManager.updateStatus(runId, "running");
|
|
454
372
|
void (async () => {
|
|
455
373
|
try {
|
|
@@ -469,6 +387,17 @@ var run_handler_default = defineHandler({
|
|
|
469
387
|
summary: result.summary,
|
|
470
388
|
error: result.error
|
|
471
389
|
});
|
|
390
|
+
const finalTurns = await sessionManager.getTurns(finalSessionId);
|
|
391
|
+
const finalTurn = finalTurns.find((t) => t.type === "assistant" && t.metadata.runId === runId);
|
|
392
|
+
const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);
|
|
393
|
+
RunManager.broadcastRunCompleted(finalSessionId, {
|
|
394
|
+
runId,
|
|
395
|
+
success: result.success,
|
|
396
|
+
summary: result.summary,
|
|
397
|
+
durationMs,
|
|
398
|
+
seq,
|
|
399
|
+
turn: finalTurn
|
|
400
|
+
});
|
|
472
401
|
await analytics?.track(
|
|
473
402
|
result.success ? AGENT_ANALYTICS_EVENTS.RUN_COMPLETED : AGENT_ANALYTICS_EVENTS.RUN_FAILED,
|
|
474
403
|
{
|
|
@@ -492,6 +421,14 @@ var run_handler_default = defineHandler({
|
|
|
492
421
|
durationMs,
|
|
493
422
|
error: errorMsg
|
|
494
423
|
});
|
|
424
|
+
const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);
|
|
425
|
+
RunManager.broadcastRunCompleted(finalSessionId, {
|
|
426
|
+
runId,
|
|
427
|
+
success: false,
|
|
428
|
+
summary: errorMsg,
|
|
429
|
+
durationMs,
|
|
430
|
+
seq
|
|
431
|
+
});
|
|
495
432
|
await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_FAILED, {
|
|
496
433
|
runId,
|
|
497
434
|
durationMs,
|
|
@@ -507,7 +444,8 @@ var run_handler_default = defineHandler({
|
|
|
507
444
|
sessionId: finalSessionId,
|
|
508
445
|
eventsPath,
|
|
509
446
|
status: "started",
|
|
510
|
-
startedAt: run.startedAt
|
|
447
|
+
startedAt: run.startedAt,
|
|
448
|
+
userTurn
|
|
511
449
|
};
|
|
512
450
|
} catch (err) {
|
|
513
451
|
rethrowForRest(err);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/rest/run-manager.ts","../../../src/rest/handlers/run-handler.ts"],"names":["run","useCache"],"mappings":"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","file":"run-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n * Uses platform eventBus for cross-process event broadcasting.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { AgentEvent, AgentEventCallback } from '@kb-labs/agent-contracts';\nimport { useCache, usePlatform } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst EVENT_TOPIC_PREFIX = 'agent:events:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n listeners: Set<AgentEventCallback>;\n /** Monotonic sequence counter for event ordering */\n lastSeq: number;\n /** Replay buffer: all events emitted since run start (for late WS connections) */\n eventBuffer: AgentEvent[];\n}\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents and listeners (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive events from ALL runs in session */\n private sessionListeners: Map<string, Set<AgentEventCallback>> = new Map();\n\n /** sessionId per runId — set when run is registered */\n private runSessionMap: Map<string, string> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n sessionId?: string\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n listeners: new Set(),\n lastSeq: 0,\n eventBuffer: [],\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Track sessionId → runId mapping for session-level listeners\n if (sessionId) {\n this.runSessionMap.set(runId, sessionId);\n }\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /** Track subscriptions for cleanup */\n private subscriptions: Map<string, Map<AgentEventCallback, () => void>> = new Map();\n\n /**\n * Add event listener to run (uses eventBus for cross-process)\n */\n addListener(runId: string, callback: AgentEventCallback): boolean {\n const platform = usePlatform();\n if (!platform?.eventBus) {\n // Fallback to in-memory only\n const run = this.activeRuns.get(runId);\n if (run) {\n run.listeners.add(callback);\n return true;\n }\n return false;\n }\n\n // Subscribe to eventBus topic for this run\n const topic = `${EVENT_TOPIC_PREFIX}${runId}`;\n const unsubscribe = platform.eventBus.subscribe<AgentEvent>(topic, async (event) => {\n try {\n callback(event);\n } catch {\n // Ignore callback errors\n }\n });\n\n // Track subscription for cleanup\n if (!this.subscriptions.has(runId)) {\n this.subscriptions.set(runId, new Map());\n }\n this.subscriptions.get(runId)!.set(callback, unsubscribe);\n\n // Also add to in-memory if run exists locally\n const run = this.activeRuns.get(runId);\n if (run) {\n run.listeners.add(callback);\n }\n\n return true;\n }\n\n /**\n * Remove event listener from run\n */\n removeListener(runId: string, callback: AgentEventCallback): void {\n // Unsubscribe from eventBus\n const runSubs = this.subscriptions.get(runId);\n if (runSubs) {\n const unsubscribe = runSubs.get(callback);\n if (unsubscribe) {\n unsubscribe();\n runSubs.delete(callback);\n }\n if (runSubs.size === 0) {\n this.subscriptions.delete(runId);\n }\n }\n\n // Also remove from in-memory\n const run = this.activeRuns.get(runId);\n if (run) {\n run.listeners.delete(callback);\n }\n }\n\n /**\n * Broadcast event to all listeners of a run (uses eventBus for cross-process)\n * Assigns monotonic sequence number for reliable ordering\n * @returns The event with seq assigned (for persistence)\n */\n broadcast(runId: string, event: AgentEvent): AgentEvent {\n const platform = usePlatform();\n const run = this.activeRuns.get(runId);\n\n // Assign sequence number for ordering\n let seqEvent = event;\n if (run) {\n run.lastSeq++;\n seqEvent = { ...event, seq: run.lastSeq, runId };\n\n // Store in replay buffer (for late WS connections)\n run.eventBuffer.push(seqEvent);\n }\n\n // Publish to eventBus for cross-process delivery\n if (platform?.eventBus) {\n const topic = `${EVENT_TOPIC_PREFIX}${runId}`;\n platform.eventBus.publish(topic, seqEvent).catch(() => {\n // Ignore publish errors\n });\n }\n\n // Also notify local in-memory listeners (for same-process)\n if (run) {\n for (const listener of run.listeners) {\n try {\n listener(seqEvent);\n } catch {\n // Ignore listener errors\n }\n }\n }\n\n // Notify session-level listeners (persistent connections)\n const sessionId = this.runSessionMap.get(runId);\n if (sessionId) {\n const sListeners = this.sessionListeners.get(sessionId);\n if (sListeners) {\n for (const listener of sListeners) {\n try {\n listener(seqEvent);\n } catch {\n // Ignore listener errors\n }\n }\n }\n }\n\n return seqEvent;\n }\n\n /**\n * Add a session-level listener — receives events from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: AgentEventCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: AgentEventCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * Get replay buffer for a run (all events emitted since start).\n * Used by WS handler to send missed events on late connection.\n * Optionally filter by afterSeq to only get events the client hasn't seen.\n */\n getEventBuffer(runId: string, afterSeq?: number): AgentEvent[] {\n const run = this.activeRuns.get(runId);\n if (!run) {return [];}\n\n if (afterSeq != null) {\n return run.eventBuffer.filter((e) => e.seq != null && e.seq > afterSeq);\n }\n return [...run.eventBuffer];\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * POST /run handler\n *\n * Starts a new agent run via Orchestrator\n */\n\nimport { defineHandler, rethrowForRest, useAnalytics, useCache, useConfig, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager, createCoreToolPack, bootstrapAgentSDK, createSessionMemoryBridge } from '@kb-labs/agent-core';\nimport { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';\nimport { IncrementalTraceWriter } from '@kb-labs/agent-tracing';\n\n// Register SDKAgentRunner as the RunnerFactory (idempotent — runs once per process)\nbootstrapAgentSDK();\nimport { AgentSDK } from '@kb-labs/agent-sdk';\nimport { createToolRegistry } from '@kb-labs/agent-tools';\nimport type { RunRequest, RunResponse, AgentsPluginConfig, KernelState } from '@kb-labs/agent-contracts';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport {\n AGENTS_WS_BASE_PATH,\n AGENTS_WS_CHANNELS,\n AGENT_ANALYTICS_EVENTS,\n} from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nconst FOLLOW_UP_SCOPE_RE = /\\b(глубже|подробнее|детал|слишком поверхност|deeper|more depth|details?)\\b/i;\n\nfunction isLikelyFollowUpScopeTask(task: string): boolean {\n return FOLLOW_UP_SCOPE_RE.test(task);\n}\n\nfunction pathExists(dir: string): boolean {\n try {\n return fs.existsSync(dir);\n } catch {\n return false;\n }\n}\n\nfunction scoreRepoFromToolPath(rawPath: string, scores: Map<string, number>): void {\n const p = rawPath.replace(/\\\\/g, '/');\n\n // Explicit repo prefix: kb-labs-xxx/...\n const explicit = p.match(/(^|\\/)(kb-labs-[^/]+)\\//);\n if (explicit?.[2]) {\n scores.set(explicit[2], (scores.get(explicit[2]) ?? 0) + 5);\n }\n\n // Heuristic by package naming patterns\n if (p.startsWith('packages/')) {\n if (/packages\\/agent[-/]/.test(p) || /agent-core|agent-tools|agent-cli|agent-task-runner/.test(p)) {\n scores.set('kb-labs-agents', (scores.get('kb-labs-agents') ?? 0) + 4);\n }\n if (/packages\\/mind[-/]/.test(p) || /mind-engine|mind-core/.test(p)) {\n scores.set('kb-labs-mind', (scores.get('kb-labs-mind') ?? 0) + 4);\n }\n }\n}\n\nasync function inferFollowUpWorkingDir(\n sessionManager: SessionManager,\n sessionId: string,\n baseWorkingDir: string,\n): Promise<string | null> {\n const events = await sessionManager.getSessionEvents(sessionId);\n if (!events.length) {\n return null;\n }\n\n // Find the latest completed run in this session\n const completedRuns = new Set<string>();\n for (const event of events) {\n if (event.type === 'agent:end' && event.runId) {\n completedRuns.add(event.runId);\n }\n }\n const lastRunId = Array.from(completedRuns).at(-1);\n if (!lastRunId) {\n return null;\n }\n\n const repoScores = new Map<string, number>();\n for (const event of events) {\n if (event.runId !== lastRunId) {\n continue;\n }\n\n if (event.type === 'tool:start') {\n const input = (event.data?.input as Record<string, unknown> | undefined) ?? {};\n const p1 = input.path;\n const p2 = input.directory;\n if (typeof p1 === 'string') {scoreRepoFromToolPath(p1, repoScores);}\n if (typeof p2 === 'string') {scoreRepoFromToolPath(p2, repoScores);}\n }\n\n if (event.type === 'tool:end') {\n const metadata = (event.data?.metadata as Record<string, unknown> | undefined) ?? {};\n const p = metadata.path;\n if (typeof p === 'string') {scoreRepoFromToolPath(p, repoScores);}\n }\n }\n\n const ranked = Array.from(repoScores.entries()).sort((a, b) => b[1] - a[1]);\n const top = ranked[0];\n if (!top || top[1] < 4) {\n return null;\n }\n\n const inferredDir = path.join(baseWorkingDir, top[0]);\n return pathExists(inferredDir) ? inferredDir : null;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<RunRequest>\n ): Promise<RunResponse> {\n try {\n const body = input.body as RunRequest | undefined;\n\n if (!body?.task) {\n throw new Error('Task is required');\n }\n\n const analytics = useAnalytics();\n const runId = RunManager.generateRunId();\n const startTime = Date.now();\n\n // Get or create session\n let sessionId = body.sessionId;\n let workingDir = body.workingDir || ctx.cwd;\n let sessionManager = new SessionManager(workingDir);\n if (!sessionId) {\n // Create new session\n const session = await sessionManager.createSession({\n mode: 'execute',\n task: body.task,\n agentId: body.agentId ?? 'orchestrator',\n });\n sessionId = session.id;\n ctx.platform.logger.info(`[run-handler] Created new session ${sessionId}`);\n } else {\n // Verify session exists (from current manager first)\n const existingSession = await sessionManager.loadSession(sessionId);\n let resolvedSession = existingSession;\n\n // Fallback: session may belong to a different root than current ctx.cwd\n if (!resolvedSession && pathExists(ctx.cwd)) {\n const fallbackManager = new SessionManager(ctx.cwd);\n const fallbackSession = await fallbackManager.loadSession(sessionId);\n if (fallbackSession) {\n sessionManager = fallbackManager;\n resolvedSession = fallbackSession;\n }\n }\n\n if (!resolvedSession) {\n throw new Error(`Session not found: ${sessionId} (cwd=${ctx.cwd})`);\n }\n\n // Session workingDir is primary source of truth for follow-up runs\n workingDir = body.workingDir || resolvedSession.workingDir || workingDir;\n\n // Smart follow-up anchoring: keep depth requests in the same repo/module as previous run\n if (!body.workingDir && isLikelyFollowUpScopeTask(body.task)) {\n const inferred = await inferFollowUpWorkingDir(sessionManager, sessionId, resolvedSession.workingDir || ctx.cwd);\n if (inferred && inferred !== workingDir) {\n ctx.platform.logger.info(`[run-handler] Follow-up scope inferred: ${workingDir} -> ${inferred}`);\n workingDir = inferred;\n }\n }\n\n // Rebind session manager to effective working directory\n sessionManager = new SessionManager(workingDir);\n ctx.platform.logger.info(`[run-handler] Continuing session ${sessionId} (workingDir=${workingDir})`);\n }\n\n ctx.platform.logger.info(`[run-handler] Starting run ${runId} for task: ${body.task}`);\n\n // Create user turn with task/question\n await sessionManager.createUserTurn(sessionId, body.task, runId);\n\n // Track run started\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STARTED, {\n runId,\n sessionId,\n taskLength: body.task.length,\n tier: body.tier ?? 'medium',\n enableEscalation: body.enableEscalation ?? true,\n responseMode: body.responseMode ?? 'auto',\n verbose: body.verbose ?? false,\n });\n\n // Create tool registry with standard tools\n const sessionMemory = createSessionMemoryBridge(workingDir, sessionId);\n const responseRequirementsSelector = createDefaultResponseRequirementsSelector();\n const toolRegistry = createToolRegistry({\n workingDir,\n currentTask: body.task,\n sessionId,\n verbose: body.verbose,\n cache: useCache(),\n sessionMemory,\n responseRequirementsResolver: async ({ task, kernel }: {\n task?: string;\n answer: string;\n kernel: KernelState | null;\n }) =>\n responseRequirementsSelector.select({\n state: kernel,\n messages: [],\n task: task ?? body.task,\n }),\n });\n const agentsConfig = await useConfig<AgentsPluginConfig>();\n\n const finalSessionId = sessionId; // Capture for closure\n const traceDir = path.join(workingDir, '.kb', 'traces', 'incremental');\n const traceWriter = new IncrementalTraceWriter(runId, {}, traceDir);\n\n // Create agent with event broadcasting and session persistence\n const agent = new AgentSDK()\n .register(createCoreToolPack(toolRegistry))\n .createRunner({\n sessionId: finalSessionId,\n workingDir,\n maxIterations: 50,\n temperature: 0.1,\n tier: body.tier ?? 'medium',\n tokenBudget: agentsConfig?.tokenBudget,\n onEvent: (event) => {\n // Broadcast to all WebSocket listeners (assigns seq)\n const seqEvent = RunManager.broadcast(runId, event);\n\n // Persist event with seq + runId + sessionId in metadata to session storage\n void sessionManager.addEvent(finalSessionId, {\n ...seqEvent,\n sessionId: finalSessionId,\n runId,\n metadata: {\n ...seqEvent.metadata,\n sessionId: finalSessionId,\n runId,\n workingDir,\n },\n });\n },\n });\n\n // Register run (pass sessionManager and sessionId so session-level WS listeners receive events)\n const run = await RunManager.register(runId, body.task, agent, sessionManager, finalSessionId);\n await RunManager.updateStatus(runId, 'running');\n\n // Start execution in background (don't await)\n void (async () => {\n try {\n const result = await agent.execute(body.task);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n // Attach file change summaries to the turn so the UI can show rollback/approve panel\n // Populated by ChangeTrackingMiddleware via run.meta → TaskResult.fileChanges\n if (result.fileChanges && result.fileChanges.length > 0) {\n await sessionManager.attachFileChangesToTurn(finalSessionId, runId, result.fileChanges);\n }\n\n await RunManager.updateStatus(runId, result.success ? 'completed' : 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n summary: result.summary,\n error: result.error,\n });\n\n // Track completion\n await analytics?.track(\n result.success ? AGENT_ANALYTICS_EVENTS.RUN_COMPLETED : AGENT_ANALYTICS_EVENTS.RUN_FAILED,\n {\n runId,\n durationMs,\n success: result.success,\n summary: result.summary?.slice(0, 200),\n }\n );\n\n ctx.platform.logger.info(`[run-handler] Run ${runId} completed: ${result.success}`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n await RunManager.updateStatus(runId, 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n error: errorMsg,\n });\n\n // Track failure\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_FAILED, {\n runId,\n durationMs,\n error: errorMsg.slice(0, 200),\n });\n\n ctx.platform.logger.error(`[run-handler] Run ${runId} failed: ${errorMsg}`);\n }\n })();\n\n // Return relative WS path — clients construct the full URL from their own base URL.\n const wsPath = AGENTS_WS_CHANNELS.SESSION_STREAM.replace(':sessionId', finalSessionId);\n const eventsPath = `${AGENTS_WS_BASE_PATH}${wsPath}`;\n\n return {\n runId,\n sessionId: finalSessionId,\n eventsPath,\n status: 'started',\n startedAt: run.startedAt,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/rest/run-manager.ts","../../../src/rest/handlers/run-handler.ts"],"names":["useCache"],"mappings":"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","file":"run-handler.js","sourcesContent":["/**\n * Run Manager - tracks active agent runs for REST/WS API\n *\n * Uses platform cache for persistence and in-memory Map for active agents.\n * Cache stores serializable run state, Map stores live agent references.\n */\n\nimport type { IAgentRunner } from '@kb-labs/agent-sdk';\nimport type { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn, TurnDelta } from '@kb-labs/agent-contracts';\nimport { useCache } from '@kb-labs/sdk';\n\nconst CACHE_PREFIX = 'agent:run:';\nconst CACHE_TTL = 3600000; // 1 hour\n\n/**\n * Run status\n */\nexport type RunStatus = 'pending' | 'running' | 'completed' | 'failed' | 'stopped';\n\n/**\n * Serializable run state (stored in cache)\n */\nexport interface RunState {\n runId: string;\n task: string;\n status: RunStatus;\n startedAt: string;\n completedAt?: string;\n durationMs?: number;\n summary?: string;\n error?: string;\n}\n\n/**\n * Active run with live agent (in-memory only)\n */\nexport interface ActiveRun extends RunState {\n agent?: IAgentRunner;\n sessionManager: SessionManager;\n}\n\n/**\n * Payload delivered to session-level listeners — the sole live-update\n * channel for a session's WS connection(s). `deltas` carries incremental\n * turn changes (see TurnDelta); `run:completed` is a terminal signal\n * carrying the finished run's outcome and, when available, the final\n * state of the assistant turn it produced.\n */\nexport type SessionBroadcastPayload =\n | { kind: 'deltas'; deltas: TurnDelta[] }\n | {\n kind: 'run:completed';\n runId: string;\n success: boolean;\n summary: string;\n durationMs: number;\n seq: number;\n turn?: Turn;\n };\n\ntype SessionListenerCallback = (payload: SessionBroadcastPayload) => void;\n\n/**\n * Run Manager implementation\n */\nclass RunManagerImpl {\n /** Live agents (not cacheable) */\n private activeRuns: Map<string, ActiveRun> = new Map();\n\n /** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */\n private sessionListeners: Map<string, Set<SessionListenerCallback>> = new Map();\n\n /**\n * Generate unique run ID\n */\n generateRunId(): string {\n return `run-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;\n }\n\n /**\n * Register a new run\n */\n async register(\n runId: string,\n task: string,\n agent: IAgentRunner | undefined,\n sessionManager: SessionManager,\n ): Promise<ActiveRun> {\n const now = new Date().toISOString();\n\n const run: ActiveRun = {\n runId,\n task,\n status: 'pending',\n agent,\n sessionManager,\n startedAt: now,\n };\n\n // Store in memory (for live agent)\n this.activeRuns.set(runId, run);\n\n // Store serializable state in cache\n await this.saveToCache(run);\n\n return run;\n }\n\n /**\n * Get run by ID (from memory first, then cache for state)\n */\n get(runId: string): ActiveRun | undefined {\n return this.activeRuns.get(runId);\n }\n\n /**\n * Check if run exists (in memory or cache)\n */\n async exists(runId: string): Promise<boolean> {\n // Check memory first\n if (this.activeRuns.has(runId)) {\n return true;\n }\n // Fallback to cache\n const state = await this.getState(runId);\n return state !== null;\n }\n\n /**\n * Get run state from cache (for completed runs or cross-process access)\n */\n async getState(runId: string): Promise<RunState | null> {\n const cache = useCache();\n if (!cache) {return null;}\n\n return cache.get<RunState>(`${CACHE_PREFIX}${runId}`);\n }\n\n /**\n * Update run status\n */\n async updateStatus(runId: string, status: RunStatus, extra?: Partial<RunState>): Promise<void> {\n const run = this.activeRuns.get(runId);\n if (run) {\n run.status = status;\n if (extra) {\n Object.assign(run, extra);\n }\n await this.saveToCache(run);\n }\n }\n\n /**\n * Save run state to cache\n */\n private async saveToCache(run: ActiveRun): Promise<void> {\n const cache = useCache();\n if (!cache) {return;}\n\n const state: RunState = {\n runId: run.runId,\n task: run.task,\n status: run.status,\n startedAt: run.startedAt,\n completedAt: run.completedAt,\n durationMs: run.durationMs,\n summary: run.summary,\n error: run.error,\n };\n\n await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);\n }\n\n /**\n * Broadcast turn deltas to all session-level listeners. Callers MUST await\n * persistence (sessionManager.addEvent) before calling this, so listeners\n * never observe a delta whose underlying turn state isn't on disk yet —\n * that ordering is what makes gap-recovery / reconnect resume correct.\n */\n broadcastSessionDeltas(sessionId: string, deltas: TurnDelta[]): void {\n if (deltas.length === 0) { return; }\n this.notifySessionListeners(sessionId, { kind: 'deltas', deltas });\n }\n\n /**\n * Broadcast a run's terminal outcome to session-level listeners. Called\n * directly from the run's own completion handler (after `agent.execute()`\n * resolves) rather than derived reactively from an `agent:end` event —\n * the completion handler already has definitive success/summary/duration,\n * and this guarantees the message fires exactly once, deterministically.\n */\n broadcastRunCompleted(sessionId: string, payload: Omit<Extract<SessionBroadcastPayload, { kind: 'run:completed' }>, 'kind'>): void {\n this.notifySessionListeners(sessionId, { kind: 'run:completed', ...payload });\n }\n\n private notifySessionListeners(sessionId: string, payload: SessionBroadcastPayload): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (!listeners) { return; }\n for (const listener of listeners) {\n try {\n listener(payload);\n } catch {\n // Ignore listener errors — one bad WS connection shouldn't affect others\n }\n }\n }\n\n /**\n * Add a session-level listener — receives updates from ALL runs in this session.\n */\n addSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n if (!this.sessionListeners.has(sessionId)) {\n this.sessionListeners.set(sessionId, new Set());\n }\n this.sessionListeners.get(sessionId)!.add(callback);\n }\n\n /**\n * Remove a session-level listener.\n */\n removeSessionListener(sessionId: string, callback: SessionListenerCallback): void {\n const listeners = this.sessionListeners.get(sessionId);\n if (listeners) {\n listeners.delete(callback);\n if (listeners.size === 0) {\n this.sessionListeners.delete(sessionId);\n }\n }\n }\n\n /**\n * List all active runs\n */\n listActive(): Array<{ runId: string; task: string; status: RunStatus; startedAt: string }> {\n return Array.from(this.activeRuns.values()).map(r => ({\n runId: r.runId,\n task: r.task,\n status: r.status,\n startedAt: r.startedAt,\n }));\n }\n\n /**\n * Request graceful stop of a running agent (and its child agents via propagated AbortSignal).\n * Agent finishes its current tool call then exits at the next iteration boundary.\n */\n requestStop(runId: string): boolean {\n const run = this.activeRuns.get(runId);\n if (!run || run.status !== 'running' || !run.agent) {\n return false;\n }\n run.agent.requestStop();\n return true;\n }\n\n /**\n * Clean up completed runs from memory (cache handles its own TTL)\n */\n cleanup(): void {\n for (const [runId, run] of this.activeRuns) {\n if (run.status === 'completed' || run.status === 'failed' || run.status === 'stopped') {\n // Remove from memory but keep in cache\n this.activeRuns.delete(runId);\n }\n }\n }\n}\n\n/**\n * Singleton instance — stored on globalThis so all bundled modules share one instance.\n * When tsup compiles multiple entry points, each gets its own module scope,\n * so a plain `export const RunManager = new RunManagerImpl()` creates separate instances.\n * Using globalThis ensures run-handler.js and session-stream-handler.js share one RunManager.\n */\nconst GLOBAL_KEY = '__kb_agent_run_manager__';\nif (!(globalThis as Record<string, unknown>)[GLOBAL_KEY]) {\n (globalThis as Record<string, unknown>)[GLOBAL_KEY] = new RunManagerImpl();\n}\nexport const RunManager = (globalThis as Record<string, unknown>)[GLOBAL_KEY] as RunManagerImpl;\n","/**\n * POST /run handler\n *\n * Starts a new agent run via Orchestrator\n */\n\nimport { defineHandler, rethrowForRest, useAnalytics, useCache, useConfig, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager, createCoreToolPack, bootstrapAgentSDK, createSessionMemoryBridge } from '@kb-labs/agent-core';\nimport { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';\nimport { IncrementalTraceWriter } from '@kb-labs/agent-tracing';\n\n// Register SDKAgentRunner as the RunnerFactory (idempotent — runs once per process)\nbootstrapAgentSDK();\nimport { AgentSDK } from '@kb-labs/agent-sdk';\nimport { createToolRegistry } from '@kb-labs/agent-tools';\nimport type { RunRequest, RunResponse, AgentsPluginConfig, KernelState } from '@kb-labs/agent-contracts';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport {\n AGENTS_WS_BASE_PATH,\n AGENTS_WS_CHANNELS,\n AGENT_ANALYTICS_EVENTS,\n} from '@kb-labs/agent-contracts';\nimport { RunManager } from '../run-manager.js';\n\nconst FOLLOW_UP_SCOPE_RE = /\\b(глубже|подробнее|детал|слишком поверхност|deeper|more depth|details?)\\b/i;\n\nfunction isLikelyFollowUpScopeTask(task: string): boolean {\n return FOLLOW_UP_SCOPE_RE.test(task);\n}\n\nfunction pathExists(dir: string): boolean {\n try {\n return fs.existsSync(dir);\n } catch {\n return false;\n }\n}\n\nfunction scoreRepoFromToolPath(rawPath: string, scores: Map<string, number>): void {\n const p = rawPath.replace(/\\\\/g, '/');\n\n // Explicit repo prefix: kb-labs-xxx/...\n const explicit = p.match(/(^|\\/)(kb-labs-[^/]+)\\//);\n if (explicit?.[2]) {\n scores.set(explicit[2], (scores.get(explicit[2]) ?? 0) + 5);\n }\n\n // Heuristic by package naming patterns\n if (p.startsWith('packages/')) {\n if (/packages\\/agent[-/]/.test(p) || /agent-core|agent-tools|agent-cli|agent-task-runner/.test(p)) {\n scores.set('kb-labs-agents', (scores.get('kb-labs-agents') ?? 0) + 4);\n }\n if (/packages\\/mind[-/]/.test(p) || /mind-engine|mind-core/.test(p)) {\n scores.set('kb-labs-mind', (scores.get('kb-labs-mind') ?? 0) + 4);\n }\n }\n}\n\nasync function inferFollowUpWorkingDir(\n sessionManager: SessionManager,\n sessionId: string,\n baseWorkingDir: string,\n): Promise<string | null> {\n const events = await sessionManager.getSessionEvents(sessionId);\n if (!events.length) {\n return null;\n }\n\n // Find the latest completed run in this session\n const completedRuns = new Set<string>();\n for (const event of events) {\n if (event.type === 'agent:end' && event.runId) {\n completedRuns.add(event.runId);\n }\n }\n const lastRunId = Array.from(completedRuns).at(-1);\n if (!lastRunId) {\n return null;\n }\n\n const repoScores = new Map<string, number>();\n for (const event of events) {\n if (event.runId !== lastRunId) {\n continue;\n }\n\n if (event.type === 'tool:start') {\n const input = (event.data?.input as Record<string, unknown> | undefined) ?? {};\n const p1 = input.path;\n const p2 = input.directory;\n if (typeof p1 === 'string') {scoreRepoFromToolPath(p1, repoScores);}\n if (typeof p2 === 'string') {scoreRepoFromToolPath(p2, repoScores);}\n }\n\n if (event.type === 'tool:end') {\n const metadata = (event.data?.metadata as Record<string, unknown> | undefined) ?? {};\n const p = metadata.path;\n if (typeof p === 'string') {scoreRepoFromToolPath(p, repoScores);}\n }\n }\n\n const ranked = Array.from(repoScores.entries()).sort((a, b) => b[1] - a[1]);\n const top = ranked[0];\n if (!top || top[1] < 4) {\n return null;\n }\n\n const inferredDir = path.join(baseWorkingDir, top[0]);\n return pathExists(inferredDir) ? inferredDir : null;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<RunRequest>\n ): Promise<RunResponse> {\n try {\n const body = input.body as RunRequest | undefined;\n\n if (!body?.task) {\n throw new Error('Task is required');\n }\n\n const analytics = useAnalytics();\n const runId = RunManager.generateRunId();\n const startTime = Date.now();\n\n // Get or create session\n let sessionId = body.sessionId;\n let workingDir = body.workingDir || ctx.cwd;\n let sessionManager = new SessionManager(workingDir);\n if (!sessionId) {\n // Create new session\n const session = await sessionManager.createSession({\n mode: 'execute',\n task: body.task,\n agentId: body.agentId ?? 'orchestrator',\n });\n sessionId = session.id;\n ctx.platform.logger.info(`[run-handler] Created new session ${sessionId}`);\n } else {\n // Verify session exists (from current manager first)\n const existingSession = await sessionManager.loadSession(sessionId);\n let resolvedSession = existingSession;\n\n // Fallback: session may belong to a different root than current ctx.cwd\n if (!resolvedSession && pathExists(ctx.cwd)) {\n const fallbackManager = new SessionManager(ctx.cwd);\n const fallbackSession = await fallbackManager.loadSession(sessionId);\n if (fallbackSession) {\n sessionManager = fallbackManager;\n resolvedSession = fallbackSession;\n }\n }\n\n if (!resolvedSession) {\n throw new Error(`Session not found: ${sessionId} (cwd=${ctx.cwd})`);\n }\n\n // Session workingDir is primary source of truth for follow-up runs\n workingDir = body.workingDir || resolvedSession.workingDir || workingDir;\n\n // Smart follow-up anchoring: keep depth requests in the same repo/module as previous run\n if (!body.workingDir && isLikelyFollowUpScopeTask(body.task)) {\n const inferred = await inferFollowUpWorkingDir(sessionManager, sessionId, resolvedSession.workingDir || ctx.cwd);\n if (inferred && inferred !== workingDir) {\n ctx.platform.logger.info(`[run-handler] Follow-up scope inferred: ${workingDir} -> ${inferred}`);\n workingDir = inferred;\n }\n }\n\n // Rebind session manager to effective working directory\n sessionManager = new SessionManager(workingDir);\n ctx.platform.logger.info(`[run-handler] Continuing session ${sessionId} (workingDir=${workingDir})`);\n }\n\n ctx.platform.logger.info(`[run-handler] Starting run ${runId} for task: ${body.task}`);\n\n // Create user turn with task/question\n const userTurn = await sessionManager.createUserTurn(sessionId, body.task, runId, body.clientId);\n\n // Track run started\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_STARTED, {\n runId,\n sessionId,\n taskLength: body.task.length,\n tier: body.tier ?? 'medium',\n enableEscalation: body.enableEscalation ?? true,\n responseMode: body.responseMode ?? 'auto',\n verbose: body.verbose ?? false,\n });\n\n // Create tool registry with standard tools\n const sessionMemory = createSessionMemoryBridge(workingDir, sessionId);\n const responseRequirementsSelector = createDefaultResponseRequirementsSelector();\n const toolRegistry = createToolRegistry({\n workingDir,\n currentTask: body.task,\n sessionId,\n verbose: body.verbose,\n cache: useCache(),\n sessionMemory,\n responseRequirementsResolver: async ({ task, kernel }: {\n task?: string;\n answer: string;\n kernel: KernelState | null;\n }) =>\n responseRequirementsSelector.select({\n state: kernel,\n messages: [],\n task: task ?? body.task,\n }),\n });\n const agentsConfig = await useConfig<AgentsPluginConfig>();\n\n const finalSessionId = sessionId; // Capture for closure\n const traceDir = path.join(workingDir, '.kb', 'traces', 'incremental');\n const traceWriter = new IncrementalTraceWriter(runId, {}, traceDir);\n\n // Create agent with event broadcasting and session persistence\n const agent = new AgentSDK()\n .register(createCoreToolPack(toolRegistry))\n .createRunner({\n sessionId: finalSessionId,\n workingDir,\n maxIterations: 50,\n temperature: 0.1,\n tier: body.tier ?? 'medium',\n tokenBudget: agentsConfig?.tokenBudget,\n onEvent: (event) => {\n // Persist FIRST, broadcast only once that's confirmed — deltas are\n // computed from what was actually written, so a WS listener can\n // never observe turn state that isn't safely on disk yet. This\n // ordering (previously reversed: broadcast raced ahead of persist)\n // was the root cause of the WS stream silently lagging one event\n // behind the true state.\n void sessionManager.addEvent(finalSessionId, {\n ...event,\n sessionId: finalSessionId,\n runId,\n metadata: {\n ...event.metadata,\n sessionId: finalSessionId,\n runId,\n workingDir,\n },\n }).then((deltas) => {\n RunManager.broadcastSessionDeltas(finalSessionId, deltas);\n });\n },\n });\n\n // Register run (session-level WS listeners are registered separately via addSessionListener)\n const run = await RunManager.register(runId, body.task, agent, sessionManager);\n await RunManager.updateStatus(runId, 'running');\n\n // Start execution in background (don't await)\n void (async () => {\n try {\n const result = await agent.execute(body.task);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n // Attach file change summaries to the turn so the UI can show rollback/approve panel\n // Populated by ChangeTrackingMiddleware via run.meta → TaskResult.fileChanges\n if (result.fileChanges && result.fileChanges.length > 0) {\n await sessionManager.attachFileChangesToTurn(finalSessionId, runId, result.fileChanges);\n }\n\n await RunManager.updateStatus(runId, result.success ? 'completed' : 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n summary: result.summary,\n error: result.error,\n });\n\n // The terminal WS signal fires from here — the run's own completion\n // handler, which has definitive success/summary/duration — rather\n // than being derived reactively from an agent:end event on the WS\n // side. Carries the final assistant turn (if this run produced one)\n // so the client has a guaranteed-fresh terminal state without\n // depending on delta message ordering.\n const finalTurns = await sessionManager.getTurns(finalSessionId);\n const finalTurn = finalTurns.find((t) => t.type === 'assistant' && t.metadata.runId === runId);\n const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);\n RunManager.broadcastRunCompleted(finalSessionId, {\n runId,\n success: result.success,\n summary: result.summary,\n durationMs,\n seq,\n turn: finalTurn,\n });\n\n // Track completion\n await analytics?.track(\n result.success ? AGENT_ANALYTICS_EVENTS.RUN_COMPLETED : AGENT_ANALYTICS_EVENTS.RUN_FAILED,\n {\n runId,\n durationMs,\n success: result.success,\n summary: result.summary?.slice(0, 200),\n }\n );\n\n ctx.platform.logger.info(`[run-handler] Run ${runId} completed: ${result.success}`);\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n const durationMs = Date.now() - startTime;\n const detailedTrace = traceWriter.getEntries() as unknown as Array<Record<string, unknown>>;\n await traceWriter.finalize?.();\n if (detailedTrace.length > 0) {\n await sessionManager.storeTraceArtifacts(finalSessionId, runId, detailedTrace);\n }\n\n await RunManager.updateStatus(runId, 'failed', {\n completedAt: new Date().toISOString(),\n durationMs,\n error: errorMsg,\n });\n\n const seq = await sessionManager.getCurrentSessionSeq(finalSessionId);\n RunManager.broadcastRunCompleted(finalSessionId, {\n runId,\n success: false,\n summary: errorMsg,\n durationMs,\n seq,\n });\n\n // Track failure\n await analytics?.track(AGENT_ANALYTICS_EVENTS.RUN_FAILED, {\n runId,\n durationMs,\n error: errorMsg.slice(0, 200),\n });\n\n ctx.platform.logger.error(`[run-handler] Run ${runId} failed: ${errorMsg}`);\n }\n })();\n\n // Return relative WS path — clients construct the full URL from their own base URL.\n const wsPath = AGENTS_WS_CHANNELS.SESSION_STREAM.replace(':sessionId', finalSessionId);\n const eventsPath = `${AGENTS_WS_BASE_PATH}${wsPath}`;\n\n return {\n runId,\n sessionId: finalSessionId,\n eventsPath,\n status: 'started',\n startedAt: run.startedAt,\n userTurn,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { defineHandler, rethrowForRest, useCache
|
|
1
|
+
import { defineHandler, rethrowForRest, useCache } from '@kb-labs/sdk';
|
|
2
2
|
|
|
3
3
|
// src/rest/handlers/status-handler.ts
|
|
4
4
|
var CACHE_PREFIX = "agent:run:";
|
|
5
|
-
var EVENT_TOPIC_PREFIX = "agent:events:";
|
|
6
5
|
var CACHE_TTL = 36e5;
|
|
7
6
|
var RunManagerImpl = class {
|
|
8
|
-
/** Live agents
|
|
7
|
+
/** Live agents (not cacheable) */
|
|
9
8
|
activeRuns = /* @__PURE__ */ new Map();
|
|
10
|
-
/** Session-level listeners: sessionId → Set<callback> — receive
|
|
9
|
+
/** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */
|
|
11
10
|
sessionListeners = /* @__PURE__ */ new Map();
|
|
12
|
-
/** sessionId per runId — set when run is registered */
|
|
13
|
-
runSessionMap = /* @__PURE__ */ new Map();
|
|
14
11
|
/**
|
|
15
12
|
* Generate unique run ID
|
|
16
13
|
*/
|
|
@@ -20,7 +17,7 @@ var RunManagerImpl = class {
|
|
|
20
17
|
/**
|
|
21
18
|
* Register a new run
|
|
22
19
|
*/
|
|
23
|
-
async register(runId, task, agent, sessionManager
|
|
20
|
+
async register(runId, task, agent, sessionManager) {
|
|
24
21
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
25
22
|
const run = {
|
|
26
23
|
runId,
|
|
@@ -28,15 +25,9 @@ var RunManagerImpl = class {
|
|
|
28
25
|
status: "pending",
|
|
29
26
|
agent,
|
|
30
27
|
sessionManager,
|
|
31
|
-
startedAt: now
|
|
32
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
33
|
-
lastSeq: 0,
|
|
34
|
-
eventBuffer: []
|
|
28
|
+
startedAt: now
|
|
35
29
|
};
|
|
36
30
|
this.activeRuns.set(runId, run);
|
|
37
|
-
if (sessionId) {
|
|
38
|
-
this.runSessionMap.set(runId, sessionId);
|
|
39
|
-
}
|
|
40
31
|
await this.saveToCache(run);
|
|
41
32
|
return run;
|
|
42
33
|
}
|
|
@@ -99,101 +90,42 @@ var RunManagerImpl = class {
|
|
|
99
90
|
};
|
|
100
91
|
await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);
|
|
101
92
|
}
|
|
102
|
-
/** Track subscriptions for cleanup */
|
|
103
|
-
subscriptions = /* @__PURE__ */ new Map();
|
|
104
93
|
/**
|
|
105
|
-
*
|
|
94
|
+
* Broadcast turn deltas to all session-level listeners. Callers MUST await
|
|
95
|
+
* persistence (sessionManager.addEvent) before calling this, so listeners
|
|
96
|
+
* never observe a delta whose underlying turn state isn't on disk yet —
|
|
97
|
+
* that ordering is what makes gap-recovery / reconnect resume correct.
|
|
106
98
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const run2 = this.activeRuns.get(runId);
|
|
111
|
-
if (run2) {
|
|
112
|
-
run2.listeners.add(callback);
|
|
113
|
-
return true;
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
const topic = `${EVENT_TOPIC_PREFIX}${runId}`;
|
|
118
|
-
const unsubscribe = platform.eventBus.subscribe(topic, async (event) => {
|
|
119
|
-
try {
|
|
120
|
-
callback(event);
|
|
121
|
-
} catch {
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
if (!this.subscriptions.has(runId)) {
|
|
125
|
-
this.subscriptions.set(runId, /* @__PURE__ */ new Map());
|
|
126
|
-
}
|
|
127
|
-
this.subscriptions.get(runId).set(callback, unsubscribe);
|
|
128
|
-
const run = this.activeRuns.get(runId);
|
|
129
|
-
if (run) {
|
|
130
|
-
run.listeners.add(callback);
|
|
99
|
+
broadcastSessionDeltas(sessionId, deltas) {
|
|
100
|
+
if (deltas.length === 0) {
|
|
101
|
+
return;
|
|
131
102
|
}
|
|
132
|
-
|
|
103
|
+
this.notifySessionListeners(sessionId, { kind: "deltas", deltas });
|
|
133
104
|
}
|
|
134
105
|
/**
|
|
135
|
-
*
|
|
106
|
+
* Broadcast a run's terminal outcome to session-level listeners. Called
|
|
107
|
+
* directly from the run's own completion handler (after `agent.execute()`
|
|
108
|
+
* resolves) rather than derived reactively from an `agent:end` event —
|
|
109
|
+
* the completion handler already has definitive success/summary/duration,
|
|
110
|
+
* and this guarantees the message fires exactly once, deterministically.
|
|
136
111
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (runSubs) {
|
|
140
|
-
const unsubscribe = runSubs.get(callback);
|
|
141
|
-
if (unsubscribe) {
|
|
142
|
-
unsubscribe();
|
|
143
|
-
runSubs.delete(callback);
|
|
144
|
-
}
|
|
145
|
-
if (runSubs.size === 0) {
|
|
146
|
-
this.subscriptions.delete(runId);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const run = this.activeRuns.get(runId);
|
|
150
|
-
if (run) {
|
|
151
|
-
run.listeners.delete(callback);
|
|
152
|
-
}
|
|
112
|
+
broadcastRunCompleted(sessionId, payload) {
|
|
113
|
+
this.notifySessionListeners(sessionId, { kind: "run:completed", ...payload });
|
|
153
114
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
*/
|
|
159
|
-
broadcast(runId, event) {
|
|
160
|
-
const platform = usePlatform();
|
|
161
|
-
const run = this.activeRuns.get(runId);
|
|
162
|
-
let seqEvent = event;
|
|
163
|
-
if (run) {
|
|
164
|
-
run.lastSeq++;
|
|
165
|
-
seqEvent = { ...event, seq: run.lastSeq, runId };
|
|
166
|
-
run.eventBuffer.push(seqEvent);
|
|
167
|
-
}
|
|
168
|
-
if (platform?.eventBus) {
|
|
169
|
-
const topic = `${EVENT_TOPIC_PREFIX}${runId}`;
|
|
170
|
-
platform.eventBus.publish(topic, seqEvent).catch(() => {
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
|
-
if (run) {
|
|
174
|
-
for (const listener of run.listeners) {
|
|
175
|
-
try {
|
|
176
|
-
listener(seqEvent);
|
|
177
|
-
} catch {
|
|
178
|
-
}
|
|
179
|
-
}
|
|
115
|
+
notifySessionListeners(sessionId, payload) {
|
|
116
|
+
const listeners = this.sessionListeners.get(sessionId);
|
|
117
|
+
if (!listeners) {
|
|
118
|
+
return;
|
|
180
119
|
}
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
for (const listener of sListeners) {
|
|
186
|
-
try {
|
|
187
|
-
listener(seqEvent);
|
|
188
|
-
} catch {
|
|
189
|
-
}
|
|
190
|
-
}
|
|
120
|
+
for (const listener of listeners) {
|
|
121
|
+
try {
|
|
122
|
+
listener(payload);
|
|
123
|
+
} catch {
|
|
191
124
|
}
|
|
192
125
|
}
|
|
193
|
-
return seqEvent;
|
|
194
126
|
}
|
|
195
127
|
/**
|
|
196
|
-
* Add a session-level listener — receives
|
|
128
|
+
* Add a session-level listener — receives updates from ALL runs in this session.
|
|
197
129
|
*/
|
|
198
130
|
addSessionListener(sessionId, callback) {
|
|
199
131
|
if (!this.sessionListeners.has(sessionId)) {
|
|
@@ -213,21 +145,6 @@ var RunManagerImpl = class {
|
|
|
213
145
|
}
|
|
214
146
|
}
|
|
215
147
|
}
|
|
216
|
-
/**
|
|
217
|
-
* Get replay buffer for a run (all events emitted since start).
|
|
218
|
-
* Used by WS handler to send missed events on late connection.
|
|
219
|
-
* Optionally filter by afterSeq to only get events the client hasn't seen.
|
|
220
|
-
*/
|
|
221
|
-
getEventBuffer(runId, afterSeq) {
|
|
222
|
-
const run = this.activeRuns.get(runId);
|
|
223
|
-
if (!run) {
|
|
224
|
-
return [];
|
|
225
|
-
}
|
|
226
|
-
if (afterSeq != null) {
|
|
227
|
-
return run.eventBuffer.filter((e) => e.seq != null && e.seq > afterSeq);
|
|
228
|
-
}
|
|
229
|
-
return [...run.eventBuffer];
|
|
230
|
-
}
|
|
231
148
|
/**
|
|
232
149
|
* List all active runs
|
|
233
150
|
*/
|