@sema-agent/core 7.52.0 → 7.54.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 +470 -0
- package/LICENSE +3 -1
- package/README.md +3 -1
- package/dist/agents/cross-session-envelope.d.ts +8 -0
- package/dist/agents/cross-session-envelope.js +6 -0
- package/dist/agents/cross-session-judge.d.ts +21 -1
- package/dist/agents/cross-session-judge.js +8 -0
- package/dist/agents/cross-session-ref.d.ts +5 -0
- package/dist/agents/cross-session-ref.js +1 -0
- package/dist/agents/org-delivery-gate.d.ts +122 -0
- package/dist/agents/org-delivery-gate.js +69 -0
- package/dist/agents/peer-held-queue.d.ts +9 -4
- package/dist/agents/peer-held-queue.js +6 -5
- package/dist/agents/peer-session-drain.d.ts +35 -6
- package/dist/agents/peer-session-drain.js +271 -182
- package/dist/agents/read-inbox-tool.d.ts +7 -0
- package/dist/agents/read-inbox-tool.js +5 -1
- package/dist/agents/send-message-tool.js +3 -4
- package/dist/agents/subagent.d.ts +6 -5
- package/dist/agents/subagent.js +117 -83
- package/dist/agents/tool-filter.d.ts +25 -4
- package/dist/agents/tool-filter.js +13 -3
- package/dist/brain/anthropic.d.ts +6 -1
- package/dist/brain/anthropic.js +4 -4
- package/dist/brain/model-presets.js +2 -1
- package/dist/brain/route-adjudicator.d.ts +6 -0
- package/dist/brain/routing.d.ts +24 -1
- package/dist/brain/routing.js +54 -19
- package/dist/brain/timeout.js +5 -4
- package/dist/core/a2a.d.ts +5 -2
- package/dist/core/a2a.js +33 -14
- package/dist/core/allow-entry.d.ts +3 -1
- package/dist/core/allow-entry.js +3 -2
- package/dist/core/approval-object.d.ts +87 -0
- package/dist/core/approval-object.js +85 -0
- package/dist/core/arg-summary.d.ts +3 -2
- package/dist/core/arg-summary.js +17 -11
- package/dist/core/ask-origin.d.ts +43 -27
- package/dist/core/ask-origin.js +20 -11
- package/dist/core/ask-question.d.ts +0 -1
- package/dist/core/ask-question.js +4 -67
- package/dist/core/ask-unresolvable-notice.d.ts +3 -2
- package/dist/core/auto-compaction.d.ts +106 -50
- package/dist/core/auto-compaction.js +69 -53
- package/dist/core/auto-mode-prompt.d.ts +4 -2
- package/dist/core/auto-mode-prompt.js +4 -3
- package/dist/core/canonical-json.d.ts +69 -0
- package/dist/core/canonical-json.js +130 -8
- package/dist/core/checkpoint-requirements.d.ts +13 -7
- package/dist/core/checkpoint-requirements.js +4 -1
- package/dist/core/checkpoint-store.d.ts +60 -36
- package/dist/core/checkpoint-store.js +7 -6
- package/dist/core/child-clamp-seats.d.ts +45 -6
- package/dist/core/child-clamp-seats.js +56 -4
- package/dist/core/compliance.js +3 -1
- package/dist/core/consolidate-scope.d.ts +1 -1
- package/dist/core/cross-boundary-taint.d.ts +213 -0
- package/dist/core/cross-boundary-taint.js +196 -0
- package/dist/core/decision-receipt.d.ts +44 -1
- package/dist/core/decision-receipt.js +16 -0
- package/dist/core/effective-path-target.d.ts +28 -6
- package/dist/core/effective-path-target.js +28 -2
- package/dist/core/engine-notice.d.ts +47 -4
- package/dist/core/engine-notice.js +17 -1
- package/dist/core/engine-storage-backend.d.ts +73 -0
- package/dist/core/engine-storage-backend.js +1 -0
- package/dist/core/file-history-store.d.ts +6 -2
- package/dist/core/file-history-store.js +1 -0
- package/dist/core/gate-fold.js +13 -4
- package/dist/core/gate-lanes.js +41 -34
- package/dist/core/gate-outcome.d.ts +18 -9
- package/dist/core/governance-codes.d.ts +9 -2
- package/dist/core/governance-codes.js +9 -0
- package/dist/core/hands-band-screen.d.ts +7 -0
- package/dist/core/hands-band-screen.js +32 -0
- package/dist/core/hooks.d.ts +21 -19
- package/dist/core/hooks.js +6 -5
- package/dist/core/locked-config.d.ts +110 -31
- package/dist/core/locked-config.js +155 -42
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mcp-probe.js +1 -1
- package/dist/core/mcp-server-spec.d.ts +152 -17
- package/dist/core/mcp-server-spec.js +223 -40
- package/dist/core/mcp.d.ts +21 -14
- package/dist/core/mcp.js +59 -54
- package/dist/core/memory-engine/engine.d.ts +14 -19
- package/dist/core/memory-engine/engine.js +9 -6
- package/dist/core/memory-engine/export-bundle.d.ts +1 -1
- package/dist/core/memory-engine/export-bundle.js +1 -1
- package/dist/core/memory-engine/file-backend.d.ts +2 -6
- package/dist/core/memory-engine/file-backend.js +1 -12
- package/dist/core/memory.d.ts +3 -3
- package/dist/core/mode-policy.d.ts +16 -26
- package/dist/core/mode-policy.js +5 -18
- package/dist/core/mods/kernel/dispatch.js +13 -15
- package/dist/core/mods/kernel/events.d.ts +9 -6
- package/dist/core/mods/kernel/events.js +2 -2
- package/dist/core/mods/kernel/receive.d.ts +41 -11
- package/dist/core/mods/kernel/receive.js +124 -54
- package/dist/core/mods/kernel/site-rules.d.ts +80 -15
- package/dist/core/mods/kernel/site-rules.js +232 -40
- package/dist/core/mods/stations.d.ts +0 -6
- package/dist/core/mods/stations.js +0 -7
- package/dist/core/mounted-mcp.d.ts +57 -0
- package/dist/core/mounted-mcp.js +71 -2
- package/dist/core/own-property-receipt.d.ts +13 -0
- package/dist/core/own-property-receipt.js +3 -1
- package/dist/core/parent-spec-seat.d.ts +12 -15
- package/dist/core/parent-spec-seat.js +14 -6
- package/dist/core/pause-registry.d.ts +35 -1
- package/dist/core/pause-registry.js +10 -0
- package/dist/core/permission-rule-consent.d.ts +18 -5
- package/dist/core/permission-rule-consent.js +13 -8
- package/dist/core/permission-rule-model.d.ts +87 -15
- package/dist/core/permission-rule-model.js +87 -8
- package/dist/core/permission-rule-org.d.ts +200 -33
- package/dist/core/permission-rule-org.js +217 -91
- package/dist/core/permission-rule-session.js +2 -2
- package/dist/core/permission-rule-store.d.ts +8 -0
- package/dist/core/permission-rule-store.js +1 -0
- package/dist/core/permission-rule-sync.js +3 -2
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +37 -8
- package/dist/core/read-only-shell.d.ts +1 -1
- package/dist/core/read-only-shell.js +30 -9
- package/dist/core/remote-env.d.ts +41 -1
- package/dist/core/remote-env.js +18 -0
- package/dist/core/resume-startup-cause.d.ts +18 -0
- package/dist/core/resume-startup-cause.js +12 -0
- package/dist/core/retention.js +7 -2
- package/dist/core/retired-keys.d.ts +8 -2
- package/dist/core/retired-keys.js +12 -1
- package/dist/core/roles.js +60 -10
- package/dist/core/rule-lane-reads.js +1 -1
- package/dist/core/runner/approval-feedback.d.ts +46 -0
- package/dist/core/runner/approval-feedback.js +41 -0
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/compaction-call-options.js +2 -2
- package/dist/core/runner/contracts.d.ts +34 -41
- package/dist/core/runner/cross-boundary-lane.d.ts +87 -0
- package/dist/core/runner/cross-boundary-lane.js +190 -0
- package/dist/core/runner/decide-continuation.d.ts +4 -4
- package/dist/core/runner/decide-continuation.js +3 -1
- package/dist/core/runner/gate-exit.d.ts +32 -12
- package/dist/core/runner/gate-exit.js +77 -34
- package/dist/core/runner/inherited-ask-grants.js +2 -2
- package/dist/core/runner/mcp-redial.d.ts +52 -10
- package/dist/core/runner/mcp-redial.js +38 -9
- package/dist/core/runner/permission-rule-lanes.d.ts +5 -2
- package/dist/core/runner/permission-rule-lanes.js +22 -10
- package/dist/core/runner/person-path-rows.d.ts +5 -3
- package/dist/core/runner/person-path-rows.js +2 -2
- package/dist/core/runner/prepare-acquire-reconcile.d.ts +3 -4
- package/dist/core/runner/prepare-acquire-reconcile.js +3 -3
- package/dist/core/runner/prepare-ask-lane.js +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +6 -5
- package/dist/core/runner/prepare-caps-and-workflow.js +3 -3
- package/dist/core/runner/prepare-config-doors.d.ts +58 -15
- package/dist/core/runner/prepare-config-doors.js +167 -146
- package/dist/core/runner/prepare-context-lane.js +6 -3
- package/dist/core/runner/prepare-defer-classify.js +4 -7
- package/dist/core/runner/prepare-delegation-surface.d.ts +5 -4
- package/dist/core/runner/prepare-delegation-surface.js +8 -7
- package/dist/core/runner/prepare-execution-env.d.ts +1 -2
- package/dist/core/runner/prepare-execution-env.js +2 -1
- package/dist/core/runner/prepare-gate-stations.d.ts +2 -0
- package/dist/core/runner/prepare-gate-stations.js +4 -3
- package/dist/core/runner/prepare-hands-readface.d.ts +3 -3
- package/dist/core/runner/prepare-hands-readface.js +3 -2
- package/dist/core/runner/prepare-inherited-gate.d.ts +2 -0
- package/dist/core/runner/prepare-inherited-gate.js +3 -2
- package/dist/core/runner/prepare-listings.d.ts +1 -1
- package/dist/core/runner/prepare-listings.js +4 -2
- package/dist/core/runner/prepare-memory-engine-session.d.ts +0 -6
- package/dist/core/runner/prepare-memory-engine-session.js +19 -6
- package/dist/core/runner/prepare-memory.d.ts +3 -2
- package/dist/core/runner/prepare-memory.js +6 -2
- package/dist/core/runner/prepare-offload-wrappers.d.ts +4 -4
- package/dist/core/runner/prepare-offload-wrappers.js +2 -1
- package/dist/core/runner/prepare-park-ask.d.ts +1 -1
- package/dist/core/runner/prepare-park-ask.js +9 -3
- package/dist/core/runner/prepare-policy-chain.d.ts +1 -1
- package/dist/core/runner/prepare-policy-chain.js +14 -19
- package/dist/core/runner/prepare-project-context.d.ts +1 -1
- package/dist/core/runner/prepare-project-context.js +6 -4
- package/dist/core/runner/prepare-prompt-assembly.d.ts +1 -1
- package/dist/core/runner/prepare-prompt-assembly.js +20 -16
- package/dist/core/runner/prepare-prompt-inputs.d.ts +12 -6
- package/dist/core/runner/prepare-prompt-inputs.js +6 -3
- package/dist/core/runner/prepare-protocol-tools.d.ts +7 -5
- package/dist/core/runner/prepare-protocol-tools.js +19 -12
- package/dist/core/runner/prepare-question-face.d.ts +4 -2
- package/dist/core/runner/prepare-question-face.js +4 -3
- package/dist/core/runner/prepare-safety-scan.d.ts +7 -2
- package/dist/core/runner/prepare-safety-scan.js +34 -27
- package/dist/core/runner/prepare-suspend-saga.d.ts +2 -2
- package/dist/core/runner/prepare-suspend-saga.js +6 -2
- package/dist/core/runner/prepare-task.js +22 -19
- package/dist/core/runner/prepare-turn-wiring.d.ts +10 -5
- package/dist/core/runner/prepare-turn-wiring.js +14 -49
- package/dist/core/runner/prepare-wiring-manifest.d.ts +10 -5
- package/dist/core/runner/prepare-wiring-manifest.js +9 -6
- package/dist/core/runner/prepare-workspace-restore.js +2 -2
- package/dist/core/runner/resume-admission.d.ts +4 -1
- package/dist/core/runner/resume-admission.js +16 -14
- package/dist/core/runner/resume-apply.js +4 -4
- package/dist/core/runner/resume-internals-and-config.d.ts +3 -3
- package/dist/core/runner/resume-internals-and-config.js +3 -8
- package/dist/core/runner/resume-policy-outcome.d.ts +2 -2
- package/dist/core/runner/resume-policy-outcome.js +18 -15
- package/dist/core/runner/resume-preflight.js +2 -2
- package/dist/core/runner/resume-review-outcome.js +3 -3
- package/dist/core/runner/retired-runner-deps.d.ts +5 -6
- package/dist/core/runner/retired-runner-deps.js +1 -4
- package/dist/core/runner/run-leg.js +97 -43
- package/dist/core/runner/run-recovery-lanes.js +5 -3
- package/dist/core/runner/run-settle-and-teardown.js +2 -0
- package/dist/core/runner/run-terminal-adoption.js +21 -9
- package/dist/core/runner/run-turn-boundary.js +9 -3
- package/dist/core/runner/runtask.js +1 -1
- package/dist/core/runner/session-file-state-replay.d.ts +5 -2
- package/dist/core/runner/session-file-state-replay.js +3 -2
- package/dist/core/runner/skills-seat.d.ts +15 -0
- package/dist/core/runner/skills-seat.js +57 -0
- package/dist/core/runner/stream-steer-verb.js +2 -2
- package/dist/core/runner/sub-agent-deny-lists.d.ts +13 -11
- package/dist/core/runner/sub-agent-deny-lists.js +7 -5
- package/dist/core/runner/synthetic-tools.d.ts +5 -2
- package/dist/core/runner/synthetic-tools.js +2 -12
- package/dist/core/runner/tool-face-overlay.d.ts +24 -6
- package/dist/core/runner/tool-face-overlay.js +24 -15
- package/dist/core/runner-deps.d.ts +37 -22
- package/dist/core/session-policy-store.d.ts +19 -0
- package/dist/core/session-policy-store.js +22 -2
- package/dist/core/session-store.d.ts +35 -16
- package/dist/core/session-store.js +20 -12
- package/dist/core/{shell-lexer.d.ts → shell-run-candidates.d.ts} +36 -12
- package/dist/core/{shell-lexer.js → shell-run-candidates.js} +145 -225
- package/dist/core/shell-wrapper-table.d.ts +5 -3
- package/dist/core/shell-wrapper-table.js +1 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.js +13 -0
- package/dist/core/store-contracts/session-store-contract.d.ts +49 -0
- package/dist/core/store-contracts/session-store-contract.js +639 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.d.ts +12 -0
- package/dist/core/store-contracts/session-store-incarnation-contract.js +5 -2
- package/dist/core/task-event.d.ts +44 -6
- package/dist/core/task-notification.js +2 -2
- package/dist/core/task-registry-agent.js +1 -0
- package/dist/core/task-registry-shared.d.ts +5 -0
- package/dist/core/task-registry.d.ts +7 -0
- package/dist/core/task-registry.js +17 -0
- package/dist/core/task-result.d.ts +1 -1
- package/dist/core/task-spec.d.ts +7 -7
- package/dist/core/tighten-task-spec.d.ts +6 -4
- package/dist/core/tighten-task-spec.js +2 -2
- package/dist/core/tool-catalog-entries.d.ts +1 -1
- package/dist/core/tool-catalog-entries.js +52 -52
- package/dist/core/tool-face-reader.d.ts +49 -0
- package/dist/core/tool-face-reader.js +94 -0
- package/dist/core/tool-face.d.ts +17 -8
- package/dist/core/tool-face.js +1 -0
- package/dist/core/tool-policy.d.ts +67 -23
- package/dist/core/tool-policy.js +72 -60
- package/dist/core/tool-roster.d.ts +46 -28
- package/dist/core/tool-roster.js +91 -14
- package/dist/core/tool-spec-members.js +2 -2
- package/dist/core/tool-spec.d.ts +20 -4
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +24 -2
- package/dist/core/types.d.ts +3 -3
- package/dist/core/types.js +1 -1
- package/dist/core/untrusted-text.d.ts +23 -0
- package/dist/core/untrusted-text.js +10 -10
- package/dist/core/user-attachment.d.ts +56 -2
- package/dist/core/user-attachment.js +139 -56
- package/dist/core/wiring-manifest.d.ts +4 -2
- package/dist/engine/compaction/compaction.d.ts +2 -2
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/harness/agent-harness.js +2 -1
- package/dist/engine/harness/types.d.ts +10 -4
- package/dist/engine/llm/types.d.ts +7 -2
- package/dist/engine/llm/types.js +2 -1
- package/dist/engine/loop/agent-loop.d.ts +12 -1
- package/dist/engine/loop/agent-loop.js +17 -5
- package/dist/engine/loop/types.d.ts +7 -1
- package/dist/engine/session/repo-utils.d.ts +5 -0
- package/dist/engine/session/repo-utils.js +9 -0
- package/dist/engine/session/storage-base.js +2 -2
- package/dist/index.d.ts +37 -17
- package/dist/index.js +31 -14
- package/dist/internal/harness.d.ts +1 -0
- package/dist/internal/harness.js +1 -0
- package/dist/internal/llm.d.ts +1 -1
- package/dist/internal/llm.js +1 -1
- package/dist/orchestration/goal.d.ts +24 -1
- package/dist/orchestration/goal.js +3 -2
- package/dist/orchestration/run-workflow-tool.d.ts +3 -0
- package/dist/orchestration/run-workflow-tool.js +1 -0
- package/dist/orchestration/workflow-governance.d.ts +1 -1
- package/dist/orchestration/workflow.d.ts +3 -0
- package/dist/orchestration/workflow.js +2 -1
- package/dist/prompt-assembly/artifact-store.d.ts +44 -9
- package/dist/prompt-assembly/artifact-store.js +38 -12
- package/dist/prompt-assembly/artifact.d.ts +12 -11
- package/dist/prompt-assembly/artifact.js +52 -21
- package/dist/prompt-assembly/assemble.d.ts +2 -0
- package/dist/prompt-assembly/assemble.js +2 -1
- package/dist/prompt-assembly/catalog/index.js +2 -1
- package/dist/prompt-assembly/catalog/memory.d.ts +13 -0
- package/dist/prompt-assembly/catalog/memory.js +6 -0
- package/dist/prompt-assembly/catalog/schema.d.ts +19 -2
- package/dist/prompt-assembly/catalog/schema.js +3 -0
- package/dist/prompt-assembly/composer.d.ts +2 -0
- package/dist/prompt-assembly/composer.js +1 -1
- package/dist/prompt-assembly/overlay.d.ts +21 -11
- package/dist/prompt-assembly/overlay.js +57 -19
- package/dist/prompt-assembly/select.d.ts +21 -6
- package/dist/prompt-assembly/select.js +41 -4
- package/dist/prompts/default.d.ts +1 -12
- package/dist/prompts/default.js +0 -3
- package/dist/shell/lex.d.ts +87 -8
- package/dist/shell/lex.js +283 -49
- package/dist/stores/file/index.d.ts +8 -6
- package/dist/stores/file/permission-rule-store.d.ts +1 -1
- package/dist/stores/file/permission-rule-store.js +2 -1
- package/dist/tools/artifact/artifact-tool.js +14 -3
- package/dist/tools/fs/bash-program-position.d.ts +3 -15
- package/dist/tools/fs/bash-program-position.js +3 -10
- package/dist/tools/fs/bash-readonly-classifier.js +2 -0
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-bash.js +72 -101
- package/dist/tools/fs/fs-read.d.ts +12 -0
- package/dist/tools/fs/fs-read.js +10 -9
- package/dist/tools/fs/fs-shared.d.ts +27 -31
- package/dist/tools/fs/fs-shared.js +12 -15
- package/dist/tools/fs/fs-write.js +1 -1
- package/dist/tools/fs/index.js +2 -2
- package/dist/tools/fs/read-deny-home.d.ts +1 -1
- package/dist/tools/fs/read-deny-home.js +5 -4
- package/dist/tools/fs/read-deny.d.ts +16 -3
- package/dist/tools/fs/read-deny.js +12 -9
- package/dist/tools/fs/safety.d.ts +7 -6
- package/dist/tools/fs/shell-read-bindings.d.ts +5 -3
- package/dist/tools/fs/shell-read-bindings.js +15 -16
- package/dist/tools/fs/shell-read-device.js +1 -1
- package/dist/tools/fs/shell-read-plan.js +36 -47
- package/dist/tools/fs/shell-read-word.d.ts +1 -6
- package/dist/tools/fs/shell-read-word.js +2 -20
- package/dist/tools/fs/shell-reentry-text.js +1 -1
- package/dist/tools/web.d.ts +2 -2
- package/package.json +4 -1
- package/test/export-surface.snapshot.json +5651 -5457
- package/wire-changes/core@7.53.0.json +1968 -0
- package/wire-changes/core@7.54.0.json +2870 -0
- package/dist/core/shell-scan.d.ts +0 -60
- package/dist/core/shell-scan.js +0 -183
|
@@ -3,8 +3,9 @@ import { describeFault, isPlainRecord, receive } from "../core/mods/kernel/recei
|
|
|
3
3
|
import { egressText } from "../core/untrusted-egress.js";
|
|
4
4
|
import { bandOf, isBandId } from "./bands.js";
|
|
5
5
|
import { SEMA_DEFAULT_CATALOG, catalogMessage } from "./catalog/index.js";
|
|
6
|
-
import { HOST_FORMS, HOST_ROLES, OVERLAY_OPS, PROMPT_FACT_NAMES, PROMPT_TRAITS, isWordOf, } from "./catalog/schema.js";
|
|
6
|
+
import { HOST_FORMS, HOST_ROLES, OVERLAY_OPS, PROMPT_FACT_NAMES, PROMPT_TRAITS, isHostRole, isWordOf, } from "./catalog/schema.js";
|
|
7
7
|
import { RENDERERS } from "./renderers.js";
|
|
8
|
+
import { canonicalWhen } from "./select.js";
|
|
8
9
|
export const OVERLAY_SOURCE_ORDER = Object.freeze(["bundled", "task", "center", "deploy"]);
|
|
9
10
|
export const ABSENT_THIS_RUN = "(absent this run)";
|
|
10
11
|
const SECTION_BY_ID = new Map(SEMA_DEFAULT_CATALOG.sections.map((s) => [s.id, s]));
|
|
@@ -40,16 +41,49 @@ export function assembledRoleRefused(field, hits) {
|
|
|
40
41
|
return Object.assign(new Error(`prompt.assembled_role_refused: ${field} contains, verbatim, the locked text of ${named.slice(0, 4).join(", ")}${named.length > 4 ? ` and ${named.length - 4} more` : ""} — the engine composes the locked sections itself; supply only the role layer (an already-assembled prompt is refused, never passed through)`), { code: "prompt.assembled_role_refused" });
|
|
41
42
|
}
|
|
42
43
|
const ID_GRAMMAR = /^[a-z0-9][a-z0-9/._-]*$/;
|
|
43
|
-
const OVERLAY_KEYS = new Set(["id", "op", "target", "text", "message", "
|
|
44
|
+
const OVERLAY_KEYS = new Set(["id", "op", "target", "text", "message", "when"]);
|
|
44
45
|
const OPS = new Set(OVERLAY_OPS);
|
|
45
46
|
const PROMPT_DATA = Object.freeze({ accessors: "refuse", depth: 4, others: "refuse", freeze: true, isProxy: (v) => types.isProxy(v) });
|
|
46
47
|
export function receivePromptData(raw) {
|
|
47
48
|
const r = receive(raw, PROMPT_DATA);
|
|
48
49
|
return r.ok ? { value: r.value } : { notData: describeFault(r.fault) };
|
|
49
50
|
}
|
|
50
|
-
const
|
|
51
|
+
export const PROMPT_BINDING_MAX_CHARS = 128;
|
|
52
|
+
export const PROMPT_BINDING_LIST_MAX = 64;
|
|
53
|
+
export function codePointsOver(s, max) {
|
|
54
|
+
if (s.length <= max)
|
|
55
|
+
return false;
|
|
56
|
+
if (s.length > 2 * max)
|
|
57
|
+
return true;
|
|
58
|
+
let n = 0;
|
|
59
|
+
for (const _ of s)
|
|
60
|
+
if (++n > max)
|
|
61
|
+
return true;
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
51
64
|
function bindingProblem(v) {
|
|
52
|
-
return typeof v !== "string" || v.trim() === "" || v
|
|
65
|
+
return typeof v !== "string" || v.trim() === "" || codePointsOver(v, PROMPT_BINDING_MAX_CHARS) ? `${str(v)} is not a non-blank string of at most ${PROMPT_BINDING_MAX_CHARS} characters (code points)` : undefined;
|
|
66
|
+
}
|
|
67
|
+
function bindingConditionProblem(b) {
|
|
68
|
+
if (!isPlainRecord(b))
|
|
69
|
+
return `"when.binding" is ${Array.isArray(b) ? "an array" : str(b)}, not { anyOf: [...] } or { noneOf: [...] }`;
|
|
70
|
+
const keys = Object.keys(b);
|
|
71
|
+
const k = keys[0];
|
|
72
|
+
if (keys.length !== 1 || (k !== "anyOf" && k !== "noneOf"))
|
|
73
|
+
return `"when.binding" carries ${keys.length === 0 ? "no list" : keys.map((x) => str(x)).join(", ")} (exactly one of anyOf, noneOf)`;
|
|
74
|
+
const list = b[k];
|
|
75
|
+
if (!Array.isArray(list) || list.length === 0)
|
|
76
|
+
return `"when.binding.${k}" is ${Array.isArray(list) ? "empty" : str(list)}, not a list naming at least one binding`;
|
|
77
|
+
if (list.length > PROMPT_BINDING_LIST_MAX)
|
|
78
|
+
return `"when.binding.${k}" names ${list.length} bindings (at most ${PROMPT_BINDING_LIST_MAX})`;
|
|
79
|
+
for (const name of list) {
|
|
80
|
+
const why = bindingProblem(name);
|
|
81
|
+
if (why !== undefined)
|
|
82
|
+
return `"when.binding.${k}": ${why}`;
|
|
83
|
+
}
|
|
84
|
+
if (new Set(list).size !== list.length)
|
|
85
|
+
return `"when.binding.${k}" names a binding twice`;
|
|
86
|
+
return undefined;
|
|
53
87
|
}
|
|
54
88
|
export function resolvePromptBinding(task) {
|
|
55
89
|
if (task.promptBinding === undefined)
|
|
@@ -69,8 +103,8 @@ function whenViolation(when) {
|
|
|
69
103
|
if (typeof when !== "object" || when === null || Array.isArray(when))
|
|
70
104
|
return `"when" is ${str(when)}, not an object`;
|
|
71
105
|
for (const k of Object.keys(when))
|
|
72
|
-
if (k !== "traits" && k !== "host" && k !== "facts")
|
|
73
|
-
return `"when" carries ${str(k)} (traits, host, facts only)`;
|
|
106
|
+
if (k !== "traits" && k !== "host" && k !== "facts" && k !== "binding")
|
|
107
|
+
return `"when" carries ${str(k)} (traits, host, facts, binding only)`;
|
|
74
108
|
const w = when;
|
|
75
109
|
if (w["traits"] !== undefined) {
|
|
76
110
|
const t = w["traits"];
|
|
@@ -91,7 +125,7 @@ function whenViolation(when) {
|
|
|
91
125
|
if (typeof h !== "object" || h === null || Array.isArray(h))
|
|
92
126
|
return `"when.host" is not an object`;
|
|
93
127
|
for (const [k, v] of Object.entries(h)) {
|
|
94
|
-
if (k === "role" ? !
|
|
128
|
+
if (k === "role" ? !isHostRole(v) : k === "form" ? !isWordOf(HOST_FORMS, v) : true) {
|
|
95
129
|
return `"when.host" carries ${str(k)} = ${str(v)} (role: ${HOST_ROLES.join(" | ")}; form: ${HOST_FORMS.join(" | ")})`;
|
|
96
130
|
}
|
|
97
131
|
}
|
|
@@ -107,6 +141,8 @@ function whenViolation(when) {
|
|
|
107
141
|
return `"when.facts.${k}" is ${str(v)}, not a boolean`;
|
|
108
142
|
}
|
|
109
143
|
}
|
|
144
|
+
if (w["binding"] !== undefined)
|
|
145
|
+
return bindingConditionProblem(w["binding"]);
|
|
110
146
|
return undefined;
|
|
111
147
|
}
|
|
112
148
|
function textsOf(o) {
|
|
@@ -124,11 +160,14 @@ export function validateOverlay(raw, ctx) {
|
|
|
124
160
|
const r = received.value;
|
|
125
161
|
if (!isPlainRecord(r))
|
|
126
162
|
return fail(`an overlay is an object, got ${Array.isArray(r) ? "an array" : str(r)}`);
|
|
127
|
-
for (const k of Object.keys(r))
|
|
128
|
-
if (
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
163
|
+
for (const k of Object.keys(r)) {
|
|
164
|
+
if (OVERLAY_KEYS.has(k))
|
|
165
|
+
continue;
|
|
166
|
+
const rewrite = k === "scope" ? `; an overlay names its binding as "when": { "binding": { "anyOf": [<binding>] } }` : "";
|
|
167
|
+
return fail(`an overlay carries ${str(k)} (id, op, target, text, message, when only)${rewrite}`);
|
|
168
|
+
}
|
|
169
|
+
const { id, op, target, text, message, when } = r;
|
|
170
|
+
if (typeof id !== "string" || id.length === 0 || codePointsOver(id, 128) || !ID_GRAMMAR.test(id))
|
|
132
171
|
return fail(`overlay id ${str(id)} is not ^[a-z0-9][a-z0-9/._-]*$ of at most 128 characters`);
|
|
133
172
|
if (id.startsWith("core/") && ctx.sugar !== true)
|
|
134
173
|
return fail(`overlay id ${str(id)}: the core/ namespace is the engine's own`);
|
|
@@ -150,11 +189,6 @@ export function validateOverlay(raw, ctx) {
|
|
|
150
189
|
if (why !== undefined)
|
|
151
190
|
return fail(`overlay "${id}": ${why}`);
|
|
152
191
|
}
|
|
153
|
-
if (scope !== undefined && ctx.source !== "center")
|
|
154
|
-
return fail(`overlay "${id}": "scope" selects among a center artifact's overlays; a ${ctx.source} overlay answers for this run`);
|
|
155
|
-
if (scope !== undefined && (!isPlainRecord(scope) || Object.entries(scope).some(([k, v]) => k !== "binding" || bindingProblem(v) !== undefined))) {
|
|
156
|
-
return fail(`overlay "${id}": "scope" is { binding?: a non-blank string of at most ${BINDING_MAX} characters }`);
|
|
157
|
-
}
|
|
158
192
|
let band;
|
|
159
193
|
let where;
|
|
160
194
|
if (op === "add") {
|
|
@@ -191,14 +225,14 @@ export function validateOverlay(raw, ctx) {
|
|
|
191
225
|
}
|
|
192
226
|
if (ctx.event !== undefined && row.modsEvent !== ctx.event)
|
|
193
227
|
return fail(`overlay "${id}": ${where} is written through ${row.modsEvent ?? "no mods event"}, not ${ctx.event}`);
|
|
228
|
+
const normalWhen = canonicalWhen(when);
|
|
194
229
|
const overlay = Object.freeze({
|
|
195
230
|
id,
|
|
196
231
|
op: op,
|
|
197
232
|
target,
|
|
198
233
|
...(text !== undefined ? { text: text } : {}),
|
|
199
234
|
...(message !== undefined ? { message: message } : {}),
|
|
200
|
-
...(
|
|
201
|
-
...(when !== undefined ? { when: when } : {}),
|
|
235
|
+
...(normalWhen !== undefined ? { when: normalWhen } : {}),
|
|
202
236
|
});
|
|
203
237
|
for (const t of textsOf(overlay)) {
|
|
204
238
|
const hits = lockedTextIn(t);
|
|
@@ -255,6 +289,10 @@ export function foldOverlays(ordered, selectedText, applies, overlayText) {
|
|
|
255
289
|
addedBy.delete(o.target);
|
|
256
290
|
continue;
|
|
257
291
|
}
|
|
292
|
+
if (!SECTION_BY_ID.has(o.target)) {
|
|
293
|
+
supersede(me, o.target, ABSENT_THIS_RUN);
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
258
296
|
for (const m of sectionMessages(o.target)) {
|
|
259
297
|
for (const w of writers.get(m) ?? [])
|
|
260
298
|
supersede(w, m, o.id);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The selector: the one reading that picks, for a catalog message, the variant a run receives — and decides
|
|
3
|
-
* whether an overlay's `when` applies to this run.
|
|
4
|
-
* ever needs a precedence order:
|
|
3
|
+
* whether an overlay's `when` applies to this run (every source class alike). Four dimensions, each with exactly one
|
|
4
|
+
* writer, so no value ever needs a precedence order:
|
|
5
5
|
*
|
|
6
6
|
* - `traits` — derived from the run's two prompt-shape axes by {@link promptTraitsOf} (the prompt profile and the
|
|
7
7
|
* fable-family model); catalog data reads traits, never the axes.
|
|
@@ -9,10 +9,12 @@
|
|
|
9
9
|
* `form` (`TaskSpec.promptForm`, which every engine-built child receives through the parent spec seat; absent ⇒
|
|
10
10
|
* `standard`).
|
|
11
11
|
* - `facts` — the runtime facts prepare produces (one derived: `executionEnvironmentDeclared`).
|
|
12
|
+
* - `binding` — the deployment's scenario name (`TaskSpec.promptBinding`, an open vocabulary; absent ⇒ none).
|
|
12
13
|
*
|
|
13
|
-
* A
|
|
14
|
-
* equal,
|
|
14
|
+
* A `when` is a conjunction: every listed trait present, every `noneOf` trait absent, every host key equal, every
|
|
15
|
+
* fact equal, the binding inside its `anyOf` (or outside its `noneOf`). No disjunction across dimensions.
|
|
15
16
|
*/
|
|
17
|
+
import type { PromptManifestSelectors } from "../core/trace.js";
|
|
16
18
|
import { type CatalogMessage, type FactConjunction, type HostForm, type HostRole, type PromptFactName, type PromptTrait, type Variant, type VariantWhen } from "./catalog/schema.js";
|
|
17
19
|
import type { PromptRuntimeFacts } from "./types.js";
|
|
18
20
|
/** The run's selector values, resolved once per assembly. */
|
|
@@ -23,6 +25,7 @@ export interface PromptSelectors {
|
|
|
23
25
|
readonly form: HostForm;
|
|
24
26
|
};
|
|
25
27
|
readonly facts: Readonly<Record<PromptFactName, boolean>>;
|
|
28
|
+
readonly binding?: string;
|
|
26
29
|
}
|
|
27
30
|
/**
|
|
28
31
|
* The run's prompt traits, derived from the two prompt-shape axes the engine resolves today: the simple
|
|
@@ -44,13 +47,25 @@ export declare function resolveHost(task: {
|
|
|
44
47
|
readonly role?: HostRole;
|
|
45
48
|
readonly form?: HostForm;
|
|
46
49
|
};
|
|
47
|
-
/** The run's selectors: traits and facts from the runtime facts, the host from its two writers' values
|
|
50
|
+
/** The run's selectors — their one mint: traits and facts from the runtime facts, the host from its two writers' values,
|
|
51
|
+
* the binding as the task's door validated it. */
|
|
48
52
|
export declare function selectorsOf(facts: PromptRuntimeFacts, host?: {
|
|
49
53
|
readonly role?: HostRole;
|
|
50
54
|
readonly form?: HostForm;
|
|
51
|
-
}): PromptSelectors;
|
|
55
|
+
}, binding?: string): PromptSelectors;
|
|
56
|
+
/** The selectors' plain form (traits sorted): what the manifest shows, the identity's `binding` element digests and the
|
|
57
|
+
* `prompt.compose` event carries — one record. */
|
|
58
|
+
export declare function selectorRecordOf(s: PromptSelectors): PromptManifestSelectors;
|
|
52
59
|
export declare function factsHold(conj: FactConjunction | undefined, facts: Readonly<Record<PromptFactName, boolean>>): boolean;
|
|
53
60
|
/** Whether a `when` holds under the run's selectors. */
|
|
54
61
|
export declare function whenHolds(when: VariantWhen | undefined, s: PromptSelectors): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* A `when` in its normal form — the one spelling of what it asks: every list sorted and without repeats, a conjunct that
|
|
64
|
+
* asks nothing (an empty `traits`, `host` or `facts`, an empty list) left out, and a condition left with no conjunct
|
|
65
|
+
* (`{}`) is no condition at all (`undefined`). Two conditions that hold in the same runs by construction are equal as
|
|
66
|
+
* values here, so the overlay door (`validateOverlay`) hands every reader — the artifact digest, the publish-side
|
|
67
|
+
* conflict check — the same condition. Idempotent; it never changes which runs a condition holds for.
|
|
68
|
+
*/
|
|
69
|
+
export declare function canonicalWhen(when: VariantWhen | undefined): VariantWhen | undefined;
|
|
55
70
|
/** The variant this run receives, or undefined when no variant's `when` holds (the message is absent). */
|
|
56
71
|
export declare function selectVariant(message: CatalogMessage, s: PromptSelectors): Variant | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HOST_ROLES,
|
|
1
|
+
import { HOST_ROLES, isHostRole } from "./catalog/schema.js";
|
|
2
2
|
export function promptTraitsOf(facts) {
|
|
3
3
|
const traits = new Set();
|
|
4
4
|
if (facts.promptProfile !== "classic")
|
|
@@ -32,17 +32,26 @@ export function resolveHost(task) {
|
|
|
32
32
|
code: "config.prompt_selector_invalid",
|
|
33
33
|
});
|
|
34
34
|
};
|
|
35
|
-
const role = task.promptRole === undefined ? undefined :
|
|
35
|
+
const role = task.promptRole === undefined ? undefined : isHostRole(task.promptRole) ? task.promptRole : refuse("promptRole", task.promptRole, HOST_ROLES);
|
|
36
36
|
const form = task.promptForm === undefined ? undefined : task.promptForm === "minimal" ? "minimal" : refuse("promptForm", task.promptForm, ["minimal"]);
|
|
37
37
|
return Object.freeze({ ...(role !== undefined ? { role } : {}), ...(form !== undefined ? { form } : {}) });
|
|
38
38
|
}
|
|
39
|
-
export function selectorsOf(facts, host = {}) {
|
|
39
|
+
export function selectorsOf(facts, host = {}, binding) {
|
|
40
40
|
return Object.freeze({
|
|
41
41
|
traits: promptTraitsOf(facts),
|
|
42
42
|
host: Object.freeze({ role: host.role ?? "general", form: host.form ?? "standard" }),
|
|
43
43
|
facts: Object.freeze(catalogFactsOf(facts)),
|
|
44
|
+
...(binding !== undefined ? { binding } : {}),
|
|
44
45
|
});
|
|
45
46
|
}
|
|
47
|
+
export function selectorRecordOf(s) {
|
|
48
|
+
return {
|
|
49
|
+
...(s.binding !== undefined ? { binding: s.binding } : {}),
|
|
50
|
+
traits: [...s.traits].sort(),
|
|
51
|
+
host: { role: s.host.role, form: s.host.form },
|
|
52
|
+
facts: { ...s.facts },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
46
55
|
export function factsHold(conj, facts) {
|
|
47
56
|
if (conj === undefined)
|
|
48
57
|
return true;
|
|
@@ -61,8 +70,36 @@ function hostHolds(cond, host) {
|
|
|
61
70
|
return true;
|
|
62
71
|
return (cond.role === undefined || cond.role === host.role) && (cond.form === undefined || cond.form === host.form);
|
|
63
72
|
}
|
|
73
|
+
function bindingHolds(cond, binding) {
|
|
74
|
+
if (cond === undefined)
|
|
75
|
+
return true;
|
|
76
|
+
if (cond.anyOf !== undefined)
|
|
77
|
+
return binding !== undefined && cond.anyOf.includes(binding);
|
|
78
|
+
return binding === undefined || !cond.noneOf.includes(binding);
|
|
79
|
+
}
|
|
64
80
|
export function whenHolds(when, s) {
|
|
65
|
-
return when === undefined || (traitsHold(when.traits, s.traits) && hostHolds(when.host, s.host) && factsHold(when.facts, s.facts));
|
|
81
|
+
return when === undefined || (traitsHold(when.traits, s.traits) && hostHolds(when.host, s.host) && factsHold(when.facts, s.facts) && bindingHolds(when.binding, s.binding));
|
|
82
|
+
}
|
|
83
|
+
const byText = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
84
|
+
const sortedSet = (xs) => Object.freeze([...new Set(xs ?? [])].sort(byText));
|
|
85
|
+
export function canonicalWhen(when) {
|
|
86
|
+
if (when === undefined)
|
|
87
|
+
return undefined;
|
|
88
|
+
const allOf = sortedSet(when.traits?.allOf);
|
|
89
|
+
const noneOf = sortedSet(when.traits?.noneOf);
|
|
90
|
+
const hostKeys = Object.keys(when.host ?? {});
|
|
91
|
+
const factNames = Object.keys(when.facts ?? {}).sort(byText);
|
|
92
|
+
const binding = when.binding;
|
|
93
|
+
const out = {};
|
|
94
|
+
if (allOf.length > 0 || noneOf.length > 0)
|
|
95
|
+
out.traits = Object.freeze({ ...(allOf.length > 0 ? { allOf } : {}), ...(noneOf.length > 0 ? { noneOf } : {}) });
|
|
96
|
+
if (hostKeys.length > 0)
|
|
97
|
+
out.host = Object.freeze({ ...when.host });
|
|
98
|
+
if (factNames.length > 0)
|
|
99
|
+
out.facts = Object.freeze(Object.fromEntries(factNames.map((n) => [n, when.facts[n]])));
|
|
100
|
+
if (binding !== undefined)
|
|
101
|
+
out.binding = Object.freeze(binding.anyOf !== undefined ? { anyOf: sortedSet(binding.anyOf) } : { noneOf: sortedSet(binding.noneOf) });
|
|
102
|
+
return Object.keys(out).length === 0 ? undefined : Object.freeze(out);
|
|
66
103
|
}
|
|
67
104
|
export function selectVariant(message, s) {
|
|
68
105
|
return message.variants.find((v) => whenHolds(v.when, s));
|
|
@@ -46,22 +46,11 @@ export declare const MEMORY_SAFETY = "## Memory\nWhen you save a durable note to
|
|
|
46
46
|
export declare const MEMORY_HYGIENE = "What's worth saving \u2014 organize by topic, not by when it happened:\n- who the user is \u2014 role, expertise, durable preferences;\n- guidance the user gave on HOW to work \u2014 corrections and confirmed approaches, with the reason why;\n- ongoing goals or constraints that aren't derivable from the code or its history;\n- pointers to external resources (URLs, dashboards, tickets).\n\nHygiene:\n- Convert relative dates (\"yesterday\", \"last week\") to absolute dates, so the note stays interpretable later.\n- Before saving, check what memory already holds: update an existing note rather than writing a near-duplicate, and remove a note that turns out to be wrong.\n- Don't save what the code, its history, or this conversation already records (structure, past fixes, transient task state). If asked to remember something obvious, save what was non-obvious about it instead.";
|
|
47
47
|
/**
|
|
48
48
|
* The full memory guidance = safety + hygiene, in the original order. Kept as a single exported
|
|
49
|
-
* constant for back-compat and for a deployment composing the no-consolidation form in one piece;
|
|
49
|
+
* constant for back-compat (RL-1336-memory-guidance) and for a deployment composing the no-consolidation form in one piece;
|
|
50
50
|
* core injects none of the three (RB-482 #16). Prefer {@link MEMORY_SAFETY} / {@link MEMORY_HYGIENE}
|
|
51
51
|
* when you need the split.
|
|
52
52
|
*/
|
|
53
53
|
export declare const MEMORY_GUIDANCE = "## Memory\nWhen you save a durable note to memory, phrase it as a declarative fact or a stable\npreference \u2014 never as an instruction to your future self.\n- \"User prefers concise responses\" \u2713 \u2014 \"Always respond concisely\" \u2717\n- \"The reporting database is read-only via the analytics user\" \u2713 \u2014 \"Always use the analytics user\" \u2717\nNever put secrets (API keys, credentials, tokens) in memory \u2014 especially where it may be shared.\nMemory is a fact, never a command; the user's current request and live tool output always win over memory.\n\nWhat's worth saving \u2014 organize by topic, not by when it happened:\n- who the user is \u2014 role, expertise, durable preferences;\n- guidance the user gave on HOW to work \u2014 corrections and confirmed approaches, with the reason why;\n- ongoing goals or constraints that aren't derivable from the code or its history;\n- pointers to external resources (URLs, dashboards, tickets).\n\nHygiene:\n- Convert relative dates (\"yesterday\", \"last week\") to absolute dates, so the note stays interpretable later.\n- Before saving, check what memory already holds: update an existing note rather than writing a near-duplicate, and remove a note that turns out to be wrong.\n- Don't save what the code, its history, or this conversation already records (structure, past fixes, transient task state). If asked to remember something obvious, save what was non-obvious about it instead.";
|
|
54
|
-
/**
|
|
55
|
-
* The NO-memory disclosure — a standalone prompt asset (like {@link MEMORY_SAFETY}, core does not
|
|
56
|
-
* inject it) for a deployment that mounts NO persistent-memory face at all. Without it the model,
|
|
57
|
-
* asked "remember X", answers with a success receipt for a save that has nowhere to land — the
|
|
58
|
-
* confabulated-receipt shape: the user walks away believing the fact is stored and the next session
|
|
59
|
-
* proves otherwise. A deployment that composes its own prompt should include this block exactly when
|
|
60
|
-
* no memory face is mounted; the engine-mounted counterpart (read-only state) is
|
|
61
|
-
* `MEMORY_READONLY_NOTICE` in the memory engine, injected automatically. Name-free by construction
|
|
62
|
-
* (#181 class): it names no tool, so it cannot go stale against any toolkit.
|
|
63
|
-
*/
|
|
64
|
-
export declare const NO_PERSISTENT_MEMORY_NOTICE = "# Memory\n\nYou have no persistent memory store: what is said in this conversation is not automatically retained for future sessions. If the user asks you to remember something for later, say plainly that you cannot store it \u2014 do not claim to have noted or saved it. If you have file tools, you may offer to write it into a project file instead (files persist; conversation memory does not).";
|
|
65
54
|
/** The refuse-harmful-use security boundary (composed on every shape; safety text is never gated). */
|
|
66
55
|
export declare const CYBER_RISK: string;
|
|
67
56
|
/** The never-guess-URLs rule (composed on every shape). */
|
package/dist/prompts/default.js
CHANGED
|
@@ -24,9 +24,6 @@ Hygiene:
|
|
|
24
24
|
- Before saving, check what memory already holds: update an existing note rather than writing a near-duplicate, and remove a note that turns out to be wrong.
|
|
25
25
|
- Don't save what the code, its history, or this conversation already records (structure, past fixes, transient task state). If asked to remember something obvious, save what was non-obvious about it instead.`;
|
|
26
26
|
export const MEMORY_GUIDANCE = `${MEMORY_SAFETY}\n\n${MEMORY_HYGIENE}`;
|
|
27
|
-
export const NO_PERSISTENT_MEMORY_NOTICE = `# Memory
|
|
28
|
-
|
|
29
|
-
You have no persistent memory store: what is said in this conversation is not automatically retained for future sessions. If the user asks you to remember something for later, say plainly that you cannot store it — do not claim to have noted or saved it. If you have file tools, you may offer to write it into a project file instead (files persist; conversation memory does not).`;
|
|
30
27
|
export const CYBER_RISK = catalogText("core/security.cyber-risk");
|
|
31
28
|
export const URL_SAFETY = catalogText("core/security.url-safety");
|
|
32
29
|
export const SUMMARIZE_TOOL_RESULTS = catalogText("core/harness.tool-result-retention");
|
package/dist/shell/lex.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare const EXPANSION_KINDS: readonly ["parameter", "command", "process
|
|
|
12
12
|
export type ExpansionKind = (typeof EXPANSION_KINDS)[number];
|
|
13
13
|
/** Why a word's value cannot be read off the text. Each member is a spelling whose value the text does not
|
|
14
14
|
* contain — never "the lexer did not look". */
|
|
15
|
-
export declare const UNRESOLVED_REASONS: readonly ["ansi_c_escape", "locale_string", "parameter_text", "subscript_text", "compound_array_value"];
|
|
15
|
+
export declare const UNRESOLVED_REASONS: readonly ["ansi_c_escape", "locale_string", "parameter_text", "subscript_text", "compound_array_value", "trailing_backslash"];
|
|
16
16
|
export type UnresolvedReason = (typeof UNRESOLVED_REASONS)[number];
|
|
17
17
|
/** The sentence a consumer hands on for an unresolved word: every reason is one a face ASKS about (the locale
|
|
18
18
|
* string included — its translation is not in the text), and a deny row is still judged on the written spelling
|
|
@@ -23,9 +23,10 @@ export declare const UNRESOLVED_SENTENCE: {
|
|
|
23
23
|
readonly parameter_text: "a parameter expansion carries text this lexer does not read";
|
|
24
24
|
readonly subscript_text: "a subscript carries text this lexer does not read";
|
|
25
25
|
readonly compound_array_value: "a compound assignment value is a list this lexer does not read";
|
|
26
|
+
readonly trailing_backslash: "a backslash ends the command, which the shell versions read differently (3.2 drops it, 5 keeps it)";
|
|
26
27
|
};
|
|
27
28
|
/** Why a command yields no segments: bash's own syntax errors and the two constructs this lexer cannot delimit. */
|
|
28
|
-
export declare const PARSE_FAILURE_REASONS: readonly ["unterminated_single_quote", "unterminated_double_quote", "unterminated_ansi_c", "unterminated_subscript", "unterminated_compound_value", "unterminated_command_substitution", "unterminated_process_substitution", "unterminated_parameter_expansion", "unterminated_heredoc", "undelimited_substitution", "redirect_without_target", "heredoc_without_delimiter", "heredoc_delimiter_expands"];
|
|
29
|
+
export declare const PARSE_FAILURE_REASONS: readonly ["unterminated_single_quote", "unterminated_double_quote", "unterminated_ansi_c", "unterminated_subscript", "unterminated_compound_value", "unterminated_command_substitution", "unterminated_process_substitution", "unterminated_parameter_expansion", "unterminated_arithmetic_expansion", "unterminated_heredoc", "undelimited_substitution", "redirect_without_target", "heredoc_without_delimiter", "heredoc_delimiter_expands"];
|
|
29
30
|
export type ParseFailureReason = (typeof PARSE_FAILURE_REASONS)[number];
|
|
30
31
|
export declare const PARSE_FAILURE_SENTENCE: {
|
|
31
32
|
readonly unterminated_single_quote: "a single-quoted word never closes";
|
|
@@ -36,6 +37,7 @@ export declare const PARSE_FAILURE_SENTENCE: {
|
|
|
36
37
|
readonly unterminated_command_substitution: "a command substitution never terminates";
|
|
37
38
|
readonly unterminated_process_substitution: "a process substitution never terminates";
|
|
38
39
|
readonly unterminated_parameter_expansion: "a parameter expansion never terminates";
|
|
40
|
+
readonly unterminated_arithmetic_expansion: "an arithmetic expansion never terminates";
|
|
39
41
|
readonly unterminated_heredoc: "a here-document body never terminates";
|
|
40
42
|
readonly undelimited_substitution: "a command substitution carries a construct this lexer cannot delimit";
|
|
41
43
|
readonly redirect_without_target: "a redirection names no target";
|
|
@@ -76,7 +78,9 @@ export interface WordPiece {
|
|
|
76
78
|
}
|
|
77
79
|
export interface WordExpansion {
|
|
78
80
|
readonly kind: ExpansionKind;
|
|
79
|
-
/** `"many"` where the result
|
|
81
|
+
/** `"many"` where the result may be zero or several words: word-split (an unquoted parameter, command or arithmetic
|
|
82
|
+
* substitution), a brace list, a glob, or a parameter expanded once per element even in double quotes (`"$@"`,
|
|
83
|
+
* `"${a[@]}"`, `"${!prefix@}"`). */
|
|
80
84
|
readonly yields: "one" | "many";
|
|
81
85
|
/** The text between the delimiters, where there is one (a substitution body, a brace list, a tilde-prefix). */
|
|
82
86
|
readonly body?: string;
|
|
@@ -93,6 +97,9 @@ export interface WordExpansion {
|
|
|
93
97
|
readonly written: string;
|
|
94
98
|
readonly judged: string;
|
|
95
99
|
};
|
|
100
|
+
/** The expansions a brace list or a bracket class encloses (`{${a[n]},x}`, `[$x]`): they run before the pattern is
|
|
101
|
+
* formed. Absent when it encloses none. */
|
|
102
|
+
readonly inner?: readonly WordExpansion[];
|
|
96
103
|
}
|
|
97
104
|
export interface QuotedSpan {
|
|
98
105
|
/** Offsets into {@link LexedWord.raw}, `[start, end)`; the quote characters belong to their span. */
|
|
@@ -154,7 +161,8 @@ export interface LexedWord {
|
|
|
154
161
|
* output form and `0` for an input form, is the reader's to apply). */
|
|
155
162
|
export interface LexedRedirect {
|
|
156
163
|
readonly kind: "redirect";
|
|
157
|
-
|
|
164
|
+
/** `<>` opens its target for reading AND writing (creating it), on descriptor 0 unless one is written. */
|
|
165
|
+
readonly op: "<" | ">" | ">>" | "<<<" | "<>" | "&>" | "&>>" | ">&" | "<&";
|
|
158
166
|
readonly fd?: number;
|
|
159
167
|
readonly target?: LexedWord;
|
|
160
168
|
readonly dup?: string;
|
|
@@ -192,6 +200,9 @@ export interface LexedSegment {
|
|
|
192
200
|
readonly tokens: readonly LexedToken[];
|
|
193
201
|
/** The bodies of the substitutions found in THIS segment (its words and its redirection targets), in order. */
|
|
194
202
|
readonly substitutions: readonly string[];
|
|
203
|
+
/** The bodies among {@link substitutions} of a function or value substitution (`${ list; }`, `${| list; }`): their list
|
|
204
|
+
* runs in the CURRENT shell, so what it assigns or where it moves outlives the word. Absent when there is none. */
|
|
205
|
+
readonly currentShell?: readonly string[];
|
|
195
206
|
}
|
|
196
207
|
export interface LexedCommand {
|
|
197
208
|
readonly segments: readonly LexedSegment[];
|
|
@@ -203,6 +214,10 @@ export interface LexParseFailure {
|
|
|
203
214
|
readonly reason: ParseFailureReason;
|
|
204
215
|
readonly at: number;
|
|
205
216
|
};
|
|
217
|
+
/** The segments the walk read before it stopped, the last one holding the tokens it had read when it stopped. Bash runs
|
|
218
|
+
* each complete line before it parses the next one (`rm -r x` on line 1 runs although line 2 never closes its quote),
|
|
219
|
+
* so a reader asking what the text MAY run reads these as runs; a reader asking what the text DOES reads the failure. */
|
|
220
|
+
readonly readBefore: readonly LexedSegment[];
|
|
206
221
|
}
|
|
207
222
|
/** A command: its segments, or the one reason it has none. */
|
|
208
223
|
export type ShellLex = LexedCommand | LexParseFailure;
|
|
@@ -222,7 +237,7 @@ export declare const SHELL_CONTROL_PREFIXES: ReadonlySet<string>;
|
|
|
222
237
|
* Does the `$` at `at` OPEN a quote form (`$'…'` / `$"…"`)? ONE question, asked by every walker that has to
|
|
223
238
|
* answer it. Escaped means an ODD run of backslashes in front of it: `\$'y'` is a literal `$`, while `x\\$'y'`
|
|
224
239
|
* is a literal backslash followed by a real ANSI-C quote. Counting the run is what a one-character peek behind
|
|
225
|
-
* cannot do.
|
|
240
|
+
* cannot do. The quote may follow line continuations bash removes first (`$\<newline>"…"` is `$"…"`).
|
|
226
241
|
*/
|
|
227
242
|
export declare function dollarOpensQuote(text: string, at: number): boolean;
|
|
228
243
|
/** The `'` that CLOSES the ANSI-C quote opened at `open`, or `undefined` when none does. `\'` does not close
|
|
@@ -236,12 +251,75 @@ export declare function literalTildeSpelling(word: string): string;
|
|
|
236
251
|
export declare function argvOf(segment: LexedSegment): readonly LexedWord[];
|
|
237
252
|
/** The two-spelling view of {@link argvOf}, for the readers that compare spellings. */
|
|
238
253
|
export declare function wordsOf(segment: LexedSegment): SegmentTokens;
|
|
239
|
-
/**
|
|
240
|
-
*
|
|
254
|
+
/** One expansion of an unquoted here-document body; `unresolved` where the parameter text is one this lexer does not
|
|
255
|
+
* read (`${x:-$(…)}`, a nested `${…}`) — what it may assign or run is then not in the facts. */
|
|
256
|
+
export interface HeredocExpansion {
|
|
257
|
+
readonly expansion: WordExpansion;
|
|
258
|
+
readonly unresolved?: "parameter_text";
|
|
259
|
+
/** A function or value substitution ({@link opensCurrentShellSubstitution}): its list runs in the current shell. */
|
|
260
|
+
readonly currentShell?: true;
|
|
261
|
+
}
|
|
262
|
+
/** The expansions of an UNQUOTED here-document body, in order: `$(…)`, `$((…))`, `$[…]` and backticks, `${ …; }` /
|
|
263
|
+
* `${| …; }`, `${…}` and `$NAME`. The body expands as double-quoted text does: quotes are ordinary characters, a backslash
|
|
264
|
+
* protects the next character, nothing is word-split. `undefined` when an expansion never closes. */
|
|
265
|
+
export declare function expansionsInHeredocBody(body: string): readonly HeredocExpansion[] | undefined;
|
|
266
|
+
/** The substitution bodies of an UNQUOTED here-document body (the command and arithmetic members of
|
|
267
|
+
* {@link expansionsInHeredocBody}, a function / value substitution marked `currentShell`). `undefined` when an
|
|
268
|
+
* expansion never closes. */
|
|
241
269
|
export declare function substitutionsInHeredocBody(body: string): {
|
|
242
270
|
readonly body: string;
|
|
243
271
|
readonly kind: "command" | "arithmetic";
|
|
272
|
+
readonly currentShell?: true;
|
|
244
273
|
}[] | undefined;
|
|
274
|
+
/** Can expanding an unquoted here-document body run a program the text does not show ({@link expansionHidesRun} over
|
|
275
|
+
* its expansions)? A body whose expansions cannot be delimited, a parameter text this lexer does not read, and a
|
|
276
|
+
* process-substitution opener (text to bash in a body; read here as one — the side that judges more) all count. */
|
|
277
|
+
export declare function heredocBodyHidesRun(body: string): boolean;
|
|
278
|
+
/** A `${…}` body read once, past its head ({@link PARAMETER_HEAD}): the texts bash evaluates as arithmetic — the subscript
|
|
279
|
+
* (`a[i]`, `#a[i]`, `!a[i]`: up to the first `]`, or to the end where none closes) and a substring expansion's offset and
|
|
280
|
+
* length (`x:off:len`, `*:N+=1`, after a closed subscript or none; not the `:-` `:=` `:+` `:?` operators). A line
|
|
281
|
+
* continuation is removed first. The one reading of the body grammar: the deny lanes and auto-background ask whether
|
|
282
|
+
* either text names a variable ({@link expansionHidesRun}), the read station re-enters what either runs. */
|
|
283
|
+
export declare function parameterArithmeticTexts(body: string): {
|
|
284
|
+
readonly subscript?: string;
|
|
285
|
+
readonly offset?: string;
|
|
286
|
+
};
|
|
287
|
+
/**
|
|
288
|
+
* Can evaluating this expansion run a program the text does not show? A command or process substitution runs one. The
|
|
289
|
+
* arithmetic evaluator evaluates a NAME recursively (`a='x[$(…)]'; $((a))`), so arithmetic text that names a variable or
|
|
290
|
+
* carries a `$` may run one, and so may a parameter expansion's subscript or substring offset, its own or one nested in
|
|
291
|
+
* its text (`${x:-${a[i]}}`); a parameter, brace or glob text carrying a substitution opener runs what it opens.
|
|
292
|
+
*/
|
|
293
|
+
export declare function expansionHidesRun(e: WordExpansion): boolean;
|
|
294
|
+
/** Can a compound assignment's value `(…)` run what its text does not show? The lexer keeps the value one opaque piece
|
|
295
|
+
* (its elements unread), so any `$` or backquote in it may (`(${P@P})`, `(${!N})`, `(${x:-$(…)})`), and so may a `[…]`
|
|
296
|
+
* subscript the evaluator reads — one naming a variable (`([x]=1)`), or carrying a `$` or backquote, an ANSI-C `$'…'`
|
|
297
|
+
* among them (`([$'\170']=1)`: bash decodes `\170` to the name `x` and evaluates it). A `$'…'` is not counted OUTSIDE a
|
|
298
|
+
* `[…]` — a standalone element opens an ANSI-C string and runs nothing (`($'\t' x)`) — but inside a subscript it is (the
|
|
299
|
+
* `[…]` arm's char class holds `$`). (An integer array's ANSI-C ELEMENT, `declare -ai A=($'\170')`, decodes and
|
|
300
|
+
* evaluates too, but needs the `-i` attribute the value text does not carry — not caught here, see KNOWN-LIMITS.) Its
|
|
301
|
+
* command substitutions are the segment's already. The one reading the deny lanes, the read station and
|
|
302
|
+
* auto-background share until the value is read element by element. */
|
|
303
|
+
export declare function compoundValueHidesRun(w: {
|
|
304
|
+
readonly assignment?: AssignmentFact;
|
|
305
|
+
}): boolean;
|
|
306
|
+
/** Does the parameter body (`P@P`, `a[i]@P`) carry a transformation that EVALUATES the value — `${P@P}` expands P's value
|
|
307
|
+
* as a prompt string, its parameter, command and arithmetic expansions run (measured on 5.3) — rather than respelling it? */
|
|
308
|
+
export declare function transformEvaluates(body: string): boolean;
|
|
309
|
+
/** Does evaluating a parameter expansion with this body RE-READ the parameter's own VALUE — an indirect `${!R}` (R's
|
|
310
|
+
* value names what is then expanded, so `R='a[$(…)]'` evaluates that subscript; a name list `${!prefix*}` / a key list
|
|
311
|
+
* `${!a[@]}` expand names only) or an evaluating transform `${P@P}` (the value is expanded as a prompt string, its own
|
|
312
|
+
* expansions run)? The one reading every consumer uses for "the value runs what the text does not show": the read
|
|
313
|
+
* station asks (it does not follow the value), the deny lanes and auto-background read it a hidden run through
|
|
314
|
+
* {@link expansionHidesRun}. A subscript or substring offset re-reads the BODY's own text, not the value — that is
|
|
315
|
+
* {@link parameterArithmeticTexts}. A line continuation in the body is removed first (`${P@\⏎P}` is `${P@P}`). */
|
|
316
|
+
export declare function parameterRereadsValue(body: string): boolean;
|
|
317
|
+
/** Is the arithmetic text (an arithmetic command's interior) provably free of a variable — the same reading
|
|
318
|
+
* {@link expansionHidesRun} gives an arithmetic expansion? */
|
|
319
|
+
export declare function arithmeticTextIsPlain(text: string): boolean;
|
|
320
|
+
/** Does `word`, standing right before the redirection `next`, name the descriptor that redirection opens (`{fd}>file`):
|
|
321
|
+
* a bare `{NAME}` that belongs to the operator rather than to the argv? */
|
|
322
|
+
export declare function namesRedirectDescriptor(word: LexedWord, next: LexedToken | undefined): boolean;
|
|
245
323
|
/** The text a word's pieces hand the program when every piece is literal; `undefined` when one is an expansion or
|
|
246
324
|
* unresolved. */
|
|
247
325
|
export declare function literalTextOf(pieces: readonly WordPiece[]): string | undefined;
|
|
@@ -249,7 +327,8 @@ export declare function literalTextOf(pieces: readonly WordPiece[]): string | un
|
|
|
249
327
|
* backquote or a backslash is removed (a line continuation was joined when the body was read), every other character
|
|
250
328
|
* stands. `undefined` when an unescaped `$` or backquote stands in it: the program reads what the expansion makes. */
|
|
251
329
|
export declare function literalHeredocBody(body: string): string | undefined;
|
|
252
|
-
/** Lex a command: its segments, or the one reason bash (or this lexer) cannot delimit them
|
|
330
|
+
/** Lex a command: its segments, or the one reason bash (or this lexer) cannot delimit them — with the segments read
|
|
331
|
+
* before it ({@link LexParseFailure.readBefore}). */
|
|
253
332
|
export declare function lexShell(source: string): ShellLex;
|
|
254
333
|
/**
|
|
255
334
|
* The refused-reading view of {@link lexShell}: a parse failure, and any word whose value cannot be read off the
|