@zhixuan92/multi-model-agent 3.0.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/LICENSE +21 -0
- package/README.md +217 -0
- package/dist/cli/index.d.ts +61 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +252 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/install-skill.d.ts +158 -0
- package/dist/cli/install-skill.d.ts.map +1 -0
- package/dist/cli/install-skill.js +425 -0
- package/dist/cli/install-skill.js.map +1 -0
- package/dist/cli/print-token.d.ts +18 -0
- package/dist/cli/print-token.d.ts.map +1 -0
- package/dist/cli/print-token.js +60 -0
- package/dist/cli/print-token.js.map +1 -0
- package/dist/cli/serve.d.ts +44 -0
- package/dist/cli/serve.d.ts.map +1 -0
- package/dist/cli/serve.js +61 -0
- package/dist/cli/serve.js.map +1 -0
- package/dist/cli/status.d.ts +49 -0
- package/dist/cli/status.d.ts.map +1 -0
- package/dist/cli/status.js +155 -0
- package/dist/cli/status.js.map +1 -0
- package/dist/http/async-dispatch.d.ts +32 -0
- package/dist/http/async-dispatch.d.ts.map +1 -0
- package/dist/http/async-dispatch.js +53 -0
- package/dist/http/async-dispatch.js.map +1 -0
- package/dist/http/auth.d.ts +26 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +64 -0
- package/dist/http/auth.js.map +1 -0
- package/dist/http/cwd-validator.d.ts +11 -0
- package/dist/http/cwd-validator.d.ts.map +1 -0
- package/dist/http/cwd-validator.js +115 -0
- package/dist/http/cwd-validator.js.map +1 -0
- package/dist/http/errors.d.ts +4 -0
- package/dist/http/errors.d.ts.map +1 -0
- package/dist/http/errors.js +9 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/http/execution-context.d.ts +15 -0
- package/dist/http/execution-context.d.ts.map +1 -0
- package/dist/http/execution-context.js +35 -0
- package/dist/http/execution-context.js.map +1 -0
- package/dist/http/handler-deps.d.ts +16 -0
- package/dist/http/handler-deps.d.ts.map +1 -0
- package/dist/http/handler-deps.js +2 -0
- package/dist/http/handler-deps.js.map +1 -0
- package/dist/http/handlers/control/batch.d.ts +24 -0
- package/dist/http/handlers/control/batch.d.ts.map +1 -0
- package/dist/http/handlers/control/batch.js +81 -0
- package/dist/http/handlers/control/batch.js.map +1 -0
- package/dist/http/handlers/control/clarifications.d.ts +19 -0
- package/dist/http/handlers/control/clarifications.d.ts.map +1 -0
- package/dist/http/handlers/control/clarifications.js +58 -0
- package/dist/http/handlers/control/clarifications.js.map +1 -0
- package/dist/http/handlers/control/context-blocks.d.ts +22 -0
- package/dist/http/handlers/control/context-blocks.d.ts.map +1 -0
- package/dist/http/handlers/control/context-blocks.js +88 -0
- package/dist/http/handlers/control/context-blocks.js.map +1 -0
- package/dist/http/handlers/introspection/health.d.ts +13 -0
- package/dist/http/handlers/introspection/health.d.ts.map +1 -0
- package/dist/http/handlers/introspection/health.js +17 -0
- package/dist/http/handlers/introspection/health.js.map +1 -0
- package/dist/http/handlers/introspection/status.d.ts +26 -0
- package/dist/http/handlers/introspection/status.d.ts.map +1 -0
- package/dist/http/handlers/introspection/status.js +136 -0
- package/dist/http/handlers/introspection/status.js.map +1 -0
- package/dist/http/handlers/introspection/tools-list.d.ts +9 -0
- package/dist/http/handlers/introspection/tools-list.d.ts.map +1 -0
- package/dist/http/handlers/introspection/tools-list.js +28 -0
- package/dist/http/handlers/introspection/tools-list.js.map +1 -0
- package/dist/http/handlers/tools/audit.d.ts +4 -0
- package/dist/http/handlers/tools/audit.d.ts.map +1 -0
- package/dist/http/handlers/tools/audit.js +39 -0
- package/dist/http/handlers/tools/audit.js.map +1 -0
- package/dist/http/handlers/tools/debug.d.ts +4 -0
- package/dist/http/handlers/tools/debug.d.ts.map +1 -0
- package/dist/http/handlers/tools/debug.js +39 -0
- package/dist/http/handlers/tools/debug.js.map +1 -0
- package/dist/http/handlers/tools/delegate.d.ts +4 -0
- package/dist/http/handlers/tools/delegate.d.ts.map +1 -0
- package/dist/http/handlers/tools/delegate.js +57 -0
- package/dist/http/handlers/tools/delegate.js.map +1 -0
- package/dist/http/handlers/tools/execute-plan.d.ts +4 -0
- package/dist/http/handlers/tools/execute-plan.d.ts.map +1 -0
- package/dist/http/handlers/tools/execute-plan.js +39 -0
- package/dist/http/handlers/tools/execute-plan.js.map +1 -0
- package/dist/http/handlers/tools/retry.d.ts +4 -0
- package/dist/http/handlers/tools/retry.d.ts.map +1 -0
- package/dist/http/handlers/tools/retry.js +52 -0
- package/dist/http/handlers/tools/retry.js.map +1 -0
- package/dist/http/handlers/tools/review.d.ts +4 -0
- package/dist/http/handlers/tools/review.d.ts.map +1 -0
- package/dist/http/handlers/tools/review.js +39 -0
- package/dist/http/handlers/tools/review.js.map +1 -0
- package/dist/http/handlers/tools/verify.d.ts +4 -0
- package/dist/http/handlers/tools/verify.d.ts.map +1 -0
- package/dist/http/handlers/tools/verify.js +39 -0
- package/dist/http/handlers/tools/verify.js.map +1 -0
- package/dist/http/loopback.d.ts +17 -0
- package/dist/http/loopback.d.ts.map +1 -0
- package/dist/http/loopback.js +43 -0
- package/dist/http/loopback.js.map +1 -0
- package/dist/http/middleware/body-reader.d.ts +16 -0
- package/dist/http/middleware/body-reader.d.ts.map +1 -0
- package/dist/http/middleware/body-reader.js +44 -0
- package/dist/http/middleware/body-reader.js.map +1 -0
- package/dist/http/project-registry.d.ts +54 -0
- package/dist/http/project-registry.d.ts.map +1 -0
- package/dist/http/project-registry.js +132 -0
- package/dist/http/project-registry.js.map +1 -0
- package/dist/http/router.d.ts +14 -0
- package/dist/http/router.d.ts.map +1 -0
- package/dist/http/router.js +41 -0
- package/dist/http/router.js.map +1 -0
- package/dist/http/server.d.ts +16 -0
- package/dist/http/server.d.ts.map +1 -0
- package/dist/http/server.js +235 -0
- package/dist/http/server.js.map +1 -0
- package/dist/http/types.d.ts +9 -0
- package/dist/http/types.d.ts.map +1 -0
- package/dist/http/types.js +2 -0
- package/dist/http/types.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/install/claude-code.d.ts +43 -0
- package/dist/install/claude-code.d.ts.map +1 -0
- package/dist/install/claude-code.js +65 -0
- package/dist/install/claude-code.js.map +1 -0
- package/dist/install/codex-cli.d.ts +39 -0
- package/dist/install/codex-cli.d.ts.map +1 -0
- package/dist/install/codex-cli.js +318 -0
- package/dist/install/codex-cli.js.map +1 -0
- package/dist/install/cursor.d.ts +72 -0
- package/dist/install/cursor.d.ts.map +1 -0
- package/dist/install/cursor.js +81 -0
- package/dist/install/cursor.js.map +1 -0
- package/dist/install/gemini-cli.d.ts +66 -0
- package/dist/install/gemini-cli.d.ts.map +1 -0
- package/dist/install/gemini-cli.js +111 -0
- package/dist/install/gemini-cli.js.map +1 -0
- package/dist/install/include-utils.d.ts +27 -0
- package/dist/install/include-utils.d.ts.map +1 -0
- package/dist/install/include-utils.js +90 -0
- package/dist/install/include-utils.js.map +1 -0
- package/dist/install/manifest.d.ts +90 -0
- package/dist/install/manifest.d.ts.map +1 -0
- package/dist/install/manifest.js +200 -0
- package/dist/install/manifest.js.map +1 -0
- package/dist/openapi.d.ts +15 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +314 -0
- package/dist/openapi.js.map +1 -0
- package/dist/skills/_shared/auth.md +32 -0
- package/dist/skills/_shared/error-handling.md +31 -0
- package/dist/skills/_shared/polling.md +40 -0
- package/dist/skills/_shared/response-shape.md +46 -0
- package/dist/skills/mma-audit/SKILL.md +55 -0
- package/dist/skills/mma-clarifications/SKILL.md +68 -0
- package/dist/skills/mma-context-blocks/SKILL.md +69 -0
- package/dist/skills/mma-debug/SKILL.md +59 -0
- package/dist/skills/mma-delegate/SKILL.md +63 -0
- package/dist/skills/mma-execute-plan/SKILL.md +63 -0
- package/dist/skills/mma-retry/SKILL.md +54 -0
- package/dist/skills/mma-review/SKILL.md +55 -0
- package/dist/skills/mma-verify/SKILL.md +57 -0
- package/dist/skills/multi-model-agent/SKILL.md +55 -0
- package/package.json +60 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
const SEP = path.sep;
|
|
4
|
+
/**
|
|
5
|
+
* Walk each path component and check if any symlink points outside its
|
|
6
|
+
* containing parent directory (symlink escape). Returns true if a symlink
|
|
7
|
+
* escape is detected.
|
|
8
|
+
*
|
|
9
|
+
* Algorithm: build the path incrementally. At each component that is a symlink,
|
|
10
|
+
* canonicalize both the parent directory and the symlink's resolved target via
|
|
11
|
+
* realpathSync, then verify that the resolved target is a descendant of the
|
|
12
|
+
* canonical parent. This handles macOS-style double-indirection (e.g. /var →
|
|
13
|
+
* /private/var) without false positives.
|
|
14
|
+
*/
|
|
15
|
+
function hasSymlinkEscape(cwd) {
|
|
16
|
+
const parts = cwd.split(SEP).filter(Boolean); // ['a','b','c'] for /a/b/c
|
|
17
|
+
// We track the "logical" accumulated path (not yet canonicalized) so lstat
|
|
18
|
+
// finds the right inode even when earlier symlinks changed the real prefix.
|
|
19
|
+
// We will resolve it when we need to compare.
|
|
20
|
+
let logicalAccum = SEP;
|
|
21
|
+
for (const part of parts) {
|
|
22
|
+
const logicalCurrent = path.join(logicalAccum, part);
|
|
23
|
+
// Resolve logicalAccum to its canonical form so lstat finds the right path.
|
|
24
|
+
let canonAccum;
|
|
25
|
+
try {
|
|
26
|
+
canonAccum = fs.realpathSync(logicalAccum);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
const canonCurrent = path.join(canonAccum, part);
|
|
32
|
+
let lstat;
|
|
33
|
+
try {
|
|
34
|
+
lstat = fs.lstatSync(canonCurrent);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
// Path doesn't exist — validateCwd will catch this
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
if (lstat.isSymbolicLink()) {
|
|
41
|
+
let target;
|
|
42
|
+
try {
|
|
43
|
+
target = fs.readlinkSync(canonCurrent);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
// Resolve target relative to the canonical parent directory of the symlink.
|
|
49
|
+
const resolvedTarget = path.isAbsolute(target)
|
|
50
|
+
? target
|
|
51
|
+
: path.resolve(canonAccum, target);
|
|
52
|
+
// Canonicalize the resolved target and the parent dir for stable comparison.
|
|
53
|
+
let canonResolvedTarget;
|
|
54
|
+
try {
|
|
55
|
+
canonResolvedTarget = fs.realpathSync(resolvedTarget);
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Target doesn't exist — validateCwd will catch this
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
// The parent dir that should "contain" this symlink is canonAccum.
|
|
62
|
+
const parentWithSep = canonAccum.endsWith(SEP) ? canonAccum : canonAccum + SEP;
|
|
63
|
+
const resolvedWithSep = canonResolvedTarget.endsWith(SEP)
|
|
64
|
+
? canonResolvedTarget
|
|
65
|
+
: canonResolvedTarget + SEP;
|
|
66
|
+
if (!resolvedWithSep.startsWith(parentWithSep)) {
|
|
67
|
+
// Symlink escapes its parent directory
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
logicalAccum = resolvedTarget;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
logicalAccum = logicalCurrent;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
export function validateCwd(cwd) {
|
|
79
|
+
if (!cwd)
|
|
80
|
+
return { ok: false, error: 'missing_cwd', message: "required query param 'cwd' not provided" };
|
|
81
|
+
if (!path.isAbsolute(cwd))
|
|
82
|
+
return { ok: false, error: 'invalid_cwd', message: `cwd must be absolute: ${cwd}` };
|
|
83
|
+
let canonical;
|
|
84
|
+
try {
|
|
85
|
+
canonical = fs.realpathSync(cwd);
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const code = err.code;
|
|
89
|
+
if (code === 'ENOENT')
|
|
90
|
+
return { ok: false, error: 'cwd_not_dir', message: `cwd does not exist: ${cwd}` };
|
|
91
|
+
if (code === 'EACCES' || code === 'EPERM')
|
|
92
|
+
return { ok: false, error: 'cwd_not_dir', message: `cwd is not accessible (permission denied): ${cwd}` };
|
|
93
|
+
return { ok: false, error: 'cwd_not_dir', message: `cwd cannot be resolved (${code ?? 'unknown error'}): ${cwd}` };
|
|
94
|
+
}
|
|
95
|
+
let stat;
|
|
96
|
+
try {
|
|
97
|
+
stat = fs.statSync(canonical);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return { ok: false, error: 'cwd_not_dir', message: `cwd realpath is not accessible: ${cwd} → ${canonical}` };
|
|
101
|
+
}
|
|
102
|
+
if (!stat.isDirectory())
|
|
103
|
+
return { ok: false, error: 'cwd_not_dir', message: `cwd is not a directory: ${cwd}` };
|
|
104
|
+
// ── Symlink-escape check ──────────────────────────────────────────────────
|
|
105
|
+
// Detect symlinks whose target escapes the containing parent directory.
|
|
106
|
+
if (hasSymlinkEscape(cwd)) {
|
|
107
|
+
return {
|
|
108
|
+
ok: false,
|
|
109
|
+
error: 'forbidden_cwd',
|
|
110
|
+
message: `cwd contains a symlink that escapes its parent directory: ${cwd}`,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return { ok: true, canonicalCwd: canonical };
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=cwd-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cwd-validator.js","sourceRoot":"","sources":["../../src/http/cwd-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ServerResponse } from 'node:http';
|
|
2
|
+
export declare function sendError(res: ServerResponse, status: number, code: string, message: string, details?: unknown): void;
|
|
3
|
+
export declare function sendJson(res: ServerResponse, status: number, body: unknown): void;
|
|
4
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,wBAAgB,SAAS,CACvB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,OAAO,GAChB,IAAI,CAGN;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAGjF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export function sendError(res, status, code, message, details) {
|
|
2
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
3
|
+
res.end(JSON.stringify({ error: { code, message, ...(details !== undefined ? { details } : {}) } }));
|
|
4
|
+
}
|
|
5
|
+
export function sendJson(res, status, body) {
|
|
6
|
+
res.writeHead(status, { 'content-type': 'application/json' });
|
|
7
|
+
res.end(JSON.stringify(body));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,SAAS,CACvB,GAAmB,EACnB,MAAc,EACd,IAAY,EACZ,OAAe,EACf,OAAiB;IAEjB,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACvG,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAmB,EAAE,MAAc,EAAE,IAAa;IACzE,GAAG,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAC9D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ProjectContext } from '@zhixuan92/multi-model-agent-core';
|
|
2
|
+
import type { ExecutionContext } from '@zhixuan92/multi-model-agent-core/executors/types';
|
|
3
|
+
import type { HandlerDeps } from './handler-deps.js';
|
|
4
|
+
/**
|
|
5
|
+
* Builds the ExecutionContext passed to every executor.
|
|
6
|
+
*
|
|
7
|
+
* awaitClarification wires to the BatchRegistry clarification flow:
|
|
8
|
+
* 1. Sets entry.resolveClarification BEFORE calling requestClarification
|
|
9
|
+
* (order matters — requestClarification changes state; resolver must be
|
|
10
|
+
* registered first so resumeFromClarification can call it later).
|
|
11
|
+
* 2. Returns a Promise that resolves when resumeFromClarification is called
|
|
12
|
+
* by the POST /batch/:id/clarify handler (Phase 7).
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildExecutionContext(deps: HandlerDeps, pc: ProjectContext, batchId: string): ExecutionContext;
|
|
15
|
+
//# sourceMappingURL=execution-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-context.d.ts","sourceRoot":"","sources":["../../src/http/execution-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,KAAK,EAAE,gBAAgB,EAAyB,MAAM,mDAAmD,CAAC;AACjH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,WAAW,EACjB,EAAE,EAAE,cAAc,EAClB,OAAO,EAAE,MAAM,GACd,gBAAgB,CAqBlB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// packages/server/src/http/execution-context.ts
|
|
2
|
+
import { createProvider } from '@zhixuan92/multi-model-agent-core';
|
|
3
|
+
/**
|
|
4
|
+
* Builds the ExecutionContext passed to every executor.
|
|
5
|
+
*
|
|
6
|
+
* awaitClarification wires to the BatchRegistry clarification flow:
|
|
7
|
+
* 1. Sets entry.resolveClarification BEFORE calling requestClarification
|
|
8
|
+
* (order matters — requestClarification changes state; resolver must be
|
|
9
|
+
* registered first so resumeFromClarification can call it later).
|
|
10
|
+
* 2. Returns a Promise that resolves when resumeFromClarification is called
|
|
11
|
+
* by the POST /batch/:id/clarify handler (Phase 7).
|
|
12
|
+
*/
|
|
13
|
+
export function buildExecutionContext(deps, pc, batchId) {
|
|
14
|
+
return {
|
|
15
|
+
projectContext: pc,
|
|
16
|
+
config: deps.config,
|
|
17
|
+
logger: deps.logger,
|
|
18
|
+
contextBlockStore: pc.contextBlocks,
|
|
19
|
+
providerFactory: (profile) => createProvider(profile, deps.config),
|
|
20
|
+
parentModel: process.env['PARENT_MODEL_NAME'],
|
|
21
|
+
onProgress: undefined,
|
|
22
|
+
awaitClarification: async (proposal) => {
|
|
23
|
+
return new Promise((resolve) => {
|
|
24
|
+
const entry = deps.batchRegistry.get(batchId);
|
|
25
|
+
if (entry) {
|
|
26
|
+
// Register resolver BEFORE transitioning state so resumeFromClarification
|
|
27
|
+
// can call it immediately if it races ahead.
|
|
28
|
+
entry.resolveClarification = (interpretation) => resolve({ interpretation });
|
|
29
|
+
}
|
|
30
|
+
deps.batchRegistry.requestClarification(batchId, proposal.interpretation);
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=execution-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execution-context.js","sourceRoot":"","sources":["../../src/http/execution-context.ts"],"names":[],"mappings":"AAAA,gDAAgD;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AAKnE;;;;;;;;;GASG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAiB,EACjB,EAAkB,EAClB,OAAe;IAEf,OAAO;QACL,cAAc,EAAE,EAAE;QAClB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,iBAAiB,EAAE,EAAE,CAAC,aAAa;QACnC,eAAe,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,cAAc,CAAC,OAAiC,EAAE,IAAI,CAAC,MAAM,CAAC;QACpG,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;QAC7C,UAAU,EAAE,SAAS;QACrB,kBAAkB,EAAE,KAAK,EAAE,QAA+B,EAAE,EAAE;YAC5D,OAAO,IAAI,OAAO,CAA6B,CAAC,OAAO,EAAE,EAAE;gBACzD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAC9C,IAAI,KAAK,EAAE,CAAC;oBACV,0EAA0E;oBAC1E,6CAA6C;oBAC7C,KAAK,CAAC,oBAAoB,GAAG,CAAC,cAAsB,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;gBACvF,CAAC;gBACD,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,OAAO,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { MultiModelConfig } from '@zhixuan92/multi-model-agent-core';
|
|
2
|
+
import type { DiagnosticLogger } from '@zhixuan92/multi-model-agent-core';
|
|
3
|
+
import type { ProjectRegistry } from './project-registry.js';
|
|
4
|
+
import type { BatchRegistry } from '@zhixuan92/multi-model-agent-core';
|
|
5
|
+
/**
|
|
6
|
+
* Dependencies injected into every handler factory at server startup.
|
|
7
|
+
* Built once; passed to buildDelegateHandler, buildAuditHandler, etc.
|
|
8
|
+
*/
|
|
9
|
+
export interface HandlerDeps {
|
|
10
|
+
/** Full multi-model config (agents + defaults). May be undefined in unit tests. */
|
|
11
|
+
config: MultiModelConfig;
|
|
12
|
+
logger: DiagnosticLogger;
|
|
13
|
+
projectRegistry: ProjectRegistry;
|
|
14
|
+
batchRegistry: BatchRegistry;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=handler-deps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-deps.d.ts","sourceRoot":"","sources":["../../src/http/handler-deps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,mFAAmF;IACnF,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,gBAAgB,CAAC;IACzB,eAAe,EAAE,eAAe,CAAC;IACjC,aAAa,EAAE,aAAa,CAAC;CAC9B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-deps.js","sourceRoot":"","sources":["../../src/http/handler-deps.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { RawHandler } from '../../router.js';
|
|
2
|
+
import type { BatchRegistry } from '@zhixuan92/multi-model-agent-core';
|
|
3
|
+
export interface BatchHandlerDeps {
|
|
4
|
+
batchRegistry: BatchRegistry;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* GET /batch/:batchId — poll the current state of a batch.
|
|
8
|
+
* Optional ?taskIndex=N query param slices a single task result from a
|
|
9
|
+
* complete batch.
|
|
10
|
+
*
|
|
11
|
+
* State mapping:
|
|
12
|
+
* pending → 200 { state, startedAt }
|
|
13
|
+
* awaiting_clarification → 200 { state, proposedInterpretation }
|
|
14
|
+
* complete → 200 { state, result } (or sliced if taskIndex given)
|
|
15
|
+
* failed → 200 { state, error }
|
|
16
|
+
* expired → 200 { state: 'expired' }
|
|
17
|
+
*
|
|
18
|
+
* Errors:
|
|
19
|
+
* unknown batchId → 404 not_found
|
|
20
|
+
* non-numeric taskIndex → 400 invalid_task_index
|
|
21
|
+
* taskIndex ≥ results.len → 404 unknown_task_index
|
|
22
|
+
*/
|
|
23
|
+
export declare function buildBatchHandler(deps: BatchHandlerDeps): RawHandler;
|
|
24
|
+
//# sourceMappingURL=batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../../../src/http/handlers/control/batch.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,UAAU,CAiFpE"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { sendError, sendJson } from '../../errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* GET /batch/:batchId — poll the current state of a batch.
|
|
4
|
+
* Optional ?taskIndex=N query param slices a single task result from a
|
|
5
|
+
* complete batch.
|
|
6
|
+
*
|
|
7
|
+
* State mapping:
|
|
8
|
+
* pending → 200 { state, startedAt }
|
|
9
|
+
* awaiting_clarification → 200 { state, proposedInterpretation }
|
|
10
|
+
* complete → 200 { state, result } (or sliced if taskIndex given)
|
|
11
|
+
* failed → 200 { state, error }
|
|
12
|
+
* expired → 200 { state: 'expired' }
|
|
13
|
+
*
|
|
14
|
+
* Errors:
|
|
15
|
+
* unknown batchId → 404 not_found
|
|
16
|
+
* non-numeric taskIndex → 400 invalid_task_index
|
|
17
|
+
* taskIndex ≥ results.len → 404 unknown_task_index
|
|
18
|
+
*/
|
|
19
|
+
export function buildBatchHandler(deps) {
|
|
20
|
+
return async (_req, res, params, ctx) => {
|
|
21
|
+
const { batchId } = params;
|
|
22
|
+
// ── 1. Lookup ──────────────────────────────────────────────────────────
|
|
23
|
+
const entry = deps.batchRegistry.get(batchId);
|
|
24
|
+
if (!entry) {
|
|
25
|
+
sendError(res, 404, 'not_found', `Batch ${batchId} not found`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// ── 2. Parse optional taskIndex ────────────────────────────────────────
|
|
29
|
+
const rawTaskIndex = ctx.url.searchParams.get('taskIndex');
|
|
30
|
+
let taskIndex = null;
|
|
31
|
+
if (rawTaskIndex !== null) {
|
|
32
|
+
if (!/^\d+$/.test(rawTaskIndex)) {
|
|
33
|
+
sendError(res, 400, 'invalid_task_index', `taskIndex must be a non-negative integer; got: ${JSON.stringify(rawTaskIndex)}`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
taskIndex = parseInt(rawTaskIndex, 10);
|
|
37
|
+
}
|
|
38
|
+
// ── 3. State mapping ───────────────────────────────────────────────────
|
|
39
|
+
switch (entry.state) {
|
|
40
|
+
case 'pending':
|
|
41
|
+
sendJson(res, 200, { state: 'pending', startedAt: entry.startedAt });
|
|
42
|
+
return;
|
|
43
|
+
case 'awaiting_clarification':
|
|
44
|
+
sendJson(res, 200, {
|
|
45
|
+
state: 'awaiting_clarification',
|
|
46
|
+
proposedInterpretation: entry.proposedInterpretation,
|
|
47
|
+
});
|
|
48
|
+
return;
|
|
49
|
+
case 'complete': {
|
|
50
|
+
const fullResult = entry.result;
|
|
51
|
+
if (taskIndex !== null) {
|
|
52
|
+
const results = fullResult?.results;
|
|
53
|
+
if (!Array.isArray(results) || taskIndex >= results.length) {
|
|
54
|
+
sendError(res, 404, 'unknown_task_index', `taskIndex ${taskIndex} is out of range (batch has ${Array.isArray(results) ? results.length : 0} result(s))`);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Return the full result shape with only the sliced task
|
|
58
|
+
sendJson(res, 200, {
|
|
59
|
+
state: 'complete',
|
|
60
|
+
result: { ...fullResult, results: [results[taskIndex]] },
|
|
61
|
+
});
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
sendJson(res, 200, { state: 'complete', result: fullResult });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
case 'failed':
|
|
68
|
+
sendJson(res, 200, { state: 'failed', error: entry.error });
|
|
69
|
+
return;
|
|
70
|
+
case 'expired':
|
|
71
|
+
sendJson(res, 200, { state: 'expired' });
|
|
72
|
+
return;
|
|
73
|
+
default: {
|
|
74
|
+
// Exhaustiveness guard — should never happen
|
|
75
|
+
const _never = entry.state;
|
|
76
|
+
sendError(res, 500, 'internal_error', `Unexpected batch state: ${String(_never)}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../../../src/http/handlers/control/batch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { RawHandler } from '../../router.js';
|
|
2
|
+
import type { BatchRegistry } from '@zhixuan92/multi-model-agent-core';
|
|
3
|
+
export interface ClarificationsHandlerDeps {
|
|
4
|
+
batchRegistry: BatchRegistry;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* POST /clarifications/confirm — confirms (or idempotently re-confirms) an
|
|
8
|
+
* awaiting_clarification batch by providing the caller's chosen interpretation.
|
|
9
|
+
*
|
|
10
|
+
* Auth required; NOT cwd-gated (operates on a batchId, not a project cwd).
|
|
11
|
+
*
|
|
12
|
+
* Success → 200 { batchId, state: <current state after confirmation> }
|
|
13
|
+
* Errors:
|
|
14
|
+
* invalid body → 400 invalid_request
|
|
15
|
+
* unknown batchId → 404 not_found
|
|
16
|
+
* wrong state w/ different interpretation → 409 invalid_batch_state
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildClarificationsHandler(deps: ClarificationsHandlerDeps): RawHandler;
|
|
19
|
+
//# sourceMappingURL=clarifications.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clarifications.d.ts","sourceRoot":"","sources":["../../../../src/http/handlers/control/clarifications.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAEvE,MAAM,WAAW,yBAAyB;IACxC,aAAa,EAAE,aAAa,CAAC;CAC9B;AAOD;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,yBAAyB,GAAG,UAAU,CA8CtF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { InvalidBatchStateError } from '@zhixuan92/multi-model-agent-core';
|
|
3
|
+
import { sendError, sendJson } from '../../errors.js';
|
|
4
|
+
const confirmBodySchema = z.object({
|
|
5
|
+
batchId: z.string().uuid(),
|
|
6
|
+
interpretation: z.string().min(1),
|
|
7
|
+
});
|
|
8
|
+
/**
|
|
9
|
+
* POST /clarifications/confirm — confirms (or idempotently re-confirms) an
|
|
10
|
+
* awaiting_clarification batch by providing the caller's chosen interpretation.
|
|
11
|
+
*
|
|
12
|
+
* Auth required; NOT cwd-gated (operates on a batchId, not a project cwd).
|
|
13
|
+
*
|
|
14
|
+
* Success → 200 { batchId, state: <current state after confirmation> }
|
|
15
|
+
* Errors:
|
|
16
|
+
* invalid body → 400 invalid_request
|
|
17
|
+
* unknown batchId → 404 not_found
|
|
18
|
+
* wrong state w/ different interpretation → 409 invalid_batch_state
|
|
19
|
+
*/
|
|
20
|
+
export function buildClarificationsHandler(deps) {
|
|
21
|
+
return async (_req, res, _params, ctx) => {
|
|
22
|
+
// ── 1. Validate body ───────────────────────────────────────────────────
|
|
23
|
+
const parsed = confirmBodySchema.safeParse(ctx.body);
|
|
24
|
+
if (!parsed.success) {
|
|
25
|
+
sendError(res, 400, 'invalid_request', 'Request body validation failed', {
|
|
26
|
+
fieldErrors: parsed.error.flatten(),
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
const { batchId, interpretation } = parsed.data;
|
|
31
|
+
// ── 2. Lookup ──────────────────────────────────────────────────────────
|
|
32
|
+
const entry = deps.batchRegistry.get(batchId);
|
|
33
|
+
if (!entry) {
|
|
34
|
+
sendError(res, 404, 'not_found', `Batch ${batchId} not found`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
// ── 3. Resume (handles idempotency + state validation) ─────────────────
|
|
38
|
+
try {
|
|
39
|
+
deps.batchRegistry.resumeFromClarification(batchId, interpretation);
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
if (err instanceof InvalidBatchStateError) {
|
|
43
|
+
sendError(res, 409, 'invalid_batch_state', `Cannot confirm clarification: batch is in state '${err.currentState}'`, {
|
|
44
|
+
currentState: err.currentState,
|
|
45
|
+
});
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
throw err;
|
|
49
|
+
}
|
|
50
|
+
// ── 4. Echo current state ──────────────────────────────────────────────
|
|
51
|
+
// Re-read the entry after resumeFromClarification — the batch may have
|
|
52
|
+
// already completed if the executor was waiting.
|
|
53
|
+
const updatedEntry = deps.batchRegistry.get(batchId);
|
|
54
|
+
const currentState = updatedEntry?.state ?? 'pending';
|
|
55
|
+
sendJson(res, 200, { batchId, state: currentState });
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=clarifications.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clarifications.js","sourceRoot":"","sources":["../../../../src/http/handlers/control/clarifications.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAQtD,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;IAC1B,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAClC,CAAC,CAAC;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAA+B;IACxE,OAAO,KAAK,EACV,IAAqB,EACrB,GAAmB,EACnB,OAA+B,EAC/B,GAAG,EACH,EAAE;QACF,0EAA0E;QAC1E,MAAM,MAAM,GAAG,iBAAiB,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,iBAAiB,EAAE,gCAAgC,EAAE;gBACvE,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE;aACpC,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;QAEhD,0EAA0E;QAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,SAAS,OAAO,YAAY,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,IAAI,CAAC;YACH,IAAI,CAAC,aAAa,CAAC,uBAAuB,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QACtE,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,sBAAsB,EAAE,CAAC;gBAC1C,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,qBAAqB,EAAE,oDAAoD,GAAG,CAAC,YAAY,GAAG,EAAE;oBAClH,YAAY,EAAE,GAAG,CAAC,YAAY;iBAC/B,CAAC,CAAC;gBACH,OAAO;YACT,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,0EAA0E;QAC1E,uEAAuE;QACvE,iDAAiD;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,YAAY,GAAG,YAAY,EAAE,KAAK,IAAI,SAAS,CAAC;QAEtD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { RawHandler } from '../../router.js';
|
|
2
|
+
import type { ProjectRegistry } from '../../project-registry.js';
|
|
3
|
+
import type { ServerConfig } from '@zhixuan92/multi-model-agent-core';
|
|
4
|
+
export interface ContextBlockHandlerDeps {
|
|
5
|
+
projectRegistry: ProjectRegistry;
|
|
6
|
+
config: ServerConfig;
|
|
7
|
+
}
|
|
8
|
+
export interface DeleteContextBlockHandlerDeps {
|
|
9
|
+
projectRegistry: ProjectRegistry;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* POST /context-blocks — stores a new context block for the authenticated cwd.
|
|
13
|
+
* Requires cwd query param (cwd-gated).
|
|
14
|
+
*/
|
|
15
|
+
export declare function buildCreateContextBlockHandler(deps: ContextBlockHandlerDeps): RawHandler;
|
|
16
|
+
/**
|
|
17
|
+
* DELETE /context-blocks/:blockId — removes a context block belonging to the
|
|
18
|
+
* authenticated cwd. Returns 404 if the block does not exist or belongs to
|
|
19
|
+
* a different project (isolation).
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildDeleteContextBlockHandler(deps: DeleteContextBlockHandlerDeps): RawHandler;
|
|
22
|
+
//# sourceMappingURL=context-blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-blocks.d.ts","sourceRoot":"","sources":["../../../../src/http/handlers/control/context-blocks.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AAEtE,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,eAAe,CAAC;IACjC,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,6BAA6B;IAC5C,eAAe,EAAE,eAAe,CAAC;CAClC;AAOD;;;GAGG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,uBAAuB,GAAG,UAAU,CA4DxF;AAED;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,6BAA6B,GAAG,UAAU,CA0C9F"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { sendError, sendJson } from '../../errors.js';
|
|
3
|
+
const createBodySchema = z.object({
|
|
4
|
+
content: z.string().min(1),
|
|
5
|
+
ttlMs: z.number().int().positive().optional(),
|
|
6
|
+
});
|
|
7
|
+
/**
|
|
8
|
+
* POST /context-blocks — stores a new context block for the authenticated cwd.
|
|
9
|
+
* Requires cwd query param (cwd-gated).
|
|
10
|
+
*/
|
|
11
|
+
export function buildCreateContextBlockHandler(deps) {
|
|
12
|
+
return async (_req, res, _params, ctx) => {
|
|
13
|
+
const cwd = ctx.cwd;
|
|
14
|
+
// ── 1. Validate body ───────────────────────────────────────────────────
|
|
15
|
+
const parsed = createBodySchema.safeParse(ctx.body);
|
|
16
|
+
if (!parsed.success) {
|
|
17
|
+
sendError(res, 400, 'invalid_request', 'Request body validation failed', {
|
|
18
|
+
fieldErrors: parsed.error.flatten(),
|
|
19
|
+
});
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const { content } = parsed.data;
|
|
23
|
+
// ── 2. Content byte-size check ─────────────────────────────────────────
|
|
24
|
+
const byteLen = Buffer.byteLength(content, 'utf8');
|
|
25
|
+
const maxBytes = deps.config.server.limits.maxContextBlockBytes;
|
|
26
|
+
if (byteLen > maxBytes) {
|
|
27
|
+
sendError(res, 413, 'payload_too_large', `Context block content exceeds the ${maxBytes}-byte limit (got ${byteLen} bytes)`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// ── 3. Get project context ─────────────────────────────────────────────
|
|
31
|
+
const reserveResult = deps.projectRegistry.reserveProject(cwd);
|
|
32
|
+
if (!reserveResult.ok) {
|
|
33
|
+
sendError(res, 503, reserveResult.error, reserveResult.message);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const pc = reserveResult.projectContext;
|
|
37
|
+
pc.lastActivityAt = Date.now();
|
|
38
|
+
deps.projectRegistry.cancelReservation(cwd);
|
|
39
|
+
// ── 4. Cap check ───────────────────────────────────────────────────────
|
|
40
|
+
const maxBlocks = deps.config.server.limits.maxContextBlocksPerProject;
|
|
41
|
+
if (pc.contextBlocks.size >= maxBlocks) {
|
|
42
|
+
sendError(res, 409, 'cap_exhausted', `Project context block cap of ${maxBlocks} reached; delete unused blocks before creating new ones`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// ── 5. Create block ────────────────────────────────────────────────────
|
|
46
|
+
const registered = pc.contextBlocks.register(content);
|
|
47
|
+
sendJson(res, 201, { id: registered.id });
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* DELETE /context-blocks/:blockId — removes a context block belonging to the
|
|
52
|
+
* authenticated cwd. Returns 404 if the block does not exist or belongs to
|
|
53
|
+
* a different project (isolation).
|
|
54
|
+
*/
|
|
55
|
+
export function buildDeleteContextBlockHandler(deps) {
|
|
56
|
+
return async (_req, res, params, ctx) => {
|
|
57
|
+
const cwd = ctx.cwd;
|
|
58
|
+
const { blockId } = params;
|
|
59
|
+
// ── 1. Get project context ─────────────────────────────────────────────
|
|
60
|
+
// Look up without reserving — we need to check if the project exists at all
|
|
61
|
+
const pc = deps.projectRegistry.get(cwd);
|
|
62
|
+
if (!pc) {
|
|
63
|
+
// Project doesn't exist — no blocks can belong to it
|
|
64
|
+
sendError(res, 404, 'not_found', `Context block ${blockId} not found`);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
// ── 2. Existence + isolation check ─────────────────────────────────────
|
|
68
|
+
// Since contextBlocks is per-project, any block in pc.contextBlocks belongs
|
|
69
|
+
// to this cwd. If the id isn't in this store, it either doesn't exist or
|
|
70
|
+
// belongs to a different project — both map to 404.
|
|
71
|
+
const content = pc.contextBlocks.get(blockId);
|
|
72
|
+
if (content === undefined) {
|
|
73
|
+
sendError(res, 404, 'not_found', `Context block ${blockId} not found`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// ── 3. Pin check ───────────────────────────────────────────────────────
|
|
77
|
+
const refcount = pc.contextBlocks.refcount(blockId);
|
|
78
|
+
if (refcount > 0) {
|
|
79
|
+
sendError(res, 409, 'pinned', `Context block ${blockId} is in use by ${refcount} active batch(es)`, { refcount });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// ── 4. Delete ──────────────────────────────────────────────────────────
|
|
83
|
+
pc.contextBlocks.delete(blockId);
|
|
84
|
+
pc.lastActivityAt = Date.now();
|
|
85
|
+
sendJson(res, 200, { ok: true });
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=context-blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-blocks.js","sourceRoot":"","sources":["../../../../src/http/handlers/control/context-blocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RawHandler } from '../../router.js';
|
|
2
|
+
/**
|
|
3
|
+
* GET /health — lightweight liveness probe.
|
|
4
|
+
*
|
|
5
|
+
* This is the only unauthenticated route. It intentionally returns only
|
|
6
|
+
* `{ ok: true }` — no counters, no project data. Richer operator data
|
|
7
|
+
* lives on GET /status.
|
|
8
|
+
*
|
|
9
|
+
* Loopback guard is applied by the server pipeline before the handler
|
|
10
|
+
* is invoked (see LOOPBACK_ONLY_PATHS in server.ts).
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildHealthHandler(): RawHandler;
|
|
13
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../../../src/http/handlers/introspection/health.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,CAI/C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { sendJson } from '../../errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* GET /health — lightweight liveness probe.
|
|
4
|
+
*
|
|
5
|
+
* This is the only unauthenticated route. It intentionally returns only
|
|
6
|
+
* `{ ok: true }` — no counters, no project data. Richer operator data
|
|
7
|
+
* lives on GET /status.
|
|
8
|
+
*
|
|
9
|
+
* Loopback guard is applied by the server pipeline before the handler
|
|
10
|
+
* is invoked (see LOOPBACK_ONLY_PATHS in server.ts).
|
|
11
|
+
*/
|
|
12
|
+
export function buildHealthHandler() {
|
|
13
|
+
return (_req, res) => {
|
|
14
|
+
sendJson(res, 200, { ok: true });
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.js","sourceRoot":"","sources":["../../../../src/http/handlers/introspection/health.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,IAAqB,EAAE,GAAmB,EAAE,EAAE;QACpD,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC,CAAC;AACJ,CAAC"}
|