@sema-agent/server 7.104.0 → 7.106.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/MIGRATION.md +114 -0
- package/USAGE.md +193 -52
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +2 -0
- package/deploy/sema-up/cluster-up.sh +15 -2
- package/deploy/sema-up/kube-up.sh +8 -3
- package/deploy/sema-up/lib/flagshape.sh +29 -0
- package/deploy/sema-up/lib/parse-machines.py +4 -1
- package/deploy/sema-up/sema-up.sh +11 -9
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +3 -1
- package/dist/approval-card.d.ts +1 -1
- package/dist/approval.d.ts +6 -1
- package/dist/approval.js +4 -4
- package/dist/auth-bridge.d.ts +14 -0
- package/dist/auth-bridge.js +7 -0
- package/dist/auto-mode-face.d.ts +49 -40
- package/dist/auto-mode-face.js +6 -68
- package/dist/bench/s1/live-deps.d.ts +9 -2
- package/dist/bench/s1/live-deps.js +13 -8
- package/dist/boot/budget-tracing.js +3 -2
- package/dist/boot/config-center.d.ts +4 -0
- package/dist/boot/config-center.js +95 -37
- package/dist/boot/coordinators.d.ts +1 -0
- package/dist/boot/coordinators.js +3 -1
- package/dist/boot/device-lane.d.ts +2 -1
- package/dist/boot/execution-env.d.ts +11 -0
- package/dist/boot/execution-env.js +30 -6
- package/dist/boot/execution-lane.js +2 -3
- package/dist/boot/leader.d.ts +2 -1
- package/dist/boot/leader.js +2 -0
- package/dist/boot/parked-revive-gate.d.ts +10 -7
- package/dist/boot/parked-revive-gate.js +4 -11
- package/dist/boot/resolve-spec.d.ts +1 -4
- package/dist/boot/resolve-spec.js +44 -21
- package/dist/boot/runner-deps.d.ts +5 -8
- package/dist/boot/runner-deps.js +5 -10
- package/dist/boot/side-query-lane.d.ts +2 -2
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +2 -1
- package/dist/boot/stage-05-execution-env.js +2 -2
- package/dist/boot/stage-06-runners.d.ts +3 -2
- package/dist/boot/stage-06-runners.js +2 -5
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +1 -2
- package/dist/boot/stage-08-reapers.d.ts +2 -2
- package/dist/boot/stage-09-leader.d.ts +2 -2
- package/dist/boot/stage-09-leader.js +2 -2
- package/dist/boot/stage-10-http-server.d.ts +2 -2
- package/dist/boot/stage-10-http-server.js +11 -7
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +6 -4
- package/dist/brain.d.ts +24 -2
- package/dist/brain.js +29 -10
- package/dist/budget.js +3 -0
- package/dist/capabilities/center-wiring.d.ts +64 -0
- package/dist/capabilities/center-wiring.js +24 -0
- package/dist/capabilities/composite-members.d.ts +89 -0
- package/dist/capabilities/composite-members.js +20 -0
- package/dist/capabilities/execution-lane.d.ts +3 -0
- package/dist/capabilities/execution-lane.js +5 -2
- package/dist/config-catalog.d.ts +30 -5
- package/dist/config-catalog.js +75 -26
- package/dist/config-center/apply-effective.d.ts +1 -1
- package/dist/config-center/apply-effective.js +7 -8
- package/dist/config-center/apply-ledger.d.ts +17 -0
- package/dist/config-center/apply-ledger.js +5 -0
- package/dist/config-center/center-request.d.ts +17 -0
- package/dist/config-center/center-request.js +4 -0
- package/dist/config-center/pull-state.d.ts +29 -0
- package/dist/config-center/pull-state.js +2 -0
- package/dist/config-types.d.ts +41 -14
- package/dist/config-types.js +1 -0
- package/dist/config.d.ts +50 -2
- package/dist/config.js +111 -23
- package/dist/cross-session-settings.d.ts +1 -1
- package/dist/deployment-governance.d.ts +12 -1
- package/dist/deployment-governance.js +2 -0
- package/dist/execution-lane-caps.d.ts +30 -2
- package/dist/execution-lane-caps.js +12 -0
- package/dist/file-history-disclosure.d.ts +7 -31
- package/dist/file-history-disclosure.js +12 -0
- package/dist/fleet/fleet-bus.d.ts +5 -1
- package/dist/fleet-client.d.ts +18 -13
- package/dist/fleet-client.js +32 -22
- package/dist/fleet-lease.d.ts +72 -47
- package/dist/fleet-lease.js +66 -14
- package/dist/governance-http-status.d.ts +0 -1
- package/dist/governance-http-status.js +0 -1
- package/dist/hosted-posture.d.ts +6 -17
- package/dist/hosted-posture.js +11 -6
- package/dist/http/admission.d.ts +1 -1
- package/dist/http/admission.js +14 -9
- package/dist/http/approval-sweeps.js +13 -1
- package/dist/http/dispatch.d.ts +18 -0
- package/dist/http/dispatch.js +18 -5
- package/dist/http/durable-run-leg.js +2 -0
- package/dist/http/request-guards.d.ts +25 -0
- package/dist/http/request-guards.js +25 -5
- package/dist/http/resume-legs.d.ts +1 -1
- package/dist/http/resume-legs.js +19 -11
- package/dist/http/route-ctx.d.ts +9 -0
- package/dist/http/route-table.d.ts +15 -4
- package/dist/http/route-table.js +6 -5
- package/dist/http/routes/approvals-assistant.js +0 -1
- package/dist/http/routes/capabilities.js +12 -11
- package/dist/http/routes/config-catalog.js +2 -1
- package/dist/http/routes/diagnostics.js +2 -0
- package/dist/http/routes/fleet.d.ts +3 -2
- package/dist/http/routes/images.js +0 -1
- package/dist/http/routes/runs.js +2 -8
- package/dist/http/routes/session-sync.js +6 -1
- package/dist/http/routes/sessions.js +5 -2
- package/dist/http/routes/side-query.js +8 -1
- package/dist/http/routes/tasks.js +4 -1
- package/dist/http/routes/trace-usage.d.ts +2 -0
- package/dist/http/routes/trace-usage.js +4 -9
- package/dist/http/server.d.ts +29 -8
- package/dist/http/server.js +4 -1
- package/dist/http/session-inherit-env.d.ts +37 -0
- package/dist/http/session-inherit-env.js +6 -0
- package/dist/http/sse-lifecycle.d.ts +1 -1
- package/dist/http/sse-log.d.ts +12 -9
- package/dist/http/sse-log.js +1 -8
- package/dist/http/wire-types.d.ts +19 -28
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/key-resolver.d.ts +74 -19
- package/dist/key-resolver.js +65 -7
- package/dist/leader/leader.d.ts +6 -0
- package/dist/leader/leader.js +2 -1
- package/dist/leader/repair-wire.js +2 -1
- package/dist/leader/wire.d.ts +9 -1
- package/dist/leader/wire.js +10 -6
- package/dist/observability/fail-open.d.ts +9 -1
- package/dist/observability/fail-open.js +9 -1
- package/dist/observability/metrics.js +3 -1
- package/dist/observability/permission-rule-events.d.ts +1 -1
- package/dist/observability/permission-rule-events.js +1 -1
- package/dist/observability/run-terminal.d.ts +82 -9
- package/dist/observability/run-terminal.js +112 -9
- package/dist/observability/secret-env-scrub.js +1 -1
- package/dist/observability/tool-trace.d.ts +2 -0
- package/dist/operator-ask.d.ts +29 -1
- package/dist/operator-ask.js +6 -0
- package/dist/parked-decide.d.ts +14 -1
- package/dist/parked-decide.js +8 -1
- package/dist/plugins/image-bake-store-sql.d.ts +0 -2
- package/dist/plugins/image-bake-store-sql.js +0 -5
- package/dist/plugins/retention-store-sql.js +1 -0
- package/dist/plugins/run-store-sql.d.ts +3 -2
- package/dist/plugins/schema-indexes.js +1 -0
- package/dist/plugins/session-policy-store-sql.d.ts +38 -7
- package/dist/plugins/session-policy-store-sql.js +73 -18
- package/dist/plugins/sql-driver.d.ts +1 -1
- package/dist/plugins/store-backend.d.ts +17 -6
- package/dist/plugins/store-backend.js +16 -5
- package/dist/plugins/tidb-pool.js +5 -4
- package/dist/read-face-posture.d.ts +25 -4
- package/dist/read-face-posture.js +9 -0
- package/dist/request-key-closure.js +2 -2
- package/dist/request-value-closure.d.ts +17 -5
- package/dist/request-value-closure.js +12 -0
- package/dist/router/route-orchestration.d.ts +11 -0
- package/dist/router/route-orchestration.js +7 -6
- package/dist/rules-consent.js +0 -11
- package/dist/run-local.js +4 -2
- package/dist/runs.d.ts +2 -1
- package/dist/runs.js +4 -4
- package/dist/runtime-caps-resolver.d.ts +4 -10
- package/dist/runtime-governance.d.ts +8 -11
- package/dist/runtime-governance.js +10 -41
- package/dist/sealed-key.d.ts +0 -40
- package/dist/sealed-key.js +0 -20
- package/dist/server-secret-env.d.ts +11 -12
- package/dist/session-policy-wire.d.ts +100 -12
- package/dist/session-policy-wire.js +71 -8
- package/dist/session-titler.d.ts +11 -0
- package/dist/session-titler.js +6 -2
- package/dist/sql-engine-posture.d.ts +2 -2
- package/dist/store-posture.d.ts +53 -0
- package/dist/store-posture.js +32 -0
- package/dist/task-settings.d.ts +34 -45
- package/dist/task-settings.js +46 -25
- package/dist/tool-approval.d.ts +51 -22
- package/dist/tool-approval.js +44 -8
- package/dist/tool-declaration-http-status.d.ts +12 -0
- package/dist/tool-declaration-http-status.js +12 -0
- package/dist/trace/core-keyset-guard.d.ts +7 -7
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +5 -0
- package/dist/trace/project.d.ts +13 -7
- package/dist/trace/project.js +54 -6
- package/dist/trace/redact.d.ts +7 -0
- package/dist/trace/redact.js +153 -61
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- package/dist/unattended-permission-mode.d.ts +110 -0
- package/dist/unattended-permission-mode.js +65 -0
- package/package.json +3 -3
- package/dist/boot/session-shell-gate-registry.d.ts +0 -39
- package/dist/boot/session-shell-gate-registry.js +0 -21
- package/dist/plugins/memory-session-policy-store.d.ts +0 -46
- package/dist/plugins/memory-session-policy-store.js +0 -52
- package/dist/roster-bound-http-status.d.ts +0 -6
- package/dist/roster-bound-http-status.js +0 -6
package/dist/http/routes/runs.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { persistedPlaneOf } from "../../terminal.js";
|
|
2
|
-
import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, redactHead,
|
|
3
|
-
import { isModelTextLedgerEventType } from "../../trace/ledger-events.js";
|
|
2
|
+
import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, redactHead, redactLedgerEventForRead, redactTerminalResult } from "../../observability/run-terminal.js";
|
|
4
3
|
import { z } from "zod";
|
|
5
4
|
import { uuidv7, mintCheckpointToken, CheckpointError, validatePendingSteer, TASK_OUTPUT_REPLAY_KINDS } from "@sema-agent/core";
|
|
6
5
|
import { isTerminalRunStatus, isParkedRunStatus, runProvenElsewhere } from "../../plugins/store-contracts.js";
|
|
@@ -126,14 +125,9 @@ async function streamRunEvents(req, res, deps, runStore, taskId, staleMs) {
|
|
|
126
125
|
return run ? { status: run.status, updatedAt: run.updatedAt } : undefined;
|
|
127
126
|
},
|
|
128
127
|
getEvents: (id, after) => runStore.getEvents(id, after),
|
|
129
|
-
retainedFrom: (id) => runStore.retainedFrom(id),
|
|
130
128
|
formatEvent: (ev) => {
|
|
131
129
|
const type = normalizeRunEventType(ev.type);
|
|
132
|
-
const redacted = type
|
|
133
|
-
? { ...ev.data, result: memoRedactTerminalResult("ev.done.result", ev.data.result) }
|
|
134
|
-
: type === "failed" ? memoRedactedRead("ev.failed", ev.data, (d) => redactLedgerEventData(type, d))
|
|
135
|
-
: isModelTextLedgerEventType(type) ? memoRedactedRead("ev.model-text", ev.data, (d) => redactLedgerEventData(type, d))
|
|
136
|
-
: redactLedgerEventData(type, ev.data);
|
|
130
|
+
const redacted = redactLedgerEventForRead(type, ev.data);
|
|
137
131
|
const data = screenedStoredEventData(type, redacted);
|
|
138
132
|
return { id: ev.seq, event: type, data: { type, ...(data ?? {}) } };
|
|
139
133
|
},
|
|
@@ -13,7 +13,7 @@ const SYNC_NDJSON_LINE_MAX_BYTES = 8 * 1024 * 1024;
|
|
|
13
13
|
const SYNC_IMPORT_BATCH = 500;
|
|
14
14
|
import { SHA256_HEX_RE } from "../../digest-form.js";
|
|
15
15
|
import { assertNever } from "../route-ctx.js";
|
|
16
|
-
import { readSessionRulesRecords, describeSessionRulesRecordProblem } from "../../session-policy-wire.js";
|
|
16
|
+
import { readSessionRulesRecords, describeSessionRulesRecordProblem, legacyToolNameProblemOf } from "../../session-policy-wire.js";
|
|
17
17
|
export function createSessionSyncLocal() {
|
|
18
18
|
const pendingStagings = new Map();
|
|
19
19
|
const importLeases = new Map();
|
|
@@ -235,6 +235,11 @@ export async function handleSessionSync(req, res, match, ctx) {
|
|
|
235
235
|
}
|
|
236
236
|
const policyRead = readSessionRulesRecords(body.policy);
|
|
237
237
|
if (policyRead.problem !== undefined) {
|
|
238
|
+
const legacy = legacyToolNameProblemOf(policyRead.problem);
|
|
239
|
+
if (legacy !== undefined) {
|
|
240
|
+
sendError(res, 400, "rules.legacy_tool_name", `policy: ${describeSessionRulesRecordProblem(policyRead.problem)}`, { field: legacy.field, name: legacy.name });
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
238
243
|
sendError(res, 400, "request.field_invalid", `policy: ${describeSessionRulesRecordProblem(policyRead.problem)}`);
|
|
239
244
|
return;
|
|
240
245
|
}
|
|
@@ -6,7 +6,7 @@ import { redactSecrets } from "../../trace/redact.js";
|
|
|
6
6
|
import { recordFailOpen } from "../../observability/fail-open.js";
|
|
7
7
|
import { targetOutsideStoreOf } from "../../memory-store-refusal.js";
|
|
8
8
|
import { MAX_SETTINGS_OUTPUT_STYLE_CHARS, MAX_SETTINGS_PERMISSION_RULES, MAX_SETTINGS_ENV_VARS, MAX_SETTINGS_ENV_KEY_CHARS, MAX_SETTINGS_ENV_VALUE_CHARS } from "../../task-settings.js";
|
|
9
|
-
import {
|
|
9
|
+
import { readWritableSessionPermissionRules, describeSessionPermissionRulesProblem } from "../../session-policy-wire.js";
|
|
10
10
|
import { sendJson, sendError, sendSessionError, sendSessionPolicyError, sseHeaders } from "../send.js";
|
|
11
11
|
import { gatedPrincipal, explicitOperatorOk, runOwnerReadable, sendPrincipalRefusal, sendUnauthorized } from "../principal-gate.js";
|
|
12
12
|
import { assertNever } from "../route-ctx.js";
|
|
@@ -777,7 +777,7 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
777
777
|
sendError(res, 400, "request.invalid_json", "invalid JSON body");
|
|
778
778
|
return;
|
|
779
779
|
}
|
|
780
|
-
const read =
|
|
780
|
+
const read = readWritableSessionPermissionRules(body.rules);
|
|
781
781
|
if (read.problem !== undefined) {
|
|
782
782
|
switch (read.problem.kind) {
|
|
783
783
|
case "not-an-object":
|
|
@@ -786,6 +786,9 @@ export async function handleSessions(req, res, match, ctx) {
|
|
|
786
786
|
case "field-not-string-array":
|
|
787
787
|
sendError(res, 400, "request.field_invalid", describeSessionPermissionRulesProblem(read.problem));
|
|
788
788
|
return;
|
|
789
|
+
case "legacy-tool-name":
|
|
790
|
+
sendError(res, 400, "rules.legacy_tool_name", describeSessionPermissionRulesProblem(read.problem), { field: read.problem.field, name: read.problem.name });
|
|
791
|
+
return;
|
|
789
792
|
default: {
|
|
790
793
|
const unhandled = read.problem;
|
|
791
794
|
throw new Error(`unhandled SessionPermissionRules problem: ${JSON.stringify(unhandled)}`);
|
|
@@ -3,6 +3,7 @@ import { HttpError } from "../../security.js";
|
|
|
3
3
|
import { isModelAllowlisted, matchCatalogModel, refusedCatalogEntry, selectableCatalog } from "../../model-select.js";
|
|
4
4
|
import { modelUnavailableMessage } from "../../model-entry-refusal.js";
|
|
5
5
|
import { redactSecrets } from "../../trace/redact.js";
|
|
6
|
+
import { admitProviderEcho } from "../../observability/run-terminal.js";
|
|
6
7
|
import { sendJson, sendError, httpErrorCode, msg } from "../send.js";
|
|
7
8
|
import { gatedPrincipal, sendPrincipalRefusal } from "../principal-gate.js";
|
|
8
9
|
import { assertNever } from "../route-ctx.js";
|
|
@@ -28,6 +29,12 @@ function isModelRole(value) {
|
|
|
28
29
|
function passthroughModelRole(value) {
|
|
29
30
|
return value;
|
|
30
31
|
}
|
|
32
|
+
function shapeSideQueryEcho(result) {
|
|
33
|
+
if (result.responseModel === undefined || admitProviderEcho(result.responseModel, "side-query.responseModel"))
|
|
34
|
+
return result;
|
|
35
|
+
const { responseModel: _outOfShape, ...admitted } = result;
|
|
36
|
+
return admitted;
|
|
37
|
+
}
|
|
31
38
|
export async function handleSideQuery(req, res, match, ctx) {
|
|
32
39
|
const { deps } = ctx;
|
|
33
40
|
const { readJson, rateLimited, quotaExceeded, leaseDenied } = ctx.helpers;
|
|
@@ -100,7 +107,7 @@ export async function handleSideQuery(req, res, match, ctx) {
|
|
|
100
107
|
deps.sideQueryAccounting?.(principal, { model: modelId, usage: rr.usage });
|
|
101
108
|
deps.metrics?.inc?.("side_query_total", { result: "ok" });
|
|
102
109
|
if (!res.writableEnded)
|
|
103
|
-
sendJson(res, 200, result);
|
|
110
|
+
sendJson(res, 200, shapeSideQueryEcho(result));
|
|
104
111
|
}
|
|
105
112
|
catch (e) {
|
|
106
113
|
deps.metrics?.inc?.("side_query_total", { result: "error" });
|
|
@@ -22,6 +22,7 @@ import { buildApprovalPreamble, buildApprovalPreambleSseFrames } from "../../app
|
|
|
22
22
|
import { createApprovalCardEmitter, resolveApprovalLeg, resolveStreamApprovalGate } from "../../tool-approval.js";
|
|
23
23
|
import { buildActiveRunConflict, toDoneFrameResult } from "../active-run-conflict.js";
|
|
24
24
|
import { commitPlacement, devicePlacementErrorBody } from "../device-placement.js";
|
|
25
|
+
import { commitSessionInheritEnv } from "../session-inherit-env.js";
|
|
25
26
|
import { headerStr, gatedPrincipal, explicitOperatorOk } from "../principal-gate.js";
|
|
26
27
|
import { failOpenTagForDroppedFrame, recordFailOpen } from "../../observability/fail-open.js";
|
|
27
28
|
import { buildSyncSubmitBody } from "../sync-submit-body.js";
|
|
@@ -248,6 +249,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
248
249
|
}
|
|
249
250
|
durableTaskId = tid;
|
|
250
251
|
}
|
|
252
|
+
commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
|
|
251
253
|
if (prepared.spec.sessionId)
|
|
252
254
|
markChildrenStoppedByUserOnAbort(ac.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.principal);
|
|
253
255
|
let ledgerSink;
|
|
@@ -633,7 +635,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
633
635
|
if (deps.toolApproval) {
|
|
634
636
|
const toolApproval = deps.toolApproval;
|
|
635
637
|
prepared.spec.onAsk = windowZero
|
|
636
|
-
?
|
|
638
|
+
? toolApproval.boundUnattendedAsk({ owner: askOwner, taskId: askTaskId, ...(prepared.spec.sessionId ? { sessionId: prepared.spec.sessionId } : {}) })
|
|
637
639
|
: toolApproval.boundAsk({
|
|
638
640
|
owner: askOwner,
|
|
639
641
|
taskId: askTaskId,
|
|
@@ -795,6 +797,7 @@ export async function handleTasks(req, res, match, ctx) {
|
|
|
795
797
|
deps.sessionTitler?.maybeTitle(prepared.spec.sessionId, prepared.spec.objective, typeof prepared.spec.model === "string" ? prepared.spec.model : prepared.spec.model?.id);
|
|
796
798
|
durableTaskId = tid;
|
|
797
799
|
}
|
|
800
|
+
commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
|
|
798
801
|
if (deps.checkpointStore && prepared.spec.sessionId) {
|
|
799
802
|
await deps.checkpointStore.putCtx(prepared.spec.sessionId, { body: prepared.body, memoryScope: prepared.auth?.memoryScope });
|
|
800
803
|
}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*
|
|
7
7
|
* ⚠️ 三块都跑在全局 service-credential 门**之前**(与 /metrics 同款待遇)——只读 traceToken 单凭据的调用方
|
|
8
8
|
* (registry 中继的姿势)在全局门会被 401,挂门后=门内 traceToken 支持成死代码(1.148 a2 实机抓获)。
|
|
9
|
+
* S-672(7.105.0):门前不等于不设防 —— 本域坐在读路谓词段,先过 `dispatch.ts` 的 `readCredentialOk`
|
|
10
|
+
* (部署配了 service 凭据时要「service token / traceToken / 已验 principal」之一),块内这几道门在它之后。
|
|
9
11
|
* 因此本域在 `handle()` 里的位置就是契约的一部分:必须留在鉴权门上方,顺序不可与其他域对调。本域零可变状态。
|
|
10
12
|
*/
|
|
11
13
|
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { projectEvents, taskSummary, mapTraceEvent } from "../../trace/project.js";
|
|
2
|
+
import { redactLedgerEventForRead } from "../../observability/run-terminal.js";
|
|
2
3
|
import { projectArtifacts } from "../../trace/artifacts.js";
|
|
3
4
|
import { usageSummary, usageSeries, usageBreakdown } from "../../usage-analytics.js";
|
|
4
5
|
import { sleep } from "../sse-log.js";
|
|
@@ -220,6 +221,7 @@ async function handleToolResult(res, store, runStore, taskId, ownedRun, ref, que
|
|
|
220
221
|
return notFound();
|
|
221
222
|
sendJson(res, 200, { content: slice.content, offset: slice.offset, totalChars: slice.totalChars });
|
|
222
223
|
}
|
|
224
|
+
const readFaceEvent = (ev) => ({ ...ev, data: redactLedgerEventForRead(ev.type, ev.data) });
|
|
223
225
|
async function handleTaskTurns(res, runStore, taskId, query) {
|
|
224
226
|
const run = await runStore.getRun(taskId);
|
|
225
227
|
if (!run) {
|
|
@@ -229,7 +231,7 @@ async function handleTaskTurns(res, runStore, taskId, query) {
|
|
|
229
231
|
const limit = Math.min(100, Math.max(1, Number(query.get("limit") ?? 20) || 20));
|
|
230
232
|
const cursorSeq = Number(query.get("cursor") ?? 0) || 0;
|
|
231
233
|
const [events, retainedFrom] = await Promise.all([runStore.getEvents(taskId, 0), runStore.retainedFrom(taskId)]);
|
|
232
|
-
const all = projectEvents(events);
|
|
234
|
+
const all = projectEvents(events.map(readFaceEvent));
|
|
233
235
|
const eligible = cursorSeq > 0 ? all.filter((t) => t.seq < cursorSeq) : all;
|
|
234
236
|
const turns = eligible.slice(Math.max(0, eligible.length - limit));
|
|
235
237
|
const oldest = turns[0];
|
|
@@ -244,13 +246,6 @@ async function streamTaskTrace(req, res, runStore, taskId, staleMs, search) {
|
|
|
244
246
|
}
|
|
245
247
|
const lastId = Number(req.headers["last-event-id"] ?? new URLSearchParams(search).get("from") ?? 0);
|
|
246
248
|
let from = Number.isFinite(lastId) ? lastId : 0;
|
|
247
|
-
if (from > 0) {
|
|
248
|
-
const retainedFrom = await runStore.retainedFrom(taskId);
|
|
249
|
-
if (retainedFrom > from + 1) {
|
|
250
|
-
sendError(res, 416, "limit.retention_evicted", "resume point evicted past retention", { retainedFrom });
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
249
|
sseHeaders(res);
|
|
255
250
|
res.write(`event: meta\ndata: ${JSON.stringify({ type: "meta", version: 1, mode: "delta", resumeFrom: from })}\n\n`);
|
|
256
251
|
let closed = false;
|
|
@@ -261,7 +256,7 @@ async function streamTaskTrace(req, res, runStore, taskId, staleMs, search) {
|
|
|
261
256
|
let lastBeat = Date.now();
|
|
262
257
|
const write = (events) => {
|
|
263
258
|
for (const ev of events) {
|
|
264
|
-
const out = mapTraceEvent(ev.type, ev.seq, (ev.data ?? {}));
|
|
259
|
+
const out = mapTraceEvent(ev.type, ev.seq, (readFaceEvent(ev).data ?? {}));
|
|
265
260
|
if (out)
|
|
266
261
|
res.write(`id: ${ev.seq}\nevent: ${out.event}\ndata: ${JSON.stringify(out.data)}\n\n`);
|
|
267
262
|
from = ev.seq;
|
package/dist/http/server.d.ts
CHANGED
|
@@ -104,18 +104,27 @@ export interface ServiceCoreDeps {
|
|
|
104
104
|
* 缺席(桩)⇒ 只走结构化日志终点,行为逐字不变。
|
|
105
105
|
* ⚠️ 7.69.0(R-1)起 **resume 家族也递这一位** —— 四条 resume 腿收敛到 `resolveResumeSpec` 一只 resolver,
|
|
106
106
|
* 通告口接一次、四腿同得(见 http/server.ts 的 `resolveResumeSpec` 顶注);此处旧注写作「resume 家族缺席」
|
|
107
|
-
* 已过期,按新行为改。
|
|
107
|
+
* 已过期,按新行为改。
|
|
108
|
+
* `opts.unattendedLeg`(S-877 候裁 18,codex r3 F1):续跑家族在 ctx 带无人值守标(`CheckpointCtx.unattendedLeg`)时递 `true` ——
|
|
109
|
+
* 装配器在**全部折叠之后**经 `createUnattendedLeg` / `withUnattendedLeg` 重挂那条腿(表 / 根取续跑 Runner 的同名座)。只由续跑腿
|
|
110
|
+
* 按服务端写的 ctx 位递,绝不从请求体读。 */
|
|
108
111
|
resolveSpec: (body: TaskRequestBody, req: IncomingMessage | undefined, auth?: RequestAuth, opts?: {
|
|
109
112
|
leg?: "fresh" | "resume";
|
|
110
113
|
liveStream?: boolean;
|
|
111
114
|
onNotice?: (notice: EngineNotice) => void;
|
|
115
|
+
unattendedLeg?: true;
|
|
112
116
|
}) => TaskSpec | Promise<TaskSpec>;
|
|
113
117
|
/**
|
|
114
118
|
* [ref] 场景 hands lane 选路:按 `resolveSpec` 刚产出的 TaskSpec 取本任务的执行 Runner。
|
|
115
|
-
* 装配点(
|
|
116
|
-
*
|
|
119
|
+
* 装配点(`boot/stage-10-http-server.ts`)传的是 `createHandsRunnerSelector` —— 选路规则只有那一份实现,
|
|
120
|
+
* 本层不解释场景,只取用。
|
|
121
|
+
* 🔴 **必填**(S-175,7.105.0):修前这一席可选,缺席 ⇒ 静默落 {@link ServiceDeps.runner} —— 最宽的那只
|
|
122
|
+
* (带全量手的主 Runner)。而同一轴上「车道**字段**缺席」早已是拒(S-149,`handsLaneOf` 抛
|
|
123
|
+
* `HandsLaneUnstampedError`),席缺席回落最宽 = 同一件事两条律。现在缺席是**编译错**;绕过类型
|
|
124
|
+
* (JS 嵌入方 / `as` 硬转)造的 deps 在 {@link createHttpServer} 入口**拒启**。单 Runner 的嵌入方显式传
|
|
125
|
+
* `runnerFor: () => runner` —— 那是一句表态,不是一个回落。
|
|
117
126
|
*/
|
|
118
|
-
runnerFor
|
|
127
|
+
runnerFor: (spec: TaskSpec) => Runner;
|
|
119
128
|
}
|
|
120
129
|
/** **durable 持久面**:每个键 present ⇔ 对应路由/能力位在场,absent ⇒ 501(诚实缺席),
|
|
121
130
|
* 绝不静默降级。装配点 = main.ts 的 store backend 开箱段。 */
|
|
@@ -334,6 +343,12 @@ export interface ServiceSeamDeps {
|
|
|
334
343
|
* 所以三者的在场性是同一个事实;族内 501 谓词因此可以是「三件齐」这一句话。
|
|
335
344
|
*/
|
|
336
345
|
deviceEnrollment?: import("../device-enrollment.js").DeviceEnrollment;
|
|
346
|
+
/**
|
|
347
|
+
* S-895 × 7.106.0 合并复审 X1:host 车道会话登记簿的 `inheritEnv` **写口**(`boot/execution-env.ts` 的 `setSessionInheritEnv`)。
|
|
348
|
+
* 唯一调用者 = `http/session-inherit-env.ts` 的 `commitSessionInheritEnv`(四个 run 认领点在认领之后调;判据与残余见那只文件)。
|
|
349
|
+
* 缺席 = 本部署不是 host 车道(没有工厂读这一格)⇒ 提交点 no-op。装配 = `boot/stage-10-http-server.ts`(host 车道才给)。
|
|
350
|
+
*/
|
|
351
|
+
bindSessionInheritEnv?: import("./session-inherit-env.js").SessionInheritEnvCommitCtx["bindSessionInheritEnv"];
|
|
337
352
|
/** Audit回溯: current context (+ summary) for a session, plus its owner. Enables GET /v1/sessions/:id. */
|
|
338
353
|
sessionAudit?: (sessionId: string) => Promise<({
|
|
339
354
|
owner: string | null;
|
|
@@ -646,8 +661,14 @@ export interface ServiceDeploymentDeps {
|
|
|
646
661
|
* main.ts passes the effective store label (`durable(pg)` / `durable(mysql)` / `durable(local)` / "memory",
|
|
647
662
|
* same derivation as the boot `listening` log). Absent → fall back to the raw config enum. */
|
|
648
663
|
sessionStoreLabel?: string;
|
|
649
|
-
/** S5
|
|
650
|
-
|
|
664
|
+
/** S5 → S-866 ①:持久化姿态的**唯一**装配值(`store-posture.ts`,`boot/stores.ts` 铸):`/health` 的 `storeDegraded` / `durable:false`
|
|
665
|
+
* (present-iff `degradedReason` 在场)与 caps `store` 同读它,gauge `store_backend_degraded` 在装配点读同一只。
|
|
666
|
+
* 缺席 = 这个进程不是由 composition root 装起来的(测试夹具形)⇒ `/health` 不带降级位、caps `store` 取诚实下限
|
|
667
|
+
* (`declared` = 配置词,`backend:"memory"` —— 本面不知道任何装出来的后端)。 */
|
|
668
|
+
storePosture?: import("../store-posture.js").StorePosture;
|
|
669
|
+
/** S-866 ②:caps `centerWiring` 的读面(`capabilities/center-wiring.ts` `createCenterWiringReader`;入参 = 请求的已验 principal)。
|
|
670
|
+
* 缺席 = 没接中心(或测试夹具)⇒ 键整个缺席。 */
|
|
671
|
+
centerWiring?: (principal: string | undefined) => import("../capabilities/center-wiring.js").CenterWiring;
|
|
651
672
|
/**
|
|
652
673
|
* Graceful drain — shared mutable state between main.ts (flips `draining` on SIGTERM) and this server:
|
|
653
674
|
* • while `draining`, NEW model-running submissions (the billable submit paths) get 503 + Retry-After, so an
|
|
@@ -749,7 +770,7 @@ export interface ServiceDeploymentDeps {
|
|
|
749
770
|
/** S-131:SQL 引擎姿态的 **live getter**(`sql-engine-posture.ts` 的单一推导点 —— boot 期借一条池连接
|
|
750
771
|
* 触发驱动的连接初始化,读的是 `SET` 之后**回读复核**过的真值)。两个读面共用:
|
|
751
772
|
* `GET /v1/diagnostics/wiring` 的 `sqlEngine` 段(operator-only,全量含版本)与 `GET /v1/capabilities`
|
|
752
|
-
* 的 `sql` 位(
|
|
773
|
+
* 的 `store.sql` 位(窄投影;7.106.0 前是顶层 `sql`,S-866 ①)。getter 而不是快照:池重连后驱动会重新初始化并刷新事实,快照会说谎。
|
|
753
774
|
* 缺席 / 返回 null = 本部署没有 SQL 后端(env-only worker、local 文件后端)—— 诚实缺席,不铸空壳。 */
|
|
754
775
|
sqlEngineFacts?: () => import("../plugins/sql-driver.js").SqlEngineFacts | null;
|
|
755
776
|
/** S-138:**写保护名表**的姿态(`write-protection.ts` 的 boot 期单一推导点 —— 与递给每只 Runner 的
|
|
@@ -856,7 +877,7 @@ export declare function createHttpServer(rawDeps: ServiceDeps): http.Server & {
|
|
|
856
877
|
/** SSE: replay durable events after Last-Event-ID, then tail until the run is terminal (or stale). */
|
|
857
878
|
/**
|
|
858
879
|
* The differences a concrete log (task_run | image_bake) feeds the ONE resumable SSE reader (P2.8). Everything
|
|
859
|
-
* the reader does — Last-Event-ID/`?from=` resume
|
|
880
|
+
* the reader does — Last-Event-ID/`?from=` resume (every row with seq > from; no eviction answer, S-211 ①), the per-poll concurrent
|
|
860
881
|
* status+events read, the terminal re-fetch (the terminal event lands in the gap before the status flips), the
|
|
861
882
|
* stale fallback, the 15-min cap, the 15s idle heartbeat — is provider-agnostic and lives in `streamSseLog`.
|
|
862
883
|
* 🔴 The task_run provider MUST keep the existing wire bytes EXACTLY (center's relay + 730+ tests depend on it).
|
package/dist/http/server.js
CHANGED
|
@@ -38,6 +38,9 @@ export function flattenServiceDeps(deps) {
|
|
|
38
38
|
}
|
|
39
39
|
export function createHttpServer(rawDeps) {
|
|
40
40
|
const deps = flattenServiceDeps(rawDeps);
|
|
41
|
+
if (typeof deps.runnerFor !== "function") {
|
|
42
|
+
throw new Error("createHttpServer: the runnerFor seat is required (it picks each task's Runner from its execution lane) — pass the hands-lane selector, or `runnerFor: () => runner` for a single-Runner embedding; refusing to start rather than run every task on the widest Runner");
|
|
43
|
+
}
|
|
41
44
|
const idemCache = new IdempotencyCache();
|
|
42
45
|
const inflightRuns = new Map();
|
|
43
46
|
const cancelledViaVerb = new Set();
|
|
@@ -118,7 +121,7 @@ export function createHttpServer(rawDeps) {
|
|
|
118
121
|
});
|
|
119
122
|
deps.deviceHub?.attach(server);
|
|
120
123
|
function runnerFor(spec) {
|
|
121
|
-
return deps.runnerFor
|
|
124
|
+
return deps.runnerFor(spec);
|
|
122
125
|
}
|
|
123
126
|
function recordTaskResult(result) {
|
|
124
127
|
const plane = outwardPlane(result.terminal);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* S-895 × 7.106.0 合并复审 X1(gpt-6 腿 A F1 [high],验证腿 B verified)—— 请求键 `inheritEnv` 的**会话绑定唯一提交点**。
|
|
3
|
+
*
|
|
4
|
+
* ── 分界(与 `device-placement.ts` 的首绑写协议同一句判据)──────────────────────────────────────────────────
|
|
5
|
+
* 凡需要「这条会话此刻归我这条 run」才成立的事,排在 run 认领之后;其余全排在建任何东西之前。`inheritEnv` 的三道判
|
|
6
|
+
* (值形 / 车道 / 射程)是**读**,住在 `resolveSpec`(两腿同判,任何副作用之前);而「本会话的 host 工厂下一次造环境按哪个词」
|
|
7
|
+
* 是**写**,它只属于一条**被受理**的 run —— 修前它写在 `resolveSpec` 的最后一步,仍先于路由层的拒(`/v1/tasks/stream` 的
|
|
8
|
+
* verify / cascade 400 `request.field_conflict`、会话占用 409、`/v1/runs` 的建行 409、placement 拒、续跑的 CAS 输 / 配额 429 …),
|
|
9
|
+
* 一条被拒的 `"all"` 于是把同会话上一条已受理的 `"scrub"` 放宽成整份继承。
|
|
10
|
+
*
|
|
11
|
+
* ── 调用点(类级机器门钉住:`test/inherit-env-request-key.test.ts`「X1 类级机器门」)───────────────────────────
|
|
12
|
+
* 四个 run 认领点在认领(与 placement 提交)成功之后、起跑之前各调一次 —— 流式提交 / 同步提交(`routes/tasks.ts`)、durable 建行腿
|
|
13
|
+
* (`durable-run-leg.ts`,`/v1/runs` · A2A · `/decide` 第三车道共用)、续跑驱动腿(`resume-legs.ts` 的 `driveResumeLeg`,markResuming
|
|
14
|
+
* 赢或 wake 新行建成之后)。无 run 店的部署没有认领这回事:调用点落在认领段**之后**的同一位置,等价于「起跑前、一切拒之后」。
|
|
15
|
+
* 写的值 = 受理时那条请求体的键(续跑腿 = 盘上那条体的键);缺席 = 清掉(缺省清洗;理由在 `setSessionInheritEnv` 顶注)。
|
|
16
|
+
*
|
|
17
|
+
* ── 残余(如实,S-908)──────────────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
* 登记簿仍按**会话**键控、host 工厂在 run 起跑那一刻现读(core `ExecutionEnvFactoryContext` 只带 sessionId / taskId,没有 per-run 座)。
|
|
19
|
+
* 有 run 店的部署上认领本身串行化同会话的 run(`task_active` 唯一键),「写 → 读」落在同一条认领窗里;没有 run 店的部署上同会话
|
|
20
|
+
* 并发受理的两条 run 仍是「最后写者赢」。续跑腿在 markResuming 赢之后写,core 的 pre-CAS 守卫(D-1 绑定 / 过期 token)之后才拒的续跑
|
|
21
|
+
* 已写下**那条 park 任务自己**盘上的值(不是别的请求的),下一条受理的 run 照写覆盖。根治 = core 的 per-run 座(S-908)。
|
|
22
|
+
* 射程只在单用户 host 部署(`"all"` 的射程门)⇒ 写者恒是同一主人。
|
|
23
|
+
*/
|
|
24
|
+
import type { TaskInheritEnv } from "../request-value-closure.js";
|
|
25
|
+
/** 提交点的依赖 —— 逐字取自 `ServiceDeps` 的同名键(同一只 deps 对象喂进来)。 */
|
|
26
|
+
export interface SessionInheritEnvCommitCtx {
|
|
27
|
+
/** host 车道会话登记簿的写口(`boot/execution-env.ts` 的 `setSessionInheritEnv`);缺席 = 本部署不是 host 车道 ⇒ 没有消费点。 */
|
|
28
|
+
bindSessionInheritEnv?: ((sessionId: string, policy: TaskInheritEnv | undefined) => void) | undefined;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 在 run 认领之后调用:把受理的那条请求的 `inheritEnv`(缺席 = 清)写进本会话的绑定。`sessionId` 缺席(不接 authorizer 的嵌入形)⇒
|
|
32
|
+
* 不写 —— `"all"` 在那一形已被 `resolveSpec` 响亮拒,`"scrub"` / 缺席与工厂缺省同形。
|
|
33
|
+
*/
|
|
34
|
+
export declare function commitSessionInheritEnv(ctx: SessionInheritEnvCommitCtx, sessionId: string | undefined, body: {
|
|
35
|
+
readonly inheritEnv?: TaskInheritEnv | undefined;
|
|
36
|
+
}): void;
|
|
37
|
+
//# sourceMappingURL=session-inherit-env.d.ts.map
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* ## 为什么注册完还要回看一眼状态
|
|
34
34
|
*
|
|
35
35
|
* 光「订阅未来事件」不够:`'close'` **只发一次**,而四条腿的接线全都排在若干次 await 之后
|
|
36
|
-
* (trace 是 `getRun
|
|
36
|
+
* (trace 是 `getRun`,runs 是 subagent probe;sse-log 自 S-211 ① 起写头前已无 await,此前是 `retainedFrom`)。客户端
|
|
37
37
|
* 在那段慢查询里断开 ⇒ 两个 close 都在监听器注册**之前**烧完(实测:后装的监听器不会被补发)⇒
|
|
38
38
|
* 清理整条不发生,泵对着死连接轮询到 15 分钟帽。这不是假想:`sse-log.ts` 的 preamble 注里记着的
|
|
39
39
|
* 同一个坑,当时只把 preamble 挪到了接线之后,而接线本身前面还有别的 await。
|
package/dist/http/sse-log.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* [ref] A9 seam —— 通用可恢复 SSE 泵(P2.8),从 `http/server.ts` 整段搬出的原文。
|
|
3
3
|
*
|
|
4
|
-
* task_run 与 image_bake 两条日志共用同一套 liveness/heartbeat
|
|
4
|
+
* task_run 与 image_bake 两条日志共用同一套 liveness/heartbeat/终态复取/15 分钟帽逻辑;域模块
|
|
5
5
|
* (routes/images.ts)与 server.ts 都要用它,所以它必须住在 http/ 叶子里(routes/* 值 import server.ts
|
|
6
6
|
* 会闭合运行时装载环)。
|
|
7
7
|
*/
|
|
@@ -17,8 +17,6 @@ export interface SseLogProvider<E extends {
|
|
|
17
17
|
} | null | undefined>;
|
|
18
18
|
/** Events with seq strictly greater than `after`, ascending. */
|
|
19
19
|
getEvents(id: string, after: number): Promise<E[]>;
|
|
20
|
-
/** Earliest retained seq → the 416 resume boundary. */
|
|
21
|
-
retainedFrom(id: string): Promise<number>;
|
|
22
20
|
/** Map ONE event to its SSE frame (the `id:`/`event:`/`data:` lines differ per log). */
|
|
23
21
|
formatEvent(ev: E): {
|
|
24
22
|
id: number;
|
|
@@ -31,13 +29,12 @@ export interface SseLogProvider<E extends {
|
|
|
31
29
|
data: unknown;
|
|
32
30
|
};
|
|
33
31
|
/**
|
|
34
|
-
* [ref] 车3 §5:**开流 preamble** —— 在
|
|
32
|
+
* [ref] 车3 §5:**开流 preamble** —— 在 `sseHeaders` **之后**、日志 tail **之前**写的
|
|
35
33
|
* 一批**非账本**帧(今天唯一的用户 = 审批未决卡的全量对账基准)。
|
|
36
34
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* headers-already-sent),而调用方自己先调 `sseHeaders` 又会被本 helper 重复写头。
|
|
35
|
+
* 为什么是这里的内部 hook,而不是调用方在 `streamSseLog` **之前**自己写:写头是本 helper 的事,调用方
|
|
36
|
+
* 先调 `sseHeaders` 会被这里重复写头。(S-211 ① 之前本 helper 在写头之前还有一道 416 判定,那是这条
|
|
37
|
+
* 理由的另一半 —— 判定随「账本不存在局部头部裁剪」一起删了,见 {@link streamSseLog} 头注。)
|
|
41
38
|
*
|
|
42
39
|
* 返回帧**不带 `id:`** —— 它不是账本行,不参与 `Last-Event-ID` 游标(壳的规则:preamble 给的是
|
|
43
40
|
* 权威全量卡集,账本重放里的同 id 帧只用于时间线渲染)。
|
|
@@ -83,7 +80,13 @@ export declare function collectSsePreamble(preamble: (signal: AbortSignal) => Pr
|
|
|
83
80
|
data: unknown;
|
|
84
81
|
}>>;
|
|
85
82
|
/** The shared resumable SSE pump (P2.8) — provider supplies the log-specific differences; the liveness/
|
|
86
|
-
* heartbeat/
|
|
83
|
+
* heartbeat/terminal-re-fetch/15-min-cap logic is identical for task_run + image_bake.
|
|
84
|
+
*
|
|
85
|
+
* 🔴 S-211 ①:**没有「续读点已被淘汰」这一答**。两条日志都**没有局部头部裁剪腿** —— `task_event` 唯一的删除者
|
|
86
|
+
* 是整棵会话树连删(会话删除 / 托管留存,`task_run` 行同批消失 ⇒ 调用方开流前 404),`image_bake_event` 库里一条
|
|
87
|
+
* 删除语句都没有。此前这里按 `retainedFrom > from + 1` 答 416 `limit.retention_evicted`:真淘汰永远走不到它,
|
|
88
|
+
* 唯一走得到的形是「写失败耗掉了号」留下的**头部缺行**(ledger-sink 账本留洞)—— 那一形里什么都没被淘汰,416
|
|
89
|
+
* 是一句谎。续读语义因此只有一句:投 `seq > from` 的每一行(缺的行就是缺的,不补、不猜)。 */
|
|
87
90
|
export declare function streamSseLog<E extends {
|
|
88
91
|
seq: number;
|
|
89
92
|
}>(req: IncomingMessage, res: ServerResponse, provider: SseLogProvider<E>, id: string, staleMs: number): Promise<void>;
|
package/dist/http/sse-log.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { bindSseLifecycle } from "./sse-lifecycle.js";
|
|
2
|
-
import {
|
|
2
|
+
import { sseHeaders, SSE_MAX_STREAM_MS, SSE_HEARTBEAT_IDLE_MS } from "./send.js";
|
|
3
3
|
export const SSE_PREAMBLE_TIMEOUT_MS = 2_000;
|
|
4
4
|
export async function collectSsePreamble(preamble, onFailure, timeoutMs = SSE_PREAMBLE_TIMEOUT_MS) {
|
|
5
5
|
const timedOut = Symbol("preamble-timeout");
|
|
@@ -34,13 +34,6 @@ export async function collectSsePreamble(preamble, onFailure, timeoutMs = SSE_PR
|
|
|
34
34
|
export async function streamSseLog(req, res, provider, id, staleMs) {
|
|
35
35
|
const lastId = Number(req.headers["last-event-id"] ?? new URL(req.url ?? "", "http://x").searchParams.get("from") ?? 0);
|
|
36
36
|
let from = Number.isFinite(lastId) ? lastId : 0;
|
|
37
|
-
if (from > 0) {
|
|
38
|
-
const retainedFrom = await provider.retainedFrom(id);
|
|
39
|
-
if (retainedFrom > from + 1) {
|
|
40
|
-
sendError(res, 416, "limit.retention_evicted", "resume point evicted past retention", { retainedFrom });
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
37
|
sseHeaders(res);
|
|
45
38
|
let closed = false;
|
|
46
39
|
bindSseLifecycle(req, res, () => {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* cut: ONLY TaskRequestBody (its field types are inline or core imports — no other server.ts-local satellites);
|
|
7
7
|
* sibling request/response shapes can migrate here later on the same pattern.
|
|
8
8
|
*/
|
|
9
|
-
import type { A2aServerSpec, AgentDefinition,
|
|
9
|
+
import type { A2aServerSpec, AgentDefinition, McpServerSpec, SkillSpec } from "@sema-agent/core";
|
|
10
10
|
import type { SettingsPermissionMode } from "../task-settings.js";
|
|
11
11
|
import type { wiringManifestFaceEventData } from "../trace/project.js";
|
|
12
12
|
import type { buildSyncSubmitBody } from "./sync-submit-body.js";
|
|
@@ -197,8 +197,9 @@ export interface TaskRequestBody {
|
|
|
197
197
|
* 这条 run 零历史店调用:编辑照常落盘,但不做首次触碰备份、不铸回合边界、不做 fork 携带;委派出去的子代继承
|
|
198
198
|
* (core `ParentSpecSeat` 从本位铸,本仓零接线)。`wiring_manifest.fileHistory` 报 `"disabled"`。
|
|
199
199
|
* 同一个提交里再要还原(`restoreFiles` / `rewindFilesTo` / 退役 `rewindFiles`)= 体内矛盾 ⇒ **受理时** 400
|
|
200
|
-
* `request.field_conflict`(`request-value-closure.ts` 的 `FILE_HISTORY_DISABLED_NO_RESTORE`)
|
|
201
|
-
* 落在会话按 `resumeAt`
|
|
200
|
+
* `request.field_conflict`(`request-value-closure.ts` 的 `FILE_HISTORY_DISABLED_NO_RESTORE`):立门时 core 的 `rewind.capture_disabled`
|
|
201
|
+
* 落在会话按 `resumeAt` 分叉之后、拒后不回滚,所以本层在副作用之前拒(S-865 / core 7.35.0 #1195 起 core 在分叉**之前**拒,
|
|
202
|
+
* 本层 400 照旧有效)。续跑腿不过这道门。
|
|
202
203
|
* ⚠️ 拼写门**两腿同判、响亮拒**:fresh 400 `request.field_invalid`;resume 重放同判(与 `memoryCapture` / `memory`
|
|
203
204
|
* 同一张单成员闭集表,`request-value-closure.ts` 的 `singleMemberOffFieldIssue`)。
|
|
204
205
|
* Rides the persisted body onto resume legs —— 它是这条 run 的策略,不是一次性历史动作(与 `rewindFilesTo` 不同,续跑不剥)。 */
|
|
@@ -330,31 +331,6 @@ export interface TaskRequestBody {
|
|
|
330
331
|
* `SETTINGS_PERMISSION_MODES`(受理腿 `isSettingsPermissionMode` 与两句 400 文案同读那一份)。
|
|
331
332
|
* 改前这里是第 6 份手抄的五词联合 —— 加/退一个模式时 wire 型面与受理腿会各走各的。 */
|
|
332
333
|
permissionMode?: SettingsPermissionMode;
|
|
333
|
-
/**
|
|
334
|
-
* **#1000**(core 7.26.0 `TaskSpec.approverPosture`;CC-116 装配口)—— 宿主对这个 run 的**审批姿态声明**:
|
|
335
|
-
* 「这些卡由我自己自动答」。一个词(`"bypass"`),闭集属主在 core(`ApproverPosture` / `APPROVER_POSTURES`)。
|
|
336
|
-
*
|
|
337
|
-
* 🔴 **它不授权任何东西,也不是一只门**(core 头注逐字:"a statement about who answers this run's approval
|
|
338
|
-
* cards, never an instruction to the gate";引擎只把它**渲**给模型,没有任何裁决腿读它)。所以它与
|
|
339
|
-
* {@link permissionMode} 的 `"bypassPermissions"` **不是**一回事,也不能互相派生:后者选的是**门的形状**
|
|
340
|
-
* (且只能收紧、deny-wins),前者只说「谁来答卡」。两者在语义上同族,声明它而不开 `bypassPermissions`
|
|
341
|
-
* 只是对模型说了一句与实际不符的话 —— 见契约文档那一段的「谁受伤」。
|
|
342
|
-
*
|
|
343
|
-
* 🔴 **值域上本仓零判据**(`boot/resolve-spec.ts` 写点):词的拒绝逻辑属引擎
|
|
344
|
-
* (`refuseInvalidApproverPosture` 响亮拒一个不认识的词),server **不抄词表、不加第二道值域门** ——
|
|
345
|
-
* 在下游再判一次就是同一语义面的第二个判官(源头修复纪律 [ref]),而且本仓抄一份词表的那天 core 加
|
|
346
|
-
* 第二个词就会被静默 400 掉。型也从 core 的 `ApproverPosture` 派生(不抄字面联合)。
|
|
347
|
-
*
|
|
348
|
-
* 🔴 **但「原样过境」自 7.95.0(S-591 腿③)起不再成立 —— 它有一道**准入**闸**:本键是一句**宿主姿态
|
|
349
|
-
* 声明**(「这个 run 的审批卡由宿主自己自动答」),而在**托管 / 多租**部署上提交方**不是**宿主。
|
|
350
|
-
* 所以托管形上它被**忽略 + 留声**(`task_approver_posture_ignored`,`honored:false`),与同族的
|
|
351
|
-
* `settings.hooks` / `cwd` / `settings.env` 三条逐字同姿势;单用户 turnkey 与 device 车道照旧过境
|
|
352
|
-
* (射程判据单点 = `src/hosted-posture.ts` 的 `taskApproverPostureHonored`)。
|
|
353
|
-
* ⚠️ **刻意不是 400/422**:本键零授权,而续跑腿逐字重放盘上的体、调用方删不掉它 ⇒ 拒会把一条 parked
|
|
354
|
-
* 任务永久砖死(clay 裁定① 2026-09-22;本仓成文结论「砖死 resume 比降级糟」)。
|
|
355
|
-
* ⇒ 这一条与「值域零判据」**不矛盾**:值域仍归引擎,本仓判的是**这台部署认不认这句声明**。
|
|
356
|
-
*/
|
|
357
|
-
approverPosture?: ApproverPosture;
|
|
358
334
|
/** MF-30 memory PAUSE (shell-host contract, option B per-request — clay 2026-06-27): `false` makes THIS run
|
|
359
335
|
* read-only over long-term memory (`TaskSpec.memory.writeScope:null` — the [ref] memory ENGINE materializes/
|
|
360
336
|
* reads but its harvest commits nothing). Absent/`true` ⇒ normal read+write. The shell's `/memory` pause carries
|
|
@@ -418,6 +394,21 @@ export interface TaskRequestBody {
|
|
|
418
394
|
* (a caller can't point a shared/cloud worker at an arbitrary host path). Validated absolute (prepareSpec 400s a
|
|
419
395
|
* relative cwd — it would silently resolve against the SERVICE process cwd). */
|
|
420
396
|
cwd?: string;
|
|
397
|
+
/**
|
|
398
|
+
* S-895(7.106.0,core [ref] [ref] ②)—— 模型驱动的 host shell **继承多少用户环境**,由调用方按请求声明。
|
|
399
|
+
* 闭集两词(词表外 ⇒ 400 `request.field_invalid`,两腿同判,判据属主 `request-value-closure.ts` 的 `inheritEnvFieldIssue`):
|
|
400
|
+
* · `"all"` —— 整份继承(`{ ...process.env }` 逐字原样,CC 交互形);只在**单用户**部署兑现,射程 = 写容纳面那一只
|
|
401
|
+
* `hostPostureDeclarationsHonored`(`hosted-posture.ts`)⇒ 托管部署(`REQUIRE_PRINCIPAL=true`)响亮拒
|
|
402
|
+
* 422 `request.host_posture_refused`;
|
|
403
|
+
* · `"scrub"` —— 缺省清洗(剥凭据形变量),**任何车道、任何部署**都受理(它就是缺省;7.106.0 合并复审 X7)。
|
|
404
|
+
* **缺席 = 缺省清洗**:不带键的请求把本会话的绑定清掉(不继承上一条请求的声明 —— 这一位是「本条请求要什么」,
|
|
405
|
+
* 粘到下一条上就是替一个没说话的请求放宽)。名单形(`string[]`)**不上 wire**(那是嵌入方构造执行环境的选项)。
|
|
406
|
+
* 🔒 **只有 host 车道有消费点**:别的车道(e2b / k8s / local-docker / ssh / adb / device / in-process)带 `"all"` ⇒
|
|
407
|
+
* 400 `request.field_invalid`「applies to the host lane only」,不静默忽略、不映射到别的车道的 env 名单;`"scrub"` 在那些车道上照受理(无消费点,无害)。
|
|
408
|
+
* Rides the persisted body onto resume legs:重放照射程与车道重判(部署由单用户改托管后 revive ⇒ 同一只拒,
|
|
409
|
+
* resume-legs 折成 `409 resume_blocked_by_policy`)。
|
|
410
|
+
*/
|
|
411
|
+
inheritEnv?: "all" | "scrub";
|
|
421
412
|
/**
|
|
422
413
|
* S-470(device lane 首绑写协议,design `device-executor-lane-v2` §4.3.2)—— 这条**根会话**要执行在
|
|
423
414
|
* 哪台已注册的员工设备上(`POST /v1/devices/enroll` 返回的 `dev_<ulid>`)。
|
package/dist/index.d.ts
CHANGED
|
@@ -26,5 +26,6 @@ export type { TaskRequestBody } from "./http/wire-types.js";
|
|
|
26
26
|
export { createHttpServer, type ServiceDeps, type RequestAuth, type FlatServiceDeps, type ServiceDepGroups, type ServiceCoreDeps, type ServiceStoreDeps, type ServiceCoordinatorDeps, type ServiceSeamDeps, type ServiceObservabilityDeps, type ServiceGovernanceDeps, type ServiceDeploymentDeps, type ServiceKnobDeps, } from "./http/server.js";
|
|
27
27
|
export { createSideQueryLane, createPerModelKeyBrain, type KeyResolver, type SideQueryLane, type SideQueryLaneCtx } from "./boot/side-query-lane.js";
|
|
28
28
|
export { createKeyResolver, resolveModelApiKey, type ModelKeyRef } from "./key-resolver.js";
|
|
29
|
-
export {
|
|
29
|
+
export { isModelKeyPoison, ModelKeyPoisonedError, type ModelKeyPoison, type ModelKeyPoisonReason } from "./key-resolver.js";
|
|
30
|
+
export { RETIRED_ENVS, type RetiredEnv, type RetiredEnvKind, type RetiredEnvWire } from "./config.js";
|
|
30
31
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -23,5 +23,6 @@ export { memoryScopeFor, memoryEngineBackendFor } from "./memory-scope.js";
|
|
|
23
23
|
export { createHttpServer, } from "./http/server.js";
|
|
24
24
|
export { createSideQueryLane, createPerModelKeyBrain } from "./boot/side-query-lane.js";
|
|
25
25
|
export { createKeyResolver, resolveModelApiKey } from "./key-resolver.js";
|
|
26
|
-
export {
|
|
26
|
+
export { isModelKeyPoison, ModelKeyPoisonedError } from "./key-resolver.js";
|
|
27
|
+
export { RETIRED_ENVS } from "./config.js";
|
|
27
28
|
//# sourceMappingURL=index.js.map
|