@sema-agent/server 7.79.2 → 7.80.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.
Files changed (104) hide show
  1. package/dist/boot/late-binds.d.ts +35 -0
  2. package/dist/boot/late-binds.js +20 -0
  3. package/dist/boot/stage-01-config.d.ts +7 -0
  4. package/dist/boot/stage-01-config.js +60 -0
  5. package/dist/boot/stage-02-registry-pull.d.ts +10 -0
  6. package/dist/boot/stage-02-registry-pull.js +11 -0
  7. package/dist/boot/stage-03-store-backend.d.ts +32 -0
  8. package/dist/boot/stage-03-store-backend.js +11 -0
  9. package/dist/boot/stage-04-stores.d.ts +69 -0
  10. package/dist/boot/stage-04-stores.js +49 -0
  11. package/dist/boot/stage-05-execution-env.d.ts +82 -0
  12. package/dist/boot/stage-05-execution-env.js +20 -0
  13. package/dist/boot/stage-06-runners.d.ts +143 -0
  14. package/dist/boot/stage-06-runners.js +207 -0
  15. package/dist/boot/stage-07-capability-layer.d.ts +157 -0
  16. package/dist/boot/stage-07-capability-layer.js +162 -0
  17. package/dist/boot/stage-08-reapers.d.ts +172 -0
  18. package/dist/boot/stage-08-reapers.js +78 -0
  19. package/dist/boot/stage-09-leader.d.ts +204 -0
  20. package/dist/boot/stage-09-leader.js +47 -0
  21. package/dist/boot/stage-10-http-server.d.ts +204 -0
  22. package/dist/boot/stage-10-http-server.js +289 -0
  23. package/dist/config-invariants.d.ts +9 -0
  24. package/dist/config-invariants.js +7 -1
  25. package/dist/config-types.d.ts +1 -1
  26. package/dist/http/dispatch.js +28 -8
  27. package/dist/http/route-ctx.d.ts +101 -4
  28. package/dist/http/route-ctx.js +4 -0
  29. package/dist/http/route-table.d.ts +71 -43
  30. package/dist/http/route-table.js +111 -187
  31. package/dist/http/routes/a2a-serve.d.ts +18 -3
  32. package/dist/http/routes/a2a-serve.js +25 -23
  33. package/dist/http/routes/admin-config-refresh.d.ts +9 -2
  34. package/dist/http/routes/admin-config-refresh.js +32 -31
  35. package/dist/http/routes/admin-drain.d.ts +9 -2
  36. package/dist/http/routes/admin-drain.js +32 -31
  37. package/dist/http/routes/admin-memory-optout.d.ts +28 -2
  38. package/dist/http/routes/admin-memory-optout.js +26 -39
  39. package/dist/http/routes/adoption.d.ts +15 -2
  40. package/dist/http/routes/adoption.js +52 -52
  41. package/dist/http/routes/agents-roster.d.ts +9 -2
  42. package/dist/http/routes/agents-roster.js +82 -80
  43. package/dist/http/routes/approvals-assistant.d.ts +58 -5
  44. package/dist/http/routes/approvals-assistant.js +37 -38
  45. package/dist/http/routes/attachments.d.ts +22 -2
  46. package/dist/http/routes/attachments.js +81 -72
  47. package/dist/http/routes/capabilities.d.ts +21 -2
  48. package/dist/http/routes/capabilities.js +174 -170
  49. package/dist/http/routes/config-catalog.d.ts +9 -2
  50. package/dist/http/routes/config-catalog.js +28 -31
  51. package/dist/http/routes/devices.d.ts +24 -2
  52. package/dist/http/routes/devices.js +19 -21
  53. package/dist/http/routes/diagnostics.d.ts +9 -2
  54. package/dist/http/routes/diagnostics.js +41 -43
  55. package/dist/http/routes/fleet.d.ts +11 -2
  56. package/dist/http/routes/fleet.js +23 -22
  57. package/dist/http/routes/images.d.ts +63 -9
  58. package/dist/http/routes/images.js +53 -46
  59. package/dist/http/routes/leader.d.ts +20 -2
  60. package/dist/http/routes/leader.js +43 -40
  61. package/dist/http/routes/memory-bundle.d.ts +15 -2
  62. package/dist/http/routes/memory-bundle.js +38 -38
  63. package/dist/http/routes/memory-compliance.d.ts +16 -4
  64. package/dist/http/routes/memory-compliance.js +44 -45
  65. package/dist/http/routes/memory-consolidation.d.ts +14 -2
  66. package/dist/http/routes/memory-consolidation.js +66 -66
  67. package/dist/http/routes/memory-origin.d.ts +23 -4
  68. package/dist/http/routes/memory-origin.js +65 -65
  69. package/dist/http/routes/memory-policy.d.ts +21 -2
  70. package/dist/http/routes/memory-policy.js +119 -115
  71. package/dist/http/routes/notify-wake.d.ts +21 -11
  72. package/dist/http/routes/notify-wake.js +118 -116
  73. package/dist/http/routes/observability.d.ts +16 -2
  74. package/dist/http/routes/observability.js +54 -51
  75. package/dist/http/routes/retention-ops.d.ts +19 -2
  76. package/dist/http/routes/retention-ops.js +20 -22
  77. package/dist/http/routes/rules.d.ts +36 -2
  78. package/dist/http/routes/rules.js +22 -24
  79. package/dist/http/routes/run-memory-capture.d.ts +10 -3
  80. package/dist/http/routes/run-memory-capture.js +84 -84
  81. package/dist/http/routes/runs.d.ts +102 -22
  82. package/dist/http/routes/runs.js +71 -88
  83. package/dist/http/routes/session-sync.d.ts +41 -2
  84. package/dist/http/routes/session-sync.js +25 -23
  85. package/dist/http/routes/sessions-list.d.ts +16 -2
  86. package/dist/http/routes/sessions-list.js +78 -75
  87. package/dist/http/routes/sessions.d.ts +77 -2
  88. package/dist/http/routes/sessions.js +50 -47
  89. package/dist/http/routes/shared-memory.d.ts +19 -2
  90. package/dist/http/routes/shared-memory.js +65 -63
  91. package/dist/http/routes/side-query.d.ts +11 -2
  92. package/dist/http/routes/side-query.js +81 -79
  93. package/dist/http/routes/tasks.d.ts +17 -2
  94. package/dist/http/routes/tasks.js +18 -11
  95. package/dist/http/routes/trace-usage.d.ts +40 -2
  96. package/dist/http/routes/trace-usage.js +46 -35
  97. package/dist/http/routes/workflows.d.ts +35 -3
  98. package/dist/http/routes/workflows.js +29 -29
  99. package/dist/main.js +20 -870
  100. package/dist/service-version.d.ts +5 -0
  101. package/dist/service-version.js +12 -0
  102. package/dist/trace/redact.d.ts +7 -6
  103. package/dist/trace/redact.js +419 -229
  104. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { sendJson, sendError, httpErrorCode } from "../send.js";
