@sema-agent/server 7.140.0 → 7.142.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 +505 -0
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/USAGE.md +142 -25
- package/dist/approval-ask-audit-store.d.ts +54 -38
- package/dist/approval-ask-audit-store.js +58 -39
- package/dist/approval-batch-census.d.ts +27 -0
- package/dist/approval-batch-census.js +27 -0
- package/dist/approval-card.d.ts +39 -24
- package/dist/approval-card.js +6 -3
- package/dist/approval-crash-convergence.d.ts +17 -7
- package/dist/approval-crash-convergence.js +94 -22
- package/dist/approval-deny-reasons.d.ts +34 -30
- package/dist/approval-deny-reasons.js +21 -6
- package/dist/approval-policy-settlement.d.ts +1 -1
- package/dist/approval-reconciler.d.ts +33 -1
- package/dist/approval-reconciler.js +43 -40
- 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/auth-bridge.d.ts +9 -6
- package/dist/auth-bridge.js +9 -3
- package/dist/boot/adoption.js +2 -1
- package/dist/boot/budget-tracing.d.ts +16 -0
- package/dist/boot/budget-tracing.js +10 -6
- 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.d.ts +24 -4
- package/dist/boot/execution-env.js +34 -27
- package/dist/boot/execution-lane.js +2 -1
- package/dist/boot/exit-boundary.js +5 -4
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/memory-consolidation.d.ts +1 -1
- package/dist/boot/memory-consolidation.js +3 -2
- package/dist/boot/parked-revive-gate.js +2 -1
- package/dist/boot/permission-rules-audit.d.ts +0 -28
- package/dist/boot/permission-rules-audit.js +2 -1
- package/dist/boot/read-deny-anchor-audit.js +2 -1
- package/dist/boot/reapers.d.ts +2 -2
- package/dist/boot/reapers.js +4 -3
- package/dist/boot/resolve-spec.js +18 -6
- package/dist/boot/retention-lane.js +5 -3
- package/dist/boot/runner-deps.js +16 -13
- package/dist/boot/runtime-caps.js +3 -2
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +8 -6
- package/dist/boot/shutdown.js +8 -2
- package/dist/boot/stage-04-stores.js +3 -2
- package/dist/boot/stage-05-execution-env.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.js +11 -7
- package/dist/boot/stage-06-runners.d.ts +1 -3
- package/dist/boot/stage-06-runners.js +3 -2
- package/dist/boot/stage-07-capability-layer.d.ts +1 -2
- package/dist/boot/stage-07-capability-layer.js +10 -11
- package/dist/boot/stage-08-reapers.d.ts +1 -2
- package/dist/boot/stage-08-reapers.js +3 -2
- package/dist/boot/stage-09-leader.d.ts +1 -2
- package/dist/boot/stage-10-http-server.d.ts +1 -2
- package/dist/boot/stage-10-http-server.js +6 -4
- package/dist/boot/stores.js +13 -6
- package/dist/boot/web-admin.js +18 -17
- package/dist/boot/webfetch-summarize-lane.js +2 -1
- package/dist/boot/workflow-orchestration.js +3 -2
- package/dist/capabilities/builtin-tools.d.ts +2 -1
- package/dist/capabilities/builtin-tools.js +2 -4
- package/dist/capabilities/composite-members.d.ts +2 -1
- package/dist/capabilities/composite-members.js +2 -1
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +33 -0
- package/dist/capability-facts.js +32 -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 +13 -13
- package/dist/config-provider.js +19 -33
- package/dist/config-types.d.ts +39 -10
- package/dist/config.d.ts +6 -0
- package/dist/config.js +72 -49
- package/dist/delegated-session-owner.d.ts +21 -19
- package/dist/delegated-session-owner.js +1 -1
- 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 +50 -2
- package/dist/execution-lane-caps.js +90 -13
- 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/fleet/fleet-bus.d.ts +6 -3
- package/dist/hooks/hook-runner.d.ts +6 -0
- package/dist/hooks/hook-runner.js +30 -1
- 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 +8 -2
- package/dist/http/execution-context.d.ts +2 -2
- package/dist/http/idempotency.d.ts +1 -1
- package/dist/http/live-frame.d.ts +24 -0
- package/dist/http/live-frame.js +16 -0
- package/dist/http/principal-gate.d.ts +3 -1
- package/dist/http/principal-gate.js +17 -8
- package/dist/http/resume-legs.js +42 -29
- package/dist/http/route-table.js +4 -0
- package/dist/http/routes/approvals-assistant.js +1 -0
- package/dist/http/routes/attachments.js +18 -0
- package/dist/http/routes/capabilities.js +10 -6
- 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 +1 -1
- package/dist/http/routes/memory-compliance.js +1 -1
- package/dist/http/routes/memory-policy.js +27 -7
- 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/runs.js +3 -3
- package/dist/http/routes/session-memory-sync.d.ts +63 -0
- package/dist/http/routes/session-memory-sync.js +157 -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-list.d.ts +2 -1
- package/dist/http/routes/sessions.js +5 -4
- package/dist/http/routes/tasks.js +70 -71
- package/dist/http/run-read-face.d.ts +7 -0
- package/dist/http/run-read-face.js +10 -4
- package/dist/http/send.d.ts +6 -1
- package/dist/http/send.js +10 -3
- package/dist/http/server.d.ts +20 -7
- package/dist/http/server.js +2 -4
- 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/http/submit-replay.d.ts +4 -3
- package/dist/http/submit-replay.js +2 -2
- package/dist/http/sync-submit-body.d.ts +21 -4
- package/dist/http/sync-submit-body.js +13 -0
- package/dist/identity-source.d.ts +21 -2
- package/dist/identity-source.js +6 -0
- package/dist/instruction-source-notice.d.ts +7 -0
- package/dist/instruction-source-notice.js +6 -6
- package/dist/mcp-assertion-header.d.ts +4 -0
- package/dist/mcp-assertion-header.js +5 -0
- package/dist/memory-incident-sink.d.ts +19 -6
- package/dist/memory-incident-sink.js +8 -4
- package/dist/memory-posture.d.ts +1 -1
- package/dist/memory-scope.d.ts +4 -4
- package/dist/memory-scope.js +1 -1
- package/dist/memory-sync-client.d.ts +35 -23
- package/dist/memory-sync-client.js +122 -52
- package/dist/memory-sync-identity.d.ts +24 -0
- package/dist/memory-sync-identity.js +57 -0
- package/dist/memory-sync.d.ts +7 -1
- package/dist/memory-sync.js +6 -3
- package/dist/observability/fail-open.d.ts +57 -12
- package/dist/observability/fail-open.js +50 -9
- package/dist/observability/metrics.js +0 -1
- package/dist/observability/run-terminal.d.ts +93 -31
- package/dist/observability/run-terminal.js +175 -171
- 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/approval-ask-store-file.d.ts +14 -4
- package/dist/plugins/approval-ask-store-file.js +48 -7
- package/dist/plugins/approval-ask-store-memory.d.ts +2 -1
- package/dist/plugins/approval-ask-store-memory.js +9 -8
- package/dist/plugins/approval-ask-store-sql.d.ts +42 -10
- package/dist/plugins/approval-ask-store-sql.js +49 -19
- package/dist/plugins/caching-session-store.d.ts +6 -0
- package/dist/plugins/caching-session-store.js +3 -0
- package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
- package/dist/plugins/checkpoint-store-sql.js +74 -3
- package/dist/plugins/device-store-sql.d.ts +5 -2
- package/dist/plugins/device-store-sql.js +4 -1
- package/dist/plugins/execution-placement-sql.d.ts +11 -1
- package/dist/plugins/execution-placement-sql.js +12 -1
- package/dist/plugins/file-run-store.d.ts +7 -2
- package/dist/plugins/file-run-store.js +12 -2
- package/dist/plugins/fork-routing-session-store.d.ts +10 -32
- package/dist/plugins/fork-routing-session-store.js +2 -61
- package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
- package/dist/plugins/k8s-exec-protocol.js +6 -1
- 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 +260 -39
- package/dist/plugins/local-session-store.js +582 -57
- package/dist/plugins/local-session-window.d.ts +17 -3
- package/dist/plugins/local-session-window.js +7 -13
- package/dist/plugins/local-task-attachment-store.d.ts +12 -2
- package/dist/plugins/local-task-attachment-store.js +67 -43
- package/dist/plugins/memory-key-guards.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +7 -2
- package/dist/plugins/memory-run-store.js +12 -2
- package/dist/plugins/one-time-migrations.d.ts +68 -2
- package/dist/plugins/one-time-migrations.js +120 -4
- 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-e2b.d.ts +47 -7
- package/dist/plugins/remote-env-e2b.js +242 -46
- package/dist/plugins/remote-env-k8s.d.ts +51 -6
- package/dist/plugins/remote-env-k8s.js +234 -44
- package/dist/plugins/remote-env-local-docker.d.ts +40 -14
- package/dist/plugins/remote-env-local-docker.js +127 -33
- package/dist/plugins/run-store-sql.d.ts +11 -3
- package/dist/plugins/run-store-sql.js +13 -4
- package/dist/plugins/sandbox-read-floor.d.ts +273 -0
- package/dist/plugins/sandbox-read-floor.js +608 -0
- 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-store.d.ts +18 -20
- package/dist/plugins/session-store.js +4 -12
- package/dist/plugins/store-backend.d.ts +41 -7
- package/dist/plugins/store-backend.js +22 -4
- package/dist/plugins/store-contracts.d.ts +35 -3
- package/dist/plugins/store-contracts.js +3 -0
- package/dist/plugins/task-attachment-store.d.ts +112 -14
- package/dist/plugins/task-attachment-store.js +221 -28
- package/dist/plugins/tidb-pool.js +2 -1
- package/dist/plugins/tidb-session-store.d.ts +4 -1
- package/dist/plugins/tidb-session-store.js +3 -2
- package/dist/plugins/workspace-fill.d.ts +60 -0
- package/dist/plugins/workspace-fill.js +106 -0
- package/dist/project-bundle.d.ts +38 -0
- package/dist/project-bundle.js +609 -0
- package/dist/run-cancel-context.d.ts +34 -0
- package/dist/run-cancel-context.js +7 -0
- package/dist/run-local.js +2 -8
- package/dist/runs.d.ts +39 -12
- package/dist/runs.js +69 -55
- package/dist/sandbox-egress-policy.d.ts +4 -1
- package/dist/sandbox-egress-policy.js +3 -1
- package/dist/sandbox-git-plane.d.ts +31 -12
- package/dist/sandbox-git-plane.js +24 -4
- package/dist/security.d.ts +11 -2
- package/dist/security.js +8 -0
- package/dist/server-secret-env.d.ts +2 -1
- package/dist/server-secret-env.js +2 -4
- package/dist/session-error-wire.d.ts +46 -4
- package/dist/session-error-wire.js +23 -0
- package/dist/session-incarnation.d.ts +9 -3
- 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/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/task-a2a.d.ts +1 -1
- package/dist/task-mcp.d.ts +1 -1
- package/dist/task-settings.d.ts +62 -27
- package/dist/task-settings.js +105 -29
- package/dist/terminal.d.ts +97 -20
- package/dist/terminal.js +107 -18
- package/dist/tool-approval.d.ts +4 -3
- package/dist/tool-approval.js +12 -14
- package/dist/trace/core-keyset-guard.d.ts +196 -2
- package/dist/trace/engine-notice-wire.d.ts +8 -2
- package/dist/trace/engine-notice-wire.js +4 -2
- package/dist/trace/exit-seat.d.ts +9 -1
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/ledger-sink.d.ts +8 -4
- package/dist/trace/ledger-sink.js +2 -2
- package/dist/trace/model-segment.d.ts +2 -2
- package/dist/trace/project.d.ts +18 -1
- package/dist/trace/project.js +16 -0
- package/dist/trace/redact.js +323 -90
- package/dist/trace/self-minted-wire.d.ts +419 -4
- package/dist/trace/self-minted-wire.js +145 -0
- package/dist/trace/wire-projection-faces.d.ts +1 -1
- package/dist/trace/wire-projection-faces.js +1 -1
- 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 +22 -2
- package/dist/web-admin-client/candidate-gate.d.ts +1 -1
- package/dist/web-admin-client/effective-keys.js +2 -0
- package/dist/web-admin-client/read-warnings.d.ts +2 -2
- package/dist/web-admin-client/types.d.ts +4 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
- package/package.json +2 -2
- package/wire-changes/server@7.141.0.json +367 -0
- package/wire-changes/server@7.142.0.json +639 -0
|
@@ -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,24 @@
|
|
|
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`)。
|
|
60
|
+
*
|
|
61
|
+
* ## 读一只会话的存档时的故障:一张表、两个读者({@link openFaceFaultWire})
|
|
62
|
+
* open 面映射有臂 ⇒ 那一格;否则(open 面留白的词,与不是 `SessionError` 的读故障 —— I/O 级的 EACCES / EISDIR …,core 的读腿只吞 ENOENT、其余 errno 原样抛)
|
|
63
|
+
* ⇒ 通用 500 {@link INTERNAL_ERROR_WIRE}。读者:① 全局兜底(`http/server.ts`:路由里逃出来的故障就按它答 —— 会话视图 / 头探针 / 事件流 / 改名门放行之后对坏档答的码
|
|
64
|
+
* 都出自这里);② 会话列表行的 `unreadable`({@link sessionUnreadableOf}:列表行 = 会话行,头的叶子读不出 ⇒ 行带标记,码 = 打开它时读口答的那一个)。
|
|
65
|
+
* 两个读者读同一只函数,列表说的码与读口答的码不会分叉。
|
|
58
66
|
*/
|
|
59
|
-
import
|
|
67
|
+
import { SessionError } from "@sema-agent/core";
|
|
60
68
|
/** core `SessionError` 的码闭集(core 不从包根导出这个型名 ⇒ 从导出类的 `code` 键派生,不手抄)。 */
|
|
61
69
|
export type SessionErrorCode = SessionError["code"];
|
|
62
70
|
/** 映射的面(见文件头注)。 */
|
|
@@ -76,7 +84,7 @@ export interface SessionErrorWire {
|
|
|
76
84
|
/** import 面 `invalid_session` 的固定句(修前 session-sync 暂存导入腿那一行的原文)。 */
|
|
77
85
|
export declare const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
|
|
78
86
|
/**
|
|
79
|
-
* import 面 `placement_refused` 的固定句:wire 上不发引擎原句 ——
|
|
87
|
+
* import 面 `placement_refused` 的固定句:wire 上不发引擎原句 —— 三只持久会话店的原句各不相同(措辞各自铸),都点名会话 id 与引擎内部词
|
|
80
88
|
* (「placement partition」「delegation transcript」);固定句只说调用方能做什么(冻结在 `test/api-error-text-freeze.test.ts` 的常量锚格)。
|
|
81
89
|
*/
|
|
82
90
|
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 +93,40 @@ export declare const PLACED_SESSION_SENTENCE = "this session holds a delegated a
|
|
|
85
93
|
* 不发店的原句(它点名会话 id);固定句只说发生了什么与出路(冻结在 `test/api-error-text-freeze.test.ts` 的常量锚格)。
|
|
86
94
|
*/
|
|
87
95
|
export declare const STAGED_IMPORT_OWNER_CHANGED_SENTENCE = "session owner changed while the import streamed; nothing was imported \u2014 start the sync again";
|
|
96
|
+
/**
|
|
97
|
+
* local 店的具名拒(唯一铸点 `plugins/local-session-store.ts`):这只会话的引擎存档仍带更早版本写下的属主戳(一次性迁移 M33 改写不了它,或数据根跳过了带这次迁移的版本)
|
|
98
|
+
* ⇒ 不在它上面造新存档(fork),也不原地换它的日志(改日志的推送);零写。码是 core 闭集的 `conflict`(码不另铸);句子(给运维日志,点名会话 id)归本错,
|
|
99
|
+
* wire 上发固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}(两面同一句;映射 {@link sessionErrorWireOf})。
|
|
100
|
+
*/
|
|
101
|
+
export declare class StampedSessionArchiveError extends SessionError {
|
|
102
|
+
readonly sessionId: string;
|
|
103
|
+
constructor(sessionId: string);
|
|
104
|
+
}
|
|
105
|
+
/** {@link StampedSessionArchiveError} 的 wire 固定句(fork 与改日志的推送同一句;不点名会话 id;出路在句里 —— 从头再同步照样撞)。 */
|
|
106
|
+
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";
|
|
107
|
+
/**
|
|
108
|
+
* 一只 `SessionError` 在一面上的 wire 答复 —— 下发点({@link sendSessionError} 的唯一读法)经这里:本服务自铸的同码具名拒先按型认(它的出路与同码的
|
|
109
|
+
* 按码答复不同),其余按码({@link sessionErrorHttp})。
|
|
110
|
+
*/
|
|
111
|
+
export declare function sessionErrorWireOf(e: SessionError, face: SessionErrorFace): SessionErrorWire | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* 全局兜底的末臂:open 面映射没有臂的故障(登记过的留白词;不是 `SessionError` 的故障)⇒ 通用 500,句子固定(故障的原句只进运维日志 `request_error`,
|
|
114
|
+
* 不上 wire —— I/O 级的原句带 errno 与盘上路径)。
|
|
115
|
+
*/
|
|
116
|
+
export declare const INTERNAL_ERROR_WIRE: SessionErrorWire & {
|
|
117
|
+
readonly sentence: string;
|
|
118
|
+
};
|
|
119
|
+
/** 一只读存档的故障在 open 面上的 wire 答复(两个读者见文件头注「一张表、两个读者」):有臂 ⇒ 那一格;否则 {@link INTERNAL_ERROR_WIRE}。 */
|
|
120
|
+
export declare function openFaceFaultWire(fault: unknown): SessionErrorWire;
|
|
121
|
+
/**
|
|
122
|
+
* 会话列表行的加性键 `unreadable`:这只会话的头的叶子读不出(存档读不出)。present-iff 读不出;`errorCode` = 读口打开这只会话时答的码
|
|
123
|
+
* (`GET /v1/sessions/:id` / `…/head` / `…/events` / `PATCH` 门放行之后)。今天读得到的值:`corrupt_session`(会话头坏)· `internal.error`(I/O 级)。
|
|
124
|
+
*/
|
|
125
|
+
export interface SessionUnreadable {
|
|
126
|
+
readonly errorCode: string;
|
|
127
|
+
}
|
|
128
|
+
/** {@link SessionUnreadable} 的唯一铸点(列表行的那只标记;码经 {@link openFaceFaultWire},与全局兜底同表)。 */
|
|
129
|
+
export declare function sessionUnreadableOf(fault: unknown): SessionUnreadable;
|
|
88
130
|
export declare function sessionErrorHttp(code: SessionErrorCode, face: SessionErrorFace): SessionErrorWire | undefined;
|
|
89
131
|
export declare function isSessionErrorCode(code: string): code is SessionErrorCode;
|
|
90
132
|
//# sourceMappingURL=session-error-wire.d.ts.map
|
|
@@ -1,12 +1,35 @@
|
|
|
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
|
+
}
|
|
26
|
+
export const INTERNAL_ERROR_WIRE = { status: 500, errorCode: "internal.error", sentence: "internal error" };
|
|
27
|
+
export function openFaceFaultWire(fault) {
|
|
28
|
+
return (fault instanceof SessionError ? sessionErrorWireOf(fault, "open") : undefined) ?? INTERNAL_ERROR_WIRE;
|
|
29
|
+
}
|
|
30
|
+
export function sessionUnreadableOf(fault) {
|
|
31
|
+
return { errorCode: openFaceFaultWire(fault).errorCode };
|
|
32
|
+
}
|
|
10
33
|
export function sessionErrorHttp(code, face) {
|
|
11
34
|
switch (code) {
|
|
12
35
|
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} 解码。
|
|
@@ -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
|
package/dist/session-sync.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { classifySyncRelationship } from "./session-sync-kernel.js";
|
|
1
|
+
import { anchorEntryDeclared, classifySyncRelationship } from "./session-sync-kernel.js";
|
|
2
|
+
import { recordFailOpen } from "./observability/fail-open.js";
|
|
2
3
|
import { loosenReasons, normalizeRules } from "@sema-agent/core";
|
|
3
4
|
import { headReadOf } from "./session-incarnation.js";
|
|
4
5
|
import { judgeSessionRulesWrite } from "@sema-agent/core";
|
|
@@ -60,8 +61,14 @@ export async function replayFileHistory(store, scope, envelope, srcGetBlob, opts
|
|
|
60
61
|
function ownerAware(backend) {
|
|
61
62
|
return backend.session();
|
|
62
63
|
}
|
|
64
|
+
const DIAG_VALUE_MAX = 96;
|
|
65
|
+
function brief(value) {
|
|
66
|
+
return JSON.stringify(value.length > DIAG_VALUE_MAX ? `${value.slice(0, DIAG_VALUE_MAX)}…(${value.length} chars)` : value);
|
|
67
|
+
}
|
|
63
68
|
export async function exportSessionManifest(sessionId, srcBackend, historyStore) {
|
|
64
69
|
const session = ownerAware(srcBackend);
|
|
70
|
+
const anchorStore = srcBackend.resumeAnchor();
|
|
71
|
+
const anchors = await anchorStore.listBySession(sessionId);
|
|
65
72
|
const listEntryIds = session.listEntryIds?.bind(session);
|
|
66
73
|
if (!listEntryIds)
|
|
67
74
|
return null;
|
|
@@ -76,15 +83,20 @@ export async function exportSessionManifest(sessionId, srcBackend, historyStore)
|
|
|
76
83
|
const policy = typeof policyStore.listBySession === "function"
|
|
77
84
|
? await policyStore.listBySession(sessionId)
|
|
78
85
|
: [];
|
|
79
|
-
const anchorStore = srcBackend.resumeAnchor();
|
|
80
|
-
const anchors = await anchorStore.listBySession(sessionId);
|
|
81
86
|
const summaryOf = session.sessionSummaryOf?.bind(session);
|
|
82
87
|
if (summaryOf === undefined)
|
|
83
88
|
throw new Error("exportSessionManifest: the session store has no row read face (sessionSummaryOf) — the sessionSync fact should have refused this deployment");
|
|
84
89
|
const row = await summaryOf(sessionId);
|
|
85
90
|
const getBlob = blobGetterOf(fs);
|
|
91
|
+
const declared = new Set(entryIds);
|
|
92
|
+
const soundAnchors = anchors.filter((a) => {
|
|
93
|
+
if (anchorEntryDeclared(declared, a.entryId))
|
|
94
|
+
return true;
|
|
95
|
+
recordFailOpen("server.session-sync.dangling-anchor-export", `sessionId=${brief(sessionId)} eventId=${brief(a.eventId)} entryId=${brief(a.entryId)}`);
|
|
96
|
+
return false;
|
|
97
|
+
});
|
|
86
98
|
return {
|
|
87
|
-
manifest: { sessionId, entryIds, entryCount: entryIds.length, leafId, fileHistory, policy, anchors, ...(row !== undefined ? { title: row.title, pinned: row.pinned } : {}) },
|
|
99
|
+
manifest: { sessionId, entryIds, entryCount: entryIds.length, leafId, fileHistory, policy, anchors: soundAnchors, ...(row !== undefined ? { title: row.title, pinned: row.pinned } : {}) },
|
|
88
100
|
getBlob,
|
|
89
101
|
};
|
|
90
102
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一只 SQL 引擎「开店所需的坐标」—— 单一来源(纯叶,零依赖)。
|
|
3
|
+
*
|
|
4
|
+
* ## 病
|
|
5
|
+
* 显式 `DB_BACKEND=pg|mysql` 是运维在说「我要这只持久引擎」。可是坐标缺席时,起服在三种 `SESSION_BACKEND` 写法下走三条路:
|
|
6
|
+
* 未设 / `mysql` ⇒ 读坐标抛 `missing required env`(响亮);`auto` ⇒ 「坐标不在就不探测」,**静默落内存**,姿态位却照报 `declared: "pg"` ——
|
|
7
|
+
* 一个自以为在持久化的部署跑在内存里,`/health` 照样 200。`REQUIRE_PRINCIPAL=true` 同形。同一个声明,拒不拒取决于第二个旋钮怎么写。
|
|
8
|
+
*
|
|
9
|
+
* ## 药
|
|
10
|
+
* 声明 ∧ 坐标缺席 ⇒ 配置期拒启,**不看** `SESSION_BACKEND`(判官在 `config.ts` 的 store 域,一只):三种写法同一句拒句,
|
|
11
|
+
* 拒句点名缺的坐标**键名**(不回显值,也读不到值)与两条出路。本模块只出两样东西:各引擎的必需坐标键表,与按这张表铸的两句话
|
|
12
|
+
* ({@link buildDeclaredEngineWithoutCoordinatesRefusal} 给配置判官、{@link buildSqlPoolMissingRefusal} 给 `boot/stores.ts` 的记忆引擎同池门)。
|
|
13
|
+
*
|
|
14
|
+
* ## 为什么键表在这里、`config.ts` 的 `env("MYSQL_HOST")` 读法不动
|
|
15
|
+
* 配置目录的对账门按名字面扫 `env("NAME")` 与 `process.env.NAME`,把读法改成按表取名会让它看不见这些键;所以两块 `env()` 读仍是字面读,
|
|
16
|
+
* 本表与它们的一致由 `test/sql-engine-coordinates.test.ts` 的源码钉守(表里每个键在 `config.ts` 里恰有一处 `env("KEY")` 必需读)。
|
|
17
|
+
*/
|
|
18
|
+
/** SQL 引擎词(`DB_BACKEND` 闭集里的两只持久引擎;`local` / `memory` 没有坐标)。 */
|
|
19
|
+
export type SqlEngine = "mysql" | "pg";
|
|
20
|
+
/**
|
|
21
|
+
* 每只引擎开店**必需**的坐标键(缺一 `config.ts` 的对应块抛 `missing required env`)。可选键(`*_PORT` / `*_PASSWORD` / `*_POOL_SIZE`)不在表里 ——
|
|
22
|
+
* 它们缺席有缺省,不是「没有坐标」。主机键是首位:它是「SQL 信号」与 `auto` 探测的唯一判据(`config.ts` `dbHostSet`)。
|
|
23
|
+
*/
|
|
24
|
+
export declare const SQL_ENGINE_COORDINATE_KEYS: {
|
|
25
|
+
readonly mysql: readonly ["MYSQL_HOST", "MYSQL_USER", "MYSQL_DATABASE"];
|
|
26
|
+
readonly pg: readonly ["PG_HOST", "PG_USER", "PG_DATABASE"];
|
|
27
|
+
};
|
|
28
|
+
/** 该引擎的主机键(`SQL_ENGINE_COORDINATE_KEYS` 的首位)。 */
|
|
29
|
+
export declare function sqlEngineHostKey(engine: SqlEngine): string;
|
|
30
|
+
/** 必需坐标键里此刻缺席(未设或空串 —— 空串在本仓一律等同未设)的那几个,表序。只读键名,不读值。 */
|
|
31
|
+
export declare function missingSqlCoordinateKeys(engine: SqlEngine, env: NodeJS.ProcessEnv): readonly string[];
|
|
32
|
+
/**
|
|
33
|
+
* 显式 `DB_BACKEND=<engine>` 而该引擎的坐标缺席 ⇒ 配置期拒启句(唯一铸点;**与 `SESSION_BACKEND` 无关**,所以句子里没有它)。
|
|
34
|
+
* `missing` 是 {@link missingSqlCoordinateKeys} 的读数(此时至少含主机键)。
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildDeclaredEngineWithoutCoordinatesRefusal(engine: SqlEngine, missing: readonly string[]): string;
|
|
37
|
+
/**
|
|
38
|
+
* 记忆引擎要绑 `<engine>` 的池而店后端没给 ⇒ `boot/stores.ts` 的拒句。记忆持久面的 SQL 方言词与店的引擎词是**同一个字**(`MEMORY_ENGINE_BACKEND=pg|mysql`
|
|
39
|
+
* ↔ `DB_BACKEND=pg|mysql`),所以拒句只收引擎词。分两形(`DB_BACKEND` 是否已经点名该引擎):
|
|
40
|
+
* · 没点名 ⇒ 缺的是声明:`MEMORY_ENGINE_BACKEND=<engine>` 要 `DB_BACKEND=<engine>`;
|
|
41
|
+
* · 已点名 ⇒ 声明没缺,「要 DB_BACKEND=<engine>」指错了修法 —— 点名真正开店的两个条件(持久会话后端、必需坐标)与此刻缺的坐标键。
|
|
42
|
+
* 坐标缺席本身在配置期已被 {@link buildDeclaredEngineWithoutCoordinatesRefusal} 拒掉,走到这里的已点名形 = 坐标齐(或只缺非主机键)而会话后端是 `memory`。
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildSqlPoolMissingRefusal(args: {
|
|
45
|
+
readonly engine: SqlEngine;
|
|
46
|
+
readonly declared: boolean;
|
|
47
|
+
readonly missing: readonly string[];
|
|
48
|
+
}): string;
|
|
49
|
+
//# sourceMappingURL=sql-engine-coordinates.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const SQL_ENGINE_COORDINATE_KEYS = {
|
|
2
|
+
mysql: ["MYSQL_HOST", "MYSQL_USER", "MYSQL_DATABASE"],
|
|
3
|
+
pg: ["PG_HOST", "PG_USER", "PG_DATABASE"],
|
|
4
|
+
};
|
|
5
|
+
export function sqlEngineHostKey(engine) {
|
|
6
|
+
return SQL_ENGINE_COORDINATE_KEYS[engine][0];
|
|
7
|
+
}
|
|
8
|
+
export function missingSqlCoordinateKeys(engine, env) {
|
|
9
|
+
return SQL_ENGINE_COORDINATE_KEYS[engine].filter((key) => env[key] === undefined || env[key] === "");
|
|
10
|
+
}
|
|
11
|
+
const ENGINE_LABEL = { mysql: "MySQL-protocol", pg: "PostgreSQL" };
|
|
12
|
+
export function buildDeclaredEngineWithoutCoordinatesRefusal(engine, missing) {
|
|
13
|
+
const required = SQL_ENGINE_COORDINATE_KEYS[engine];
|
|
14
|
+
return (`DB_BACKEND=${engine} declares the ${ENGINE_LABEL[engine]} engine, but its connection coordinates are not set (missing: ${missing.join(", ")}) — ` +
|
|
15
|
+
`no session store can open, so the deployment would run IN MEMORY while declaring a durable engine. ` +
|
|
16
|
+
`Refusing to boot rather than starting non-durable under that declaration (whatever SESSION_BACKEND says). ` +
|
|
17
|
+
`To persist: set ${required.join(", ")} (optional: ${engine === "pg" ? "PG_PORT, PG_PASSWORD" : "MYSQL_PORT, MYSQL_PASSWORD"}); ` +
|
|
18
|
+
`to run without SQL: DB_BACKEND=local (single-user file store) or DB_BACKEND=memory.`);
|
|
19
|
+
}
|
|
20
|
+
export function buildSqlPoolMissingRefusal(args) {
|
|
21
|
+
const { engine, declared, missing } = args;
|
|
22
|
+
if (!declared)
|
|
23
|
+
return `MEMORY_ENGINE_BACKEND=${engine} requires DB_BACKEND=${engine} (the memory engine binds the same ${ENGINE_LABEL[engine]} pool) — refusing to start half-configured`;
|
|
24
|
+
return (`MEMORY_ENGINE_BACKEND=${engine} binds the ${ENGINE_LABEL[engine]} pool of the deployment's store, but none is open although the effective DB_BACKEND is ${engine}: the SQL store opens only under a durable session backend (SESSION_BACKEND unset, mysql or auto — not memory) ` +
|
|
25
|
+
`with ${SQL_ENGINE_COORDINATE_KEYS[engine].join(", ")} set${missing.length > 0 ? ` (not set now: ${missing.join(", ")})` : ""} — refusing to start half-configured`);
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=sql-engine-coordinates.js.map
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 站着的答案的**授予绑定**的唯一读口:这一问的应答授不授予「这一次调用」之外的东西,授予的话绑定是什么。
|
|
3
|
+
*
|
|
4
|
+
* 站着的答案(活的「本会话放行」、耐久的 `remember:"session"`)记下的是**上一次**应答;它只配代答「上一次应答覆盖得到」的问。
|
|
5
|
+
* 有一类卡的应答还**授予**别的东西:批准引擎的 `Skill` = 激活那只技能 + 本 run 内它 `allowedTools` 上的工具免问。这类卡的答案只能按
|
|
6
|
+
* 「工具 + 授予绑定」记、只代答绑定相同的问(core 原句「an answer is remembered by "this tool + this binding"」)。判据本身在
|
|
7
|
+
* `tool-approval.ts` 的 `standingAnswerHome`(本读口是它的一位);本文件只回答「授不授予、绑定是什么」,是叶模块。
|
|
8
|
+
*
|
|
9
|
+
* 🔴 **一条律:只读引擎的词,载体不论**。引擎的绑定工厂给一次调用的每一个载体盖**同一组词**、恰带一臂:`boundGrantDigest`(对引擎 `Skill` 工具的
|
|
10
|
+
* 激活:技能名 + 两只清单规范拼写的摘要)或 `boundGrantAbsence`(闭集 core `BOUND_GRANT_ABSENCES`:`not_bindable` = 不绑任何授予 / `unreadable` = 绑着却读不出)。
|
|
11
|
+
* 载体 = 活的 `AskRequest`、停驻行 `PendingAction.tool_approval`、读这两者的运维队列行 / inbox 行,以及 core 7.59.0 起 Runner 交给策略层的 `ToolCallRequest`
|
|
12
|
+
* (部署名单门、workflow 问句门在交出自己的问之前读它)。读法与 core 自己的 inbox 投影逐臂同一条:摘要是串 ⇒ `bound`;否则摘要不在且词是 `not_bindable`
|
|
13
|
+
* ⇒ `none`;其余(词是 `unreadable`、摘要在而不是串、集外词、两者都不说)⇒ `unreadable`。**不读工具名**。
|
|
14
|
+
* · 两者都不说的载体:7.51.0 之前停驻的行(core:「it does not say」)、宿主不经 Runner 自建的请求 —— 读作 `unreadable`:不可记、不被代答(fail-closed)。
|
|
15
|
+
* · 读面上的那一臂({@link grantBindingArm})是本读口的逆像:停驻行的运维队列行 / `/stream` 的 `pending` 帧投的就是 `grantBindingArm(grantBindingOf(行))` ——
|
|
16
|
+
* 恰带摘要与缺席词之一,与 core 投收件箱行的那一臂同值;卡上显示的臂与「本会话放行」记不记得住由同一次读定,不会两答。
|
|
17
|
+
* · 部署名单自己的问(答案记在 server 的会话豁免店,按 (会话, 工具名))的写侧、名单门的读侧、豁免列表三处读同一组词 —— 7.129.0–7.137.x 读侧手里的请求
|
|
18
|
+
* 不带词,三处只好按工具名读调用载体;那只读口随 core 7.59.0 退役。
|
|
19
|
+
*/
|
|
20
|
+
import type { BoundGrantAbsence } from "@sema-agent/core";
|
|
1
21
|
/** 载体:引擎给一次调用盖过绑定词的任何形(活的 `AskRequest`、停驻行的 `tool_approval` 臂、运维队列行、策略层的 `ToolCallRequest` 都结构上满足)。 */
|
|
2
22
|
export interface StandingAnswerCard {
|
|
3
23
|
readonly boundGrantDigest?: unknown;
|
|
@@ -12,6 +32,15 @@ export type GrantBinding = {
|
|
|
12
32
|
} | {
|
|
13
33
|
readonly kind: "unreadable";
|
|
14
34
|
};
|
|
15
|
-
/** 载体上的授予绑定 —— 只读引擎的词(读法见文件头注):摘要是串 ⇒ bound;摘要不在且词是 `not_bindable` ⇒ none;其余 ⇒ unreadable。
|
|
16
|
-
|
|
35
|
+
/** 载体上的授予绑定 —— 只读引擎的词(读法见文件头注):摘要是串 ⇒ bound;摘要不在且词是 `not_bindable` ⇒ none;其余 ⇒ unreadable。
|
|
36
|
+
* 形参是任意对象(载体不论):读自持久层的停驻行(运维队列行的投影、`/decide` 的原始行)两座都按 `unknown` 读,结构上满足 {@link StandingAnswerCard} 的载体照传。 */
|
|
37
|
+
export declare function grantBindingOf(card: StandingAnswerCard | object): GrantBinding;
|
|
38
|
+
/** 授予绑定在读面上的形:恰一臂 —— 摘要,或缺席词(闭集 core `BOUND_GRANT_ABSENCES`)。 */
|
|
39
|
+
export type GrantBindingArm = {
|
|
40
|
+
readonly boundGrantDigest: string;
|
|
41
|
+
} | {
|
|
42
|
+
readonly boundGrantAbsence: BoundGrantAbsence;
|
|
43
|
+
};
|
|
44
|
+
/** {@link GrantBinding} 投回读面的那一臂(逐臂穷尽:core 给绑定加一态而这里不跟 ⇒ 编译红):bound ⇒ 摘要;none ⇒ `not_bindable`;unreadable ⇒ `unreadable`。 */
|
|
45
|
+
export declare function grantBindingArm(binding: GrantBinding): GrantBindingArm;
|
|
17
46
|
//# sourceMappingURL=standing-answer-grant.d.ts.map
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
const NOT_BINDABLE = "not_bindable";
|
|
2
|
+
const UNREADABLE = "unreadable";
|
|
2
3
|
export function grantBindingOf(card) {
|
|
3
|
-
const digest = card.boundGrantDigest;
|
|
4
|
+
const digest = "boundGrantDigest" in card ? card.boundGrantDigest : undefined;
|
|
4
5
|
if (typeof digest === "string")
|
|
5
6
|
return { kind: "bound", digest };
|
|
6
|
-
|
|
7
|
+
const word = "boundGrantAbsence" in card ? card.boundGrantAbsence : undefined;
|
|
8
|
+
return digest === undefined && word === NOT_BINDABLE ? { kind: "none" } : { kind: "unreadable" };
|
|
9
|
+
}
|
|
10
|
+
export function grantBindingArm(binding) {
|
|
11
|
+
switch (binding.kind) {
|
|
12
|
+
case "bound":
|
|
13
|
+
return { boundGrantDigest: binding.digest };
|
|
14
|
+
case "none":
|
|
15
|
+
return { boundGrantAbsence: NOT_BINDABLE };
|
|
16
|
+
case "unreadable":
|
|
17
|
+
return { boundGrantAbsence: UNREADABLE };
|
|
18
|
+
}
|
|
7
19
|
}
|
|
8
20
|
//# sourceMappingURL=standing-answer-grant.js.map
|
package/dist/store-posture.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* ## 形
|
|
10
10
|
* `declared` = 运维的声明(`DB_BACKEND` 词,含缺省推导);`backend` = **装配出的**后端 kind(没装出后端 = `memory`);两者不等是合法的
|
|
11
|
-
* 形(`DB_BACKEND=pg` + `SESSION_BACKEND=memory` = 声明 pg
|
|
11
|
+
* 形(`DB_BACKEND=pg` + 坐标在场 + `SESSION_BACKEND=memory` = 声明 pg、刻意不持久 —— 坐标缺席的声明在配置期拒启,见 `sql-engine-coordinates.ts`;缺省推导 local 起不来)—— 两位都上 wire,
|
|
12
12
|
* 由调用方自己读出落差。`degradedReason` present-iff 降级臂走过(按后端族定词,{@link storeDegradedReasonFor})。
|
|
13
13
|
* 顶层 `sql` 并入 `store.sql`(硬 breaking,零别名;对象逐字同形)。
|
|
14
14
|
*/
|
package/dist/task-a2a.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare const A2A_PEER_DISPOSITION: {
|
|
|
57
57
|
readonly toolAxes: "engine";
|
|
58
58
|
};
|
|
59
59
|
/** 请求体 `a2aPeers[i]` 的键闭集 = 处置表的键(书写序即判序)。 */
|
|
60
|
-
export declare const A2A_PEER_ENTRY_KEYS: readonly ("name" | "headers" | "
|
|
60
|
+
export declare const A2A_PEER_ENTRY_KEYS: readonly ("name" | "headers" | "url" | "principalHeader" | "toolAxes" | "cardUrl" | "allowSkills")[];
|
|
61
61
|
/**
|
|
62
62
|
* **请求入口的一次读**(`boot/resolve-spec.ts` 在腿首铸一份,受理门与读器——续跑重放腿只有读器——都吃这一份):`body.a2aPeers` 若是数组,返回同形数组
|
|
63
63
|
* (每个对象条目换成它的 {@link PeerSnapshot};非对象条目原样;长度保真 —— 界外的条数仍是受理门撞帽拒与读器丢弃留声的依据,只快照界内的条目);不是数组(缺席 / `null` / 别的形)原样返回。
|
package/dist/task-mcp.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ export declare const MCP_SERVER_ENTRY_KEYS: readonly ["allowTools", "contentOrig
|
|
|
71
71
|
/** `transport.kind:"stdio"` 的键闭集 = stdio 臂处置表的键(`env` 是件,其余进声明)。 */
|
|
72
72
|
export declare const STDIO_MCP_TRANSPORT_KEYS: readonly ("env" | "kind" | "args" | "command")[];
|
|
73
73
|
/** `transport.kind:"http"` 的键闭集 = http 臂处置表的键(`headers` 是件,`assertionHeader` 承载不发送,其余进声明)。 */
|
|
74
|
-
export declare const HTTP_MCP_TRANSPORT_KEYS: readonly ("headers" | "kind" | "
|
|
74
|
+
export declare const HTTP_MCP_TRANSPORT_KEYS: readonly ("headers" | "kind" | "url" | "principalHeader" | "assertionHeader")[];
|
|
75
75
|
/**
|
|
76
76
|
* Does THIS deployment honor caller-supplied per-request MCP servers? TRUE for a SINGLE-USER deployment
|
|
77
77
|
* (deployment-shape row `multiTenant` does not hold) — the requester is the super-admin of their own worker, so their `.mcp.json` is
|