@oscharko-dev/keiko-server 0.2.7 → 0.2.9
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/.tsbuildinfo +1 -1
- package/dist/chat-handlers.d.ts +18 -2
- package/dist/chat-handlers.d.ts.map +1 -1
- package/dist/chat-handlers.js +185 -3
- package/dist/command-runner-errors.d.ts +17 -0
- package/dist/command-runner-errors.d.ts.map +1 -0
- package/dist/command-runner-errors.js +37 -0
- package/dist/command-runner-evidence.d.ts +23 -0
- package/dist/command-runner-evidence.d.ts.map +1 -0
- package/dist/command-runner-evidence.js +69 -0
- package/dist/command-runner-routes.d.ts +7 -0
- package/dist/command-runner-routes.d.ts.map +1 -0
- package/dist/command-runner-routes.js +175 -0
- package/dist/command-runner.d.ts +29 -0
- package/dist/command-runner.d.ts.map +1 -0
- package/dist/command-runner.js +348 -0
- package/dist/conversation-prompt.d.ts +2 -2
- package/dist/conversation-prompt.d.ts.map +1 -1
- package/dist/conversation-prompt.js +17 -1
- package/dist/csp.d.ts.map +1 -1
- package/dist/csp.js +3 -0
- package/dist/deps.d.ts +28 -1
- package/dist/deps.d.ts.map +1 -1
- package/dist/deps.js +288 -13
- package/dist/discussion-prompt.d.ts +4 -0
- package/dist/discussion-prompt.d.ts.map +1 -0
- package/dist/discussion-prompt.js +19 -0
- package/dist/editor/agentActionAudit.d.ts +18 -0
- package/dist/editor/agentActionAudit.d.ts.map +1 -0
- package/dist/editor/agentActionAudit.js +80 -0
- package/dist/editor/agentRoutes.d.ts +1 -0
- package/dist/editor/agentRoutes.d.ts.map +1 -1
- package/dist/editor/agentRoutes.js +292 -55
- package/dist/editor/agentSessionRegistry.d.ts +35 -0
- package/dist/editor/agentSessionRegistry.d.ts.map +1 -0
- package/dist/editor/agentSessionRegistry.js +243 -0
- package/dist/editor/completionRoutes.d.ts.map +1 -1
- package/dist/editor/completionRoutes.js +5 -10
- package/dist/editor/languageRoutes.d.ts +12 -1
- package/dist/editor/languageRoutes.d.ts.map +1 -1
- package/dist/editor/languageRoutes.js +71 -8
- package/dist/editor/languageService.d.ts +3 -2
- package/dist/editor/languageService.d.ts.map +1 -1
- package/dist/editor/languageService.js +41 -3
- package/dist/editor/languageServiceHost.d.ts.map +1 -1
- package/dist/editor/languageServiceHost.js +2 -2
- package/dist/editor/lsp/hostLanguageOperation.d.ts +17 -0
- package/dist/editor/lsp/hostLanguageOperation.d.ts.map +1 -0
- package/dist/editor/lsp/hostLanguageOperation.js +436 -0
- package/dist/editor/lsp/hostLanguageProviders.d.ts +26 -0
- package/dist/editor/lsp/hostLanguageProviders.d.ts.map +1 -0
- package/dist/editor/lsp/hostLanguageProviders.js +161 -0
- package/dist/editor/lsp/lspFrameCodec.d.ts +13 -0
- package/dist/editor/lsp/lspFrameCodec.d.ts.map +1 -0
- package/dist/editor/lsp/lspFrameCodec.js +164 -0
- package/dist/editor/lsp/lspJsonRpcClient.d.ts +34 -0
- package/dist/editor/lsp/lspJsonRpcClient.d.ts.map +1 -0
- package/dist/editor/lsp/lspJsonRpcClient.js +173 -0
- package/dist/editor/lsp/lspLanguageProvider.d.ts +7 -0
- package/dist/editor/lsp/lspLanguageProvider.d.ts.map +1 -0
- package/dist/editor/lsp/lspLanguageProvider.js +29 -0
- package/dist/editor/lsp/lspLifecycleLedger.d.ts +5 -0
- package/dist/editor/lsp/lspLifecycleLedger.d.ts.map +1 -0
- package/dist/editor/lsp/lspLifecycleLedger.js +37 -0
- package/dist/editor/lsp/lspNodeAdapter.d.ts +31 -0
- package/dist/editor/lsp/lspNodeAdapter.d.ts.map +1 -0
- package/dist/editor/lsp/lspNodeAdapter.js +230 -0
- package/dist/editor/lsp/lspProcessManager.d.ts +24 -0
- package/dist/editor/lsp/lspProcessManager.d.ts.map +1 -0
- package/dist/editor/lsp/lspProcessManager.js +255 -0
- package/dist/editor/lsp/lspRestartThrottle.d.ts +6 -0
- package/dist/editor/lsp/lspRestartThrottle.d.ts.map +1 -0
- package/dist/editor/lsp/lspRestartThrottle.js +24 -0
- package/dist/editor/lsp/lspStatusRoute.d.ts +8 -0
- package/dist/editor/lsp/lspStatusRoute.d.ts.map +1 -0
- package/dist/editor/lsp/lspStatusRoute.js +22 -0
- package/dist/editor/lsp/lspTransport.d.ts +19 -0
- package/dist/editor/lsp/lspTransport.d.ts.map +1 -0
- package/dist/editor/lsp/lspTransport.js +55 -0
- package/dist/editor/lsp/testing/fakeLspProcess.d.ts +23 -0
- package/dist/editor/lsp/testing/fakeLspProcess.d.ts.map +1 -0
- package/dist/editor/lsp/testing/fakeLspProcess.js +132 -0
- package/dist/files.d.ts +63 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +799 -1
- package/dist/gateway-readiness.d.ts +6 -0
- package/dist/gateway-readiness.d.ts.map +1 -0
- package/dist/gateway-readiness.js +624 -0
- package/dist/gateway-setup.d.ts +2 -0
- package/dist/gateway-setup.d.ts.map +1 -1
- package/dist/gateway-setup.js +275 -11
- package/dist/gitDelivery/actionSheetProjection.d.ts +30 -0
- package/dist/gitDelivery/actionSheetProjection.d.ts.map +1 -0
- package/dist/gitDelivery/actionSheetProjection.js +206 -0
- package/dist/gitDelivery/actionSheetRoutes.d.ts +29 -0
- package/dist/gitDelivery/actionSheetRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/actionSheetRoutes.js +293 -0
- package/dist/gitDelivery/agentOperationsRoutes.d.ts +33 -0
- package/dist/gitDelivery/agentOperationsRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/agentOperationsRoutes.js +405 -0
- package/dist/gitDelivery/commitRoutes.d.ts +23 -0
- package/dist/gitDelivery/commitRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/commitRoutes.js +204 -0
- package/dist/gitDelivery/evidenceRoutes.d.ts +9 -0
- package/dist/gitDelivery/evidenceRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/evidenceRoutes.js +101 -0
- package/dist/gitDelivery/execution.d.ts +38 -0
- package/dist/gitDelivery/execution.d.ts.map +1 -0
- package/dist/gitDelivery/execution.js +117 -0
- package/dist/gitDelivery/localMutationRoutes.d.ts +30 -0
- package/dist/gitDelivery/localMutationRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/localMutationRoutes.js +165 -0
- package/dist/gitDelivery/mergeExecution.d.ts +63 -0
- package/dist/gitDelivery/mergeExecution.d.ts.map +1 -0
- package/dist/gitDelivery/mergeExecution.js +168 -0
- package/dist/gitDelivery/mergeRoutes.d.ts +12 -0
- package/dist/gitDelivery/mergeRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/mergeRoutes.js +218 -0
- package/dist/gitDelivery/mutationEvidenceLedger.d.ts +23 -0
- package/dist/gitDelivery/mutationEvidenceLedger.d.ts.map +1 -0
- package/dist/gitDelivery/mutationEvidenceLedger.js +87 -0
- package/dist/gitDelivery/prExecution.d.ts +54 -0
- package/dist/gitDelivery/prExecution.d.ts.map +1 -0
- package/dist/gitDelivery/prExecution.js +192 -0
- package/dist/gitDelivery/prRoutes.d.ts +12 -0
- package/dist/gitDelivery/prRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/prRoutes.js +256 -0
- package/dist/gitDelivery/pushExecution.d.ts +43 -0
- package/dist/gitDelivery/pushExecution.d.ts.map +1 -0
- package/dist/gitDelivery/pushExecution.js +124 -0
- package/dist/gitDelivery/pushRoutes.d.ts +12 -0
- package/dist/gitDelivery/pushRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/pushRoutes.js +200 -0
- package/dist/gitDelivery/requestGuards.d.ts +15 -0
- package/dist/gitDelivery/requestGuards.d.ts.map +1 -0
- package/dist/gitDelivery/requestGuards.js +97 -0
- package/dist/gitDelivery/syncEvidence.d.ts +37 -0
- package/dist/gitDelivery/syncEvidence.d.ts.map +1 -0
- package/dist/gitDelivery/syncEvidence.js +85 -0
- package/dist/gitDelivery/syncExecution.d.ts +30 -0
- package/dist/gitDelivery/syncExecution.d.ts.map +1 -0
- package/dist/gitDelivery/syncExecution.js +266 -0
- package/dist/gitDelivery/syncRoutes.d.ts +13 -0
- package/dist/gitDelivery/syncRoutes.d.ts.map +1 -0
- package/dist/gitDelivery/syncRoutes.js +200 -0
- package/dist/gitPorcelainStatus.d.ts +15 -0
- package/dist/gitPorcelainStatus.d.ts.map +1 -0
- package/dist/gitPorcelainStatus.js +104 -0
- package/dist/gitRepositoryReads.d.ts +10 -0
- package/dist/gitRepositoryReads.d.ts.map +1 -0
- package/dist/gitRepositoryReads.js +314 -0
- package/dist/gitRepositoryRoutes.d.ts +7 -0
- package/dist/gitRepositoryRoutes.d.ts.map +1 -0
- package/dist/gitRepositoryRoutes.js +221 -0
- package/dist/gitRoutes.d.ts +66 -0
- package/dist/gitRoutes.d.ts.map +1 -0
- package/dist/gitRoutes.js +543 -0
- package/dist/governed-workflow.d.ts +2 -0
- package/dist/governed-workflow.d.ts.map +1 -1
- package/dist/governed-workflow.js +4 -0
- package/dist/grounded-qa-hybrid.d.ts.map +1 -1
- package/dist/grounded-qa-hybrid.js +2 -0
- package/dist/grounded-qa-multi-source.d.ts.map +1 -1
- package/dist/grounded-qa-multi-source.js +1 -0
- package/dist/grounded-qa.d.ts +11 -0
- package/dist/grounded-qa.d.ts.map +1 -1
- package/dist/grounded-qa.js +14 -4
- package/dist/headers.d.ts +4 -1
- package/dist/headers.d.ts.map +1 -1
- package/dist/headers.js +11 -4
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/local-knowledge-grounded-qa.d.ts.map +1 -1
- package/dist/local-knowledge-grounded-qa.js +11 -2
- package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts +1 -1
- package/dist/qualityIntelligence/figmaSnapshotRoutes.d.ts.map +1 -1
- package/dist/qualityIntelligence/figmaSnapshotRoutes.js +1 -1
- package/dist/read-handlers.d.ts +5 -0
- package/dist/read-handlers.d.ts.map +1 -1
- package/dist/read-handlers.js +57 -1
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +260 -12
- package/dist/run-engine.d.ts.map +1 -1
- package/dist/run-engine.js +3 -0
- package/dist/run-handlers.d.ts +0 -1
- package/dist/run-handlers.d.ts.map +1 -1
- package/dist/run-handlers.js +64 -211
- package/dist/run-request.d.ts +11 -0
- package/dist/run-request.d.ts.map +1 -1
- package/dist/run-request.js +158 -10
- package/dist/runtime/capabilityDetector.d.ts +38 -0
- package/dist/runtime/capabilityDetector.d.ts.map +1 -0
- package/dist/runtime/capabilityDetector.js +443 -0
- package/dist/runtime/capabilityRoutes.d.ts +9 -0
- package/dist/runtime/capabilityRoutes.d.ts.map +1 -0
- package/dist/runtime/capabilityRoutes.js +45 -0
- package/dist/runtime/containerEngineDetector.d.ts +17 -0
- package/dist/runtime/containerEngineDetector.d.ts.map +1 -0
- package/dist/runtime/containerEngineDetector.js +222 -0
- package/dist/runtime/containerRoutes.d.ts +8 -0
- package/dist/runtime/containerRoutes.d.ts.map +1 -0
- package/dist/runtime/containerRoutes.js +207 -0
- package/dist/runtime/containerRunner-errors.d.ts +18 -0
- package/dist/runtime/containerRunner-errors.d.ts.map +1 -0
- package/dist/runtime/containerRunner-errors.js +42 -0
- package/dist/runtime/containerRunner-evidence.d.ts +24 -0
- package/dist/runtime/containerRunner-evidence.d.ts.map +1 -0
- package/dist/runtime/containerRunner-evidence.js +74 -0
- package/dist/runtime/containerRunner.d.ts +37 -0
- package/dist/runtime/containerRunner.d.ts.map +1 -0
- package/dist/runtime/containerRunner.js +443 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +24 -4
- package/dist/store/db.d.ts.map +1 -1
- package/dist/store/db.js +2 -1
- package/dist/store/index.d.ts +1 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/messages.d.ts +2 -1
- package/dist/store/messages.d.ts.map +1 -1
- package/dist/store/messages.js +46 -4
- package/dist/store/schema.d.ts +1 -1
- package/dist/store/schema.d.ts.map +1 -1
- package/dist/store/schema.js +68 -1
- package/dist/store/types.d.ts +3 -2
- package/dist/store/types.d.ts.map +1 -1
- package/dist/task-workspace/active-store.d.ts +21 -0
- package/dist/task-workspace/active-store.d.ts.map +1 -0
- package/dist/task-workspace/active-store.js +55 -0
- package/dist/task-workspace/authorization.d.ts +7 -0
- package/dist/task-workspace/authorization.d.ts.map +1 -0
- package/dist/task-workspace/authorization.js +54 -0
- package/dist/task-workspace/binding.d.ts +3 -0
- package/dist/task-workspace/binding.d.ts.map +1 -0
- package/dist/task-workspace/binding.js +22 -0
- package/dist/task-workspace/cleanup.d.ts +4 -0
- package/dist/task-workspace/cleanup.d.ts.map +1 -0
- package/dist/task-workspace/cleanup.js +428 -0
- package/dist/task-workspace/errors.d.ts +14 -0
- package/dist/task-workspace/errors.d.ts.map +1 -0
- package/dist/task-workspace/errors.js +81 -0
- package/dist/task-workspace/evidence.d.ts +32 -0
- package/dist/task-workspace/evidence.d.ts.map +1 -0
- package/dist/task-workspace/evidence.js +52 -0
- package/dist/task-workspace/field-safety.d.ts +3 -0
- package/dist/task-workspace/field-safety.d.ts.map +1 -0
- package/dist/task-workspace/field-safety.js +42 -0
- package/dist/task-workspace/health.d.ts +4 -0
- package/dist/task-workspace/health.d.ts.map +1 -0
- package/dist/task-workspace/health.js +163 -0
- package/dist/task-workspace/lifecycle.d.ts +3 -0
- package/dist/task-workspace/lifecycle.d.ts.map +1 -0
- package/dist/task-workspace/lifecycle.js +248 -0
- package/dist/task-workspace/locks.d.ts +13 -0
- package/dist/task-workspace/locks.d.ts.map +1 -0
- package/dist/task-workspace/locks.js +44 -0
- package/dist/task-workspace/managed-root.d.ts +7 -0
- package/dist/task-workspace/managed-root.d.ts.map +1 -0
- package/dist/task-workspace/managed-root.js +98 -0
- package/dist/task-workspace/mutex.d.ts +8 -0
- package/dist/task-workspace/mutex.d.ts.map +1 -0
- package/dist/task-workspace/mutex.js +82 -0
- package/dist/task-workspace/naming.d.ts +15 -0
- package/dist/task-workspace/naming.d.ts.map +1 -0
- package/dist/task-workspace/naming.js +0 -0
- package/dist/task-workspace/provisioning.d.ts +3 -0
- package/dist/task-workspace/provisioning.d.ts.map +1 -0
- package/dist/task-workspace/provisioning.js +528 -0
- package/dist/task-workspace/reconciliation.d.ts +15 -0
- package/dist/task-workspace/reconciliation.d.ts.map +1 -0
- package/dist/task-workspace/reconciliation.js +274 -0
- package/dist/task-workspace/repair.d.ts +3 -0
- package/dist/task-workspace/repair.d.ts.map +1 -0
- package/dist/task-workspace/repair.js +286 -0
- package/dist/task-workspace/routes.d.ts +19 -0
- package/dist/task-workspace/routes.d.ts.map +1 -0
- package/dist/task-workspace/routes.js +481 -0
- package/dist/task-workspace/store.d.ts +12 -0
- package/dist/task-workspace/store.d.ts.map +1 -0
- package/dist/task-workspace/store.js +128 -0
- package/dist/task-workspace/types.d.ts +170 -0
- package/dist/task-workspace/types.d.ts.map +1 -0
- package/dist/task-workspace/types.js +5 -0
- package/dist/voice-action-governance.d.ts +23 -0
- package/dist/voice-action-governance.d.ts.map +1 -0
- package/dist/voice-action-governance.js +126 -0
- package/dist/voice-handlers.d.ts +6 -0
- package/dist/voice-handlers.d.ts.map +1 -0
- package/dist/voice-handlers.js +570 -0
- package/dist/voice-realtime-grounded-tool.d.ts +31 -0
- package/dist/voice-realtime-grounded-tool.d.ts.map +1 -0
- package/dist/voice-realtime-grounded-tool.js +322 -0
- package/dist/voice-realtime.d.ts +69 -0
- package/dist/voice-realtime.d.ts.map +1 -0
- package/dist/voice-realtime.js +787 -0
- package/dist/workspace-state-handlers.d.ts +5 -0
- package/dist/workspace-state-handlers.d.ts.map +1 -0
- package/dist/workspace-state-handlers.js +106 -0
- package/package.json +20 -19
- package/dist/grounded-handoff.d.ts +0 -4
- package/dist/grounded-handoff.d.ts.map +0 -1
- package/dist/grounded-handoff.js +0 -445
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { RouteContext, RouteResult } from "./routes.js";
|
|
2
|
+
export declare function handleGetWorkspaceState(): RouteResult;
|
|
3
|
+
export declare function handlePutWorkspaceState(ctx: RouteContext): Promise<RouteResult>;
|
|
4
|
+
export declare function resetWorkspaceStateForTests(): void;
|
|
5
|
+
//# sourceMappingURL=workspace-state-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-state-handlers.d.ts","sourceRoot":"","sources":["../src/workspace-state-handlers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA2F7D,wBAAgB,uBAAuB,IAAI,WAAW,CAErD;AAED,wBAAsB,uBAAuB,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAwBrF;AAED,wBAAgB,2BAA2B,IAAI,IAAI,CAElD"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { errorBody } from "./routes.js";
|
|
2
|
+
const MAX_WORKSPACE_STATE_BODY_BYTES = 256_000;
|
|
3
|
+
const MAX_WORKSPACE_WINDOWS = 128;
|
|
4
|
+
const MAX_WORKSPACE_CONNECTIONS = 512;
|
|
5
|
+
let workspaceState = {
|
|
6
|
+
revision: 0,
|
|
7
|
+
windows: [],
|
|
8
|
+
connections: [],
|
|
9
|
+
updatedAtMs: 0,
|
|
10
|
+
};
|
|
11
|
+
class InvalidWorkspaceState extends Error {
|
|
12
|
+
constructor(message) {
|
|
13
|
+
super(message);
|
|
14
|
+
this.name = "InvalidWorkspaceState";
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
class WorkspaceStateBodyTooLarge extends Error {
|
|
18
|
+
constructor() {
|
|
19
|
+
super("body too large");
|
|
20
|
+
this.name = "WorkspaceStateBodyTooLarge";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function readBody(req) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const chunks = [];
|
|
26
|
+
let total = 0;
|
|
27
|
+
let capped = false;
|
|
28
|
+
req.on("data", (chunk) => {
|
|
29
|
+
total += chunk.length;
|
|
30
|
+
if (total > MAX_WORKSPACE_STATE_BODY_BYTES) {
|
|
31
|
+
if (!capped) {
|
|
32
|
+
capped = true;
|
|
33
|
+
chunks.length = 0;
|
|
34
|
+
reject(new WorkspaceStateBodyTooLarge());
|
|
35
|
+
req.resume();
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
chunks.push(chunk);
|
|
40
|
+
});
|
|
41
|
+
req.on("end", () => {
|
|
42
|
+
if (!capped)
|
|
43
|
+
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
44
|
+
});
|
|
45
|
+
req.on("error", reject);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function asRecord(value) {
|
|
49
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
50
|
+
throw new InvalidWorkspaceState("Request body must be a JSON object.");
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
53
|
+
}
|
|
54
|
+
async function readJsonObject(req) {
|
|
55
|
+
let parsed;
|
|
56
|
+
try {
|
|
57
|
+
parsed = JSON.parse(await readBody(req));
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (error instanceof WorkspaceStateBodyTooLarge)
|
|
61
|
+
throw error;
|
|
62
|
+
throw new InvalidWorkspaceState("Request body is not valid JSON.");
|
|
63
|
+
}
|
|
64
|
+
return asRecord(parsed);
|
|
65
|
+
}
|
|
66
|
+
function requireArray(body, key, maxItems) {
|
|
67
|
+
const value = body[key];
|
|
68
|
+
if (!Array.isArray(value))
|
|
69
|
+
throw new InvalidWorkspaceState(`Field "${key}" must be an array.`);
|
|
70
|
+
if (value.length > maxItems) {
|
|
71
|
+
throw new InvalidWorkspaceState(`Field "${key}" exceeds the item limit.`);
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
74
|
+
}
|
|
75
|
+
export function handleGetWorkspaceState() {
|
|
76
|
+
return { status: 200, body: { workspace: workspaceState } };
|
|
77
|
+
}
|
|
78
|
+
export async function handlePutWorkspaceState(ctx) {
|
|
79
|
+
try {
|
|
80
|
+
const body = await readJsonObject(ctx.req);
|
|
81
|
+
const windows = requireArray(body, "windows", MAX_WORKSPACE_WINDOWS);
|
|
82
|
+
const connections = requireArray(body, "connections", MAX_WORKSPACE_CONNECTIONS);
|
|
83
|
+
workspaceState = {
|
|
84
|
+
revision: workspaceState.revision + 1,
|
|
85
|
+
windows,
|
|
86
|
+
connections,
|
|
87
|
+
updatedAtMs: Date.now(),
|
|
88
|
+
};
|
|
89
|
+
return { status: 200, body: { workspace: workspaceState } };
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
if (error instanceof WorkspaceStateBodyTooLarge) {
|
|
93
|
+
return {
|
|
94
|
+
status: 413,
|
|
95
|
+
body: errorBody("payload_too_large", "Workspace state exceeds the size limit."),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
if (error instanceof InvalidWorkspaceState) {
|
|
99
|
+
return { status: 400, body: errorBody("invalid_request", error.message) };
|
|
100
|
+
}
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function resetWorkspaceStateForTests() {
|
|
105
|
+
workspaceState = { revision: 0, windows: [], connections: [], updatedAtMs: 0 };
|
|
106
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscharko-dev/keiko-server",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"description": "Internal server package: local loopback BFF runtime (HTTP/SSE/WebSocket router, CSP, host check, CSRF gate, terminal, browser, files, run engine, SQLite-backed UI store) that mediates the browser presentation tier and the Node-side domain packages (ADR-0019). Not published independently.",
|
|
@@ -29,24 +29,25 @@
|
|
|
29
29
|
"node": ">=22"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@oscharko-dev/keiko-contracts": "0.2.
|
|
33
|
-
"@oscharko-dev/keiko-security": "0.2.
|
|
34
|
-
"@oscharko-dev/keiko-model-gateway": "0.2.
|
|
35
|
-
"@oscharko-dev/keiko-quality-intelligence": "0.2.
|
|
36
|
-
"@oscharko-dev/keiko-local-knowledge": "0.2.
|
|
37
|
-
"@oscharko-dev/keiko-workspace": "0.2.
|
|
38
|
-
"@oscharko-dev/keiko-sandbox": "0.2.
|
|
39
|
-
"@oscharko-dev/keiko-tools": "0.2.
|
|
40
|
-
"@oscharko-dev/keiko-evidence": "0.2.
|
|
41
|
-
"@oscharko-dev/keiko-verification": "0.2.
|
|
42
|
-
"@oscharko-dev/keiko-harness": "0.2.
|
|
43
|
-
"@oscharko-dev/keiko-sdk": "0.2.
|
|
44
|
-
"@oscharko-dev/keiko-workflows": "0.2.
|
|
45
|
-
"@oscharko-dev/keiko-memory-vault": "0.2.
|
|
46
|
-
"@oscharko-dev/keiko-memory-governance": "0.2.
|
|
47
|
-
"@oscharko-dev/keiko-memory-retrieval": "0.2.
|
|
48
|
-
"@oscharko-dev/keiko-memory-capture": "0.2.
|
|
49
|
-
"@oscharko-dev/keiko-memory-consolidation": "0.2.
|
|
32
|
+
"@oscharko-dev/keiko-contracts": "0.2.9",
|
|
33
|
+
"@oscharko-dev/keiko-security": "0.2.9",
|
|
34
|
+
"@oscharko-dev/keiko-model-gateway": "0.2.9",
|
|
35
|
+
"@oscharko-dev/keiko-quality-intelligence": "0.2.9",
|
|
36
|
+
"@oscharko-dev/keiko-local-knowledge": "0.2.9",
|
|
37
|
+
"@oscharko-dev/keiko-workspace": "0.2.9",
|
|
38
|
+
"@oscharko-dev/keiko-sandbox": "0.2.9",
|
|
39
|
+
"@oscharko-dev/keiko-tools": "0.2.9",
|
|
40
|
+
"@oscharko-dev/keiko-evidence": "0.2.9",
|
|
41
|
+
"@oscharko-dev/keiko-verification": "0.2.9",
|
|
42
|
+
"@oscharko-dev/keiko-harness": "0.2.9",
|
|
43
|
+
"@oscharko-dev/keiko-sdk": "0.2.9",
|
|
44
|
+
"@oscharko-dev/keiko-workflows": "0.2.9",
|
|
45
|
+
"@oscharko-dev/keiko-memory-vault": "0.2.9",
|
|
46
|
+
"@oscharko-dev/keiko-memory-governance": "0.2.9",
|
|
47
|
+
"@oscharko-dev/keiko-memory-retrieval": "0.2.9",
|
|
48
|
+
"@oscharko-dev/keiko-memory-capture": "0.2.9",
|
|
49
|
+
"@oscharko-dev/keiko-memory-consolidation": "0.2.9",
|
|
50
|
+
"ws": "^8.21.0",
|
|
50
51
|
"typescript": "^6.0.3"
|
|
51
52
|
}
|
|
52
53
|
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { type UiHandlerDeps } from "./deps.js";
|
|
2
|
-
import type { RouteContext, RouteResult } from "./routes.js";
|
|
3
|
-
export declare function handleGroundedWorkflowHandoff(ctx: RouteContext, deps: UiHandlerDeps): Promise<RouteResult>;
|
|
4
|
-
//# sourceMappingURL=grounded-handoff.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"grounded-handoff.d.ts","sourceRoot":"","sources":["../src/grounded-handoff.ts"],"names":[],"mappings":"AAmBA,OAAO,EAA2B,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AAYxE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA8hB7D,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,YAAY,EACjB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,WAAW,CAAC,CAOtB"}
|
package/dist/grounded-handoff.js
DELETED
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
-
import { DEFAULT_PATCH_SCOPE_LIMITS, EXPECTED_CHECKS, WORKFLOW_HANDOFF_SCHEMA_VERSION, WORKFLOW_KINDS, validateWorkflowHandoffRequest, } from "@oscharko-dev/keiko-contracts/workflow-handoff";
|
|
3
|
-
import { createAuditRedactor } from "@oscharko-dev/keiko-evidence";
|
|
4
|
-
import { WorkspaceError } from "@oscharko-dev/keiko-workspace";
|
|
5
|
-
import { currentRedactionSecrets } from "./deps.js";
|
|
6
|
-
import { approvalTokenInputFor, contextPackStableIdForPacks, createApprovalToken, evidenceAtomIdsForPacks, readOnlyPathsForPacks, } from "./governed-workflow.js";
|
|
7
|
-
import { lookupGroundedTurn } from "./grounded-turn-registry.js";
|
|
8
|
-
import { startRun } from "./run-engine.js";
|
|
9
|
-
import { parseRunRequest } from "./run-request.js";
|
|
10
|
-
import { ActiveRunLimitError } from "./runs.js";
|
|
11
|
-
import { errorBody } from "./routes.js";
|
|
12
|
-
import { memoryCaptureCustomerMatchers } from "./memory-capture-policy.js";
|
|
13
|
-
const MAX_BODY_BYTES = 256 * 1024;
|
|
14
|
-
const RESERVED_WORKFLOW_INPUT_FIELDS = new Set([
|
|
15
|
-
"apply",
|
|
16
|
-
"governedHandoff",
|
|
17
|
-
"limits",
|
|
18
|
-
"modelId",
|
|
19
|
-
"workflowHandoff",
|
|
20
|
-
"workspaceRoot",
|
|
21
|
-
]);
|
|
22
|
-
const VERIFY_NOOP_MODEL = {
|
|
23
|
-
call: () => Promise.reject(new Error("verify runs must not call the model")),
|
|
24
|
-
};
|
|
25
|
-
class BodyTooLargeError extends Error {
|
|
26
|
-
constructor() {
|
|
27
|
-
super("request body too large");
|
|
28
|
-
this.name = "BodyTooLargeError";
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function readBody(req) {
|
|
32
|
-
return new Promise((resolve, reject) => {
|
|
33
|
-
const chunks = [];
|
|
34
|
-
let total = 0;
|
|
35
|
-
let capped = false;
|
|
36
|
-
req.on("data", (chunk) => {
|
|
37
|
-
total += chunk.length;
|
|
38
|
-
if (total > MAX_BODY_BYTES) {
|
|
39
|
-
if (!capped) {
|
|
40
|
-
capped = true;
|
|
41
|
-
chunks.length = 0;
|
|
42
|
-
reject(new BodyTooLargeError());
|
|
43
|
-
req.resume();
|
|
44
|
-
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
chunks.push(chunk);
|
|
48
|
-
});
|
|
49
|
-
req.on("end", () => {
|
|
50
|
-
if (!capped) {
|
|
51
|
-
resolve(Buffer.concat(chunks).toString("utf8"));
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
req.on("error", reject);
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
function isRecord(value) {
|
|
58
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
59
|
-
}
|
|
60
|
-
function isExpectedCheck(value) {
|
|
61
|
-
return typeof value === "string" && EXPECTED_CHECKS.includes(value);
|
|
62
|
-
}
|
|
63
|
-
function isWorkflowKind(value) {
|
|
64
|
-
return typeof value === "string" && WORKFLOW_KINDS.includes(value);
|
|
65
|
-
}
|
|
66
|
-
function parseJsonRecord(raw) {
|
|
67
|
-
let parsed;
|
|
68
|
-
try {
|
|
69
|
-
parsed = JSON.parse(raw);
|
|
70
|
-
}
|
|
71
|
-
catch {
|
|
72
|
-
return { status: 400, body: errorBody("BAD_REQUEST", "Request body is not valid JSON.") };
|
|
73
|
-
}
|
|
74
|
-
if (!isRecord(parsed)) {
|
|
75
|
-
return { status: 400, body: errorBody("BAD_REQUEST", "Request body must be a JSON object.") };
|
|
76
|
-
}
|
|
77
|
-
return parsed;
|
|
78
|
-
}
|
|
79
|
-
function isRouteResult(value) {
|
|
80
|
-
return isRecord(value) && typeof value.status === "number" && "body" in value;
|
|
81
|
-
}
|
|
82
|
-
function badField(field, message) {
|
|
83
|
-
return {
|
|
84
|
-
status: 400,
|
|
85
|
-
body: errorBody("BAD_REQUEST", `Field "${field}" ${message}.`),
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
function requireString(body, field) {
|
|
89
|
-
const value = body[field];
|
|
90
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
91
|
-
return badField(field, "is required");
|
|
92
|
-
}
|
|
93
|
-
return value;
|
|
94
|
-
}
|
|
95
|
-
function requireNumber(body, field) {
|
|
96
|
-
const value = body[field];
|
|
97
|
-
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
98
|
-
return badField(field, "must be a finite number");
|
|
99
|
-
}
|
|
100
|
-
return value;
|
|
101
|
-
}
|
|
102
|
-
function requireRecord(body, field) {
|
|
103
|
-
const value = body[field];
|
|
104
|
-
if (!isRecord(value)) {
|
|
105
|
-
return badField(field, "must be an object");
|
|
106
|
-
}
|
|
107
|
-
return value;
|
|
108
|
-
}
|
|
109
|
-
function validateWorkflowInput(input) {
|
|
110
|
-
for (const field of RESERVED_WORKFLOW_INPUT_FIELDS) {
|
|
111
|
-
if (Object.prototype.hasOwnProperty.call(input, field)) {
|
|
112
|
-
return badField("input", `must not include reserved workflow field "${field}"`);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return null;
|
|
116
|
-
}
|
|
117
|
-
function stringArrayField(body, field) {
|
|
118
|
-
const value = body[field];
|
|
119
|
-
if (!Array.isArray(value)) {
|
|
120
|
-
return badField(field, "must be an array");
|
|
121
|
-
}
|
|
122
|
-
const parsed = [];
|
|
123
|
-
for (const entry of value) {
|
|
124
|
-
if (typeof entry !== "string" || entry.trim().length === 0) {
|
|
125
|
-
return badField(field, "must contain non-empty strings");
|
|
126
|
-
}
|
|
127
|
-
parsed.push(entry);
|
|
128
|
-
}
|
|
129
|
-
return parsed;
|
|
130
|
-
}
|
|
131
|
-
function defaultExpectedChecks(workflowKind) {
|
|
132
|
-
if (workflowKind === "unit-test-generation") {
|
|
133
|
-
return ["tests"];
|
|
134
|
-
}
|
|
135
|
-
return ["verify"];
|
|
136
|
-
}
|
|
137
|
-
function parseExpectedChecks(body, workflowKind) {
|
|
138
|
-
if (body.expectedChecks === undefined) {
|
|
139
|
-
return defaultExpectedChecks(workflowKind);
|
|
140
|
-
}
|
|
141
|
-
const parsed = stringArrayField(body, "expectedChecks");
|
|
142
|
-
if (isRouteResult(parsed)) {
|
|
143
|
-
return parsed;
|
|
144
|
-
}
|
|
145
|
-
if (!parsed.every(isExpectedCheck)) {
|
|
146
|
-
return {
|
|
147
|
-
status: 400,
|
|
148
|
-
body: errorBody("BAD_REQUEST", 'Field "expectedChecks" contains an unknown check.'),
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
return parsed;
|
|
152
|
-
}
|
|
153
|
-
function parseWorkflowKindField(body) {
|
|
154
|
-
const workflowKind = requireString(body, "workflowKind");
|
|
155
|
-
if (isRouteResult(workflowKind)) {
|
|
156
|
-
return workflowKind;
|
|
157
|
-
}
|
|
158
|
-
return isWorkflowKind(workflowKind)
|
|
159
|
-
? workflowKind
|
|
160
|
-
: { status: 400, body: errorBody("BAD_REQUEST", 'Field "workflowKind" is invalid.') };
|
|
161
|
-
}
|
|
162
|
-
function parseUnknowns(body) {
|
|
163
|
-
return body.unknowns === undefined ? [] : stringArrayField(body, "unknowns");
|
|
164
|
-
}
|
|
165
|
-
function parseRequiredFields(body) {
|
|
166
|
-
const workflowKind = parseWorkflowKindField(body);
|
|
167
|
-
if (isRouteResult(workflowKind)) {
|
|
168
|
-
return workflowKind;
|
|
169
|
-
}
|
|
170
|
-
const assistantMessageId = requireString(body, "assistantMessageId");
|
|
171
|
-
if (isRouteResult(assistantMessageId)) {
|
|
172
|
-
return assistantMessageId;
|
|
173
|
-
}
|
|
174
|
-
const chatId = requireString(body, "chatId");
|
|
175
|
-
if (isRouteResult(chatId)) {
|
|
176
|
-
return chatId;
|
|
177
|
-
}
|
|
178
|
-
const modelId = requireString(body, "modelId");
|
|
179
|
-
if (isRouteResult(modelId)) {
|
|
180
|
-
return modelId;
|
|
181
|
-
}
|
|
182
|
-
const input = requireRecord(body, "input");
|
|
183
|
-
if (isRouteResult(input)) {
|
|
184
|
-
return input;
|
|
185
|
-
}
|
|
186
|
-
const inputError = validateWorkflowInput(input);
|
|
187
|
-
if (inputError !== null) {
|
|
188
|
-
return inputError;
|
|
189
|
-
}
|
|
190
|
-
return { assistantMessageId, chatId, modelId, workflowKind, input };
|
|
191
|
-
}
|
|
192
|
-
function parseBody(raw) {
|
|
193
|
-
const body = parseJsonRecord(raw);
|
|
194
|
-
if (isRouteResult(body)) {
|
|
195
|
-
return body;
|
|
196
|
-
}
|
|
197
|
-
const required = parseRequiredFields(body);
|
|
198
|
-
if (isRouteResult(required)) {
|
|
199
|
-
return required;
|
|
200
|
-
}
|
|
201
|
-
const editablePaths = stringArrayField(body, "editablePaths");
|
|
202
|
-
if (isRouteResult(editablePaths)) {
|
|
203
|
-
return editablePaths;
|
|
204
|
-
}
|
|
205
|
-
const unknowns = parseUnknowns(body);
|
|
206
|
-
if (isRouteResult(unknowns)) {
|
|
207
|
-
return unknowns;
|
|
208
|
-
}
|
|
209
|
-
const requestedAtMs = requireNumber(body, "requestedAtMs");
|
|
210
|
-
if (isRouteResult(requestedAtMs)) {
|
|
211
|
-
return requestedAtMs;
|
|
212
|
-
}
|
|
213
|
-
const expectedChecks = parseExpectedChecks(body, required.workflowKind);
|
|
214
|
-
if (isRouteResult(expectedChecks)) {
|
|
215
|
-
return expectedChecks;
|
|
216
|
-
}
|
|
217
|
-
return {
|
|
218
|
-
...required,
|
|
219
|
-
editablePaths,
|
|
220
|
-
expectedChecks,
|
|
221
|
-
unknowns,
|
|
222
|
-
requestedAtMs,
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
function workspaceRootForTurn(record) {
|
|
226
|
-
const roots = new Set(record?.packs.map((pack) => pack.scope.workspaceRoot) ?? []);
|
|
227
|
-
if (roots.size !== 1) {
|
|
228
|
-
return {
|
|
229
|
-
status: 409,
|
|
230
|
-
body: errorBody("BAD_REQUEST", "Grounded handoff requires evidence from a single connected workspace root."),
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
const root = [...roots][0];
|
|
234
|
-
if (typeof root !== "string" || root.length === 0) {
|
|
235
|
-
return {
|
|
236
|
-
status: 404,
|
|
237
|
-
body: errorBody("NOT_FOUND", "Grounded handoff context is no longer available."),
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
return root;
|
|
241
|
-
}
|
|
242
|
-
function runRequestFor(workflowKind, modelId, workspaceRoot, input) {
|
|
243
|
-
const parsed = parseRunRequest(JSON.stringify({
|
|
244
|
-
...(workflowKind === "verification" ? { taskType: "verify" } : { workflowId: workflowKind }),
|
|
245
|
-
modelId,
|
|
246
|
-
input: { ...input, workspaceRoot },
|
|
247
|
-
}));
|
|
248
|
-
if ("code" in parsed) {
|
|
249
|
-
return { status: 400, body: errorBody(parsed.code, parsed.message) };
|
|
250
|
-
}
|
|
251
|
-
return parsed;
|
|
252
|
-
}
|
|
253
|
-
function summaryDiscriminator(workflowKind) {
|
|
254
|
-
if (workflowKind === "verification") {
|
|
255
|
-
return { workflowId: undefined, taskType: "verify" };
|
|
256
|
-
}
|
|
257
|
-
return { workflowId: workflowKind, taskType: undefined };
|
|
258
|
-
}
|
|
259
|
-
function workflowLabel(workflowKind) {
|
|
260
|
-
if (workflowKind === "unit-test-generation") {
|
|
261
|
-
return "grounded unit-test generation";
|
|
262
|
-
}
|
|
263
|
-
if (workflowKind === "bug-investigation") {
|
|
264
|
-
return "grounded bug investigation";
|
|
265
|
-
}
|
|
266
|
-
return "grounded verification";
|
|
267
|
-
}
|
|
268
|
-
function persistGroundedHandoffMessages(deps, chatId, workflowKind, runId) {
|
|
269
|
-
const now = Date.now();
|
|
270
|
-
const discriminator = summaryDiscriminator(workflowKind);
|
|
271
|
-
const label = workflowLabel(workflowKind);
|
|
272
|
-
const [user, summary] = deps.store.createMessages([
|
|
273
|
-
{
|
|
274
|
-
chatId,
|
|
275
|
-
role: "user",
|
|
276
|
-
content: `Requested ${label}.`,
|
|
277
|
-
timestamp: now,
|
|
278
|
-
runId: undefined,
|
|
279
|
-
workflowId: undefined,
|
|
280
|
-
workflowStatus: undefined,
|
|
281
|
-
shortResult: undefined,
|
|
282
|
-
taskType: undefined,
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
chatId,
|
|
286
|
-
role: "system",
|
|
287
|
-
content: `Launched ${label}.`,
|
|
288
|
-
timestamp: now + 1,
|
|
289
|
-
runId,
|
|
290
|
-
workflowId: discriminator.workflowId,
|
|
291
|
-
workflowStatus: "running",
|
|
292
|
-
shortResult: undefined,
|
|
293
|
-
taskType: discriminator.taskType,
|
|
294
|
-
},
|
|
295
|
-
]);
|
|
296
|
-
if (user === undefined || summary === undefined) {
|
|
297
|
-
throw new Error("createMessages returned fewer rows than expected");
|
|
298
|
-
}
|
|
299
|
-
return [user, summary];
|
|
300
|
-
}
|
|
301
|
-
function resolveRunModel(request, deps) {
|
|
302
|
-
return request.kind === "verify" ? VERIFY_NOOP_MODEL : deps.modelPortFactory(request.modelId);
|
|
303
|
-
}
|
|
304
|
-
function engineContextFor(deps, request, model) {
|
|
305
|
-
return {
|
|
306
|
-
request,
|
|
307
|
-
model,
|
|
308
|
-
registry: deps.registry,
|
|
309
|
-
evidence: {
|
|
310
|
-
store: deps.evidenceStore,
|
|
311
|
-
env: deps.env,
|
|
312
|
-
additionalSecrets: currentRedactionSecrets(deps),
|
|
313
|
-
},
|
|
314
|
-
memoryVault: deps.memoryVault,
|
|
315
|
-
memoryAuditRedactString: createAuditRedactor({ additionalSecrets: currentRedactionSecrets(deps) }, deps.env),
|
|
316
|
-
memoryCustomerIdentifierMatchers: memoryCaptureCustomerMatchers(deps),
|
|
317
|
-
};
|
|
318
|
-
}
|
|
319
|
-
function markSummaryFailed(deps, message, shortResult) {
|
|
320
|
-
try {
|
|
321
|
-
deps.store.updateMessage(message.id, { workflowStatus: "failed", shortResult });
|
|
322
|
-
}
|
|
323
|
-
catch {
|
|
324
|
-
// best-effort compensation only
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
function mapRunStartError(error) {
|
|
328
|
-
if (error instanceof ActiveRunLimitError) {
|
|
329
|
-
return { status: 429, body: errorBody("TOO_MANY_RUNS", "The active run limit is reached.") };
|
|
330
|
-
}
|
|
331
|
-
if (error instanceof WorkspaceError) {
|
|
332
|
-
return {
|
|
333
|
-
status: 400,
|
|
334
|
-
body: errorBody("WORKSPACE_UNAVAILABLE", "The selected workspace could not be prepared: no recognized project workspace marker was found, or the target file could not be read."),
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
throw error;
|
|
338
|
-
}
|
|
339
|
-
function buildGovernedHandoffRequest(body, record) {
|
|
340
|
-
const patchScope = {
|
|
341
|
-
schemaVersion: WORKFLOW_HANDOFF_SCHEMA_VERSION,
|
|
342
|
-
editablePaths: body.editablePaths,
|
|
343
|
-
readOnlyPaths: readOnlyPathsForPacks(record.packs, body.editablePaths),
|
|
344
|
-
evidenceAtomIds: evidenceAtomIdsForPacks(record.packs),
|
|
345
|
-
limits: DEFAULT_PATCH_SCOPE_LIMITS,
|
|
346
|
-
expectedChecks: body.expectedChecks,
|
|
347
|
-
unknowns: body.unknowns,
|
|
348
|
-
};
|
|
349
|
-
const draft = {
|
|
350
|
-
schemaVersion: WORKFLOW_HANDOFF_SCHEMA_VERSION,
|
|
351
|
-
contextPackStableId: contextPackStableIdForPacks(record.packs),
|
|
352
|
-
workflowKind: body.workflowKind,
|
|
353
|
-
patchScope,
|
|
354
|
-
requestedAtMs: body.requestedAtMs,
|
|
355
|
-
userApprovalToken: "0".repeat(64),
|
|
356
|
-
};
|
|
357
|
-
const request = {
|
|
358
|
-
...draft,
|
|
359
|
-
userApprovalToken: createApprovalToken(approvalTokenInputFor(draft)),
|
|
360
|
-
};
|
|
361
|
-
const validation = validateWorkflowHandoffRequest(request);
|
|
362
|
-
if (!validation.ok) {
|
|
363
|
-
return {
|
|
364
|
-
status: 400,
|
|
365
|
-
body: errorBody("BAD_REQUEST", validation.reasons.join("; ")),
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
return request;
|
|
369
|
-
}
|
|
370
|
-
async function parseGroundedHandoffBody(req) {
|
|
371
|
-
try {
|
|
372
|
-
return parseBody(await readBody(req));
|
|
373
|
-
}
|
|
374
|
-
catch (error) {
|
|
375
|
-
if (error instanceof BodyTooLargeError) {
|
|
376
|
-
return {
|
|
377
|
-
status: 413,
|
|
378
|
-
body: errorBody("PAYLOAD_TOO_LARGE", "Request body exceeds the size limit."),
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
throw error;
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
function resolveGroundedHandoffLaunch(body, deps) {
|
|
385
|
-
const record = lookupGroundedTurn(body.assistantMessageId);
|
|
386
|
-
if (record === undefined) {
|
|
387
|
-
return {
|
|
388
|
-
status: 404,
|
|
389
|
-
body: errorBody("NOT_FOUND", "Grounded handoff context is no longer available."),
|
|
390
|
-
};
|
|
391
|
-
}
|
|
392
|
-
if (record.chatId !== body.chatId) {
|
|
393
|
-
return {
|
|
394
|
-
status: 404,
|
|
395
|
-
body: errorBody("NOT_FOUND", "Grounded handoff context is no longer available."),
|
|
396
|
-
};
|
|
397
|
-
}
|
|
398
|
-
const workspaceRoot = workspaceRootForTurn(record);
|
|
399
|
-
if (isRouteResult(workspaceRoot)) {
|
|
400
|
-
return workspaceRoot;
|
|
401
|
-
}
|
|
402
|
-
const governedHandoff = buildGovernedHandoffRequest(body, record);
|
|
403
|
-
if (isRouteResult(governedHandoff)) {
|
|
404
|
-
return governedHandoff;
|
|
405
|
-
}
|
|
406
|
-
const baseRequest = runRequestFor(body.workflowKind, body.modelId, workspaceRoot, body.input);
|
|
407
|
-
if (isRouteResult(baseRequest)) {
|
|
408
|
-
return baseRequest;
|
|
409
|
-
}
|
|
410
|
-
const request = {
|
|
411
|
-
...baseRequest,
|
|
412
|
-
governedHandoff,
|
|
413
|
-
governedHandoffSourceGroundedRunId: record.evidenceRunId,
|
|
414
|
-
};
|
|
415
|
-
const model = resolveRunModel(request, deps);
|
|
416
|
-
if (model === undefined) {
|
|
417
|
-
return { status: 400, body: errorBody("NO_MODEL", "No model provider is configured.") };
|
|
418
|
-
}
|
|
419
|
-
return { chatId: record.chatId, workflowKind: body.workflowKind, request, model };
|
|
420
|
-
}
|
|
421
|
-
function startGroundedWorkflowRun(deps, launch) {
|
|
422
|
-
const runId = randomUUID();
|
|
423
|
-
const messages = persistGroundedHandoffMessages(deps, launch.chatId, launch.workflowKind, runId);
|
|
424
|
-
try {
|
|
425
|
-
const run = startRun(engineContextFor(deps, launch.request, launch.model), deps.redactor, {
|
|
426
|
-
runId,
|
|
427
|
-
});
|
|
428
|
-
return {
|
|
429
|
-
status: 202,
|
|
430
|
-
body: { run, messages },
|
|
431
|
-
};
|
|
432
|
-
}
|
|
433
|
-
catch (error) {
|
|
434
|
-
markSummaryFailed(deps, messages[1], "Run could not be started.");
|
|
435
|
-
return mapRunStartError(error);
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
export async function handleGroundedWorkflowHandoff(ctx, deps) {
|
|
439
|
-
const body = await parseGroundedHandoffBody(ctx.req);
|
|
440
|
-
if (isRouteResult(body)) {
|
|
441
|
-
return body;
|
|
442
|
-
}
|
|
443
|
-
const launch = resolveGroundedHandoffLaunch(body, deps);
|
|
444
|
-
return isRouteResult(launch) ? launch : startGroundedWorkflowRun(deps, launch);
|
|
445
|
-
}
|