@sema-agent/server 7.144.0 → 7.146.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 +621 -0
- package/README.md +3 -0
- package/README.zh-CN.md +1 -0
- package/USAGE.md +233 -54
- package/deploy/facts/CHANGES.json +25 -0
- package/deploy/facts/README.md +57 -0
- package/deploy/facts/lanes.json +54 -0
- package/deploy/facts/lanes.schema.json +57 -0
- package/deploy/facts/sandbox-rbac.json +113 -0
- package/deploy/facts/sandbox-rbac.schema.json +74 -0
- package/deploy/facts/sealed-key.json +9 -0
- package/deploy/facts/sealed-key.schema.json +52 -0
- package/deploy/sema-up/chart/templates/_helpers.tpl +19 -0
- package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +47 -7
- package/deploy/sema-up/chart/templates/server-v4pro.yaml +4 -0
- package/deploy/sema-up/chart/templates/server.yaml +4 -0
- package/deploy/sema-up/chart/values.yaml +7 -0
- package/deploy/sema-up/stack/sema-stack-cluster.yaml +30 -14
- package/dist/adoption/import-limits.d.ts +6 -0
- package/dist/adoption/import-limits.js +7 -0
- package/dist/adoption/import.d.ts +62 -0
- package/dist/adoption/import.js +107 -0
- package/dist/adoption/wire.d.ts +52 -0
- package/dist/adoption/wire.js +9 -0
- package/dist/approval-ask-machine.d.ts +2 -2
- package/dist/approval-card.d.ts +3 -12
- package/dist/approval-card.js +0 -4
- package/dist/approval-gate-currency.d.ts +1 -1
- package/dist/approval-gate-currency.js +1 -1
- package/dist/approval-reconciler.d.ts +1 -1
- package/dist/audit.d.ts +2 -21
- package/dist/audit.js +0 -9
- package/dist/boot/deployment-mods.d.ts +11 -1
- package/dist/boot/deployment-mods.js +15 -2
- package/dist/boot/device-lane.js +2 -0
- package/dist/boot/engine-lease.d.ts +193 -21
- package/dist/boot/engine-lease.js +146 -20
- package/dist/boot/execution-env.d.ts +4 -0
- package/dist/boot/execution-env.js +12 -0
- package/dist/boot/exit-boundary.d.ts +50 -0
- package/dist/boot/exit-boundary.js +32 -0
- package/dist/boot/exit-last.d.ts +20 -4
- package/dist/boot/exit-last.js +21 -4
- package/dist/boot/governance-seams.js +1 -0
- package/dist/boot/memory-consolidation.d.ts +29 -17
- package/dist/boot/memory-consolidation.js +26 -15
- package/dist/boot/reapers.d.ts +12 -4
- package/dist/boot/reapers.js +39 -15
- package/dist/boot/resolve-spec.d.ts +2 -0
- package/dist/boot/resolve-spec.js +38 -15
- package/dist/boot/runner-deps.js +1 -1
- package/dist/boot/session-faces.d.ts +1 -1
- package/dist/boot/session-faces.js +6 -4
- package/dist/boot/shutdown.js +27 -9
- package/dist/boot/stage-01-config.js +1 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -0
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -0
- package/dist/boot/stage-05-execution-env.d.ts +3 -0
- package/dist/boot/stage-05-execution-env.js +3 -3
- package/dist/boot/stage-06-runners.d.ts +3 -0
- package/dist/boot/stage-06-runners.js +11 -10
- package/dist/boot/stage-07-capability-layer.d.ts +3 -0
- package/dist/boot/stage-07-capability-layer.js +7 -2
- package/dist/boot/stage-08-reapers.d.ts +3 -0
- package/dist/boot/stage-08-reapers.js +3 -3
- package/dist/boot/stage-09-leader.d.ts +4 -1
- package/dist/boot/stage-10-http-server.d.ts +4 -1
- package/dist/boot/stage-10-http-server.js +4 -3
- package/dist/boot/stores.d.ts +1 -0
- package/dist/boot/stores.js +35 -19
- package/dist/boot/workflow-orchestration.d.ts +1 -1
- package/dist/boot/workflow-orchestration.js +2 -1
- package/dist/capabilities/composite-members.d.ts +3 -1
- package/dist/capabilities/composite-members.js +3 -1
- package/dist/capabilities/scenarios.d.ts +2 -2
- package/dist/capability-facts.d.ts +18 -1
- package/dist/capability-facts.js +25 -7
- package/dist/checkpoint-ctx-seal-m28.d.ts +1 -1
- package/dist/config-catalog.js +13 -4
- package/dist/config-d-migration.d.ts +3 -2
- package/dist/config-provider.d.ts +2 -2
- package/dist/config-types.d.ts +43 -4
- package/dist/config.d.ts +6 -1
- package/dist/config.js +67 -11
- package/dist/deleted-session-ids.d.ts +19 -0
- package/dist/deleted-session-ids.js +26 -0
- package/dist/deploy-facts.d.ts +155 -0
- package/dist/deploy-facts.js +94 -0
- package/dist/device-ws-hub.d.ts +48 -3
- package/dist/device-ws-hub.js +48 -2
- package/dist/error-code-family.d.ts +35 -0
- package/dist/error-code-family.js +26 -0
- package/dist/fleet/drain-entry.d.ts +39 -3
- package/dist/fleet/drain-entry.js +6 -0
- package/dist/fleet/fleet-bus.d.ts +15 -4
- package/dist/fleet/fleet-bus.js +17 -3
- package/dist/hooks/branch-transcript.d.ts +1 -1
- package/dist/hooks/branch-transcript.js +1 -0
- package/dist/hooks/classic-stations.d.ts +25 -8
- package/dist/hooks/classic-stations.js +29 -3
- package/dist/hooks/hook-runner.d.ts +33 -16
- package/dist/hooks/hook-runner.js +166 -73
- package/dist/hooks/hook-source.d.ts +14 -2
- package/dist/hooks/hook-source.js +8 -0
- package/dist/http/active-run-conflict.d.ts +1 -1
- package/dist/http/active-run-conflict.js +1 -1
- package/dist/http/admission.js +13 -2
- package/dist/http/checkpoint-ctx.d.ts +60 -71
- package/dist/http/checkpoint-ctx.js +35 -40
- package/dist/http/dispatch.js +18 -2
- package/dist/http/durable-run-leg.d.ts +5 -0
- package/dist/http/durable-run-leg.js +8 -6
- package/dist/http/execution-context.d.ts +4 -0
- package/dist/http/execution-context.js +9 -0
- package/dist/http/health-self-report.d.ts +6 -2
- package/dist/http/health-self-report.js +3 -2
- package/dist/http/memory-compliance-failure-reply.d.ts +1 -1
- package/dist/http/memory-compliance-failure-reply.js +2 -15
- package/dist/http/memory-control-plane-corrupt-reply.d.ts +25 -0
- package/dist/http/memory-control-plane-corrupt-reply.js +19 -0
- package/dist/http/principal-gate.d.ts +35 -12
- package/dist/http/principal-gate.js +16 -12
- package/dist/http/request-guards.d.ts +1 -1
- package/dist/http/request-guards.js +5 -5
- package/dist/http/resume-legs.d.ts +22 -0
- package/dist/http/resume-legs.js +31 -20
- package/dist/http/route-ctx.d.ts +26 -10
- package/dist/http/route-table.js +2 -0
- package/dist/http/routes/adoption.d.ts +11 -0
- package/dist/http/routes/adoption.js +80 -6
- package/dist/http/routes/agents-roster.js +1 -0
- package/dist/http/routes/approvals-assistant.d.ts +20 -1
- package/dist/http/routes/approvals-assistant.js +29 -7
- package/dist/http/routes/background.js +1 -0
- package/dist/http/routes/capabilities.js +4 -1
- package/dist/http/routes/diagnostics.d.ts +9 -14
- package/dist/http/routes/diagnostics.js +10 -20
- package/dist/http/routes/engine.d.ts +31 -0
- package/dist/http/routes/engine.js +81 -0
- package/dist/http/routes/memory-bundle.js +3 -0
- package/dist/http/routes/memory-consolidation.js +3 -5
- package/dist/http/routes/memory-origin.d.ts +1 -1
- package/dist/http/routes/memory-origin.js +2 -4
- package/dist/http/routes/memory-policy.js +5 -1
- package/dist/http/routes/observability.js +3 -6
- package/dist/http/routes/rules.d.ts +1 -1
- package/dist/http/routes/rules.js +5 -2
- package/dist/http/routes/runs.js +7 -3
- package/dist/http/routes/session-sync.js +24 -25
- package/dist/http/routes/sessions-list.d.ts +1 -1
- package/dist/http/routes/sessions.js +4 -0
- package/dist/http/routes/tasks.js +35 -14
- package/dist/http/routes/trace-usage.js +1 -1
- package/dist/http/run-concurrency-cap.d.ts +86 -0
- package/dist/http/run-concurrency-cap.js +54 -0
- package/dist/http/run-meta.d.ts +14 -7
- package/dist/http/run-meta.js +5 -2
- package/dist/http/server.d.ts +27 -16
- package/dist/http/server.js +21 -3
- package/dist/http/stored-body-replay.d.ts +9 -6
- package/dist/http/stored-body-replay.js +19 -5
- package/dist/http/submit-ctx.d.ts +12 -0
- package/dist/http/submit-ctx.js +23 -0
- package/dist/http/wire-types.d.ts +8 -3
- package/dist/json-body-limit.d.ts +8 -0
- package/dist/json-body-limit.js +2 -0
- package/dist/leader/diffout.d.ts +1 -1
- package/dist/local-data-root.d.ts +2 -2
- package/dist/memory-operator-faces.d.ts +9 -4
- package/dist/memory-scope-stores.d.ts +9 -7
- package/dist/memory-scope-stores.js +3 -14
- package/dist/memory-scope.d.ts +36 -0
- package/dist/memory-scope.js +32 -1
- package/dist/net-address.d.ts +53 -0
- package/dist/net-address.js +111 -0
- package/dist/observability/fail-open.d.ts +28 -12
- package/dist/observability/fail-open.js +28 -12
- package/dist/orchestration/workflow-notify-journal.js +2 -3
- package/dist/org-delivery-gate.js +1 -1
- package/dist/peer-directory.d.ts +6 -12
- package/dist/peer-directory.js +5 -1
- package/dist/plugins/approval-ask-store-file.d.ts +16 -2
- package/dist/plugins/approval-ask-store-file.js +21 -1
- package/dist/plugins/approval-ask-store-memory.d.ts +8 -2
- package/dist/plugins/approval-ask-store-memory.js +11 -8
- package/dist/plugins/caching-session-store.d.ts +6 -1
- package/dist/plugins/caching-session-store.js +6 -0
- package/dist/plugins/checkpoint-store-face.d.ts +426 -0
- package/dist/plugins/checkpoint-store-face.js +152 -0
- package/dist/plugins/file-run-store.d.ts +13 -7
- package/dist/plugins/file-run-store.js +12 -13
- package/dist/plugins/fork-routing-session-store.d.ts +6 -2
- package/dist/plugins/fork-routing-session-store.js +2 -2
- package/dist/plugins/imported-layer-root-retirement.d.ts +10 -8
- package/dist/plugins/local-checkpoint-store.d.ts +16 -5
- package/dist/plugins/local-checkpoint-store.js +25 -6
- package/dist/plugins/local-session-store.d.ts +80 -21
- package/dist/plugins/local-session-store.js +79 -22
- package/dist/plugins/memory-engine-pg.d.ts +29 -6
- package/dist/plugins/memory-engine-pg.js +96 -214
- package/dist/plugins/memory-engine-sql-apply.d.ts +121 -0
- package/dist/plugins/memory-engine-sql-apply.js +358 -0
- package/dist/plugins/memory-engine-tidb.d.ts +35 -9
- package/dist/plugins/memory-engine-tidb.js +97 -227
- package/dist/plugins/memory-key-guards.d.ts +1 -1
- package/dist/plugins/memory-origin-law.d.ts +3 -3
- package/dist/plugins/memory-run-store.d.ts +2 -0
- package/dist/plugins/memory-run-store.js +6 -0
- package/dist/plugins/one-time-migrations.d.ts +32 -56
- package/dist/plugins/one-time-migrations.js +27 -119
- package/dist/plugins/permission-rule-store-file.d.ts +17 -3
- package/dist/plugins/permission-rule-store-file.js +8 -1
- package/dist/plugins/pg-pool.js +1 -1
- package/dist/plugins/pg-session-storage.d.ts +17 -4
- package/dist/plugins/pg-session-storage.js +8 -4
- package/dist/plugins/run-store-sql.d.ts +4 -0
- package/dist/plugins/run-store-sql.js +5 -2
- package/dist/plugins/schema-ensure-legs.js +2 -2
- package/dist/plugins/session-fork.d.ts +31 -9
- package/dist/plugins/session-fork.js +3 -2
- package/dist/plugins/session-placement.d.ts +4 -2
- package/dist/plugins/session-store.d.ts +1 -1
- package/dist/plugins/sql-json-column.d.ts +5 -1
- package/dist/plugins/store-backend.d.ts +11 -8
- package/dist/plugins/store-backend.js +8 -7
- package/dist/plugins/store-contracts.d.ts +1 -11
- package/dist/plugins/store-contracts.js +0 -9
- package/dist/plugins/store-sweep.d.ts +63 -0
- package/dist/plugins/store-sweep.js +48 -0
- package/dist/plugins/tidb-pool.js +1 -1
- package/dist/plugins/tidb-session-store.d.ts +16 -3
- package/dist/plugins/tidb-session-store.js +8 -4
- package/dist/prompt-screen.d.ts +18 -0
- package/dist/prompt-screen.js +5 -0
- package/dist/rules-consent.d.ts +56 -51
- package/dist/rules-consent.js +86 -14
- package/dist/run-acceptance.d.ts +40 -10
- package/dist/run-acceptance.js +38 -5
- package/dist/run-cancel-context.d.ts +4 -1
- package/dist/run-cancel-context.js +2 -1
- package/dist/runs.js +2 -2
- package/dist/sandbox-egress-policy.js +6 -11
- package/dist/sandbox-rbac-rules.d.ts +88 -0
- package/dist/sandbox-rbac-rules.js +80 -0
- package/dist/sealed-key-layout.d.ts +17 -0
- package/dist/sealed-key-layout.js +4 -0
- package/dist/sealed-key.js +5 -5
- package/dist/security.d.ts +48 -9
- package/dist/security.js +9 -2
- package/dist/session-agent.d.ts +39 -0
- package/dist/session-agent.js +16 -0
- package/dist/session-error-wire.d.ts +4 -4
- package/dist/session-notify-door.d.ts +5 -3
- package/dist/session-resident-background.d.ts +57 -0
- package/dist/session-resident-background.js +20 -0
- package/dist/session-sync-kernel.d.ts +53 -14
- package/dist/session-sync-kernel.js +70 -1
- package/dist/session-sync.d.ts +5 -3
- package/dist/session-workspace.d.ts +1 -0
- package/dist/session-workspace.js +1 -0
- package/dist/sighup-idle.d.ts +9 -7
- package/dist/sighup-idle.js +4 -5
- package/dist/spec-fields.d.ts +16 -0
- package/dist/spec-fields.js +7 -0
- package/dist/stored-request-env-credentials-m38.d.ts +3 -0
- package/dist/stored-request-env-credentials-m38.js +8 -0
- package/dist/stored-request-prompt-profile-m30.d.ts +1 -1
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.d.ts +33 -429
- package/dist/{plugins → stores-sql}/checkpoint-store-sql.js +70 -209
- package/dist/{plugins → stores-sql}/mailbox-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/mailbox-store-sql.js +4 -4
- package/dist/{plugins → stores-sql}/roster-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/roster-store-sql.js +1 -1
- package/dist/{plugins → stores-sql}/tool-result-store-sql.d.ts +2 -2
- package/dist/{plugins → stores-sql}/tool-result-store-sql.js +6 -6
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.d.ts +7 -12
- package/dist/{plugins → stores-sql}/workflow-journal-store-sql.js +3 -8
- package/dist/task-settings.d.ts +59 -4
- package/dist/task-settings.js +50 -4
- package/dist/tool-approval.d.ts +2 -2
- package/dist/trace/core-keyset-guard.d.ts +8 -7
- package/dist/trace/engine-notice-wire.d.ts +1 -1
- package/dist/trace/engine-notice-wire.js +2 -0
- package/dist/trace/exit-seat.d.ts +6 -0
- package/dist/trace/exit-seat.js +1 -0
- package/dist/trace/model-segment.d.ts +3 -2
- package/dist/trace/model-segment.js +16 -8
- package/dist/trace/project.js +9 -0
- package/dist/trace/redact.d.ts +79 -4
- package/dist/trace/redact.js +523 -123
- package/dist/trace/self-minted-wire.d.ts +391 -1
- 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/usage-analytics.d.ts +4 -0
- package/package.json +12 -4
- package/scripts/drain-check-local.mjs +8 -29
- package/scripts/drain-check.mysql.sql +3 -24
- package/scripts/drain-check.pg.sql +3 -24
- package/skills/update-config.md +1 -1
- package/wire-changes/server@7.145.0.json +146 -0
- package/wire-changes/server@7.146.0.json +3221 -0
- package/dist/approval-batch-census.d.ts +0 -27
- package/dist/approval-batch-census.js +0 -27
package/dist/task-settings.d.ts
CHANGED
|
@@ -195,6 +195,13 @@ export declare function skillListingBudgetFractionOk(v: unknown): v is number;
|
|
|
195
195
|
/** {@link skillListingBudgetFractionOk} 的孪生(`int().positive()`;`isSafeInteger` 而不是 `isInteger` 的
|
|
196
196
|
* 理由见那里)。 */
|
|
197
197
|
export declare function skillListingMaxDescOk(v: unknown): v is number;
|
|
198
|
+
/**
|
|
199
|
+
* `settings.autoCompactEnabled`(CC 2.1.309 settings 同名键,`cli309.js:252692` 的 settings 声明:布尔,「上下文装满时自动压缩对话」)的值域判据 —— **只收布尔**。
|
|
200
|
+
* 与上面两只谓词同姿势:FRESH 提交面的 400 门(`http/admission.ts`)问「合不合法」,RESUME 宽容层({@link parseTaskSettings})问「收不收下」,
|
|
201
|
+
* 这两句话是同一个问题的正反面,只写在这一处(`"false"` / `0` / `null` 这类假值形都不是布尔:不读成「开」也不读成「关」)。
|
|
202
|
+
* server 侧零加工:`true` / `false` 逐字交给引擎的自动压缩座 `TaskSpec.compaction.autoCompact`(`spec-fields.ts` 的 `compactionSpecFragment`),缺席 ⇒ 整键不写,默认值的属主是引擎。
|
|
203
|
+
*/
|
|
204
|
+
export declare function autoCompactEnabledOk(v: unknown): v is boolean;
|
|
198
205
|
/** The validated, service-trusted subset of `SemaSettings` we project onto the spec. `env` is parsed only to REPORT
|
|
199
206
|
* it as received-but-deferred when off the host lane (never silently dropped); a MALFORMED `hooks` likewise reports
|
|
200
207
|
* deferred (submit 路径另有 400 fail-loud),valid `hooks` 进 applied shape(hook-runner 阶段一)。 */
|
|
@@ -233,7 +240,7 @@ export interface ParsedTaskSettings {
|
|
|
233
240
|
ultracode?: boolean;
|
|
234
241
|
/** hooks hook-runner(阶段一):经 `parseHooksConfig`(契约包分类器 + 服务侧上限 + 本仓会跑的条目类型)判过的 hooks 配置。像 shellEnv 一样
|
|
235
242
|
* 这里只 PARSE;应用点(main.ts resolveSpec)按单用户闸(`requirePrincipal !== true`)决定翻不翻成
|
|
236
|
-
* 任务座 `TaskSpec.mods`
|
|
243
|
+
* 任务座 `TaskSpec.mods` 上的车道注册(非托管 `settings.hooks`,有托管组时另一张 `settings.hooks.managed`)——多租户 lane 收到只警告忽略(hook 命令跑在 worker host = class ② 能力授予)。 */
|
|
237
244
|
hooks?: RunnableHooksConfig;
|
|
238
245
|
/** [ref](7.77.0)—— CC settings 同名键:上下文窗口里**留给技能清单**的比例((0,1];CC 默认 0.01 = 1%)。
|
|
239
246
|
* 超预算时引擎把描述裁短、再不够退成 name-only(`cli259.js` 的清单渲染算法),**从不**拒掉一条技能 ——
|
|
@@ -242,6 +249,10 @@ export interface ParsedTaskSettings {
|
|
|
242
249
|
skillListingBudgetFraction?: number;
|
|
243
250
|
/** 同族第二键:每条技能描述在清单里的字符帽(正整数;CC 默认 1536)。超出由引擎**截断**,不是拒。 */
|
|
244
251
|
skillListingMaxDescChars?: number;
|
|
252
|
+
/** `settings.autoCompactEnabled`(CC 2.1.309 settings 同名键,布尔):这条 run 的自动压缩开关。逐字交给引擎的自动压缩座 `TaskSpec.compaction.autoCompact`
|
|
253
|
+
* (写点 = `boot/resolve-spec.ts` 经 `spec-fields.ts` 的 `compactionSpecFragment`,与顶层 `compaction.clampTolerance` 同一只映射)。
|
|
254
|
+
* `false` 是有意义的值(不是「没设」),所以 {@link parseTaskSettings} 把它收下、`settings` 因它在场。缺席 ⇒ 整键不写。 */
|
|
255
|
+
autoCompactEnabled?: boolean;
|
|
245
256
|
/** [ref] —— 「只收紧」座位族(`tighten-only-seats.ts` 的四座:读拒模式 / 写保护名的加法 / 合规额外禁项 / 永不自动放行名单)的归一值,**一个键**而不是四个散字段:
|
|
246
257
|
* wire 位置由座位表说(三座在 `settings` 顶层,`neverAuto` 在 `settings.permissions`),解析后与位置无关。空数组 ≡ 缺席(不铸键)。
|
|
247
258
|
* 去处:三座经 {@link applyTaskSettings} 落 core 任务层席;`neverAuto` 经 {@link deriveSettingsPolicy} 落请求叶策略。 */
|
|
@@ -263,9 +274,11 @@ export interface ParseTaskSettingsResult {
|
|
|
263
274
|
readonly stripped: readonly string[];
|
|
264
275
|
};
|
|
265
276
|
}
|
|
266
|
-
/** `parseTaskSettings` 的可选座:续跑重放腿才有的重读座(一次性迁移 M20;新提交腿与不问 hooks 的读者不递)
|
|
277
|
+
/** `parseTaskSettings` 的可选座:续跑重放腿才有的重读座(一次性迁移 M20;新提交腿与不问 hooks 的读者不递)与调用方已读(并已判)的 `settings.env` 那一份。 */
|
|
267
278
|
export interface ParseTaskSettingsSeats {
|
|
268
279
|
readonly storedHooksReread?: StoredHooksRereadM20;
|
|
280
|
+
/** {@link readSettingsEnv} 的一次读数(`resolveSpec` 两腿恒递:凭据判据判的就是这一份,解析层不再读第二次;续跑腿 M38 剥过键的是剥后那一份)。缺席 ⇒ 解析层自己读一次(不交子进程的读者)。 */
|
|
281
|
+
readonly settingsEnv?: SettingsEnvLayer;
|
|
269
282
|
}
|
|
270
283
|
/** Cap on `outputStyle` length — it lands in the system prompt, so it shares the `MAX_SYSTEM_PROMPT_CHARS` (16384)
|
|
271
284
|
* posture (an uncapped prompt body is a per-turn token-cost hole; cross review). Exported so the HTTP layer
|
|
@@ -275,6 +288,40 @@ export declare const MAX_SETTINGS_OUTPUT_STYLE_CHARS = 16384;
|
|
|
275
288
|
export declare const MAX_SETTINGS_ENV_VARS = 256;
|
|
276
289
|
export declare const MAX_SETTINGS_ENV_VALUE_CHARS = 32768;
|
|
277
290
|
export declare const MAX_SETTINGS_ENV_KEY_CHARS = 256;
|
|
291
|
+
/** 一条 `settings.env` 条目被判成凭据的根据(闭集;wire 字段 `entries[].match` 的全部词):`name` = 名字是本进程的凭据变量名;`value_shape` = 值是秘密形。两者都中按 `name` 报。 */
|
|
292
|
+
export declare const SETTINGS_ENV_CREDENTIAL_MATCHES: readonly ["name", "value_shape"];
|
|
293
|
+
export type SettingsEnvCredentialMatch = (typeof SETTINGS_ENV_CREDENTIAL_MATCHES)[number];
|
|
294
|
+
/** 拒体的机读位(原样进 wire 错误体 / `HttpError.extra`):`field` 恒为 `settings.env`;`entries` 按体内序列出每一条命中,键名过调用方串的唯一回显口径,值从不进来。 */
|
|
295
|
+
export interface SettingsEnvCredentialFields {
|
|
296
|
+
readonly field: "settings.env";
|
|
297
|
+
readonly entries: readonly {
|
|
298
|
+
readonly key: string;
|
|
299
|
+
readonly match: SettingsEnvCredentialMatch;
|
|
300
|
+
}[];
|
|
301
|
+
}
|
|
302
|
+
/** 一次裁决的产物:wire 文案 + 机读位 + 命中条目的**原键**(`keys`:不出门,只给续跑腿的一次性迁移按键剥)。 */
|
|
303
|
+
export interface SettingsEnvCredentialIssue {
|
|
304
|
+
readonly message: string;
|
|
305
|
+
readonly fields: SettingsEnvCredentialFields;
|
|
306
|
+
readonly keys: readonly string[];
|
|
307
|
+
}
|
|
308
|
+
/** `settings.env` 的一次读数:`sent` = 调用方送了这个键(不是缺席 / `null`);`reaching` = 会交到子进程的那几条({@link cleanEnvMap};形不对 / 没有一条够格 ⇒ `undefined`;一次性迁移 M38 剥空的是 `{}`,见 {@link withoutKeys})。 */
|
|
309
|
+
export interface SettingsEnvLayer {
|
|
310
|
+
readonly sent: boolean;
|
|
311
|
+
readonly reaching: Readonly<Record<string, string>> | undefined;
|
|
312
|
+
}
|
|
313
|
+
/** `settings.env` 的**唯一**读法:`settings` 不是对象 ⇒ 没送;否则 `env` 只取一次,形判与收取都对这一次的值做。判据、解析层与续跑腿的剥键都吃这一份。 */
|
|
314
|
+
export declare function readSettingsEnv(settings: unknown): SettingsEnvLayer;
|
|
315
|
+
/**
|
|
316
|
+
* `settings.env` 里凭据条目的**唯一**判据(纯函数;律见上方段头)。`reaching` = {@link readSettingsEnv} 读出的那一份(会交到子进程的条目;非串值、超帽的键 / 值本来就到不了子进程;
|
|
317
|
+
* 缺席 / 形不对 ⇒ `undefined` ⇒ 不判,形归受理门的形判)。`credentialNames` = 本进程的凭据变量名(调用方递 `serverCredentialValueSources(config.modelApiKeyEnv)`)。没有命中 ⇒ `null`。
|
|
318
|
+
*/
|
|
319
|
+
export declare function settingsEnvCredentialIssue(reaching: Readonly<Record<string, string>> | undefined, credentialNames: readonly string[]): SettingsEnvCredentialIssue | null;
|
|
320
|
+
/**
|
|
321
|
+
* 一次性迁移 M38(窗口见 `plugins/one-time-migrations.ts` 登记表):从读到的那一份里去掉判据点名的原键,交回剥后的一份。**剥空 = 空表**(调用方送了这一块,剥完什么都不剩):
|
|
322
|
+
* 解析层把它当作这次请求的环境层原样交出,`resolveSpec` 登记它 —— 覆盖这条会话上一条登记;若读成「缺席」,会话注册表按「缺席 = 留着上一条」把上一条(可能正是被剥的那个名字)留给 shell。
|
|
323
|
+
*/
|
|
324
|
+
export declare function withoutKeys(layer: SettingsEnvLayer, keys: readonly string[]): SettingsEnvLayer;
|
|
278
325
|
/** 三桶(闭集;判据按此序逐桶判)。 */
|
|
279
326
|
export declare const SETTINGS_PERMISSION_BUCKETS: readonly ["allow", "deny", "ask"];
|
|
280
327
|
export type SettingsPermissionBucket = (typeof SETTINGS_PERMISSION_BUCKETS)[number];
|
|
@@ -305,7 +352,7 @@ export interface SettingsPermissionBucketIssue {
|
|
|
305
352
|
*/
|
|
306
353
|
export declare function settingsPermissionBucketIssue(perms: unknown): SettingsPermissionBucketIssue | null;
|
|
307
354
|
/** 本 service 真正**消费**的 `settings` 顶层键 —— 闭集。每一个都有消费点:
|
|
308
|
-
* `env`/`hooks`/`model`/`outputStyle`/`permissions`/`ultracode` 与两个 `skillListing*` 在
|
|
355
|
+
* `autoCompactEnabled`/`env`/`hooks`/`model`/`outputStyle`/`permissions`/`ultracode` 与两个 `skillListing*` 在
|
|
309
356
|
* {@link parseTaskSettings};`webSearch` 在 `capabilities/scenarios.ts`(判决 `judgeRequestWebSearch`,单用户闸;形错在受理面 400,[ref])。
|
|
310
357
|
* 加键必须同时加消费点,否则就是往闭集里塞一个新的静默丢。
|
|
311
358
|
*
|
|
@@ -322,10 +369,18 @@ export declare function settingsPermissionBucketIssue(perms: unknown): SettingsP
|
|
|
322
369
|
* 消费点 = 本文件的 parse + `boot/resolve-spec.ts` 的 `TaskSpec` 透传。语义(预算怎么花、描述怎么裁、
|
|
323
370
|
* 溢出怎么退成 name-only)整个归引擎,本仓一个字节都不渲染,也**不复刻默认值**——缺席即整键不写。
|
|
324
371
|
*
|
|
372
|
+
* 🔴 `autoCompactEnabled` = **CC settings 同名键**(2.1.309 的 settings 声明,布尔):这条 run 的自动压缩开关,值域只收布尔({@link autoCompactEnabledOk},两层同问这一只);
|
|
373
|
+
* 消费点 = 本文件的 parse + `boot/resolve-spec.ts` 经 `spec-fields.ts` 的 `compactionSpecFragment` 逐字交给引擎的自动压缩座 `TaskSpec.compaction.autoCompact`(与顶层 `compaction.clampTolerance` 同一只映射、同一个对象)。
|
|
374
|
+
* 关掉的是引擎**自起**的三条道(窗阈值那一遍、prompt-too-long 恢复那一遍、任务尾摘要):守卫链先清旧工具结果、再按尾部裁剪 → 仍装不下则服务商的「prompt too long」拒原样成为
|
|
375
|
+
* 这条 run 的失败终局(不摘要、不重试);怎么终局整个归引擎,本仓不复刻、不夹紧。调用方要的那一遍(`POST /v1/runs/:id/compact`)归引擎的另一只座 `manualCompact`,
|
|
376
|
+
* 本服务不写它 ⇒ 关了自动压缩,手动 `/compact` 照样能跑(与参照实现的 `autoCompactEnabled` 同读)。壳的环境变量 `DISABLE_AUTO_COMPACT` / `DISABLE_COMPACT`
|
|
377
|
+
* 不在本服务的读法里:环境变量是壳进程的事 —— 壳把两者都折成 `autoCompactEnabled: false` 再发;`DISABLE_COMPACT` 多出的「手动也关」由壳自己不发 `/compact` 动词实现
|
|
378
|
+
* (本服务不另读 `settings.env` 里的同名变量 —— 那是 shell 子进程的环境,不是引擎的开关)。
|
|
379
|
+
*
|
|
325
380
|
* 🔴 `allowedHttpHookUrls` / `httpHookAllowedEnvVars` = **CC settings 同名键**(契约包的 http hook 两张名单,键表属主 = 契约包 `HTTP_HOOK_ALLOWLIST_KEYS`):
|
|
326
381
|
* 消费点 = {@link parseTaskSettings} 把它们原样收成一层({@link requestHttpHookAllowlistLayer})→ `boot/resolve-spec.ts` 交给 hooks 注册 → `hooks/hook-runner.ts` 的 http 腿
|
|
327
382
|
* 在拨出之前问契约包判官。受理面只判键名(本门),不判值:名单的读法只有判官那一只(坏形由判官答 `malformed`、拦)。 */
|
|
328
|
-
export declare const TASK_SETTINGS_KEYS: readonly ["allowedHttpHookUrls", "approvalFrameFamilies", "complianceAdditionalDenies", "env", "hooks", "httpHookAllowedEnvVars", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
|
|
383
|
+
export declare const TASK_SETTINGS_KEYS: readonly ["allowedHttpHookUrls", "approvalFrameFamilies", "autoCompactEnabled", "complianceAdditionalDenies", "env", "hooks", "httpHookAllowedEnvVars", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
|
|
329
384
|
/** 本 service 消费的 `settings.permissions` 子键 —— 闭集(值形校验另有既有门,本门只判键名)。 */
|
|
330
385
|
export declare const TASK_SETTINGS_PERMISSION_KEYS: readonly ["allow", "ask", "defaultMode", "deny", "disableAutoMode", "neverAuto"];
|
|
331
386
|
/** CC/SDK 合约里合法、本 service **不接线**的顶层键。词表外的 CC 键落 `unknown` —— 两列都是 400,标签只影响
|
package/dist/task-settings.js
CHANGED
|
@@ -8,7 +8,8 @@ import { limitRefusal } from "./limit-refusal.js";
|
|
|
8
8
|
import { tightenGoverned } from "./governance-overrides.js";
|
|
9
9
|
import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
|
|
10
10
|
import { hooksCoordinate, parseHooksConfig } from "./hooks/hook-runner.js";
|
|
11
|
-
import { HTTP_HOOK_ALLOWLIST_KEYS, SETTINGS_SOURCES } from "@sema-agent/settings-schema";
|
|
11
|
+
import { HTTP_HOOK_ALLOWLIST_KEYS, SETTINGS_SOURCES, containsSecretToken } from "@sema-agent/settings-schema";
|
|
12
|
+
import { echoCallerText } from "./caller-text-echo.js";
|
|
12
13
|
import { heldRuleName } from "./tool-rule-names.js";
|
|
13
14
|
import { policyAskStandingAnswerFacts, standingAnswerDurablyRecordable } from "./tool-approval.js";
|
|
14
15
|
import { createRequestNeverAutoPolicy } from "./approval.js";
|
|
@@ -70,6 +71,9 @@ export function skillListingBudgetFractionOk(v) {
|
|
|
70
71
|
export function skillListingMaxDescOk(v) {
|
|
71
72
|
return typeof v === "number" && Number.isSafeInteger(v) && v > 0;
|
|
72
73
|
}
|
|
74
|
+
export function autoCompactEnabledOk(v) {
|
|
75
|
+
return typeof v === "boolean";
|
|
76
|
+
}
|
|
73
77
|
export const MAX_SETTINGS_OUTPUT_STYLE_CHARS = 16_384;
|
|
74
78
|
export const MAX_SETTINGS_ENV_VARS = 256;
|
|
75
79
|
export const MAX_SETTINGS_ENV_VALUE_CHARS = 32_768;
|
|
@@ -91,6 +95,44 @@ function cleanEnvMap(v) {
|
|
|
91
95
|
}
|
|
92
96
|
return n > 0 ? out : undefined;
|
|
93
97
|
}
|
|
98
|
+
export const SETTINGS_ENV_CREDENTIAL_MATCHES = ["name", "value_shape"];
|
|
99
|
+
export function readSettingsEnv(settings) {
|
|
100
|
+
if (settings === null || typeof settings !== "object" || Array.isArray(settings))
|
|
101
|
+
return { sent: false, reaching: undefined };
|
|
102
|
+
const env = settings.env;
|
|
103
|
+
return { sent: env !== undefined && env !== null, reaching: cleanEnvMap(env) };
|
|
104
|
+
}
|
|
105
|
+
const MAX_CREDENTIAL_KEYS_NAMED = 8;
|
|
106
|
+
const MATCH_PHRASE = { name: "a credential variable of this engine", value_shape: "a value shaped like a secret" };
|
|
107
|
+
export function settingsEnvCredentialIssue(reaching, credentialNames) {
|
|
108
|
+
if (reaching === undefined)
|
|
109
|
+
return null;
|
|
110
|
+
const names = new Set(credentialNames.map((n) => n.toUpperCase()));
|
|
111
|
+
const hits = [];
|
|
112
|
+
for (const [key, value] of Object.entries(reaching)) {
|
|
113
|
+
if (names.has(key.toUpperCase()))
|
|
114
|
+
hits.push({ key, match: "name" });
|
|
115
|
+
else if (containsSecretToken(value))
|
|
116
|
+
hits.push({ key, match: "value_shape" });
|
|
117
|
+
}
|
|
118
|
+
if (hits.length === 0)
|
|
119
|
+
return null;
|
|
120
|
+
const entries = hits.map((h) => ({ key: echoCallerText(h.key, { maxChars: MAX_SETTINGS_ENV_KEY_CHARS }), match: h.match }));
|
|
121
|
+
const named = entries.slice(0, MAX_CREDENTIAL_KEYS_NAMED).map((e) => `${e.key} (${MATCH_PHRASE[e.match]})`);
|
|
122
|
+
const more = entries.length > MAX_CREDENTIAL_KEYS_NAMED ? `, and ${entries.length - MAX_CREDENTIAL_KEYS_NAMED} more` : "";
|
|
123
|
+
return {
|
|
124
|
+
message: `settings.env carries credentials: ${named.join(", ")}${more}. A credential reaches the engine only through the environment its process starts from, never through a request's settings.env — ` +
|
|
125
|
+
"that block comes from a settings file the model can read, and the request hands it to the session's shell and hooks. Move these out of settings.env into the engine's environment " +
|
|
126
|
+
"(a sema shell that keeps credentials in its credentials.env file does this; upgrade a shell that still writes them into settings.json). " +
|
|
127
|
+
"If an entry is not a credential: rename a variable that matched by name, or keep a value that matched by shape out of settings.env the same way (the shape scan is deliberately coarse)",
|
|
128
|
+
fields: { field: "settings.env", entries },
|
|
129
|
+
keys: hits.map((h) => h.key),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export function withoutKeys(layer, keys) {
|
|
133
|
+
const drop = new Set(keys);
|
|
134
|
+
return { sent: layer.sent, reaching: Object.fromEntries(Object.entries(layer.reaching ?? {}).filter(([k]) => !drop.has(k))) };
|
|
135
|
+
}
|
|
94
136
|
export const SETTINGS_PERMISSION_BUCKETS = ["allow", "deny", "ask"];
|
|
95
137
|
export const SETTINGS_PERMISSION_BUCKET_REFUSALS = ["over_cap", "bad_entry"];
|
|
96
138
|
const BUCKET_ENTRY_RULE = { allow: "allow_layer", deny: "rule_policy", ask: "rule_policy" };
|
|
@@ -163,7 +205,7 @@ export function settingsPermissionBucketIssue(perms) {
|
|
|
163
205
|
function acceptedRuleList(v) {
|
|
164
206
|
return Array.isArray(v) && v.length > 0 ? v.slice() : undefined;
|
|
165
207
|
}
|
|
166
|
-
export const TASK_SETTINGS_KEYS = ["allowedHttpHookUrls", "approvalFrameFamilies", "complianceAdditionalDenies", "env", "hooks", "httpHookAllowedEnvVars", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
|
|
208
|
+
export const TASK_SETTINGS_KEYS = ["allowedHttpHookUrls", "approvalFrameFamilies", "autoCompactEnabled", "complianceAdditionalDenies", "env", "hooks", "httpHookAllowedEnvVars", "model", "outputStyle", "permissions", "readDenyPatterns", "skillListingBudgetFraction", "skillListingMaxDescChars", "ultracode", "webSearch", "writeProtectedExtra"];
|
|
167
209
|
export const TASK_SETTINGS_PERMISSION_KEYS = ["allow", "ask", "defaultMode", "deny", "disableAutoMode", "neverAuto"];
|
|
168
210
|
export const TASK_SETTINGS_UNSUPPORTED_KEYS = ["apiKeyHelper", "crossSessionInbound", "dialogExpiry", "sandbox", "statusLine"];
|
|
169
211
|
export const TASK_SETTINGS_UNSUPPORTED_PERMISSION_KEYS = ["additionalDirectories", "disableBypassPermissionsMode"];
|
|
@@ -265,8 +307,9 @@ export function parseTaskSettings(raw, seats = {}) {
|
|
|
265
307
|
deferred.push("hooks");
|
|
266
308
|
}
|
|
267
309
|
}
|
|
268
|
-
const
|
|
269
|
-
|
|
310
|
+
const envLayer = seats.settingsEnv ?? readSettingsEnv(s);
|
|
311
|
+
const shellEnv = envLayer.reaching;
|
|
312
|
+
if (envLayer.sent && shellEnv === undefined)
|
|
270
313
|
deferred.push("env");
|
|
271
314
|
const out = {};
|
|
272
315
|
const perms = s.permissions;
|
|
@@ -311,6 +354,9 @@ export function parseTaskSettings(raw, seats = {}) {
|
|
|
311
354
|
const maxDesc = s.skillListingMaxDescChars;
|
|
312
355
|
if (skillListingMaxDescOk(maxDesc))
|
|
313
356
|
out.skillListingMaxDescChars = maxDesc;
|
|
357
|
+
const autoCompact = s.autoCompactEnabled;
|
|
358
|
+
if (autoCompactEnabledOk(autoCompact))
|
|
359
|
+
out.autoCompactEnabled = autoCompact;
|
|
314
360
|
const tightenSeats = readTightenOnlySeats(raw);
|
|
315
361
|
for (const name of tightenSeats.rejected)
|
|
316
362
|
deferred.push(tightenOnlySeatDeferredName(name));
|
package/dist/tool-approval.d.ts
CHANGED
|
@@ -611,8 +611,8 @@ export interface ToolApprovalFrame {
|
|
|
611
611
|
* `redactSecrets` 后截长一次算定)。形不合 / 空表 ⇒ 不铸键。
|
|
612
612
|
*
|
|
613
613
|
* 耐久路(park 行)的对偶是 `gate.riskDescriptor.allowRuleShadowed`(整体透传,两条 durable 读面在读边界对条目补 `redactSecrets`,
|
|
614
|
-
* 叶表属主 `observability/run-terminal.ts` 的 `redactRiskDescriptor`)
|
|
615
|
-
*
|
|
614
|
+
* 叶表属主 `observability/run-terminal.ts` 的 `redactRiskDescriptor`)。引擎 7.41.x 停驻的行带旧键 `shadowedRule`:不在这一位上(那一格只经脱敏叶表
|
|
615
|
+
* 「认不得的键按内容脱敏」一条原样显示)。
|
|
616
616
|
*/
|
|
617
617
|
allowRuleShadowed?: AllowRuleShadowProjection[];
|
|
618
618
|
/**
|
|
@@ -231,7 +231,7 @@ type _GuardParkArmQueueReverse = AssertAllKeysHandled<Exclude<ParkArmQueueProjec
|
|
|
231
231
|
type _NoDoubleBookParkArmQueue = AssertAllKeysHandled<Extract<ParkArmQueueProjected, ParkArmQueueExcluded>>;
|
|
232
232
|
type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "promptRole" | "promptBinding" | "memory" | "suggestNextPrompts" | "restoreFiles" | "acceptPartialRestore" | "rewindFilesTo" | "tools" | "excludeTools" | "deferTools" | "toolMaterializeStrategy" | "promptLean" | "toolPolicy" | "onAsk" | "onQuestion" | "mods" | "durableApproval" | "resourceSuspend" | "resilience" | "finalVerification" | "checkpointStore" | "handsReadOnly" | "memoryPersistenceCapable" | "additionalDirectories" | "additionalReadDirectories" | "enablePlanMode" | "interactiveTools" | "enableFork" | "shellGate" | "approvalReach" | "writeFace" | "mcp" | "a2a" | "skills" | "backgroundScope" | "envFacts" | "limits" | "configOverrides" | "forwardSubagentEvents" | "retainSubagentSessions" | "retainBackgroundProcesses" | "outputSchema" | "outputRetries" | "compaction" | "attachments" | "selfOrchestration" | "getApiKeyAndHeaders" | "interactionPosture" | "agents" | "permissionMode" | "taskId" | "signal" | "preemptSignal" | "maxSuspends" | "skillListingBudgetFraction" | "skillListingMaxDescChars" | "excludeAllTools" | "fileHistory" | "userInvokedSkills" | "outputStyle" | "projectMemory" | "allowedTools" | "allowTools" | "userAttachments" | "readDenyPatterns" | "writeProtectedAdditions" | "complianceAdditionalDenies" | "projectId";
|
|
233
233
|
/** 导出:请求体键闭集门(`request-key-closure.ts`)据它锁「本仓记为未接线的引擎座,提交口不许受理」—— 两处分类只能同向。 */
|
|
234
|
-
export type TaskSpecUnwired = "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars" | "peerPresence" | "modelRole" | "enableBlockedReport" | "promptForm" | "advisorModel" | "runOrigin" | "planFile" | "classifyAllShell";
|
|
234
|
+
export type TaskSpecUnwired = "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars" | "peerPresence" | "modelRole" | "enableBlockedReport" | "promptForm" | "advisorModel" | "runOrigin" | "planFile" | "classifyAllShell" | "workspace";
|
|
235
235
|
type _GuardTaskSpec = AssertAllKeysHandled<Exclude<keyof TaskSpec, TaskSpecWired | TaskSpecUnwired>>;
|
|
236
236
|
type _GuardTaskSpecReverse = AssertAllKeysHandled<Exclude<TaskSpecWired | TaskSpecUnwired, keyof TaskSpec>>;
|
|
237
237
|
type TaskResultForwarded = "taskId" | "runId" | "sessionId" | "terminal" | "model" | "effectiveReasoning" | "result" | "salvagedOutput" | "remoteEnvFailures" | "apiFailure" | "retryAfterMs" | "degraded" | "structuredOutput" | "rewindNotes" | "haltedOnUserRejection" | "haltedByUser" | "strandedHumanAnswers" | "pendingApproval" | "approvalWaitedMs" | "effectiveReadFace" | "effectiveReadDenyPatterns" | "effectiveWriteFace" | "effectiveMemoryScopes" | "stats" | "editedFiles" | "responseModel" | "compaction" | "resultEntryIds" | "placementRoot";
|
|
@@ -434,11 +434,12 @@ type _CoverWordsCheck = AssertAllKeysHandled<Exclude<CoveringWords<{
|
|
|
434
434
|
note: string;
|
|
435
435
|
}[], _CoverProbeWords>>>;
|
|
436
436
|
type SessionMemoryStatusSourceKey = keyof SessionMemoryStatus | keyof DeploymentSessionMemoryStatus;
|
|
437
|
-
type SessionMemoryStatusProjected = "captureOptedOut" | "committedCount" | "foldedCount" | "optOutSource" | "lastCaptureAt";
|
|
438
|
-
|
|
439
|
-
type
|
|
440
|
-
type
|
|
441
|
-
type
|
|
437
|
+
type SessionMemoryStatusProjected = "captureOptedOut" | "committedCount" | "foldedCount" | "optOutSource" | "lastCaptureAt" | "writeHome" | "planes";
|
|
438
|
+
/** 其中部署对象顶层也答的那些(引擎折好的五键 + 引擎择一的 `writeHome`;`planes` 是逐店明细本身)。 */
|
|
439
|
+
type SessionMemoryStatusDeploymentTop = Exclude<SessionMemoryStatusProjected, "planes">;
|
|
440
|
+
type _GuardSessionMemoryStatus = AssertAllKeysHandled<Exclude<SessionMemoryStatusSourceKey, SessionMemoryStatusProjected>>;
|
|
441
|
+
type _GuardSessionMemoryStatusReverse = AssertAllKeysHandled<Exclude<SessionMemoryStatusProjected, SessionMemoryStatusSourceKey>>;
|
|
442
|
+
type _GuardSessionMemoryStatusDeploymentReverse = AssertAllKeysHandled<Exclude<SessionMemoryStatusDeploymentTop, keyof DeploymentSessionMemoryStatus>>;
|
|
442
443
|
type SideQueryResultForwarded = "text" | "toolCalls" | "model" | "servedModel" | "degraded" | "responseModel" | "usage" | "usageMissing" | "stopReason" | "errorMessage" | "errorCode" | "errorKind" | "inputTooLongRuledOut" | "account";
|
|
443
444
|
type SideQueryResultStripped = never;
|
|
444
445
|
type _GuardSideQueryResult = AssertAllKeysHandled<Exclude<keyof SideQueryResult, SideQueryResultForwarded | SideQueryResultStripped>>;
|
|
@@ -453,7 +454,7 @@ type GateOutcomeProjected = "disposition" | "settlement" | "origin";
|
|
|
453
454
|
type _GuardGateOutcome = AssertAllKeysHandled<Exclude<keyof GateOutcome, GateOutcomeProjected>>;
|
|
454
455
|
type _GuardGateOutcomeReverse = AssertAllKeysHandled<Exclude<GateOutcomeProjected, keyof GateOutcome>>;
|
|
455
456
|
type GateDispositionKeys = GateDisposition extends infer D ? (D extends object ? keyof D : never) : never;
|
|
456
|
-
type GateDispositionProjected = "kind" | "deniedBy" | "cause" | "classifier" | "released" | "clearedBy" | "mode" | "askClass" | "classes" | "extension";
|
|
457
|
+
type GateDispositionProjected = "kind" | "deniedBy" | "cause" | "classifier" | "released" | "clearedBy" | "mode" | "askClass" | "classes" | "extension" | "echoed";
|
|
457
458
|
type _GuardGateDisposition = AssertAllKeysHandled<Exclude<GateDispositionKeys, GateDispositionProjected>>;
|
|
458
459
|
type _GuardGateDispositionReverse = AssertAllKeysHandled<Exclude<GateDispositionProjected, GateDispositionKeys>>;
|
|
459
460
|
type SettlementProjected = "kind" | "who" | "when" | "note";
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* 同文件 G1 e2e 的全码扇出夹具、以及契约文档附录 D.3 那张表(含**小节标题里的码数** —— 那道门本批
|
|
17
17
|
* 刚立,立完就在下一次加码时自己咬住了)。
|
|
18
18
|
*/
|
|
19
|
-
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "mcp.injection_dropped", "delegation.ask_unresolvable", "task.interrupt_unconsumed", "approval.read_root_granted", "approval.read_root_grant_rejected", "instructions.source_changed", "session.lineage_rerooted", "server.model_unreachable", "permission.entry_mode_clamped", "classifier.unavailable", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "permission.allowed_tool_not_granted", "task.tool_turn_incomplete", "route.finish_reason_unknown", "route.stream_end_ignored", "route.credential_origin_mismatch", "mods.registration_refused", "config.session_rules_earlier_grammar", "advisor.not_attached", "inherit_env.names_withheld", "model.capability_downgraded", "context.media_removed", "mcp.authorization_required", "classifier.seat_rate_limited", "context.tool_schema_removed"];
|
|
19
|
+
export declare const ENGINE_NOTICE_WIRE_CODES: readonly ["memory.session_polluted", "memory.harvest_quarantined", "memory.delegation_static_mark_waived", "memory.hold_opened", "memory.hold_released", "memory.hold_disposed", "task.turn_interrupted", "steering.parked_input_blocked", "task.user_steer_undrained", "task.user_followup_undrained", "memory.capture_opted_out", "memory.capture_optout_unpersisted", "task.halt_unconsumed", "task.late_approval", "config.durable_gate_unavailable", "peer.inbound_disposition", "peer.held_settled", "peer.idle_subscription", "classifier.denial_limit", "mcp.injection_dropped", "delegation.ask_unresolvable", "task.interrupt_unconsumed", "approval.read_root_granted", "approval.read_root_grant_rejected", "instructions.source_changed", "session.lineage_rerooted", "server.model_unreachable", "permission.entry_mode_clamped", "classifier.unavailable", "config.permission_mode_unavailable", "permission.ask_released_by_mode", "permission.read_deny_unapplied", "permission.rule_store_unavailable", "permission.rule_row_dropped", "permission.allowed_tool_not_granted", "task.tool_turn_incomplete", "route.finish_reason_unknown", "route.stream_end_ignored", "route.credential_origin_mismatch", "mods.registration_refused", "config.session_rules_earlier_grammar", "advisor.not_attached", "inherit_env.names_withheld", "model.capability_downgraded", "context.media_removed", "mcp.authorization_required", "classifier.seat_rate_limited", "context.tool_schema_removed", "memory.harvest_refused", "memory.harvest_conflict"];
|
|
20
20
|
export type EngineNoticeWireCode = (typeof ENGINE_NOTICE_WIRE_CODES)[number];
|
|
21
21
|
/** 白名单谓词(单点):路由与门都读这一个,不许第二处手抄码串。 */
|
|
22
22
|
export declare function isEngineNoticeWireCode(code: string): code is EngineNoticeWireCode;
|
|
@@ -51,6 +51,8 @@ export const ENGINE_NOTICE_WIRE_CODES = [
|
|
|
51
51
|
"mcp.authorization_required",
|
|
52
52
|
"classifier.seat_rate_limited",
|
|
53
53
|
"context.tool_schema_removed",
|
|
54
|
+
"memory.harvest_refused",
|
|
55
|
+
"memory.harvest_conflict",
|
|
54
56
|
];
|
|
55
57
|
const WIRE_CODES = new Set(ENGINE_NOTICE_WIRE_CODES);
|
|
56
58
|
export function isEngineNoticeWireCode(code) {
|
|
@@ -25,6 +25,9 @@ export type SafeText = string & {
|
|
|
25
25
|
* 这一行比 `trace-frame-text` 多一条界(4000 码元,与同族条目的文本位同额),原样出门:`payload` 列是 TEXT,无界的文本一旦超过列宽,入箱写整条失败、补投连摘要一起丢(完成已被记作送达),所以先有界。
|
|
26
26
|
* · `boot-refusal-line`:起服拒启的一行拒句 —— 部署座装配的拒句(`mods-declaration.ts`:声明的席名、包名、读包者 / 引擎准入交回的话);它经进程级 fatal 出口原样多行进 stderr,
|
|
27
27
|
* 所以必须在这里先压成一行(一句拒因里的换行会在运维的终端里伪造出第二条日志行);界 512 码元(含截断记号)。
|
|
28
|
+
* · `workflow-recovery-summary`:workflow 完成通知在崩溃恢复路径上由 run 行的错误文本合成的摘要(`summary`;`orchestration/workflow-notify-journal.ts` 的 `recoverySummary`)——
|
|
29
|
+
* 诊断面,脱敏器的诊断档(`diagnostic`:自由文本档全员 + 诊断值位臂,凭据名 / 方案词后面的值不设强度门);不设界、原样出门:摘要的界与主机身份两形(整条 URL / 绝对路径)
|
|
30
|
+
* 是摘要自己的形(它镜像引擎 live 摘要的那一形),在座之后施加,不是凭据判定。
|
|
28
31
|
* · `peer-inbound-card-text`:运维审批队列 `peer_inbound` 行(`GET /v1/approvals` 的 `pending[]` 与 `/v1/approvals/stream` 的 `pending` 帧)上被扣跨会话来信的
|
|
29
32
|
* 存储正文(`content`,core 的规范存储形 `[summary] message`)与发信方显示名(`fromName`)—— 别的会话写的自由文本,读者是收信方本人;不设界(core 存的那一份就是
|
|
30
33
|
* 收信方要审的全文,截了就审不全),原样出门(JSON 串值,消费方自己渲染)。
|
|
@@ -81,6 +84,9 @@ declare const EXIT_SEATS: {
|
|
|
81
84
|
readonly "peer-inbound-card-text": {
|
|
82
85
|
readonly scope: "free-text";
|
|
83
86
|
};
|
|
87
|
+
readonly "workflow-recovery-summary": {
|
|
88
|
+
readonly scope: "diagnostic";
|
|
89
|
+
};
|
|
84
90
|
};
|
|
85
91
|
export type ExitSeat = keyof typeof EXIT_SEATS;
|
|
86
92
|
/** 设了界的座名。 */
|
package/dist/trace/exit-seat.js
CHANGED
|
@@ -17,6 +17,7 @@ const EXIT_SEATS = {
|
|
|
17
17
|
"inbox-diagnostics-text": { scope: "free-text", maxChars: 4000 },
|
|
18
18
|
"boot-refusal-line": { scope: "free-text", maxChars: 512, emit: "log-line" },
|
|
19
19
|
"peer-inbound-card-text": { scope: "free-text" },
|
|
20
|
+
"workflow-recovery-summary": { scope: "diagnostic" },
|
|
20
21
|
};
|
|
21
22
|
export function seatMaxChars(seat) {
|
|
22
23
|
return EXIT_SEATS[seat].maxChars;
|
|
@@ -53,8 +53,9 @@ export type LiveModelTextFrame = (LiveEventIdentity & {
|
|
|
53
53
|
* 一块的原文只有一个定义({@link blockText}:它的 delta 字节;一个 delta 字节都没有、只有 `text_end` 的块 = 它的正文),活流段流与两条账本腿同读 ——
|
|
54
54
|
* 只有 `text_end` 的块照样进本段的流,由段末帧交付(不另出逐块帧),也照样进账本 `text` 行。
|
|
55
55
|
* 交付点上:① 这一块还押在窗里的字节按整段读法、**文本到此为止**交出(流式口的 `takeAll`;一帧不带 `eventId` 的 `text_delta`,紧贴段末帧之前);
|
|
56
|
-
* ② `text_end.content` = 引擎这一块的正文,**接在本段已喂入的前文之后**判(`textEndEventData(ev, 前文)`:与账本行同一只 `redactModelText
|
|
57
|
-
*
|
|
56
|
+
* ② `text_end.content` = 引擎这一块的正文,**接在本段已喂入的前文之后**判(`textEndEventData(ev, 前文)`:与账本行同一只 `redactModelText`;前文只作判定上下文;
|
|
57
|
+
* 前文与块界都是流式口自己的状态(`blockContext` / `blockBytes` / `endBlock`),登记册不另记 —— 流式口只留判定还需要的那一截前文(「扫描窗」,见 `trace/redact.ts` 流式口顶注),读法与带整段前文逐字节同);
|
|
58
|
+
* ③ 记下块界(`endBlock`)。⇒ 每块的逐块帧拼接 = 该块 `text_end.content`(引擎没修剪那一块时逐字节),各块依次拼接 = 账本 `text` 行(块界上到此为止的判定与整段判定不同时除外,见下)。
|
|
58
59
|
* 判定读不到交付点之后的字节,到此为止的判定可以与整段判定不同:一条凭据形恰横跨块界(交付那一截按到此为止判,读得出的半形出记号,后一块上横跨的那一条整枚换记号),
|
|
59
60
|
* 或交付时认作凭据、后文让它不再是(活流那一截是记号)—— 两种都是账本整段判,
|
|
60
61
|
* 段末核对对不上计一次 `server.live-text.hold-diverged` —— 这是交付点的定义,不是第二套规则(等后文 = 一段引子要扣到下一个结构帧,例如整份工具入参生成完)。
|
|
@@ -39,7 +39,7 @@ function release(s) {
|
|
|
39
39
|
return s.text.takeSettled();
|
|
40
40
|
}
|
|
41
41
|
catch (err) {
|
|
42
|
-
recordFailOpen("server.run-terminal.redact-threw", `live-hold len=${s.text.
|
|
42
|
+
recordFailOpen("server.run-terminal.redact-threw", `live-hold len=${s.text.length} err=${errorKindOf(err)}`);
|
|
43
43
|
return "";
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -48,20 +48,28 @@ function deliverBlock(s) {
|
|
|
48
48
|
return s.text.takeAll();
|
|
49
49
|
}
|
|
50
50
|
catch (err) {
|
|
51
|
-
recordFailOpen("server.run-terminal.redact-threw", `live-hold len=${s.text.
|
|
51
|
+
recordFailOpen("server.run-terminal.redact-threw", `live-hold len=${s.text.length} err=${errorKindOf(err)}`);
|
|
52
52
|
s.text.skip();
|
|
53
53
|
return OVERSIZED_REDACTION_PLACEHOLDER;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
|
+
function closeBlock(s) {
|
|
57
|
+
try {
|
|
58
|
+
s.text.endBlock();
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
recordFailOpen("server.run-terminal.redact-threw", `live-hold len=${s.text.length} err=${errorKindOf(err)}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
56
64
|
function remainderOf(family, s) {
|
|
57
65
|
try {
|
|
58
66
|
const r = s.text.flush();
|
|
59
67
|
if (r.diverged)
|
|
60
|
-
recordFailOpen("server.live-text.hold-diverged", `family=${family} len=${s.text.
|
|
68
|
+
recordFailOpen("server.live-text.hold-diverged", `family=${family} len=${s.text.length}`);
|
|
61
69
|
return r.rest;
|
|
62
70
|
}
|
|
63
71
|
catch (err) {
|
|
64
|
-
recordFailOpen("server.run-terminal.redact-threw", `live-hold len=${s.text.
|
|
72
|
+
recordFailOpen("server.run-terminal.redact-threw", `live-hold len=${s.text.length} err=${errorKindOf(err)}`);
|
|
65
73
|
return OVERSIZED_REDACTION_PLACEHOLDER;
|
|
66
74
|
}
|
|
67
75
|
}
|
|
@@ -69,7 +77,7 @@ export function createLiveModelText() {
|
|
|
69
77
|
const open = { text: new Map(), reasoning: new Map() };
|
|
70
78
|
const deltaType = (family) => (family === "text" ? "text_delta" : "reasoning_delta");
|
|
71
79
|
const openSegment = (family, key, ident, deliver) => {
|
|
72
|
-
const s = { ident, text: createRedactionStream(), delivering: deliver
|
|
80
|
+
const s = { ident, text: createRedactionStream(), delivering: deliver };
|
|
73
81
|
open[family].set(key, s);
|
|
74
82
|
return s;
|
|
75
83
|
};
|
|
@@ -131,8 +139,8 @@ export function createLiveModelText() {
|
|
|
131
139
|
if (ev.type === "text_end") {
|
|
132
140
|
let s = open.text.get(key);
|
|
133
141
|
const out = [];
|
|
134
|
-
const before = s === undefined ? "" : s.text.
|
|
135
|
-
const arrived = s === undefined ? "" : s.text.
|
|
142
|
+
const before = s === undefined ? "" : s.text.blockContext();
|
|
143
|
+
const arrived = s === undefined ? "" : s.text.blockBytes();
|
|
136
144
|
const unfed = blockText(arrived, ev).slice(arrived.length);
|
|
137
145
|
const endOnly = unfed !== "" ? unfed : undefined;
|
|
138
146
|
if (s === undefined && endOnly !== undefined)
|
|
@@ -151,7 +159,7 @@ export function createLiveModelText() {
|
|
|
151
159
|
if (rest !== "" && endOnly === undefined)
|
|
152
160
|
out.push({ type: "text_delta", delta: rest, ...liveIdentityFields(s.ident) });
|
|
153
161
|
}
|
|
154
|
-
s
|
|
162
|
+
closeBlock(s);
|
|
155
163
|
}
|
|
156
164
|
const end = deliver ? textEndEventData(ev, before) : null;
|
|
157
165
|
if (end !== null)
|
package/dist/trace/project.js
CHANGED
|
@@ -174,6 +174,15 @@ function screenedGateOrThrow(v) {
|
|
|
174
174
|
...(d.askClass === undefined ? {} : { askClass: d.askClass }),
|
|
175
175
|
...(d.classes === undefined ? {} : { classes: [...d.classes] }),
|
|
176
176
|
...(d.extension === undefined ? {} : { extension: seatText("trace-frame-text", d.extension) }),
|
|
177
|
+
...(d.echoed === undefined
|
|
178
|
+
? {}
|
|
179
|
+
: {
|
|
180
|
+
echoed: d.echoed.map((e) => ({
|
|
181
|
+
kind: e.kind,
|
|
182
|
+
value: seatText("trace-frame-text", e.value),
|
|
183
|
+
...(e.canonical === undefined ? {} : { canonical: seatText("trace-frame-text", e.canonical) }),
|
|
184
|
+
})),
|
|
185
|
+
}),
|
|
177
186
|
}
|
|
178
187
|
: { kind: "allowed", ...(classifier === undefined ? {} : { classifier }), ...(released === undefined ? {} : { released }), ...(clearedBy === undefined ? {} : { clearedBy }) },
|
|
179
188
|
...(settlement === undefined ? {} : { settlement }),
|
package/dist/trace/redact.d.ts
CHANGED
|
@@ -38,6 +38,10 @@ export declare function armPoolBudgetForTest(): {
|
|
|
38
38
|
readings: number;
|
|
39
39
|
coverageVisits: number;
|
|
40
40
|
rowVisits: number;
|
|
41
|
+
scannedUnits: number;
|
|
42
|
+
windowAdvances: number;
|
|
43
|
+
windowRefusals: number;
|
|
44
|
+
windowEvaluations: number;
|
|
41
45
|
};
|
|
42
46
|
export declare function resetArmPoolBudgetForTest(): void;
|
|
43
47
|
/**
|
|
@@ -53,9 +57,15 @@ export declare function resetArmPoolBudgetForTest(): void;
|
|
|
53
57
|
* 锚在每一份视图里都被摧毁。把结构锚臂一并踢出本档,270 形读数**零差**。留着它们是因为「谁的判别力依赖
|
|
54
58
|
* 自由文本语法」这条**判据**上它们本就不该被排除(踢掉是另一条理由),不是因为它们在这里还起作用。
|
|
55
59
|
*
|
|
60
|
+
* · `"diagnostic"`:诊断面 —— 由错误文本合成、给人读的失败句(workflow 恢复摘要)。多遮一个字只是一句诊断少一截,少遮一个字是凭据明文,
|
|
61
|
+
* 所以这一档 = 自由文本档**全员** + 只在这一档在场的**诊断值位臂**({@link collectDiagnosticValueSpans}:凭据名表里的名字 / `Basic`·`Bearer` 方案词后面的值,
|
|
62
|
+
* 不设强度门)。它是诊断面的那一读归进同一只脱敏器的落点:读的是同一张名表、同一个候选池、同一条并集律,出口经出口座的诊断行。
|
|
63
|
+
*
|
|
56
64
|
* 闭集:加一个档而不在 {@link armPool} 的档表里处置 ⇒ **编译**红。
|
|
57
65
|
*/
|
|
58
|
-
type RedactionScope = "free-text" | "bounded-unit";
|
|
66
|
+
type RedactionScope = "free-text" | "bounded-unit" | "diagnostic";
|
|
67
|
+
/** 🧪 值词表里 `type-name` 一列的词(增补纪律钉读:每个类型名在基线门 c 组都有一格语料)。 */
|
|
68
|
+
export declare function lineKeyTypeNamesForTest(): readonly string[];
|
|
59
69
|
/** 本模块会写进文本的全部替换 token(`«…»` 字面),从三张表现算 —— 表改这里自动跟,不另抄一份。
|
|
60
70
|
* 🔴 **[ref] v2 修复轮起它只剩一个语义:闭形闭集的加载期校验**。运行期「这一段是不是一枚记号」已经由
|
|
61
71
|
* 记号行的闭**形**一处答完({@link tokenUnits} / {@link tokenEnd}),按闭**集**再认一遍的
|
|
@@ -89,6 +99,9 @@ export declare function unitCountsWithinForTest(table: ReadonlyArray<readonly [n
|
|
|
89
99
|
/** 🧪 结构读数(与 {@link ppkScanBytesForTest} 同一条技法):本扫描器读过的单元数,线性钉用。 */
|
|
90
100
|
export declare function anchoredScanUnitsForTest(): number;
|
|
91
101
|
export declare function resetAnchoredScanUnitsForTest(): void;
|
|
102
|
+
/** 🧪 结构读数(与 {@link anchoredScanUnitsForTest} 同一条技法):诊断值位扫描器读过的单元数(向右读的值 / 空白单元 + 向左走的空白 / 名字码元),线性钉用。 */
|
|
103
|
+
export declare function diagnosticScanUnitsForTest(): number;
|
|
104
|
+
export declare function resetDiagnosticScanUnitsForTest(): void;
|
|
92
105
|
/** 测试可见([ref] 真值表的两半):结构段里**表行只作声明、实现是手写扫描器**的臂 —— 声明正则的**新拷贝**
|
|
93
106
|
* (`lastIndex` 不与模块内那一枚共享)+ 扫描器在一份原文上产的候选跨度 `[起, 止)`。臂名是闭集 ⇒ 穷尽 `switch`
|
|
94
107
|
* (少一个 `case` = 缺返回 = 编译红)。 */
|
|
@@ -99,6 +112,23 @@ export declare function structuralScannerForTest(arm: "json-secret-field" | "pem
|
|
|
99
112
|
/** 测试可见:扫描器 indexOf 实际扫过的字节数(摊还线性 ⇒ ≤ 常数 × 输入长)。 */
|
|
100
113
|
export declare function ppkScanBytesForTest(): number;
|
|
101
114
|
export declare function resetPpkScanBytesForTest(): void;
|
|
115
|
+
/**
|
|
116
|
+
* 🔴 **一条臂向前读多远**(候选池成员身份的必填一格 {@link MemberIdentity.prior};闭集两形,读者一律穷尽 `switch`)—— 流式口扫描窗的两张字母表
|
|
117
|
+
* (地平线不数的间隔码元、被丢前缀里不许有的定界字面)由这一格现算({@link STREAM_WINDOW_ALPHABETS}),窗不另持一份。
|
|
118
|
+
* · `bounded`:判定一个位置时向前读的部分有界 —— 判定距离之内({@link MemberIdentity.reach})、同一行之内,或隔着构造两部分之间一段**任意长**的间隔 run;
|
|
119
|
+
* `gap` 答「哪些码元可以出现在这段间隔里」(按码元判,原文读法 `json = false` —— 流式口只这样读)。没有任意长间隔的臂给 {@link NO_GAP}。
|
|
120
|
+
* 正则臂由构造者现算:词法关键字臂 = 它的分隔段类({@link KeywordTail.isSeparator},造正则的同一份类源);其余正则臂的「无界原子之后还有必需的东西」在
|
|
121
|
+
* {@link regexDecisionReach} 已加载期抛 ⇒ 没有间隔。手写扫描器给它自己读间隔时调的那只谓词(同一只函数,不抄字符表)。
|
|
122
|
+
* · `anchored`:读**整段之前任意远**的前文(孤立收尾栅栏看「之前有过起始栅栏」、无头体起于前面某一枚收尾之后),但只从这几枚**字面锚**起读 —— 容器的定界字面;
|
|
123
|
+
* 前文里没有它们,这条臂就没有可读的前文。间隔不必声明:窗不越过任何一枚字面锚(这一形的构造整只在锚之后)。
|
|
124
|
+
*/
|
|
125
|
+
export type PriorReading = {
|
|
126
|
+
readonly kind: "bounded";
|
|
127
|
+
readonly gap: (unit: number) => boolean;
|
|
128
|
+
} | {
|
|
129
|
+
readonly kind: "anchored";
|
|
130
|
+
readonly anchors: readonly [string, ...string[]];
|
|
131
|
+
};
|
|
102
132
|
/** Redact unambiguous secret formats from reasoning/CoT before it is persisted to the durable trace log. */
|
|
103
133
|
/** S24 (SILENT-FALLBACK P1): optional redaction observer — rewrites previously had zero fingerprint, so
|
|
104
134
|
* over-redaction (mangling legit content) and under-redaction (a pattern that never fires) were both
|
|
@@ -165,7 +195,7 @@ export declare const WHOLE_EXTENT: RedactionExtent;
|
|
|
165
195
|
* `from`:出门区与余量**各自从自己的起点数**(窗 = 出门区〔从头数半窗〕+ 余量〔从出门区终点起再数半窗〕),不是各自从头数「第一个 ≥ units 的终点」—— 后者遇到不可见填充会按翻倍
|
|
166
196
|
* 跳到同一个终点,余量塌成 0,被窗尾切开的凭据在出门区里露出半截(修复验证 r3 high)。
|
|
167
197
|
* 取舍:不可见填充很大的文本,窗随之延伸(最坏延伸到整段 = 整段读法的代价),换来「窗里的读法单元数恒 ≥ `units`」这一个不变量 —— 窗里每一读的视图都不短于 `units`。
|
|
168
|
-
* 终点不落在转义写法中间:前缀末尾还没写完的转义写法({@link
|
|
198
|
+
* 终点不落在转义写法中间:前缀末尾还没写完的转义写法(转义写法读者的截断读数,在读法后文本上判,{@link shortestReading})不计数、窗延伸到它写完 —— 出门区终点与窗尾都因此落在转义的边上,余量从干净的边起数。
|
|
169
199
|
* 复杂度:**第一趟**若可见占比 ≥ 一半(少量换行 / 色码)按占比补足缺口,均匀的文本一两趟落在终点附近;补不足(或占比低)的趟一律至少翻倍 —— 总趟数 O(log 终点)、总功 O(终点),
|
|
170
200
|
* 不存在逐趟只前进几个码元的爬行(4095 个可见 + 4000 个控制字符曾因此平方,K=4000 约 0.2–0.3 s)。判据与读法格同源(同一批切除点收集器,零第二份「什么算不可见」)。
|
|
171
201
|
*/
|
|
@@ -208,11 +238,13 @@ export declare function redactSecretsWithArms(text: string, opts?: {
|
|
|
208
238
|
* 同一只 {@link runRedaction}、同一遍扫描,交出池算好的 `kept` 跨度映回**原文**之后的那一份([ref] 那一份;坐标在原文上,
|
|
209
239
|
* 与产物同一套 —— [ref] 起;此前在剥后视图上),
|
|
210
240
|
* 不是第二只脱敏器、不改任何判据、不喂观察者(`observe:false`,与影子重扫同口);`opts.json` 与 {@link redactSecrets} 的同名选项
|
|
211
|
-
* 逐字同义(JSON 模式,`redactedPreview` 走的那一条)
|
|
241
|
+
* 逐字同义(JSON 模式,`redactedPreview` 走的那一条);`opts.scope` = 档(缺省自由文本档;`"diagnostic"` = 诊断档,生产入口是出口座的诊断行 `workflow-recovery-summary`,
|
|
242
|
+
* 基线门的诊断档按它跑 —— 座不收 JSON 模式,a 组的 json 份经这里量同一个档)。生产代码不调用它:
|
|
212
243
|
* 问「有没有凭据形」的消费方走 {@link redactSecretsWithArms}。
|
|
213
244
|
*/
|
|
214
245
|
export declare function redactionSpansForTest(text: string, opts?: {
|
|
215
246
|
json?: boolean;
|
|
247
|
+
scope?: "free-text" | "diagnostic";
|
|
216
248
|
}): {
|
|
217
249
|
text: string;
|
|
218
250
|
spans: ReadonlyArray<{
|
|
@@ -254,6 +286,23 @@ export declare function pendingTailReachForTest(): ReadonlyArray<{
|
|
|
254
286
|
readonly order: number;
|
|
255
287
|
readonly reach: number;
|
|
256
288
|
}>;
|
|
289
|
+
/** 测试可见:扫描窗的两张字母表 —— 全池成员的声明再加 `extra`(造一条新臂的声明),与生产同一只派生、同一份自证(不成立照样抛)。 */
|
|
290
|
+
export declare function streamWindowAlphabetsForTest(extra?: readonly PriorReading[]): {
|
|
291
|
+
readonly isBlank: (unit: number) => boolean;
|
|
292
|
+
readonly containerDelimiters: readonly string[];
|
|
293
|
+
};
|
|
294
|
+
/** 测试可见:转义写法文法本身 —— `read(s)` = 读者对 `s`(引导 run 起头)的读数(码点 / `-1` 读不出 / `-2` 截断)与写法末尾;`isBodyUnit` = 字面锚自证读的那只本体谓词。 */
|
|
295
|
+
export declare function escapeGrammarForTest(): {
|
|
296
|
+
readonly read: (s: string) => {
|
|
297
|
+
readonly value: number;
|
|
298
|
+
readonly end: number;
|
|
299
|
+
};
|
|
300
|
+
readonly isBodyUnit: (unit: number) => boolean;
|
|
301
|
+
};
|
|
302
|
+
/** 测试可见:扫描窗的前移点候选(`-1` = 窗尾有一枚还没写完的转义写法;`0` = 没有),字母表按全池成员的声明再加 `extra` 现算({@link streamWindowAlphabetsForTest})。 */
|
|
303
|
+
export declare function windowAdvancePointForTest(text: string, units: number, extra?: readonly PriorReading[]): number;
|
|
304
|
+
/** 测试可见:扫描窗前移点的认证(生产里 `q` 恒是行首;单测拿非行首的 `q` 钉住「名字在 `q` 之前、值在 `q` 之后」「跨度横跨 `q`」两形各自被认证挡下)。 */
|
|
305
|
+
export declare function windowIndependentAtForTest(text: string, q: number): boolean;
|
|
257
306
|
/**
|
|
258
307
|
* 🔴 **流式口 —— 同一只脱敏器的三口**(live 面逐块到达的模型文本 `text_delta` / `reasoning_delta` 的唯一放行器;登记册在 `trace/model-segment.ts`)。
|
|
259
308
|
* 同一只 {@link runRedaction}、同一张表,只多一件事:知道文本还在长。
|
|
@@ -268,6 +317,20 @@ export declare function pendingTailReachForTest(): ReadonlyArray<{
|
|
|
268
317
|
* 读错的那一形在冲刷时现形(`diverged`),调用方响亮留痕。
|
|
269
318
|
* 延迟上界:一个字节在它之后又到 {@link PENDING_TAIL_UNITS} 个读法单元之后的下一次重扫时交出;盖住它的跨度判定之前(或冲刷之前)不交出。
|
|
270
319
|
* 不喂观察者(`observe:false`,与影子重扫同口):命中只在段末那一次整段脱敏里计(段末帧的铸点),逐块重扫不重复计数。扫描器抛 ⇒ 原样抛(放行位不动)。
|
|
320
|
+
*
|
|
321
|
+
* 🔴 **扫描窗**(多块长段的扫描量;与上面「押在窗里的字节」的窗不是一回事 —— 那是还没交出的未决尾,这是判定要读的前文):一段里每个块的交付点都要「前文 + 本块」一起判(锚在前一块、值在这一块),整段重扫则一段 N 块的总扫描量随 N 平方涨。流式口因此只留判定还需要的那一截前文 ——
|
|
322
|
+
* **扫描窗** = 全段的一个后缀 `[base, 全段长)`:取已判定前缀、交付点与前文({@link RedactionStream.blockContext})都只在窗上扫;只有收尾冲刷仍是整段一遍(一段一次),窗若曾判错,对不上在这里现形(`diverged`)。
|
|
323
|
+
* 扫描窗只在块界({@link RedactionStream.endBlock})前移,前移点 `q` 同时满足:① 是行首(其前一码元是换行 —— 行内向左读的臂不会读过它);② 其后至少留
|
|
324
|
+
* {@link STREAM_WINDOW_HORIZON} × 未决尾个**非空白**读法单元({@link windowAdvancePoint}:任何判定距离之内的候选与它们的证据邻居都在窗里;键与冒号已到、值的起引号还隔着一段任意长的空白在后文里的锚,
|
|
325
|
+
* 此刻不显现为任何跨度,只有「后文接在窗尾」能补全它 —— 空白不挤掉它们);③ 已交出到段尾(没有未交出的字节落在 `q` 之前);
|
|
326
|
+
* ④ 被丢的前缀里没有容器类臂的定界字面({@link STREAM_WINDOW_ALPHABETS} 的 `containerDelimiters`:孤立收尾、无头体、「前面有过起始栅栏」读的是整段之前任意远的前文);
|
|
327
|
+
* ⑤ 经 {@link windowIndependentAt} 认证(head 读法下:没有跨度横跨 `q`;从 `q` 起单独扫的跨度与整窗里同一截逐条相同)。
|
|
328
|
+
* 没有满足这五条的点(没有换行的超长单行、一枚始终没收尾的多块结构、整段里出现过密钥栅栏 / PuTTY 密钥头、整窗只有一行 …)⇒ 窗不动、读法不变,代价退回「窗长」(= 与改前同阶)。扫描窗能前移时,每块的扫描量是 O(块长 + 地平线 + 最长行),与段长无关。
|
|
329
|
+
* 🔴 **五条规则健全的三条前提,都由构造成立、不靠手抄**(臂集一变,窗随之变;没有一份要人记得同步的镜像):
|
|
330
|
+
* ① 每条臂任意长间隔里的字符,地平线都不数 —— 地平线不数的字符**就是**全池 `bounded` 声明的间隔之并({@link STREAM_WINDOW_ALPHABETS},{@link PriorReading});
|
|
331
|
+
* ② 读整段之前任意远前文的臂,都只从字面锚起读,窗不越过这些字面 —— 定界字面表**就是**全池 `anchored` 声明的字面锚之并(加载期自证每枚字面对删除单调:字面里没有一读会删的码元、首码元不是转义写法本体能读进的码元;不成立即抛);
|
|
332
|
+
* ③ 读法里「多码元、补全后消失」的写法只有转义写法,窗尾的半枚由**同一只**转义写法读者判({@link readEscapeElement} 的截断读数,{@link collectSpelledCuts} 的 `open`)—— 文法一份,新写法只改一处。
|
|
333
|
+
* 原生代理对拼成的星平面格式字符已到的那一半只占一个读法单元,撑不起地平线;原生控制字符逐码元删(不是一串整只消失)。
|
|
271
334
|
*/
|
|
272
335
|
export interface RedactionStream {
|
|
273
336
|
/** 喂入下一块原文。 */
|
|
@@ -283,10 +346,22 @@ export interface RedactionStream {
|
|
|
283
346
|
};
|
|
284
347
|
/** 跳过:已喂入的字节不再交出(没有收件人;tail 面没人在听时),之后的判定仍按整段上下文。 */
|
|
285
348
|
skip(): void;
|
|
286
|
-
/**
|
|
349
|
+
/** 块界:已喂入的字节到此为一块(引擎的 `text_end`)。扫描窗在此尝试前移;之后的 {@link RedactionStream.blockContext} / {@link RedactionStream.blockBytes} 从这里起算。认证扫描抛 ⇒ 原样抛(块界已记、窗不动)。 */
|
|
350
|
+
endBlock(): void;
|
|
351
|
+
/** 本块**之前**的前文(扫描窗内那一截;只作判定上下文,`text_end` 的正文接它判)。 */
|
|
352
|
+
blockContext(): string;
|
|
353
|
+
/** 本块已到的字节(上一个块界之后喂入的)。 */
|
|
354
|
+
blockBytes(): string;
|
|
355
|
+
/** 已喂入的整段原文(扫描窗之前丢出去的前缀也在;读时拼接)。 */
|
|
287
356
|
readonly fed: string;
|
|
357
|
+
/** 已喂入的整段长度(码元)。 */
|
|
358
|
+
readonly length: number;
|
|
288
359
|
}
|
|
289
360
|
export declare function createRedactionStream(): RedactionStream;
|
|
361
|
+
/** 测试可见:同一只流式口,扫描窗永不前移(= 改前的读法:每次扫描都读整段)—— 差分钉用它当参照,断言有窗与无窗交出的帧逐字节相同。 */
|
|
362
|
+
export declare function createRedactionStreamWithoutWindowForTest(): RedactionStream;
|
|
363
|
+
/** 测试可见:同一只流式口,前移点的认证换成调用方给的函数(造「认证扫描抛」的形:真扫描器造不出来;断言抛出后窗与块界的状态一个字节没改)。 */
|
|
364
|
+
export declare function createRedactionStreamWithCertifierForTest(certify: (text: string, q: number) => boolean): RedactionStream;
|
|
290
365
|
/** 测试可见:同一只流式口,未决尾按调用方给的数(比 {@link PENDING_TAIL_UNITS} 小 ⇒ 律被打破的那一形,冲刷时 `diverged` 现形 —— 响亮臂的触发器;生产调用方只有上面那一只)。 */
|
|
291
366
|
export declare function createRedactionStreamWithTailForTest(units: number): RedactionStream;
|
|
292
367
|
/**
|