@sema-agent/server 7.139.0 → 7.141.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 +471 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +94 -26
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/approval-batch-census.d.ts +27 -0
- package/dist/approval-batch-census.js +27 -0
- package/dist/approval-card.d.ts +37 -22
- package/dist/approval-card.js +6 -3
- package/dist/approval.d.ts +15 -0
- package/dist/approval.js +10 -0
- package/dist/audit.d.ts +4 -2
- package/dist/audit.js +2 -2
- package/dist/bench/s1/live-deps.js +3 -2
- package/dist/bench/s1/row.d.ts +5 -2
- package/dist/bench/s1/row.js +2 -22
- package/dist/boot/adoption.js +1 -1
- package/dist/boot/device-lane.d.ts +11 -0
- package/dist/boot/device-lane.js +16 -0
- package/dist/boot/engine-lease.d.ts +24 -3
- package/dist/boot/engine-lease.js +9 -2
- package/dist/boot/execution-env.js +18 -12
- package/dist/boot/execution-lane.d.ts +8 -0
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/memory-boundary.d.ts +16 -53
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +16 -12
- package/dist/boot/memory-consolidation.js +24 -13
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/resolve-spec.d.ts +3 -5
- package/dist/boot/resolve-spec.js +9 -8
- package/dist/boot/runner-deps.d.ts +3 -3
- package/dist/boot/runner-deps.js +1 -0
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +4 -3
- package/dist/boot/shutdown.js +5 -0
- package/dist/boot/stage-03-store-backend.d.ts +2 -6
- package/dist/boot/stage-03-store-backend.js +2 -3
- package/dist/boot/stage-04-stores.d.ts +2 -6
- package/dist/boot/stage-04-stores.js +5 -5
- package/dist/boot/stage-05-execution-env.d.ts +2 -6
- package/dist/boot/stage-05-execution-env.js +3 -1
- package/dist/boot/stage-06-runners.d.ts +2 -8
- package/dist/boot/stage-06-runners.js +3 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -7
- package/dist/boot/stage-07-capability-layer.js +8 -10
- package/dist/boot/stage-08-reapers.d.ts +2 -7
- package/dist/boot/stage-09-leader.d.ts +2 -7
- package/dist/boot/stage-10-http-server.d.ts +2 -7
- package/dist/boot/stage-10-http-server.js +6 -4
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +37 -44
- package/dist/boot/task-list-lane.d.ts +1 -1
- package/dist/boot/task-list-lane.js +1 -1
- package/dist/boot/web-admin.js +36 -9
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +9 -0
- package/dist/capability-facts.js +9 -0
- package/dist/card-void.d.ts +38 -0
- package/dist/card-void.js +23 -0
- package/dist/config-catalog.js +12 -8
- package/dist/config-provider.d.ts +18 -17
- package/dist/config-provider.js +28 -36
- package/dist/config-types.d.ts +36 -9
- package/dist/config.js +56 -46
- package/dist/delegated-session-owner.d.ts +23 -20
- package/dist/delegated-session-owner.js +2 -2
- package/dist/deployment-shape.d.ts +9 -8
- package/dist/deployment-shape.js +4 -4
- package/dist/device-store.d.ts +7 -0
- package/dist/device-store.js +3 -0
- package/dist/execution-config-root.d.ts +22 -0
- package/dist/execution-config-root.js +35 -0
- package/dist/execution-lane-caps.d.ts +145 -107
- package/dist/execution-lane-caps.js +144 -83
- package/dist/execution-placement.d.ts +3 -0
- package/dist/execution-placement.js +7 -0
- package/dist/fleet/drain-entry.d.ts +3 -0
- package/dist/hosted-posture.d.ts +8 -0
- package/dist/hosted-posture.js +4 -0
- package/dist/http/admission.js +3 -3
- package/dist/http/caller-trust.d.ts +3 -2
- package/dist/http/caller-trust.js +2 -1
- package/dist/http/dispatch.js +4 -0
- package/dist/http/live-frame.d.ts +24 -0
- package/dist/http/live-frame.js +16 -0
- package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
- package/dist/http/memory-compliance-failure-reply.js +5 -0
- package/dist/http/memory-layer-reply.d.ts +30 -0
- package/dist/http/memory-layer-reply.js +24 -0
- package/dist/http/resume-legs.js +49 -35
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/capabilities.js +5 -4
- package/dist/http/routes/diagnostics.d.ts +0 -19
- package/dist/http/routes/diagnostics.js +16 -2
- package/dist/http/routes/memory-bundle.d.ts +2 -2
- package/dist/http/routes/memory-bundle.js +4 -1
- package/dist/http/routes/memory-compliance.js +9 -2
- package/dist/http/routes/memory-consolidation.js +12 -1
- package/dist/http/routes/memory-origin.js +14 -2
- package/dist/http/routes/memory-policy.js +7 -2
- package/dist/http/routes/run-permission-mode.d.ts +75 -0
- package/dist/http/routes/run-permission-mode.js +170 -0
- package/dist/http/routes/session-sync.d.ts +3 -6
- package/dist/http/routes/session-sync.js +7 -2
- package/dist/http/routes/sessions.js +33 -15
- package/dist/http/routes/tasks.js +67 -68
- package/dist/http/run-read-face.js +3 -3
- package/dist/http/send.d.ts +1 -1
- package/dist/http/send.js +2 -2
- package/dist/http/server.d.ts +14 -27
- package/dist/http/server.js +2 -2
- package/dist/http/sse-log.d.ts +3 -8
- package/dist/http/stored-body-replay.d.ts +3 -3
- package/dist/http/stored-body-replay.js +3 -1
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- package/dist/instruction-source-notice.d.ts +7 -0
- package/dist/instruction-source-notice.js +6 -6
- package/dist/lane-home-probe.d.ts +68 -42
- package/dist/lane-home-probe.js +53 -30
- package/dist/leader/wire.js +5 -4
- package/dist/mcp-assertion-header.d.ts +4 -0
- package/dist/mcp-assertion-header.js +5 -0
- package/dist/memory-bundle-engine.d.ts +16 -9
- package/dist/memory-bundle-engine.js +29 -6
- package/dist/memory-operator-faces.d.ts +85 -30
- package/dist/memory-operator-faces.js +136 -30
- package/dist/memory-posture.d.ts +1 -1
- package/dist/memory-project-layer.d.ts +3 -21
- package/dist/memory-project-layer.js +11 -8
- package/dist/memory-scope-stores.d.ts +73 -0
- package/dist/memory-scope-stores.js +86 -0
- package/dist/memory-scope.d.ts +33 -9
- package/dist/memory-scope.js +17 -5
- package/dist/memory-sync-client.d.ts +34 -9
- package/dist/memory-sync-client.js +108 -28
- package/dist/observability/fail-open.d.ts +30 -2
- package/dist/observability/fail-open.js +30 -2
- package/dist/observability/metrics.js +0 -1
- package/dist/observability/run-terminal.d.ts +6 -2
- package/dist/observability/run-terminal.js +25 -26
- package/dist/observability/secret-env-scrub.d.ts +20 -1
- package/dist/observability/secret-env-scrub.js +14 -0
- package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
- package/dist/orchestration/workflow-completion-inbox.js +13 -5
- package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
- package/dist/orchestration/workflow-notify-journal.js +2 -1
- package/dist/permission-mode-admission.d.ts +68 -0
- package/dist/permission-mode-admission.js +23 -0
- package/dist/permission-rule-list.d.ts +55 -6
- package/dist/permission-rule-list.js +52 -5
- package/dist/plugins/adoption-log-sql.js +4 -4
- package/dist/plugins/approval-ask-store-sql.js +14 -14
- package/dist/plugins/approval-nonce-store.js +4 -4
- package/dist/plugins/blob-backend.d.ts +4 -4
- package/dist/plugins/blob-backend.js +7 -7
- package/dist/plugins/breaker-state-sql.js +2 -2
- package/dist/plugins/caching-session-store.d.ts +6 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
- package/dist/plugins/checkpoint-store-sql.js +90 -19
- package/dist/plugins/device-store-sql.d.ts +5 -2
- package/dist/plugins/device-store-sql.js +23 -20
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +19 -9
- package/dist/plugins/execution-placement-sql.js +20 -9
- package/dist/plugins/file-history-store-sql.d.ts +2 -2
- package/dist/plugins/file-history-store-sql.js +4 -4
- package/dist/plugins/file-run-store.d.ts +2 -2
- package/dist/plugins/file-run-store.js +1 -1
- package/dist/plugins/fork-routing-session-store.d.ts +10 -32
- package/dist/plugins/fork-routing-session-store.js +2 -61
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
- package/dist/plugins/k8s-exec-protocol.js +6 -1
- package/dist/plugins/leader-run-store-sql.js +4 -4
- package/dist/plugins/local-checkpoint-store.d.ts +10 -1
- package/dist/plugins/local-checkpoint-store.js +22 -0
- package/dist/plugins/local-session-store.d.ts +227 -35
- package/dist/plugins/local-session-store.js +518 -37
- package/dist/plugins/local-session-window.d.ts +17 -3
- package/dist/plugins/local-session-window.js +7 -13
- package/dist/plugins/mailbox-store-sql.d.ts +2 -1
- package/dist/plugins/mailbox-store-sql.js +4 -4
- package/dist/plugins/memory-engine-tidb.js +5 -5
- package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
- package/dist/plugins/memory-run-store.d.ts +2 -2
- package/dist/plugins/memory-run-store.js +1 -1
- package/dist/plugins/memory-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +52 -11
- package/dist/plugins/one-time-migrations.js +101 -39
- package/dist/plugins/org-delivery-quota-store.js +2 -2
- package/dist/plugins/outcome-ledger-sql.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
- package/dist/plugins/permission-rule-store-sql.js +16 -16
- package/dist/plugins/pg-pool.js +3 -2
- package/dist/plugins/pg-session-storage.d.ts +2 -0
- package/dist/plugins/pg-session-storage.js +3 -2
- package/dist/plugins/remote-env-adb.d.ts +7 -24
- package/dist/plugins/remote-env-adb.js +22 -5
- package/dist/plugins/remote-env-device.d.ts +2 -28
- package/dist/plugins/remote-env-device.js +2 -1
- package/dist/plugins/remote-env-e2b.d.ts +40 -27
- package/dist/plugins/remote-env-e2b.js +180 -20
- package/dist/plugins/remote-env-file-error.d.ts +1 -1
- package/dist/plugins/remote-env-file-error.js +8 -2
- package/dist/plugins/remote-env-host.d.ts +19 -35
- package/dist/plugins/remote-env-host.js +26 -3
- package/dist/plugins/remote-env-k8s.d.ts +22 -14
- package/dist/plugins/remote-env-k8s.js +150 -26
- package/dist/plugins/remote-env-local-docker.d.ts +27 -24
- package/dist/plugins/remote-env-local-docker.js +91 -24
- package/dist/plugins/remote-env-ssh.d.ts +4 -24
- package/dist/plugins/remote-env-ssh.js +4 -3
- package/dist/plugins/resume-anchor-store-sql.js +2 -2
- package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
- package/dist/plugins/retention-lane-store-sql.js +2 -2
- package/dist/plugins/retention-store-sql.d.ts +1 -1
- package/dist/plugins/retention-store-sql.js +6 -6
- package/dist/plugins/run-store-sql.d.ts +3 -3
- package/dist/plugins/run-store-sql.js +19 -18
- package/dist/plugins/sandbox-read-floor.d.ts +273 -0
- package/dist/plugins/sandbox-read-floor.js +608 -0
- package/dist/plugins/schema-consistency.d.ts +6 -6
- package/dist/plugins/schema-consistency.js +1 -1
- package/dist/plugins/schema-ensure-legs.d.ts +2 -3
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/schema-live-columns.d.ts +1 -1
- package/dist/plugins/session-capture-record-store-sql.js +1 -1
- package/dist/plugins/session-ownership.d.ts +2 -1
- package/dist/plugins/session-placement.d.ts +17 -4
- package/dist/plugins/session-placement.js +2 -1
- package/dist/plugins/session-rules-column.d.ts +1 -1
- package/dist/plugins/session-rules-column.js +1 -1
- package/dist/plugins/session-store.d.ts +18 -20
- package/dist/plugins/session-store.js +4 -12
- package/dist/plugins/session-workspace-cell.d.ts +1 -1
- package/dist/plugins/session-workspace-cell.js +1 -1
- package/dist/plugins/shared-memory-store-sql.js +2 -2
- package/dist/plugins/sql-driver.d.ts +10 -5
- package/dist/plugins/sql-driver.js +6 -6
- package/dist/plugins/sql-errors.js +1 -1
- package/dist/plugins/store-backend.d.ts +35 -6
- package/dist/plugins/store-backend.js +27 -10
- package/dist/plugins/store-contracts.d.ts +9 -2
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.js +7 -6
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.d.ts +4 -1
- package/dist/plugins/tidb-session-store.js +16 -15
- package/dist/plugins/tool-result-store-sql.d.ts +2 -2
- package/dist/plugins/tool-result-store-sql.js +3 -3
- package/dist/plugins/user-input-ledger-sql.js +2 -2
- package/dist/plugins/workflow-journal-store-sql.js +5 -5
- package/dist/plugins/workflow-run-store-sql.js +19 -19
- package/dist/plugins/write-behind-counter.d.ts +2 -3
- package/dist/plugins/write-behind-counter.js +5 -5
- package/dist/resource-suspend.d.ts +14 -12
- package/dist/resource-suspend.js +1 -1
- package/dist/resource-window.d.ts +4 -3
- package/dist/run-cancel-context.d.ts +34 -0
- package/dist/run-cancel-context.js +7 -0
- package/dist/run-local.js +14 -19
- package/dist/runs.d.ts +47 -16
- package/dist/runs.js +112 -113
- package/dist/security.d.ts +2 -2
- package/dist/server-secret-env.d.ts +2 -1
- package/dist/server-secret-env.js +2 -4
- package/dist/session-error-wire.d.ts +22 -4
- package/dist/session-error-wire.js +16 -0
- package/dist/session-incarnation.d.ts +10 -4
- package/dist/session-incarnation.js +1 -1
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-sync-kernel.d.ts +42 -1
- package/dist/session-sync-kernel.js +17 -0
- package/dist/session-sync.js +16 -4
- package/dist/sql-engine-coordinates.d.ts +49 -0
- package/dist/sql-engine-coordinates.js +27 -0
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +1 -1
- package/dist/standing-answer-grant.d.ts +31 -2
- package/dist/standing-answer-grant.js +14 -2
- package/dist/store-posture.d.ts +1 -1
- package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
- package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
- package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
- package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
- package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
- package/dist/task-a2a.d.ts +1 -1
- package/dist/task-a2a.js +5 -6
- package/dist/task-mcp.d.ts +21 -8
- package/dist/task-mcp.js +17 -9
- package/dist/task-settings.d.ts +52 -25
- package/dist/task-settings.js +91 -28
- package/dist/terminal.d.ts +103 -19
- package/dist/terminal.js +72 -20
- package/dist/trace/core-keyset-guard.d.ts +79 -2
- package/dist/trace/exit-seat.d.ts +7 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/model-segment.d.ts +2 -2
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +395 -110
- package/dist/trace/self-minted-wire.d.ts +226 -2
- package/dist/trace/self-minted-wire.js +79 -0
- package/dist/verifier-pause-card.d.ts +8 -0
- package/dist/verifier-pause-card.js +19 -0
- package/dist/web-admin-client/apply-effective.d.ts +5 -7
- package/dist/web-admin-client/apply-effective.js +2 -2
- package/dist/web-admin-client/candidate-gate.d.ts +11 -7
- package/dist/web-admin-client/candidate-gate.js +1 -1
- package/dist/web-admin-client/http-client.d.ts +5 -4
- package/dist/web-admin-client/http-client.js +2 -2
- package/dist/web-admin-client/read-warnings.d.ts +7 -17
- package/dist/web-admin-client/read-warnings.js +5 -9
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
- package/package.json +2 -2
- package/wire-changes/server@7.140.0.json +184 -0
- package/wire-changes/server@7.141.0.json +367 -0
package/dist/runs.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { runWithVerification, runCascade, defaultTaskRegistry, taskNotificationDedupKey, DURABLE_AGENT_HANDLE_RE } from "@sema-agent/core";
|
|
2
|
-
import { failureCodeOf, sealResultForExit, outwardPlane } from "./terminal.js";
|
|
2
|
+
import { atHostBoundary, failureCodeOf, sealResultForExit, outwardPlane } from "./terminal.js";
|
|
3
|
+
import { voidVerifierPauseCard } from "./verifier-pause-card.js";
|
|
4
|
+
import { voidPendingCard } from "./card-void.js";
|
|
3
5
|
import { NOT_IN_ROSTER, entryProblemsFacts } from "./entry-problems.js";
|
|
4
6
|
import { GOVERNANCE_HTTP_STATUS } from "./governance-http-status.js";
|
|
5
7
|
import { TOOL_DECLARATION_HTTP_STATUS } from "./tool-declaration-http-status.js";
|
|
@@ -19,7 +21,9 @@ import { createApprovalCardEmitter, resolveApprovalLeg } from "./tool-approval.j
|
|
|
19
21
|
import { fleetRunResiduals, isFleetAgentTerminalNotification } from "./fleet/fleet-bus.js";
|
|
20
22
|
import { defaultSubagentTailBus } from "./fleet/subagent-tail-bus.js";
|
|
21
23
|
import { emitPendingWorkflowCompletions, taskNotificationInboxEntry, taskNotificationStreamKeyOf, NotifiedKeys } from "./orchestration/workflow-completion-inbox.js";
|
|
24
|
+
import { isParkLedgerEventType } from "./trace/ledger-events.js";
|
|
22
25
|
import { recordFailOpen } from "./observability/fail-open.js";
|
|
26
|
+
import { BASELINE_IO_DEADLINE_MS, IoDeadlineExceeded, withinIoDeadline } from "./instruction-source-notice.js";
|
|
23
27
|
import { errorText as errText } from "./observability/err-text.js";
|
|
24
28
|
import { LIVENESS_HEARTBEAT_MS } from "./config-invariants.js";
|
|
25
29
|
export async function backgroundAgentOutput(registry, handle, access, agentStore) {
|
|
@@ -88,6 +92,7 @@ const PREPARE_REFUSAL_HTTP_STATUS = {
|
|
|
88
92
|
"config.project_identity_mismatch": 409,
|
|
89
93
|
"config.memory_project_marker": 409,
|
|
90
94
|
"config.memory_project_marker_nested": 409,
|
|
95
|
+
"config.read_deny_floor_unkept": 409,
|
|
91
96
|
};
|
|
92
97
|
export function resumeAtHttpStatus(result) {
|
|
93
98
|
const code = failureCodeOf(result.terminal);
|
|
@@ -196,16 +201,25 @@ export function createPromptCommitReader() {
|
|
|
196
201
|
return closed.commits[closed.commits.length - 1 - closed.frames];
|
|
197
202
|
};
|
|
198
203
|
}
|
|
204
|
+
export async function settleResumeAnchor(write, where) {
|
|
205
|
+
try {
|
|
206
|
+
await withinIoDeadline(write);
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
const why = err instanceof IoDeadlineExceeded ? `reason=timeout boundMs=${BASELINE_IO_DEADLINE_MS}` : `reason=error error=${err instanceof Error ? err.message : String(err)}`;
|
|
210
|
+
recordFailOpen("server.resume-anchor.capture-failed", `leg=${where.leg} kind=${where.kind} ${why}`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
199
213
|
export class TurnAnchorCapture {
|
|
200
214
|
capture;
|
|
201
|
-
|
|
215
|
+
leg;
|
|
202
216
|
captureUser;
|
|
203
217
|
firstTextEventId;
|
|
204
218
|
turnHadTool = false;
|
|
205
219
|
promptCommit = createPromptCommitReader();
|
|
206
|
-
constructor(capture,
|
|
220
|
+
constructor(capture, leg, captureUser) {
|
|
207
221
|
this.capture = capture;
|
|
208
|
-
this.
|
|
222
|
+
this.leg = leg;
|
|
209
223
|
this.captureUser = captureUser;
|
|
210
224
|
}
|
|
211
225
|
onHumanInput(ev) {
|
|
@@ -214,9 +228,9 @@ export class TurnAnchorCapture {
|
|
|
214
228
|
async onMessageCommitted(role, entryId) {
|
|
215
229
|
const committed = { type: "message_committed", role, entryId };
|
|
216
230
|
const prompt = this.promptCommit(committed);
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
231
|
+
const captureUser = this.captureUser;
|
|
232
|
+
if (prompt !== undefined && captureUser)
|
|
233
|
+
await settleResumeAnchor(() => captureUser(prompt), { leg: this.leg, kind: "prompt" });
|
|
220
234
|
}
|
|
221
235
|
onText(eventId) {
|
|
222
236
|
if (this.firstTextEventId === undefined) {
|
|
@@ -229,9 +243,10 @@ export class TurnAnchorCapture {
|
|
|
229
243
|
}
|
|
230
244
|
async onTurnEnd() {
|
|
231
245
|
this.promptCommit({ type: "turn_end" });
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
246
|
+
const capture = this.capture;
|
|
247
|
+
const handle = this.firstTextEventId;
|
|
248
|
+
if (handle && !this.turnHadTool && capture)
|
|
249
|
+
await settleResumeAnchor(() => capture(handle), { leg: this.leg, kind: "turn" });
|
|
235
250
|
this.firstTextEventId = undefined;
|
|
236
251
|
this.turnHadTool = false;
|
|
237
252
|
}
|
|
@@ -257,7 +272,12 @@ export async function graftParkToolCallId(result, cs) {
|
|
|
257
272
|
const id = await parkToolCallId(result, cs);
|
|
258
273
|
return id === undefined ? result : { ...result, toolCallId: id };
|
|
259
274
|
}
|
|
260
|
-
export async function
|
|
275
|
+
export async function voidHeldParkCard(held, hostSessionId, cards, leg) {
|
|
276
|
+
if (held?.terminal.kind !== "paused")
|
|
277
|
+
return;
|
|
278
|
+
await voidPendingCard({ token: held.terminal.token, sessionId: hostSessionId }, cards, "server.park.held-card-void-failed", `leg=${leg}`);
|
|
279
|
+
}
|
|
280
|
+
export async function runInBackground(runner, spec, runStore, taskId, metrics, principal, verify, cascade, instrumentDegenerate, planCacheProbe, persistThinking = false, inflight, preemptable, steerable, modelUsage, elicitation, elicitOwner, captureTurnAnchor, fleetPublisher, captureUserMessageAnchor, question, workflowCompletionInbox, subagentSteer, completionDiagLog, sendUserFile, promptManifests, approval, checkpointCards, pendingEngineNotices, trustedInternals, userInputLedger, acceptance, workspaceRecorder) {
|
|
261
281
|
const startedAt = Date.now();
|
|
262
282
|
metrics?.addGauge("runs_active", 1);
|
|
263
283
|
fleetPublisher?.onStart();
|
|
@@ -272,7 +292,6 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
272
292
|
? mintCancelledResult({ taskId, sessionId: spec.sessionId ?? "", startedAtMs: startedAt, message: "cancelled by user", cause, engineResult })
|
|
273
293
|
: mintCancelledResult({ taskId, sessionId: spec.sessionId ?? "", startedAtMs: startedAt, message: "cancelled by user", cause });
|
|
274
294
|
const recordDone = (result, status) => {
|
|
275
|
-
metrics?.addGauge("runs_active", -1);
|
|
276
295
|
metrics?.inc("tasks_total", { status });
|
|
277
296
|
metrics?.observe("task_duration_seconds", (Date.now() - startedAt) / 1000);
|
|
278
297
|
if (result?.stats.tokens)
|
|
@@ -317,7 +336,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
317
336
|
}
|
|
318
337
|
}, HEARTBEAT_MS);
|
|
319
338
|
heartbeat.unref?.();
|
|
320
|
-
const anchor = new TurnAnchorCapture(captureTurnAnchor,
|
|
339
|
+
const anchor = new TurnAnchorCapture(captureTurnAnchor, "bg", captureUserMessageAnchor);
|
|
321
340
|
let reached;
|
|
322
341
|
let observedDone;
|
|
323
342
|
let causeAtDone;
|
|
@@ -326,14 +345,35 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
326
345
|
let legLive = true;
|
|
327
346
|
const notifiedKeys = new NotifiedKeys();
|
|
328
347
|
const subagentHandleEvictions = [];
|
|
329
|
-
const
|
|
330
|
-
|
|
348
|
+
const parkRowWrite = {
|
|
349
|
+
suspended: (sealed) => runStore.setSuspended(taskId, sealed),
|
|
350
|
+
needs_review: (sealed) => runStore.setNeedsReview(taskId, sealed),
|
|
351
|
+
};
|
|
352
|
+
const parkLeg = async (word, res) => {
|
|
353
|
+
const grafted = await graftParkToolCallId(res, checkpointCards);
|
|
354
|
+
await sink.appendParked(word, grafted);
|
|
331
355
|
await flushModelUsage();
|
|
332
|
-
const sealed = sealResultForExit(
|
|
333
|
-
reached = { kind:
|
|
334
|
-
await
|
|
335
|
-
|
|
336
|
-
|
|
356
|
+
const sealed = sealResultForExit(grafted);
|
|
357
|
+
reached = { kind: word, result: sealed };
|
|
358
|
+
await parkRowWrite[word](sealed);
|
|
359
|
+
acceptance?.settle(sealed);
|
|
360
|
+
};
|
|
361
|
+
const settleLegResult = async (engineResult) => {
|
|
362
|
+
const result = atHostBoundary(engineResult, spec.sessionId);
|
|
363
|
+
const parkWord = result.terminal.kind === "paused" ? outwardPlane(result.terminal).status : undefined;
|
|
364
|
+
if (parkWord !== undefined && isParkLedgerEventType(parkWord)) {
|
|
365
|
+
await parkLeg(parkWord, result);
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const settled = causeAtDone !== undefined ? cancelledResult(causeAtDone, result) : result;
|
|
369
|
+
settledAsCancel = failureCodeOf(settled.terminal) === CANCELLED_CODE;
|
|
370
|
+
const safe = await withModelUsage(sealResultForExit(settled));
|
|
371
|
+
await sink.appendDone(safe);
|
|
372
|
+
reached = { kind: "done", result: safe };
|
|
373
|
+
const plane = outwardPlane(safe.terminal);
|
|
374
|
+
await runStore.setTerminal(taskId, plane.status, safe, plane.errorMessage ?? null);
|
|
375
|
+
await releaseKeyIfZeroWorkRefusal(runStore, taskId, safe);
|
|
376
|
+
acceptance?.settle(safe);
|
|
337
377
|
};
|
|
338
378
|
const instructionLeg = createInstructionSelectionLeg();
|
|
339
379
|
const sink = createLedgerSink({ appendEvent: (seq, type, data) => runStore.appendEvent(taskId, seq, type, data), persistThinking, notifiedKeys, onActivity: (kind, statusData) => recordTurnActivity(taskId, kind, statusData), legSections: () => ({ instructions: instructionLeg.segment(), skills: runSkillsOf(spec) }) });
|
|
@@ -419,32 +459,19 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
419
459
|
void sink.appendStatus(e).catch((err) => completionDiagLog?.("status_event_append_failed", { route: "bg-run-composite", taskId, err: err instanceof Error ? err.message : String(err) }));
|
|
420
460
|
},
|
|
421
461
|
};
|
|
422
|
-
|
|
423
|
-
|
|
462
|
+
const compositeLeg = verify !== undefined
|
|
463
|
+
? () => runWithVerification(runner, { ...spec, taskId, signal: cancelCtrl.signal }, verify, { ...fwdInternals, ...statusSeat })
|
|
464
|
+
: cascade !== undefined
|
|
465
|
+
? () => runCascade(runner, { ...spec, taskId, signal: cancelCtrl.signal }, cascade, { ...fwdInternals, ...statusSeat })
|
|
466
|
+
: undefined;
|
|
467
|
+
if (compositeLeg !== undefined) {
|
|
468
|
+
const result = await compositeLeg();
|
|
469
|
+
observedDone = result;
|
|
470
|
+
causeAtDone = cancelCtrl.cause();
|
|
471
|
+
await voidVerifierPauseCard(result, checkpointCards);
|
|
424
472
|
await flush();
|
|
425
473
|
await flushPromptManifest();
|
|
426
|
-
|
|
427
|
-
await append("done", { result: safe });
|
|
428
|
-
reached = { kind: "done", result: safe };
|
|
429
|
-
const plane = outwardPlane(safe.terminal);
|
|
430
|
-
await runStore.setTerminal(taskId, plane.status, safe, plane.errorMessage ?? null);
|
|
431
|
-
await releaseKeyIfZeroWorkRefusal(runStore, taskId, safe);
|
|
432
|
-
acceptance?.settle(safe);
|
|
433
|
-
recordDone(safe, plane.status);
|
|
434
|
-
return;
|
|
435
|
-
}
|
|
436
|
-
if (cascade !== undefined) {
|
|
437
|
-
const result = await runCascade(runner, { ...spec, taskId, signal: cancelCtrl.signal }, cascade, { ...fwdInternals, ...statusSeat });
|
|
438
|
-
await flush();
|
|
439
|
-
await flushPromptManifest();
|
|
440
|
-
const safe = await withModelUsage(sealResultForExit(result));
|
|
441
|
-
await append("done", { result: safe });
|
|
442
|
-
reached = { kind: "done", result: safe };
|
|
443
|
-
const plane = outwardPlane(safe.terminal);
|
|
444
|
-
await runStore.setTerminal(taskId, plane.status, safe, plane.errorMessage ?? null);
|
|
445
|
-
await releaseKeyIfZeroWorkRefusal(runStore, taskId, safe);
|
|
446
|
-
acceptance?.settle(safe);
|
|
447
|
-
recordDone(safe, plane.status);
|
|
474
|
+
await settleLegResult(result);
|
|
448
475
|
return;
|
|
449
476
|
}
|
|
450
477
|
const stream = runner.runTaskStream({ ...spec, taskId, signal: cancelCtrl.signal, preemptSignal: preemptCtrl.signal }, undefined, fwdInternals);
|
|
@@ -479,33 +506,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
479
506
|
}
|
|
480
507
|
if (ev.type === "done") {
|
|
481
508
|
await flush();
|
|
482
|
-
|
|
483
|
-
if (parkStatus === "suspended") {
|
|
484
|
-
const grafted = await graftParkToolCallId(ev.result, parkCheckpointReader);
|
|
485
|
-
await sink.appendParked("suspended", grafted);
|
|
486
|
-
await flushModelUsage();
|
|
487
|
-
const sealed = sealResultForExit(grafted);
|
|
488
|
-
reached = { kind: "suspended", result: sealed };
|
|
489
|
-
await runStore.setSuspended(taskId, sealed);
|
|
490
|
-
metrics?.addGauge("runs_active", -1);
|
|
491
|
-
metrics?.inc("tasks_total", { status: "suspended" });
|
|
492
|
-
continue;
|
|
493
|
-
}
|
|
494
|
-
if (parkStatus === "needs_review") {
|
|
495
|
-
await parkNeedsReview(ev.result);
|
|
496
|
-
continue;
|
|
497
|
-
}
|
|
498
|
-
{
|
|
499
|
-
const settled = causeAtDone !== undefined ? cancelledResult(causeAtDone, ev.result) : ev.result;
|
|
500
|
-
settledAsCancel = failureCodeOf(settled.terminal) === CANCELLED_CODE;
|
|
501
|
-
const safe = await withModelUsage(sealResultForExit(settled));
|
|
502
|
-
await sink.appendDone(safe);
|
|
503
|
-
reached = { kind: "done", result: safe };
|
|
504
|
-
const plane = outwardPlane(safe.terminal);
|
|
505
|
-
await runStore.setTerminal(taskId, plane.status, safe, plane.errorMessage ?? null);
|
|
506
|
-
await releaseKeyIfZeroWorkRefusal(runStore, taskId, safe);
|
|
507
|
-
recordDone(safe, failureCodeOf(safe.terminal) === CANCELLED_CODE ? CANCELLED_CODE : plane.status);
|
|
508
|
-
}
|
|
509
|
+
await settleLegResult(ev.result);
|
|
509
510
|
continue;
|
|
510
511
|
}
|
|
511
512
|
await sink.onEvent(ev);
|
|
@@ -561,7 +562,6 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
561
562
|
}
|
|
562
563
|
reached = { kind: "done", result: c };
|
|
563
564
|
await runStore.setTerminal(taskId, "failed", c, outwardPlane(c.terminal).errorMessage ?? null);
|
|
564
|
-
recordDone(c, CANCELLED_CODE);
|
|
565
565
|
}
|
|
566
566
|
}
|
|
567
567
|
catch (err) {
|
|
@@ -581,11 +581,9 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
581
581
|
await releaseKeyIfZeroWorkRefusal(runStore, taskId, reached.result);
|
|
582
582
|
acceptance?.settle(reached.result);
|
|
583
583
|
}
|
|
584
|
-
else if (reached
|
|
585
|
-
await
|
|
586
|
-
|
|
587
|
-
else if (reached?.kind === "needs_review") {
|
|
588
|
-
await runStore.setNeedsReview(taskId, reached.result);
|
|
584
|
+
else if (reached !== undefined) {
|
|
585
|
+
await parkRowWrite[reached.kind](reached.result);
|
|
586
|
+
acceptance?.settle(reached.result);
|
|
589
587
|
}
|
|
590
588
|
else if (thrownCancelCause !== undefined && observedDone === undefined) {
|
|
591
589
|
const c = cancelledResult(thrownCancelCause);
|
|
@@ -601,6 +599,7 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
601
599
|
else {
|
|
602
600
|
settledAsCancel = false;
|
|
603
601
|
const safeMsg = redactErrorMessage(message) ?? message;
|
|
602
|
+
await voidHeldParkCard(observedDone === undefined ? undefined : atHostBoundary(observedDone, spec.sessionId), spec.sessionId, checkpointCards, "bg");
|
|
604
603
|
try {
|
|
605
604
|
await append("failed", { errorMessage: safeMsg });
|
|
606
605
|
}
|
|
@@ -612,48 +611,48 @@ export async function runInBackground(runner, spec, runStore, taskId, metrics, p
|
|
|
612
611
|
}
|
|
613
612
|
catch {
|
|
614
613
|
}
|
|
615
|
-
if (reached?.kind === "done")
|
|
616
|
-
recordDone(reached.result, failureCodeOf(reached.result.terminal) === CANCELLED_CODE ? CANCELLED_CODE : outwardPlane(reached.result.terminal).status);
|
|
617
|
-
else if (reached?.kind === "suspended") {
|
|
618
|
-
metrics?.addGauge("runs_active", -1);
|
|
619
|
-
metrics?.inc("tasks_total", { status: "suspended" });
|
|
620
|
-
}
|
|
621
|
-
else if (settledAsCancel) {
|
|
622
|
-
recordDone(null, CANCELLED_CODE);
|
|
623
|
-
}
|
|
624
|
-
else {
|
|
625
|
-
recordDone(null, "failed");
|
|
626
|
-
}
|
|
627
614
|
}
|
|
628
615
|
finally {
|
|
629
616
|
legLive = false;
|
|
630
617
|
unregisterEngineNotice();
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
618
|
+
const verdict = reached?.kind === "done"
|
|
619
|
+
? { kind: "terminal", label: failureCodeOf(reached.result.terminal) === CANCELLED_CODE ? CANCELLED_CODE : outwardPlane(reached.result.terminal).status, result: reached.result }
|
|
620
|
+
: reached !== undefined
|
|
621
|
+
? { kind: "park", word: reached.kind }
|
|
622
|
+
: { kind: "terminal", label: settledAsCancel ? CANCELLED_CODE : "failed", result: null };
|
|
623
|
+
try {
|
|
624
|
+
metrics?.addGauge("runs_active", -1);
|
|
625
|
+
if (verdict.kind === "park")
|
|
626
|
+
metrics?.inc("tasks_total", { status: verdict.word });
|
|
638
627
|
else
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
628
|
+
recordDone(verdict.result, verdict.label);
|
|
629
|
+
}
|
|
630
|
+
finally {
|
|
631
|
+
if (fleetPublisher) {
|
|
632
|
+
if (verdict.kind === "park")
|
|
633
|
+
fleetPublisher.onTerminal(verdict.word);
|
|
634
|
+
else if (verdict.result !== null)
|
|
635
|
+
fleetPublisher.onTerminal(verdict.label, fleetRunResiduals(verdict.result));
|
|
636
|
+
else
|
|
637
|
+
fleetPublisher.onTerminal(verdict.label, {
|
|
638
|
+
...(verdict.label === CANCELLED_CODE ? { stoppedBy: "user" } : {}),
|
|
639
|
+
...(spec.sessionId ? { transcriptId: spec.sessionId } : {}),
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
if (steerableStreamRef !== undefined)
|
|
643
|
+
await userInputLedger?.settleLeg(steerableStreamRef);
|
|
644
|
+
if (inflight?.get(taskId) === cancelCtrl)
|
|
645
|
+
inflight.delete(taskId);
|
|
646
|
+
if (preemptable?.get(taskId) === preemptCtrl)
|
|
647
|
+
preemptable.delete(taskId);
|
|
648
|
+
if (steerableStreamRef !== undefined && steerable?.get(taskId) === steerableStreamRef)
|
|
649
|
+
steerable.delete(taskId);
|
|
650
|
+
for (const evict of subagentHandleEvictions)
|
|
651
|
+
evict();
|
|
652
|
+
modelUsage?.clear(taskId);
|
|
653
|
+
promptManifests?.clear(taskId, manifestLease);
|
|
654
|
+
clearInterval(heartbeat);
|
|
643
655
|
}
|
|
644
|
-
if (steerableStreamRef !== undefined)
|
|
645
|
-
await userInputLedger?.settleLeg(steerableStreamRef);
|
|
646
|
-
if (inflight?.get(taskId) === cancelCtrl)
|
|
647
|
-
inflight.delete(taskId);
|
|
648
|
-
if (preemptable?.get(taskId) === preemptCtrl)
|
|
649
|
-
preemptable.delete(taskId);
|
|
650
|
-
if (steerableStreamRef !== undefined && steerable?.get(taskId) === steerableStreamRef)
|
|
651
|
-
steerable.delete(taskId);
|
|
652
|
-
for (const evict of subagentHandleEvictions)
|
|
653
|
-
evict();
|
|
654
|
-
modelUsage?.clear(taskId);
|
|
655
|
-
promptManifests?.clear(taskId, manifestLease);
|
|
656
|
-
clearInterval(heartbeat);
|
|
657
656
|
}
|
|
658
657
|
}
|
|
659
658
|
export const HEARTBEAT_MS = LIVENESS_HEARTBEAT_MS;
|
package/dist/security.d.ts
CHANGED
|
@@ -176,10 +176,10 @@ export declare function legacyUnownedAmnestyOpen(deployment: DeploymentShapeInpu
|
|
|
176
176
|
export type OwnerAwareSessionStore = SessionStore & {
|
|
177
177
|
/** 属主登记(core `SessionStore.register` 的契约:对没有行的 id 建行并记下属主,首写赢;对已有的行什么都不做)。读回走 `headOf`。 */
|
|
178
178
|
register?: (sessionId: string, owner: string | null) => Promise<void>;
|
|
179
|
-
/** [ref] 委派继承律的**认领口** —— 只在记录委派树的店上(
|
|
179
|
+
/** [ref] 委派继承律的**认领口** —— 只在记录委派树的店上(三只持久会话店,只命中 placed 行;不记委派树的店没有):判断时读到的那一位住客仍是无主的 placed 行 ⇒ 写 `owner`,
|
|
180
180
|
* 返回是否写成(只 CAS 子行自己)。唯一调用方 = 停驻挂点的 `settleDelegatedOwner`(`delegated-session-owner.ts`;M23 走同一句 SQL);规则写在那个模块。 */
|
|
181
181
|
claimOwnerless?: OwnerlessClaim;
|
|
182
|
-
/** [ref] placed 分区的元组读口(店的既有读口,一行 PK 读;`undefined` = 普通会话或无此行)。店不交它 = 不实现 placement = 没有 placed 行(
|
|
182
|
+
/** [ref] placed 分区的元组读口(店的既有读口,一行 PK 读;`undefined` = 普通会话或无此行)。店不交它 = 不实现 placement = 没有 placed 行(无 repo 的内存店)。两个读者:
|
|
183
183
|
* ① 会话面的属主门只在属主为 NULL 时读它一次(无主的 placed 行不是公共行,`http/principal-gate.ts` 的 `sessionOwnerCellOf`);
|
|
184
184
|
* ② 会话视图读它投影体顶层 `agent` 键(`audit.ts` 的 `sessionAgentOf`,只在视图读上付):店没有这一面 ⇒ 键缺席,读面不凭别处另铸子代身份。 */
|
|
185
185
|
placementOf?: (sessionId: string) => Promise<SessionPlacementRecord | undefined>;
|
|
@@ -73,7 +73,8 @@ export declare function serverCredentialValueSources(modelApiKeyEnv?: ModelApiKe
|
|
|
73
73
|
* 所以这一次抛只可能是名的问题。
|
|
74
74
|
* · **值臂**:{@link serverCredentialValueSources} 的每一个变量此刻在 env 里的值,逐个交给引擎**同一只**判(不另写「什么算凭据值」的第二份判据):引擎收下 ⇒ 记进值臂;
|
|
75
75
|
* 引擎拒(不是凭据值:空白 / 占位词 / 一个字符重复 / 不足 8 字符;或它是每个子进程都会拿到的变量的值)⇒ 这一个值不扣、名照扣、**不拒启**(与引擎自己的收值口
|
|
76
|
-
* `holdOwnCredentialValues` 同一姿势:不收 + 说一次)
|
|
76
|
+
* `holdOwnCredentialValues` 同一姿势:不收 + 说一次),经留痕座结构化点名那个变量一次 —— `warn` 行 `own_credential_value_not_withheld { name, reason }`
|
|
77
|
+
* ({@link recordOwnCredentialValueNotWithheld};`reason` 是引擎拒句原文,从不回显值;起服第一步还没有 logger 时当拍经进程默认的 JSON 行日志器写 stderr,不缓冲),能力位 `inherit_env.own_credential_values_withheld`
|
|
77
78
|
* 因此答 false(位真 ⇔ 值臂真扣)。引擎拒一个值时声明保持上一份,所以逐个交表的中间态都是上一份的超集。
|
|
78
79
|
* 返回声明的名单(只名、不值)。
|
|
79
80
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { declareWithheldEnv, hostChildEnv, inheritedHostEnv } from "@sema-agent/core";
|
|
2
2
|
import { CONFIG_CATALOG } from "./config-catalog.js";
|
|
3
3
|
import { ENV_NAME_ALLOWLIST_KNOB_NAMES } from "./env-name-allowlist-knobs.js";
|
|
4
|
-
import { recordSecretEnvScrub } from "./observability/secret-env-scrub.js";
|
|
4
|
+
import { recordOwnCredentialValueNotWithheld, recordSecretEnvScrub } from "./observability/secret-env-scrub.js";
|
|
5
5
|
export const CATALOG_SECRET_ENV_NAMES = new Set(CONFIG_CATALOG.filter((spec) => spec.type === "secret").map((spec) => spec.name));
|
|
6
6
|
const NO_MODEL_ENTRIES = Object.freeze({});
|
|
7
7
|
export function serverWithheldEnvNames(modelApiKeyEnv = NO_MODEL_ENTRIES) {
|
|
@@ -31,9 +31,7 @@ export function declareServerWithheldEnv(modelApiKeyEnv = NO_MODEL_ENTRIES) {
|
|
|
31
31
|
catch (e) {
|
|
32
32
|
if (!valueRefusalAnnounced.has(source)) {
|
|
33
33
|
valueRefusalAnnounced.add(source);
|
|
34
|
-
|
|
35
|
-
"the variable name is still withheld under every inheritEnv policy, but a variable holding the same string under another name is not, and GET /v1/capabilities answers inherit_env.own_credential_values_withheld: false. " +
|
|
36
|
-
"Give it a real credential value (at least 8 characters, not a placeholder) to withhold copies of it too.");
|
|
34
|
+
recordOwnCredentialValueNotWithheld({ name: source, reason: e instanceof Error ? e.message : String(e) });
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
}
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
* 列表里的缺席),码位各不相同,不由本表统一。
|
|
38
38
|
* · `placement_refused` —— `import` 面 **409 `conflict.session_placed`**(机读位 `detail.placement_kind`,固定句);`open` 面留白。
|
|
39
39
|
* 同一个词在两面上说的不是同一件事:import 面只有「会话同步往一只**分区会话**(委派子代的转录)上写」一个来源
|
|
40
|
-
* (
|
|
40
|
+
* (三只持久会话店的整段换装 / 暂存提交门:目标 id 的 `placement_kind` 在场 ⇒ 不适用),调用方没做错格式、是**目标**不收这种写;
|
|
41
41
|
* open 面上同一个词还含「声明了分区的创建撞上了分区外 / 异组的行」两形(core `TtlSessionStore.assertPlacementAdmission` 的后两条),
|
|
42
42
|
* 那不是「目标是分区会话」。而 run 终局上它是引擎词汇(`terminal.code`),原样随 failed 体走 —— 若在这里分诊成 409,
|
|
43
43
|
* 体上的 `errorCode` 仍是引擎词 `placement_refused`,一个状态两个名字。所以 open 面留白,`invalid_session` 是同形先例。
|
|
@@ -47,16 +47,18 @@
|
|
|
47
47
|
* (请求 core 把种类放进错误,而不是在这里解析句子)。
|
|
48
48
|
* · `invalid_entry` / `invalid_fork_target` —— 留白:本仓今天没有一条 wire 口把它们作为自己的
|
|
49
49
|
* 应答(它们在 core 的追加 / 分叉面上抛,落进各站点既有的处置或通用 500)。给它们起名是另一件事、另一张票。
|
|
50
|
-
* · `conflict` —— `import` 面 **409 `conflict`**(固定句 {@link STAGED_IMPORT_OWNER_CHANGED_SENTENCE});`open`
|
|
50
|
+
* · `conflict` —— `import` 面 **409 `conflict`**(固定句 {@link STAGED_IMPORT_OWNER_CHANGED_SENTENCE});`open` 面留白。按码映射时 import 面上这个词只有一个来源:
|
|
51
51
|
* 暂存提交的属主 CAS(`session-sync-kernel.ts` 的 `StagedCommitOwnerChangedError`,三家店在提交事务里比「此刻的属主格 = 这次导入的门判过的那一格」,
|
|
52
52
|
* 不等 ⇒ 回滚)—— 码位与同族的提交期同步冲突(`SyncConflictError` ⇒ 409 `conflict`「sync conflict」)同一个,出路也相同:从第一阶段重来(重新过门)。
|
|
53
|
+
* 本服务自铸的同码具名拒 {@link StampedSessionArchiveError}(local 店:存档仍带更早版本写下的属主戳)不按码映射 —— 出路不同(重来照样撞),
|
|
54
|
+
* 由 {@link sessionErrorWireOf} 按**型**先认:两面同答 409 `conflict` + 固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}。
|
|
53
55
|
* open 面上它是 run 的写撞上真并发写,落成那条 run 的 `failed` 终局(`terminal.code: "conflict"`),提交腿不另作处置。
|
|
54
56
|
* · `storage` / `unknown` —— 留白:故障类,通用 500 就是它们今天的应答。
|
|
55
57
|
*
|
|
56
58
|
* core 给闭集加一个词 ⇒ 下面的 `switch` 编译红,由人裁定它在两面上的答复,而不是让它静默落进某个恰好存在的臂
|
|
57
59
|
* ([ref] 词表纪律;同形先例 `session-policy-wire.ts` 的 `sessionPolicyErrorHttp`)。
|
|
58
60
|
*/
|
|
59
|
-
import
|
|
61
|
+
import { SessionError } from "@sema-agent/core";
|
|
60
62
|
/** core `SessionError` 的码闭集(core 不从包根导出这个型名 ⇒ 从导出类的 `code` 键派生,不手抄)。 */
|
|
61
63
|
export type SessionErrorCode = SessionError["code"];
|
|
62
64
|
/** 映射的面(见文件头注)。 */
|
|
@@ -76,7 +78,7 @@ export interface SessionErrorWire {
|
|
|
76
78
|
/** import 面 `invalid_session` 的固定句(修前 session-sync 暂存导入腿那一行的原文)。 */
|
|
77
79
|
export declare const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
|
|
78
80
|
/**
|
|
79
|
-
* import 面 `placement_refused` 的固定句:wire 上不发引擎原句 ——
|
|
81
|
+
* import 面 `placement_refused` 的固定句:wire 上不发引擎原句 —— 三只持久会话店的原句各不相同(措辞各自铸),都点名会话 id 与引擎内部词
|
|
80
82
|
* (「placement partition」「delegation transcript」);固定句只说调用方能做什么(冻结在 `test/api-error-text-freeze.test.ts` 的常量锚格)。
|
|
81
83
|
*/
|
|
82
84
|
export declare const PLACED_SESSION_SENTENCE = "this session holds a delegated agent's transcript, so session sync cannot overwrite it; sync into a different session id";
|
|
@@ -85,6 +87,22 @@ export declare const PLACED_SESSION_SENTENCE = "this session holds a delegated a
|
|
|
85
87
|
* 不发店的原句(它点名会话 id);固定句只说发生了什么与出路(冻结在 `test/api-error-text-freeze.test.ts` 的常量锚格)。
|
|
86
88
|
*/
|
|
87
89
|
export declare const STAGED_IMPORT_OWNER_CHANGED_SENTENCE = "session owner changed while the import streamed; nothing was imported \u2014 start the sync again";
|
|
90
|
+
/**
|
|
91
|
+
* local 店的具名拒(唯一铸点 `plugins/local-session-store.ts`):这只会话的引擎存档仍带更早版本写下的属主戳(一次性迁移 M33 改写不了它,或数据根跳过了带这次迁移的版本)
|
|
92
|
+
* ⇒ 不在它上面造新存档(fork),也不原地换它的日志(改日志的推送);零写。码是 core 闭集的 `conflict`(码不另铸);句子(给运维日志,点名会话 id)归本错,
|
|
93
|
+
* wire 上发固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}(两面同一句;映射 {@link sessionErrorWireOf})。
|
|
94
|
+
*/
|
|
95
|
+
export declare class StampedSessionArchiveError extends SessionError {
|
|
96
|
+
readonly sessionId: string;
|
|
97
|
+
constructor(sessionId: string);
|
|
98
|
+
}
|
|
99
|
+
/** {@link StampedSessionArchiveError} 的 wire 固定句(fork 与改日志的推送同一句;不点名会话 id;出路在句里 —— 从头再同步照样撞)。 */
|
|
100
|
+
export declare const STAMPED_SESSION_ARCHIVE_SENTENCE = "this session's stored archive still carries an owner stamp written by an earlier server version, so it cannot be forked or have its log replaced; nothing was written \u2014 delete the session and push it again";
|
|
101
|
+
/**
|
|
102
|
+
* 一只 `SessionError` 在一面上的 wire 答复 —— 下发点({@link sendSessionError} 的唯一读法)经这里:本服务自铸的同码具名拒先按型认(它的出路与同码的
|
|
103
|
+
* 按码答复不同),其余按码({@link sessionErrorHttp})。
|
|
104
|
+
*/
|
|
105
|
+
export declare function sessionErrorWireOf(e: SessionError, face: SessionErrorFace): SessionErrorWire | undefined;
|
|
88
106
|
export declare function sessionErrorHttp(code: SessionErrorCode, face: SessionErrorFace): SessionErrorWire | undefined;
|
|
89
107
|
export declare function isSessionErrorCode(code: string): code is SessionErrorCode;
|
|
90
108
|
//# sourceMappingURL=session-error-wire.d.ts.map
|
|
@@ -1,12 +1,28 @@
|
|
|
1
|
+
import { SessionError } from "@sema-agent/core";
|
|
1
2
|
export const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
|
|
2
3
|
export const PLACED_SESSION_SENTENCE = "this session holds a delegated agent's transcript, so session sync cannot overwrite it; sync into a different session id";
|
|
3
4
|
const PLACEMENT_KIND = "subagent";
|
|
4
5
|
export const STAGED_IMPORT_OWNER_CHANGED_SENTENCE = "session owner changed while the import streamed; nothing was imported — start the sync again";
|
|
6
|
+
export class StampedSessionArchiveError extends SessionError {
|
|
7
|
+
sessionId;
|
|
8
|
+
constructor(sessionId) {
|
|
9
|
+
super("conflict", `session ${sessionId}'s stored archive still carries an owner stamp written by an earlier version (the one-time migration M33 could not rewrite it as anonymous, ` +
|
|
10
|
+
"or this data root skipped the versions that carry that migration) — no new session is made from it and its log is not replaced, so this write was refused and nothing was written. " +
|
|
11
|
+
"Reading, resuming and pulling the session are unaffected. Way out: delete the session and push it again (a push onto an absent session creates it anew).");
|
|
12
|
+
this.sessionId = sessionId;
|
|
13
|
+
this.name = "StampedSessionArchiveError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export const STAMPED_SESSION_ARCHIVE_SENTENCE = "this session's stored archive still carries an owner stamp written by an earlier server version, so it cannot be forked or have its log replaced; nothing was written — delete the session and push it again";
|
|
5
17
|
const CORRUPT_SESSION = { status: 500, errorCode: "corrupt_session" };
|
|
6
18
|
const STORED_LOG_INVALID = { status: 500, errorCode: "invalid_session" };
|
|
7
19
|
const INVALID_ENTRIES = { status: 422, errorCode: "invalid_entries", sentence: STAGED_IMPORT_INVALID_SENTENCE };
|
|
8
20
|
const SESSION_PLACED = { status: 409, errorCode: "conflict.session_placed", sentence: PLACED_SESSION_SENTENCE, detail: { placement_kind: PLACEMENT_KIND } };
|
|
9
21
|
const STAGED_IMPORT_OWNER_CHANGED = { status: 409, errorCode: "conflict", sentence: STAGED_IMPORT_OWNER_CHANGED_SENTENCE };
|
|
22
|
+
const STAMPED_SESSION_ARCHIVE = { status: 409, errorCode: "conflict", sentence: STAMPED_SESSION_ARCHIVE_SENTENCE };
|
|
23
|
+
export function sessionErrorWireOf(e, face) {
|
|
24
|
+
return e instanceof StampedSessionArchiveError ? STAMPED_SESSION_ARCHIVE : sessionErrorHttp(e.code, face);
|
|
25
|
+
}
|
|
10
26
|
export function sessionErrorHttp(code, face) {
|
|
11
27
|
switch (code) {
|
|
12
28
|
case "corrupt_session":
|
|
@@ -6,9 +6,15 @@
|
|
|
6
6
|
* 一个可比的答案 —— 今天只能比属主,同一个人删了重建就比不出来。
|
|
7
7
|
*
|
|
8
8
|
* ## 规则(全仓唯一处写)
|
|
9
|
-
* · **铸点只在新建行**:会话店的 `register` / 无 id 创建 / fork / session-sync
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* · **铸点只在新建行**:会话店的 `register` / 无 id 创建 / fork / session-sync 的导入新行。已存在的行化身一个字节都不动;
|
|
10
|
+
* session-sync 的整段换装(replace / staged commit)换的是**同一位住客**的日志,化身沿用 —— 属主却可以被换装重戳为导入者(local 的 M10 认领同理),
|
|
11
|
+
* 所以化身与属主不是同一条律(读法分三种,见下「两读」)。删除随行消失,同 id 重新登记铸新的。
|
|
12
|
+
* · **两读(住客的三种问法,各读各的格,不混用)**:
|
|
13
|
+
* K1 **住客自己的记录**(工作区、记忆、空间分区……按「这一位住客」落的东西)只按化身绑 —— 同一位住客的属主换代(推送重戳 / 认领)不换住客,记录照落;
|
|
14
|
+
* K2 **以「这一行的这一代」为条件的写**(执行放置的换绑 / 收回、执行上下文的复核)比属主与化身整对,判官 = core 的行期望判官 `sessionRowMatches`
|
|
15
|
+
* (`execution-placement.ts` 的 `sameOccupant`,SQL `incarnation = ? AND owner <=> ?` 的对位)—— 读与写之间属主换了一代 ⇒ 不是判过的那一行;
|
|
16
|
+
* K0 **只问属主的门**(授权门、暂存提交的属主 CAS)只读属主那一格。三种都读会话**行**;local 店的行 = 会话元数据边档那一格(引擎仓里的存档是匿名内容仓,
|
|
17
|
+
* 存档头上的属主不是行事实 —— `plugins/local-session-store.ts` 头注)。
|
|
12
18
|
* · **值是不透明随机串**(`randomUUID()`,v4:没有时间戳、没有机器信息 —— 刻意不用 uuidv7,那一形带铸造时刻)。只拿来比较。
|
|
13
19
|
* · **一格、一个解码**:住客令牌是会话**行**上的一格 —— SQL `session_meta.incarnation`(两方言)、local 后端的会话元数据边档那一格
|
|
14
20
|
* (`plugins/local-session-store.ts` 的 `session-incarnations.json`)。行上的值只经 {@link incarnationFromCell} 解码。
|
|
@@ -146,7 +152,7 @@ export declare function carriedRowCells(sessionId: string, prior: {
|
|
|
146
152
|
*/
|
|
147
153
|
export declare const SESSION_META_INCARNATION_COLUMN: {
|
|
148
154
|
readonly name: "incarnation";
|
|
149
|
-
readonly
|
|
155
|
+
readonly mysql: "incarnation VARCHAR(64) NOT NULL DEFAULT ''";
|
|
150
156
|
readonly pg: "incarnation VARCHAR(64) COLLATE \"C\" NOT NULL DEFAULT ''";
|
|
151
157
|
};
|
|
152
158
|
//# sourceMappingURL=session-incarnation.d.ts.map
|
|
@@ -75,7 +75,7 @@ export function carriedRowCells(sessionId, prior) {
|
|
|
75
75
|
}
|
|
76
76
|
export const SESSION_META_INCARNATION_COLUMN = {
|
|
77
77
|
name: "incarnation",
|
|
78
|
-
|
|
78
|
+
mysql: "incarnation VARCHAR(64) NOT NULL DEFAULT ''",
|
|
79
79
|
pg: `incarnation VARCHAR(64) COLLATE "C" NOT NULL DEFAULT ''`,
|
|
80
80
|
};
|
|
81
81
|
//# sourceMappingURL=session-incarnation.js.map
|
|
@@ -139,7 +139,7 @@ export declare function sessionPolicyErrorFacts(e: SessionPolicyError): Readonly
|
|
|
139
139
|
* · `conflict`(409)—— CAS 输了,重读 `rev` 再来。**码位与状态逐字不变**。
|
|
140
140
|
* · `loosen_forbidden`(403)—— 非 operator 想放松。**码位与状态逐字不变**。⚠️ 这个词还有**第二个铸点**([ref] B5,
|
|
141
141
|
* 如实登记、未改):PG 后端的 SQL 双生对含 NUL / 孤代理字节的规则拒收时借用了它
|
|
142
|
-
* (`
|
|
142
|
+
* (`stores-sql/session-policy-store-sql.ts` 的 `pgHasUnstorable` 臂)—— 那一形**既非放宽也非越权**,operator 写同样撞上;
|
|
143
143
|
* core 的闭集里没有「输入不可存」这个词,改码位要先裁定新码与 PUT / 2c 导入两条入口同判(DEBTS [ref] B5)。
|
|
144
144
|
* · `corrupt`(**500**)—— 店读不出它自己该读的那份字节(记号/行被列外篡改或撕裂,或存着引擎今天的形读法读不出的规则体)。
|
|
145
145
|
* 不是 4xx:调用方没做错任何事,它也改不了这件事;不是 503:重试改不了判(修复路径是**人**去改回或删掉那一行,
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* (security ↔ session-sync; lens2 §B/§E). This file imports nothing from the repo but TYPES from leaves (core types, and
|
|
9
9
|
* the session-face type from `session-incarnation.ts`, itself a leaf) — a leaf, same shape as session-sync-content.ts. Its one VALUE import is
|
|
10
10
|
* core's `SessionError` class (the closed-set store error the three adapters already throw). session-sync.ts re-exports everything here, so existing import sites
|
|
11
|
-
* keep working unchanged.
|
|
11
|
+
* keep working unchanged. The import door's anchor judge ({@link readImportAnchors}) was written here, not moved: it is pure too, and the route and the
|
|
12
|
+
* tests read it from the same leaf.
|
|
12
13
|
*/
|
|
13
14
|
import { SessionError, type SessionTreeEntry } from "@sema-agent/core";
|
|
14
15
|
import type { SessionFace } from "./session-incarnation.js";
|
|
@@ -180,4 +181,44 @@ export declare class SyncConflictError extends Error {
|
|
|
180
181
|
relation: "fork" | "stale";
|
|
181
182
|
}>);
|
|
182
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* §9 — one anchor of a Phase-A import body as the import door reads it: the live `eventId` the shell holds → the persisted `entryId` it resumes at.
|
|
186
|
+
* The wire's `owner` is not carried: every replay re-keys the anchor to the IMPORTING principal (the importer, never the exporter, owns the row),
|
|
187
|
+
* so nothing downstream reads the sender's value and nothing here judges it.
|
|
188
|
+
*/
|
|
189
|
+
export interface ImportAnchor {
|
|
190
|
+
readonly eventId: string;
|
|
191
|
+
readonly entryId: string;
|
|
192
|
+
}
|
|
193
|
+
/** The import door's verdict on `anchors[]`: the judged list, or ONE sentence for the first violation (index + the offending `entryId`, nothing else). */
|
|
194
|
+
export type ImportAnchorsRead = {
|
|
195
|
+
readonly anchors: ImportAnchor[];
|
|
196
|
+
} | {
|
|
197
|
+
readonly problem: string;
|
|
198
|
+
};
|
|
199
|
+
/**
|
|
200
|
+
* §9 — THE predicate of the anchor law, and its only spelling: an anchor is sound iff the entry it resumes at is one of the entries declared next to it
|
|
201
|
+
* (an import body's `entryIds`; a manifest's `entryIds`). The import door ({@link readImportAnchors}) refuses an anchor that fails it, and the manifest
|
|
202
|
+
* export (`exportSessionManifest`) does not hand one out — one fact, one reading, on both sides of the wire.
|
|
203
|
+
*/
|
|
204
|
+
export declare function anchorEntryDeclared(declared: ReadonlySet<string>, anchorEntryId: string): boolean;
|
|
205
|
+
/**
|
|
206
|
+
* §9 — the ONE judge of a Phase-A body's `anchors[]`, run at the door before anything is classified, mirrored, staged or written (a refusal
|
|
207
|
+
* writes no anchor, no log, no session row, opens no staging, takes no lease, and leaves the execution cell alone).
|
|
208
|
+
*
|
|
209
|
+
* The law (single source): an anchor may only point at an entry the session HOLDS once the import has landed, and what an import lands is the log
|
|
210
|
+
* its body declares (`entryIds`): a commit REPLACES the destination's log with the staged entries (SQL: purge + row rename in one transaction; local:
|
|
211
|
+
* an in-place swap), `fresh` / `fast_forward` / `identical` leave no destination entry the declaration lacks, and an `overwrite-dst` `fork` / `stale`
|
|
212
|
+
* removes the destination-only entries (and wipes the anchors that pointed at them). So "the entries the import declares" is the whole question: an
|
|
213
|
+
* `entryId` outside it names a row that is not there once the import lands (an anchor to a destination-only entry is exactly the dangling anchor the
|
|
214
|
+
* purge exists to prevent). An entry a concurrent writer appends after the body's ids were read is outside the declaration too, and an anchor to it is
|
|
215
|
+
* refused the same way — the conservative direction: the sender re-reads its manifest and pushes again (`exportSessionManifest` reads the anchors BEFORE
|
|
216
|
+
* the entry ids, so a manifest never carries an anchor newer than its own id list, and drops — loudly, by the same {@link anchorEntryDeclared} — an
|
|
217
|
+
* anchor an earlier version stored for an entry the log does not hold). The replays downstream (the `identical` arm, the post-commit leg)
|
|
218
|
+
* only iterate the list this function returned — they do not judge again.
|
|
219
|
+
*
|
|
220
|
+
* Shape is judged by the same reader — an element that is not an object with a string `eventId` and a string `entryId` is refused by index —
|
|
221
|
+
* so a `null` element is a 400 at the door, not a TypeError in a replay leg.
|
|
222
|
+
*/
|
|
223
|
+
export declare function readImportAnchors(raw: readonly unknown[], declaredEntryIds: readonly string[]): ImportAnchorsRead;
|
|
183
224
|
//# sourceMappingURL=session-sync-kernel.d.ts.map
|
|
@@ -55,4 +55,21 @@ export class SyncConflictError extends Error {
|
|
|
55
55
|
this.name = "SyncConflictError";
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
export function anchorEntryDeclared(declared, anchorEntryId) {
|
|
59
|
+
return declared.has(anchorEntryId);
|
|
60
|
+
}
|
|
61
|
+
export function readImportAnchors(raw, declaredEntryIds) {
|
|
62
|
+
const declared = new Set(declaredEntryIds);
|
|
63
|
+
const anchors = [];
|
|
64
|
+
for (let i = 0; i < raw.length; i++) {
|
|
65
|
+
const a = raw[i];
|
|
66
|
+
const { eventId, entryId } = (typeof a === "object" && a !== null && !Array.isArray(a) ? a : {});
|
|
67
|
+
if (typeof eventId !== "string" || typeof entryId !== "string")
|
|
68
|
+
return { problem: `anchors: [${i}] must be an object with a string eventId and a string entryId` };
|
|
69
|
+
if (!anchorEntryDeclared(declared, entryId))
|
|
70
|
+
return { problem: `anchors: [${i}].entryId ${JSON.stringify(entryId)} is not among the entryIds this import declares` };
|
|
71
|
+
anchors.push({ eventId, entryId });
|
|
72
|
+
}
|
|
73
|
+
return { anchors };
|
|
74
|
+
}
|
|
58
75
|
//# sourceMappingURL=session-sync-kernel.js.map
|