3
3
  import { gatedPrincipal, explicitOperatorOk } from "../principal-gate.js";
4
+ import { assertNever } from "../route-ctx.js";
4
5
  import { createLogger } from "../../observability/logger.js";
5
6
  import { RULE_IMPORT_RETRY_AFTER_SEC, MAX_RULE_SCOPE_CHARS, parseRuleScope, serializeRuleScope } from "../../rules-consent.js";
6
7
  import { CONTROL_AND_BIDI_CHARS } from "../../text-bidi.js";
@@ -82,24 +83,9 @@ function decodeRulesCursor(raw) {
82
83
  }
83
84
  }
84
85
  const rowKey = (r) => `${r.scope}\u0000${r.rule}\u0000${r.behavior}`;
85
- export async function handleRules(req, res, url, ctx) {
86
- const miss = { fell: false };
87
- await handleRulesBody(req, res, url, ctx, miss);
88
- return !miss.fell;
89
- }
90
- async function handleRulesBody(req, res, url, ctx, miss) {
86
+ export async function handleRules(req, res, match, ctx) {
91
87
  const { deps } = ctx;
92
88
  const { readJson, rateLimited } = ctx.helpers;
93
- const isPrepare = req.method === "POST" && url === RULES_CC_IMPORT_PREPARE_PATH;
94
- const isRedeem = req.method === "POST" && url === RULES_CC_IMPORT_REDEEM_PATH;
95
- const isLocalPrepare = req.method === "POST" && url === RULES_LOCAL_IMPORT_PREPARE_PATH;
96
- const isLocalRedeem = req.method === "POST" && url === RULES_LOCAL_IMPORT_REDEEM_PATH;
97
- const isList = req.method === "GET" && url === RULES_PATH;
98
- const isRevoke = req.method === "DELETE" && url === RULES_PATH;
99
- if (!isPrepare && !isRedeem && !isList && !isRevoke && !isLocalPrepare && !isLocalRedeem) {
100
- miss.fell = true;
101
- return;
102
- }
103
89
  if (rateLimited(req, res))
104
90
  return;
105
91
  const principal = gatedPrincipal(req, deps.config);
@@ -112,8 +98,8 @@ async function handleRulesBody(req, res, url, ctx, miss) {
112
98
  sendError(res, 501, "capability.rule_store_required", "this deployment has no permission-rule store wired");
113
99
  return;
114
100
  }
115
- if (isList) {
116
- await handleRuleList(req, res, principal, lane, deps.config.operatorPrincipals);
101
+ if (match.decl.id === "rules-list") {
102
+ await handleRuleList(res, match.search, principal, lane, deps.config.operatorPrincipals);
117
103
  return;
118
104
  }
119
105
  let rawBody;
@@ -128,11 +114,11 @@ async function handleRulesBody(req, res, url, ctx, miss) {
128
114
  sendError(res, 400, "request.body_shape", "body must be valid JSON");
129
115
  return;
130
116
  }
131
- if (isRevoke) {
117
+ if (match.decl.id === "rules-revoke") {
132
118
  await handleRuleRevoke(res, rawBody, principal, lane, deps.config.operatorPrincipals);
133
119
  return;
134
120
  }
135
- if (isLocalPrepare) {
121
+ if (match.decl.id === "rules-local-import-prepare") {
136
122
  const parsed = LocalImportPrepareBodySchema.safeParse(rawBody);
137
123
  if (!parsed.success) {
138
124
  sendError(res, 400, "request.body_shape", "body must be {rows:[{behavior,rule,scope,tool,match,command,adds}]}");
@@ -147,7 +133,7 @@ async function handleRulesBody(req, res, url, ctx, miss) {
147
133
  sendJson(res, 200, { preview: prepared.preview, ...(prepared.ticket !== undefined ? { ticket: prepared.ticket, expiresAtMs: prepared.expiresAtMs } : {}) });
148
134
  return;
149
135
  }
150
- if (isLocalRedeem) {
136
+ if (match.decl.id === "rules-local-import-redeem") {
151
137
  const parsed = LocalImportRedeemBodySchema.safeParse(rawBody);
152
138
  if (!parsed.success) {
153
139
  sendError(res, 400, "request.body_shape", "body must be {ticket}");
@@ -172,7 +158,7 @@ async function handleRulesBody(req, res, url, ctx, miss) {
172
158
  sendError(res, 404, "not_found.rule_ticket", "no such import ticket");
173
159
  return;
174
160
  }
175
- if (isPrepare) {
161
+ if (match.decl.id === "rules-cc-import-prepare") {
176
162
  const parsed = CcImportPrepareBodySchema.safeParse(rawBody);
177
163
  if (!parsed.success) {
178
164
  sendError(res, 400, "request.body_shape", "body must be {layers:[{layer,path,root,content}]}");
@@ -186,6 +172,8 @@ async function handleRulesBody(req, res, url, ctx, miss) {
186
172
  sendJson(res, 200, { preview: prepared.preview, ...(prepared.ticket !== undefined ? { ticket: prepared.ticket, expiresAtMs: prepared.expiresAtMs } : {}) });
187
173
  return;
188
174
  }
175
+ if (match.decl.id !== "rules-cc-import-redeem")
176
+ return assertNever(match.decl.id);
189
177
  const parsed = CcImportRedeemBodySchema.safeParse(rawBody);
190
178
  if (!parsed.success) {
191
179
  sendError(res, 400, "request.body_shape", "body must be {ticket}");
@@ -216,8 +204,8 @@ function resolveTargetPrincipal(requested, caller, operatorPrincipals) {
216
204
  return { ok: false };
217
205
  return { ok: true, principal: requested };
218
206
  }
219
- async function handleRuleList(req, res, caller, lane, operatorPrincipals) {
220
- const q = new URL(req.url ?? "/", "http://localhost").searchParams;
207
+ async function handleRuleList(res, search, caller, lane, operatorPrincipals) {
208
+ const q = new URLSearchParams(search);
221
209
  const target = resolveTargetPrincipal(q.get("principal") ?? undefined, caller, operatorPrincipals);
222
210
  if (!target.ok) {
223
211
  sendError(res, 403, "auth.operator_only", "reading another principal's rules is an operator-only action");
@@ -286,4 +274,14 @@ async function handleRuleRevoke(res, rawBody, caller, lane, operatorPrincipals)
286
274
  return;
287
275
  }
288
276
  }
277
+ export const RULES_ROUTES = [
278
+ { id: "rules-cc-import-prepare", path: RULES_CC_IMPORT_PREPARE_PATH, methods: ["POST"] },
279
+ { id: "rules-cc-import-redeem", path: RULES_CC_IMPORT_REDEEM_PATH, methods: ["POST"] },
280
+ { id: "rules-local-import-prepare", path: RULES_LOCAL_IMPORT_PREPARE_PATH, methods: ["POST"] },
281
+ { id: "rules-local-import-redeem", path: RULES_LOCAL_IMPORT_REDEEM_PATH, methods: ["POST"] },
282
+ { id: "rules-list", path: RULES_PATH, methods: ["GET"] },
283
+ { id: "rules-revoke", path: RULES_PATH, credentialGated: ["DELETE"], methods: ["DELETE"] },
284
+ { prefix: "/v1/rules/cc-import/", credentialGated: ["POST"] },
285
+ { prefix: "/v1/rules/local-import/", credentialGated: ["POST"] },
286
+ ];
289
287
  //# sourceMappingURL=rules.js.map
@@ -28,7 +28,14 @@
28
28
  * `sessionBackgroundable` 同谓词):老 worker 键缺席 ⇒ 壳不渲入口(假 affordance 纪律)。
29
29
  */
30
30
  import type { IncomingMessage, ServerResponse } from "node:http";
31
- import { type RouteCtx } from "../route-ctx.js";
32
- export declare const RUN_MEMORY_CAPTURE_OPTOUT_RE: RegExp;
33
- export declare function handleRunMemoryCapture(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
31
+ import { type RouteCtx, type RouteMatch, type RouteIdsOf } from "../route-ctx.js";
32
+ export declare function handleRunMemoryCapture(req: IncomingMessage, res: ServerResponse, match: RouteMatch<RunMemoryCaptureRouteId>, ctx: RouteCtx): Promise<void>;
33
+ export declare const RUN_MEMORY_CAPTURE_ROUTES: readonly [{
34
+ readonly id: "run-memory-capture-optout";
35
+ readonly pattern: RegExp;
36
+ readonly label: "/v1/runs/:id/memory/capture-optout";
37
+ readonly methods: readonly ["POST"];
38
+ }];
39
+ /** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽(漏一口 = 编译红)。 */
40
+ export type RunMemoryCaptureRouteId = RouteIdsOf<typeof RUN_MEMORY_CAPTURE_ROUTES>;
34
41
  //# sourceMappingURL=run-memory-capture.d.ts.map
@@ -3,95 +3,95 @@ import { isParkedRunStatus, isTerminalRunStatus } from "../../plugins/store-cont
3
3
  import { sendJson, sendError } from "../send.js";
4
4
  import { gatedPrincipal, sendPrincipalRefusal } from "../principal-gate.js";
5
5
  import { RUN_NOT_FOUND_MESSAGE, runNotFoundMessage } from "../route-ctx.js";
6
- export const RUN_MEMORY_CAPTURE_OPTOUT_RE = /^\/v1\/runs\/([^/]+)\/memory\/capture-optout$/;
6
+ import { assertNever } from "../route-ctx.js";
7
7
  const BodySchema = z.object({ reason: z.string().min(1).max(500).optional() }).strict();
8
- export async function handleRunMemoryCapture(req, res, url, ctx) {
9
- const miss = { fell: false };
10
- await handleBody(req, res, url, ctx, miss);
11
- return !miss.fell;
12
- }
13
- async function handleBody(req, res, url, ctx, miss) {
8
+ export async function handleRunMemoryCapture(req, res, match, ctx) {
14
9
  const { deps } = ctx;
15
- const m = req.method === "POST" ? RUN_MEMORY_CAPTURE_OPTOUT_RE.exec(url) : null;
16
- if (m === null) {
17
- miss.fell = true;
18
- return;
19
- }
20
- if (ctx.helpers.rateLimited(req, res))
21
- return;
22
- if (!deps.runStore) {
23
- sendError(res, 501, "capability.run_store_required", "async runs require a durable run store (DB_BACKEND=mysql|pg|local)");
24
- return;
25
- }
26
- const principal = gatedPrincipal(req, deps.config);
27
- if (deps.config.requirePrincipal && principal === undefined) {
28
- sendPrincipalRefusal(res, req, deps.config);
29
- return;
30
- }
31
- const taskId = m[1];
32
- const parsed = BodySchema.safeParse((await ctx.helpers.readJson(req)) ?? {});
33
- if (!parsed.success) {
34
- sendError(res, 400, "request.body_shape", "body must be {} or { reason: string (non-empty, at most 500 chars) } — the session memory-capture opt-out verb takes no other keys");
35
- return;
36
- }
37
- const run = await deps.runStore.getRun(taskId);
38
- if (!run) {
39
- sendError(res, 404, "not_found.run", runNotFoundMessage(taskId));
40
- return;
41
- }
42
- if (run.owner !== null && run.owner !== principal) {
43
- sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
44
- return;
45
- }
46
- const live = ctx.registry.steerableRuns.get(taskId);
47
- if (live) {
48
- try {
49
- const { outcome } = await live.optOutMemoryCapture(parsed.data.reason !== undefined ? { reason: parsed.data.reason } : {});
50
- sendJson(res, 200, { taskId, sessionId: run.sessionId, outcome });
51
- return;
52
- }
53
- catch (e) {
54
- const code = e.code;
55
- const msg = e instanceof Error ? e.message : String(e);
56
- switch (code) {
57
- case "memory.capture_optout_denied":
58
- sendError(res, 403, "memory.capture_optout_denied", msg);
59
- return;
60
- case "memory.capture_optout_unpersisted":
61
- sendError(res, 503, "memory.capture_optout_unpersisted", msg);
62
- return;
63
- case "memory.capture_optout_unavailable":
64
- sendError(res, 409, "memory.capture_optout_unavailable", msg);
65
- return;
66
- case "memory.capture_optout_sweep_failed":
67
- sendError(res, 409, "memory.capture_optout_sweep_failed", msg);
68
- return;
69
- case "config.memory_capture_unsupported":
70
- sendError(res, 409, "config.memory_capture_unsupported", msg);
71
- return;
72
- case "steering.invalid_content":
73
- sendError(res, 422, "steering.invalid_content", msg);
74
- return;
75
- case "steering.not_running":
76
- sendError(res, 409, "steering.not_running", "run just finished — the memory-capture opt-out verb needs a live run; declare it on the next submit instead (memoryCapture: 'off')");
10
+ switch (match.decl.id) {
11
+ case "run-memory-capture-optout": {
12
+ if (ctx.helpers.rateLimited(req, res))
13
+ return;
14
+ if (!deps.runStore) {
15
+ sendError(res, 501, "capability.run_store_required", "async runs require a durable run store (DB_BACKEND=mysql|pg|local)");
16
+ return;
17
+ }
18
+ const principal = gatedPrincipal(req, deps.config);
19
+ if (deps.config.requirePrincipal && principal === undefined) {
20
+ sendPrincipalRefusal(res, req, deps.config);
21
+ return;
22
+ }
23
+ const taskId = match.params.taskId;
24
+ const parsed = BodySchema.safeParse((await ctx.helpers.readJson(req)) ?? {});
25
+ if (!parsed.success) {
26
+ sendError(res, 400, "request.body_shape", "body must be {} or { reason: string (non-empty, at most 500 chars) } — the session memory-capture opt-out verb takes no other keys");
27
+ return;
28
+ }
29
+ const run = await deps.runStore.getRun(taskId);
30
+ if (!run) {
31
+ sendError(res, 404, "not_found.run", runNotFoundMessage(taskId));
32
+ return;
33
+ }
34
+ if (run.owner !== null && run.owner !== principal) {
35
+ sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
36
+ return;
37
+ }
38
+ const live = ctx.registry.steerableRuns.get(taskId);
39
+ if (live) {
40
+ try {
41
+ const { outcome } = await live.optOutMemoryCapture(parsed.data.reason !== undefined ? { reason: parsed.data.reason } : {});
42
+ sendJson(res, 200, { taskId, sessionId: run.sessionId, outcome });
77
43
  return;
78
- default: throw e;
44
+ }
45
+ catch (e) {
46
+ const code = e.code;
47
+ const msg = e instanceof Error ? e.message : String(e);
48
+ switch (code) {
49
+ case "memory.capture_optout_denied":
50
+ sendError(res, 403, "memory.capture_optout_denied", msg);
51
+ return;
52
+ case "memory.capture_optout_unpersisted":
53
+ sendError(res, 503, "memory.capture_optout_unpersisted", msg);
54
+ return;
55
+ case "memory.capture_optout_unavailable":
56
+ sendError(res, 409, "memory.capture_optout_unavailable", msg);
57
+ return;
58
+ case "memory.capture_optout_sweep_failed":
59
+ sendError(res, 409, "memory.capture_optout_sweep_failed", msg);
60
+ return;
61
+ case "config.memory_capture_unsupported":
62
+ sendError(res, 409, "config.memory_capture_unsupported", msg);
63
+ return;
64
+ case "steering.invalid_content":
65
+ sendError(res, 422, "steering.invalid_content", msg);
66
+ return;
67
+ case "steering.not_running":
68
+ sendError(res, 409, "steering.not_running", "run just finished — the memory-capture opt-out verb needs a live run; declare it on the next submit instead (memoryCapture: 'off')");
69
+ return;
70
+ default: throw e;
71
+ }
72
+ }
73
+ }
74
+ if (isParkedRunStatus(run.status)) {
75
+ sendError(res, 409, "steering.not_running", "run is parked on a pending decision — the memory-capture opt-out verb needs a live turn, and a resumed continuation rebuilds its spec from the persisted body (it cannot take a new declaration); the opt-out becomes effective on this session's next NEW submit (POST /v1/tasks with this sessionId and memoryCapture: 'off') — content captured until then stays captured");
76
+ return;
79
77
  }
78
+ if (isTerminalRunStatus(run.status)) {
79
+ sendError(res, 409, "steering.not_running", "run already ended — the memory-capture opt-out verb needs a live run; submit the next turn of this session with memoryCapture: 'off' (the declaration writes the same one-way session record)");
80
+ return;
81
+ }
82
+ const provenElsewhere = typeof run.instanceId === "string" && run.instanceId.length > 0 && deps.instanceId !== undefined && run.instanceId !== deps.instanceId;
83
+ if (provenElsewhere) {
84
+ sendError(res, 409, "steering.not_running", "run is live on another replica — the memory-capture opt-out verb must reach the replica holding the stream; resend it there, or declare memoryCapture: 'off' on the next submit");
85
+ return;
86
+ }
87
+ sendError(res, 409, "steering.not_running", "no live steerable face for this run on this replica — verify/cascade execution lanes expose none; declare memoryCapture: 'off' on the next submit of this session instead");
88
+ return;
80
89
  }
90
+ default:
91
+ return assertNever(match.decl.id);
81
92
  }
82
- if (isParkedRunStatus(run.status)) {
83
- sendError(res, 409, "steering.not_running", "run is parked on a pending decision — the memory-capture opt-out verb needs a live turn, and a resumed continuation rebuilds its spec from the persisted body (it cannot take a new declaration); the opt-out becomes effective on this session's next NEW submit (POST /v1/tasks with this sessionId and memoryCapture: 'off') — content captured until then stays captured");
84
- return;
85
- }
86
- if (isTerminalRunStatus(run.status)) {
87
- sendError(res, 409, "steering.not_running", "run already ended — the memory-capture opt-out verb needs a live run; submit the next turn of this session with memoryCapture: 'off' (the declaration writes the same one-way session record)");
88
- return;
89
- }
90
- const provenElsewhere = typeof run.instanceId === "string" && run.instanceId.length > 0 && deps.instanceId !== undefined && run.instanceId !== deps.instanceId;
91
- if (provenElsewhere) {
92
- sendError(res, 409, "steering.not_running", "run is live on another replica — the memory-capture opt-out verb must reach the replica holding the stream; resend it there, or declare memoryCapture: 'off' on the next submit");
93
- return;
94
- }
95
- sendError(res, 409, "steering.not_running", "no live steerable face for this run on this replica — verify/cascade execution lanes expose none; declare memoryCapture: 'off' on the next submit of this session instead");
96
93
  }
94
+ export const RUN_MEMORY_CAPTURE_ROUTES = [
95
+ { id: "run-memory-capture-optout", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/memory\/capture-optout$/, label: "/v1/runs/:id/memory/capture-optout", methods: ["POST"] },
96
+ ];
97
97
  //# sourceMappingURL=run-memory-capture.js.map
@@ -1,33 +1,17 @@
1
1
  import type { IncomingMessage, ServerResponse } from "node:http";
2
2
  import { ActorAssertionWire } from "@sema-agent/settings-schema";
3
- import type { RouteCtx, PreparedTaskSubmission } from "../route-ctx.js";
4
- export declare const RUN_ID_RE: RegExp;
5
- export declare const RUN_CANCEL_RE: RegExp;
6
- export declare const RUN_STEER_RE: RegExp;
7
- export declare const RUN_DETACH_RE: RegExp;
8
- export declare const RUN_COMPACT_RE: RegExp;
9
- export declare const RUN_INTERRUPT_RE: RegExp;
10
- /** PAIR-REVIEW F-10:runs 面 404 文案统一富形——a\* 形 id(background-agent registry 句柄,`a`+hex 短形)
11
- * 是「结构性不在 run 店」的常客([ref]⑤ 记档裁量:不改路由,只给引导)。识别句法形即补引导;
12
- * 非 a\* 形保通用富文案(cancel 腿 [ref]① 同款)。 */
13
- export declare const ELICIT_RESPOND_RE: RegExp;
14
- export declare const QUESTION_RESPOND_RE: RegExp;
15
- export declare const TOOL_APPROVAL_RESPOND_RE: RegExp;
16
- export declare const TASK_ASK_DECISION_RE: RegExp;
3
+ import type { RouteCtx, PreparedTaskSubmission, RouteMatch, RouteIdsOf } from "../route-ctx.js";
17
4
  /** 行上的 `decision_actor`(裸 JSON)投成回显形;形不认 ⇒ undefined(调用点省略该键,不 500)。
18
5
  * 导出仅为契约门(`test/ask-decision-actor-contract.test.ts` 钉「键集同源包版 + 严格度刻意宽读」两条)
19
6
  * —— 导出的是**行为**而不是 schema 对象:schema 的推断类型会牵出 registry-core 内嵌的 zod 路径
20
7
  * (TS2742,不可移植),而这道门要钉的本来就是行为。非 wire 面。 */
21
8
  export declare function projectDecisionActor(raw: unknown): ActorAssertionWire | undefined;
22
- export declare const RUN_SUBAGENT_STEER_RE: RegExp;
23
- export declare const RUN_SUBAGENT_RESUME_RE: RegExp;
24
- export declare const RUN_SUBAGENT_OUTPUT_RE: RegExp;
25
- export declare const RUN_SUBAGENT_STREAM_RE: RegExp;
26
- export declare const RUN_TASK_OUTPUT_RE: RegExp;
27
- export declare const RUN_TASK_STOP_RE: RegExp;
28
- export declare function handleRuns(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
29
9
  /** 子代理 / 任务句柄 / HITL 应答段——`handle()` 里它在 SVC-5 workflow steer **之后**,故是独立的域入口。 */
30
- export declare function handleRunVerbs(req: IncomingMessage, res: ServerResponse, url: string, ctx: RouteCtx): Promise<boolean>;
10
+ /** 路由体 = 从 `server.ts` 的 `handle()` 里**整段剪切**过来的原文(唯一改动:统一去缩进两格)。裸 `return;`
11
+ * = 「本域已应答」;走到函数尾才是「没匹配上」。跨域的东西一律在首行解构出来。 */
12
+ export declare function handleRuns(req: IncomingMessage, res: ServerResponse, match: RouteMatch<RunsRouteId>, ctx: RouteCtx): Promise<void>;
13
+ /** 同上纪律(子代理 / 任务句柄 / HITL 应答段)。 */
14
+ export declare function handleRunVerbs(req: IncomingMessage, res: ServerResponse, match: RouteMatch<RunVerbsRouteId>, ctx: RouteCtx): Promise<void>;
31
15
  /**
32
16
  * DESIGN-269 车2 件2 —— `POST /v1/runs` 的**建行 + 驱动**段,从路由体里原样搬出来的具名腿。
33
17
  *
@@ -54,4 +38,100 @@ idemKey: string | undefined): Promise<{
54
38
  status: number;
55
39
  body: unknown;
56
40
  } | null>;
41
+ export declare const RUNS_ROUTES: readonly [{
42
+ readonly id: "runs-submit";
43
+ readonly path: "/v1/runs";
44
+ readonly billable: true;
45
+ readonly methods: readonly ["POST"];
46
+ }, {
47
+ readonly id: "run-steer";
48
+ readonly pattern: RegExp;
49
+ readonly label: "/v1/runs/:id/steer";
50
+ readonly methods: readonly ["POST"];
51
+ }, {
52
+ readonly id: "run-interrupt";
53
+ readonly pattern: RegExp;
54
+ readonly label: "/v1/runs/:id/interrupt";
55
+ readonly methods: readonly ["POST"];
56
+ }, {
57
+ readonly id: "run-detach";
58
+ readonly pattern: RegExp;
59
+ readonly label: "/v1/runs/:id/detach";
60
+ readonly methods: readonly ["POST"];
61
+ }, {
62
+ readonly id: "run-cancel";
63
+ readonly pattern: RegExp;
64
+ readonly label: "/v1/runs/:id/cancel";
65
+ readonly methods: readonly ["POST"];
66
+ }, {
67
+ readonly id: "run-compact";
68
+ readonly pattern: RegExp;
69
+ readonly label: "/v1/runs/:id/compact";
70
+ readonly methods: readonly ["POST"];
71
+ }, {
72
+ readonly id: "run-events";
73
+ readonly pattern: RegExp;
74
+ readonly label: "/v1/runs/:id/events";
75
+ readonly methods: readonly ["GET"];
76
+ }, {
77
+ readonly id: "run-detail";
78
+ readonly pattern: RegExp;
79
+ readonly label: "/v1/runs/:id";
80
+ readonly methods: readonly ["GET"];
81
+ }];
82
+ /** 本域可分派行的 `id` 闭集 —— handler 的收尾按它判穷尽(漏一口 = 编译红)。 */
83
+ export type RunsRouteId = RouteIdsOf<typeof RUNS_ROUTES>;
84
+ export declare const RUN_VERBS_ROUTES: readonly [{
85
+ readonly id: "run-subagent-output";
86
+ readonly pattern: RegExp;
87
+ readonly label: "/v1/runs/:id/subagents/:sub/*";
88
+ readonly methods: readonly ["GET"];
89
+ }, {
90
+ readonly id: "run-subagent-stream";
91
+ readonly pattern: RegExp;
92
+ readonly label: "/v1/runs/:id/subagents/:sub/*";
93
+ readonly methods: readonly ["GET"];
94
+ }, {
95
+ readonly id: "run-subagent-steer";
96
+ readonly pattern: RegExp;
97
+ readonly label: "/v1/runs/:id/subagents/:sub/*";
98
+ readonly methods: readonly ["POST"];
99
+ }, {
100
+ readonly id: "run-subagent-resume";
101
+ readonly pattern: RegExp;
102
+ readonly label: "/v1/runs/:id/subagents/:sub/*";
103
+ readonly billable: true;
104
+ readonly methods: readonly ["POST"];
105
+ }, {
106
+ readonly id: "run-task-output";
107
+ readonly pattern: RegExp;
108
+ readonly label: "/v1/runs/:id/tasks/:tid/*";
109
+ readonly methods: readonly ["GET"];
110
+ }, {
111
+ readonly id: "run-task-stop";
112
+ readonly pattern: RegExp;
113
+ readonly label: "/v1/runs/:id/tasks/:tid/*";
114
+ readonly methods: readonly ["POST"];
115
+ }, {
116
+ readonly id: "elicitation-respond";
117
+ readonly pattern: RegExp;
118
+ readonly label: "/v1/elicitations/:id/respond";
119
+ readonly methods: readonly ["POST"];
120
+ }, {
121
+ readonly id: "question-respond";
122
+ readonly pattern: RegExp;
123
+ readonly label: "/v1/questions/:id/respond";
124
+ readonly methods: readonly ["POST"];
125
+ }, {
126
+ readonly id: "tool-approval-respond";
127
+ readonly pattern: RegExp;
128
+ readonly label: "/v1/tool-approvals/:id/respond";
129
+ readonly methods: readonly ["POST"];
130
+ }, {
131
+ readonly id: "task-ask-decision";
132
+ readonly pattern: RegExp;
133
+ readonly label: "/v1/tasks/:id/asks/:askId/decision";
134
+ readonly methods: readonly ["POST"];
135
+ }];
136
+ export type RunVerbsRouteId = RouteIdsOf<typeof RUN_VERBS_ROUTES>;
57
137
  //# sourceMappingURL=runs.d.ts.map