@sema-agent/server 7.79.3 → 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.
- package/dist/http/dispatch.js +28 -8
- package/dist/http/route-ctx.d.ts +101 -4
- package/dist/http/route-ctx.js +4 -0
- package/dist/http/route-table.d.ts +71 -43
- package/dist/http/route-table.js +111 -187
- package/dist/http/routes/a2a-serve.d.ts +18 -3
- package/dist/http/routes/a2a-serve.js +25 -23
- package/dist/http/routes/admin-config-refresh.d.ts +9 -2
- package/dist/http/routes/admin-config-refresh.js +32 -31
- package/dist/http/routes/admin-drain.d.ts +9 -2
- package/dist/http/routes/admin-drain.js +32 -31
- package/dist/http/routes/admin-memory-optout.d.ts +28 -2
- package/dist/http/routes/admin-memory-optout.js +26 -39
- package/dist/http/routes/adoption.d.ts +15 -2
- package/dist/http/routes/adoption.js +52 -52
- package/dist/http/routes/agents-roster.d.ts +9 -2
- package/dist/http/routes/agents-roster.js +82 -80
- package/dist/http/routes/approvals-assistant.d.ts +58 -5
- package/dist/http/routes/approvals-assistant.js +37 -38
- package/dist/http/routes/attachments.d.ts +22 -2
- package/dist/http/routes/attachments.js +81 -72
- package/dist/http/routes/capabilities.d.ts +21 -2
- package/dist/http/routes/capabilities.js +174 -170
- package/dist/http/routes/config-catalog.d.ts +9 -2
- package/dist/http/routes/config-catalog.js +28 -31
- package/dist/http/routes/devices.d.ts +24 -2
- package/dist/http/routes/devices.js +19 -21
- package/dist/http/routes/diagnostics.d.ts +9 -2
- package/dist/http/routes/diagnostics.js +41 -43
- package/dist/http/routes/fleet.d.ts +11 -2
- package/dist/http/routes/fleet.js +23 -22
- package/dist/http/routes/images.d.ts +63 -9
- package/dist/http/routes/images.js +53 -46
- package/dist/http/routes/leader.d.ts +20 -2
- package/dist/http/routes/leader.js +43 -40
- package/dist/http/routes/memory-bundle.d.ts +15 -2
- package/dist/http/routes/memory-bundle.js +38 -38
- package/dist/http/routes/memory-compliance.d.ts +16 -4
- package/dist/http/routes/memory-compliance.js +44 -45
- package/dist/http/routes/memory-consolidation.d.ts +14 -2
- package/dist/http/routes/memory-consolidation.js +66 -66
- package/dist/http/routes/memory-origin.d.ts +23 -4
- package/dist/http/routes/memory-origin.js +65 -65
- package/dist/http/routes/memory-policy.d.ts +21 -2
- package/dist/http/routes/memory-policy.js +119 -115
- package/dist/http/routes/notify-wake.d.ts +21 -11
- package/dist/http/routes/notify-wake.js +118 -116
- package/dist/http/routes/observability.d.ts +16 -2
- package/dist/http/routes/observability.js +54 -51
- package/dist/http/routes/retention-ops.d.ts +19 -2
- package/dist/http/routes/retention-ops.js +20 -22
- package/dist/http/routes/rules.d.ts +36 -2
- package/dist/http/routes/rules.js +22 -24
- package/dist/http/routes/run-memory-capture.d.ts +10 -3
- package/dist/http/routes/run-memory-capture.js +84 -84
- package/dist/http/routes/runs.d.ts +102 -22
- package/dist/http/routes/runs.js +71 -88
- package/dist/http/routes/session-sync.d.ts +41 -2
- package/dist/http/routes/session-sync.js +25 -23
- package/dist/http/routes/sessions-list.d.ts +16 -2
- package/dist/http/routes/sessions-list.js +78 -75
- package/dist/http/routes/sessions.d.ts +77 -2
- package/dist/http/routes/sessions.js +50 -47
- package/dist/http/routes/shared-memory.d.ts +19 -2
- package/dist/http/routes/shared-memory.js +65 -63
- package/dist/http/routes/side-query.d.ts +11 -2
- package/dist/http/routes/side-query.js +81 -79
- package/dist/http/routes/tasks.d.ts +17 -2
- package/dist/http/routes/tasks.js +18 -11
- package/dist/http/routes/trace-usage.d.ts +40 -2
- package/dist/http/routes/trace-usage.js +46 -35
- package/dist/http/routes/workflows.d.ts +35 -3
- package/dist/http/routes/workflows.js +29 -29
- package/package.json +1 -1
package/dist/http/routes/runs.js
CHANGED
|
@@ -25,19 +25,10 @@ import { mintCancelledResult } from "../../run-cancel-context.js";
|
|
|
25
25
|
import { buildCrossSliceUsage, readResourceWindow } from "../../resource-window.js";
|
|
26
26
|
import { headerStr, gatedPrincipal, explicitOperatorOk, sendPrincipalRefusal } from "../principal-gate.js";
|
|
27
27
|
import { ActorAssertionWire } from "@sema-agent/settings-schema";
|
|
28
|
+
import { assertNever } from "../route-ctx.js";
|
|
28
29
|
import { mintAndDriveDurableRun } from "../durable-run-leg.js";
|
|
29
30
|
import { RUN_NOT_FOUND_MESSAGE, runNotFoundMessage } from "../route-ctx.js";
|
|
30
31
|
import { withPrincipal } from "../../observability/principal-context.js";
|
|
31
|
-
export const RUN_ID_RE = /^\/v1\/runs\/([^/]+)(\/events)?$/;
|
|
32
|
-
export const RUN_CANCEL_RE = /^\/v1\/runs\/([^/]+)\/cancel$/;
|
|
33
|
-
export const RUN_STEER_RE = /^\/v1\/runs\/([^/]+)\/steer$/;
|
|
34
|
-
export const RUN_DETACH_RE = /^\/v1\/runs\/([^/]+)\/detach$/;
|
|
35
|
-
export const RUN_COMPACT_RE = /^\/v1\/runs\/([^/]+)\/compact$/;
|
|
36
|
-
export const RUN_INTERRUPT_RE = /^\/v1\/runs\/([^/]+)\/interrupt$/;
|
|
37
|
-
export const ELICIT_RESPOND_RE = /^\/v1\/elicitations\/([^/]+)\/respond$/;
|
|
38
|
-
export const QUESTION_RESPOND_RE = /^\/v1\/questions\/([^/]+)\/respond$/;
|
|
39
|
-
export const TOOL_APPROVAL_RESPOND_RE = /^\/v1\/tool-approvals\/([^/]+)\/respond$/;
|
|
40
|
-
export const TASK_ASK_DECISION_RE = /^\/v1\/tasks\/([^/]+)\/asks\/([^/]+)\/decision$/;
|
|
41
32
|
const ASK_PARKING_RETRY_AFTER_SEC = 2;
|
|
42
33
|
const ASK_ACTOR_LABEL_MAX = 256;
|
|
43
34
|
const AskDecisionActorSchema = ActorAssertionWire.strip();
|
|
@@ -73,13 +64,7 @@ export function projectDecisionActor(raw) {
|
|
|
73
64
|
const parsed = AskDecisionActorSchema.safeParse(raw);
|
|
74
65
|
return parsed.success ? parsed.data : undefined;
|
|
75
66
|
}
|
|
76
|
-
|
|
77
|
-
export const RUN_SUBAGENT_RESUME_RE = /^\/v1\/runs\/([^/]+)\/subagents\/([^/]+)\/resume$/;
|
|
78
|
-
export const RUN_SUBAGENT_OUTPUT_RE = /^\/v1\/runs\/([^/]+)\/subagents\/([^/]+)\/output$/;
|
|
79
|
-
export const RUN_SUBAGENT_STREAM_RE = /^\/v1\/runs\/([^/]+)\/subagents\/([^/]+)\/stream$/;
|
|
80
|
-
export const RUN_TASK_OUTPUT_RE = /^\/v1\/runs\/([^/]+)\/tasks\/([^/]+)\/output$/;
|
|
81
|
-
export const RUN_TASK_STOP_RE = /^\/v1\/runs\/([^/]+)\/tasks\/([^/]+)\/stop$/;
|
|
82
|
-
async function subagentReadGate(req, res, deps, runId) {
|
|
67
|
+
async function subagentReadGate(req, res, deps, runId, search) {
|
|
83
68
|
const principal = gatedPrincipal(req, deps.config);
|
|
84
69
|
if (deps.config.requirePrincipal && principal === undefined) {
|
|
85
70
|
sendPrincipalRefusal(res, req, deps.config);
|
|
@@ -91,7 +76,7 @@ async function subagentReadGate(req, res, deps, runId) {
|
|
|
91
76
|
sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
|
|
92
77
|
return null;
|
|
93
78
|
}
|
|
94
|
-
const callerSession = new
|
|
79
|
+
const callerSession = new URLSearchParams(search).get("session");
|
|
95
80
|
if (!trusted && run.sessionId && callerSession !== run.sessionId) {
|
|
96
81
|
sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
|
|
97
82
|
return null;
|
|
@@ -149,23 +134,13 @@ async function streamRunEvents(req, res, deps, runStore, taskId, staleMs) {
|
|
|
149
134
|
staleFrame: () => ({ event: "failed", data: { type: "failed", errorMessage: "run stalled (instance lost?)" } }),
|
|
150
135
|
}, taskId, staleMs);
|
|
151
136
|
}
|
|
152
|
-
export async function handleRuns(req, res,
|
|
153
|
-
const miss = { fell: false };
|
|
154
|
-
await handleRunsBody(req, res, url, ctx, miss);
|
|
155
|
-
return !miss.fell;
|
|
156
|
-
}
|
|
157
|
-
export async function handleRunVerbs(req, res, url, ctx) {
|
|
158
|
-
const miss = { fell: false };
|
|
159
|
-
await handleRunVerbsBody(req, res, url, ctx, miss);
|
|
160
|
-
return !miss.fell;
|
|
161
|
-
}
|
|
162
|
-
async function handleRunsBody(req, res, url, ctx, miss) {
|
|
137
|
+
export async function handleRuns(req, res, match, ctx) {
|
|
163
138
|
const { deps } = ctx;
|
|
164
139
|
const { idemCache, inflightRuns, preemptableRuns, cancelledViaVerb, steerableRuns, wakeParkMints } = ctx.registry;
|
|
165
140
|
const { readJson, rateLimited, quotaExceeded, leaseDenied, usageWindowDenied, runOwnerOk, runSessionAcceptOk } = ctx.helpers;
|
|
166
141
|
const { prepareSpec } = ctx.legs;
|
|
167
142
|
const source = ctx.req.source;
|
|
168
|
-
if (
|
|
143
|
+
if (match.decl.id === "runs-submit") {
|
|
169
144
|
if (!deps.runStore) {
|
|
170
145
|
sendError(res, 501, "capability.run_store_required", "async runs require a durable run store (DB_BACKEND=mysql|pg|local)");
|
|
171
146
|
return;
|
|
@@ -189,13 +164,12 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
189
164
|
sendJson(res, resp.status, resp.body);
|
|
190
165
|
return;
|
|
191
166
|
}
|
|
192
|
-
|
|
193
|
-
if (runMatch) {
|
|
167
|
+
if (match.decl.id === "run-detail" || match.decl.id === "run-events") {
|
|
194
168
|
if (!deps.runStore) {
|
|
195
169
|
sendError(res, 501, "capability.run_store_required", "async runs require a durable run store (DB_BACKEND=mysql|pg|local)");
|
|
196
170
|
return;
|
|
197
171
|
}
|
|
198
|
-
const taskId =
|
|
172
|
+
const taskId = match.params.taskId;
|
|
199
173
|
if (deps.config.requirePrincipal && !gatedPrincipal(req, deps.config)) {
|
|
200
174
|
sendPrincipalRefusal(res, req, deps.config);
|
|
201
175
|
return;
|
|
@@ -207,9 +181,9 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
207
181
|
}
|
|
208
182
|
if (!runOwnerOk(req, res, run.owner))
|
|
209
183
|
return;
|
|
210
|
-
if (!runSessionAcceptOk(req, res, run,
|
|
184
|
+
if (!runSessionAcceptOk(req, res, run, match.decl.id === "run-events" ? "run.events" : "run.poll"))
|
|
211
185
|
return;
|
|
212
|
-
if (
|
|
186
|
+
if (match.decl.id === "run-events") {
|
|
213
187
|
await streamRunEvents(req, res, deps, deps.runStore, taskId, deps.config.runStaleSec * 1000);
|
|
214
188
|
}
|
|
215
189
|
else {
|
|
@@ -272,8 +246,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
272
246
|
}
|
|
273
247
|
return;
|
|
274
248
|
}
|
|
275
|
-
|
|
276
|
-
if (cancelMatch) {
|
|
249
|
+
if (match.decl.id === "run-cancel") {
|
|
277
250
|
if (!deps.runStore) {
|
|
278
251
|
sendError(res, 501, "capability.run_store_required", "async runs require a durable run store (DB_BACKEND=mysql|pg|local)");
|
|
279
252
|
return;
|
|
@@ -282,7 +255,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
282
255
|
sendPrincipalRefusal(res, req, deps.config);
|
|
283
256
|
return;
|
|
284
257
|
}
|
|
285
|
-
const taskId =
|
|
258
|
+
const taskId = match.params.taskId;
|
|
286
259
|
const run = await deps.runStore.getRun(taskId);
|
|
287
260
|
if (!run) {
|
|
288
261
|
sendError(res, 404, "not_found.run", runNotFoundMessage(taskId));
|
|
@@ -397,8 +370,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
397
370
|
}
|
|
398
371
|
return;
|
|
399
372
|
}
|
|
400
|
-
|
|
401
|
-
if (steerMatch) {
|
|
373
|
+
if (match.decl.id === "run-steer") {
|
|
402
374
|
if (rateLimited(req, res) || quotaExceeded(req, res) || (await leaseDenied(req, res)))
|
|
403
375
|
return;
|
|
404
376
|
if (!deps.runStore) {
|
|
@@ -410,7 +382,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
410
382
|
sendPrincipalRefusal(res, req, deps.config);
|
|
411
383
|
return;
|
|
412
384
|
}
|
|
413
|
-
const taskId =
|
|
385
|
+
const taskId = match.params.taskId;
|
|
414
386
|
let body;
|
|
415
387
|
try {
|
|
416
388
|
body = ((await readJson(req)) ?? {});
|
|
@@ -676,8 +648,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
676
648
|
sendNotRunning(`run is ${run.status} — not accepting steers`);
|
|
677
649
|
return;
|
|
678
650
|
}
|
|
679
|
-
|
|
680
|
-
if (interruptMatch) {
|
|
651
|
+
if (match.decl.id === "run-interrupt") {
|
|
681
652
|
if (rateLimited(req, res) || quotaExceeded(req, res) || (await leaseDenied(req, res)))
|
|
682
653
|
return;
|
|
683
654
|
if (!deps.runStore) {
|
|
@@ -689,7 +660,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
689
660
|
sendPrincipalRefusal(res, req, deps.config);
|
|
690
661
|
return;
|
|
691
662
|
}
|
|
692
|
-
const taskId =
|
|
663
|
+
const taskId = match.params.taskId;
|
|
693
664
|
let interruptRaw;
|
|
694
665
|
try {
|
|
695
666
|
interruptRaw = await readJson(req);
|
|
@@ -822,8 +793,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
822
793
|
sendJson(res, 202, { taskId, status: run.status, delivery: "queued-immediate", messageId: interruptMessageId, note: "interrupt accepted — the cut is best-effort: a task.turn_interrupted event on the run stream is the proof a turn was actually cut; with nothing in flight the text lands at the next turn boundary" });
|
|
823
794
|
return;
|
|
824
795
|
}
|
|
825
|
-
|
|
826
|
-
if (compactMatch) {
|
|
796
|
+
if (match.decl.id === "run-compact") {
|
|
827
797
|
if (rateLimited(req, res) || quotaExceeded(req, res) || (await leaseDenied(req, res)))
|
|
828
798
|
return;
|
|
829
799
|
if (!deps.runStore) {
|
|
@@ -835,7 +805,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
835
805
|
sendPrincipalRefusal(res, req, deps.config);
|
|
836
806
|
return;
|
|
837
807
|
}
|
|
838
|
-
const taskId =
|
|
808
|
+
const taskId = match.params.taskId;
|
|
839
809
|
const run = await deps.runStore.getRun(taskId);
|
|
840
810
|
if (!run) {
|
|
841
811
|
sendError(res, 404, "not_found.run", RUN_NOT_FOUND_MESSAGE);
|
|
@@ -889,8 +859,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
889
859
|
sendJson(res, 202, { taskId, status: "running", delivery: "accepted", note: "compaction will run at the next turn boundary; a compacted{trigger:'manual'} event rides the run stream if anything is summarized" });
|
|
890
860
|
return;
|
|
891
861
|
}
|
|
892
|
-
|
|
893
|
-
if (detachMatch) {
|
|
862
|
+
if (match.decl.id === "run-detach") {
|
|
894
863
|
if (rateLimited(req, res))
|
|
895
864
|
return;
|
|
896
865
|
if (!deps.runStore) {
|
|
@@ -902,7 +871,7 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
902
871
|
sendPrincipalRefusal(res, req, deps.config);
|
|
903
872
|
return;
|
|
904
873
|
}
|
|
905
|
-
const taskId =
|
|
874
|
+
const taskId = match.params.taskId;
|
|
906
875
|
let body;
|
|
907
876
|
try {
|
|
908
877
|
body = ((await readJson(req)) ?? {});
|
|
@@ -940,24 +909,23 @@ async function handleRunsBody(req, res, url, ctx, miss) {
|
|
|
940
909
|
sendJson(res, 202, { taskId, toolCallId: body.toolCallId, delivery: "requested", note: "if the tool call is running in a detach-capable env it settles early with 'moved to background; task_id=b*'; otherwise the request is a no-op (fail-safe)" });
|
|
941
910
|
return;
|
|
942
911
|
}
|
|
943
|
-
|
|
912
|
+
return assertNever(match.decl.id);
|
|
944
913
|
}
|
|
945
|
-
async function
|
|
914
|
+
export async function handleRunVerbs(req, res, match, ctx) {
|
|
946
915
|
const { deps } = ctx;
|
|
947
916
|
const { readJson, rateLimited, quotaExceeded, ownerQuotaDenied, leaseDenied, ownerLeaseDenied, safeDecode, runSessionAcceptOk } = ctx.helpers;
|
|
948
|
-
|
|
949
|
-
if (subOutputMatch) {
|
|
917
|
+
if (match.decl.id === "run-subagent-output") {
|
|
950
918
|
if (!deps.runStore || !deps.subagentTaskOutput) {
|
|
951
919
|
sendError(res, 501, "capability.run_store_required", "subagent output reads require the run store");
|
|
952
920
|
return;
|
|
953
921
|
}
|
|
954
|
-
const runId = safeDecode(
|
|
955
|
-
const target = safeDecode(
|
|
922
|
+
const runId = safeDecode(match.params.runId);
|
|
923
|
+
const target = safeDecode(match.params.sub);
|
|
956
924
|
if (runId === null || target === null) {
|
|
957
925
|
sendError(res, 400, "request.path_malformed", "malformed subagent path (invalid percent-encoding)");
|
|
958
926
|
return;
|
|
959
927
|
}
|
|
960
|
-
const gated = await subagentReadGate(req, res, deps, runId);
|
|
928
|
+
const gated = await subagentReadGate(req, res, deps, runId, match.search);
|
|
961
929
|
if (!gated)
|
|
962
930
|
return;
|
|
963
931
|
const { run } = gated;
|
|
@@ -971,19 +939,18 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
971
939
|
sendJson(res, 200, { taskId: runId, target, content: out.content, output: out.details });
|
|
972
940
|
return;
|
|
973
941
|
}
|
|
974
|
-
|
|
975
|
-
if (subStreamMatch) {
|
|
942
|
+
if (match.decl.id === "run-subagent-stream") {
|
|
976
943
|
if (!deps.runStore || !deps.subagentTaskOutput) {
|
|
977
944
|
sendError(res, 501, "capability.run_store_required", "subagent streams require the run store");
|
|
978
945
|
return;
|
|
979
946
|
}
|
|
980
|
-
const runId = safeDecode(
|
|
981
|
-
const target = safeDecode(
|
|
947
|
+
const runId = safeDecode(match.params.runId);
|
|
948
|
+
const target = safeDecode(match.params.sub);
|
|
982
949
|
if (runId === null || target === null) {
|
|
983
950
|
sendError(res, 400, "request.path_malformed", "malformed subagent path (invalid percent-encoding)");
|
|
984
951
|
return;
|
|
985
952
|
}
|
|
986
|
-
const gatedTail = await subagentReadGate(req, res, deps, runId);
|
|
953
|
+
const gatedTail = await subagentReadGate(req, res, deps, runId, match.search);
|
|
987
954
|
if (!gatedTail)
|
|
988
955
|
return;
|
|
989
956
|
const { run } = gatedTail;
|
|
@@ -1034,26 +1001,25 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1034
1001
|
}
|
|
1035
1002
|
return;
|
|
1036
1003
|
}
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
const stopVerb = req.method === "POST";
|
|
1004
|
+
if (match.decl.id === "run-task-output" || match.decl.id === "run-task-stop") {
|
|
1005
|
+
const stopVerb = match.decl.id === "run-task-stop";
|
|
1040
1006
|
if (!deps.runStore || !deps.taskHandleOutput || !deps.taskHandleStop) {
|
|
1041
1007
|
sendError(res, 501, "capability.run_store_required", "task-handle verbs require the run store + task-registry seams");
|
|
1042
1008
|
return;
|
|
1043
1009
|
}
|
|
1044
1010
|
if (stopVerb && rateLimited(req, res))
|
|
1045
1011
|
return;
|
|
1046
|
-
const runId = safeDecode(
|
|
1047
|
-
const target = safeDecode(
|
|
1012
|
+
const runId = safeDecode(match.params.runId);
|
|
1013
|
+
const target = safeDecode(match.params.tid);
|
|
1048
1014
|
if (runId === null || target === null) {
|
|
1049
1015
|
sendError(res, 400, "request.path_malformed", "malformed task path (invalid percent-encoding)");
|
|
1050
1016
|
return;
|
|
1051
1017
|
}
|
|
1052
|
-
const gatedB = await subagentReadGate(req, res, deps, runId);
|
|
1018
|
+
const gatedB = await subagentReadGate(req, res, deps, runId, match.search);
|
|
1053
1019
|
if (!gatedB)
|
|
1054
1020
|
return;
|
|
1055
1021
|
const { run } = gatedB;
|
|
1056
|
-
const q = new
|
|
1022
|
+
const q = new URLSearchParams(match.search);
|
|
1057
1023
|
const access = { owner: runId, scope: run.owner ?? "default", ...(run.sessionId ? { sessionId: run.sessionId } : {}) };
|
|
1058
1024
|
if (q.get("filter") !== null) {
|
|
1059
1025
|
sendError(res, 400, "request.param_unsupported", "filter is not accepted on the wire — fetch the output and filter client-side (note: the wire serves the clipped projection)");
|
|
@@ -1106,9 +1072,8 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1106
1072
|
sendJson(res, 200, { taskId: runId, target, content: out.content, output: out.details, ...g14 });
|
|
1107
1073
|
return;
|
|
1108
1074
|
}
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
const verb = url.endsWith("/resume") ? "resume" : "steer";
|
|
1075
|
+
if (match.decl.id === "run-subagent-steer" || match.decl.id === "run-subagent-resume") {
|
|
1076
|
+
const verb = match.decl.id === "run-subagent-resume" ? "resume" : "steer";
|
|
1112
1077
|
if (rateLimited(req, res) || quotaExceeded(req, res) || (await leaseDenied(req, res)))
|
|
1113
1078
|
return;
|
|
1114
1079
|
if (!deps.runStore) {
|
|
@@ -1120,8 +1085,8 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1120
1085
|
sendPrincipalRefusal(res, req, deps.config);
|
|
1121
1086
|
return;
|
|
1122
1087
|
}
|
|
1123
|
-
const runId = safeDecode(
|
|
1124
|
-
const target = safeDecode(
|
|
1088
|
+
const runId = safeDecode(match.params.runId);
|
|
1089
|
+
const target = safeDecode(match.params.sub);
|
|
1125
1090
|
if (runId === null || target === null) {
|
|
1126
1091
|
sendError(res, 400, "request.path_malformed", "malformed subagent path (invalid percent-encoding)");
|
|
1127
1092
|
return;
|
|
@@ -1204,8 +1169,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1204
1169
|
: `run is ${run.status} — its sub-agents are no longer addressable`);
|
|
1205
1170
|
return;
|
|
1206
1171
|
}
|
|
1207
|
-
|
|
1208
|
-
if (elicitMatch) {
|
|
1172
|
+
if (match.decl.id === "elicitation-respond") {
|
|
1209
1173
|
if (rateLimited(req, res))
|
|
1210
1174
|
return;
|
|
1211
1175
|
if (!deps.elicitation) {
|
|
@@ -1217,7 +1181,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1217
1181
|
sendPrincipalRefusal(res, req, deps.config);
|
|
1218
1182
|
return;
|
|
1219
1183
|
}
|
|
1220
|
-
const id =
|
|
1184
|
+
const id = match.params.id;
|
|
1221
1185
|
let body;
|
|
1222
1186
|
try {
|
|
1223
1187
|
body = await readJson(req);
|
|
@@ -1230,8 +1194,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1230
1194
|
sendJson(res, status, respBody);
|
|
1231
1195
|
return;
|
|
1232
1196
|
}
|
|
1233
|
-
|
|
1234
|
-
if (questionMatch) {
|
|
1197
|
+
if (match.decl.id === "question-respond") {
|
|
1235
1198
|
if (rateLimited(req, res))
|
|
1236
1199
|
return;
|
|
1237
1200
|
if (!deps.question) {
|
|
@@ -1243,7 +1206,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1243
1206
|
sendPrincipalRefusal(res, req, deps.config);
|
|
1244
1207
|
return;
|
|
1245
1208
|
}
|
|
1246
|
-
const id =
|
|
1209
|
+
const id = match.params.id;
|
|
1247
1210
|
let body;
|
|
1248
1211
|
try {
|
|
1249
1212
|
body = await readJson(req);
|
|
@@ -1256,8 +1219,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1256
1219
|
sendJson(res, status, respBody);
|
|
1257
1220
|
return;
|
|
1258
1221
|
}
|
|
1259
|
-
|
|
1260
|
-
if (approvalMatch) {
|
|
1222
|
+
if (match.decl.id === "tool-approval-respond") {
|
|
1261
1223
|
if (rateLimited(req, res))
|
|
1262
1224
|
return;
|
|
1263
1225
|
if (!deps.toolApproval) {
|
|
@@ -1269,7 +1231,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1269
1231
|
sendPrincipalRefusal(res, req, deps.config);
|
|
1270
1232
|
return;
|
|
1271
1233
|
}
|
|
1272
|
-
const id =
|
|
1234
|
+
const id = match.params.id;
|
|
1273
1235
|
let body;
|
|
1274
1236
|
try {
|
|
1275
1237
|
body = await readJson(req);
|
|
@@ -1286,8 +1248,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1286
1248
|
sendJson(res, status, respBody);
|
|
1287
1249
|
return;
|
|
1288
1250
|
}
|
|
1289
|
-
|
|
1290
|
-
if (askDecisionMatch) {
|
|
1251
|
+
if (match.decl.id === "task-ask-decision") {
|
|
1291
1252
|
if (rateLimited(req, res))
|
|
1292
1253
|
return;
|
|
1293
1254
|
const gate = resolveStreamApprovalGate({
|
|
@@ -1321,8 +1282,8 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1321
1282
|
}
|
|
1322
1283
|
const body = parsedBody.data;
|
|
1323
1284
|
const hasUpdatedInput = typeof rawBody === "object" && rawBody !== null && "updatedInput" in rawBody;
|
|
1324
|
-
const taskId =
|
|
1325
|
-
const askId =
|
|
1285
|
+
const taskId = match.params.taskId;
|
|
1286
|
+
const askId = match.params.askId;
|
|
1326
1287
|
const askNotFound = () => sendError(res, 404, "not_found.ask", "no such approval ask under this task (never existed, belongs to another task, or is not yours)");
|
|
1327
1288
|
const row0 = await askStore.getAsk(askId);
|
|
1328
1289
|
if (!row0 || row0.taskId !== taskId) {
|
|
@@ -1531,7 +1492,7 @@ async function handleRunVerbsBody(req, res, url, ctx, miss) {
|
|
|
1531
1492
|
});
|
|
1532
1493
|
return;
|
|
1533
1494
|
}
|
|
1534
|
-
|
|
1495
|
+
return assertNever(match.decl.id);
|
|
1535
1496
|
}
|
|
1536
1497
|
export async function createDurableRun(req, res, ctx, prepared, idemKey) {
|
|
1537
1498
|
const { deps } = ctx;
|
|
@@ -1571,4 +1532,26 @@ export async function createDurableRun(req, res, ctx, prepared, idemKey) {
|
|
|
1571
1532
|
}), (r) => r.status === 202);
|
|
1572
1533
|
return resp;
|
|
1573
1534
|
}
|
|
1535
|
+
export const RUNS_ROUTES = [
|
|
1536
|
+
{ id: "runs-submit", path: "/v1/runs", billable: true, methods: ["POST"] },
|
|
1537
|
+
{ id: "run-steer", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/steer$/, label: "/v1/runs/:id/steer", methods: ["POST"] },
|
|
1538
|
+
{ id: "run-interrupt", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/interrupt$/, label: "/v1/runs/:id/interrupt", methods: ["POST"] },
|
|
1539
|
+
{ id: "run-detach", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/detach$/, label: "/v1/runs/:id/detach", methods: ["POST"] },
|
|
1540
|
+
{ id: "run-cancel", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/cancel$/, label: "/v1/runs/:id/cancel", methods: ["POST"] },
|
|
1541
|
+
{ id: "run-compact", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/compact$/, label: "/v1/runs/:id/compact", methods: ["POST"] },
|
|
1542
|
+
{ id: "run-events", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)\/events$/, label: "/v1/runs/:id/events", methods: ["GET"] },
|
|
1543
|
+
{ id: "run-detail", pattern: /^\/v1\/runs\/(?<taskId>[^/]+)$/, label: "/v1/runs/:id", methods: ["GET"] },
|
|
1544
|
+
];
|
|
1545
|
+
export const RUN_VERBS_ROUTES = [
|
|
1546
|
+
{ id: "run-subagent-output", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/output$/, label: "/v1/runs/:id/subagents/:sub/*", methods: ["GET"] },
|
|
1547
|
+
{ id: "run-subagent-stream", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/stream$/, label: "/v1/runs/:id/subagents/:sub/*", methods: ["GET"] },
|
|
1548
|
+
{ id: "run-subagent-steer", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/steer$/, label: "/v1/runs/:id/subagents/:sub/*", methods: ["POST"] },
|
|
1549
|
+
{ id: "run-subagent-resume", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/subagents\/(?<sub>[^/]+)\/resume$/, label: "/v1/runs/:id/subagents/:sub/*", billable: true, methods: ["POST"] },
|
|
1550
|
+
{ id: "run-task-output", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/tasks\/(?<tid>[^/]+)\/output$/, label: "/v1/runs/:id/tasks/:tid/*", methods: ["GET"] },
|
|
1551
|
+
{ id: "run-task-stop", pattern: /^\/v1\/runs\/(?<runId>[^/]+)\/tasks\/(?<tid>[^/]+)\/stop$/, label: "/v1/runs/:id/tasks/:tid/*", methods: ["POST"] },
|
|
1552
|
+
{ id: "elicitation-respond", pattern: /^\/v1\/elicitations\/(?<id>[^/]+)\/respond$/, label: "/v1/elicitations/:id/respond", methods: ["POST"] },
|
|
1553
|
+
{ id: "question-respond", pattern: /^\/v1\/questions\/(?<id>[^/]+)\/respond$/, label: "/v1/questions/:id/respond", methods: ["POST"] },
|
|
1554
|
+
{ id: "tool-approval-respond", pattern: /^\/v1\/tool-approvals\/(?<id>[^/]+)\/respond$/, label: "/v1/tool-approvals/:id/respond", methods: ["POST"] },
|
|
1555
|
+
{ id: "task-ask-decision", pattern: /^\/v1\/tasks\/(?<taskId>[^/]+)\/asks\/(?<askId>[^/]+)\/decision$/, label: "/v1/tasks/:id/asks/:askId/decision", methods: ["POST"] },
|
|
1556
|
+
];
|
|
1574
1557
|
//# sourceMappingURL=runs.js.map
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
11
11
|
import { type SessionRulesRecord, type FileHistoryExport } from "@sema-agent/core";
|
|
12
12
|
import { type StagingHandle } from "../../session-sync-kernel.js";
|
|
13
|
-
import type { RouteCtx } from "../route-ctx.js";
|
|
13
|
+
import type { RouteCtx, RouteMatch, RouteIdsOf } from "../route-ctx.js";
|
|
14
14
|
export type PendingStaging = {
|
|
15
15
|
handle: StagingHandle;
|
|
16
16
|
realSessionId: string;
|
|
@@ -45,5 +45,44 @@ export interface SessionSyncLocal {
|
|
|
45
45
|
cleanupStaging(stagingId: string): void;
|
|
46
46
|
}
|
|
47
47
|
export declare function createSessionSyncLocal(): SessionSyncLocal;
|
|
48
|
-
|
|
48
|
+
/** 路由体 = 从 `server.ts` 的 `handle()` 里**整段剪切**过来的原文(唯一改动:统一去缩进两格)。 */
|
|
49
|
+
export declare function handleSessionSync(req: IncomingMessage, res: ServerResponse, match: RouteMatch<SessionSyncRouteId>, ctx: RouteCtx): Promise<void>;
|
|
50
|
+
export declare const SESSION_SYNC_ROUTES: readonly [{
|
|
51
|
+
readonly id: "session-sync-manifest";
|
|
52
|
+
readonly pattern: RegExp;
|
|
53
|
+
readonly label: "/v1/sessions/:id/sync/$verb";
|
|
54
|
+
readonly methods: readonly ["GET"];
|
|
55
|
+
}, {
|
|
56
|
+
readonly id: "session-sync-entries";
|
|
57
|
+
readonly pattern: RegExp;
|
|
58
|
+
readonly label: "/v1/sessions/:id/sync/$verb";
|
|
59
|
+
readonly methods: readonly ["GET"];
|
|
60
|
+
}, {
|
|
61
|
+
readonly id: "session-sync-plan";
|
|
62
|
+
readonly pattern: RegExp;
|
|
63
|
+
readonly label: "/v1/sessions/:id/sync/$verb";
|
|
64
|
+
readonly methods: readonly ["POST"];
|
|
65
|
+
}, {
|
|
66
|
+
readonly id: "session-sync-import";
|
|
67
|
+
readonly pattern: RegExp;
|
|
68
|
+
readonly label: "/v1/sessions/:id/sync/import";
|
|
69
|
+
readonly methods: readonly ["POST"];
|
|
70
|
+
}, {
|
|
71
|
+
readonly id: "session-sync-import-entries";
|
|
72
|
+
readonly pattern: RegExp;
|
|
73
|
+
readonly label: "/v1/sessions/:id/sync/import";
|
|
74
|
+
readonly methods: readonly ["POST"];
|
|
75
|
+
}, {
|
|
76
|
+
readonly id: "session-sync-blob-put";
|
|
77
|
+
readonly pattern: RegExp;
|
|
78
|
+
readonly label: "/v1/sessions/:id/sync/blobs";
|
|
79
|
+
readonly methods: readonly ["PUT"];
|
|
80
|
+
}, {
|
|
81
|
+
readonly id: "session-sync-history-blob";
|
|
82
|
+
readonly pattern: RegExp;
|
|
83
|
+
readonly label: "/v1/sessions/:id/sync/history/blobs/:hash";
|
|
84
|
+
readonly methods: readonly ["GET"];
|
|
85
|
+
}];
|
|
86
|
+
/** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽(漏一口 = 编译红)。 */
|
|
87
|
+
export type SessionSyncRouteId = RouteIdsOf<typeof SESSION_SYNC_ROUTES>;
|
|
49
88
|
//# sourceMappingURL=session-sync.d.ts.map
|
|
@@ -11,6 +11,7 @@ const SYNC_BLOB_MAX_BYTES = 64 * 1024 * 1024;
|
|
|
11
11
|
const SYNC_NDJSON_LINE_MAX_BYTES = 8 * 1024 * 1024;
|
|
12
12
|
const SYNC_IMPORT_BATCH = 500;
|
|
13
13
|
import { SHA256_HEX_RE } from "../../digest-form.js";
|
|
14
|
+
import { assertNever } from "../route-ctx.js";
|
|
14
15
|
export function createSessionSyncLocal() {
|
|
15
16
|
const pendingStagings = new Map();
|
|
16
17
|
const importLeases = new Map();
|
|
@@ -27,18 +28,12 @@ export function createSessionSyncLocal() {
|
|
|
27
28
|
};
|
|
28
29
|
return { pendingStagings, importLeases, touchImportLease, cleanupStaging };
|
|
29
30
|
}
|
|
30
|
-
export async function handleSessionSync(req, res,
|
|
31
|
-
const miss = { fell: false };
|
|
32
|
-
await handleSessionSyncBody(req, res, url, ctx, miss);
|
|
33
|
-
return !miss.fell;
|
|
34
|
-
}
|
|
35
|
-
async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
31
|
+
export async function handleSessionSync(req, res, match, ctx) {
|
|
36
32
|
const { deps } = ctx;
|
|
37
33
|
const { readJson, readRawBody, safeDecode, sessionOwnerScopeForWrite, rateLimited } = ctx.helpers;
|
|
38
34
|
const { pendingStagings, importLeases, touchImportLease, cleanupStaging } = ctx.local.sessionSync;
|
|
39
35
|
{
|
|
40
|
-
|
|
41
|
-
if (sm) {
|
|
36
|
+
{
|
|
42
37
|
const ownerOf = deps.sessionStorage?.ownerOf?.bind(deps.sessionStorage);
|
|
43
38
|
if (!deps.backend || !ownerOf) {
|
|
44
39
|
sendError(res, 501, "capability.session_store_required", "session sync requires a durable session store");
|
|
@@ -49,7 +44,7 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
49
44
|
sendError(res, 401, "auth.unauthorized", "unauthorized");
|
|
50
45
|
return;
|
|
51
46
|
}
|
|
52
|
-
const sessionId = safeDecode(
|
|
47
|
+
const sessionId = safeDecode(match.params.sessionId);
|
|
53
48
|
if (sessionId === null || !isUuidShape(sessionId)) {
|
|
54
49
|
sendError(res, 400, "request.id_invalid", "invalid session id (must be a canonical uuid)");
|
|
55
50
|
return;
|
|
@@ -74,7 +69,7 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
74
69
|
}
|
|
75
70
|
return true;
|
|
76
71
|
};
|
|
77
|
-
if (
|
|
72
|
+
if (match.decl.id === "session-sync-manifest") {
|
|
78
73
|
if (!pullGateOk())
|
|
79
74
|
return;
|
|
80
75
|
const out = await exportSessionManifest(sessionId, deps.backend);
|
|
@@ -85,10 +80,10 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
85
80
|
sendJson(res, 200, { manifest: out.manifest });
|
|
86
81
|
return;
|
|
87
82
|
}
|
|
88
|
-
if (
|
|
83
|
+
if (match.decl.id === "session-sync-entries") {
|
|
89
84
|
if (!pullGateOk())
|
|
90
85
|
return;
|
|
91
|
-
const afterSeqRaw = new
|
|
86
|
+
const afterSeqRaw = new URLSearchParams(match.search).get("afterSeq");
|
|
92
87
|
let afterSeq;
|
|
93
88
|
if (afterSeqRaw !== null) {
|
|
94
89
|
const n = Number(afterSeqRaw);
|
|
@@ -127,10 +122,10 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
127
122
|
}
|
|
128
123
|
return;
|
|
129
124
|
}
|
|
130
|
-
if (
|
|
125
|
+
if (match.decl.id === "session-sync-history-blob") {
|
|
131
126
|
if (!pullGateOk())
|
|
132
127
|
return;
|
|
133
|
-
const hash = safeDecode(
|
|
128
|
+
const hash = safeDecode(match.params.hash);
|
|
134
129
|
if (hash === null) {
|
|
135
130
|
sendError(res, 400, "request.path_malformed", "invalid blob hash");
|
|
136
131
|
return;
|
|
@@ -159,12 +154,12 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
159
154
|
res.end(Buffer.from(bytes));
|
|
160
155
|
return;
|
|
161
156
|
}
|
|
162
|
-
if (
|
|
157
|
+
if (match.decl.id === "session-sync-blob-put") {
|
|
163
158
|
if (rateLimited(req, res))
|
|
164
159
|
return;
|
|
165
160
|
if (!pushGateOk())
|
|
166
161
|
return;
|
|
167
|
-
const hash = safeDecode(
|
|
162
|
+
const hash = safeDecode(match.params.hash);
|
|
168
163
|
if (hash === null || !SHA256_HEX_RE.test(hash)) {
|
|
169
164
|
sendError(res, 400, "request.id_invalid", "blob hash must be 64 lowercase-hex chars");
|
|
170
165
|
return;
|
|
@@ -191,7 +186,7 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
191
186
|
res.writeHead(204).end();
|
|
192
187
|
return;
|
|
193
188
|
}
|
|
194
|
-
if (
|
|
189
|
+
if (match.decl.id === "session-sync-import") {
|
|
195
190
|
if (!pushGateOk())
|
|
196
191
|
return;
|
|
197
192
|
if (deps.sessionMirrorRuling && !scope.fleetWide && scope.gateOwner !== null) {
|
|
@@ -353,8 +348,8 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
353
348
|
sendJson(res, 200, { stagingId, relation: relA.relation });
|
|
354
349
|
return;
|
|
355
350
|
}
|
|
356
|
-
if (
|
|
357
|
-
const stagingId = safeDecode(
|
|
351
|
+
if (match.decl.id === "session-sync-import-entries") {
|
|
352
|
+
const stagingId = safeDecode(match.params.stagingId);
|
|
358
353
|
if (stagingId === null) {
|
|
359
354
|
sendError(res, 400, "request.id_invalid", "invalid staging id");
|
|
360
355
|
return;
|
|
@@ -507,7 +502,7 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
507
502
|
}
|
|
508
503
|
return;
|
|
509
504
|
}
|
|
510
|
-
if (
|
|
505
|
+
if (match.decl.id === "session-sync-plan") {
|
|
511
506
|
if (!pushGateOk())
|
|
512
507
|
return;
|
|
513
508
|
let body;
|
|
@@ -527,10 +522,17 @@ async function handleSessionSyncBody(req, res, url, ctx, miss) {
|
|
|
527
522
|
sendJson(res, 200, relation);
|
|
528
523
|
return;
|
|
529
524
|
}
|
|
530
|
-
|
|
531
|
-
return;
|
|
525
|
+
return assertNever(match.decl.id);
|
|
532
526
|
}
|
|
533
527
|
}
|
|
534
|
-
miss.fell = true;
|
|
535
528
|
}
|
|
529
|
+
export const SESSION_SYNC_ROUTES = [
|
|
530
|
+
{ id: "session-sync-manifest", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/sync\/manifest$/, label: "/v1/sessions/:id/sync/$verb", methods: ["GET"] },
|
|
531
|
+
{ id: "session-sync-entries", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/sync\/entries$/, label: "/v1/sessions/:id/sync/$verb", methods: ["GET"] },
|
|
532
|
+
{ id: "session-sync-plan", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/sync\/plan$/, label: "/v1/sessions/:id/sync/$verb", methods: ["POST"] },
|
|
533
|
+
{ id: "session-sync-import", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/sync\/import$/, label: "/v1/sessions/:id/sync/import", methods: ["POST"] },
|
|
534
|
+
{ id: "session-sync-import-entries", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/sync\/import\/(?<stagingId>[^/]+)\/entries$/, label: "/v1/sessions/:id/sync/import", methods: ["POST"] },
|
|
535
|
+
{ id: "session-sync-blob-put", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/sync\/blobs\/(?<hash>[^/]+)$/, label: "/v1/sessions/:id/sync/blobs", methods: ["PUT"] },
|
|
536
|
+
{ id: "session-sync-history-blob", pattern: /^\/v1\/sessions\/(?<sessionId>[^/]+)\/sync\/history\/blobs\/(?<hash>[^/]+)$/, label: "/v1/sessions/:id/sync/history/blobs/:hash", methods: ["GET"] },
|
|
537
|
+
];
|
|
536
538
|
//# sourceMappingURL=session-sync.js.map
|
|
@@ -5,6 +5,20 @@
|
|
|
5
5
|
* owner-scope 与 trace 列表同一权威模型(system/traceToken=fleet-wide,principal=钉住本人)。本域零可变状态。
|
|
6
6
|
*/
|
|
7
7
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
8
|
-
import type { RouteCtx } from "../route-ctx.js";
|
|
9
|
-
|
|
8
|
+
import type { RouteCtx, RouteMatch, RouteIdsOf } from "../route-ctx.js";
|
|
9
|
+
/** 路由体 = 从 `server.ts` 的 `handle()` 里**整段剪切**过来的原文(唯一改动:统一去缩进两格)。裸 `return;`
|
|
10
|
+
* 的语义原样 =「本域已应答」;走到函数尾才是「没匹配上」,置 `miss.fell` 交回装配器继续下一个域。
|
|
11
|
+
* 跨域的东西(deps / 助手 / 单域状态)一律在首行解构出来,于是下面每一行都逐字不变。 */
|
|
12
|
+
export declare function handleSessionsList(req: IncomingMessage, res: ServerResponse, match: RouteMatch<SessionsListRouteId>, ctx: RouteCtx): Promise<void>;
|
|
13
|
+
export declare const SESSIONS_LIST_ROUTES: readonly [{
|
|
14
|
+
readonly id: "sessions-list";
|
|
15
|
+
readonly path: "/v1/sessions";
|
|
16
|
+
readonly methods: readonly ["GET"];
|
|
17
|
+
}, {
|
|
18
|
+
readonly id: "sendfile-links";
|
|
19
|
+
readonly path: "/v1/sendfile-links";
|
|
20
|
+
readonly methods: readonly ["GET"];
|
|
21
|
+
}];
|
|
22
|
+
/** 本域可分派行的 `id` 闭集 —— handler 的 `switch` 按它判穷尽(漏一口 = 编译红)。 */
|
|
23
|
+
export type SessionsListRouteId = RouteIdsOf<typeof SESSIONS_LIST_ROUTES>;
|
|
10
24
|
//# sourceMappingURL=sessions-list.d.ts.map
|