@kb-labs/agent-entry 2.118.2 → 2.119.0-canary.0c078654e
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.map +1 -1
- package/dist/cli/commands/history.js.map +1 -1
- package/dist/cli/commands/quality-report.js.map +1 -1
- package/dist/cli/commands/rollback.js.map +1 -1
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/trace-context.js.map +1 -1
- package/dist/cli/commands/trace-diagnose.js.map +1 -1
- package/dist/cli/commands/trace-event-normalizer.js.map +1 -1
- package/dist/cli/commands/trace-filter.js.map +1 -1
- package/dist/cli/commands/trace-iteration.js.map +1 -1
- package/dist/cli/commands/trace-stats.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/manifest.js.map +1 -1
- package/dist/rest/handlers/approve-handler.js.map +1 -1
- package/dist/rest/handlers/approve-session-plan-handler.js.map +1 -1
- package/dist/rest/handlers/correct-handler.js +29 -112
- package/dist/rest/handlers/correct-handler.js.map +1 -1
- package/dist/rest/handlers/create-session-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/get-file-diff-handler.js.map +1 -1
- package/dist/rest/handlers/get-session-handler.js.map +1 -1
- package/dist/rest/handlers/get-session-plan-handler.js.map +1 -1
- package/dist/rest/handlers/get-session-turns-handler.js.map +1 -1
- package/dist/rest/handlers/get-spec-handler.js.map +1 -1
- package/dist/rest/handlers/list-file-changes-handler.js.map +1 -1
- package/dist/rest/handlers/list-sessions-handler.js.map +1 -1
- package/dist/rest/handlers/rollback-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/sessions-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/ws/session-stream-handler.js +70 -180
- package/dist/ws/session-stream-handler.js.map +1 -1
- package/package.json +14 -14
- package/dist/manifest.json +0 -685
- package/dist/widgets/117.js +0 -25
- package/dist/widgets/165.js +0 -1
- package/dist/widgets/326.js +0 -1
- package/dist/widgets/370.js +0 -1
- package/dist/widgets/405.js +0 -1
- package/dist/widgets/46.js +0 -445
- package/dist/widgets/50.js +0 -1
- package/dist/widgets/546.js +0 -1
- package/dist/widgets/62.js +0 -96
- package/dist/widgets/648.js +0 -1
- package/dist/widgets/669.js +0 -1
- package/dist/widgets/707.js +0 -1
- package/dist/widgets/775.js +0 -1
- package/dist/widgets/78.js +0 -1
- package/dist/widgets/875.js +0 -25
- package/dist/widgets/945.js +0 -1
- package/dist/widgets/968.js +0 -9
- package/dist/widgets/__federation_expose_AgentsPage.js +0 -1
- package/dist/widgets/mf-manifest.json +0 -229
- package/dist/widgets/mf-stats.json +0 -256
- package/dist/widgets/remoteEntry.js +0 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineHandler, rethrowForRest, useCache
|
|
1
|
+
import { defineHandler, rethrowForRest, useCache } from '@kb-labs/sdk';
|
|
2
2
|
import { SessionManager, SpecModeHandler, createSessionMemoryBridge } from '@kb-labs/agent-core';
|
|
3
3
|
import { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';
|
|
4
4
|
import { IncrementalTraceWriter } from '@kb-labs/agent-tracing';
|
|
@@ -8,15 +8,12 @@ import path from 'path';
|
|
|
8
8
|
|
|
9
9
|
// src/rest/handlers/generate-spec-handler.ts
|
|
10
10
|
var CACHE_PREFIX = "agent:run:";
|
|
11
|
-
var EVENT_TOPIC_PREFIX = "agent:events:";
|
|
12
11
|
var CACHE_TTL = 36e5;
|
|
13
12
|
var RunManagerImpl = class {
|
|
14
|
-
/** Live agents
|
|
13
|
+
/** Live agents (not cacheable) */
|
|
15
14
|
activeRuns = /* @__PURE__ */ new Map();
|
|
16
|
-
/** Session-level listeners: sessionId → Set<callback> — receive
|
|
15
|
+
/** Session-level listeners: sessionId → Set<callback> — receive updates from ALL runs in session */
|
|
17
16
|
sessionListeners = /* @__PURE__ */ new Map();
|
|
18
|
-
/** sessionId per runId — set when run is registered */
|
|
19
|
-
runSessionMap = /* @__PURE__ */ new Map();
|
|
20
17
|
/**
|
|
21
18
|
* Generate unique run ID
|
|
22
19
|
*/
|
|
@@ -26,7 +23,7 @@ var RunManagerImpl = class {
|
|
|
26
23
|
/**
|
|
27
24
|
* Register a new run
|
|
28
25
|
*/
|
|
29
|
-
async register(runId, task, agent, sessionManager
|
|
26
|
+
async register(runId, task, agent, sessionManager) {
|
|
30
27
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
31
28
|
const run = {
|
|
32
29
|
runId,
|
|
@@ -34,15 +31,9 @@ var RunManagerImpl = class {
|
|
|
34
31
|
status: "pending",
|
|
35
32
|
agent,
|
|
36
33
|
sessionManager,
|
|
37
|
-
startedAt: now
|
|
38
|
-
listeners: /* @__PURE__ */ new Set(),
|
|
39
|
-
lastSeq: 0,
|
|
40
|
-
eventBuffer: []
|
|
34
|
+
startedAt: now
|
|
41
35
|
};
|
|
42
36
|
this.activeRuns.set(runId, run);
|
|
43
|
-
if (sessionId) {
|
|
44
|
-
this.runSessionMap.set(runId, sessionId);
|
|
45
|
-
}
|
|
46
37
|
await this.saveToCache(run);
|
|
47
38
|
return run;
|
|
48
39
|
}
|
|
@@ -105,101 +96,42 @@ var RunManagerImpl = class {
|
|
|
105
96
|
};
|
|
106
97
|
await cache.set(`${CACHE_PREFIX}${run.runId}`, state, CACHE_TTL);
|
|
107
98
|
}
|
|
108
|
-
/** Track subscriptions for cleanup */
|
|
109
|
-
subscriptions = /* @__PURE__ */ new Map();
|
|
110
99
|
/**
|
|
111
|
-
*
|
|
100
|
+
* Broadcast turn deltas to all session-level listeners. Callers MUST await
|
|
101
|
+
* persistence (sessionManager.addEvent) before calling this, so listeners
|
|
102
|
+
* never observe a delta whose underlying turn state isn't on disk yet —
|
|
103
|
+
* that ordering is what makes gap-recovery / reconnect resume correct.
|
|
112
104
|
*/
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const run2 = this.activeRuns.get(runId);
|
|
117
|
-
if (run2) {
|
|
118
|
-
run2.listeners.add(callback);
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
const topic = `${EVENT_TOPIC_PREFIX}${runId}`;
|
|
124
|
-
const unsubscribe = platform.eventBus.subscribe(topic, async (event) => {
|
|
125
|
-
try {
|
|
126
|
-
callback(event);
|
|
127
|
-
} catch {
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
if (!this.subscriptions.has(runId)) {
|
|
131
|
-
this.subscriptions.set(runId, /* @__PURE__ */ new Map());
|
|
132
|
-
}
|
|
133
|
-
this.subscriptions.get(runId).set(callback, unsubscribe);
|
|
134
|
-
const run = this.activeRuns.get(runId);
|
|
135
|
-
if (run) {
|
|
136
|
-
run.listeners.add(callback);
|
|
105
|
+
broadcastSessionDeltas(sessionId, deltas) {
|
|
106
|
+
if (deltas.length === 0) {
|
|
107
|
+
return;
|
|
137
108
|
}
|
|
138
|
-
|
|
109
|
+
this.notifySessionListeners(sessionId, { kind: "deltas", deltas });
|
|
139
110
|
}
|
|
140
111
|
/**
|
|
141
|
-
*
|
|
112
|
+
* Broadcast a run's terminal outcome to session-level listeners. Called
|
|
113
|
+
* directly from the run's own completion handler (after `agent.execute()`
|
|
114
|
+
* resolves) rather than derived reactively from an `agent:end` event —
|
|
115
|
+
* the completion handler already has definitive success/summary/duration,
|
|
116
|
+
* and this guarantees the message fires exactly once, deterministically.
|
|
142
117
|
*/
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if (runSubs) {
|
|
146
|
-
const unsubscribe = runSubs.get(callback);
|
|
147
|
-
if (unsubscribe) {
|
|
148
|
-
unsubscribe();
|
|
149
|
-
runSubs.delete(callback);
|
|
150
|
-
}
|
|
151
|
-
if (runSubs.size === 0) {
|
|
152
|
-
this.subscriptions.delete(runId);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
const run = this.activeRuns.get(runId);
|
|
156
|
-
if (run) {
|
|
157
|
-
run.listeners.delete(callback);
|
|
158
|
-
}
|
|
118
|
+
broadcastRunCompleted(sessionId, payload) {
|
|
119
|
+
this.notifySessionListeners(sessionId, { kind: "run:completed", ...payload });
|
|
159
120
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
*/
|
|
165
|
-
broadcast(runId, event) {
|
|
166
|
-
const platform = usePlatform();
|
|
167
|
-
const run = this.activeRuns.get(runId);
|
|
168
|
-
let seqEvent = event;
|
|
169
|
-
if (run) {
|
|
170
|
-
run.lastSeq++;
|
|
171
|
-
seqEvent = { ...event, seq: run.lastSeq, runId };
|
|
172
|
-
run.eventBuffer.push(seqEvent);
|
|
173
|
-
}
|
|
174
|
-
if (platform?.eventBus) {
|
|
175
|
-
const topic = `${EVENT_TOPIC_PREFIX}${runId}`;
|
|
176
|
-
platform.eventBus.publish(topic, seqEvent).catch(() => {
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
if (run) {
|
|
180
|
-
for (const listener of run.listeners) {
|
|
181
|
-
try {
|
|
182
|
-
listener(seqEvent);
|
|
183
|
-
} catch {
|
|
184
|
-
}
|
|
185
|
-
}
|
|
121
|
+
notifySessionListeners(sessionId, payload) {
|
|
122
|
+
const listeners = this.sessionListeners.get(sessionId);
|
|
123
|
+
if (!listeners) {
|
|
124
|
+
return;
|
|
186
125
|
}
|
|
187
|
-
const
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
for (const listener of sListeners) {
|
|
192
|
-
try {
|
|
193
|
-
listener(seqEvent);
|
|
194
|
-
} catch {
|
|
195
|
-
}
|
|
196
|
-
}
|
|
126
|
+
for (const listener of listeners) {
|
|
127
|
+
try {
|
|
128
|
+
listener(payload);
|
|
129
|
+
} catch {
|
|
197
130
|
}
|
|
198
131
|
}
|
|
199
|
-
return seqEvent;
|
|
200
132
|
}
|
|
201
133
|
/**
|
|
202
|
-
* Add a session-level listener — receives
|
|
134
|
+
* Add a session-level listener — receives updates from ALL runs in this session.
|
|
203
135
|
*/
|
|
204
136
|
addSessionListener(sessionId, callback) {
|
|
205
137
|
if (!this.sessionListeners.has(sessionId)) {
|
|
@@ -219,21 +151,6 @@ var RunManagerImpl = class {
|
|
|
219
151
|
}
|
|
220
152
|
}
|
|
221
153
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Get replay buffer for a run (all events emitted since start).
|
|
224
|
-
* Used by WS handler to send missed events on late connection.
|
|
225
|
-
* Optionally filter by afterSeq to only get events the client hasn't seen.
|
|
226
|
-
*/
|
|
227
|
-
getEventBuffer(runId, afterSeq) {
|
|
228
|
-
const run = this.activeRuns.get(runId);
|
|
229
|
-
if (!run) {
|
|
230
|
-
return [];
|
|
231
|
-
}
|
|
232
|
-
if (afterSeq != null) {
|
|
233
|
-
return run.eventBuffer.filter((e) => e.seq != null && e.seq > afterSeq);
|
|
234
|
-
}
|
|
235
|
-
return [...run.eventBuffer];
|
|
236
|
-
}
|
|
237
154
|
/**
|
|
238
155
|
* List all active runs
|
|
239
156
|
*/
|
|
@@ -313,8 +230,7 @@ var generate_spec_handler_default = defineHandler({
|
|
|
313
230
|
runId,
|
|
314
231
|
`Generate spec for plan ${plan.id}`,
|
|
315
232
|
void 0,
|
|
316
|
-
sessionManager
|
|
317
|
-
sessionId
|
|
233
|
+
sessionManager
|
|
318
234
|
);
|
|
319
235
|
await RunManager.updateStatus(runId, "running");
|
|
320
236
|
const specHandler = new SpecModeHandler();
|
|
@@ -334,13 +250,15 @@ var generate_spec_handler_default = defineHandler({
|
|
|
334
250
|
const specPromise = (async () => {
|
|
335
251
|
const configOnEvent = (event) => {
|
|
336
252
|
traceWriter.trace(event);
|
|
337
|
-
const seqEvent = RunManager.broadcast(runId, event);
|
|
338
253
|
void sessionManager.addEvent(sessionId, {
|
|
339
|
-
...
|
|
254
|
+
...event,
|
|
340
255
|
sessionId,
|
|
341
256
|
runId
|
|
257
|
+
}).then((deltas) => {
|
|
258
|
+
RunManager.broadcastSessionDeltas(sessionId, deltas);
|
|
342
259
|
});
|
|
343
260
|
};
|
|
261
|
+
const specStartTime = Date.now();
|
|
344
262
|
try {
|
|
345
263
|
const result = await specHandler.execute(plan, {
|
|
346
264
|
workingDir,
|
|
@@ -356,6 +274,14 @@ var generate_spec_handler_default = defineHandler({
|
|
|
356
274
|
summary: result.summary,
|
|
357
275
|
error: result.success ? void 0 : result.summary
|
|
358
276
|
});
|
|
277
|
+
const seq = await sessionManager.getCurrentSessionSeq(sessionId);
|
|
278
|
+
RunManager.broadcastRunCompleted(sessionId, {
|
|
279
|
+
runId,
|
|
280
|
+
success: result.success,
|
|
281
|
+
summary: result.summary,
|
|
282
|
+
durationMs: Date.now() - specStartTime,
|
|
283
|
+
seq
|
|
284
|
+
});
|
|
359
285
|
return result;
|
|
360
286
|
} catch (error) {
|
|
361
287
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -364,6 +290,14 @@ var generate_spec_handler_default = defineHandler({
|
|
|
364
290
|
summary: message,
|
|
365
291
|
error: message
|
|
366
292
|
});
|
|
293
|
+
const seq = await sessionManager.getCurrentSessionSeq(sessionId);
|
|
294
|
+
RunManager.broadcastRunCompleted(sessionId, {
|
|
295
|
+
runId,
|
|
296
|
+
success: false,
|
|
297
|
+
summary: message,
|
|
298
|
+
durationMs: Date.now() - specStartTime,
|
|
299
|
+
seq
|
|
300
|
+
});
|
|
367
301
|
throw error;
|
|
368
302
|
} finally {
|
|
369
303
|
const detailedTrace = traceWriter.getEntries();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/rest/run-manager.ts","../../../src/rest/handlers/generate-spec-handler.ts"],"names":["run","fs"],"mappings":"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","file":"generate-spec-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 /sessions/:sessionId/plan/spec\n * Generate a detailed specification from an approved session plan.\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager, SpecModeHandler, createSessionMemoryBridge } from '@kb-labs/agent-core';\nimport { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';\nimport { IncrementalTraceWriter } from '@kb-labs/agent-tracing';\nimport { createToolRegistry } from '@kb-labs/agent-tools';\nimport type {\n AgentEvent,\n DetailedTraceEntry,\n GenerateSpecRequest,\n GenerateSpecResponse,\n KernelState,\n TaskPlan,\n} from '@kb-labs/agent-contracts';\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { RunManager } from '../run-manager.js';\n\ninterface SpecRouteParams {\n sessionId?: string;\n}\n\nasync function loadPlan(planPath: string): Promise<TaskPlan> {\n const content = await fs.readFile(planPath, 'utf-8');\n return JSON.parse(content) as TaskPlan;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<GenerateSpecRequest, unknown, SpecRouteParams>\n ): Promise<GenerateSpecResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n const body = (input.body ?? {}) as GenerateSpecRequest;\n\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const baseManager = new SessionManager(ctx.cwd);\n const session = await baseManager.loadSession(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const workingDir = session.workingDir || ctx.cwd;\n const sessionManager = new SessionManager(workingDir);\n const planPath = sessionManager.getSessionPlanPath(sessionId);\n\n let plan: TaskPlan;\n try {\n plan = await loadPlan(planPath);\n } catch {\n throw new Error(`Plan not found for session ${sessionId}`);\n }\n\n if (plan.status !== 'approved') {\n throw new Error(`Plan must be approved before spec generation (current status: ${plan.status})`);\n }\n\n // Run spec generation asynchronously via RunManager\n const runId = `run-spec-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n const startedAt = new Date().toISOString();\n const traceDir = path.join(workingDir, '.kb', 'traces', 'incremental');\n const traceWriter = new IncrementalTraceWriter(runId, {}, traceDir);\n await RunManager.register(\n runId,\n `Generate spec for plan ${plan.id}`,\n undefined,\n sessionManager,\n sessionId,\n );\n await RunManager.updateStatus(runId, 'running');\n\n // Start spec generation in background\n const specHandler = new SpecModeHandler();\n const sessionMemory = createSessionMemoryBridge(workingDir, sessionId);\n const responseRequirementsSelector = createDefaultResponseRequirementsSelector();\n const toolRegistry = createToolRegistry({\n workingDir,\n currentTask: `Generate spec for plan ${plan.id}`,\n sessionId,\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 ?? `Generate spec for plan ${plan.id}`,\n }),\n });\n\n const specPromise = (async () => {\n const configOnEvent = (event: AgentEvent) => {\n traceWriter.trace(event as unknown as DetailedTraceEntry);\n const seqEvent = RunManager.broadcast(runId, event);\n void sessionManager.addEvent(sessionId, {\n ...seqEvent,\n sessionId,\n runId,\n } as unknown as AgentEvent);\n };\n\n try {\n const result = await specHandler.execute(plan, {\n workingDir,\n sessionId,\n agentId: `spec-${sessionId}`,\n maxIterations: plan.phases.length * 8,\n tier: body.tier || 'medium',\n temperature: 0.1,\n onEvent: configOnEvent,\n }, toolRegistry);\n await RunManager.updateStatus(runId, result.success ? 'completed' : 'failed', {\n completedAt: new Date().toISOString(),\n summary: result.summary,\n error: result.success ? undefined : result.summary,\n });\n return result;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await RunManager.updateStatus(runId, 'failed', {\n completedAt: new Date().toISOString(),\n summary: message,\n error: message,\n });\n throw error;\n } finally {\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(sessionId, runId, detailedTrace);\n }\n }\n })();\n\n void specPromise;\n\n return {\n sessionId,\n planId: plan.id,\n specId: `spec-${runId}`,\n runId,\n eventsPath: `/ws/plugins/agents/session/${sessionId}`,\n status: 'generating',\n startedAt,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/run-manager.ts","../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/generate-spec-handler.ts"],"names":["fs"],"mappings":"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","file":"generate-spec-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 /sessions/:sessionId/plan/spec\n * Generate a detailed specification from an approved session plan.\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager, SpecModeHandler, createSessionMemoryBridge } from '@kb-labs/agent-core';\nimport { createDefaultResponseRequirementsSelector } from '@kb-labs/agent-runtime';\nimport { IncrementalTraceWriter } from '@kb-labs/agent-tracing';\nimport { createToolRegistry } from '@kb-labs/agent-tools';\nimport type {\n AgentEvent,\n DetailedTraceEntry,\n GenerateSpecRequest,\n GenerateSpecResponse,\n KernelState,\n TaskPlan,\n} from '@kb-labs/agent-contracts';\nimport { promises as fs } from 'node:fs';\nimport path from 'node:path';\nimport { RunManager } from '../run-manager.js';\n\ninterface SpecRouteParams {\n sessionId?: string;\n}\n\nasync function loadPlan(planPath: string): Promise<TaskPlan> {\n const content = await fs.readFile(planPath, 'utf-8');\n return JSON.parse(content) as TaskPlan;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<GenerateSpecRequest, unknown, SpecRouteParams>\n ): Promise<GenerateSpecResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n const body = (input.body ?? {}) as GenerateSpecRequest;\n\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const baseManager = new SessionManager(ctx.cwd);\n const session = await baseManager.loadSession(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const workingDir = session.workingDir || ctx.cwd;\n const sessionManager = new SessionManager(workingDir);\n const planPath = sessionManager.getSessionPlanPath(sessionId);\n\n let plan: TaskPlan;\n try {\n plan = await loadPlan(planPath);\n } catch {\n throw new Error(`Plan not found for session ${sessionId}`);\n }\n\n if (plan.status !== 'approved') {\n throw new Error(`Plan must be approved before spec generation (current status: ${plan.status})`);\n }\n\n // Run spec generation asynchronously via RunManager\n const runId = `run-spec-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;\n const startedAt = new Date().toISOString();\n const traceDir = path.join(workingDir, '.kb', 'traces', 'incremental');\n const traceWriter = new IncrementalTraceWriter(runId, {}, traceDir);\n await RunManager.register(\n runId,\n `Generate spec for plan ${plan.id}`,\n undefined,\n sessionManager,\n );\n await RunManager.updateStatus(runId, 'running');\n\n // Start spec generation in background\n const specHandler = new SpecModeHandler();\n const sessionMemory = createSessionMemoryBridge(workingDir, sessionId);\n const responseRequirementsSelector = createDefaultResponseRequirementsSelector();\n const toolRegistry = createToolRegistry({\n workingDir,\n currentTask: `Generate spec for plan ${plan.id}`,\n sessionId,\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 ?? `Generate spec for plan ${plan.id}`,\n }),\n });\n\n const specPromise = (async () => {\n const configOnEvent = (event: AgentEvent) => {\n traceWriter.trace(event as unknown as DetailedTraceEntry);\n // Persist first, broadcast only once confirmed — see run-handler.ts's onEvent for why.\n void sessionManager.addEvent(sessionId, {\n ...event,\n sessionId,\n runId,\n } as unknown as AgentEvent).then((deltas) => {\n RunManager.broadcastSessionDeltas(sessionId, deltas);\n });\n };\n\n const specStartTime = Date.now();\n try {\n const result = await specHandler.execute(plan, {\n workingDir,\n sessionId,\n agentId: `spec-${sessionId}`,\n maxIterations: plan.phases.length * 8,\n tier: body.tier || 'medium',\n temperature: 0.1,\n onEvent: configOnEvent,\n }, toolRegistry);\n await RunManager.updateStatus(runId, result.success ? 'completed' : 'failed', {\n completedAt: new Date().toISOString(),\n summary: result.summary,\n error: result.success ? undefined : result.summary,\n });\n const seq = await sessionManager.getCurrentSessionSeq(sessionId);\n RunManager.broadcastRunCompleted(sessionId, {\n runId,\n success: result.success,\n summary: result.summary,\n durationMs: Date.now() - specStartTime,\n seq,\n });\n return result;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n await RunManager.updateStatus(runId, 'failed', {\n completedAt: new Date().toISOString(),\n summary: message,\n error: message,\n });\n const seq = await sessionManager.getCurrentSessionSeq(sessionId);\n RunManager.broadcastRunCompleted(sessionId, {\n runId,\n success: false,\n summary: message,\n durationMs: Date.now() - specStartTime,\n seq,\n });\n throw error;\n } finally {\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(sessionId, runId, detailedTrace);\n }\n }\n })();\n\n void specPromise;\n\n return {\n sessionId,\n planId: plan.id,\n specId: `spec-${runId}`,\n runId,\n eventsPath: `/ws/plugins/agents/session/${sessionId}`,\n status: 'generating',\n startedAt,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/get-file-diff-handler.ts"],"names":[],"mappings":";;;;;AAqBA,IAAO,gCAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAgD;AAClF,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,MAAA,MAAM,WAAW,MAAA,EAAQ,QAAA;AACzB,MAAA,IAAI,CAAC,SAAA,EAAW;AAAC,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAAE;AAC3D,MAAA,IAAI,CAAC,QAAA,EAAU;AAAC,QAAA,MAAM,IAAI,MAAM,uBAAuB,CAAA;AAAA,MAAE;AAEzD,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAC1D,MAAA,MAAM,UAAA,GAAa,OAAA,EAAS,UAAA,IAAc,GAAA,CAAI,GAAA;AAE9C,MAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,CAAY,UAAU,CAAA;AACxC,MAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,GAAA,CAAI,WAAW,QAAQ,CAAA;AAClD,MAAA,IAAI,CAAC,MAAA,EAAQ;AAAC,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,QAAQ,CAAA,YAAA,EAAe,SAAS,CAAA,CAAE,CAAA;AAAA,MAAE;AAEvF,MAAA,MAAM,IAAA,GAAO,mBAAA,CAAoB,MAAA,CAAO,QAAA,EAAU,MAAA,CAAO,MAAA,EAAQ,OAAA,EAAS,MAAA,CAAO,KAAA,CAAM,OAAA,EAAS,MAAA,CAAO,SAAS,CAAA;AAChH,MAAA,MAAM,EAAE,KAAA,EAAO,OAAA,EAAQ,GAAI,eAAe,IAAI,CAAA;AAE9C,MAAA,OAAO;AAAA,QACL,UAAU,MAAA,CAAO,EAAA;AAAA,QACjB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,IAAA;AAAA,QACA,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,EAAE,IAAA,EAAM,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,MAAA,CAAO,IAAA,EAAK,GAAI,KAAA,CAAA;AAAA,QACjF,KAAA,EAAO,EAAE,IAAA,EAAM,MAAA,CAAO,MAAM,IAAA,EAAM,IAAA,EAAM,MAAA,CAAO,KAAA,CAAM,IAAA,EAAK;AAAA,QAC1D,UAAA,EAAY,KAAA;AAAA,QACZ,YAAA,EAAc,OAAA;AAAA,QACd,KAAA,EAAO,CAAC,MAAA,CAAO,MAAA;AAAA,QACf,WAAW,MAAA,CAAO;AAAA,OACpB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"get-file-diff-handler.js","sourcesContent":["/**\n * GET /sessions/:sessionId/changes/:changeId/diff — Unified diff for a file change snapshot.\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport { ChangeStore, generateUnifiedDiff, countDiffLines } from '@kb-labs/agent-history';\n\ninterface GetFileDiffResponse {\n changeId: string;\n filePath: string;\n operation: 'write' | 'patch' | 'delete';\n diff: string;\n before?: { hash: string; size: number };\n after: { hash: string; size: number };\n linesAdded: number;\n linesRemoved: number;\n isNew: boolean;\n timestamp: string;\n}\n\nexport default defineHandler({\n async execute(ctx: PluginContextV3, input: RestInput): Promise<GetFileDiffResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n const changeId = params?.changeId;\n if (!sessionId) {throw new Error('Session ID is required');}\n if (!changeId) {throw new Error('Change ID is required');}\n\n const sessionManager = new SessionManager(ctx.cwd);\n const session = await sessionManager.loadSession(sessionId);\n const workingDir = session?.workingDir || ctx.cwd;\n\n const store = new ChangeStore(workingDir);\n const change = await store.get(sessionId, changeId);\n if (!change) {throw new Error(`Change not found: ${changeId} in session ${sessionId}`);}\n\n const diff = generateUnifiedDiff(change.filePath, change.before?.content, change.after.content, change.operation);\n const { added, removed } = countDiffLines(diff);\n\n return {\n changeId: change.id,\n filePath: change.filePath,\n operation: change.operation,\n diff,\n before: change.before ? { hash: change.before.hash, size: change.before.size } : undefined,\n after: { hash: change.after.hash, size: change.after.size },\n linesAdded: added,\n linesRemoved: removed,\n isNew: !change.before,\n timestamp: change.timestamp,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/get-session-handler.ts"],"names":[],"mappings":";;;;AAYA,IAAO,8BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC6B;AAC7B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAE1B,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,cAAA,CAAe,SAAS,CAAA;AAE7D,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,MACnD;AAEA,MAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,IACnB,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"get-session-handler.js","sourcesContent":["/**\n * GET /sessions/:sessionId - Get session details\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport type { GetSessionResponse } from '@kb-labs/agent-contracts';\n\ninterface GetSessionRequest {\n sessionId?: string;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<GetSessionRequest>\n ): Promise<GetSessionResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const sessionManager = new SessionManager(ctx.cwd);\n const session = await sessionManager.getSessionInfo(sessionId);\n\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n return { session };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/get-session-plan-handler.ts"],"names":["fs"],"mappings":";;;;;AAcA,eAAe,SAAS,QAAA,EAA4C;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAMA,QAAA,CAAG,QAAA,CAAS,UAAU,OAAO,CAAA;AACnD,IAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,eAAe,WAAW,QAAA,EAAoC;AAC5D,EAAA,IAAI;AACF,IAAA,MAAMA,QAAA,CAAG,OAAO,QAAQ,CAAA;AACxB,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,IAAO,mCAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EACiC;AACjC,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAC1D,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,MACnD;AAEA,MAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,GAAA,CAAI,GAAA;AAC7C,MAAA,MAAM,OAAA,GAAU,IAAI,cAAA,CAAe,UAAU,CAAA;AAC7C,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,kBAAA,CAAmB,SAAS,CAAA;AACrD,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,QAAQ,CAAA;AAEpC,MAAA,IAAI,CAAC,IAAA,EAAM;AACT,QAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAK;AAAA,MACjC;AAEA,MAAA,MAAM,eAAA,GAAkB,IAAI,mBAAA,CAAoB,UAAU,CAAA;AAC1D,MAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,WAAA,CAAY,IAAI,CAAA;AAEtD,MAAA,OAAO;AAAA,QACL,SAAA;AAAA,QACA,IAAA;AAAA,QACA,QAAA,EAAU,MAAM,UAAA,CAAW,aAAa,IAAI,aAAA,GAAgB,KAAA;AAAA,OAC9D;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"get-session-plan-handler.js","sourcesContent":["/**\n * GET /sessions/:sessionId/plan\n * Get current session plan (JSON + canonical markdown path if present).\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager, PlanDocumentService } from '@kb-labs/agent-core';\nimport type { GetSessionPlanResponse, TaskPlan } from '@kb-labs/agent-contracts';\nimport { promises as fs } from 'node:fs';\n\ninterface GetSessionPlanRequest {\n sessionId?: string;\n}\n\nasync function loadPlan(planPath: string): Promise<TaskPlan | null> {\n try {\n const content = await fs.readFile(planPath, 'utf-8');\n return JSON.parse(content) as TaskPlan;\n } catch {\n return null;\n }\n}\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<GetSessionPlanRequest>\n ): Promise<GetSessionPlanResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const sessionManager = new SessionManager(ctx.cwd);\n const session = await sessionManager.loadSession(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const workingDir = session.workingDir || ctx.cwd;\n const manager = new SessionManager(workingDir);\n const planPath = manager.getSessionPlanPath(sessionId);\n const plan = await loadPlan(planPath);\n\n if (!plan) {\n return { sessionId, plan: null };\n }\n\n const documentService = new PlanDocumentService(workingDir);\n const canonicalPath = documentService.getPlanPath(plan);\n\n return {\n sessionId,\n plan,\n planPath: await pathExists(canonicalPath) ? canonicalPath : undefined,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/get-session-turns-handler.ts"],"names":[],"mappings":";;;;AAoBA,IAAO,oCAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EACkC;AAClC,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,MAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AAEpB,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAEjD,MAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,yBAAA,EAA4B,IAAI,GAAG,CAAA,aAAA,EAAgB,SAAS,CAAA,CAAE,CAAA;AACvF,MAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,+BAAA,EAAkC,eAAe,YAAA,CAAa,SAAS,CAAC,CAAA,CAAE,CAAA;AAGnG,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAC1D,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,MACnD;AAGA,MAAA,IAAI,KAAA,GAAQ,MAAM,cAAA,CAAe,QAAA,CAAS,SAAS,CAAA;AAEnD,MAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,CAAA,0BAAA,EAA6B,KAAA,CAAM,MAAM,CAAA,MAAA,CAAQ,CAAA;AAG1E,MAAA,MAAM,QAAQ,KAAA,CAAM,MAAA;AACpB,MAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,QAAA,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA;AAAA,MAClC;AACA,MAAA,IAAI,OAAO,KAAA,EAAO;AAChB,QAAA,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AAAA,MACpC;AAEA,MAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AAAA,IACxB,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"get-session-turns-handler.js","sourcesContent":["/**\n * GET /sessions/:sessionId/turns - Get session turns (turn-based UI)\n * NEW (Phase 2): Returns ready-made Turn snapshots instead of raw events\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport type { Turn } from '@kb-labs/agent-contracts';\n\ninterface GetSessionTurnsRequest {\n sessionId?: string;\n limit?: number;\n offset?: number;\n}\n\ninterface GetSessionTurnsResponse {\n turns: Turn[];\n total: number;\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<GetSessionTurnsRequest>\n ): Promise<GetSessionTurnsResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n const query = input.query as Partial<GetSessionTurnsRequest> | undefined;\n\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const sessionManager = new SessionManager(ctx.cwd);\n\n ctx.platform.logger.info(`[get-session-turns] cwd: ${ctx.cwd}, sessionId: ${sessionId}`);\n ctx.platform.logger.info(`[get-session-turns] turnsPath: ${sessionManager.getTurnsPath(sessionId)}`);\n\n // Verify session exists\n const session = await sessionManager.loadSession(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n // Get turns (with lazy migration from events if needed)\n let turns = await sessionManager.getTurns(sessionId);\n\n ctx.platform.logger.info(`[get-session-turns] Found ${turns.length} turns`);\n\n // Apply pagination\n const total = turns.length;\n if (query?.offset) {\n turns = turns.slice(query.offset);\n }\n if (query?.limit) {\n turns = turns.slice(0, query.limit);\n }\n\n return { turns, total };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/get-spec-handler.ts"],"names":["fs"],"mappings":";;;;;AAcA,eAAe,SAAS,QAAA,EAA4C;AAClE,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,MAAMA,QAAA,CAAG,QAAA,CAAS,UAAU,OAAO,CAAA;AACnD,IAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,EAC3B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,IAAO,2BAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC0B;AAC1B,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAM,WAAA,GAAc,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAC9C,MAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,WAAA,CAAY,SAAS,CAAA;AACvD,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,MACnD;AAEA,MAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,GAAA,CAAI,GAAA;AAC7C,MAAA,MAAM,OAAA,GAAU,IAAI,cAAA,CAAe,UAAU,CAAA;AAC7C,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,kBAAA,CAAmB,SAAS,CAAA;AACrD,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,QAAQ,CAAA;AAEpC,MAAA,OAAO;AAAA,QACL,SAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"get-spec-handler.js","sourcesContent":["/**\n * GET /sessions/:sessionId/spec\n * Get current session spec (JSON + markdown path if present).\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport type { GetSpecResponse, TaskSpec } from '@kb-labs/agent-contracts';\nimport { promises as fs } from 'node:fs';\n\ninterface GetSpecRouteParams {\n sessionId?: string;\n}\n\nasync function loadSpec(specPath: string): Promise<TaskSpec | null> {\n try {\n const content = await fs.readFile(specPath, 'utf-8');\n return JSON.parse(content) as TaskSpec;\n } catch {\n return null;\n }\n}\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<unknown, unknown, GetSpecRouteParams>\n ): Promise<GetSpecResponse> {\n try {\n const params = input.params as Record<string, string> | undefined;\n const sessionId = params?.sessionId;\n if (!sessionId) {\n throw new Error('Session ID is required');\n }\n\n const baseManager = new SessionManager(ctx.cwd);\n const session = await baseManager.loadSession(sessionId);\n if (!session) {\n throw new Error(`Session not found: ${sessionId}`);\n }\n\n const workingDir = session.workingDir || ctx.cwd;\n const manager = new SessionManager(workingDir);\n const specPath = manager.getSessionSpecPath(sessionId);\n const spec = await loadSpec(specPath);\n\n return {\n sessionId,\n spec,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/list-file-changes-handler.ts"],"names":[],"mappings":";;;;;AAiBA,IAAO,oCAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CAAQ,GAAA,EAAsB,KAAA,EAAoD;AACtF,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,MAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,MAAA,IAAI,CAAC,SAAA,EAAW;AAAC,QAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,MAAE;AAE3D,MAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,MAAA,MAAM,QAAQ,KAAA,EAAO,KAAA;AAErB,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,MAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAC1D,MAAA,IAAI,CAAC,OAAA,EAAS;AAAC,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,MAAE;AAElE,MAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,GAAA,CAAI,GAAA;AAC7C,MAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,CAAY,UAAU,CAAA;AAExC,MAAA,MAAM,OAAA,GAAU,KAAA,GACZ,MAAM,KAAA,CAAM,OAAA,CAAQ,SAAA,EAAW,KAAK,CAAA,GACpC,MAAM,KAAA,CAAM,WAAA,CAAY,SAAS,CAAA;AAErC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA;AAAA,QAC9B,OAAO,OAAA,CAAQ,MAAA;AAAA,QACf,SAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"list-file-changes-handler.js","sourcesContent":["/**\n * GET /sessions/:sessionId/changes — List file changes for a session.\n * Optional query: ?runId= to scope to a specific agent run.\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport { ChangeStore, toSummary } from '@kb-labs/agent-history';\nimport type { FileChangeSummary } from '@kb-labs/agent-history';\n\ninterface ListFileChangesResponse {\n changes: FileChangeSummary[];\n total: number;\n sessionId: string;\n runId?: string;\n}\n\nexport default defineHandler({\n async execute(ctx: PluginContextV3, input: RestInput): Promise<ListFileChangesResponse> {\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 query = input.query as Record<string, string> | undefined;\n const runId = query?.runId;\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 const changes = runId\n ? await store.listRun(sessionId, runId)\n : await store.listSession(sessionId);\n\n return {\n changes: changes.map(toSummary),\n total: changes.length,\n sessionId,\n runId,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/src/rest/handlers/list-sessions-handler.ts"],"names":[],"mappings":";;;;AAQA,IAAO,gCAAQ,aAAA,CAAc;AAAA,EAC3B,MAAM,OAAA,CACJ,GAAA,EACA,KAAA,EAC+B;AAC/B,IAAA,IAAI;AACF,MAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,MAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAGjD,MAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,YAAA,CAAa;AAAA,QAC/C,QAAQ,KAAA,EAAO,MAAA;AAAA,QACf,KAAA,EAAO,OAAO,KAAA,IAAS,EAAA;AAAA,QACvB,MAAA,EAAQ,OAAO,MAAA,IAAU;AAAA,OAC1B,CAAA;AAED,MAAA,OAAO;AAAA,QACL,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,OAAO,MAAA,CAAO;AAAA,OAChB;AAAA,IACF,SAAS,GAAA,EAAK;AACZ,MAAA,cAAA,CAAe,GAAG,CAAA;AAAA,IACpB;AAAA,EACF;AACF,CAAC","file":"list-sessions-handler.js","sourcesContent":["/**\n * GET /sessions - List all sessions\n */\n\nimport { defineHandler, rethrowForRest, type RestInput, type PluginContextV3 } from '@kb-labs/sdk';\nimport { SessionManager } from '@kb-labs/agent-core';\nimport type { ListSessionsRequest, ListSessionsResponse } from '@kb-labs/agent-contracts';\n\nexport default defineHandler({\n async execute(\n ctx: PluginContextV3,\n input: RestInput<ListSessionsRequest>\n ): Promise<ListSessionsResponse> {\n try {\n const query = input.query as ListSessionsRequest | undefined;\n const sessionManager = new SessionManager(ctx.cwd);\n\n // List all sessions (optionally filtered by status)\n const result = await sessionManager.listSessions({\n status: query?.status,\n limit: query?.limit ?? 50,\n offset: query?.offset ?? 0,\n });\n\n return {\n sessions: result.sessions,\n total: result.total,\n };\n } catch (err) {\n rethrowForRest(err);\n }\n },\n});\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["
|
|
1
|
+
{"version":3,"sources":["../../../../home/runner/work/kb-labs/kb-labs/plugins/agents/entry/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"]}
|