@sema-agent/server 7.130.0 → 7.132.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 +396 -0
- package/README.md +13 -6
- package/README.zh-CN.md +9 -5
- package/USAGE.md +187 -50
- package/dist/approval-card.d.ts +3 -1
- package/dist/approval-card.js +2 -3
- package/dist/audit.d.ts +7 -10
- package/dist/audit.js +4 -1
- package/dist/auth-bridge.d.ts +4 -0
- package/dist/auth-bridge.js +10 -11
- package/dist/bench/s1/live-deps.js +2 -0
- package/dist/boot/deployment-mods.d.ts +31 -0
- package/dist/boot/deployment-mods.js +26 -0
- package/dist/boot/execution-env.d.ts +1 -1
- package/dist/boot/execution-env.js +19 -6
- package/dist/boot/memory-boundary.d.ts +2 -2
- package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
- package/dist/boot/read-deny-anchor-audit.js +36 -0
- package/dist/boot/resolve-spec.d.ts +1 -5
- package/dist/boot/resolve-spec.js +56 -61
- package/dist/boot/runner-deps.d.ts +19 -8
- package/dist/boot/runner-deps.js +14 -2
- package/dist/boot/session-faces.d.ts +1 -7
- package/dist/boot/stage-02-web-admin-pull.js +9 -1
- package/dist/boot/stage-03-store-backend.d.ts +1 -1
- package/dist/boot/stage-03-store-backend.js +2 -2
- package/dist/boot/stage-04-stores.d.ts +1 -1
- package/dist/boot/stage-05-execution-env.d.ts +4 -4
- package/dist/boot/stage-05-execution-env.js +7 -10
- package/dist/boot/stage-06-runners.d.ts +2 -2
- package/dist/boot/stage-06-runners.js +5 -4
- package/dist/boot/stage-07-capability-layer.d.ts +2 -2
- package/dist/boot/stage-07-capability-layer.js +3 -3
- package/dist/boot/stage-08-reapers.d.ts +2 -2
- package/dist/boot/stage-09-leader.d.ts +3 -9
- package/dist/boot/stage-10-http-server.d.ts +3 -9
- package/dist/boot/stage-10-http-server.js +12 -10
- package/dist/boot/stores.d.ts +1 -1
- package/dist/boot/stores.js +5 -6
- package/dist/boot/web-admin.d.ts +0 -3
- package/dist/boot/web-admin.js +35 -35
- package/dist/brain.js +17 -22
- package/dist/budget.js +5 -4
- package/dist/caller-text-echo.d.ts +20 -0
- package/dist/caller-text-echo.js +24 -0
- package/dist/capabilities/brand-identity.d.ts +26 -0
- package/dist/capabilities/brand-identity.js +27 -0
- package/dist/capabilities/builtin-tools.js +2 -1
- package/dist/capabilities/center-plugins.js +1 -1
- package/dist/capabilities/center-prompts.d.ts +32 -59
- package/dist/capabilities/center-prompts.js +18 -32
- package/dist/capabilities/composite-members.d.ts +1 -0
- package/dist/capabilities/composite-members.js +1 -0
- package/dist/capabilities/engine-capabilities.js +2 -1
- package/dist/capabilities/hands-lane.d.ts +9 -6
- package/dist/capabilities/hands-lane.js +3 -3
- package/dist/capabilities/host-tool-names.d.ts +17 -0
- package/dist/capabilities/host-tool-names.js +15 -0
- package/dist/capabilities/mcp-probe.d.ts +14 -1
- package/dist/capabilities/mcp-probe.js +22 -133
- package/dist/capabilities/repo-tools.js +4 -3
- package/dist/capabilities/scenarios.d.ts +42 -47
- package/dist/capabilities/scenarios.js +19 -35
- package/dist/capabilities/select-environment-tool.js +2 -1
- package/dist/capabilities/send-user-file-tool.d.ts +0 -1
- package/dist/capabilities/send-user-file-tool.js +2 -2
- package/dist/capabilities/skills.d.ts +19 -4
- package/dist/capabilities/skills.js +30 -10
- package/dist/capabilities/tool-defer.js +2 -1
- package/dist/config-catalog.js +22 -11
- package/dist/config-invariants.js +2 -2
- package/dist/config-lkg.d.ts +9 -9
- package/dist/config-lkg.js +20 -4
- package/dist/config-provider.d.ts +3 -1
- package/dist/config-provider.js +14 -6
- package/dist/config-types.d.ts +13 -9
- package/dist/config.d.ts +2 -2
- package/dist/config.js +34 -20
- package/dist/device-ws-protocol.d.ts +1 -1
- package/dist/device-ws-protocol.js +1 -0
- package/dist/elicitation.d.ts +7 -0
- package/dist/elicitation.js +20 -5
- package/dist/env-name-allowlist-knobs.d.ts +12 -2
- package/dist/env-name-allowlist-knobs.js +5 -4
- package/dist/exec-bounds.d.ts +15 -3
- package/dist/exec-bounds.js +4 -0
- package/dist/execution-lane-caps.d.ts +9 -2
- package/dist/execution-lane-caps.js +11 -0
- package/dist/hooks/classic-stations.d.ts +86 -0
- package/dist/hooks/classic-stations.js +27 -0
- package/dist/hooks/hook-llm.d.ts +8 -5
- package/dist/hooks/hook-llm.js +80 -37
- package/dist/hooks/hook-runner.d.ts +273 -75
- package/dist/hooks/hook-runner.js +293 -317
- package/dist/http/admission.d.ts +8 -2
- package/dist/http/admission.js +103 -59
- package/dist/http/approval-sweeps.js +59 -18
- package/dist/http/checkpoint-ctx.d.ts +36 -18
- package/dist/http/checkpoint-ctx.js +14 -10
- package/dist/http/claimed-run.d.ts +13 -0
- package/dist/http/claimed-run.js +15 -0
- package/dist/http/device-placement.js +5 -10
- package/dist/http/dispatch.d.ts +0 -4
- package/dist/http/dispatch.js +6 -10
- package/dist/http/durable-run-leg.d.ts +2 -1
- package/dist/http/durable-run-leg.js +5 -3
- package/dist/http/health-self-report.d.ts +7 -5
- package/dist/http/health-self-report.js +4 -18
- package/dist/http/principal-gate.d.ts +23 -6
- package/dist/http/principal-gate.js +24 -5
- package/dist/http/refusal-body.d.ts +21 -0
- package/dist/http/refusal-body.js +4 -0
- package/dist/http/request-guards.d.ts +27 -0
- package/dist/http/request-guards.js +24 -3
- package/dist/http/resume-legs.d.ts +25 -0
- package/dist/http/resume-legs.js +48 -26
- package/dist/http/routes/approvals-assistant.js +1 -1
- package/dist/http/routes/capabilities.js +7 -17
- package/dist/http/routes/diagnostics.js +1 -1
- package/dist/http/routes/rules.js +2 -2
- package/dist/http/routes/runs.js +13 -17
- package/dist/http/routes/session-sync.js +4 -2
- package/dist/http/routes/sessions.js +23 -11
- package/dist/http/routes/shared-memory.js +2 -13
- package/dist/http/routes/side-query.js +2 -3
- package/dist/http/routes/tasks.js +34 -19
- package/dist/http/scenario-read-face.d.ts +14 -0
- package/dist/http/scenario-read-face.js +5 -0
- package/dist/http/send.d.ts +13 -1
- package/dist/http/send.js +12 -1
- package/dist/http/server.d.ts +37 -23
- package/dist/http/server.js +30 -4
- package/dist/http/stored-body-replay.d.ts +10 -3
- package/dist/http/stored-body-replay.js +27 -6
- package/dist/http/submit-ctx.d.ts +25 -0
- package/dist/http/submit-ctx.js +39 -0
- package/dist/http/wire-types.d.ts +18 -5
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/lane-home-probe.d.ts +43 -0
- package/dist/lane-home-probe.js +35 -0
- package/dist/limit-refusal.d.ts +47 -0
- package/dist/limit-refusal.js +12 -0
- package/dist/main.js +1 -1
- package/dist/mcp-assertion-header.d.ts +3 -11
- package/dist/mcp-assertion-header.js +3 -9
- package/dist/mcp-tool-faces.d.ts +5 -0
- package/dist/mcp-tool-faces.js +5 -1
- package/dist/memory-scope.d.ts +1 -1
- package/dist/model-entry-refusal.d.ts +1 -7
- package/dist/model-provider.d.ts +39 -12
- package/dist/model-provider.js +19 -2
- package/dist/model-route-endpoint.d.ts +52 -12
- package/dist/model-route-endpoint.js +48 -26
- package/dist/model-route-gap.d.ts +5 -4
- package/dist/model-route-gap.js +1 -1
- package/dist/model-select.d.ts +58 -0
- package/dist/model-select.js +31 -0
- package/dist/namespaced-rule-name.d.ts +7 -4
- package/dist/namespaced-rule-name.js +4 -3
- package/dist/observability/cost-taxonomy.d.ts +7 -7
- package/dist/observability/fail-open.d.ts +53 -12
- package/dist/observability/fail-open.js +47 -7
- package/dist/observability/metrics.js +3 -1
- package/dist/observability/prompt-manifest.d.ts +47 -82
- package/dist/observability/prompt-manifest.js +119 -17
- package/dist/observability/run-terminal.js +14 -6
- package/dist/observability/secret-env-scrub.d.ts +13 -1
- package/dist/observability/secret-env-scrub.js +13 -1
- package/dist/observability/tool-trace.d.ts +16 -21
- package/dist/observability/tool-trace.js +51 -42
- package/dist/per-task-image.d.ts +7 -1
- package/dist/per-task-image.js +3 -3
- package/dist/plain-string-record.d.ts +25 -0
- package/dist/plain-string-record.js +32 -0
- package/dist/plugins/blob-backend.d.ts +68 -13
- package/dist/plugins/blob-backend.js +53 -10
- package/dist/plugins/checkpoint-store-sql.d.ts +14 -4
- package/dist/plugins/checkpoint-store-sql.js +39 -26
- package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
- package/dist/plugins/k8s-bg-scripts.js +22 -0
- package/dist/plugins/local-checkpoint-store.js +5 -2
- package/dist/plugins/local-session-store.js +3 -3
- package/dist/plugins/one-time-migrations.d.ts +147 -91
- package/dist/plugins/one-time-migrations.js +372 -208
- package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
- package/dist/plugins/permission-rule-store-sql.js +4 -18
- package/dist/plugins/pg-session-storage.d.ts +4 -5
- package/dist/plugins/pg-session-storage.js +7 -17
- package/dist/plugins/remote-env-adb.d.ts +6 -0
- package/dist/plugins/remote-env-adb.js +9 -4
- package/dist/plugins/remote-env-device.js +3 -0
- package/dist/plugins/remote-env-e2b.d.ts +1 -1
- package/dist/plugins/remote-env-e2b.js +21 -9
- package/dist/plugins/remote-env-host.d.ts +9 -9
- package/dist/plugins/remote-env-host.js +10 -32
- package/dist/plugins/remote-env-k8s.d.ts +95 -26
- package/dist/plugins/remote-env-k8s.js +265 -90
- package/dist/plugins/remote-env-local-docker.d.ts +20 -1
- package/dist/plugins/remote-env-local-docker.js +77 -9
- package/dist/plugins/remote-env-ssh.d.ts +15 -0
- package/dist/plugins/remote-env-ssh.js +109 -3
- package/dist/plugins/remote-shell.d.ts +0 -1
- package/dist/plugins/remote-shell.js +1 -2
- package/dist/plugins/retention-store-sql.js +6 -2
- package/dist/plugins/schema-consistency.d.ts +54 -0
- package/dist/plugins/schema-consistency.js +52 -0
- package/dist/plugins/session-epoch-anchor.d.ts +13 -0
- package/dist/plugins/session-epoch-anchor.js +23 -0
- package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
- package/dist/plugins/shared-memory-store-sql.js +5 -16
- package/dist/plugins/sql-driver.d.ts +141 -0
- package/dist/plugins/sql-driver.js +115 -1
- package/dist/plugins/sql-errors.d.ts +41 -0
- package/dist/plugins/sql-errors.js +36 -0
- package/dist/plugins/store-backend.js +2 -1
- package/dist/plugins/tidb-session-storage.d.ts +7 -11
- package/dist/plugins/tidb-session-storage.js +6 -16
- package/dist/plugins/tidb-session-store.js +1 -1
- package/dist/prompts-domain-validate.d.ts +17 -61
- package/dist/prompts-domain-validate.js +9 -119
- package/dist/question.d.ts +18 -9
- package/dist/question.js +21 -13
- package/dist/request-key-closure.d.ts +4 -4
- package/dist/request-key-closure.js +18 -13
- package/dist/rule-entry-list.d.ts +134 -24
- package/dist/rule-entry-list.js +162 -30
- package/dist/run-local.d.ts +3 -3
- package/dist/run-local.js +26 -25
- package/dist/runs.d.ts +48 -2
- package/dist/runs.js +61 -2
- package/dist/server-secret-env.d.ts +44 -18
- package/dist/server-secret-env.js +49 -8
- package/dist/session-incarnation.d.ts +15 -5
- package/dist/session-incarnation.js +16 -9
- package/dist/session-titler.js +12 -2
- package/dist/spec-fields.d.ts +34 -18
- package/dist/spec-fields.js +46 -53
- package/dist/sql-engine-posture.d.ts +29 -4
- package/dist/sql-engine-posture.js +36 -1
- package/dist/stored-request-hooks-m20.d.ts +23 -0
- package/dist/stored-request-hooks-m20.js +124 -0
- package/dist/stored-request-tool-axes-m19.d.ts +20 -5
- package/dist/stored-request-tool-axes-m19.js +30 -2
- package/dist/task-a2a.d.ts +9 -1
- package/dist/task-a2a.js +73 -47
- package/dist/task-mcp.d.ts +54 -102
- package/dist/task-mcp.js +194 -92
- package/dist/task-settings.d.ts +47 -25
- package/dist/task-settings.js +46 -61
- package/dist/text-bidi.d.ts +3 -46
- package/dist/text-bidi.js +3 -3
- package/dist/tool-approval.d.ts +1 -1
- package/dist/trace/core-keyset-guard.d.ts +24 -4
- package/dist/trace/engine-notice-wire.d.ts +11 -3
- package/dist/trace/engine-notice-wire.js +8 -1
- package/dist/trace/ledger-events.d.ts +3 -1
- package/dist/trace/ledger-sink.d.ts +29 -0
- package/dist/trace/ledger-sink.js +15 -1
- package/dist/trace/model-segment.js +1 -1
- package/dist/trace/project.d.ts +25 -6
- package/dist/trace/project.js +68 -22
- package/dist/trace/wire-projection-faces.d.ts +80 -2
- package/dist/trace/wire-projection-faces.js +23 -1
- package/dist/user-authored-text.d.ts +7 -0
- package/dist/user-authored-text.js +3 -0
- package/dist/web-admin-client/apply-effective.js +10 -5
- package/dist/web-admin-client/candidate-gate.d.ts +6 -6
- package/dist/web-admin-client/candidate-gate.js +3 -3
- package/dist/web-admin-client/http-client.js +0 -6
- package/dist/web-admin-client/read-warnings.d.ts +13 -0
- package/dist/web-admin-client/read-warnings.js +10 -0
- package/dist/web-admin-client/skills-mcp.d.ts +3 -0
- package/dist/web-admin-client/skills-mcp.js +9 -6
- package/dist/web-admin-client/types.d.ts +3 -4
- package/dist/workspace-cache.d.ts +35 -0
- package/dist/workspace-cache.js +36 -0
- package/dist/workspace-space.d.ts +3 -2
- package/dist/workspace-space.js +2 -0
- package/docs/DEVICE-EXECUTOR-PROTOCOL.md +8 -1
- package/package.json +4 -4
- package/scripts/drain-check-local.mjs +37 -3
- package/scripts/drain-check.mysql.sql +30 -2
- package/scripts/drain-check.pg.sql +29 -2
- package/dist/capabilities/memory-notice.d.ts +0 -138
- package/dist/capabilities/memory-notice.js +0 -64
- package/dist/capabilities/prompt.d.ts +0 -17
- package/dist/capabilities/prompt.js +0 -6
- package/dist/mcp-content-origin.d.ts +0 -34
- package/dist/mcp-content-origin.js +0 -10
- package/dist/tool-axis-words.d.ts +0 -27
- package/dist/tool-axis-words.js +0 -9
- package/dist/wire-name-bound.d.ts +0 -14
- package/dist/wire-name-bound.js +0 -13
package/dist/task-settings.d.ts
CHANGED
|
@@ -47,9 +47,10 @@
|
|
|
47
47
|
* - (`hooks` NO LONGER deferred either — 轴B #2 注释保鲜:applied 形已接线(本文件 hooks 分片 +
|
|
48
48
|
* main.ts 单用户闸),仅 malformed 才报 deferred;旧「需要 remote hook-runner」是接线前拍照。)
|
|
49
49
|
*/
|
|
50
|
-
import { type ExecutionEnv, type TaskSpec, type ThinkingLevel, type ToolPolicy, type
|
|
51
|
-
import type { HooksConfig } from "@sema-agent/settings-schema/hooks";
|
|
50
|
+
import { type PathRuleBases, type ExecutionEnv, type TaskSpec, type ThinkingLevel, type ToolPolicy, type PermissionMode } from "@sema-agent/core";
|
|
52
51
|
import { type KeyClosureIssue } from "./request-key-closure.js";
|
|
52
|
+
import { type RunnableHooksConfig } from "./hooks/hook-runner.js";
|
|
53
|
+
import type { StoredHooksRereadM20 } from "./stored-request-hooks-m20.js";
|
|
53
54
|
import { type EntryPermissionMode } from "./runtime-governance.js";
|
|
54
55
|
/**
|
|
55
56
|
* 请求面 `permissionMode` 的闭集 = core `PERMISSION_MODES` **全集**(顶层 `permissionMode` / `settings.permissions.defaultMode` /
|
|
@@ -213,10 +214,10 @@ export interface ParsedTaskSettings {
|
|
|
213
214
|
* orthogonal axes — `thinking:"max"` (the reasoning axis) + `selfOrchestration:true` (the orchestration axis,
|
|
214
215
|
* through its existing fail-closed gate). NOT a new mechanism; just a preset that fans out to existing spec fields. */
|
|
215
216
|
ultracode?: boolean;
|
|
216
|
-
/** hooks hook-runner(阶段一)
|
|
217
|
+
/** hooks hook-runner(阶段一):经 `parseHooksConfig`(契约包分类器 + 服务侧上限 + 本仓会跑的条目类型)判过的 hooks 配置。像 shellEnv 一样
|
|
217
218
|
* 这里只 PARSE;应用点(main.ts resolveSpec)按单用户闸(`requirePrincipal !== true`)决定翻不翻成
|
|
218
|
-
*
|
|
219
|
-
hooks?:
|
|
219
|
+
* 任务座 `TaskSpec.mods` 上的一张注册 `settings.hooks`——多租户 lane 收到只警告忽略(hook 命令跑在 worker host = class ② 能力授予)。 */
|
|
220
|
+
hooks?: RunnableHooksConfig;
|
|
220
221
|
/** [ref](7.77.0)—— CC settings 同名键:上下文窗口里**留给技能清单**的比例((0,1];CC 默认 0.01 = 1%)。
|
|
221
222
|
* 超预算时引擎把描述裁短、再不够退成 name-only(`cli259.js` 的清单渲染算法),**从不**拒掉一条技能 ——
|
|
222
223
|
* 这正是本版把技能条数/描述两条帽整条退役后的补偿面:per-turn 成本的旋钮在**渲染侧**,不在受理侧。
|
|
@@ -232,6 +233,15 @@ export interface ParseTaskSettingsResult {
|
|
|
232
233
|
/** Sub-fields the caller SENT but this version does not wire(`env`;`hooks` 仅在 MALFORMED 时入列——valid hooks
|
|
233
234
|
* 已是 applied 字段)。Empty when none. */
|
|
234
235
|
deferred: string[];
|
|
236
|
+
/** 一次性迁移 M20(窗口见 `plugins/one-time-migrations.ts` 登记表):存下的 hooks 被唯一读者拒掉、经重读座剥掉点名的键后过了读者 ⇒ 本次读数里 `settings.hooks` 是重读的产物,
|
|
237
|
+
* 并带被剥的坐标(出门形)。缺席 = 没有发生重读。 */
|
|
238
|
+
hooksReread?: {
|
|
239
|
+
readonly stripped: readonly string[];
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
/** `parseTaskSettings` 的可选座:续跑重放腿才有的重读座(一次性迁移 M20;新提交腿与不问 hooks 的读者不递)。 */
|
|
243
|
+
export interface ParseTaskSettingsSeats {
|
|
244
|
+
readonly storedHooksReread?: StoredHooksRereadM20;
|
|
235
245
|
}
|
|
236
246
|
/** Cap on `outputStyle` length — it lands in the system prompt, so it shares the `MAX_SYSTEM_PROMPT_CHARS` (16384)
|
|
237
247
|
* posture (an uncapped prompt body is a per-turn token-cost hole; cross review). Exported so the HTTP layer
|
|
@@ -314,7 +324,7 @@ export declare function taskSettingsKeyIssue(raw: unknown): KeyClosureIssue | nu
|
|
|
314
324
|
* 🔒 **`settings.hooks` 会不会被采纳** —— 全仓**唯一**的车道谓词(S-995,主会话裁):hook 命令跑在 WORKER HOST([ref] class ② 能力授予),所以只有单用户车道
|
|
315
325
|
* (`requirePrincipal !== true`,与 scheduler / backgroundShell / lspHost / MCP 注入同一姿势)采纳;多租户车道收到 hooks **整只忽略**(`task_hooks_ignored`),绝不执行。
|
|
316
326
|
* 三处读它,谁也不许内联 `requirePrincipal`(各写各的 = 迟早漂):
|
|
317
|
-
* · `boot/resolve-spec.ts` —— 装配:不采纳 ⇒
|
|
327
|
+
* · `boot/resolve-spec.ts` —— 装配:不采纳 ⇒ 不铸 `TaskSpec.mods` 的 `settings.hooks` 注册 + 一条 `task_hooks_ignored`;
|
|
318
328
|
* · `http/routes/capabilities.ts` —— 能力位 `taskSettings.hooks`(「says yes ⟺ route works」);
|
|
319
329
|
* · `http/admission.ts` —— fresh 受理面的「别名 matcher 永不命中」判据的**求值深度**:采纳 ⇒ `"regex"`(运行期同一只匹配函数,带资源闸);不采纳 ⇒ `"literal"`
|
|
320
330
|
* (7.112.0 的字面判:零调用方正则执行 —— 受理面是所有车道,租户不能借一只灾难回溯的 matcher 占满事件循环)。
|
|
@@ -333,31 +343,17 @@ export declare function taskHooksHonored(config: {
|
|
|
333
343
|
* 重放也走的宽容层,一个 4xx 在这里会把存量 parked 任务永久砖死;FRESH 提交面由 {@link taskSettingsKeyIssue}
|
|
334
344
|
* 在 `server.ts` prepareSpec 里 400 响亮拒 + 逐字列名。双层姿势与 outputStyle / permissionMode 两处逐字相同。
|
|
335
345
|
*/
|
|
336
|
-
export declare function parseTaskSettings(raw: unknown): ParseTaskSettingsResult;
|
|
346
|
+
export declare function parseTaskSettings(raw: unknown, seats?: ParseTaskSettingsSeats): ParseTaskSettingsResult;
|
|
337
347
|
/** Defensive acceptance of the `appendSystemPrompt` rider ([ref] R2 + codex F2): the HTTP 400 gate (prepareSpec,
|
|
338
348
|
* MAX_SYSTEM_PROMPT_CHARS) only covers FRESH submits — every resume family re-enters resolveSpec on a STORED body,
|
|
339
349
|
* and a pre-1.243 store preserved unknown request keys verbatim (the field was INERT then), so an over-cap legacy
|
|
340
350
|
* value must not become active prompt content after rollout (context exhaustion / spend hole). Over-cap ⇒ dropped +
|
|
341
351
|
* warned — the rider was inert pre-upgrade, so dropping preserves the stored task's prior behavior; a 4xx here would
|
|
342
352
|
* permanently brick that task's resume instead (same defensive posture as parseTaskSettings' outputStyle drop).
|
|
343
|
-
* Cap value = the submit gate's (16384; MAX_SETTINGS_OUTPUT_STYLE_CHARS — both land in the same spec field).
|
|
344
|
-
|
|
345
|
-
*
|
|
346
|
-
|
|
347
|
-
* there. Shared predicate for the submit 400 gate, the resolveSpec resume mirror, and the center-declaration
|
|
348
|
-
* probe — one definition so the three gates can't drift. */
|
|
349
|
-
export declare function hasConstitutionAnchors(text: unknown): boolean;
|
|
350
|
-
/** codex R9 (provider-aware append-less detection): mirrors core's ACTUAL pass-through triggers instead of a raw
|
|
351
|
-
* body-text heuristic — the assembler's migration guard probes (a) `stableBlocks` identity declarations and
|
|
352
|
-
* (b) `stableSystem` OUTPUT for the three anchors; a plain `userSystemPrompt` under the DEFAULT provider (no
|
|
353
|
-
* scenario provider) never triggers it and `core/role.append` is retained, so an anchored systemPrompt there
|
|
354
|
-
* must NOT block/strip a rider (R9 false-positive: unbranded default / scan rejected valid combos). Probing
|
|
355
|
-
* calls the provider hooks with a minimal ctx — server providers (and centerPromptProvider) are pure functions
|
|
356
|
-
* of ctx, and the same hooks run again inside core's assembly; a hook throw = conservative false (core will
|
|
357
|
-
* fail the task loudly on its own). `replaceAll` owns the whole prompt(legacy free-form `system()` 腿已随 core 2.0.0 删除)
|
|
358
|
-
* (REPLACE_ALL_EXCLUDED strips role.append) → append-less true. */
|
|
359
|
-
export declare function providerDropsAppend(provider: PromptProvider | undefined, userSystemPrompt: string | undefined): boolean;
|
|
360
|
-
export declare function acceptAppendSystemPrompt(v: unknown, warn?: (detail: string) => void, packDropsAppend?: boolean): string | undefined;
|
|
353
|
+
* Cap value = the submit gate's (16384; MAX_SETTINGS_OUTPUT_STYLE_CHARS — both land in the same spec field).
|
|
354
|
+
* A well-formed rider always mounts: the engine (core 7.52.0) lands it in its own task-append band whatever the role
|
|
355
|
+
* text is — there is no "already-assembled" pass-through arm left that could drop it. */
|
|
356
|
+
export declare function acceptAppendSystemPrompt(v: unknown, warn?: (detail: string) => void): string | undefined;
|
|
361
357
|
/** [ref]②/codex F2 — what the workflow ask leg needs from the deployment, on EVERY lane. It is name-keyed and
|
|
362
358
|
* fs-independent, so it never had the lane split {@link FsWriteGateWiring} carried (that split is itself gone
|
|
363
359
|
* since [ref] — the sandbox lanes wire a gate of their own shape instead of no gate). */
|
|
@@ -457,6 +453,32 @@ export interface FsWriteGateWiring {
|
|
|
457
453
|
* 本 wiring 的组合点。) */
|
|
458
454
|
isExempt?: (toolName: string, canonicalPath: string) => boolean | Promise<boolean>;
|
|
459
455
|
}
|
|
456
|
+
/**
|
|
457
|
+
* deny / ask 两桶(core 规则编译器读的收紧表)的**问序,单表**:{@link rulePolicyBucketsRefusal} 的两段循环(名字层 + 文法 · `~/` 要 home)都迭代它 ——
|
|
458
|
+
* 两桶都有坏条目时,拒点与存体预判点名同一个桶、说同一句。表里每个词同时是 core 规则的 `behavior`。
|
|
459
|
+
*/
|
|
460
|
+
export declare const RULE_POLICY_BUCKETS: readonly ["ask", "deny"];
|
|
461
|
+
export type RulePolicyBucket = (typeof RULE_POLICY_BUCKETS)[number];
|
|
462
|
+
/**
|
|
463
|
+
* deny / ask 两桶的**完整规则判**,唯一一只(拒点 {@link rejectUnmatchableSettingsNames} 与存体预判 `http/stored-body-replay.ts` 同调):
|
|
464
|
+
* ② 按 {@link RULE_POLICY_BUCKETS} 的序逐桶问 `unmatchableToolNamesRefusal`(名字层 + core 规则文法);③ 都过了,再逐桶判 `~/` 形要 home 的那一拒。第一个坏处答 `{ bucket, message }`。
|
|
465
|
+
* 入参:桶、{@link RulePolicyBases}。**home 同源**:拒点的 home 是 `resolve-spec.ts` 的 `laneHomeBase()` 经 `executionLaneHomeDir(config)` 算出的,预判传同一个函数对同一份部署配置算出的。
|
|
466
|
+
* **声明给文法的基**只有拒点有(根 + home 的并集,执行车道才知道根):core 的规则文法对**没声明**的基不下判词(见 `config.ts` `uncompilableRuleGuidance`),所以预判什么也不声明、两腿逐字同句;
|
|
467
|
+
* 预判不能把 home 当「半个基」声明给文法 —— core 的路径族只从根推,缺根时一个合法的 Windows 形 home 会按默认族被判 `unsupported.path_base`(V6-k)。
|
|
468
|
+
* ③ 排在最后:一条同时文法不成立又带 `~/` 的规则,先说文法(补上 home 它仍被文法拒,先说 home 是误导)。
|
|
469
|
+
*/
|
|
470
|
+
export interface RulePolicyBases {
|
|
471
|
+
/** 声明给 core 规则文法的路径基(这条 task 的根 + home):拒点才有;存体预判不声明。 */
|
|
472
|
+
readonly declared?: PathRuleBases;
|
|
473
|
+
/** 执行环境的 home(`~/` 形规则的前提);这个部署解不出 ⇒ 缺席。 */
|
|
474
|
+
readonly home?: string;
|
|
475
|
+
}
|
|
476
|
+
export declare function rulePolicyBucketsRefusal(permissions: Readonly<Partial<Record<RulePolicyBucket, readonly string[]>>>, bases: RulePolicyBases): {
|
|
477
|
+
readonly bucket: RulePolicyBucket;
|
|
478
|
+
readonly message: string;
|
|
479
|
+
} | undefined;
|
|
480
|
+
/** 请求的 settings 编不成生效的规则 / 有永远不生效的条目 ⇒ 422 的句首(三只桶同一个出口;`resolveSpec` 的拒点与存体重放预判的 409 句子同用这一个,不各写一份)。 */
|
|
481
|
+
export declare const REQUEST_SETTINGS_REFUSAL_PREFIX = "request settings cannot be applied as written: ";
|
|
460
482
|
export declare function deriveSettingsPolicy(settings: ParsedTaskSettings, gate?: FsWriteGateWiring, workflowGate?: WorkflowGateWiring): {
|
|
461
483
|
toolPolicy?: ToolPolicy;
|
|
462
484
|
};
|
package/dist/task-settings.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { combinePolicies, createFsWriteGatePolicy, parseRuleText, resolveReasoningProfile, rankOf, isThinkingLevel,
|
|
1
|
+
import { combinePolicies, createFsWriteGatePolicy, parseRuleText, resolveReasoningProfile, rankOf, isThinkingLevel, RUN_WORKFLOW_TOOL_NAME, PERMISSION_MODES, isPermissionMode, ruleToolGrammarOf, } from "@sema-agent/core";
|
|
2
2
|
import { unmatchableToolNamesRefusal } from "./config.js";
|
|
3
3
|
import { MAX_PERMISSION_RULES_PER_LIST, createRuleListPolicy } from "./permission-rule-list.js";
|
|
4
4
|
import { allowLayerEntryCountIssue, describeAllowLayerOverCap, ruleEntryListShapeOk } from "./rule-entry-list.js";
|
|
5
|
+
import { limitRefusal } from "./limit-refusal.js";
|
|
5
6
|
import { tightenGoverned } from "./governance-overrides.js";
|
|
6
7
|
import { MAX_KEY_ECHO, keyClosureClause, scanKeyClosure } from "./request-key-closure.js";
|
|
7
8
|
import { parseHooksConfig } from "./hooks/hook-runner.js";
|
|
@@ -93,8 +94,9 @@ function bucketIssueMessage(f, rule) {
|
|
|
93
94
|
case "over_cap":
|
|
94
95
|
switch (rule) {
|
|
95
96
|
case "rule_policy":
|
|
96
|
-
return (
|
|
97
|
-
|
|
97
|
+
return limitRefusal(f.field, "entries", f.count, f.cap, {
|
|
98
|
+
tail: "Refused rather than truncated: a truncated list silently drops the rules past the cap, and a dropped deny / ask rule is a tightening that never happened. Merge rules into broader patterns or trim the list",
|
|
99
|
+
}).message;
|
|
98
100
|
case "allow_layer":
|
|
99
101
|
return describeAllowLayerOverCap(f.field, f.count);
|
|
100
102
|
}
|
|
@@ -138,7 +140,7 @@ export function settingsPermissionBucketIssue(perms) {
|
|
|
138
140
|
case "allow_layer": {
|
|
139
141
|
const over = allowLayerEntryCountIssue(field, v);
|
|
140
142
|
if (over !== undefined)
|
|
141
|
-
fields = { field, reason: "over_cap", count: over.count, cap: over.cap };
|
|
143
|
+
fields = { field, reason: "over_cap", count: over.facts.count, cap: over.facts.cap };
|
|
142
144
|
else if (!ruleEntryListShapeOk(v))
|
|
143
145
|
fields = { field, reason: "bad_entry", index: v.findIndex((x) => typeof x !== "string") };
|
|
144
146
|
break;
|
|
@@ -193,18 +195,26 @@ export function taskSettingsKeyIssue(raw) {
|
|
|
193
195
|
export function taskHooksHonored(config) {
|
|
194
196
|
return config.requirePrincipal !== true;
|
|
195
197
|
}
|
|
196
|
-
export function parseTaskSettings(raw) {
|
|
198
|
+
export function parseTaskSettings(raw, seats = {}) {
|
|
197
199
|
if (raw === null || raw === undefined || typeof raw !== "object")
|
|
198
200
|
return { deferred: [] };
|
|
199
201
|
const s = raw;
|
|
200
202
|
const deferred = [];
|
|
201
203
|
let hooksConfig;
|
|
204
|
+
let hooksReread;
|
|
202
205
|
if (s.hooks !== undefined && s.hooks !== null) {
|
|
203
206
|
const parsedHooks = parseHooksConfig(s.hooks);
|
|
204
207
|
if (parsedHooks.config)
|
|
205
208
|
hooksConfig = parsedHooks.config;
|
|
206
|
-
else
|
|
207
|
-
|
|
209
|
+
else {
|
|
210
|
+
const reread = seats.storedHooksReread?.(s.hooks);
|
|
211
|
+
if (reread !== undefined) {
|
|
212
|
+
hooksConfig = reread.config;
|
|
213
|
+
hooksReread = { stripped: reread.stripped };
|
|
214
|
+
}
|
|
215
|
+
else
|
|
216
|
+
deferred.push("hooks");
|
|
217
|
+
}
|
|
208
218
|
}
|
|
209
219
|
const shellEnv = cleanEnvMap(s.env);
|
|
210
220
|
if (s.env !== undefined && s.env !== null && shellEnv === undefined)
|
|
@@ -252,36 +262,9 @@ export function parseTaskSettings(raw) {
|
|
|
252
262
|
const maxDesc = s.skillListingMaxDescChars;
|
|
253
263
|
if (skillListingMaxDescOk(maxDesc))
|
|
254
264
|
out.skillListingMaxDescChars = maxDesc;
|
|
255
|
-
return { settings: Object.keys(out).length > 0 ? out : undefined, deferred };
|
|
256
|
-
}
|
|
257
|
-
export function hasConstitutionAnchors(text) {
|
|
258
|
-
return typeof text === "string" && text.includes(CYBER_RISK) && text.includes(URL_SAFETY) && text.includes(HARNESS_SECTION_ANCHOR);
|
|
259
|
-
}
|
|
260
|
-
export function providerDropsAppend(provider, userSystemPrompt) {
|
|
261
|
-
if (!provider)
|
|
262
|
-
return false;
|
|
263
|
-
if (provider.replaceAll === true)
|
|
264
|
-
return true;
|
|
265
|
-
const ctx = { userSystemPrompt, tools: [], memoryEnabled: false, consolidationEnabled: false };
|
|
266
|
-
if (provider.stableBlocks) {
|
|
267
|
-
try {
|
|
268
|
-
return provider.stableBlocks(ctx).some((d) => d.slot === "identity" && hasConstitutionAnchors(d.text));
|
|
269
|
-
}
|
|
270
|
-
catch {
|
|
271
|
-
return false;
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (provider.stableSystem) {
|
|
275
|
-
try {
|
|
276
|
-
return hasConstitutionAnchors(provider.stableSystem(ctx));
|
|
277
|
-
}
|
|
278
|
-
catch {
|
|
279
|
-
return false;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
return false;
|
|
265
|
+
return { settings: Object.keys(out).length > 0 ? out : undefined, deferred, ...(hooksReread !== undefined ? { hooksReread } : {}) };
|
|
283
266
|
}
|
|
284
|
-
export function acceptAppendSystemPrompt(v, warn
|
|
267
|
+
export function acceptAppendSystemPrompt(v, warn) {
|
|
285
268
|
if (v === undefined)
|
|
286
269
|
return undefined;
|
|
287
270
|
if (typeof v !== "string" || v.length === 0) {
|
|
@@ -292,10 +275,6 @@ export function acceptAppendSystemPrompt(v, warn, packDropsAppend) {
|
|
|
292
275
|
warn?.(`appendSystemPrompt dropped: ${v.length} chars exceeds the ${MAX_SETTINGS_OUTPUT_STYLE_CHARS} cap (pre-cap stored body on a resume leg?)`);
|
|
293
276
|
return undefined;
|
|
294
277
|
}
|
|
295
|
-
if (packDropsAppend === true) {
|
|
296
|
-
warn?.("appendSystemPrompt dropped: the effective prompt pack cannot mount the append rider (assembled-identity/stableSystem pass-through, replaceAll, or legacy provider — no core/role.append section)");
|
|
297
|
-
return undefined;
|
|
298
|
-
}
|
|
299
278
|
return v;
|
|
300
279
|
}
|
|
301
280
|
const RULE_SOURCE_BY_BEHAVIOR = { ask: "settings.permissions.ask", deny: "settings.permissions.deny" };
|
|
@@ -321,33 +300,39 @@ function createWorkflowAskPolicy(isExempt) {
|
|
|
321
300
|
};
|
|
322
301
|
}
|
|
323
302
|
function rejectUnmatchableSettingsNames(perms, pathBases) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
303
|
+
const refused = rulePolicyBucketsRefusal(perms, { ...(pathBases !== undefined ? { declared: pathBases } : {}), ...(pathBases?.home !== undefined ? { home: pathBases.home } : {}) });
|
|
304
|
+
if (refused !== undefined)
|
|
305
|
+
throw new Error(refused.message);
|
|
306
|
+
}
|
|
307
|
+
export const RULE_POLICY_BUCKETS = ["ask", "deny"];
|
|
308
|
+
export function rulePolicyBucketsRefusal(permissions, bases) {
|
|
309
|
+
for (const bucket of RULE_POLICY_BUCKETS) {
|
|
310
|
+
const names = permissions[bucket];
|
|
311
|
+
if (!names)
|
|
312
|
+
continue;
|
|
313
|
+
const unmatchable = unmatchableToolNamesRefusal(`permissions.${bucket}`, names, { consumer: "rule-policy", behavior: bucket, ...(bases.declared !== undefined ? { pathBases: bases.declared } : {}) });
|
|
314
|
+
if (unmatchable !== undefined)
|
|
315
|
+
return { bucket, message: unmatchable.message };
|
|
316
|
+
}
|
|
317
|
+
if (bases.home === undefined) {
|
|
318
|
+
for (const bucket of RULE_POLICY_BUCKETS) {
|
|
319
|
+
const field = `permissions.${bucket}`;
|
|
320
|
+
for (const name of permissions[bucket] ?? []) {
|
|
321
|
+
const parsed = parseRuleText(name, bucket);
|
|
331
322
|
if ("rule" in parsed && ruleToolGrammarOf(parsed.rule.tool) === "path" && parsed.rule.command.startsWith("~/")) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
323
|
+
return {
|
|
324
|
+
bucket,
|
|
325
|
+
message: `${field} has a home-relative path rule (${name}) but this deployment cannot resolve the EXECUTION environment's home directory — ` +
|
|
326
|
+
`the engine never guesses one: without a home base the rule resolves to "unreadable" and every matching call stops to ask, so it guards nothing. ` +
|
|
327
|
+
`Spell the path absolutely (${"Edit(//abs/path/**)"} form), declare the lane's home with REMOTE_EXEC_HOME_DIR, or run the task on a lane whose home this worker knows.`,
|
|
328
|
+
};
|
|
335
329
|
}
|
|
336
330
|
}
|
|
337
331
|
}
|
|
338
332
|
}
|
|
339
|
-
|
|
340
|
-
["permissions.ask", perms.ask, { consumer: "rule-policy", behavior: "ask", ...(pathBases !== undefined ? { pathBases } : {}) }],
|
|
341
|
-
["permissions.deny", perms.deny, { consumer: "rule-policy", behavior: "deny", ...(pathBases !== undefined ? { pathBases } : {}) }],
|
|
342
|
-
];
|
|
343
|
-
for (const [field, names, judgment] of judgments) {
|
|
344
|
-
if (!names)
|
|
345
|
-
continue;
|
|
346
|
-
const unmatchable = unmatchableToolNamesRefusal(field, names, judgment);
|
|
347
|
-
if (unmatchable !== undefined)
|
|
348
|
-
throw new Error(unmatchable.message);
|
|
349
|
-
}
|
|
333
|
+
return undefined;
|
|
350
334
|
}
|
|
335
|
+
export const REQUEST_SETTINGS_REFUSAL_PREFIX = "request settings cannot be applied as written: ";
|
|
351
336
|
export function deriveSettingsPolicy(settings, gate, workflowGate) {
|
|
352
337
|
const perms = settings.permissions;
|
|
353
338
|
if (!perms)
|
package/dist/text-bidi.d.ts
CHANGED
|
@@ -1,50 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* ## 为什么有这个文件
|
|
5
|
-
* 同一条字符类此前在本仓有两份逐字手抄(`session-titler.ts` 的 `sanitizeTitle`、
|
|
6
|
-
* `plugins/send-user-file.ts` 的 `sanitizeSendFileName`),第三份还要给审批卡的 bidi **在场检测**用。
|
|
7
|
-
* 这是一条安全语义上的词表(它划定「人眼看到的顺序可能不是字节顺序」那一族码点),三份手抄必然漂移 ——
|
|
8
|
-
* 单一属主的纪律与 `APPROVAL_GATE_KINDS` 同源(CLAUDE.md 硬条款:词表是闭集,不许散落副本)。
|
|
9
|
-
*
|
|
10
|
-
* ## 两条类刻意分开(**别合并**)
|
|
11
|
-
* · {@link BIDI_CONTROL_CHARS} —— **只有** bidi 一族(LRM/RLM、嵌入与覆写、隔离符)。它是**检测**用的:
|
|
12
|
-
* 问的是「这串文本里有没有能让人眼读到与执行顺序不同的东西」。C0 控制符不属于这一问 —— 一条 Bash
|
|
13
|
-
* 命令里出现换行、一段 diff 里出现制表符都是**正常**的,把它们算进来会让检测位恒为真、从而毫无判别力。
|
|
14
|
-
* · {@link CONTROL_AND_BIDI_CHARS} —— bidi ∪ C0/DEL,**清洗**用的(标题、文件名这类要落一行的短串)。
|
|
15
|
-
* 清洗面比检测面宽是对的:那两处要的是「只留可打印的一行」。
|
|
16
|
-
*
|
|
17
|
-
* ## 案锚
|
|
18
|
-
* Trojan Source([ref]②;`docs/DISEASE-SHAPES.md` 的不可见字符条):字面控制符让**人审与机器门看到
|
|
19
|
-
* 两份不同的文本**。审批卡是本仓唯一一处「把模型写的命令交给人眼判断」的面,所以它需要的是**披露**
|
|
20
|
-
* (告诉壳「这串里有 bidi」),不是清洗 —— 清洗会改掉即将被执行的那串字节,让卡上显示的与真正跑的不是
|
|
21
|
-
* 同一个东西,那比不披露更坏。
|
|
22
|
-
*/
|
|
23
|
-
/**
|
|
24
|
-
* bidi 一族的字符类**内容**(不含方括号,便于拼进更大的类)。
|
|
25
|
-
*
|
|
26
|
-
* 逐字 = Unicode 的 `Bidi_Control=Yes` **全集**(12 个码点),不是「常见的那几个」:
|
|
27
|
-
* · U+061C = ALM(Arabic Letter Mark);U+200E/200F = LRM/RLM;
|
|
28
|
-
* · U+202A-202E = 嵌入/覆写族(含 RLO);U+2066-2069 = 隔离符族。
|
|
29
|
-
*
|
|
30
|
-
* 🔴 **U+061C 是 codex 交叉复审 [medium] 验真后补的**:首版漏了它 —— 而漏一个码点在**检测**面上不是
|
|
31
|
-
* 「覆盖率差一点」,是一条完整的跳过路(只用 ALM 构造的输入让在场位缺席,壳于是照常按干净渲染)。
|
|
32
|
-
* 交叉锚:core 自己的 `APPROVER_REFUSED_CHARS_RE`(`dist/core/tool-policy.js`)同样含 `\\u061c`。
|
|
33
|
-
*
|
|
34
|
-
* ⚠️ 与 core 那只**更宽**的集合的差额如实登记(刻意,不是漏):core 还含 C1(`\\u0080-\\u009f`)与
|
|
35
|
-
* U+2028/U+2029(行/段分隔符)。那两族**不是 bidi**(不影响阅读方向),属于「不可打印 / 换行伪装」的
|
|
36
|
-
* 另一问;本类是 bidi 专用,混进来会让 {@link hasBidiControls} 的语义从「方向可能骗你」滑成「有奇怪
|
|
37
|
-
* 字符」。清洗面要不要跟着加宽是另一件(见 {@link CONTROL_AND_BIDI_CHARS} 的注)。
|
|
38
|
-
*/
|
|
39
|
-
export declare const BIDI_CONTROL_CHARS = "\\u061c\\u200e\\u200f\\u202a-\\u202e\\u2066-\\u2069";
|
|
40
|
-
/** bidi ∪ C0/DEL —— **清洗**面用(见文件头注:清洗面比检测面宽是刻意的)。
|
|
41
|
-
* ⚠️ 仍**不含** C1(`-`)与 U+2028/U+2029:加宽是行为变更、要各自的判据支撑,不搭本批的车
|
|
42
|
-
* (登记在此,别当成漏)。两处存量消费方(标题、文件名)较其手抄前身**多剥一枚 U+061C**
|
|
43
|
-
* (经 {@link BIDI_CONTROL_CHARS} 内插带入)—— 对本清洗类是有意收紧,merge-rescan 745 验真后
|
|
44
|
-
* 钉在两消费方各自的测试里;除此之外与手抄前身逐字同集。 */
|
|
45
|
-
export declare const CONTROL_AND_BIDI_CHARS = "\\u0000-\\u001f\\u007f\\u061c\\u200e\\u200f\\u202a-\\u202e\\u2066-\\u2069";
|
|
1
|
+
/** bidi ∪ C0/DEL —— **清洗**面用(见文件头注:清洗面比检测面宽是刻意的)。bidi 半场内插 core 的类,C0/DEL 半场是本仓清洗面自己的。 */
|
|
2
|
+
export declare const CONTROL_AND_BIDI_CHARS = "\\u0000-\\u001f\\u007f\\u061C\\u200E\\u200F\\u202A-\\u202E\\u2066-\\u2069";
|
|
46
3
|
/** 清洗用的全局正则(`String.replace` 会在返回前把 `lastIndex` 归零,故模块级常量可安全复用)。 */
|
|
47
4
|
export declare const CONTROL_AND_BIDI_STRIP_RE: RegExp;
|
|
48
|
-
/** 这串文本里**有没有** bidi
|
|
5
|
+
/** 这串文本里**有没有** bidi 控制符(判官 = core 的 {@link carriesBidiControls})。纯谓词:不改一个字节、不做任何清洗(理由见文件头注)。 */
|
|
49
6
|
export declare function hasBidiControls(text: string): boolean;
|
|
50
7
|
//# sourceMappingURL=text-bidi.d.ts.map
|
package/dist/text-bidi.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
import { BIDI_CONTROL_CHARS, carriesBidiControls } from "@sema-agent/core";
|
|
2
2
|
export const CONTROL_AND_BIDI_CHARS = `\\u0000-\\u001f\\u007f${BIDI_CONTROL_CHARS}`;
|
|
3
3
|
export const CONTROL_AND_BIDI_STRIP_RE = new RegExp(`[${CONTROL_AND_BIDI_CHARS}]`, "g");
|
|
4
|
-
const
|
|
4
|
+
const WHOLE_TEXT_SCAN = { maxNodes: 1, maxChars: Number.MAX_SAFE_INTEGER };
|
|
5
5
|
export function hasBidiControls(text) {
|
|
6
|
-
return
|
|
6
|
+
return carriesBidiControls(text, WHOLE_TEXT_SCAN);
|
|
7
7
|
}
|
|
8
8
|
//# sourceMappingURL=text-bidi.js.map
|
package/dist/tool-approval.d.ts
CHANGED
|
@@ -509,7 +509,7 @@ export interface ToolApprovalFrame {
|
|
|
509
509
|
readRootCandidate?: ReadRootGrantCandidate;
|
|
510
510
|
/**
|
|
511
511
|
* **E-14**([ref]② Trojan Source 族;**ADDITIVE**,`"tool_approval"` only)—— 这只 ask 的**工具输入**
|
|
512
|
-
* (`AskRequest.args`)里含 bidi 控制符(LRM/RLM
|
|
512
|
+
* (`AskRequest.args`)里含 bidi 控制符(LRM/RLM、嵌入/覆写、隔离符;字符类与在场谓词的属主是 core 的 `BIDI_CONTROL_CHARS` / `carriesBidiControls`,经 `text-bidi.ts` 的 `hasBidiControls` 取)。
|
|
513
513
|
*
|
|
514
514
|
* 🔴 **真才带,缺席绝不编 `false`**(与 `governanceForced`/`requiresRealApproval` 同形)。缺席的含义是
|
|
515
515
|
* 「没扫到」——它同时覆盖「真的没有」与「args 序列化不了(循环引用)所以扫不了」两形,消费端**禁**把
|
|
@@ -50,7 +50,7 @@ type _GuardAskReverse = AssertAllKeysHandled<Exclude<AskProjected | AskExcluded,
|
|
|
50
50
|
type AskFrameServerMinted = "type" | "approvalId" | "argsOmitted" | "outcome" | "governanceForced" | "expiresAtMs" | "expiresInMs" | "serverNowMs" | "parked" | "cause" | "inputHasBidi" | "rememberRefused";
|
|
51
51
|
type _GuardAskFrame = AssertAllKeysHandled<Exclude<keyof ToolApprovalFrame, AskProjected | AskFrameServerMinted>>;
|
|
52
52
|
type _GuardAskFrameReverse = AssertAllKeysHandled<Exclude<AskProjected | AskFrameServerMinted, keyof ToolApprovalFrame>>;
|
|
53
|
-
type TaskEventHandled = "text_delta" | "reasoning_delta" | "tool_start" | "tool_end" | "turn_end" | "compacted" | "diagnostics" | "message_committed" | "status" | "task_notification" | "task_progress" | "steering_injected" | "workspace_changed" | "done" | "context_usage" | "compaction_outcome" | "human_input" | "wiring_manifest" | "text_end" | "tool_roster_delta" | "tool_progress" | "tool_disclosure" | "task_started";
|
|
53
|
+
type TaskEventHandled = "text_delta" | "reasoning_delta" | "tool_start" | "tool_end" | "turn_end" | "compacted" | "diagnostics" | "message_committed" | "status" | "task_notification" | "task_progress" | "steering_injected" | "workspace_changed" | "done" | "context_usage" | "compaction_outcome" | "human_input" | "wiring_manifest" | "text_end" | "tool_roster_delta" | "tool_progress" | "tool_disclosure" | "task_started" | "compaction_started";
|
|
54
54
|
type _GuardTaskEvent = AssertAllKeysHandled<Exclude<TaskEvent["type"], TaskEventHandled>>;
|
|
55
55
|
type _GuardTaskEventReverse = AssertAllKeysHandled<Exclude<TaskEventHandled, TaskEvent["type"]>>;
|
|
56
56
|
type MailboxProjected = "seq" | "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
|
|
@@ -59,7 +59,7 @@ type _GuardMailboxReverse = AssertAllKeysHandled<Exclude<MailboxProjected, keyof
|
|
|
59
59
|
type MailboxAppendProjected = "from" | "content" | "sentAt" | "hopChain" | "peerMeta";
|
|
60
60
|
type _GuardMailboxAppend = AssertAllKeysHandled<Exclude<keyof MailboxAppendMessage, MailboxAppendProjected>>;
|
|
61
61
|
type _GuardMailboxAppendReverse = AssertAllKeysHandled<Exclude<MailboxAppendProjected, keyof MailboxAppendMessage>>;
|
|
62
|
-
type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools" | "
|
|
62
|
+
type WiringSectionProjected = "schemaVersion" | "leg" | "ask" | "question" | "interaction" | "elicit" | "parkLane" | "session" | "fleet" | "permissionRules" | "modelGate" | "autoMode" | "mcp" | "tools" | "mods" | "lsp" | "hands" | "writeProtection" | "teamRole" | "fileHistory";
|
|
63
63
|
type WiringSectionExcluded = (typeof import("./wire-projection-faces.js").WIRE_PROJECTION_FACES)["wiring_manifest_tenant"]["excluded"][number];
|
|
64
64
|
type _GuardWiringSections = AssertAllKeysHandled<Exclude<keyof WiringManifest, WiringSectionProjected | WiringSectionExcluded>>;
|
|
65
65
|
type _GuardWiringSectionsReverse = AssertAllKeysHandled<Exclude<WiringSectionProjected | WiringSectionExcluded, keyof WiringManifest>>;
|
|
@@ -67,6 +67,16 @@ type WiringSection<K extends keyof WiringManifest> = NonNullable<WiringManifest[
|
|
|
67
67
|
type WiringLegHandled = "kind";
|
|
68
68
|
type _GuardWiringLeg = AssertAllKeysHandled<Exclude<keyof WiringSection<"leg">, WiringLegHandled>>;
|
|
69
69
|
type _GuardWiringLegReverse = AssertAllKeysHandled<Exclude<WiringLegHandled, keyof WiringSection<"leg">>>;
|
|
70
|
+
type WiringModRowKeys = WiringSection<"mods">[number] extends infer R ? (R extends unknown ? keyof R : never) : never;
|
|
71
|
+
type WiringModRowHandled = "name" | "seat" | "tier" | "events" | "observe" | "skipped" | "refusedBy" | "reason";
|
|
72
|
+
type _GuardWiringModRow = AssertAllKeysHandled<Exclude<WiringModRowKeys, WiringModRowHandled>>;
|
|
73
|
+
type _GuardWiringModRowReverse = AssertAllKeysHandled<Exclude<WiringModRowHandled, WiringModRowKeys>>;
|
|
74
|
+
type WiringModSkipKeys = keyof NonNullable<Extract<WiringSection<"mods">[number], {
|
|
75
|
+
events: unknown;
|
|
76
|
+
}>["skipped"]>[number];
|
|
77
|
+
type WiringModSkipHandled = "registration" | "cause" | "reason";
|
|
78
|
+
type _GuardWiringModSkip = AssertAllKeysHandled<Exclude<WiringModSkipKeys, WiringModSkipHandled>>;
|
|
79
|
+
type _GuardWiringModSkipReverse = AssertAllKeysHandled<Exclude<WiringModSkipHandled, WiringModSkipKeys>>;
|
|
70
80
|
type WiringAskHandled = "form" | "provenance" | "effective";
|
|
71
81
|
type _GuardWiringAsk = AssertAllKeysHandled<Exclude<keyof WiringSection<"ask">, WiringAskHandled>>;
|
|
72
82
|
type _GuardWiringAskReverse = AssertAllKeysHandled<Exclude<WiringAskHandled, keyof WiringSection<"ask">>>;
|
|
@@ -136,6 +146,11 @@ type _GuardPermissionTraceReverse = AssertAllKeysHandled<Exclude<PermissionTrace
|
|
|
136
146
|
/** `T` 非 `never` 时收敛到 `never`(空集 ⇒ 残留 `"EMPTY"` ⇒ tsc 红)。 */
|
|
137
147
|
type AssertNonEmpty<T> = [T] extends [never] ? "EMPTY" : never;
|
|
138
148
|
type _GuardPermissionTraceNonEmpty = AssertAllKeysHandled<AssertNonEmpty<PermissionTraceKind>>;
|
|
149
|
+
type PromptAssembledFrame = Extract<TraceEvent, {
|
|
150
|
+
kind: "prompt.assembled";
|
|
151
|
+
}>;
|
|
152
|
+
type PromptManifestNotOnRow = (typeof import("./wire-projection-faces.js").WIRE_PROJECTION_FACES)["prompt_manifest"]["excluded"][number];
|
|
153
|
+
type _GuardPromptManifestNotOnRowReverse = AssertAllKeysHandled<Exclude<PromptManifestNotOnRow, keyof PromptAssembledFrame>>;
|
|
139
154
|
type SummaryProjected = "sessionId" | "scope" | "createdAt" | "gateKind" | "severity" | "spentMicroUsd" | "deadline" | "hasBidiControls" | "requiresRealApproval" | "denialLimitFallback" | "origin" | "mandated" | "mandate" | "boundGrantDigest" | "boundGrants" | "classifierNoRuling" | "boundGrantAbsence";
|
|
140
155
|
type SummaryExcluded = "token" | "toolInput" | "toolName" | "toolCallId" | "preview" | "principal" | "sourceTaskId" | "approvalCard" | "restoreMode" | "checkpointId" | "previewWithheld" | "authoredBy";
|
|
141
156
|
type _GuardInboxSummary = AssertAllKeysHandled<Exclude<keyof CheckpointSummary, SummaryProjected | SummaryExcluded>>;
|
|
@@ -148,9 +163,9 @@ type ParkArmQueueExcluded = "kind" | "args" | "batchToolCallIds" | "completedCal
|
|
|
148
163
|
type _GuardParkArmQueue = AssertAllKeysHandled<Exclude<ParkArmKeys, ParkArmQueueProjected | ParkArmQueueExcluded>>;
|
|
149
164
|
type _GuardParkArmQueueReverse = AssertAllKeysHandled<Exclude<ParkArmQueueProjected | ParkArmQueueExcluded, ParkArmKeys>>;
|
|
150
165
|
type _NoDoubleBookParkArmQueue = AssertAllKeysHandled<Extract<ParkArmQueueProjected, ParkArmQueueExcluded>>;
|
|
151
|
-
type TaskSpecWired = "objective" | "principal" | "images" | "sessionId" | "requireExistingSession" | "oneShot" | "clientContext" | "resumeAt" | "resumeAtMode" | "model" | "compactionModel" | "thinking" | "systemPrompt" | "appendSystemPrompt" | "
|
|
166
|
+
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" | "promptProfile" | "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" | "allowedTools" | "allowTools" | "userAttachments";
|
|
152
167
|
/** 导出:请求体键闭集门(`request-key-closure.ts`)据它锁「本仓记为未接线的引擎座,提交口不许受理」—— 两处分类只能同向。 */
|
|
153
|
-
export type TaskSpecUnwired = "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "readDenyPatterns" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars" | "peerPresence" | "writeProtectedAdditions" | "complianceAdditionalDenies" | "modelRole" | "enableBlockedReport" | "
|
|
168
|
+
export type TaskSpecUnwired = "actor" | "roles" | "lspManager" | "tracer" | "readFace" | "readDenyPatterns" | "interactiveQuestionFallback" | "alwaysLoadTools" | "restoreGatedTools" | "deferSelfResolve" | "basePolicyForResumeEdit" | "lspDiagnostics" | "streamingToolExecution" | "toolResultThresholdChars" | "peerPresence" | "writeProtectedAdditions" | "complianceAdditionalDenies" | "modelRole" | "enableBlockedReport" | "promptForm";
|
|
154
169
|
type _GuardTaskSpec = AssertAllKeysHandled<Exclude<keyof TaskSpec, TaskSpecWired | TaskSpecUnwired>>;
|
|
155
170
|
type _GuardTaskSpecReverse = AssertAllKeysHandled<Exclude<TaskSpecWired | TaskSpecUnwired, keyof TaskSpec>>;
|
|
156
171
|
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";
|
|
@@ -294,6 +309,10 @@ export type CoreKeysetGuards = [
|
|
|
294
309
|
_GuardWiringFleetReverse,
|
|
295
310
|
_GuardSubagentTranscriptTierWords,
|
|
296
311
|
_GuardSubagentTranscriptTierWordsReverse,
|
|
312
|
+
_GuardWiringModRow,
|
|
313
|
+
_GuardWiringModRowReverse,
|
|
314
|
+
_GuardWiringModSkip,
|
|
315
|
+
_GuardWiringModSkipReverse,
|
|
297
316
|
_GuardWiringMcp,
|
|
298
317
|
_GuardWiringMcpReverse,
|
|
299
318
|
_GuardWiringRules,
|
|
@@ -306,6 +325,7 @@ export type CoreKeysetGuards = [
|
|
|
306
325
|
_GuardWiringGovernanceReverse,
|
|
307
326
|
_GuardPermissionTrace,
|
|
308
327
|
_GuardPermissionTraceReverse,
|
|
328
|
+
_GuardPromptManifestNotOnRowReverse,
|
|
309
329
|
_GuardPermissionTraceNonEmpty,
|
|
310
330
|
_GuardInboxSummary,
|
|
311
331
|
_GuardInboxSummaryReverse,
|
|
@@ -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.records_skipped", "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"];
|
|
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.records_skipped", "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"];
|
|
20
20
|
export type EngineNoticeWireCode = (typeof ENGINE_NOTICE_WIRE_CODES)[number];
|
|
21
21
|
/** 白名单谓词(单点):路由与门都读这一个,不许第二处手抄码串。 */
|
|
22
22
|
export declare function isEngineNoticeWireCode(code: string): code is EngineNoticeWireCode;
|
|
@@ -47,6 +47,13 @@ export interface EngineNoticeWireRow {
|
|
|
47
47
|
/** **服务端观察时刻**(ms epoch)——`EngineNotice` 自身不带时间戳,这是本仓收到它的那一拍,不是 core 铸它的那一拍。 */
|
|
48
48
|
ts: number;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* 上 wire 的**注册方写的自由文本**的唯一出口纪律:`redactSecrets` + 截到 {@link NOTICE_TEXT_MAX}。
|
|
52
|
+
* 同一个事实(一张扩展注册被判拒、一个判官被跳过)有两个出口 —— 通告 `mods.registration_refused` 的 `detail`(经 {@link sanitizeNoticeDetail})与
|
|
53
|
+
* `wiring_manifest.mods[]` 的行(`trace/project.ts`)—— 两个出口的每一个串都过这一只,所以同一个串在两边逐字节相等;
|
|
54
|
+
* 规则只在这里写一次,`mods[]` 行不另造第二份脱敏 / 截长。
|
|
55
|
+
*/
|
|
56
|
+
export declare function sanitizeWireText(text: string): string;
|
|
50
57
|
/**
|
|
51
58
|
* `detail` 消毒(设计稿 ②:`redactSecrets` + 尺寸 bound;`workspaceChangedEventData` 先例)。
|
|
52
59
|
*
|
|
@@ -54,7 +61,7 @@ export interface EngineNoticeWireRow {
|
|
|
54
61
|
* ——§E1 的既有姿态:上 wire 的自由文本一律经本仓的脱敏器,不因为上游说过一次就免检。
|
|
55
62
|
*
|
|
56
63
|
* 契约(逐条,门在 `test/engine-notice-wire.test.ts`):
|
|
57
|
-
* · 串 ⇒ `redactSecrets` + 截到 {@link NOTICE_TEXT_MAX};
|
|
64
|
+
* · 串 ⇒ {@link sanitizeWireText}(`redactSecrets` + 截到 {@link NOTICE_TEXT_MAX});
|
|
58
65
|
* · 有限 number / boolean / null ⇒ 逐字(harvest 的 count/moved/escalated 是判据数字,不许变形);
|
|
59
66
|
* · 非有限 number(NaN/Infinity)⇒ **丢键**(JSON 里它们会变成 `null`,一个看起来合法的假读数);
|
|
60
67
|
* · 数组 ⇒ 逐项消毒,超 {@link DETAIL_MAX_ITEMS} 截断;对象 ⇒ 逐键消毒,超 {@link DETAIL_MAX_KEYS} 丢尾键;
|
|
@@ -91,7 +98,8 @@ export declare function redactNoticeMessage(message: unknown): string;
|
|
|
91
98
|
* 通告 `detail` 里的**规则文本**换成条目的脱敏原值({@link redactListEntry}:凭据换记号,不加引号、不转义 —— 机读位不是显示面,显示形只属于人读句)。
|
|
92
99
|
* 会话流行(经 {@link engineNoticeEventData},之后照常过 {@link sanitizeNoticeDetail})与运维日志行(`boot/runner-deps.ts` 的转发席,其余字段逐字)
|
|
93
100
|
* 同调这一只 ⇒ 两条出路上同一条规则文本逐字节同(会话流行另有 detail 串的 {@link NOTICE_TEXT_MAX} 字上限,超长的那一截只在日志行上),两只码里同一条
|
|
94
|
-
* 规则文本也同
|
|
101
|
+
* 规则文本也同 —— core 7.53.0(#1884)起引擎交来的两形就是同一只读法的产物(原串,长于 1 024 码点的截到 1 024 + 一枚截断记号;修前 `rule_row_dropped`
|
|
102
|
+
* 交中和形,空白 / 超长的条目两只码不同)。其余字段、其余码原样。
|
|
95
103
|
*/
|
|
96
104
|
export declare function redactNoticeRuleText(code: string, detail: Record<string, unknown> | undefined): Record<string, unknown> | undefined;
|
|
97
105
|
export declare function engineNoticeEventData(notice: {
|
|
@@ -40,6 +40,9 @@ export const ENGINE_NOTICE_WIRE_CODES = [
|
|
|
40
40
|
"task.tool_turn_incomplete",
|
|
41
41
|
"route.finish_reason_unknown",
|
|
42
42
|
"route.stream_end_ignored",
|
|
43
|
+
"route.credential_origin_mismatch",
|
|
44
|
+
"mods.registration_refused",
|
|
45
|
+
"config.session_rules_earlier_grammar",
|
|
43
46
|
];
|
|
44
47
|
const WIRE_CODES = new Set(ENGINE_NOTICE_WIRE_CODES);
|
|
45
48
|
export function isEngineNoticeWireCode(code) {
|
|
@@ -53,6 +56,9 @@ export function engineNoticeSessionId(notice) {
|
|
|
53
56
|
return typeof fromDetail === "string" && fromDetail.length > 0 ? fromDetail : undefined;
|
|
54
57
|
}
|
|
55
58
|
const NOTICE_TEXT_MAX = 1000;
|
|
59
|
+
export function sanitizeWireText(text) {
|
|
60
|
+
return redactSecrets(text).slice(0, NOTICE_TEXT_MAX);
|
|
61
|
+
}
|
|
56
62
|
const DETAIL_MAX_DEPTH = 4;
|
|
57
63
|
const DETAIL_MAX_KEYS = 32;
|
|
58
64
|
const DETAIL_MAX_ITEMS = 32;
|
|
@@ -64,7 +70,7 @@ function sanitizeValue(v, depth) {
|
|
|
64
70
|
if (v === null)
|
|
65
71
|
return null;
|
|
66
72
|
if (typeof v === "string")
|
|
67
|
-
return
|
|
73
|
+
return sanitizeWireText(v);
|
|
68
74
|
if (typeof v === "number")
|
|
69
75
|
return Number.isFinite(v) ? v : undefined;
|
|
70
76
|
if (typeof v === "boolean")
|
|
@@ -99,6 +105,7 @@ function sanitizeValue(v, depth) {
|
|
|
99
105
|
export const RULE_TEXT_DETAIL_FIELDS = {
|
|
100
106
|
"permission.allowed_tool_not_granted": { array: "entries", field: "entry" },
|
|
101
107
|
"permission.rule_row_dropped": { array: "rows", field: "rule" },
|
|
108
|
+
"config.session_rules_earlier_grammar": { array: "entries", field: "entry" },
|
|
102
109
|
};
|
|
103
110
|
export function redactNoticeMessage(message) {
|
|
104
111
|
return redactSecrets(String(message));
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
* 的 `switch (ev.type)` 白名单臂(差集门 `test/durable-append-arm-parity.test.ts` 看守两腿一致);
|
|
32
32
|
* · **腿自己的带外行**:park/终局/失败/建议/用量/装配自证(不来自流事件)。
|
|
33
33
|
*/
|
|
34
|
-
export type LedgerEventType = "reasoning" | "text" | "tool_start" | "tool_end" | "status" | "context_usage" | "compacted" | "diagnostics" | "steering_injected" | "compaction_outcome"
|
|
34
|
+
export type LedgerEventType = "reasoning" | "text" | "tool_start" | "tool_end" | "status" | "context_usage" | "compacted" | "diagnostics" | "steering_injected" | "compaction_outcome"
|
|
35
|
+
/** S-1732(core 7.53.0 #2008):压缩 pass 的开始帧(`{ trigger, pass, startedAt }`;结束帧带同一个 `pass`)。原样落账,两条 durable 腿同源。 */
|
|
36
|
+
| "compaction_started" | "workspace_changed" | "wiring_manifest"
|
|
35
37
|
/** S-212(7.71.0):运行期名册变更(core 7.8.0 [ref] ⑪)。**快照语义**——`delta.roster` 是整只
|
|
36
38
|
* 变更后名册,消费端收到即整只替换,所以回放不需要任何合并;它的耐久面因此不是 `wiring_manifest.tools`
|
|
37
39
|
* 的重复,而是那份开腿快照**之后**的每一次改动(修前两条 durable 腿零 case ⇒ 回放只见开头一版)。 */
|
|
@@ -104,6 +104,35 @@ export declare function createSerialLedgerAppend(appendEvent: (seq: number, type
|
|
|
104
104
|
* 返回 `.catch` 用的处理器(产物是函数 ⇒ `create*`)。
|
|
105
105
|
*/
|
|
106
106
|
export declare function createForwardAppendFailedNote(type: string): (err: unknown) => void;
|
|
107
|
+
/**
|
|
108
|
+
* 人在环帧(`question` / `question_complete`、`elicitation` / `elicitation_complete`)的**账本孪生投递口**。
|
|
109
|
+
*
|
|
110
|
+
* 一条律:**凡进 run 流的 HITL 帧都有账本孪生;腿只决定「还要不要同时直写 socket」**。后台腿没有 live 面,
|
|
111
|
+
* 它的投递口就是账本追加本身(`runs.ts`);同步流腿有 live SSE,走本函数 —— 同一只帧对象先落账、再按需直写,
|
|
112
|
+
* 于是两条腿对同一只帧的落法只差「直写要不要」,不差「账本有没有」。
|
|
113
|
+
*
|
|
114
|
+
* 顺序与失败语义(与后台腿同一条):
|
|
115
|
+
* · **先账本后直写**。账本落不下 ⇒ 本次投递**失败**(抛),帧不上 socket —— 一只没有孪生的帧不许单独露面
|
|
116
|
+
* (否则壳看见一张重载就丢的卡)。调用方(协调器)按「开帧投递失败」处理:这一问结算 `unavailable`、记一次既有的
|
|
117
|
+
* P-DEBT 留痕;消卡帧则落「面包屑丢失」的 F 类留痕。
|
|
118
|
+
* · **seq 不自造**:孪生走 `sink.append` —— 本腿账本唯一的那条串行链(与 text / tool / done 行同一个计数器)。
|
|
119
|
+
* · **直写口已不可达**(客户端离开,而 run 因 detach 继续)⇒ 账本孪生即送达,不再触碰那条已死的连接
|
|
120
|
+
* (不抛、也不记「丢帧」—— 帧没丢,在账本里)。
|
|
121
|
+
* · **本腿没有账本**(无 durable run 行的部署:`sink` 缺席)⇒ 直写就是全部投递,死流姿态由 `writeLive` 自己带
|
|
122
|
+
* (question 抛、elicitation 静默记账),字节逐字同孪生落地之前。
|
|
123
|
+
*
|
|
124
|
+
* 命名(CLAUDE.md 工厂命名律):`create*` —— 返回的是捕获了两个口的闭包,不是纯数据。
|
|
125
|
+
*/
|
|
126
|
+
export declare function createLedgerTwinEmit<F extends {
|
|
127
|
+
type: LedgerEventType;
|
|
128
|
+
}>(opts: {
|
|
129
|
+
/** 本腿的账本(sync 腿 = 有 durable run 行才有;缺席 ⇒ 无孪生可落)。只用 `append`:seq 由它那条链铸。 */
|
|
130
|
+
sink: Pick<LedgerSink, "append"> | undefined;
|
|
131
|
+
/** 本腿的直写口(sync 腿 = 一个具名 SSE 事件)。 */
|
|
132
|
+
writeLive: (frame: F) => void;
|
|
133
|
+
/** 直写面此刻可达吗 —— 与协调器问「这条腿还够得着人吗」的是**同一只**谓词(`QuestionRunContext.deliverable`)。 */
|
|
134
|
+
liveReachable: () => boolean;
|
|
135
|
+
}): (frame: F) => Promise<void>;
|
|
107
136
|
export declare function createLedgerSink(opts: {
|
|
108
137
|
/** The seq-stamped durable append — typically `(seq, type, data) => runStore.appendEvent(taskId, seq, type, data)`. */
|
|
109
138
|
appendEvent: (seq: number, type: LedgerEventType, data: unknown) => Promise<void>;
|