@sema-agent/server 7.138.0 → 7.140.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 +457 -7
- package/README.md +7 -4
- package/README.zh-CN.md +6 -4
- package/USAGE.md +91 -41
- package/deploy/sema-up/README.md +1 -1
- package/deploy/sema-up/lib/lanes.json +3 -2
- package/dist/adoption/runner.js +1 -1
- package/dist/adoption/sql.js +1 -1
- package/dist/adoption/wire.d.ts +3 -3
- package/dist/approval-card.d.ts +26 -26
- package/dist/bench/s1/arms.d.ts +1 -1
- package/dist/bench/s1/arms.js +1 -3
- 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/bench/s1/run-firm.js +2 -2
- package/dist/boot/adoption.js +1 -1
- package/dist/boot/device-lane.d.ts +8 -3
- package/dist/boot/device-lane.js +7 -2
- package/dist/boot/execution-env.d.ts +4 -2
- package/dist/boot/execution-env.js +28 -34
- package/dist/boot/execution-lane.d.ts +9 -1
- package/dist/boot/execution-lane.js +6 -1
- package/dist/boot/governance-seams.d.ts +3 -2
- package/dist/boot/governance-seams.js +9 -11
- package/dist/boot/memory-boundary.d.ts +14 -51
- package/dist/boot/memory-boundary.js +10 -20
- package/dist/boot/memory-consolidation.d.ts +15 -11
- package/dist/boot/memory-consolidation.js +25 -14
- package/dist/boot/resolve-spec.d.ts +4 -6
- package/dist/boot/resolve-spec.js +10 -13
- package/dist/boot/retention-lane.d.ts +5 -5
- package/dist/boot/retention-lane.js +0 -6
- package/dist/boot/runner-deps.d.ts +6 -4
- package/dist/boot/runner-deps.js +3 -1
- package/dist/boot/session-faces.d.ts +0 -3
- package/dist/boot/session-faces.js +15 -8
- package/dist/boot/stage-02-web-admin-pull.js +2 -2
- 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 +2 -2
- package/dist/boot/stage-06-runners.d.ts +2 -6
- package/dist/boot/stage-06-runners.js +2 -3
- package/dist/boot/stage-07-capability-layer.d.ts +2 -6
- package/dist/boot/stage-08-reapers.d.ts +2 -6
- package/dist/boot/stage-09-leader.d.ts +2 -6
- package/dist/boot/stage-09-leader.js +1 -2
- package/dist/boot/stage-10-http-server.d.ts +2 -6
- package/dist/boot/stage-10-http-server.js +7 -6
- package/dist/boot/stores.d.ts +3 -6
- package/dist/boot/stores.js +27 -40
- 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 +37 -11
- package/dist/capabilities/execution-lane.d.ts +2 -2
- package/dist/capabilities/mcp-probe.js +1 -1
- package/dist/capabilities/scenarios.d.ts +1 -1
- package/dist/capability-facts.d.ts +15 -7
- package/dist/capability-facts.js +8 -3
- package/dist/config-catalog.js +9 -8
- package/dist/config-invariants.d.ts +23 -3
- package/dist/config-invariants.js +42 -0
- package/dist/config-provider.d.ts +33 -37
- package/dist/config-provider.js +51 -30
- package/dist/config-types.d.ts +21 -7
- package/dist/config.d.ts +33 -0
- package/dist/config.js +46 -16
- package/dist/delegated-session-owner.d.ts +4 -3
- package/dist/delegated-session-owner.js +1 -1
- package/dist/deployment-shape.d.ts +10 -9
- package/dist/deployment-shape.js +4 -4
- package/dist/device-enrollment.d.ts +41 -2
- package/dist/device-enrollment.js +27 -12
- package/dist/device-store.d.ts +58 -85
- package/dist/device-store.js +19 -49
- package/dist/device-ws-hub.js +2 -1
- package/dist/env-name-allowlist-knobs.d.ts +5 -4
- package/dist/exec-cut.d.ts +60 -0
- package/dist/exec-cut.js +36 -0
- package/dist/execution-lane-caps.d.ts +115 -105
- package/dist/execution-lane-caps.js +76 -82
- package/dist/execution-placement.d.ts +259 -0
- package/dist/execution-placement.js +199 -0
- package/dist/field-conflict.d.ts +3 -2
- package/dist/field-conflict.js +1 -0
- package/dist/hosted-posture.d.ts +2 -2
- package/dist/http/admission.js +8 -19
- package/dist/http/checkpoint-ctx.d.ts +21 -12
- package/dist/http/checkpoint-ctx.js +4 -2
- package/dist/http/claimed-run.d.ts +1 -1
- package/dist/http/durable-run-leg.js +9 -5
- package/dist/http/execution-context.d.ts +218 -0
- package/dist/http/execution-context.js +330 -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 +63 -36
- package/dist/http/retired-service-deps.d.ts +1 -1
- package/dist/http/retired-service-deps.js +1 -1
- package/dist/http/route-ctx.d.ts +14 -8
- package/dist/http/routes/adoption.js +1 -1
- package/dist/http/routes/background.d.ts +29 -1
- package/dist/http/routes/background.js +29 -2
- package/dist/http/routes/devices.d.ts +13 -19
- package/dist/http/routes/devices.js +21 -26
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-compliance.js +8 -1
- 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 +5 -0
- package/dist/http/routes/session-sync.js +110 -15
- package/dist/http/routes/sessions.d.ts +6 -0
- package/dist/http/routes/sessions.js +143 -22
- package/dist/http/routes/side-query.d.ts +12 -4
- package/dist/http/routes/side-query.js +4 -5
- package/dist/http/routes/tasks.js +41 -33
- package/dist/http/server.d.ts +40 -44
- package/dist/http/server.js +13 -2
- package/dist/http/session-inherit-env.d.ts +3 -4
- package/dist/http/session-inherit-env.js +1 -1
- package/dist/http/wire-types.d.ts +8 -12
- package/dist/identity-source.d.ts +1 -1
- package/dist/identity-source.js +1 -1
- package/dist/index.d.ts +1 -0
- 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/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-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 +29 -5
- package/dist/memory-scope.js +16 -4
- package/dist/memory-sync-client.d.ts +70 -18
- package/dist/memory-sync-client.js +215 -117
- package/dist/memory-sync.d.ts +1 -1
- package/dist/memory-sync.js +3 -2
- package/dist/observability/cost-taxonomy.d.ts +2 -2
- package/dist/observability/fail-open.d.ts +12 -0
- package/dist/observability/fail-open.js +12 -0
- package/dist/observability/run-terminal.js +0 -1
- package/dist/orchestration/workflow-notify-journal.js +4 -4
- package/dist/org-memory-admission.d.ts +4 -3
- package/dist/org-memory-admission.js +6 -6
- package/dist/parked-decide.d.ts +34 -9
- package/dist/parked-decide.js +12 -19
- package/dist/parked-revive-surface.d.ts +12 -15
- package/dist/parked-revive-surface.js +3 -6
- package/dist/peer-seat.d.ts +13 -7
- package/dist/peer-seat.js +37 -3
- package/dist/plugins/adoption-log-sql.js +4 -4
- package/dist/plugins/approval-ask-store-file.d.ts +7 -0
- package/dist/plugins/approval-ask-store-file.js +11 -0
- package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
- package/dist/plugins/approval-ask-store-memory.js +12 -0
- package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
- package/dist/plugins/approval-ask-store-sql.js +44 -26
- 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 -2
- package/dist/plugins/caching-session-store.js +9 -3
- package/dist/plugins/checkpoint-index-columns.js +2 -2
- package/dist/plugins/checkpoint-store-sql.d.ts +6 -5
- package/dist/plugins/checkpoint-store-sql.js +21 -23
- package/dist/plugins/device-store-sql.d.ts +25 -51
- package/dist/plugins/device-store-sql.js +68 -122
- package/dist/plugins/ensure-index.d.ts +1 -2
- package/dist/plugins/execution-placement-sql.d.ts +151 -0
- package/dist/plugins/execution-placement-sql.js +223 -0
- package/dist/plugins/file-history-store-sql.d.ts +9 -8
- package/dist/plugins/file-history-store-sql.js +9 -9
- package/dist/plugins/file-run-store.d.ts +6 -1
- package/dist/plugins/file-run-store.js +4 -0
- package/dist/plugins/fork-routing-session-store.d.ts +6 -0
- package/dist/plugins/fork-routing-session-store.js +16 -0
- package/dist/plugins/image-bake-store-sql.js +9 -9
- package/dist/plugins/image-index-sql.js +11 -11
- package/dist/plugins/leader-run-store-sql.js +4 -4
- package/dist/plugins/local-session-store.d.ts +149 -50
- package/dist/plugins/local-session-store.js +382 -107
- 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-key-guards.d.ts +4 -0
- package/dist/plugins/memory-key-guards.js +1 -0
- package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
- package/dist/plugins/memory-run-store.d.ts +1 -1
- package/dist/plugins/memory-sync-store-tidb.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +117 -8
- package/dist/plugins/one-time-migrations.js +408 -38
- package/dist/plugins/org-delivery-quota-store.js +2 -2
- package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
- package/dist/plugins/outcome-ledger-sql.js +2 -2
- package/dist/plugins/permission-rule-store-sql.d.ts +17 -19
- package/dist/plugins/permission-rule-store-sql.js +29 -32
- package/dist/plugins/pg-pool.d.ts +7 -3
- package/dist/plugins/pg-session-storage.d.ts +31 -20
- package/dist/plugins/pg-session-storage.js +120 -52
- package/dist/plugins/remote-env-adb.d.ts +18 -19
- package/dist/plugins/remote-env-adb.js +91 -66
- package/dist/plugins/remote-env-device.d.ts +23 -31
- package/dist/plugins/remote-env-device.js +19 -17
- package/dist/plugins/remote-env-e2b.d.ts +27 -21
- package/dist/plugins/remote-env-e2b.js +91 -45
- package/dist/plugins/remote-env-file-error.d.ts +3 -1
- package/dist/plugins/remote-env-file-error.js +9 -3
- package/dist/plugins/remote-env-host.d.ts +31 -34
- package/dist/plugins/remote-env-host.js +91 -72
- package/dist/plugins/remote-env-k8s.d.ts +13 -29
- package/dist/plugins/remote-env-k8s.js +63 -55
- package/dist/plugins/remote-env-local-docker.d.ts +24 -12
- package/dist/plugins/remote-env-local-docker.js +49 -61
- package/dist/plugins/remote-env-ssh.d.ts +11 -19
- package/dist/plugins/remote-env-ssh.js +74 -57
- package/dist/plugins/remote-shell.d.ts +100 -3
- package/dist/plugins/remote-shell.js +166 -2
- 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 +10 -7
- package/dist/plugins/retention-store-sql.js +13 -7
- package/dist/plugins/run-store-sql.d.ts +13 -3
- package/dist/plugins/run-store-sql.js +20 -15
- package/dist/plugins/schema-consistency.d.ts +21 -11
- package/dist/plugins/schema-consistency.js +15 -9
- package/dist/plugins/schema-drift-sentence.d.ts +27 -0
- package/dist/plugins/schema-drift-sentence.js +38 -0
- 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-fork.d.ts +54 -0
- package/dist/plugins/session-fork.js +38 -1
- package/dist/plugins/session-row-sql.d.ts +22 -0
- package/dist/plugins/session-row-sql.js +81 -0
- 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 +1 -1
- 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 +5 -7
- package/dist/plugins/store-backend.js +23 -11
- package/dist/plugins/store-contracts.d.ts +25 -5
- package/dist/plugins/task-list-store-sql.js +11 -11
- package/dist/plugins/tidb-pool.d.ts +12 -7
- package/dist/plugins/tidb-pool.js +13 -7
- package/dist/plugins/tidb-session-storage.js +4 -4
- package/dist/plugins/tidb-session-store.d.ts +57 -26
- package/dist/plugins/tidb-session-store.js +127 -59
- package/dist/plugins/tool-result-store-sql.d.ts +5 -4
- package/dist/plugins/tool-result-store-sql.js +21 -13
- 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/project-memory.d.ts +9 -15
- package/dist/project-memory.js +5 -4
- package/dist/request-key-closure.js +1 -1
- package/dist/request-value-closure.d.ts +6 -7
- package/dist/request-value-closure.js +1 -3
- 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-local.d.ts +6 -0
- package/dist/run-local.js +34 -35
- package/dist/runs.d.ts +10 -5
- package/dist/runs.js +52 -66
- package/dist/security.d.ts +38 -12
- package/dist/security.js +8 -2
- package/dist/server-secret-env.d.ts +9 -5
- package/dist/session-children-retire.d.ts +27 -9
- package/dist/session-children-retire.js +9 -5
- package/dist/session-incarnation.d.ts +20 -10
- package/dist/session-incarnation.js +5 -3
- package/dist/session-policy-wire.d.ts +1 -1
- package/dist/session-row.d.ts +114 -5
- package/dist/session-row.js +55 -5
- package/dist/session-titler.d.ts +2 -2
- package/dist/sql-engine-posture.d.ts +1 -1
- package/dist/sql-engine-posture.js +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-cwd.d.ts +6 -1
- package/dist/task-mcp.d.ts +22 -9
- package/dist/task-mcp.js +17 -9
- package/dist/terminal.d.ts +27 -0
- package/dist/terminal.js +6 -0
- package/dist/tool-approval.d.ts +6 -0
- package/dist/tool-approval.js +8 -1
- package/dist/trace/project.d.ts +1 -0
- package/dist/trace/project.js +1 -0
- package/dist/trace/redact.d.ts +3 -1
- package/dist/trace/redact.js +80 -28
- package/dist/trace/self-minted-wire.d.ts +169 -2
- package/dist/trace/self-minted-wire.js +54 -1
- package/dist/url-refusal.d.ts +1 -1
- package/dist/web-admin-client/apply-effective.d.ts +17 -3
- package/dist/web-admin-client/apply-effective.js +20 -10
- 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/dist/web-admin-client/skills-mcp.js +3 -2
- package/dist/web-admin-client/types.d.ts +6 -0
- package/package.json +3 -3
- package/wire-changes/server@7.139.0.json +348 -0
- package/wire-changes/server@7.140.0.json +184 -0
- package/dist/http/device-placement.d.ts +0 -175
- package/dist/http/device-placement.js +0 -145
package/dist/device-store.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { DeviceBindOutcome, DeviceRebindOutcome, InMemoryExecutionPlacementSeat } from "./execution-placement.js";
|
|
2
|
+
import type { SessionFace } from "./session-incarnation.js";
|
|
1
3
|
/**
|
|
2
4
|
* device lane 的 HTTP 错误码闭集(v2 §4.8 逐字)。**唯一导出点** —— 端点车(A-3/车C)从这里取,
|
|
3
5
|
* 禁在路由里手抄字面量(§4.8 task-R1-12:「下表即闭集全集,禁四份手抄」)。
|
|
@@ -33,7 +35,7 @@ export declare const DEVICE_ERROR_CODES: {
|
|
|
33
35
|
* (管理面,`http/routes/devices.ts`);adapter/准入链结构上不产它。 */
|
|
34
36
|
readonly REBIND_REV_CONFLICT: "device.rebind_rev_conflict";
|
|
35
37
|
/** O4 换绑动词(v2 稿 §2 步 4):该根会话名下有非终态 run(durable 判据 = run store 的 session
|
|
36
|
-
* claim;hub
|
|
38
|
+
* claim;hub 内存在途计数**不作门**——跨副本不可见;保证 = 设备店换绑事务内锁根行后那一读,池级读只作早拒)—— 体带 `activeTaskId`。铸造点同上一条。 */
|
|
37
39
|
readonly REBIND_ACTIVE_RUN: "device.rebind_active_run";
|
|
38
40
|
};
|
|
39
41
|
/** {@link DEVICE_ERROR_CODES} 的值联合 —— 闭集(未知码 = 编译错误,[ref] 词表纪律)。 */
|
|
@@ -113,14 +115,6 @@ export interface DeviceRow {
|
|
|
113
115
|
createdAtMs: number;
|
|
114
116
|
rev: number;
|
|
115
117
|
}
|
|
116
|
-
export interface DeviceSessionRow {
|
|
117
|
-
/** 键 = **根**会话(task-R1-3:后代继承不另绑)。 */
|
|
118
|
-
rootSessionId: string;
|
|
119
|
-
deviceId: string;
|
|
120
|
-
owner: DeviceOwner;
|
|
121
|
-
boundAtMs: number;
|
|
122
|
-
rev: number;
|
|
123
|
-
}
|
|
124
118
|
export interface DeviceAuditRow {
|
|
125
119
|
id: number;
|
|
126
120
|
atMs: number;
|
|
@@ -147,7 +141,7 @@ export interface DeviceEnrollTokenRow {
|
|
|
147
141
|
export declare const DEVICE_KEY_MAX_BYTES = 190;
|
|
148
142
|
/** `device_id` 列宽(`dev_` + 26 位 Crockford base32 ULID = 30 字节,64 是三倍余量)。 */
|
|
149
143
|
export declare const DEVICE_ID_MAX_BYTES = 64;
|
|
150
|
-
/** `
|
|
144
|
+
/** 根会话 id 的形门上界(换绑路由的路径段;会话行 `session_id` 宽 64,提交入口硬拒 >64 的 sessionId,128 留一倍余量 —— 超宽的 id 等值读不到任何行)。 */
|
|
151
145
|
export declare const DEVICE_SESSION_ID_MAX_BYTES = 128;
|
|
152
146
|
/** `pubkey` / `token_hash` 列宽(Ed25519 b64 = 44,sha256 hex = 64)。 */
|
|
153
147
|
export declare const DEVICE_PUBKEY_MAX_BYTES = 128;
|
|
@@ -176,10 +170,12 @@ export declare function assertDevicePubkeyShape(pubkey: string): void;
|
|
|
176
170
|
export declare function assertNewDeviceShape(input: NewDeviceInput): void;
|
|
177
171
|
export declare function assertIssueTokenShape(input: IssueEnrollTokenInput): void;
|
|
178
172
|
export declare function assertRevokeShape(input: RevokeDeviceInput): void;
|
|
173
|
+
/** device 首绑入参的整形门(三形共用:内存参照实现与两方言从同一处过)。 */
|
|
174
|
+
export declare function assertPlaceDeviceShape(input: PlaceDeviceExecutionInput): void;
|
|
179
175
|
/** O4 换绑入参的整形门(三形共用)。`expectedRev` 收窄为非负整数:它要进 SQL 等值谓词,小数/负数/NaN
|
|
180
176
|
* 在两方言的 BIGINT 比对下不是「不匹配」而是各自的隐式转换歧义面 —— 在门口拒,方言分歧面消失。
|
|
181
177
|
* ⚠️ HTTP 层对坏形先答 400(业务拒绝);这里的抛是**编程/装配错误**的兜底,不是 wire 分支。 */
|
|
182
|
-
export declare function assertRebindShape(input:
|
|
178
|
+
export declare function assertRebindShape(input: RebindDeviceExecutionInput): void;
|
|
183
179
|
export declare function assertAcquireShape(input: AcquireConnectionInput): void;
|
|
184
180
|
/** token 摘要必须是**规范形**(小写 sha256 hex):大小写混形在 VARBINARY/COLLATE "C" 下是两个键,
|
|
185
181
|
* 于是同一个明文 token 能被消费两次 —— 这是 §7-T5 ③「一次性 CAS」的直接跳过面。 */
|
|
@@ -268,73 +264,53 @@ export type ConsumeEnrollTokenResult =
|
|
|
268
264
|
| {
|
|
269
265
|
outcome: "pubkey_taken";
|
|
270
266
|
};
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
/**
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
/**
|
|
283
|
-
|
|
284
|
-
outcome: "idempotent";
|
|
285
|
-
row: DeviceSessionRow;
|
|
286
|
-
}
|
|
287
|
-
/** 根会话已绑**另一台**设备(或另一个 owner)⇒ `device.claim_conflict`。 */
|
|
288
|
-
| {
|
|
289
|
-
outcome: "conflict";
|
|
290
|
-
row: DeviceSessionRow;
|
|
267
|
+
/**
|
|
268
|
+
* device 车道的**首绑**(§4.3.2;认领之后的初始放置写,§3.3 转换表 place / bind 两行):根会话行上这一位住客的执行格
|
|
269
|
+
* absent → writer(device, D),或迁移回填的 writer(device, ∅) → writer(device, D)。绑定**住在会话行上**(唯一载体;
|
|
270
|
+
* 列与语句的属主 = `plugins/execution-placement-sql.ts`),本店只负责「设备行判 + 写格」同一事务(锁序:设备行 → 根 `session_meta`)。
|
|
271
|
+
*/
|
|
272
|
+
export interface PlaceDeviceExecutionInput {
|
|
273
|
+
/** 根会话(放置键;后代继承,不另绑)。 */
|
|
274
|
+
readonly root: string;
|
|
275
|
+
/** 意图那一读的住客(会话店执行席 `seat.read(root)` 交出的那一位)—— 写按住客谓词定址:住客换了 ⇒ `gone`,永不写到新住客身上。 */
|
|
276
|
+
readonly occupant: SessionFace;
|
|
277
|
+
readonly deviceId: string;
|
|
278
|
+
/** 验证过的复合身份;与设备行的 owner 在**同一事务**内比对,写进格的两属主列(绑定属主 = 设备属主)。 */
|
|
279
|
+
readonly owner: DeviceOwner;
|
|
291
280
|
}
|
|
292
|
-
/**
|
|
293
|
-
|
|
294
|
-
|
|
281
|
+
/**
|
|
282
|
+
* 首绑的判别式结果 —— 并发争抢**单赢家,无未定义态**。格的那几臂与判官同一张表(`DeviceBindOutcome`:`bound` / 同设备 `same`(幂等成功)/
|
|
283
|
+
* 异设备 `device_conflict` / 异车道 `tree_bound` / `mirror` / 住客不是判过的那一位或行不在 `gone`),外加设备行的两臂:
|
|
284
|
+
* 设备不存在**或**不是请求方的(反枚举同形,见文件头注)/ 已吊销。
|
|
285
|
+
*/
|
|
286
|
+
export type PlaceDeviceExecutionResult = DeviceBindOutcome | {
|
|
287
|
+
readonly outcome: "device_not_found";
|
|
295
288
|
} | {
|
|
296
|
-
outcome: "device_revoked";
|
|
289
|
+
readonly outcome: "device_revoked";
|
|
297
290
|
};
|
|
298
291
|
/**
|
|
299
|
-
* O4 显式换绑(2026-08-30 v2 稿 §2)。`owner` =
|
|
300
|
-
* explicit operator;operator
|
|
301
|
-
* 判别位在店里就消失(反枚举,文件头注)。`expectedRev` =
|
|
302
|
-
* 防两操作员并发换绑互踩)。
|
|
292
|
+
* O4 显式换绑(2026-08-30 v2 稿 §2;§3.3 转换表 rebind 行)。`occupant` = 换绑门那一读的住客;`owner` = 门判过的**格上**两属主列
|
|
293
|
+
* (HTTP 层已裁决:属主同域或 explicit operator;operator 代操作时传的也是格上的 owner,不是操作员自己)——店内所有谓词恒带它,
|
|
294
|
+
* 判别位在店里就消失(反枚举,文件头注)。`expectedRev` = 壳从执行放置读面拿到的前态(强制显式,防两操作员并发换绑互踩)。
|
|
303
295
|
*/
|
|
304
|
-
export interface
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
296
|
+
export interface RebindDeviceExecutionInput {
|
|
297
|
+
readonly root: string;
|
|
298
|
+
readonly occupant: SessionFace;
|
|
299
|
+
readonly owner: DeviceOwner;
|
|
300
|
+
readonly expectedRev: number;
|
|
301
|
+
readonly targetDeviceId: string;
|
|
309
302
|
}
|
|
310
303
|
/**
|
|
311
|
-
* O4 换绑的判别式结果(门序 = v2 稿 §2
|
|
312
|
-
*
|
|
304
|
+
* O4 换绑的判别式结果(门序 = v2 稿 §2 + 读写序律:目标设备在场 → 锁根行读认领 → 幂等短路 → 前态 CAS → 审计)。格的那几臂与判官同一张表
|
|
305
|
+
* (`DeviceRebindOutcome`:`rebound` 带被换下的那台 / 真幂等 `idempotent` / 前态输 `rev_conflict` 携当前格 / `gone` = 行不在、住客换了、不是 writer(device, D)、
|
|
306
|
+
* 或绑定属主不是判过的那一位 —— 反枚举同形),外加:目标设备不在 / 不是该 owner 的 / **已吊销**(三臂同折 404;吊销不单列 = 判别位在店里就消失);
|
|
307
|
+
* 写事务内锁根行后读到认领 `active_run`(SQL 后端;读写序律只在 SQL 后端立 —— 内存参照实现没有认领表,答不出这一臂,内存走廊的认领判据是路由的早拒)。
|
|
313
308
|
*/
|
|
314
|
-
export type
|
|
315
|
-
|
|
316
|
-
{
|
|
317
|
-
outcome: "
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
/** 真幂等:`toDeviceId` ≡ 当前绑定 ∧ `expectedRev` ≡ 当前 rev ⇒ 回显不加 rev、不写审计。 */
|
|
321
|
-
| {
|
|
322
|
-
outcome: "idempotent";
|
|
323
|
-
row: DeviceSessionRow;
|
|
324
|
-
}
|
|
325
|
-
/** 前态输(rev 不符,含「toDeviceId 同但 rev 错」——前态错就是错)⇒ 携当前行供壳一跳重定位。 */
|
|
326
|
-
| {
|
|
327
|
-
outcome: "rev_conflict";
|
|
328
|
-
row: DeviceSessionRow;
|
|
329
|
-
}
|
|
330
|
-
/** 绑定行不在**或**不是该 owner 的 —— 反枚举同形(HTTP 层折 404 同串)。 */
|
|
331
|
-
| {
|
|
332
|
-
outcome: "binding_not_found";
|
|
333
|
-
}
|
|
334
|
-
/** 目标设备不在 / 不是该 owner 的 / **已吊销** —— v2 稿 §2 步 2:三臂同折 404(设备 id 也是
|
|
335
|
-
* 不可枚举面);吊销不单列 = 判别位在店里就消失,消费层想泄也泄不出来。 */
|
|
336
|
-
| {
|
|
337
|
-
outcome: "device_not_found";
|
|
309
|
+
export type RebindDeviceExecutionResult = DeviceRebindOutcome | {
|
|
310
|
+
readonly outcome: "device_not_found";
|
|
311
|
+
} | {
|
|
312
|
+
readonly outcome: "active_run";
|
|
313
|
+
readonly activeTaskId: string;
|
|
338
314
|
};
|
|
339
315
|
export interface RevokeDeviceInput {
|
|
340
316
|
deviceId: string;
|
|
@@ -415,14 +391,10 @@ export interface DeviceStore {
|
|
|
415
391
|
/** 世代谓词命中 = true;0 行 = 已失权。 */
|
|
416
392
|
heartbeatConnection(input: HeartbeatConnectionInput): Promise<boolean>;
|
|
417
393
|
releaseConnection(deviceId: string, generation: number): Promise<boolean>;
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
getSessionBinding(rootSessionId: string): Promise<DeviceSessionRow | null>;
|
|
423
|
-
/** purge coordinator 座(§6 注②:core 的会话删除是**逐 store 显式调用**,不是 DB 自动扫;
|
|
424
|
-
* 只建表不接 purge = 删会话后绑定残留 ⇒ sessionId 重用致旧设备粘连/claim conflict/隐私残留)。 */
|
|
425
|
-
deleteByRootSession(rootSessionId: string): Promise<number>;
|
|
394
|
+
/** 首绑(认领之后的初始放置写):设备行判(active ∧ 属主)+ 写格同一事务,按住客谓词定址。 */
|
|
395
|
+
placeDeviceExecution(input: PlaceDeviceExecutionInput): Promise<PlaceDeviceExecutionResult>;
|
|
396
|
+
/** O4 显式换绑(v2 稿 §2 步 2/3/5):目标设备门 + 写事务内锁根行读认领 + 前态 CAS + `session_rebound` 审计行同一事务。 */
|
|
397
|
+
rebindDeviceExecution(input: RebindDeviceExecutionInput): Promise<RebindDeviceExecutionResult>;
|
|
426
398
|
appendAudit(input: AppendAuditInput): Promise<void>;
|
|
427
399
|
listAudit(filter?: ListAuditFilter): Promise<DeviceAuditRow[]>;
|
|
428
400
|
}
|
|
@@ -432,15 +404,19 @@ declare function cloneOwner(o: DeviceOwner): DeviceOwner;
|
|
|
432
404
|
* 语义 oracle。**单线程 JS 的原子性**替代 SQL 事务:每个方法体内没有 `await`(除了返回值),所以
|
|
433
405
|
* 「读-判-写」在事件循环上不可分割 —— 与 SQL 侧的单事务 CAS 语义等价,这也是为什么并发格
|
|
434
406
|
* (两个并发消费同一 token)在这一形上必须给出与真库**同一个**赢家/输家分布。
|
|
407
|
+
*
|
|
408
|
+
* 绑定不在本店:它是会话行上的执行格。构造**必收**测试走廊的会话行 {@link InMemoryExecutionPlacementSeat}(同为参照实现,生产零引用)——
|
|
409
|
+
* 首绑 / 换绑在它上面做(判官与 SQL 语句模块同一组),读者经同一只席的 `read(root)` 读。
|
|
435
410
|
*/
|
|
436
411
|
export declare class InMemoryDeviceStore implements DeviceStore {
|
|
437
412
|
private readonly devices;
|
|
438
|
-
private readonly sessions;
|
|
439
413
|
private readonly tokens;
|
|
440
414
|
private readonly audit;
|
|
441
415
|
private auditSeq;
|
|
442
416
|
private readonly now;
|
|
443
|
-
|
|
417
|
+
private readonly seat;
|
|
418
|
+
constructor(opts: {
|
|
419
|
+
seat: InMemoryExecutionPlacementSeat;
|
|
444
420
|
now?: () => number;
|
|
445
421
|
});
|
|
446
422
|
issueEnrollToken(input: IssueEnrollTokenInput): Promise<DeviceEnrollTokenRow>;
|
|
@@ -454,17 +430,14 @@ export declare class InMemoryDeviceStore implements DeviceStore {
|
|
|
454
430
|
acquireConnection(input: AcquireConnectionInput): Promise<AcquireConnectionResult>;
|
|
455
431
|
heartbeatConnection(input: HeartbeatConnectionInput): Promise<boolean>;
|
|
456
432
|
releaseConnection(deviceId: string, generation: number): Promise<boolean>;
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
getSessionBinding(rootSessionId: string): Promise<DeviceSessionRow | null>;
|
|
460
|
-
deleteByRootSession(rootSessionId: string): Promise<number>;
|
|
433
|
+
placeDeviceExecution(input: PlaceDeviceExecutionInput): Promise<PlaceDeviceExecutionResult>;
|
|
434
|
+
rebindDeviceExecution(input: RebindDeviceExecutionInput): Promise<RebindDeviceExecutionResult>;
|
|
461
435
|
appendAudit(input: AppendAuditInput): Promise<void>;
|
|
462
436
|
listAudit(filter?: ListAuditFilter): Promise<DeviceAuditRow[]>;
|
|
463
437
|
private isOnline;
|
|
464
438
|
private pushAudit;
|
|
465
439
|
/** 返回**拷贝**:调用方拿到的行改了也不能污染店内状态(SQL 侧天然如此,InMemory 必须显式做)。 */
|
|
466
440
|
private snapshotDevice;
|
|
467
|
-
private snapshotSession;
|
|
468
441
|
}
|
|
469
442
|
export { sameOwner as sameDeviceOwner, cloneOwner as cloneDeviceOwner };
|
|
470
443
|
//# sourceMappingURL=device-store.d.ts.map
|
package/dist/device-store.js
CHANGED
|
@@ -123,9 +123,14 @@ export function assertRevokeShape(input) {
|
|
|
123
123
|
assertBoundedText("revokedBy", input.revokedBy, DEVICE_TEXT_LIMITS.actor);
|
|
124
124
|
assertBoundedText("revokeReason", input.reason ?? "", DEVICE_TEXT_LIMITS.revokeReason);
|
|
125
125
|
}
|
|
126
|
+
export function assertPlaceDeviceShape(input) {
|
|
127
|
+
assertRootSessionIdShape(input.root);
|
|
128
|
+
assertDeviceIdShape(input.deviceId);
|
|
129
|
+
assertDeviceOwnerShape(input.owner);
|
|
130
|
+
}
|
|
126
131
|
export function assertRebindShape(input) {
|
|
127
|
-
assertRootSessionIdShape(input.
|
|
128
|
-
assertDeviceIdShape(input.
|
|
132
|
+
assertRootSessionIdShape(input.root);
|
|
133
|
+
assertDeviceIdShape(input.targetDeviceId);
|
|
129
134
|
assertDeviceOwnerShape(input.owner);
|
|
130
135
|
if (!Number.isInteger(input.expectedRev) || input.expectedRev < 0) {
|
|
131
136
|
throw new Error(`device-store: expectedRev must be a non-negative integer (got ${input.expectedRev}) — it enters a byte-exact BIGINT equality predicate`);
|
|
@@ -194,13 +199,14 @@ function cloneOwner(o) {
|
|
|
194
199
|
}
|
|
195
200
|
export class InMemoryDeviceStore {
|
|
196
201
|
devices = new Map();
|
|
197
|
-
sessions = new Map();
|
|
198
202
|
tokens = new Map();
|
|
199
203
|
audit = [];
|
|
200
204
|
auditSeq = 0;
|
|
201
205
|
now;
|
|
206
|
+
seat;
|
|
202
207
|
constructor(opts) {
|
|
203
|
-
this.
|
|
208
|
+
this.seat = opts.seat;
|
|
209
|
+
this.now = opts.now ?? (() => Date.now());
|
|
204
210
|
}
|
|
205
211
|
async issueEnrollToken(input) {
|
|
206
212
|
assertIssueTokenShape(input);
|
|
@@ -361,57 +367,24 @@ export class InMemoryDeviceStore {
|
|
|
361
367
|
row.rev += 1;
|
|
362
368
|
return true;
|
|
363
369
|
}
|
|
364
|
-
async
|
|
365
|
-
|
|
366
|
-
assertDeviceIdShape(input.deviceId);
|
|
367
|
-
assertDeviceOwnerShape(input.owner);
|
|
370
|
+
async placeDeviceExecution(input) {
|
|
371
|
+
assertPlaceDeviceShape(input);
|
|
368
372
|
const device = this.devices.get(input.deviceId);
|
|
369
373
|
if (!device || !sameOwner(device.owner, input.owner))
|
|
370
374
|
return { outcome: "device_not_found" };
|
|
371
375
|
if (device.status !== "active")
|
|
372
376
|
return { outcome: "device_revoked" };
|
|
373
|
-
|
|
374
|
-
if (existing) {
|
|
375
|
-
const same = existing.deviceId === input.deviceId && sameOwner(existing.owner, input.owner);
|
|
376
|
-
return { outcome: same ? "idempotent" : "conflict", row: this.snapshotSession(existing) };
|
|
377
|
-
}
|
|
378
|
-
const row = {
|
|
379
|
-
rootSessionId: input.rootSessionId,
|
|
380
|
-
deviceId: input.deviceId,
|
|
381
|
-
owner: cloneOwner(input.owner),
|
|
382
|
-
boundAtMs: this.now(),
|
|
383
|
-
rev: 0,
|
|
384
|
-
};
|
|
385
|
-
this.sessions.set(row.rootSessionId, row);
|
|
386
|
-
return { outcome: "bound", row: this.snapshotSession(row) };
|
|
377
|
+
return this.seat.bindDevice(input.root, input.occupant, { id: input.deviceId, owner: cloneOwner(input.owner) }, new Date(this.now()).toISOString());
|
|
387
378
|
}
|
|
388
|
-
async
|
|
379
|
+
async rebindDeviceExecution(input) {
|
|
389
380
|
assertRebindShape(input);
|
|
390
|
-
const device = this.devices.get(input.
|
|
381
|
+
const device = this.devices.get(input.targetDeviceId);
|
|
391
382
|
if (!device || !sameOwner(device.owner, input.owner) || device.status !== "active")
|
|
392
383
|
return { outcome: "device_not_found" };
|
|
393
|
-
const
|
|
394
|
-
if (
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
return { outcome: "idempotent", row: this.snapshotSession(row) };
|
|
398
|
-
if (row.rev !== input.expectedRev)
|
|
399
|
-
return { outcome: "rev_conflict", row: this.snapshotSession(row) };
|
|
400
|
-
const from = row.deviceId;
|
|
401
|
-
row.deviceId = input.toDeviceId;
|
|
402
|
-
row.boundAtMs = this.now();
|
|
403
|
-
row.rev += 1;
|
|
404
|
-
this.pushAudit({ event: "session_rebound", deviceId: input.toDeviceId, owner: row.owner, detail: { from, to: input.toDeviceId, rev: row.rev } });
|
|
405
|
-
return { outcome: "rebound", row: this.snapshotSession(row) };
|
|
406
|
-
}
|
|
407
|
-
async getSessionBinding(rootSessionId) {
|
|
408
|
-
assertRootSessionIdShape(rootSessionId);
|
|
409
|
-
const row = this.sessions.get(rootSessionId);
|
|
410
|
-
return row ? this.snapshotSession(row) : null;
|
|
411
|
-
}
|
|
412
|
-
async deleteByRootSession(rootSessionId) {
|
|
413
|
-
assertRootSessionIdShape(rootSessionId);
|
|
414
|
-
return this.sessions.delete(rootSessionId) ? 1 : 0;
|
|
384
|
+
const out = this.seat.rebindDevice(input.root, input.occupant, cloneOwner(input.owner), input.expectedRev, input.targetDeviceId, new Date(this.now()).toISOString());
|
|
385
|
+
if (out.outcome === "rebound")
|
|
386
|
+
this.pushAudit({ event: "session_rebound", deviceId: input.targetDeviceId, owner: input.owner, detail: { from: out.from, to: input.targetDeviceId, rev: out.device.rev } });
|
|
387
|
+
return out;
|
|
415
388
|
}
|
|
416
389
|
async appendAudit(input) {
|
|
417
390
|
this.pushAudit(input);
|
|
@@ -440,9 +413,6 @@ export class InMemoryDeviceStore {
|
|
|
440
413
|
snapshotDevice(row) {
|
|
441
414
|
return { ...row, owner: cloneOwner(row.owner) };
|
|
442
415
|
}
|
|
443
|
-
snapshotSession(row) {
|
|
444
|
-
return { ...row, owner: cloneOwner(row.owner) };
|
|
445
|
-
}
|
|
446
416
|
}
|
|
447
417
|
export { sameOwner as sameDeviceOwner, cloneOwner as cloneDeviceOwner };
|
|
448
418
|
//# sourceMappingURL=device-store.js.map
|
package/dist/device-ws-hub.js
CHANGED
|
@@ -832,7 +832,8 @@ export function createDeviceWsHub(options) {
|
|
|
832
832
|
return { kind: "rejected", reject: rejection(DEVICE_DRAINING_CODE, "this device hub is closed for shutdown — the instruction was never dispatched (safe to retry once the device reconnects on a replacement replica)", DRAIN_RETRY_AFTER_SEC) };
|
|
833
833
|
if (draining)
|
|
834
834
|
return drainingRejectResult();
|
|
835
|
-
const
|
|
835
|
+
const placement = await enrollment.readPlacement(input.rootSessionId);
|
|
836
|
+
const admitted = await enrollment.admitSession({ rootSessionId: input.rootSessionId, placement, requester: input.requester });
|
|
836
837
|
if (!admitted.ok)
|
|
837
838
|
return { kind: "rejected", reject: admitted.reject };
|
|
838
839
|
if (abortedNow())
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
* 带外凭据(e2b / docker / k8s 车道本来就是多租户 fleet 的主形),与 LSP 那条「本机子进程」的形不同;多租户下起服说一句。
|
|
11
11
|
* · `BAKE_ENV_ALLOW`([ref] 残余,7.103.0)由 **bake-runner 进程**读(构建宿主守护进程:没有主体、没有租户 ⇒ 没有姿态列,
|
|
12
12
|
* 不进 {@link describeAllowlistPostures} 的姿态句)。它与服务侧四只旋钮同一只解析器、同一只「点名放行」谓词、同一条「原文按凭据类」律。
|
|
13
|
-
* · `channel` = 这张名单**交给谁、在谁的减法之上**(
|
|
13
|
+
* · `channel` = 这张名单**交给谁、在谁的减法之上**(闭集两词)。它只定拒句里「交到哪里」那半句与出路的主语,**不定拒不拒**:「不许点哪些名」对五只一律
|
|
14
|
+
* = 名单型旋钮名 ∪ 本服务自有凭据名(引擎此刻的声明:起服解析时判一次,声明增长时由换代声明对活配置里每只服务侧名单此刻交出去的名重判一次;判官 = 引擎
|
|
15
|
+
* `inheritEnvPolicyProblem`,与引擎拒嵌入方白名单同句),规则全文在解析器头注 ②。
|
|
14
16
|
* - `host-put-back`(`LSP_ENV_ALLOW` / `BAKE_ENV_ALLOW`)—— 剥后放回形:宿主子进程的 env 先经唯一组合(引擎扣掉本服务自有凭据 + 形状剥),
|
|
15
|
-
*
|
|
16
|
-
* (`inheritEnvPolicyProblem`,读起服声明;与引擎拒嵌入方白名单同句)。
|
|
17
|
+
* 名单点到的键再从本进程环境**原样**取回叠上去;点到本服务自有凭据名 = 把引擎刚扣下的那枚交回那只子进程。
|
|
17
18
|
* - `sandbox-grant`(三只沙箱名单)—— 沙箱 env 的唯一来源(沙箱不从本进程继承任何东西),部署方显式交出的带外凭据([ref] 照转发);
|
|
18
|
-
*
|
|
19
|
+
* 点到本服务自有凭据名 = 把它装进模型读得到的沙箱 env。沙箱要凭据 ⇒ 部署方给沙箱另铸一把(名与值都不同于本服务的任何凭据)。
|
|
19
20
|
* 表是 `Record<旋钮, …>`:闭集加一只旋钮而不补行 = 编译红;行形随读它的进程定(服务进程 ⇒ 必须写姿态列)。
|
|
20
21
|
*
|
|
21
22
|
* 🔴 **姿态列只在这里写一次**([ref];7.101.0 合并复审 O9):凡要对人说「多租户下哪只旋钮忽略、哪只照转发」的句子,一律取
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 一条**跑过**才被切的命令,执行错误怎么造、切断那一刻输出往哪去的**唯一一条律**(七只 adapter —— host〔管道 / spool 两形〕/ adb / e2b / ssh / k8s /
|
|
3
|
+
* local-docker / device —— 同读这一只):
|
|
4
|
+
*
|
|
5
|
+
* 命令已经起跑、之后被切 —— 墙钟(`timeout`)、静默界(`liveness_no_output`)、调用方中止(`aborted`)、宿主侧输出回调失败(`callback_error`)—— 它在被切之前
|
|
6
|
+
* 写出的 stdout / stderr 是真实的工作成果,必须原样带在 `ExecutionError.partialStdout` / `partialStderr` 上(core 合同:参考行为是超时保留**全部**已捕获的输出,
|
|
7
|
+
* 只追加一句「超时了」;丢掉 600 s 的构建日志会逼模型盲重跑)。引擎只从这两个字段读输出拼工具结果,从 `message` 读不到 ——
|
|
8
|
+
* 缺席就报「(no output was produced before the cutoff)」,模型对着一个其实已写了进度的命令说「什么也没产出」。
|
|
9
|
+
*
|
|
10
|
+
* **切断即落定**:切断时本层手里还没交出的输出(远端 shell 腿 cwd 过滤器压着的 stderr 尾巴、host spool 还没泵的字节)只**记账**(尾窗 / detach tee),
|
|
11
|
+
* 随错误交回,不经调用方的输出回调**外发**。**落定先于构造,构造只记账**:构造结局会做事的腿(ssh / adb / k8s / host spool —— 冲刷压着的尾巴、泵 spool、
|
|
12
|
+
* 杀进程)的 `finish` 收一只构造结局的函数,先置落定,再构造、收尾、解决 —— 构造期间不调调用方的代码,重入的 detach / abort / close 读到的都是「已落定」。
|
|
13
|
+
* 正常结束同一顺序:压着的尾巴先记账、解决,**之后**才交给回调(那是流本身的结尾,不是切断)—— 回调里发生什么(重入、抛错)都改不了、也挂不住结局。
|
|
14
|
+
* 构造只读尾窗 / SDK 句柄字段的腿(host 管道 / local-docker / e2b)造错误即读,没有可重入的东西;device 的错误在投递结算之后才造。
|
|
15
|
+
*
|
|
16
|
+
* 与 `exec-bounds.ts` 的分工:那一只定「什么界在何时切、切断报哪个码、哪句话、几秒」(`buildLivenessCut` 等);这一只定「切断的错误带什么」。静默切断的
|
|
17
|
+
* 数据(`buildLivenessCut` 的返回)直接就是这里的 {@link ExecCut};墙钟与中止切断各 adapter 自己说句子(它们的成因词各车道不同),错误一律经 {@link createCutError} 造;
|
|
18
|
+
* 码是数据的腿(device:码由对端说,经映射表落到本侧)经 {@link createExecFailure} 按同一判别造。
|
|
19
|
+
*
|
|
20
|
+
* 输出的口径 = 同一条命令正常收口时 `exec` 会交出的那一份,切断不另设一道界、不二次切片:自带有界滚动尾窗(`RollingTailBuffer`)的腿读尾窗的当前文本,被丢掉的字节照旧附
|
|
21
|
+
* `markTruncated` 的记号({@link buildCapturedOutput});收口交出的是 SDK 整串的腿(e2b)读 SDK 句柄自己的记录;device 读它自己收齐的两路串。远端 shell 腿(ssh / adb / k8s)
|
|
22
|
+
* 的 stderr 在读之前先把 cwd 过滤器压着的尾巴记进账,与正常收口同一步。`message` 只陈述事实(哪一界、多少毫秒),不再夹输出。
|
|
23
|
+
*
|
|
24
|
+
* 不在本律里:命令**没起跑**就失败的码(`spawn_error` / `shell_unavailable` / 起跑前的 `aborted` / device 投递门之前的拒)按定义没有输出;结果未知
|
|
25
|
+
* (`transport_lost` / `outcome_unknown`)与未分类(`unknown`)的码引擎不读它的 partial —— 判别只有 {@link isRanThenCutCode} 一处。
|
|
26
|
+
*/
|
|
27
|
+
import { ExecutionError, type ExecutionErrorCode, type RollingTailBuffer } from "@sema-agent/core";
|
|
28
|
+
/** 命令已起跑、随后被切的四个码(core `ExecutionError` 注:`partialStdout` / `partialStderr` 为这四个码而设)。 */
|
|
29
|
+
export type RanThenCutCode = Extract<ExecutionErrorCode, "timeout" | "liveness_no_output" | "aborted" | "callback_error">;
|
|
30
|
+
/**
|
|
31
|
+
* 一次切断的数据:码 + 句。`noOutputSec` 只属静默切断(静默窗口的整秒数,core `ExecutionError` 第五构造参)—— 与 `exec-bounds.ts` 的
|
|
32
|
+
* `buildLivenessCut` 返回值同形,可直接传入。
|
|
33
|
+
*/
|
|
34
|
+
export type ExecCut = {
|
|
35
|
+
readonly code: Exclude<RanThenCutCode, "liveness_no_output">;
|
|
36
|
+
readonly message: string;
|
|
37
|
+
} | {
|
|
38
|
+
readonly code: "liveness_no_output";
|
|
39
|
+
readonly message: string;
|
|
40
|
+
readonly noOutputSec?: number;
|
|
41
|
+
};
|
|
42
|
+
/** 切断那一刻命令已写出的输出(纯数据;两路都是字符串,没写 = 空串)。 */
|
|
43
|
+
export interface CapturedOutput {
|
|
44
|
+
readonly stdout: string;
|
|
45
|
+
readonly stderr: string;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 切断那一刻两路滚动尾窗里的内容 = 该命令正常收口时 `exec` 交出的那一份(滚出窗外的字节照旧附 {@link markTruncated} 的记号)。
|
|
49
|
+
* `stdout` 缺席 = 这一次往返把 stdout 整份留作**数据载荷**(字节精确的文件读取:adb / local-docker 的 `binary`、k8s 的非 `boundOutput`)—— 载荷不是
|
|
50
|
+
* 命令输出,被切的数据读取没有「已写出的输出」可交给读者,stdout 记空串;stderr 恒是命令输出。
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildCapturedOutput(stdout: RollingTailBuffer | undefined, stderr: RollingTailBuffer): CapturedOutput;
|
|
53
|
+
/** 一条起跑后被切的命令的执行错误 —— 唯一造法(见文件头注):码 / 句取自 `cut`,输出取自 `captured`(逐字,不截)。 */
|
|
54
|
+
export declare function createCutError(cut: ExecCut, captured: CapturedOutput): ExecutionError;
|
|
55
|
+
/**
|
|
56
|
+
* 码是**数据**时的执行错误(device:对端说的词经映射表落到本侧,这一刻才知道是哪个码)—— 同一条律:命令起跑过(`ran` = 它已写出的输出)且码是起跑后被切的
|
|
57
|
+
* 四个之一 ⇒ 经 {@link createCutError} 带输出;其余(没起跑 = `ran` 缺席 / 结果未知 / 未分类)按律不带。码在调用处就是字面量的腿直接用 {@link createCutError}。
|
|
58
|
+
*/
|
|
59
|
+
export declare function createExecFailure(code: ExecutionErrorCode, message: string, ran?: CapturedOutput): ExecutionError;
|
|
60
|
+
//# sourceMappingURL=exec-cut.d.ts.map
|
package/dist/exec-cut.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ExecutionError, markTruncated } from "@sema-agent/core";
|
|
2
|
+
function isRanThenCutCode(code) {
|
|
3
|
+
switch (code) {
|
|
4
|
+
case "timeout":
|
|
5
|
+
case "liveness_no_output":
|
|
6
|
+
case "aborted":
|
|
7
|
+
case "callback_error":
|
|
8
|
+
return true;
|
|
9
|
+
case "shell_unavailable":
|
|
10
|
+
case "spawn_error":
|
|
11
|
+
case "transport_lost":
|
|
12
|
+
case "suspended":
|
|
13
|
+
case "auth_failed":
|
|
14
|
+
case "outcome_unknown":
|
|
15
|
+
case "target_unavailable":
|
|
16
|
+
case "unknown":
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function buildCapturedOutput(stdout, stderr) {
|
|
21
|
+
const err = stderr.result();
|
|
22
|
+
const out = stdout?.result();
|
|
23
|
+
return {
|
|
24
|
+
stdout: out === undefined ? "" : markTruncated(out.text, out.droppedBytes),
|
|
25
|
+
stderr: markTruncated(err.text, err.droppedBytes),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function createCutError(cut, captured) {
|
|
29
|
+
return new ExecutionError(cut.code, cut.message, undefined, { stdout: captured.stdout, stderr: captured.stderr }, cut.code === "liveness_no_output" ? cut.noOutputSec : undefined);
|
|
30
|
+
}
|
|
31
|
+
export function createExecFailure(code, message, ran) {
|
|
32
|
+
if (ran !== undefined && isRanThenCutCode(code))
|
|
33
|
+
return createCutError({ code, message }, ran);
|
|
34
|
+
return new ExecutionError(code, message);
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=exec-cut.js.map
|