@sema-agent/core 5.20.0 → 5.21.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/CHANGELOG.md +9 -0
- package/dist/agents/agent-definition.d.ts +7 -0
- package/dist/agents/agent-transcript-tool.d.ts +30 -0
- package/dist/agents/builtin-agents.d.ts +60 -0
- package/dist/agents/cascade.d.ts +107 -0
- package/dist/agents/cumulative-stats.d.ts +56 -0
- package/dist/agents/observer.d.ts +162 -0
- package/dist/agents/peer-admission.d.ts +95 -0
- package/dist/agents/repair-loop.d.ts +226 -0
- package/dist/agents/retain-ledger.d.ts +141 -0
- package/dist/agents/roster-store.d.ts +105 -0
- package/dist/agents/send-message-tool.d.ts +92 -0
- package/dist/agents/session-util.d.ts +5 -0
- package/dist/agents/subagent-steps.d.ts +66 -0
- package/dist/agents/subagent.d.ts +600 -0
- package/dist/agents/suspend-guard.d.ts +29 -0
- package/dist/agents/teacher.d.ts +75 -0
- package/dist/agents/team.d.ts +120 -1
- package/dist/agents/tool-filter.d.ts +34 -0
- package/dist/agents/verify.d.ts +198 -0
- package/dist/bench/metrics.d.ts +455 -0
- package/dist/brain/anthropic.d.ts +30 -0
- package/dist/brain/circuit-breaker.d.ts +33 -0
- package/dist/brain/context-overflow.d.ts +60 -3
- package/dist/brain/degrading.d.ts +67 -0
- package/dist/brain/errors.d.ts +42 -0
- package/dist/brain/failover.d.ts +15 -0
- package/dist/brain/media-degrade.d.ts +39 -0
- package/dist/brain/model-presets.d.ts +31 -0
- package/dist/brain/open-responses.d.ts +19 -0
- package/dist/brain/openai.d.ts +46 -0
- package/dist/brain/reasoning.d.ts +106 -1
- package/dist/brain/repetition.d.ts +83 -0
- package/dist/brain/request-params.d.ts +56 -0
- package/dist/brain/retry.d.ts +46 -0
- package/dist/brain/routing.d.ts +12 -0
- package/dist/brain/status-sink.d.ts +30 -1
- package/dist/brain/stream-engine.d.ts +147 -0
- package/dist/brain/stream-shared.d.ts +34 -0
- package/dist/brain/terminal-cause.d.ts +31 -0
- package/dist/brain/timeout.d.ts +107 -0
- package/dist/brain/tool-call-id.d.ts +20 -0
- package/dist/brain/tool-call-repair.d.ts +13 -0
- package/dist/config/catalog.d.ts +47 -0
- package/dist/config/defaults.d.ts +33 -0
- package/dist/core/a2a-task-state.d.ts +53 -0
- package/dist/core/a2a.d.ts +51 -0
- package/dist/core/arg-summary.d.ts +62 -0
- package/dist/core/ask-question.d.ts +272 -2
- package/dist/core/auto-compaction.d.ts +467 -0
- package/dist/core/auto-compaction.js +20 -6
- package/dist/core/auto-mode-prompt-assets.d.ts +8 -0
- package/dist/core/auto-mode-prompt.d.ts +27 -0
- package/dist/core/auto-mode.d.ts +54 -3
- package/dist/core/auto-promote.d.ts +100 -0
- package/dist/core/background-agent-store.d.ts +292 -0
- package/dist/core/background-shell.d.ts +110 -0
- package/dist/core/cache-break-detector.d.ts +34 -0
- package/dist/core/canonical-json.d.ts +57 -0
- package/dist/core/checkpoint-store.d.ts +1574 -16
- package/dist/core/compliance.d.ts +30 -0
- package/dist/core/consolidate-scope.d.ts +75 -0
- package/dist/core/context-edit.d.ts +99 -0
- package/dist/core/context-guard.d.ts +46 -0
- package/dist/core/exec-gate.d.ts +44 -0
- package/dist/core/exec-output-tail.d.ts +61 -0
- package/dist/core/file-snapshot-store.d.ts +104 -0
- package/dist/core/fs-write-gate-policy.d.ts +36 -0
- package/dist/core/git-worktree-env.d.ts +31 -0
- package/dist/core/governance-codes.d.ts +19 -0
- package/dist/core/hooks.d.ts +608 -1
- package/dist/core/human-input-projection.d.ts +37 -0
- package/dist/core/human-input-projection.js +13 -0
- package/dist/core/image-downsample.d.ts +74 -0
- package/dist/core/locked-config.d.ts +37 -0
- package/dist/core/lsp-diagnostics.d.ts +77 -0
- package/dist/core/lsp-protocol.d.ts +29 -0
- package/dist/core/lsp-session.d.ts +60 -1
- package/dist/core/lsp.d.ts +150 -1
- package/dist/core/mailbox-store.d.ts +57 -0
- package/dist/core/mcp.d.ts +381 -0
- package/dist/core/media-byte-cap.d.ts +21 -0
- package/dist/core/memory-admission.d.ts +71 -0
- package/dist/core/memory-engine/content-origin.d.ts +64 -0
- package/dist/core/memory-engine/data-plane.d.ts +43 -0
- package/dist/core/memory-engine/dual-root.d.ts +24 -0
- package/dist/core/memory-engine/engine.d.ts +230 -0
- package/dist/core/memory-engine/engine.js +103 -35
- package/dist/core/memory-engine/file-backend.d.ts +155 -0
- package/dist/core/memory-engine/frontmatter.d.ts +16 -0
- package/dist/core/memory-engine/layout.d.ts +217 -0
- package/dist/core/memory-engine/memory-backend-contract.d.ts +12 -0
- package/dist/core/memory-engine/migrate.d.ts +9 -0
- package/dist/core/memory-engine/scan.d.ts +12 -0
- package/dist/core/memory-engine/scope-contract.d.ts +61 -1
- package/dist/core/memory-engine/sync-client.d.ts +87 -0
- package/dist/core/memory-engine/sync.d.ts +60 -0
- package/dist/core/memory-engine/tools.d.ts +41 -0
- package/dist/core/memory-engine/types.d.ts +188 -0
- package/dist/core/memory-recall.d.ts +141 -0
- package/dist/core/memory-vector.d.ts +20 -0
- package/dist/core/memory.d.ts +458 -0
- package/dist/core/message-utils.d.ts +6 -0
- package/dist/core/oracle-isolation.d.ts +69 -0
- package/dist/core/permission-rule-consent.d.ts +138 -0
- package/dist/core/permission-rule-model.d.ts +122 -0
- package/dist/core/permission-rule-store.d.ts +119 -3
- package/dist/core/permission-rules.d.ts +87 -1
- package/dist/core/present-plan-tool.d.ts +20 -0
- package/dist/core/pricing.d.ts +26 -0
- package/dist/core/property-harness.d.ts +86 -0
- package/dist/core/protocol-naming.d.ts +38 -0
- package/dist/core/protocol-table.d.ts +61 -0
- package/dist/core/push-queue.d.ts +1 -0
- package/dist/core/remote-env.d.ts +383 -1
- package/dist/core/retention-policy.d.ts +33 -0
- package/dist/core/retention.d.ts +51 -0
- package/dist/core/roles.d.ts +59 -0
- package/dist/core/runner/active-skill-scope.d.ts +34 -0
- package/dist/core/runner/assemble-result.d.ts +134 -0
- package/dist/core/runner/compaction-call-options.d.ts +97 -1
- package/dist/core/runner/grounding-signal.d.ts +10 -0
- package/dist/core/runner/image.d.ts +17 -0
- package/dist/core/runner/image.js +29 -15
- package/dist/core/runner/memory-consolidation.d.ts +60 -0
- package/dist/core/runner/prepare-memory.d.ts +59 -0
- package/dist/core/runner/prepare-task.d.ts +1011 -2
- package/dist/core/runner/prepare-task.js +12 -11
- package/dist/core/runner/prompt-suggestions.d.ts +7 -0
- package/dist/core/runner/runtask.d.ts +304 -3
- package/dist/core/runner/session-file-state-replay.d.ts +49 -0
- package/dist/core/runner/session-rule-policy.d.ts +58 -0
- package/dist/core/runner/strict-output-schema.d.ts +18 -3
- package/dist/core/runner/synthetic-tools.d.ts +113 -0
- package/dist/core/runner/teardown-bounded.d.ts +34 -0
- package/dist/core/runner/tool-disclosure.d.ts +227 -0
- package/dist/core/runner/tool-output-projection.d.ts +6 -0
- package/dist/core/runner/turn-attachments.d.ts +634 -0
- package/dist/core/runner/usage-accounting.d.ts +32 -0
- package/dist/core/runtime.d.ts +9 -0
- package/dist/core/safe-notify.d.ts +64 -0
- package/dist/core/safety-axis-vocab.d.ts +23 -0
- package/dist/core/safety-merge-corpus.d.ts +37 -0
- package/dist/core/scheduler.d.ts +121 -0
- package/dist/core/secret-env.d.ts +32 -0
- package/dist/core/select-model.d.ts +15 -0
- package/dist/core/sensitive-path-policy.d.ts +42 -0
- package/dist/core/session-policy-store.d.ts +94 -0
- package/dist/core/session-reconcile.d.ts +80 -0
- package/dist/core/session-store.d.ts +85 -0
- package/dist/core/session.d.ts +153 -0
- package/dist/core/shared-memory/contract.d.ts +22 -0
- package/dist/core/shared-memory/normalize.d.ts +123 -2
- package/dist/core/shared-memory/tools.d.ts +14 -0
- package/dist/core/shared-memory/types.d.ts +105 -0
- package/dist/core/shutdown-debug.d.ts +6 -0
- package/dist/core/side-query.d.ts +38 -0
- package/dist/core/side-query.js +6 -1
- package/dist/core/skill-tool-specifier.d.ts +72 -0
- package/dist/core/skills-directory.d.ts +100 -1
- package/dist/core/spec-contract.d.ts +89 -0
- package/dist/core/store-contracts/background-agent-store-contract.d.ts +31 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +26 -0
- package/dist/core/store-contracts/contract-harness.d.ts +20 -0
- package/dist/core/store-contracts/contract-kit-version.d.ts +27 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +8 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +42 -0
- package/dist/core/store-contracts/tool-result-store-contract.d.ts +13 -0
- package/dist/core/strategy-store.d.ts +37 -0
- package/dist/core/stub-env.d.ts +7 -0
- package/dist/core/surrogate-safe-slice.d.ts +35 -0
- package/dist/core/task-notification.d.ts +202 -0
- package/dist/core/task-outcome.d.ts +53 -0
- package/dist/core/task-registry-agent.d.ts +337 -1
- package/dist/core/task-registry-monitor.d.ts +12 -0
- package/dist/core/task-registry-shared.d.ts +540 -0
- package/dist/core/task-registry.d.ts +343 -0
- package/dist/core/task-registry.js +13 -2
- package/dist/core/task-tool-shape.d.ts +44 -0
- package/dist/core/tighten-task-spec.d.ts +21 -0
- package/dist/core/tool-detach.d.ts +21 -0
- package/dist/core/tool-errors.d.ts +131 -0
- package/dist/core/tool-errors.js +4 -0
- package/dist/core/tool-name-aliases.d.ts +27 -0
- package/dist/core/tool-policy.d.ts +555 -0
- package/dist/core/tool-result-budget.d.ts +32 -0
- package/dist/core/tool-result-store.d.ts +174 -1
- package/dist/core/tools.d.ts +45 -0
- package/dist/core/trace.d.ts +323 -0
- package/dist/core/types.d.ts +3859 -2
- package/dist/core/untrusted-egress.d.ts +8 -0
- package/dist/core/untrusted-text.d.ts +156 -0
- package/dist/core/usage-window-store.d.ts +95 -0
- package/dist/core/version.d.ts +1 -0
- package/dist/core/warm-resume.d.ts +17 -0
- package/dist/core/wiring-manifest.d.ts +169 -0
- package/dist/core/with-retry.d.ts +24 -0
- package/dist/core/workflow-journal-store.d.ts +160 -0
- package/dist/core/workflow-run-store-contract.d.ts +25 -0
- package/dist/core/workflow-run-store.d.ts +119 -0
- package/dist/engine/compaction/compaction.d.ts +256 -1
- package/dist/engine/compaction/utils.d.ts +94 -0
- package/dist/engine/execution-env/kill-tree.d.ts +29 -0
- package/dist/engine/execution-env/node-execution-env.d.ts +94 -0
- package/dist/engine/harness/agent-harness.d.ts +116 -0
- package/dist/engine/harness/agent-harness.js +3 -14
- package/dist/engine/harness/messages.d.ts +15 -0
- package/dist/engine/harness/types.d.ts +464 -2
- package/dist/engine/llm/diagnostics.d.ts +4 -0
- package/dist/engine/llm/event-stream.d.ts +3 -0
- package/dist/engine/llm/index.d.ts +7 -0
- package/dist/engine/llm/types.d.ts +500 -3
- package/dist/engine/llm/validation.d.ts +3 -0
- package/dist/engine/loop/agent-loop.d.ts +87 -2
- package/dist/engine/loop/runtime-deps.d.ts +7 -0
- package/dist/engine/loop/types.d.ts +424 -0
- package/dist/engine/lsp/frame-decoder.d.ts +13 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +107 -0
- package/dist/engine/lsp/stdio-lsp-transport.d.ts +7 -0
- package/dist/engine/session/import-validate.d.ts +27 -0
- package/dist/engine/session/log-digest.d.ts +93 -0
- package/dist/engine/session/memory-repo.d.ts +6 -0
- package/dist/engine/session/memory-storage.d.ts +2 -0
- package/dist/engine/session/session.d.ts +75 -0
- package/dist/engine/session/storage-base.d.ts +8 -0
- package/dist/fixtures/index.d.ts +36 -0
- package/dist/index.d.ts +16 -1
- package/dist/index.js +0 -1
- package/dist/internal/harness-types.d.ts +6 -0
- package/dist/internal/harness.d.ts +11 -0
- package/dist/internal/llm.d.ts +6 -0
- package/dist/orchestration/builtin-workflows.d.ts +53 -0
- package/dist/orchestration/dev-vm-script-runner.d.ts +19 -0
- package/dist/orchestration/goal.d.ts +57 -0
- package/dist/orchestration/goal.js +3 -0
- package/dist/orchestration/run-spec.d.ts +42 -0
- package/dist/orchestration/run-workflow-tool.d.ts +169 -0
- package/dist/orchestration/workflow-governance.d.ts +61 -0
- package/dist/orchestration/workflow-meta.d.ts +28 -0
- package/dist/orchestration/workflow-observe.d.ts +60 -0
- package/dist/orchestration/workflow-primitives.d.ts +23 -1
- package/dist/orchestration/workflow-sandbox-conformance.d.ts +38 -0
- package/dist/orchestration/workflow-script-runner.d.ts +88 -0
- package/dist/orchestration/workflow-script-store.d.ts +98 -0
- package/dist/orchestration/workflow-size-guideline.d.ts +67 -0
- package/dist/orchestration/workflow-types.d.ts +169 -2
- package/dist/orchestration/workflow.d.ts +358 -0
- package/dist/prompt-assembly/artifact-store.d.ts +33 -0
- package/dist/prompt-assembly/artifact.d.ts +25 -0
- package/dist/prompt-assembly/assemble.d.ts +20 -0
- package/dist/prompt-assembly/composer.d.ts +29 -0
- package/dist/prompt-assembly/epoch.d.ts +55 -1
- package/dist/prompt-assembly/event-registry.d.ts +35 -0
- package/dist/prompt-assembly/explain.d.ts +12 -0
- package/dist/prompt-assembly/tool-catalog.d.ts +38 -0
- package/dist/prompt-assembly/turn-snapshot.d.ts +40 -0
- package/dist/prompt-assembly/types.d.ts +115 -0
- package/dist/prompts/coordinator.d.ts +27 -0
- package/dist/prompts/default.d.ts +539 -0
- package/dist/prompts/simple-sections.d.ts +45 -0
- package/dist/prompts/supervisor.d.ts +66 -0
- package/dist/scenarios/env.d.ts +28 -0
- package/dist/scenarios/full-body.d.ts +50 -0
- package/dist/scenarios/scenario-registry.d.ts +60 -0
- package/dist/scenarios/teacher-quickstart.d.ts +27 -0
- package/dist/server/http.d.ts +17 -0
- package/dist/stores/cc/lockfile.d.ts +6 -0
- package/dist/stores/cc/mailbox-store.d.ts +8 -0
- package/dist/stores/cc/roster-adapter.d.ts +4 -0
- package/dist/stores/cc/sidecar-transcript.d.ts +66 -0
- package/dist/stores/file/background-agent-store.d.ts +24 -0
- package/dist/stores/file/checkpoint-store.d.ts +38 -0
- package/dist/stores/file/file-snapshot-store.d.ts +25 -0
- package/dist/stores/file/fs-atomic.d.ts +155 -0
- package/dist/stores/file/index.d.ts +89 -0
- package/dist/stores/file/mailbox-store.d.ts +36 -0
- package/dist/stores/file/memory-store.d.ts +82 -0
- package/dist/stores/file/permission-rule-store.d.ts +79 -0
- package/dist/stores/file/session-policy-store.d.ts +28 -0
- package/dist/stores/file/session-store.d.ts +40 -0
- package/dist/stores/file/shared-ledger.d.ts +83 -0
- package/dist/stores/file/tool-result-store.d.ts +11 -0
- package/dist/stores/file/usage-window-store.d.ts +18 -0
- package/dist/stores/file/workflow-journal-store.d.ts +100 -0
- package/dist/stores/file/workflow-run-store.d.ts +11 -0
- package/dist/tools/fs/bash-readonly-classifier.d.ts +282 -0
- package/dist/tools/fs/encoding.d.ts +60 -0
- package/dist/tools/fs/fs-bash.d.ts +133 -0
- package/dist/tools/fs/fs-pdf.d.ts +28 -0
- package/dist/tools/fs/fs-search-tools.d.ts +5 -0
- package/dist/tools/fs/fs-shared.d.ts +360 -0
- package/dist/tools/fs/fs-write.d.ts +16 -0
- package/dist/tools/fs/gh-rate-limit.d.ts +22 -0
- package/dist/tools/fs/index.d.ts +79 -0
- package/dist/tools/fs/notebook.d.ts +56 -0
- package/dist/tools/fs/pdf.d.ts +70 -0
- package/dist/tools/fs/pdf.js +8 -2
- package/dist/tools/fs/repo-map.d.ts +10 -0
- package/dist/tools/fs/safety.d.ts +376 -0
- package/dist/tools/fs/search.d.ts +131 -0
- package/dist/tools/loop-tick.d.ts +24 -0
- package/dist/tools/monitor.d.ts +55 -0
- package/dist/tools/scheduler-tools.d.ts +51 -0
- package/dist/tools/sql-adapters.d.ts +18 -0
- package/dist/tools/sql.d.ts +25 -0
- package/dist/tools/task-list.d.ts +77 -0
- package/dist/tools/todo.d.ts +8 -0
- package/dist/tools/web.d.ts +184 -0
- package/dist/tools/worktree.d.ts +81 -0
- package/package.json +2 -2
- package/dist/tools/gitea-issue.d.ts +0 -13
- package/dist/tools/gitea-issue.js +0 -75
|
@@ -3,7 +3,15 @@ export type { RedactionFinding, RedactionReport, RedactionConfidence, RedactionS
|
|
|
3
3
|
export { summarizeRedactions } from "./arg-summary.js";
|
|
4
4
|
export declare function redactSecrets(s: string, report?: RedactionReport): string;
|
|
5
5
|
export declare function redactHostLeaks(s: string, report?: RedactionReport): string;
|
|
6
|
+
/** Secret-redact + size-bound (NO injection fence) — the SAME-PRINCIPAL tier: workflow outputs/results/errors
|
|
7
|
+
* riding back to the launching model/script, run rows behind scope-gated observe. Paths/URLs survive
|
|
8
|
+
* ([1295]② — the assertion pattern depends on them); secrets never do. */
|
|
6
9
|
export declare function boundedRedactedSummary(value: unknown, max: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* The FULL untrusted-egress transform (design/97 CORE-2): full host-leak redaction + size-bound + FENCE. Use
|
|
12
|
+
* for any worker prompt/output (#5 transcript) or steer content (#6) shown to a HUMAN or exported beyond the
|
|
13
|
+
* launching principal, so untrusted text can neither leak host internals nor pose as instructions.
|
|
14
|
+
*/
|
|
7
15
|
export declare function untrustedEgressForHuman(value: unknown, opts: {
|
|
8
16
|
label: string;
|
|
9
17
|
max: number;
|
|
@@ -1,12 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Untrusted-text containment (design/53 §2.A — "untrusted-data-everywhere").
|
|
3
|
+
*
|
|
4
|
+
* A multi-agent code-orchestration system treats **every worker's output** (report / diff / code / module)
|
|
5
|
+
* as untrusted data: an LLM worker can be prompt-injected or adversarial, and its output flows into other
|
|
6
|
+
* models' prompts (the L3 judge, the leader, the next worker) where it could pose as instructions —
|
|
7
|
+
* e.g. emitting `</system-reminder>` to escape its framing and forge a verdict (threat BUG1, verify.ts).
|
|
8
|
+
*
|
|
9
|
+
* The trusted side of the codebase REJECTS such sequences (runtask.ts: trusted steering / deny reasons must
|
|
10
|
+
* not contain `</system-reminder>`). Worker text can't be rejected — it must be **contained**: this module
|
|
11
|
+
* NEUTRALIZES break-out sequences and wraps the text in a clearly-labeled opaque fence the consuming prompt
|
|
12
|
+
* tells the model to treat as data, not instructions. Structural and reusable across the chain, not a
|
|
13
|
+
* per-call point-fix.
|
|
14
|
+
*
|
|
15
|
+
* This is defense-in-depth, NOT a guarantee: an LLM cannot reliably honor a "this is data" boundary on its
|
|
16
|
+
* own (instructions and data share one channel). The real boundary is decorrelation + reading the objective
|
|
17
|
+
* artifact (the diff / working tree) rather than the worker's self-report (design/53 §3, design/54 §3).
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* Neutralize structural break-out sequences in UNTRUSTED text so it can't escape its framing into
|
|
21
|
+
* model-facing instructions. Always neutralizes `<system-reminder>` / `</system-reminder>` (the codebase's
|
|
22
|
+
* elevated-authority wrapper) by inserting a zero-width space after the leading `<`. Pass `extraTags` to also
|
|
23
|
+
* neutralize a CALLER's own data-framing tags — e.g. `team.ts` embeds member output inside `<statement>` /
|
|
24
|
+
* `<team-discussion>`, so an untrusted member could emit `</statement>` to break out (search [46] BUG2);
|
|
25
|
+
* the caller passes those tag names. Tag names must be literal (alphanumeric/hyphen) — they are code-supplied
|
|
26
|
+
* wrapper names, never untrusted input. Idempotent for prompt assembly (a defused tag no longer matches).
|
|
27
|
+
*/
|
|
1
28
|
export declare function sanitizeUntrustedText(text: string, extraTags?: string[]): string;
|
|
29
|
+
/**
|
|
30
|
+
* [c209-C] codex 收口 C1/C2 (metadata-driven, replaces the shape-anchored
|
|
31
|
+
* `stripLeadingSystemReminders`) — cut the engine-prepended prefix off a user-lane message using the
|
|
32
|
+
* EXACT length recorded on the message at mint time (`UserMessage.enginePrefixChars`, stamped where
|
|
33
|
+
* the engine concatenated first-frame listing reminders / a UserPromptSubmit additionalContext
|
|
34
|
+
* reminder / a resume continuation's trusted head AHEAD of the real user text). The first user turn
|
|
35
|
+
* carries those bytes as engine guidance, not user speech — a consumer that re-presents user
|
|
36
|
+
* messages under a `[user]`/`[User]:` label (the auto-mode classifier window, the compaction
|
|
37
|
+
* summarizer input) must not let them (a) impersonate user authority or (b) evict the real
|
|
38
|
+
* objective from a head-truncated excerpt.
|
|
39
|
+
*
|
|
40
|
+
* The old helper GUESSED by reminder shape, which mis-fired in both directions (codex 收口轮): a
|
|
41
|
+
* same-line engine mint (`<system-reminder>[deadline] …</system-reminder>`) was NOT recognized and
|
|
42
|
+
* entered the window under `[user]` authority, while a user who legitimately opened their own
|
|
43
|
+
* prompt with a byte-exact reminder block WAS stripped. Metadata removes the guess entirely:
|
|
44
|
+
* - a message WITH `enginePrefixChars` is cut at exactly that offset (no regex, no shape matching);
|
|
45
|
+
* - a message WITHOUT metadata is rendered VERBATIM — user-authored `<system-reminder>` prefixes
|
|
46
|
+
* are never stripped, and OLD sessions (persisted before the field existed) render unchanged.
|
|
47
|
+
* Conservative direction, deliberate: a classifier/summarizer seeing engine listings as user text
|
|
48
|
+
* is acceptable; silently losing real user text is not.
|
|
49
|
+
* An out-of-range length (≤0 / > text length — corrupt or foreign data) is ignored the same way.
|
|
50
|
+
* [c209-C] R5: the parameter is `unknown` — the field can arrive as shape-poison from old/foreign
|
|
51
|
+
* imported sessions (a string "9", null) and the typeof/integer checks below are the total guard.
|
|
52
|
+
*/
|
|
2
53
|
export declare function cutEnginePrefix(text: string, enginePrefixChars: unknown): {
|
|
3
54
|
text: string;
|
|
4
55
|
cut: boolean;
|
|
5
56
|
};
|
|
57
|
+
/** An engine-trusted segment of a user-lane message: a half-open `[start, end)` UTF-16 code-unit
|
|
58
|
+
* range — see `UserMessage.engineSegments` (engine/llm/types.ts) for the full field contract. */
|
|
6
59
|
export interface EngineSegment {
|
|
7
60
|
start: number;
|
|
8
61
|
end: number;
|
|
9
62
|
}
|
|
63
|
+
/**
|
|
64
|
+
* [c209-C] R5 codex R4 复核 — the three-state result of {@link normalizeEngineSegments}. `absent`
|
|
65
|
+
* and `malformed` are DIFFERENT states on purpose (R4 #1): a message whose `engineSegments` field
|
|
66
|
+
* is present-but-malformed must render WHOLLY verbatim — the metadata family is suspect, so a
|
|
67
|
+
* co-present `enginePrefixChars` must NOT get a second chance to cut (absent metadata is the only
|
|
68
|
+
* state where the prefix sugar applies).
|
|
69
|
+
*/
|
|
10
70
|
export type NormalizedEngineSegments = {
|
|
11
71
|
readonly state: "absent";
|
|
12
72
|
} | {
|
|
@@ -15,14 +75,110 @@ export type NormalizedEngineSegments = {
|
|
|
15
75
|
readonly state: "valid";
|
|
16
76
|
readonly segments: ReadonlyArray<EngineSegment>;
|
|
17
77
|
};
|
|
78
|
+
/**
|
|
79
|
+
* [c209-C] R4 codex 终判 (R5: three-state + exception-safe over `unknown`) — validate
|
|
80
|
+
* `UserMessage.engineSegments` against the text it indexes into.
|
|
81
|
+
* - `absent`: the field is `undefined` (or an empty array — it claims no engine bytes), so the
|
|
82
|
+
* `enginePrefixChars` sugar MAY still apply.
|
|
83
|
+
* - `valid`: EVERY range is well-formed (elements are objects whose `start`/`end` are integers,
|
|
84
|
+
* `0 ≤ start < end ≤ text.length`, ascending and non-overlapping — `prev.end ≤ next.start`).
|
|
85
|
+
* Returns FRESH `{start, end}` copies (canonical plain data, e.g. for the import gate).
|
|
86
|
+
* - `malformed`: anything else — including non-array values (`null`, `{}`), non-object elements
|
|
87
|
+
* (`[null]`), and shape-poison (`[{}]`, string offsets) from old/foreign session data. ONE bad
|
|
88
|
+
* range invalidates the WHOLE field and consumers render the entire message verbatim, prefix
|
|
89
|
+
* suppressed (losing real user text is worse than showing engine bytes). NEVER throws: the input
|
|
90
|
+
* is `unknown` by contract and any exotic shape (throwing getters included) collapses to
|
|
91
|
+
* `malformed`.
|
|
92
|
+
* Shared single source for the mint clamp (agent-harness `createUserMessage`), the session import
|
|
93
|
+
* gate, and every projection side (auto-mode window / compaction serializer / prompt suggestions).
|
|
94
|
+
*/
|
|
18
95
|
export declare function normalizeEngineSegments(text: string, segments: unknown): NormalizedEngineSegments;
|
|
96
|
+
/**
|
|
97
|
+
* [c209-C] R4 codex 终判 — the SEGMENT sibling of {@link cutEnginePrefix}: remove every
|
|
98
|
+
* engine-trusted `[start, end)` segment from a user-lane message, keeping the bytes OUTSIDE the
|
|
99
|
+
* segments verbatim (the caller/operator-authored content that derived views may present under
|
|
100
|
+
* `[user]`/`[User]:` authority). Unlike the prefix cut, segments can sit mid-message: the resume
|
|
101
|
+
* continuation preserves issue order (parked steer first, wake second — the public
|
|
102
|
+
* ResumeOutcome/ResumeRun contract), so a trusted engine frame may legally follow an untrusted
|
|
103
|
+
* fenced one.
|
|
104
|
+
*
|
|
105
|
+
* [c209-C] R5 (codex R4 #1) — the result distinguishes WHY nothing was cut: `malformed:true`
|
|
106
|
+
* means the field was PRESENT but bad (per {@link normalizeEngineSegments}) — the caller must
|
|
107
|
+
* render the whole message verbatim and MUST NOT fall through to `enginePrefixChars` (segments
|
|
108
|
+
* exist ⇒ they own the message; malformed ⇒ the metadata family is suspect wholesale). Only
|
|
109
|
+
* `cut:false, malformed:false` (absent metadata) allows the prefix-sugar fallback. Never throws.
|
|
110
|
+
*/
|
|
19
111
|
export declare function cutEngineSegments(text: string, segments: unknown): {
|
|
20
112
|
text: string;
|
|
21
113
|
cut: boolean;
|
|
22
114
|
malformed: boolean;
|
|
23
115
|
};
|
|
116
|
+
/**
|
|
117
|
+
* [c209-C] R5 (codex R4 #3) — the ONE flatten under which `engineSegments`/`enginePrefixChars`
|
|
118
|
+
* offsets are DEFINED: a user-lane message qualifies only when its content is a plain string or a
|
|
119
|
+
* SINGLE text block (whose text is that same string). Multi-block / image-bearing content returns
|
|
120
|
+
* `undefined` and consumers render the message VERBATIM with their own local flatten — the two
|
|
121
|
+
* projection sides flatten blocks DIFFERENTLY (the auto-mode window joins with `\n` + `[image]`
|
|
122
|
+
* placeholders; the compaction serializer drops non-text blocks and joins with no separator), so a
|
|
123
|
+
* single `[start, end)` range would point at different characters on each side. The restriction
|
|
124
|
+
* costs nothing real: every engine-assembled prefixed/segmented message (first-frame objective
|
|
125
|
+
* concatenation, resume continuation) is minted from ONE plain string — the sole exception is a
|
|
126
|
+
* first-frame objective that ALSO carries user images, which now falls back to verbatim (the
|
|
127
|
+
* accepted conservative direction: engine listing bytes visible under user authority, never lost
|
|
128
|
+
* user text). Single-source helper shared by both projections, the suggestions transcript, and
|
|
129
|
+
* the session import gate. Accepts `unknown` (import-side data) and never throws.
|
|
130
|
+
*/
|
|
24
131
|
export declare function flattenableUserText(content: unknown): string | undefined;
|
|
132
|
+
/**
|
|
133
|
+
* Defuse this module's triple-angle fence sentinels (`<<<` / `>>>`) inside an untrusted body so the body
|
|
134
|
+
* cannot forge {@link delimitUntrusted}'s own OPEN/CLOSE markers and break out of the fence. A worker (or
|
|
135
|
+
* an external page via `web_fetch`, an MCP resource — the label format is open-source, so the close marker
|
|
136
|
+
* `<<<END UNTRUSTED <label>>>>` is guessable) could otherwise emit the literal close marker followed by
|
|
137
|
+
* top-level injection. Caps any run of 3+ identical brackets at 2 consecutive by inserting a zero-width
|
|
138
|
+
* space — the reader still sees the text, but no `<<<`/`>>>` triple survives. Idempotent: a capped run
|
|
139
|
+
* (≤2) never re-matches `{3,}`. Defusing EITHER bracket breaks the marker; we defuse both for symmetry.
|
|
140
|
+
*
|
|
141
|
+
* Residual (council QUESTION, accepted): only ASCII `<`/`>` (U+003C/003E) are defused. A Unicode lookalike
|
|
142
|
+
* (fullwidth `<`/`>`, U+FF1C/FF1E) is NOT — but a fullwidth marker is a DIFFERENT string from the real
|
|
143
|
+
* ASCII close sentinel, so it cannot break out at the string level; at worst it visually resembles the
|
|
144
|
+
* fence to the model. Consistent with this module's "defense-in-depth, NOT a guarantee" posture.
|
|
145
|
+
*
|
|
146
|
+
* Exported (design/138 S2-C, O-F11/C-F10): the memory write-time scan detects a forged fence by diffing
|
|
147
|
+
* `defuseFenceMarkers(text) !== text` — the ONE sentinel definition serves both the defusing and the
|
|
148
|
+
* detection, so the two can never drift apart. Do not hand-copy the `<<<`/`>>>` pattern anywhere else.
|
|
149
|
+
*/
|
|
25
150
|
export declare function defuseFenceMarkers(body: string): string;
|
|
151
|
+
/**
|
|
152
|
+
* design/177 — control-character hygiene for an untrusted BLOCK that is rendered as-is under a framing
|
|
153
|
+
* line (shared-store document content). Two steps, in order:
|
|
154
|
+
* ① fold `\r\n` and a lone `\r` to `\n`, so a carriage return cannot repaint a rendered line;
|
|
155
|
+
* ② scan by code POINT and replace every C0 control except tab and newline, plus the C1 range
|
|
156
|
+
* (U+007F–U+009F), with U+FFFD.
|
|
157
|
+
*
|
|
158
|
+
* REPLACE, never delete — deliberately, and this is the half a naive strip gets wrong: deletion makes a
|
|
159
|
+
* document with an embedded escape sequence read as clean text, while a replacement character is a scar
|
|
160
|
+
* both the model and a human reviewer can see. Surrogate pairs survive intact (the scan is by code
|
|
161
|
+
* point, not by UTF-16 unit).
|
|
162
|
+
*
|
|
163
|
+
* This is the CHARACTER layer only. Structural containment (elevated-authority tags, fence sentinels)
|
|
164
|
+
* is {@link sanitizeUntrustedText} + {@link defuseFenceMarkers}, which the same pipeline applies after
|
|
165
|
+
* this one — a framing line is a discipline statement, tag neutralization is the structural defense,
|
|
166
|
+
* and an untrusted block needs both.
|
|
167
|
+
*/
|
|
26
168
|
export declare function defuseControlChars(text: string): string;
|
|
169
|
+
/**
|
|
170
|
+
* Make untrusted text safe to interpolate INLINE on a trusted prompt line (not inside a {@link delimitUntrusted}
|
|
171
|
+
* fence) — e.g. design/80 D-F echoes a chosen option label into the "The user answered:" block. Folds EVERY
|
|
172
|
+
* line/space separator to a single space so the text cannot forge a new line — `\s` (covers CR/LF/TAB/VT/FF and
|
|
173
|
+
* U+2028/U+2029 + the Unicode spaces) PLUS U+0085 NEL, which `\s` does NOT match — caps the length, then applies
|
|
174
|
+
* the same tag-neutralization (`</system-reminder>`) + fence-sentinel (`<<<`/`>>>`) defusing the fenced body gets.
|
|
175
|
+
* Defense-in-depth, NOT a guarantee (same posture as the rest of this module).
|
|
176
|
+
*/
|
|
27
177
|
export declare function inlineUntrusted(text: string, maxLen?: number): string;
|
|
178
|
+
/**
|
|
179
|
+
* Wrap untrusted text in a clearly labeled opaque fence. The consuming prompt should instruct the model to
|
|
180
|
+
* treat everything inside as untrusted data — never as instructions. Sanitizes internally (system-reminder
|
|
181
|
+
* neutralization + fence-sentinel defusing, on the body AND the label), so callers may pass raw
|
|
182
|
+
* worker/external text — and labels derived from external identifiers (hostnames, resource URIs).
|
|
183
|
+
*/
|
|
28
184
|
export declare function delimitUntrusted(label: string, text: string, maxBody?: number): string;
|
|
@@ -1,37 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/164 件五 — DEPLOYMENT-level usage governance (the seam, its arithmetic, and the in-memory
|
|
3
|
+
* reference implementation).
|
|
4
|
+
*
|
|
5
|
+
* This is a different axis from `TaskSpec.limits`: a task limit is the allowance ONE task asked for,
|
|
6
|
+
* while a usage window is the allowance an OPERATOR grants a principal (or a whole deployment) ACROSS
|
|
7
|
+
* tasks — the shape the industry converged on for account-level governance (a first-use window plus a
|
|
8
|
+
* long rolling one). Core never invents a window: with `RunnerDeps.usageWindows` unset, nothing here
|
|
9
|
+
* runs and no ledger is written.
|
|
10
|
+
*
|
|
11
|
+
* The arithmetic lives HERE, as pure functions over a per-key {@link UsageWindowRecord}, and every
|
|
12
|
+
* store implementation is a persistence shell around them — that is what makes the in-memory and file
|
|
13
|
+
* backends equivalent by construction rather than by two hand-written copies that drift.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* One governed window. Both fields are allowances, not hints: `windowMs` is the window's WIDTH and
|
|
17
|
+
* `maxTokens` the tokens it admits. `anchor` picks between the two window shapes that actually exist in
|
|
18
|
+
* the wild:
|
|
19
|
+
* - `"first-use"` — the window OPENS at the key's first charge and lasts `windowMs`; when it lapses with
|
|
20
|
+
* no further use, the next charge opens a fresh one. This is the "5 hours from when you started"
|
|
21
|
+
* shape: bursty use is admitted at full width, and an idle key is never penalized for old traffic.
|
|
22
|
+
* - `"rolling"` — a continuously sliding window: the charge from `now − windowMs` to `now`. This is the
|
|
23
|
+
* "7 days" shape: it never resets, so sustained use is bounded no matter how it is spread.
|
|
24
|
+
*/
|
|
1
25
|
export interface UsageWindow {
|
|
26
|
+
/** Window width in ms. Must be finite and > 0 (a zero-width window admits nothing and expires
|
|
27
|
+
* instantly — refused at the door rather than silently governing every task to death). */
|
|
2
28
|
windowMs: number;
|
|
29
|
+
/** Tokens the window admits before it is exhausted. Must be finite and >= 0; `0` is a real, always-full
|
|
30
|
+
* window (an operator lock-out), not "unset". */
|
|
3
31
|
maxTokens: number;
|
|
32
|
+
/** Which of the two window shapes above this is. */
|
|
4
33
|
anchor: "first-use" | "rolling";
|
|
5
34
|
}
|
|
35
|
+
/** One charge against a key: `tokens` charged at epoch ms `at`. The unit of the rolling lane's ledger. */
|
|
6
36
|
export interface UsageSlot {
|
|
7
37
|
at: number;
|
|
8
38
|
tokens: number;
|
|
9
39
|
}
|
|
40
|
+
/** The OPEN first-use window for one `windowMs` on one key. Rows for other widths coexist, so a
|
|
41
|
+
* deployment governing 5h and 7d windows keeps one row per width rather than one blended counter. */
|
|
10
42
|
export interface UsageBucketRow {
|
|
43
|
+
/** The width this row belongs to — the row's identity, matched against {@link UsageWindow.windowMs}. */
|
|
11
44
|
windowMs: number;
|
|
45
|
+
/** Epoch ms the window opened (its first charge). */
|
|
12
46
|
openedAt: number;
|
|
47
|
+
/** Tokens charged into it since it opened. */
|
|
13
48
|
tokens: number;
|
|
14
49
|
}
|
|
50
|
+
/** Everything one key's governance state consists of: the rolling lane's slots and the first-use lane's
|
|
51
|
+
* open buckets. Persisted verbatim by every backend (plain JSON, no methods). */
|
|
15
52
|
export interface UsageWindowRecord {
|
|
16
53
|
slots: readonly UsageSlot[];
|
|
17
54
|
buckets: readonly UsageBucketRow[];
|
|
18
55
|
}
|
|
56
|
+
/** The state of one window for one key, as of a given instant. */
|
|
19
57
|
export interface UsageWindowReading {
|
|
58
|
+
/** The window this reading answers for (verbatim, so a caller can name the offending allowance). */
|
|
20
59
|
window: UsageWindow;
|
|
60
|
+
/** Tokens the window currently holds. */
|
|
21
61
|
tokens: number;
|
|
62
|
+
/** `tokens >= window.maxTokens` — the window admits no further work. */
|
|
22
63
|
exhausted: boolean;
|
|
64
|
+
/** Ms until this window next frees capacity: for `first-use`, when the open window lapses; for
|
|
65
|
+
* `rolling`, when its OLDEST in-window slot ages out (which frees that slot's tokens, not
|
|
66
|
+
* necessarily enough for a whole task — a driver that resumes then and re-suspends is behaving
|
|
67
|
+
* correctly, and each attempt gets a fresh, later hint). `0` when the window is not exhausted. */
|
|
23
68
|
retryAfterMs: number;
|
|
24
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* The cross-task token ledger the governance windows are evaluated against. Deliberately two methods and
|
|
72
|
+
* no query language: core charges what a task spent and asks what the key's windows hold — everything
|
|
73
|
+
* else (retention, sharding, multi-writer safety) belongs to the backend.
|
|
74
|
+
*
|
|
75
|
+
* **Keying**: the caller passes a key that is the PRINCIPAL when the task declares one, and a single
|
|
76
|
+
* shared global key otherwise (see `GLOBAL_USAGE_KEY`) — so a multi-tenant deployment governs per tenant
|
|
77
|
+
* and a single-tenant one governs the deployment, with no branch in either.
|
|
78
|
+
*/
|
|
25
79
|
export interface UsageWindowStore {
|
|
80
|
+
/**
|
|
81
|
+
* Charge `tokens` to `key` at epoch ms `at`. `windows` is the deployment's live window set: the store
|
|
82
|
+
* needs it to know which first-use buckets to keep open and how far back the rolling lane must
|
|
83
|
+
* remember, so the ledger stays bounded instead of growing for the life of the deployment.
|
|
84
|
+
* Called once per accounting point; never with a negative or non-finite `tokens`.
|
|
85
|
+
*/
|
|
26
86
|
charge(key: string, tokens: number, at: number, windows: readonly UsageWindow[]): Promise<void>;
|
|
87
|
+
/** Read `key`'s state for each window as of `now`, in the order the windows were given. */
|
|
27
88
|
read(key: string, windows: readonly UsageWindow[], now: number): Promise<readonly UsageWindowReading[]>;
|
|
28
89
|
}
|
|
90
|
+
/** The ledger key for a task that declares NO principal: one shared bucket that governs the whole
|
|
91
|
+
* deployment. Distinctive on purpose — it must never collide with a real principal id. */
|
|
29
92
|
export declare const GLOBAL_USAGE_KEY = "__usage_global__";
|
|
93
|
+
/** A key with no history yet. Frozen: it is handed to callers as a starting value and must not be
|
|
94
|
+
* mutated into a shared-state bug. */
|
|
30
95
|
export declare const EMPTY_USAGE_WINDOW_RECORD: UsageWindowRecord;
|
|
96
|
+
/**
|
|
97
|
+
* Validate `RunnerDeps.usageWindows` at the door and return it unchanged — the `resolveTaskLimits`
|
|
98
|
+
* posture: an unevaluable governance window is not a governance window, and folding it to a default
|
|
99
|
+
* would govern a deployment by a number nobody chose. Refuses with `config.usage_window_invalid`.
|
|
100
|
+
*/
|
|
31
101
|
export declare function resolveUsageWindows(windows: readonly UsageWindow[] | undefined): readonly UsageWindow[] | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Fold one charge into a key's record and return the NEW record (pure — the input is never mutated, so a
|
|
104
|
+
* store that keeps records in a Map cannot be corrupted by a half-applied charge).
|
|
105
|
+
*
|
|
106
|
+
* Retention is part of the fold rather than a separate sweep: slots older than the widest ROLLING window
|
|
107
|
+
* can never be read again, and a first-use bucket for a width the deployment no longer governs can never
|
|
108
|
+
* be read again either, so both are dropped here. A record therefore stays bounded by (charges within the
|
|
109
|
+
* widest rolling window) + (one row per governed first-use width).
|
|
110
|
+
*/
|
|
32
111
|
export declare function chargeUsageRecord(record: UsageWindowRecord, tokens: number, at: number, windows: readonly UsageWindow[]): UsageWindowRecord;
|
|
112
|
+
/**
|
|
113
|
+
* Read a key's record against the governed windows as of `now` (pure). The `first-use` lane reads the open
|
|
114
|
+
* bucket; the `rolling` lane sums the slots inside `(now − windowMs, now]`.
|
|
115
|
+
*/
|
|
33
116
|
export declare function readUsageRecord(record: UsageWindowRecord, windows: readonly UsageWindow[], now: number): UsageWindowReading[];
|
|
117
|
+
/**
|
|
118
|
+
* The TIGHTEST binding constraint across a set of readings: how long the caller must wait before ANY
|
|
119
|
+
* window would admit work again. `undefined` when nothing is exhausted. The MAXIMUM (not the minimum) of
|
|
120
|
+
* the exhausted windows' hints — resuming when the shortest one clears would immediately re-suspend on
|
|
121
|
+
* the longer one.
|
|
122
|
+
*/
|
|
34
123
|
export declare function usageRetryAfterMs(readings: readonly UsageWindowReading[]): number | undefined;
|
|
124
|
+
/**
|
|
125
|
+
* Process-local {@link UsageWindowStore} reference implementation. Governs correctly within ONE Runner
|
|
126
|
+
* process and loses its ledger on restart — the right choice for tests and single-process deployments,
|
|
127
|
+
* and explicitly NOT the right choice for a fleet (use the file backend, or a real database, when the
|
|
128
|
+
* governance must survive a restart or span replicas).
|
|
129
|
+
*/
|
|
35
130
|
export declare class InMemoryUsageWindowStore implements UsageWindowStore {
|
|
36
131
|
private readonly records;
|
|
37
132
|
charge(key: string, tokens: number, at: number, windows: readonly UsageWindow[]): Promise<void>;
|
package/dist/core/version.d.ts
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
import type { Runner } from "./runner/runtask.js";
|
|
2
2
|
import type { TaskResult, TaskSpec } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* design/114 P0 — a convenience for the RECOMMENDED safe warm-resume of a (failed / timed-out) run: FORK the
|
|
5
|
+
* session, then run a continuation on the fork. Fork-first is the safe path (design/114 §3.2):
|
|
6
|
+
* - **idempotent** — each call branches a FRESH session, so resuming twice can't corrupt the source's linear
|
|
7
|
+
* history (vs `runTask({sessionId})` reuse, which appends two divergent continuations onto one history);
|
|
8
|
+
* - **orphan-safe** — the fork drops an in-flight tool call (`settledForkOptions`), so a continuation of an agent
|
|
9
|
+
* that died mid-tool-call gets a clean point rather than inheriting an `[INTERRUPTED]` orphan;
|
|
10
|
+
* - **fail-loud** — a missing source returns `null`; it NEVER silently starts a fresh EMPTY run the way
|
|
11
|
+
* `runTask({sessionId})` would via create-on-miss (the "looks warm, actually fresh" trap). Cross-restart /
|
|
12
|
+
* cross-replica warm-resume therefore requires a DURABLE `SessionRepo` — an in-memory fork is lost on restart.
|
|
13
|
+
*
|
|
14
|
+
* Returns `null` when the store can't fork OR the source session is gone — the caller decides what to do (surface
|
|
15
|
+
* an error, fall back, etc.), never a silent fresh run. `sessionId` typically comes from a failed
|
|
16
|
+
* `WorkflowAgentRun.sessionId` (design/114) or a prior `TaskResult.sessionId`. The continuation's `objective` is
|
|
17
|
+
* the directive for picking up the work; pass the model (and any other spec fields) via `opts` — a continuation
|
|
18
|
+
* still needs a model like any task.
|
|
19
|
+
*/
|
|
3
20
|
export declare function warmResume(runner: Runner, sessionId: string, objective: string, opts?: Omit<Partial<TaskSpec>, "objective" | "sessionId"> & {
|
|
4
21
|
owner?: string | null;
|
|
5
22
|
}): Promise<TaskResult | null>;
|
|
@@ -1,41 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* design/173 — the wiring manifest: a machine-readable disclosure of HOW this deployment/run is
|
|
3
|
+
* assembled around the optional human-interaction seams (ask / question / elicit / park lane /
|
|
4
|
+
* durability / fleet observability / governance surfaces).
|
|
5
|
+
*
|
|
6
|
+
* GUARANTEE BOUNDARY (design/173 §0): this is STATIC ASSEMBLY SELF-DISCLOSURE — seam presence and
|
|
7
|
+
* shape, as facts. It does NOT prove liveness (a callback bound to the wrong run, a dead queue, an
|
|
8
|
+
* adapter's internal failure, an answer routed to the wrong instance). Liveness belongs to
|
|
9
|
+
* round-trip probes, which are a separate obligation. Nothing here may claim "the wiring was
|
|
10
|
+
* verified" — only "the wiring was disclosed". This module provides no liveness API, deliberately;
|
|
11
|
+
* consumers (e.g. a park-wiring startup self-check) must quote this boundary rather than promise
|
|
12
|
+
* more than the manifest can know.
|
|
13
|
+
*
|
|
14
|
+
* TWO HALVES, ONE SCHEMA (design/173 §2.1): the STATIC half ({@link describeStaticWiring}) is a pure
|
|
15
|
+
* synchronous function over `(deps, spec)` — a server startup self-check. Facts it cannot compute
|
|
16
|
+
* (per-principal runtime caps, the prepare-time safety-tool vocabulary) are reported `"unresolved"`,
|
|
17
|
+
* never guessed, and `ask.effective` is OMITTED entirely (reporting "would park" as "auto-deny"
|
|
18
|
+
* would be a false fact, worse than silence). The EFFECTIVE half is built once per prepared leg by
|
|
19
|
+
* `prepareTask` from RESOLVED facts, through the SAME {@link deriveWiringManifest} derivation — two
|
|
20
|
+
* copies of the derivation would drift, so there is exactly one. A startup snapshot and a leg's
|
|
21
|
+
* effective snapshot are two DIFFERENT facts; neither may impersonate the other.
|
|
22
|
+
*/
|
|
1
23
|
import type { RunnerDeps, TaskSpec } from "./types.js";
|
|
2
24
|
import { type StoreDurability } from "./checkpoint-store.js";
|
|
3
25
|
export type { StoreDurability };
|
|
26
|
+
/** The manifest-face projection of {@link StoreDurability}: `"declared_durable"` (the name says it —
|
|
27
|
+
* a DECLARATION relayed, not a verification) vs `"process_local"` (declared so, or fail-closed
|
|
28
|
+
* absent). */
|
|
4
29
|
export type ManifestDurability = "declared_durable" | "process_local";
|
|
30
|
+
/** Which prepare leg an EFFECTIVE manifest describes (`leg` is absent on the static half — a
|
|
31
|
+
* startup self-check has no leg). taskId/parentTaskId ride the event's `TaskEventIdentity`, not
|
|
32
|
+
* this object (design/173 §8.4). "Every leg self-evidences" means ON ITS OWN STREAM: a delegated
|
|
33
|
+
* child's manifest rides the CHILD's event stream and is deliberately not in the parent-forwarding
|
|
34
|
+
* whitelist — a host that wants a child's assembly evidence subscribes to the child. */
|
|
5
35
|
export type WiringLegKind = "root" | "child" | "resume";
|
|
36
|
+
/** The shape of the resolved permission-ask seat (`spec.onAsk ?? deps.onAsk`): a live approver
|
|
37
|
+
* callback, a blanket `"allow"`/`"deny"` policy setting, or nothing at all. `"deny"` (a deliberate
|
|
38
|
+
* policy) and `"absent"` (a degrade to the headless auto-deny default) are DISTINCT on purpose —
|
|
39
|
+
* design/173 codex 5. */
|
|
6
40
|
export type AskSeamForm = "callback" | "allow" | "deny" | "absent";
|
|
41
|
+
/** What a policy `ask` actually reaches under this assembly. `"unresolved"` = not computable from
|
|
42
|
+
* the facts at hand (the static half's park-dependent arm). */
|
|
7
43
|
export type AskEffective = "human_reachable" | "auto_allow" | "auto_deny" | "park_only" | "unresolved";
|
|
44
|
+
/**
|
|
45
|
+
* The content-question channel, three-valued (design/173 §8.2 — a derived enum, not a bare
|
|
46
|
+
* boolean): `"wired"` (a resolved `onQuestion` face exists), `"absent"` (none), or
|
|
47
|
+
* `"stripped_bg_lane"` — the ENGINE deliberately stripped the spawn turn's per-request face from a
|
|
48
|
+
* long-lived background/retained leg (correct design, not a configuration lie; the flag is minted
|
|
49
|
+
* ONLY by the engine's strip sites, pair-produced with the strip itself — never inferred from spec
|
|
50
|
+
* shape).
|
|
51
|
+
*/
|
|
8
52
|
export type QuestionChannelState = "wired" | "absent" | "stripped_bg_lane";
|
|
53
|
+
/** Which seat supplied a resolved seam value (`spec` wins over `deps` everywhere). Tree-internal
|
|
54
|
+
* child legs read `"spec"` for inherited faces by construction — the delegation lane copies the
|
|
55
|
+
* parent's effective face onto the child SPEC seat (design/173 opus F7). */
|
|
9
56
|
export type SeamProvenance = "spec" | "deps";
|
|
57
|
+
/** Machine-readable reason codes for a park lane that is not (or not provably) effective. */
|
|
10
58
|
export type ParkLaneReason = "no_checkpoint_store" | "no_durable_approval_opt_in" | "no_force_durable_gate" | "no_armed_safety_vocabulary" | "await_runtime_caps" | "await_tool_vocabulary";
|
|
59
|
+
/**
|
|
60
|
+
* design/173 §2.2/§8.4 — the wiring manifest. Consumers MUST ignore unknown fields
|
|
61
|
+
* (`schemaVersion` bumps only on a semantic break of an EXISTING field). The TaskEvent face is the
|
|
62
|
+
* host/operator plane — the manifest never enters model context.
|
|
63
|
+
*/
|
|
11
64
|
export interface WiringManifest {
|
|
12
65
|
schemaVersion: 1;
|
|
66
|
+
/** Present on EFFECTIVE (per-leg) manifests only; the static half has no leg. */
|
|
13
67
|
leg?: {
|
|
14
68
|
kind: WiringLegKind;
|
|
15
69
|
};
|
|
16
70
|
ask: {
|
|
17
71
|
form: AskSeamForm;
|
|
72
|
+
/** Absent iff `form === "absent"` (no seat supplied a value — a fabricated provenance would be
|
|
73
|
+
* a false fact). */
|
|
18
74
|
provenance?: SeamProvenance;
|
|
75
|
+
/** OMITTED on the static half (design/173 §8.4): the absent-form arm depends on the park lane,
|
|
76
|
+
* which the static half cannot always resolve. Always present on the effective half. */
|
|
19
77
|
effective?: AskEffective;
|
|
20
78
|
};
|
|
21
79
|
question: {
|
|
80
|
+
/** Three-valued channel state — see {@link QuestionChannelState}. The field keeps the frozen
|
|
81
|
+
* design name `wired`. */
|
|
22
82
|
wired: QuestionChannelState;
|
|
83
|
+
/** Present iff `wired === "wired"`. */
|
|
23
84
|
provenance?: SeamProvenance;
|
|
85
|
+
/**
|
|
86
|
+
* design/173 §3 (F13, effective half only) — the composition-lie detector:
|
|
87
|
+
* `interactiveTools === true` mounted the question tool while NO delivery face exists (no live
|
|
88
|
+
* `onQuestion`, no durable park consumer, not an engine-stripped lane). The model will be
|
|
89
|
+
* offered a question tool whose answers can reach nobody. Always disclosed here; under
|
|
90
|
+
* posture `"interactive"` the prepare door additionally refuses the leg.
|
|
91
|
+
*/
|
|
24
92
|
interactiveToolsWithoutDeliveryFace?: true;
|
|
25
93
|
};
|
|
94
|
+
/** The interaction-posture declaration (the prepare door's input): `"interactive"` promises a
|
|
95
|
+
* reachable human and the door refuses a leg that cannot deliver one, `"headless"` documents the
|
|
96
|
+
* opposite, `"absent"` = no declaration (no check). Until this field existed, posture was the one
|
|
97
|
+
* interactive-face declaration the manifest did not report. */
|
|
26
98
|
interaction: {
|
|
27
99
|
posture: "interactive" | "headless" | "absent";
|
|
28
100
|
};
|
|
101
|
+
/** `seamWired` = a deployment `onElicit` seam exists. Seam presence ≠ the elicitation family is
|
|
102
|
+
* usable: the other half is per-server opt-in (`spec.mcp[].elicitation === true`), counted in
|
|
103
|
+
* `serversOptedIn` (statically readable from the spec). */
|
|
29
104
|
elicit: {
|
|
30
105
|
seamWired: boolean;
|
|
31
106
|
serversOptedIn: number;
|
|
32
107
|
};
|
|
33
108
|
parkLane: {
|
|
109
|
+
/** A checkpoint store is wired (capability — design/173 codex 13: capability and current policy
|
|
110
|
+
* are reported separately). */
|
|
34
111
|
capable: boolean;
|
|
112
|
+
/** capable ∧ (durableApproval opt-in ∨ forceDurableGate entitlement ∨ armed safety-tool
|
|
113
|
+
* vocabulary). `"unresolved"` on a static half that cannot decide (runtime caps / tool
|
|
114
|
+
* vocabulary are prepare-time facts). */
|
|
35
115
|
effective: boolean | "unresolved";
|
|
116
|
+
/** Why `effective` is `false`/`"unresolved"` — empty when `true`. The derivation chain an
|
|
117
|
+
* operator follows from `static unresolved` to `effective park unavailable` (codex 7). */
|
|
36
118
|
reasons: readonly ParkLaneReason[];
|
|
119
|
+
/** design/173 §8.4 (opus R7): the DECLARED durability of the resolved checkpoint store — an
|
|
120
|
+
* armed park lane over a process-local store is the "armed but memory-backed" degrade shape
|
|
121
|
+
* §1 names, and it must be reportable. Present iff `capable`. */
|
|
37
122
|
checkpointDurability?: ManifestDurability;
|
|
38
123
|
};
|
|
124
|
+
/** The session store's DECLARED durability (declaration relayed verbatim — never class-name
|
|
125
|
+
* sniffing; absent declaration reads fail-closed as `process_local`). */
|
|
39
126
|
session: {
|
|
40
127
|
store: ManifestDurability;
|
|
41
128
|
};
|
|
@@ -43,9 +130,19 @@ export interface WiringManifest {
|
|
|
43
130
|
backgroundAgentStore: boolean;
|
|
44
131
|
hostChildEventSink: boolean;
|
|
45
132
|
};
|
|
133
|
+
/** design/179 — the persisted allow-rule seam. The ONE loosening seam in the assembly, so its presence
|
|
134
|
+
* is a fact an operator has to be able to read off the manifest rather than infer. `false` on a
|
|
135
|
+
* deployment that wired no store, which is the shape the field has to have: an absent field would say
|
|
136
|
+
* "this build has no such feature", and a present-and-false one says "it exists and is off here". */
|
|
46
137
|
permissionRules: {
|
|
47
138
|
storeWired: boolean;
|
|
48
139
|
};
|
|
140
|
+
/**
|
|
141
|
+
* Governance surfaces (presence facts only). `audience: "operator"` is the MACHINE-READABLE
|
|
142
|
+
* projection classification (design/173 codex 9): a serving layer forwarding this event to a
|
|
143
|
+
* multi-tenant/shared stream MUST project this section for operators only — and when it does no
|
|
144
|
+
* projection, the default is to NOT disclose the section, never to leak it.
|
|
145
|
+
*/
|
|
49
146
|
governance: {
|
|
50
147
|
audience: "operator";
|
|
51
148
|
lockedConfig: boolean;
|
|
@@ -53,27 +150,47 @@ export interface WiringManifest {
|
|
|
53
150
|
memoryAdmission: boolean;
|
|
54
151
|
retention: boolean;
|
|
55
152
|
};
|
|
153
|
+
/** EFFECTIVE half only — a short, non-sensitive fingerprint (sha256 prefix over the canonical
|
|
154
|
+
* JSON of this manifest's own resolved facts; every field here is an enum/boolean/count, no
|
|
155
|
+
* secrets) so an operator can correlate legs that ran under the same resolved assembly. */
|
|
56
156
|
configFingerprint?: string;
|
|
57
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* The FULL fact set both halves derive from — one input shape, one derivation
|
|
160
|
+
* ({@link deriveWiringManifest}), so the halves cannot drift. `undefined` on the optional park
|
|
161
|
+
* atoms means "not knowable at this half" and derives `"unresolved"`, never a guess.
|
|
162
|
+
*/
|
|
58
163
|
export interface WiringFacts {
|
|
59
164
|
half: "static" | "effective";
|
|
165
|
+
/** Required on the effective half; must be absent on the static half. */
|
|
60
166
|
leg?: WiringLegKind;
|
|
61
167
|
askForm: AskSeamForm;
|
|
62
168
|
askProvenance?: SeamProvenance;
|
|
63
169
|
questionWired: boolean;
|
|
64
170
|
questionProvenance?: SeamProvenance;
|
|
171
|
+
/** The engine-minted strip flag (trusted RunInternals channel) — effective half only; the static
|
|
172
|
+
* half has no run internals and never reports `stripped_bg_lane`. */
|
|
65
173
|
questionStrippedByEngine?: boolean;
|
|
174
|
+
/** F13 composition-lie fact (effective half only). */
|
|
66
175
|
interactiveToolsWithoutDeliveryFace?: boolean;
|
|
176
|
+
/** The interaction-posture declaration this half can see: the static half reads `spec ?? deps`,
|
|
177
|
+
* the effective half reports the RESOLVED posture (spec > spawning parent > deps). Absent = no
|
|
178
|
+
* declaration anywhere — reported as `"absent"`, never guessed. */
|
|
67
179
|
interactionPosture?: "interactive" | "headless";
|
|
68
180
|
elicitSeamWired: boolean;
|
|
69
181
|
elicitServersOptedIn: number;
|
|
70
182
|
parkCapable: boolean;
|
|
71
183
|
parkDurableApprovalOptIn: boolean;
|
|
184
|
+
/** `undefined` = unresolved at this half (per-principal runtime caps are a prepare-time fact). */
|
|
72
185
|
parkForceDurableGate?: boolean;
|
|
186
|
+
/** `undefined` = unresolved at this half (the irreversible/egress tool vocabulary is assembled in
|
|
187
|
+
* prepare). */
|
|
73
188
|
parkSafetyVocabularyArmed?: boolean;
|
|
189
|
+
/** Present iff `parkCapable` (the resolved checkpoint store's declaration). */
|
|
74
190
|
checkpointDurability?: StoreDurability;
|
|
75
191
|
sessionDurability: StoreDurability;
|
|
76
192
|
backgroundAgentStoreWired: boolean;
|
|
193
|
+
/** design/179 — a persisted allow-rule store provider is wired. */
|
|
77
194
|
permissionRuleStoreWired: boolean;
|
|
78
195
|
hostChildEventSinkWired: boolean;
|
|
79
196
|
lockedConfigWired: boolean;
|
|
@@ -81,21 +198,73 @@ export interface WiringFacts {
|
|
|
81
198
|
memoryAdmissionWired: boolean;
|
|
82
199
|
retentionPolicyWired: boolean;
|
|
83
200
|
}
|
|
201
|
+
/** Named view of the deps seats the static half reads (a `Pick` of the real {@link RunnerDeps} —
|
|
202
|
+
* single-source shapes, no parallel hand-copied interface). */
|
|
84
203
|
export type StaticWiringDeps = Pick<RunnerDeps, "onAsk" | "onQuestion" | "interactionPosture" | "onElicit" | "checkpointStore" | "sessionStore" | "backgroundAgentStore" | "onBackgroundChildEvent" | "lockedConfig" | "compliancePostureResolver" | "memoryScopeAdmission" | "retentionPolicy" | "permissionRuleStore">;
|
|
204
|
+
/** Named view of the spec seats the static half reads (a `Pick` of the real {@link TaskSpec}). */
|
|
85
205
|
export type StaticWiringSpec = Pick<TaskSpec, "onAsk" | "onQuestion" | "checkpointStore" | "durableApproval" | "mcp" | "interactiveTools" | "interactionPosture">;
|
|
206
|
+
/**
|
|
207
|
+
* Read a store's {@link StoreDurability} declaration: absent ⇒ `"process-local"` (fail-closed —
|
|
208
|
+
* under-promise, never over-promise), a declared value passes through, and an UNPARSEABLE value is
|
|
209
|
+
* refused loudly (`config.store_durability_invalid`) — a junk declaration silently folded to either
|
|
210
|
+
* arm would be a manifest that lies in whichever direction the fold picked.
|
|
211
|
+
*/
|
|
86
212
|
export declare function resolveDeclaredDurability(store: {
|
|
87
213
|
readonly durability?: StoreDurability;
|
|
88
214
|
} | undefined, storeName: string): StoreDurability;
|
|
215
|
+
/**
|
|
216
|
+
* The ONE `ask.effective` derivation (design/173 codex 5) — shared by the effective manifest AND
|
|
217
|
+
* the posture door (`config.interaction_posture`), so "what does the door require" and "what does
|
|
218
|
+
* the manifest report" can never disagree:
|
|
219
|
+
* - a live approver callback ⇒ `human_reachable` (regardless of the park lane);
|
|
220
|
+
* - blanket `"allow"`/`"deny"` ⇒ the park lane decides first: a string seat is NOT a live approver,
|
|
221
|
+
* so on an armed park lane the ask parks and the honest report is `park_only` — reporting the
|
|
222
|
+
* blanket as what the ask "reaches" would be a false fact of exactly the kind this module refuses.
|
|
223
|
+
* Off the park lane the blanket is what happens: the deliberate auto policies;
|
|
224
|
+
* - no seat at all ⇒ the park lane decides: armed ⇒ `park_only`, unresolved ⇒ `unresolved`,
|
|
225
|
+
* else the headless degrade `auto_deny`.
|
|
226
|
+
*/
|
|
89
227
|
export declare function deriveAskEffective(form: AskSeamForm, parkEffective: boolean | "unresolved"): AskEffective;
|
|
228
|
+
/**
|
|
229
|
+
* design/173 §2.1 — the SINGLE derivation from facts to manifest, shared by both halves. The static
|
|
230
|
+
* half omits `ask.effective`, `leg` and the fingerprint; the effective half carries all three. Any
|
|
231
|
+
* second construction point for {@link WiringManifest} is a defect (single-mint rule).
|
|
232
|
+
*/
|
|
90
233
|
export declare function deriveWiringManifest(facts: WiringFacts): WiringManifest;
|
|
234
|
+
/** The one ask-seat resolution (`spec` wins over `deps`), shared with the effective half so the
|
|
235
|
+
* form/provenance read cannot fork. Junk values (a JS caller passing something outside the OnAsk
|
|
236
|
+
* union) are refused loudly — a manifest must not classify what it cannot name. */
|
|
91
237
|
export declare function resolveAskSeamForm(spec: Pick<TaskSpec, "onAsk">, deps: Pick<RunnerDeps, "onAsk">): {
|
|
92
238
|
form: AskSeamForm;
|
|
93
239
|
provenance?: SeamProvenance;
|
|
94
240
|
};
|
|
241
|
+
/** The one question-seat resolution (`spec` wins over `deps`), shared by both halves. Review fold
|
|
242
|
+
* r2-F2: a NON-FUNCTION present value (a JS caller passing `onQuestion: null`/junk) is refused
|
|
243
|
+
* loudly — the engine's `??` resolution would keep it, the mount's presence check would count it,
|
|
244
|
+
* and the manifest would report `wired` for a callback nothing can ever call.
|
|
245
|
+
*
|
|
246
|
+
* design/174: "a value is present" is NOT the criterion — `wired` is derived through THE shared
|
|
247
|
+
* {@link isLiveQuestionFace} predicate, the same one the gate routes on. The reserved
|
|
248
|
+
* `QUESTION_AWAITS_RESUME` placeholder is a function and is the documented standard assembly of the
|
|
249
|
+
* durable topology, but its whole contract is that it never runs; reporting it as a wired channel
|
|
250
|
+
* told an operator a question could reach a person in-stream when the only real delivery face on
|
|
251
|
+
* that assembly is the park lane (which this manifest reports separately, and honestly). */
|
|
95
252
|
export declare function resolveQuestionSeam(spec: Pick<TaskSpec, "onQuestion">, deps: Pick<RunnerDeps, "onQuestion">): {
|
|
96
253
|
wired: boolean;
|
|
97
254
|
provenance?: SeamProvenance;
|
|
98
255
|
};
|
|
256
|
+
/** Count of MCP servers that opted into elicitation on this spec (the per-server half of the
|
|
257
|
+
* elicit capability — statically readable). */
|
|
99
258
|
export declare function countElicitOptIns(spec: Pick<TaskSpec, "mcp">): number;
|
|
259
|
+
/** The one elicit-seat resolution, shared by both halves (review fold r3-F3 — the onQuestion rule
|
|
260
|
+
* applies here too): absent ⇒ not wired; a function ⇒ wired; a present NON-function (a JS caller
|
|
261
|
+
* passing null/junk) is refused loudly rather than reported as a live seam nothing can call. */
|
|
100
262
|
export declare function resolveElicitSeam(deps: Pick<RunnerDeps, "onElicit">): boolean;
|
|
263
|
+
/**
|
|
264
|
+
* design/173 §2.1 — the STATIC half: a pure synchronous description of what `(deps, spec)` can
|
|
265
|
+
* prove about the wiring, for a server's startup self-check. Facts that only prepare can resolve
|
|
266
|
+
* (per-principal runtime caps, the safety-tool vocabulary) derive `"unresolved"`; `ask.effective`
|
|
267
|
+
* is omitted entirely (see the module doc). This is DISCLOSURE, not verification — see the §0
|
|
268
|
+
* guarantee boundary above. `spec` may be omitted for a spec-less deployment self-check.
|
|
269
|
+
*/
|
|
101
270
|
export declare function describeStaticWiring(deps: StaticWiringDeps, spec?: StaticWiringSpec): WiringManifest;
|