@kb-labs/agent-cli 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +56 -0
- package/dist/cli/commands/diff.d.ts +17 -0
- package/dist/cli/commands/diff.js +182 -0
- package/dist/cli/commands/diff.js.map +1 -0
- package/dist/cli/commands/history.d.ts +16 -0
- package/dist/cli/commands/history.js +216 -0
- package/dist/cli/commands/history.js.map +1 -0
- package/dist/cli/commands/quality-report.d.ts +21 -0
- package/dist/cli/commands/quality-report.js +457 -0
- package/dist/cli/commands/quality-report.js.map +1 -0
- package/dist/cli/commands/rollback.d.ts +27 -0
- package/dist/cli/commands/rollback.js +109 -0
- package/dist/cli/commands/rollback.js.map +1 -0
- package/dist/cli/commands/run.d.ts +42 -0
- package/dist/cli/commands/run.js +923 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/trace-context.d.ts +22 -0
- package/dist/cli/commands/trace-context.js +131 -0
- package/dist/cli/commands/trace-context.js.map +1 -0
- package/dist/cli/commands/trace-diagnose.d.ts +20 -0
- package/dist/cli/commands/trace-diagnose.js +434 -0
- package/dist/cli/commands/trace-diagnose.js.map +1 -0
- package/dist/cli/commands/trace-event-normalizer.d.ts +13 -0
- package/dist/cli/commands/trace-event-normalizer.js +39 -0
- package/dist/cli/commands/trace-event-normalizer.js.map +1 -0
- package/dist/cli/commands/trace-filter.d.ts +19 -0
- package/dist/cli/commands/trace-filter.js +153 -0
- package/dist/cli/commands/trace-filter.js.map +1 -0
- package/dist/cli/commands/trace-iteration.d.ts +18 -0
- package/dist/cli/commands/trace-iteration.js +192 -0
- package/dist/cli/commands/trace-iteration.js.map +1 -0
- package/dist/cli/commands/trace-stats.d.ts +17 -0
- package/dist/cli/commands/trace-stats.js +247 -0
- package/dist/cli/commands/trace-stats.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +473 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +184 -0
- package/dist/manifest.js +473 -0
- package/dist/manifest.js.map +1 -0
- package/dist/rest/handlers/approve-handler.d.ts +15 -0
- package/dist/rest/handlers/approve-handler.js +60 -0
- package/dist/rest/handlers/approve-handler.js.map +1 -0
- package/dist/rest/handlers/approve-session-plan-handler.d.ts +10 -0
- package/dist/rest/handlers/approve-session-plan-handler.js +52 -0
- package/dist/rest/handlers/approve-session-plan-handler.js.map +1 -0
- package/dist/rest/handlers/correct-handler.d.ts +7 -0
- package/dist/rest/handlers/correct-handler.js +326 -0
- package/dist/rest/handlers/correct-handler.js.map +1 -0
- package/dist/rest/handlers/create-session-handler.d.ts +7 -0
- package/dist/rest/handlers/create-session-handler.js +25 -0
- package/dist/rest/handlers/create-session-handler.js.map +1 -0
- package/dist/rest/handlers/execute-session-plan-handler.d.ts +10 -0
- package/dist/rest/handlers/execute-session-plan-handler.js +635 -0
- package/dist/rest/handlers/execute-session-plan-handler.js.map +1 -0
- package/dist/rest/handlers/generate-spec-handler.d.ts +10 -0
- package/dist/rest/handlers/generate-spec-handler.js +389 -0
- package/dist/rest/handlers/generate-spec-handler.js.map +1 -0
- package/dist/rest/handlers/get-file-diff-handler.d.ts +24 -0
- package/dist/rest/handlers/get-file-diff-handler.js +44 -0
- package/dist/rest/handlers/get-file-diff-handler.js.map +1 -0
- package/dist/rest/handlers/get-session-handler.d.ts +10 -0
- package/dist/rest/handlers/get-session-handler.js +23 -0
- package/dist/rest/handlers/get-session-handler.js.map +1 -0
- package/dist/rest/handlers/get-session-plan-handler.d.ts +10 -0
- package/dist/rest/handlers/get-session-plan-handler.js +53 -0
- package/dist/rest/handlers/get-session-plan-handler.js.map +1 -0
- package/dist/rest/handlers/get-session-turns-handler.d.ts +16 -0
- package/dist/rest/handlers/get-session-turns-handler.js +35 -0
- package/dist/rest/handlers/get-session-turns-handler.js.map +1 -0
- package/dist/rest/handlers/get-spec-handler.d.ts +10 -0
- package/dist/rest/handlers/get-spec-handler.js +39 -0
- package/dist/rest/handlers/get-spec-handler.js.map +1 -0
- package/dist/rest/handlers/list-file-changes-handler.d.ts +13 -0
- package/dist/rest/handlers/list-file-changes-handler.js +34 -0
- package/dist/rest/handlers/list-file-changes-handler.js.map +1 -0
- package/dist/rest/handlers/list-sessions-handler.d.ts +7 -0
- package/dist/rest/handlers/list-sessions-handler.js +23 -0
- package/dist/rest/handlers/list-sessions-handler.js.map +1 -0
- package/dist/rest/handlers/rollback-handler.d.ts +22 -0
- package/dist/rest/handlers/rollback-handler.js +91 -0
- package/dist/rest/handlers/rollback-handler.js.map +1 -0
- package/dist/rest/handlers/run-handler.d.ts +7 -0
- package/dist/rest/handlers/run-handler.js +516 -0
- package/dist/rest/handlers/run-handler.js.map +1 -0
- package/dist/rest/handlers/sessions-handler.d.ts +18 -0
- package/dist/rest/handlers/sessions-handler.js +56 -0
- package/dist/rest/handlers/sessions-handler.js.map +1 -0
- package/dist/rest/handlers/status-handler.d.ts +7 -0
- package/dist/rest/handlers/status-handler.js +313 -0
- package/dist/rest/handlers/status-handler.js.map +1 -0
- package/dist/rest/handlers/stop-handler.d.ts +7 -0
- package/dist/rest/handlers/stop-handler.js +317 -0
- package/dist/rest/handlers/stop-handler.js.map +1 -0
- package/dist/widgets/220.js +446 -0
- package/dist/widgets/220.js.map +1 -0
- package/dist/widgets/331.js +2 -0
- package/dist/widgets/331.js.map +1 -0
- package/dist/widgets/403.js +2 -0
- package/dist/widgets/403.js.map +1 -0
- package/dist/widgets/406.js +35 -0
- package/dist/widgets/406.js.map +1 -0
- package/dist/widgets/455.js +2 -0
- package/dist/widgets/455.js.map +1 -0
- package/dist/widgets/482.js +2 -0
- package/dist/widgets/482.js.map +1 -0
- package/dist/widgets/485.js +2 -0
- package/dist/widgets/485.js.map +1 -0
- package/dist/widgets/527.js +2 -0
- package/dist/widgets/527.js.map +1 -0
- package/dist/widgets/628.js +2 -0
- package/dist/widgets/628.js.map +1 -0
- package/dist/widgets/694.js +2 -0
- package/dist/widgets/694.js.map +1 -0
- package/dist/widgets/712.js +2 -0
- package/dist/widgets/712.js.map +1 -0
- package/dist/widgets/866.js +2 -0
- package/dist/widgets/866.js.map +1 -0
- package/dist/widgets/915.js +39 -0
- package/dist/widgets/915.js.map +1 -0
- package/dist/widgets/957.js +10 -0
- package/dist/widgets/957.js.map +1 -0
- package/dist/widgets/983.js +2 -0
- package/dist/widgets/983.js.map +1 -0
- package/dist/widgets/@mf-types.d.ts +3 -0
- package/dist/widgets/@mf-types.zip +0 -0
- package/dist/widgets/__federation_expose_AgentsPage.js +2 -0
- package/dist/widgets/__federation_expose_AgentsPage.js.map +1 -0
- package/dist/widgets/mf-manifest.json +260 -0
- package/dist/widgets/mf-stats.json +305 -0
- package/dist/widgets/remoteEntry.js +7 -0
- package/dist/widgets/remoteEntry.js.map +1 -0
- package/dist/ws/session-stream-handler.d.ts +8 -0
- package/dist/ws/session-stream-handler.js +409 -0
- package/dist/ws/session-stream-handler.js.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
import { GetSessionResponse } from '@kb-labs/agent-contracts';
|
|
4
|
+
|
|
5
|
+
interface GetSessionRequest {
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<GetSessionRequest, unknown, unknown>, GetSessionResponse>;
|
|
9
|
+
|
|
10
|
+
export { _default as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineHandler } from '@kb-labs/sdk';
|
|
2
|
+
import { SessionManager } from '@kb-labs/agent-core';
|
|
3
|
+
|
|
4
|
+
// src/rest/handlers/get-session-handler.ts
|
|
5
|
+
var get_session_handler_default = defineHandler({
|
|
6
|
+
async execute(ctx, input) {
|
|
7
|
+
const params = input.params;
|
|
8
|
+
const sessionId = params?.sessionId;
|
|
9
|
+
if (!sessionId) {
|
|
10
|
+
throw new Error("Session ID is required");
|
|
11
|
+
}
|
|
12
|
+
const sessionManager = new SessionManager(ctx.cwd);
|
|
13
|
+
const session = await sessionManager.getSessionInfo(sessionId);
|
|
14
|
+
if (!session) {
|
|
15
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
16
|
+
}
|
|
17
|
+
return { session };
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { get_session_handler_default as default };
|
|
22
|
+
//# sourceMappingURL=get-session-handler.js.map
|
|
23
|
+
//# sourceMappingURL=get-session-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../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,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAE1B,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IAC1C;AAEA,IAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,IAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,cAAA,CAAe,SAAS,CAAA;AAE7D,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,IACnD;AAEA,IAAA,OAAO,EAAE,OAAA,EAAQ;AAAA,EACnB;AACF,CAAC","file":"get-session-handler.js","sourcesContent":["/**\n * GET /sessions/:sessionId - Get session details\n */\n\nimport { defineHandler, 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 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 },\n});\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
import { GetSessionPlanResponse } from '@kb-labs/agent-contracts';
|
|
4
|
+
|
|
5
|
+
interface GetSessionPlanRequest {
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<GetSessionPlanRequest, unknown, unknown>, GetSessionPlanResponse>;
|
|
9
|
+
|
|
10
|
+
export { _default as default };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { defineHandler } from '@kb-labs/sdk';
|
|
2
|
+
import { SessionManager, PlanDocumentService } from '@kb-labs/agent-core';
|
|
3
|
+
import { promises } from 'fs';
|
|
4
|
+
|
|
5
|
+
// src/rest/handlers/get-session-plan-handler.ts
|
|
6
|
+
async function loadPlan(planPath) {
|
|
7
|
+
try {
|
|
8
|
+
const content = await promises.readFile(planPath, "utf-8");
|
|
9
|
+
return JSON.parse(content);
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async function pathExists(filePath) {
|
|
15
|
+
try {
|
|
16
|
+
await promises.access(filePath);
|
|
17
|
+
return true;
|
|
18
|
+
} catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
var get_session_plan_handler_default = defineHandler({
|
|
23
|
+
async execute(ctx, input) {
|
|
24
|
+
const params = input.params;
|
|
25
|
+
const sessionId = params?.sessionId;
|
|
26
|
+
if (!sessionId) {
|
|
27
|
+
throw new Error("Session ID is required");
|
|
28
|
+
}
|
|
29
|
+
const sessionManager = new SessionManager(ctx.cwd);
|
|
30
|
+
const session = await sessionManager.loadSession(sessionId);
|
|
31
|
+
if (!session) {
|
|
32
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
33
|
+
}
|
|
34
|
+
const workingDir = session.workingDir || ctx.cwd;
|
|
35
|
+
const manager = new SessionManager(workingDir);
|
|
36
|
+
const planPath = manager.getSessionPlanPath(sessionId);
|
|
37
|
+
const plan = await loadPlan(planPath);
|
|
38
|
+
if (!plan) {
|
|
39
|
+
return { sessionId, plan: null };
|
|
40
|
+
}
|
|
41
|
+
const documentService = new PlanDocumentService(workingDir);
|
|
42
|
+
const canonicalPath = documentService.getPlanPath(plan);
|
|
43
|
+
return {
|
|
44
|
+
sessionId,
|
|
45
|
+
plan,
|
|
46
|
+
planPath: await pathExists(canonicalPath) ? canonicalPath : void 0
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
export { get_session_plan_handler_default as default };
|
|
52
|
+
//# sourceMappingURL=get-session-plan-handler.js.map
|
|
53
|
+
//# sourceMappingURL=get-session-plan-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../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,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IAC1C;AAEA,IAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,IAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAC1D,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,IACnD;AAEA,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,GAAA,CAAI,GAAA;AAC7C,IAAA,MAAM,OAAA,GAAU,IAAI,cAAA,CAAe,UAAU,CAAA;AAC7C,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,kBAAA,CAAmB,SAAS,CAAA;AACrD,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,QAAQ,CAAA;AAEpC,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,OAAO,EAAE,SAAA,EAAW,IAAA,EAAM,IAAA,EAAK;AAAA,IACjC;AAEA,IAAA,MAAM,eAAA,GAAkB,IAAI,mBAAA,CAAoB,UAAU,CAAA;AAC1D,IAAA,MAAM,aAAA,GAAgB,eAAA,CAAgB,WAAA,CAAY,IAAI,CAAA;AAEtD,IAAA,OAAO;AAAA,MACL,SAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAA,EAAU,MAAM,UAAA,CAAW,aAAa,IAAI,aAAA,GAAgB;AAAA,KAC9D;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, 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 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 },\n});\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
import { Turn } from '@kb-labs/agent-contracts';
|
|
4
|
+
|
|
5
|
+
interface GetSessionTurnsRequest {
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
limit?: number;
|
|
8
|
+
offset?: number;
|
|
9
|
+
}
|
|
10
|
+
interface GetSessionTurnsResponse {
|
|
11
|
+
turns: Turn[];
|
|
12
|
+
total: number;
|
|
13
|
+
}
|
|
14
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<GetSessionTurnsRequest, unknown, unknown>, GetSessionTurnsResponse>;
|
|
15
|
+
|
|
16
|
+
export { _default as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { defineHandler } from '@kb-labs/sdk';
|
|
2
|
+
import { SessionManager } from '@kb-labs/agent-core';
|
|
3
|
+
|
|
4
|
+
// src/rest/handlers/get-session-turns-handler.ts
|
|
5
|
+
var get_session_turns_handler_default = defineHandler({
|
|
6
|
+
async execute(ctx, input) {
|
|
7
|
+
const params = input.params;
|
|
8
|
+
const sessionId = params?.sessionId;
|
|
9
|
+
const query = input.query;
|
|
10
|
+
if (!sessionId) {
|
|
11
|
+
throw new Error("Session ID is required");
|
|
12
|
+
}
|
|
13
|
+
const sessionManager = new SessionManager(ctx.cwd);
|
|
14
|
+
ctx.platform.logger.info(`[get-session-turns] cwd: ${ctx.cwd}, sessionId: ${sessionId}`);
|
|
15
|
+
ctx.platform.logger.info(`[get-session-turns] turnsPath: ${sessionManager.getTurnsPath(sessionId)}`);
|
|
16
|
+
const session = await sessionManager.loadSession(sessionId);
|
|
17
|
+
if (!session) {
|
|
18
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
19
|
+
}
|
|
20
|
+
let turns = await sessionManager.getTurns(sessionId);
|
|
21
|
+
ctx.platform.logger.info(`[get-session-turns] Found ${turns.length} turns`);
|
|
22
|
+
const total = turns.length;
|
|
23
|
+
if (query?.offset) {
|
|
24
|
+
turns = turns.slice(query.offset);
|
|
25
|
+
}
|
|
26
|
+
if (query?.limit) {
|
|
27
|
+
turns = turns.slice(0, query.limit);
|
|
28
|
+
}
|
|
29
|
+
return { turns, total };
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export { get_session_turns_handler_default as default };
|
|
34
|
+
//# sourceMappingURL=get-session-turns-handler.js.map
|
|
35
|
+
//# sourceMappingURL=get-session-turns-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../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,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,IAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AAEpB,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IAC1C;AAEA,IAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAEjD,IAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,yBAAA,EAA4B,IAAI,GAAG,CAAA,aAAA,EAAgB,SAAS,CAAA,CAAE,CAAA;AACvF,IAAA,GAAA,CAAI,QAAA,CAAS,OAAO,IAAA,CAAK,CAAA,+BAAA,EAAkC,eAAe,YAAA,CAAa,SAAS,CAAC,CAAA,CAAE,CAAA;AAGnG,IAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAC1D,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,IACnD;AAGA,IAAA,IAAI,KAAA,GAAQ,MAAM,cAAA,CAAe,QAAA,CAAS,SAAS,CAAA;AAEnD,IAAA,GAAA,CAAI,SAAS,MAAA,CAAO,IAAA,CAAK,CAAA,0BAAA,EAA6B,KAAA,CAAM,MAAM,CAAA,MAAA,CAAQ,CAAA;AAG1E,IAAA,MAAM,QAAQ,KAAA,CAAM,MAAA;AACpB,IAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,MAAA,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,KAAA,CAAM,MAAM,CAAA;AAAA,IAClC;AACA,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,KAAK,CAAA;AAAA,IACpC;AAEA,IAAA,OAAO,EAAE,OAAO,KAAA,EAAM;AAAA,EACxB;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, 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 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 },\n});\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
import { GetSpecResponse } from '@kb-labs/agent-contracts';
|
|
4
|
+
|
|
5
|
+
interface GetSpecRouteParams {
|
|
6
|
+
sessionId?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<unknown, unknown, GetSpecRouteParams>, GetSpecResponse>;
|
|
9
|
+
|
|
10
|
+
export { _default as default };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineHandler } from '@kb-labs/sdk';
|
|
2
|
+
import { SessionManager } from '@kb-labs/agent-core';
|
|
3
|
+
import { promises } from 'fs';
|
|
4
|
+
|
|
5
|
+
// src/rest/handlers/get-spec-handler.ts
|
|
6
|
+
async function loadSpec(specPath) {
|
|
7
|
+
try {
|
|
8
|
+
const content = await promises.readFile(specPath, "utf-8");
|
|
9
|
+
return JSON.parse(content);
|
|
10
|
+
} catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
var get_spec_handler_default = defineHandler({
|
|
15
|
+
async execute(ctx, input) {
|
|
16
|
+
const params = input.params;
|
|
17
|
+
const sessionId = params?.sessionId;
|
|
18
|
+
if (!sessionId) {
|
|
19
|
+
throw new Error("Session ID is required");
|
|
20
|
+
}
|
|
21
|
+
const baseManager = new SessionManager(ctx.cwd);
|
|
22
|
+
const session = await baseManager.loadSession(sessionId);
|
|
23
|
+
if (!session) {
|
|
24
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
25
|
+
}
|
|
26
|
+
const workingDir = session.workingDir || ctx.cwd;
|
|
27
|
+
const manager = new SessionManager(workingDir);
|
|
28
|
+
const specPath = manager.getSessionSpecPath(sessionId);
|
|
29
|
+
const spec = await loadSpec(specPath);
|
|
30
|
+
return {
|
|
31
|
+
sessionId,
|
|
32
|
+
spec
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export { get_spec_handler_default as default };
|
|
38
|
+
//# sourceMappingURL=get-spec-handler.js.map
|
|
39
|
+
//# sourceMappingURL=get-spec-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../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,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IAC1C;AAEA,IAAA,MAAM,WAAA,GAAc,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAC9C,IAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,WAAA,CAAY,SAAS,CAAA;AACvD,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,IACnD;AAEA,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,GAAA,CAAI,GAAA;AAC7C,IAAA,MAAM,OAAA,GAAU,IAAI,cAAA,CAAe,UAAU,CAAA;AAC7C,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,kBAAA,CAAmB,SAAS,CAAA;AACrD,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,QAAQ,CAAA;AAEpC,IAAA,OAAO;AAAA,MACL,SAAA;AAAA,MACA;AAAA,KACF;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, 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 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 },\n});\n"]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
import { FileChangeSummary } from '@kb-labs/agent-history';
|
|
4
|
+
|
|
5
|
+
interface ListFileChangesResponse {
|
|
6
|
+
changes: FileChangeSummary[];
|
|
7
|
+
total: number;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
runId?: string;
|
|
10
|
+
}
|
|
11
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<unknown, unknown, unknown>, ListFileChangesResponse>;
|
|
12
|
+
|
|
13
|
+
export { _default as default };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { defineHandler } from '@kb-labs/sdk';
|
|
2
|
+
import { SessionManager } from '@kb-labs/agent-core';
|
|
3
|
+
import { ChangeStore, toSummary } from '@kb-labs/agent-history';
|
|
4
|
+
|
|
5
|
+
// src/rest/handlers/list-file-changes-handler.ts
|
|
6
|
+
var list_file_changes_handler_default = defineHandler({
|
|
7
|
+
async execute(ctx, input) {
|
|
8
|
+
const params = input.params;
|
|
9
|
+
const sessionId = params?.sessionId;
|
|
10
|
+
if (!sessionId) {
|
|
11
|
+
throw new Error("Session ID is required");
|
|
12
|
+
}
|
|
13
|
+
const query = input.query;
|
|
14
|
+
const runId = query?.runId;
|
|
15
|
+
const sessionManager = new SessionManager(ctx.cwd);
|
|
16
|
+
const session = await sessionManager.loadSession(sessionId);
|
|
17
|
+
if (!session) {
|
|
18
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
19
|
+
}
|
|
20
|
+
const workingDir = session.workingDir || ctx.cwd;
|
|
21
|
+
const store = new ChangeStore(workingDir);
|
|
22
|
+
const changes = runId ? await store.listRun(sessionId, runId) : await store.listSession(sessionId);
|
|
23
|
+
return {
|
|
24
|
+
changes: changes.map(toSummary),
|
|
25
|
+
total: changes.length,
|
|
26
|
+
sessionId,
|
|
27
|
+
runId
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export { list_file_changes_handler_default as default };
|
|
33
|
+
//# sourceMappingURL=list-file-changes-handler.js.map
|
|
34
|
+
//# sourceMappingURL=list-file-changes-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../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,MAAM,SAAS,KAAA,CAAM,MAAA;AACrB,IAAA,MAAM,YAAY,MAAA,EAAQ,SAAA;AAC1B,IAAA,IAAI,CAAC,SAAA,EAAW;AAAC,MAAA,MAAM,IAAI,MAAM,wBAAwB,CAAA;AAAA,IAAE;AAE3D,IAAA,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,IAAA,MAAM,QAAQ,KAAA,EAAO,KAAA;AAErB,IAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AACjD,IAAA,MAAM,OAAA,GAAU,MAAM,cAAA,CAAe,WAAA,CAAY,SAAS,CAAA;AAC1D,IAAA,IAAI,CAAC,OAAA,EAAS;AAAC,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,mBAAA,EAAsB,SAAS,CAAA,CAAE,CAAA;AAAA,IAAE;AAElE,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,UAAA,IAAc,GAAA,CAAI,GAAA;AAC7C,IAAA,MAAM,KAAA,GAAQ,IAAI,WAAA,CAAY,UAAU,CAAA;AAExC,IAAA,MAAM,OAAA,GAAU,KAAA,GACZ,MAAM,KAAA,CAAM,OAAA,CAAQ,SAAA,EAAW,KAAK,CAAA,GACpC,MAAM,KAAA,CAAM,WAAA,CAAY,SAAS,CAAA;AAErC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAA;AAAA,MAC9B,OAAO,OAAA,CAAQ,MAAA;AAAA,MACf,SAAA;AAAA,MACA;AAAA,KACF;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, 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 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 },\n});\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
import { ListSessionsRequest, ListSessionsResponse } from '@kb-labs/agent-contracts';
|
|
4
|
+
|
|
5
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<ListSessionsRequest, unknown, unknown>, ListSessionsResponse>;
|
|
6
|
+
|
|
7
|
+
export { _default as default };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineHandler } from '@kb-labs/sdk';
|
|
2
|
+
import { SessionManager } from '@kb-labs/agent-core';
|
|
3
|
+
|
|
4
|
+
// src/rest/handlers/list-sessions-handler.ts
|
|
5
|
+
var list_sessions_handler_default = defineHandler({
|
|
6
|
+
async execute(ctx, input) {
|
|
7
|
+
const query = input.query;
|
|
8
|
+
const sessionManager = new SessionManager(ctx.cwd);
|
|
9
|
+
const result = await sessionManager.listSessions({
|
|
10
|
+
status: query?.status,
|
|
11
|
+
limit: query?.limit ?? 50,
|
|
12
|
+
offset: query?.offset ?? 0
|
|
13
|
+
});
|
|
14
|
+
return {
|
|
15
|
+
sessions: result.sessions,
|
|
16
|
+
total: result.total
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export { list_sessions_handler_default as default };
|
|
22
|
+
//# sourceMappingURL=list-sessions-handler.js.map
|
|
23
|
+
//# sourceMappingURL=list-sessions-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../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,MAAM,QAAQ,KAAA,CAAM,KAAA;AACpB,IAAA,MAAM,cAAA,GAAiB,IAAI,cAAA,CAAe,GAAA,CAAI,GAAG,CAAA;AAGjD,IAAA,MAAM,MAAA,GAAS,MAAM,cAAA,CAAe,YAAA,CAAa;AAAA,MAC/C,QAAQ,KAAA,EAAO,MAAA;AAAA,MACf,KAAA,EAAO,OAAO,KAAA,IAAS,EAAA;AAAA,MACvB,MAAA,EAAQ,OAAO,MAAA,IAAU;AAAA,KAC1B,CAAA;AAED,IAAA,OAAO;AAAA,MACL,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,OAAO,MAAA,CAAO;AAAA,KAChB;AAAA,EACF;AACF,CAAC","file":"list-sessions-handler.js","sourcesContent":["/**\n * GET /sessions - List all sessions\n */\n\nimport { defineHandler, 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 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 },\n});\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
|
|
4
|
+
interface RollbackRequest {
|
|
5
|
+
runId?: string;
|
|
6
|
+
changeIds?: string[];
|
|
7
|
+
skipConflicts?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface ConflictEntry {
|
|
10
|
+
filePath: string;
|
|
11
|
+
changeId: string;
|
|
12
|
+
reason: string;
|
|
13
|
+
}
|
|
14
|
+
interface RollbackResponse {
|
|
15
|
+
rolledBack: number;
|
|
16
|
+
skipped: number;
|
|
17
|
+
conflicts: ConflictEntry[];
|
|
18
|
+
success: boolean;
|
|
19
|
+
}
|
|
20
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<RollbackRequest, unknown, unknown>, RollbackResponse>;
|
|
21
|
+
|
|
22
|
+
export { _default as default };
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { defineHandler } from '@kb-labs/sdk';
|
|
2
|
+
import { SessionManager } from '@kb-labs/agent-core';
|
|
3
|
+
import { ChangeStore } from '@kb-labs/agent-history';
|
|
4
|
+
import { promises } from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
// src/rest/handlers/rollback-handler.ts
|
|
8
|
+
var rollback_handler_default = defineHandler({
|
|
9
|
+
async execute(ctx, input) {
|
|
10
|
+
const params = input.params;
|
|
11
|
+
const sessionId = params?.sessionId;
|
|
12
|
+
if (!sessionId) {
|
|
13
|
+
throw new Error("Session ID is required");
|
|
14
|
+
}
|
|
15
|
+
const body = input.body ?? {};
|
|
16
|
+
const sessionManager = new SessionManager(ctx.cwd);
|
|
17
|
+
const session = await sessionManager.loadSession(sessionId);
|
|
18
|
+
if (!session) {
|
|
19
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
20
|
+
}
|
|
21
|
+
const workingDir = session.workingDir || ctx.cwd;
|
|
22
|
+
const store = new ChangeStore(workingDir);
|
|
23
|
+
let changes;
|
|
24
|
+
if (body.runId) {
|
|
25
|
+
changes = await store.listRun(sessionId, body.runId);
|
|
26
|
+
} else if (body.changeIds?.length) {
|
|
27
|
+
const ids = new Set(body.changeIds);
|
|
28
|
+
const all = await store.listSession(sessionId);
|
|
29
|
+
changes = all.filter((c) => ids.has(c.id));
|
|
30
|
+
} else {
|
|
31
|
+
changes = await store.listSession(sessionId);
|
|
32
|
+
}
|
|
33
|
+
if (changes.length === 0) {
|
|
34
|
+
return { rolledBack: 0, skipped: 0, conflicts: [], success: true };
|
|
35
|
+
}
|
|
36
|
+
const sorted = [...changes].sort(
|
|
37
|
+
(a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()
|
|
38
|
+
);
|
|
39
|
+
const fullHistory = await store.listSession(sessionId);
|
|
40
|
+
const rollbackIds = new Set(sorted.map((c) => c.id));
|
|
41
|
+
const conflicts = [];
|
|
42
|
+
let rolledBack = 0;
|
|
43
|
+
let skipped = 0;
|
|
44
|
+
for (const change of sorted) {
|
|
45
|
+
if (!body.skipConflicts) {
|
|
46
|
+
const laterChanges = fullHistory.filter(
|
|
47
|
+
(c) => c.filePath === change.filePath && new Date(c.timestamp).getTime() > new Date(change.timestamp).getTime() && !rollbackIds.has(c.id)
|
|
48
|
+
);
|
|
49
|
+
if (laterChanges.length > 0) {
|
|
50
|
+
const laterAgents = [...new Set(laterChanges.map((c) => c.agentId))].join(", ");
|
|
51
|
+
conflicts.push({
|
|
52
|
+
filePath: change.filePath,
|
|
53
|
+
changeId: change.id,
|
|
54
|
+
reason: `File was modified after this change by: ${laterAgents}. Use skipConflicts: true to force.`
|
|
55
|
+
});
|
|
56
|
+
skipped++;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const fullPath = path.join(workingDir, change.filePath);
|
|
61
|
+
try {
|
|
62
|
+
if (change.before) {
|
|
63
|
+
await promises.mkdir(path.dirname(fullPath), { recursive: true });
|
|
64
|
+
await promises.writeFile(fullPath, change.before.content, "utf-8");
|
|
65
|
+
} else {
|
|
66
|
+
await promises.unlink(fullPath).catch((e) => {
|
|
67
|
+
if (e.code !== "ENOENT") {
|
|
68
|
+
throw e;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
rolledBack++;
|
|
73
|
+
} catch (e) {
|
|
74
|
+
conflicts.push({
|
|
75
|
+
filePath: change.filePath,
|
|
76
|
+
changeId: change.id,
|
|
77
|
+
reason: `Write failed: ${e instanceof Error ? e.message : String(e)}`
|
|
78
|
+
});
|
|
79
|
+
skipped++;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
ctx.platform.logger.info(
|
|
83
|
+
`[rollback-handler] Session ${sessionId}: rolled back ${rolledBack}, skipped ${skipped}`
|
|
84
|
+
);
|
|
85
|
+
return { rolledBack, skipped, conflicts, success: skipped === 0 };
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
export { rollback_handler_default as default };
|
|
90
|
+
//# sourceMappingURL=rollback-handler.js.map
|
|
91
|
+
//# sourceMappingURL=rollback-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/rest/handlers/rollback-handler.ts"],"names":["fsp"],"mappings":"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","file":"rollback-handler.js","sourcesContent":["/**\n * POST /sessions/:sessionId/rollback — Rollback file changes.\n * Body: { runId?: string; changeIds?: string[]; skipConflicts?: boolean }\n */\n\nimport { defineHandler, 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 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 },\n});\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as _kb_labs_shared_command_kit from '@kb-labs/shared-command-kit';
|
|
2
|
+
import { RestInput } from '@kb-labs/sdk';
|
|
3
|
+
import { RunRequest, RunResponse } from '@kb-labs/agent-contracts';
|
|
4
|
+
|
|
5
|
+
declare const _default: _kb_labs_shared_command_kit.Handler<unknown, RestInput<RunRequest, unknown, unknown>, RunResponse>;
|
|
6
|
+
|
|
7
|
+
export { _default as default };
|