@sema-agent/core 7.51.2 → 7.52.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 +504 -2
- package/dist/agents/agent-transcript-tool.d.ts +1 -1
- package/dist/agents/cascade.js +4 -0
- package/dist/agents/cumulative-stats.d.ts +3 -0
- package/dist/agents/cumulative-stats.js +3 -0
- package/dist/agents/list-agents-tool.d.ts +1 -1
- package/dist/agents/read-inbox-tool.d.ts +1 -1
- package/dist/agents/repair-loop.js +4 -0
- package/dist/agents/send-message-tool.d.ts +11 -16
- package/dist/agents/send-message-tool.js +11 -13
- package/dist/agents/subagent.js +6 -4
- package/dist/agents/tool-filter.d.ts +40 -13
- package/dist/agents/tool-filter.js +28 -14
- package/dist/bench/metrics.d.ts +1 -0
- package/dist/brain/anthropic.js +16 -12
- package/dist/brain/model-presets.d.ts +4 -5
- package/dist/brain/model-presets.js +4 -4
- package/dist/brain/open-responses.js +16 -12
- package/dist/brain/openai.js +16 -12
- package/dist/brain/request-params.d.ts +12 -33
- package/dist/brain/request-params.js +5 -2
- package/dist/brain/request-route.d.ts +9 -8
- package/dist/brain/request-route.js +1 -0
- package/dist/brain/route-adjudicator.d.ts +117 -47
- package/dist/brain/route-adjudicator.js +171 -42
- package/dist/brain/route-conformance.js +2 -2
- package/dist/brain/status-sink.d.ts +18 -0
- package/dist/brain/status-sink.js +7 -0
- package/dist/core/allow-entry.d.ts +40 -8
- package/dist/core/allow-entry.js +23 -16
- package/dist/core/auto-compaction.d.ts +23 -20
- package/dist/core/auto-compaction.js +37 -16
- package/dist/core/auto-promote.d.ts +2 -1
- package/dist/core/auto-promote.js +2 -2
- package/dist/core/caller-tool-name.d.ts +9 -0
- package/dist/core/caller-tool-name.js +13 -0
- package/dist/core/checkpoint-requirements.d.ts +7 -1
- package/dist/core/checkpoint-requirements.js +2 -0
- package/dist/core/checkpoint-store.d.ts +36 -12
- package/dist/core/checkpoint-store.js +1 -1
- package/dist/core/child-clamp-seats.d.ts +6 -0
- package/dist/core/child-clamp-seats.js +2 -1
- package/dist/core/credential-vocabulary.d.ts +33 -8
- package/dist/core/credential-vocabulary.js +32 -7
- package/dist/core/decision-receipt.d.ts +2 -2
- package/dist/core/delegation-frames.d.ts +9 -2
- package/dist/core/delegation-name.d.ts +18 -0
- package/dist/core/delegation-name.js +47 -0
- package/dist/core/engine-capabilities.d.ts +8 -1
- package/dist/core/engine-capabilities.js +1 -1
- package/dist/core/engine-notice.d.ts +36 -19
- package/dist/core/frontmatter-fence.d.ts +10 -0
- package/dist/core/frontmatter-fence.js +6 -0
- package/dist/core/gate-fold.js +5 -23
- package/dist/core/gate-lanes.js +356 -270
- package/dist/core/governance-codes.d.ts +9 -4
- package/dist/core/governance-codes.js +9 -3
- package/dist/core/hooks.d.ts +276 -734
- package/dist/core/hooks.js +97 -192
- package/dist/{tools/fs → core}/image-admission.d.ts +21 -3
- package/dist/{tools/fs → core}/image-admission.js +24 -6
- package/dist/core/mcp-connection-pool.d.ts +4 -1
- package/dist/core/mcp-connection-pool.js +7 -2
- package/dist/core/mcp-probe.d.ts +12 -9
- package/dist/core/mcp-probe.js +2 -2
- package/dist/core/mcp-server-spec.d.ts +16 -0
- package/dist/core/mcp.d.ts +11 -7
- package/dist/core/mcp.js +11 -5
- package/dist/core/memory-engine/data-plane.js +5 -1
- package/dist/core/memory-engine/distiller.js +16 -2
- package/dist/core/memory-engine/engine.d.ts +8 -11
- package/dist/core/memory-engine/engine.js +9 -5
- package/dist/core/memory-engine/frontmatter.d.ts +6 -0
- package/dist/core/memory-engine/frontmatter.js +19 -16
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/mode-policy.d.ts +4 -0
- package/dist/core/mode-policy.js +7 -5
- package/dist/core/model-seat.d.ts +4 -1
- package/dist/core/mods/dollar.d.ts +109 -0
- package/dist/core/mods/dollar.js +154 -0
- package/dist/core/mods/host.d.ts +23 -0
- package/dist/core/mods/host.js +21 -0
- package/dist/core/mods/kernel/budget.d.ts +43 -0
- package/dist/core/mods/kernel/budget.js +83 -0
- package/dist/core/mods/kernel/dispatch.d.ts +100 -0
- package/dist/core/mods/kernel/dispatch.js +701 -0
- package/dist/core/mods/kernel/events.d.ts +242 -0
- package/dist/core/mods/kernel/events.js +210 -0
- package/dist/core/mods/kernel/index.d.ts +6 -0
- package/dist/core/mods/kernel/index.js +5 -0
- package/dist/core/mods/kernel/receive.d.ts +65 -0
- package/dist/core/mods/kernel/receive.js +123 -0
- package/dist/core/mods/kernel/registration.d.ts +131 -0
- package/dist/core/mods/kernel/registration.js +102 -0
- package/dist/core/mods/kernel/site-rules.d.ts +84 -0
- package/dist/core/mods/kernel/site-rules.js +104 -0
- package/dist/core/mods/stations.d.ts +350 -0
- package/dist/core/mods/stations.js +444 -0
- package/dist/core/own-property-receipt.js +11 -23
- package/dist/core/parent-spec-seat.d.ts +18 -7
- package/dist/core/parent-spec-seat.js +6 -2
- package/dist/core/path-identity.js +2 -1
- package/dist/core/permission-rule-syntax.d.ts +15 -0
- package/dist/core/permission-rule-syntax.js +24 -16
- package/dist/core/permission-rules.d.ts +7 -1
- package/dist/core/permission-rules.js +26 -15
- package/dist/core/prompt-section-seat.d.ts +15 -27
- package/dist/core/prompt-section-seat.js +73 -40
- package/dist/core/protocol-http-auth.d.ts +3 -1
- package/dist/core/protocol-http-auth.js +2 -0
- package/dist/core/reminder-mint.d.ts +2 -2
- package/dist/core/remote-env.d.ts +24 -12
- package/dist/core/remote-env.js +1 -0
- package/dist/core/resume-startup-cause.d.ts +16 -1
- package/dist/core/resume-startup-cause.js +4 -1
- package/dist/core/retired-keys.d.ts +4 -0
- package/dist/core/retired-keys.js +3 -0
- package/dist/core/runner/announce-once-ledger.d.ts +31 -1
- package/dist/core/runner/announce-once-ledger.js +22 -0
- package/dist/core/runner/assemble-result.d.ts +9 -0
- package/dist/core/runner/assemble-result.js +3 -1
- package/dist/core/runner/call-hook-stations.d.ts +23 -27
- package/dist/core/runner/call-hook-stations.js +58 -42
- package/dist/core/runner/caller-stop-gate.d.ts +25 -0
- package/dist/core/runner/caller-stop-gate.js +7 -0
- package/dist/core/runner/compaction-seams.d.ts +8 -22
- package/dist/core/runner/compaction-seams.js +28 -53
- package/dist/core/runner/construction-doors.js +11 -1
- package/dist/core/runner/contracts.d.ts +85 -83
- package/dist/core/runner/credential-origin-seat.d.ts +2 -0
- package/dist/core/runner/credential-origin-seat.js +19 -0
- package/dist/core/runner/extra-body-dropped-seat.d.ts +2 -6
- package/dist/core/runner/gate-exit.d.ts +47 -36
- package/dist/core/runner/gate-exit.js +8 -2
- package/dist/core/runner/image.js +1 -2
- package/dist/core/runner/inline-image.js +1 -1
- package/dist/core/runner/notice-seat-input.d.ts +11 -0
- package/dist/core/runner/notice-seat-input.js +1 -0
- package/dist/core/runner/person-path-rows.js +1 -0
- package/dist/core/runner/prepare-acquire-reconcile.js +5 -1
- package/dist/core/runner/prepare-ask-lane.d.ts +5 -7
- package/dist/core/runner/prepare-ask-lane.js +6 -15
- package/dist/core/runner/prepare-caps-and-workflow.d.ts +4 -2
- package/dist/core/runner/prepare-caps-and-workflow.js +25 -8
- package/dist/core/runner/prepare-config-doors.d.ts +5 -0
- package/dist/core/runner/prepare-config-doors.js +9 -0
- package/dist/core/runner/prepare-defer-classify.js +3 -4
- package/dist/core/runner/prepare-gate-stations.d.ts +8 -11
- package/dist/core/runner/prepare-gate-stations.js +11 -10
- package/dist/core/runner/prepare-inherited-gate.d.ts +8 -12
- package/dist/core/runner/prepare-inherited-gate.js +8 -21
- package/dist/core/runner/prepare-memory-engine-session.js +1 -1
- package/dist/core/runner/prepare-park-ask.js +10 -14
- package/dist/core/runner/prepare-policy-chain.d.ts +17 -15
- package/dist/core/runner/prepare-policy-chain.js +95 -100
- package/dist/core/runner/prepare-project-context.js +7 -10
- package/dist/core/runner/prepare-prompt-assembly.d.ts +45 -40
- package/dist/core/runner/prepare-prompt-assembly.js +134 -101
- package/dist/core/runner/prepare-prompt-inputs.d.ts +18 -19
- package/dist/core/runner/prepare-prompt-inputs.js +5 -7
- package/dist/core/runner/prepare-protocol-tools.d.ts +6 -4
- package/dist/core/runner/prepare-protocol-tools.js +2 -2
- package/dist/core/runner/prepare-safety-scan.js +6 -10
- package/dist/core/runner/prepare-suspend-saga.d.ts +6 -0
- package/dist/core/runner/prepare-suspend-saga.js +7 -5
- package/dist/core/runner/prepare-task.js +33 -15
- package/dist/core/runner/prepare-turn-wiring.d.ts +13 -15
- package/dist/core/runner/prepare-turn-wiring.js +29 -27
- package/dist/core/runner/prepare-wiring-manifest.d.ts +5 -6
- package/dist/core/runner/prepare-wiring-manifest.js +7 -7
- package/dist/core/runner/resume-apply.d.ts +5 -2
- package/dist/core/runner/resume-apply.js +24 -42
- package/dist/core/runner/resume-checkpoint-screen.d.ts +1 -0
- package/dist/core/runner/resume-checkpoint-screen.js +9 -1
- package/dist/core/runner/resume-preflight.js +38 -16
- package/dist/core/runner/retired-runner-deps.js +3 -1
- package/dist/core/runner/run-brain-sinks.d.ts +3 -2
- package/dist/core/runner/run-brain-sinks.js +5 -1
- package/dist/core/runner/run-compaction-machinery.d.ts +7 -1
- package/dist/core/runner/run-compaction-machinery.js +7 -33
- package/dist/core/runner/run-harness-handlers.js +4 -2
- package/dist/core/runner/run-identity-wiring.d.ts +3 -1
- package/dist/core/runner/run-identity-wiring.js +3 -2
- package/dist/core/runner/run-leg.js +62 -84
- package/dist/core/runner/run-notification-lane.js +1 -0
- package/dist/core/runner/run-recovery-lanes.d.ts +3 -0
- package/dist/core/runner/run-recovery-lanes.js +11 -10
- package/dist/core/runner/run-settle-and-teardown.js +9 -28
- package/dist/core/runner/run-stop-and-final-verify.js +18 -25
- package/dist/core/runner/run-terminal-adoption.d.ts +3 -0
- package/dist/core/runner/run-terminal-adoption.js +33 -22
- package/dist/core/runner/run-tool-mount-facts.js +5 -3
- package/dist/core/runner/run-turn-boundary.js +23 -34
- package/dist/core/runner/runtask.d.ts +6 -7
- package/dist/core/runner/runtask.js +14 -72
- package/dist/core/runner/session-rule-policy.d.ts +5 -5
- package/dist/core/runner/session-rule-policy.js +13 -8
- package/dist/core/runner/side-call-account.d.ts +68 -0
- package/dist/core/runner/side-call-account.js +61 -0
- package/dist/core/runner/stream-halt-verbs.js +12 -17
- package/dist/core/runner/stream-lifecycle-verbs.js +8 -5
- package/dist/core/runner/stream-steer-verb.d.ts +1 -1
- package/dist/core/runner/stream-steer-verb.js +20 -38
- package/dist/core/runner/sub-agent-deny-lists.d.ts +121 -22
- package/dist/core/runner/sub-agent-deny-lists.js +228 -71
- package/dist/core/runner/tool-end-body.d.ts +5 -6
- package/dist/core/runner/tool-end-body.js +6 -4
- package/dist/core/runner/tool-not-executed.d.ts +15 -0
- package/dist/core/runner/tool-not-executed.js +30 -0
- package/dist/core/runner/tool-occurrence.d.ts +8 -7
- package/dist/core/runner/tool-occurrence.js +5 -5
- package/dist/core/runner/tool-result-media-seat.d.ts +1 -1
- package/dist/core/runner-deps.d.ts +20 -28
- package/dist/core/safety-merge-corpus.js +18 -2
- package/dist/core/secret-env.d.ts +88 -20
- package/dist/core/secret-env.js +192 -38
- package/dist/core/session-policy-store.d.ts +52 -16
- package/dist/core/session-policy-store.js +118 -28
- package/dist/core/session-reconcile.d.ts +4 -0
- package/dist/core/session-reconcile.js +2 -1
- package/dist/core/shell-read-silence.js +3 -32
- package/dist/core/side-query.d.ts +5 -3
- package/dist/core/skill-grant.d.ts +3 -2
- package/dist/core/skill-grant.js +17 -9
- package/dist/core/skills-directory.d.ts +31 -11
- package/dist/core/skills-directory.js +655 -104
- package/dist/core/task-event.d.ts +13 -3
- package/dist/core/task-result.d.ts +8 -0
- package/dist/core/task-spec.d.ts +20 -19
- package/dist/core/task-stream.d.ts +14 -4
- package/dist/core/tighten-task-spec.d.ts +4 -3
- package/dist/core/tighten-task-spec.js +2 -4
- package/dist/core/tool-check-reading.d.ts +74 -0
- package/dist/core/tool-check-reading.js +80 -0
- package/dist/core/tool-policy.d.ts +59 -18
- package/dist/core/tool-policy.js +77 -12
- package/dist/core/tool-registry.d.ts +20 -0
- package/dist/core/tool-registry.js +4 -0
- package/dist/core/tool-spec.d.ts +10 -6
- package/dist/core/tools.js +2 -0
- package/dist/core/trace.d.ts +51 -32
- package/dist/core/unc-spelling.d.ts +10 -0
- package/dist/core/unc-spelling.js +3 -0
- package/dist/core/untrusted-egress.d.ts +8 -0
- package/dist/core/untrusted-egress.js +4 -1
- package/dist/core/user-attachment.d.ts +12 -2
- package/dist/core/user-attachment.js +17 -2
- package/dist/core/wiring-manifest.d.ts +14 -13
- package/dist/core/wiring-manifest.js +2 -2
- package/dist/engine/compaction/utils.js +1 -2
- package/dist/engine/execution-env/node-execution-env.d.ts +4 -3
- package/dist/engine/execution-env/symlink-chain.js +1 -1
- package/dist/engine/harness/agent-harness.d.ts +1 -1
- package/dist/engine/harness/agent-harness.js +3 -3
- package/dist/engine/harness/types.d.ts +17 -16
- package/dist/engine/harness/types.js +7 -1
- package/dist/engine/llm/types.d.ts +12 -7
- package/dist/engine/loop/agent-loop.js +1 -1
- package/dist/engine/loop/types.d.ts +1 -1
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.js +3 -10
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/engine/session/session.js +4 -4
- package/dist/index.d.ts +20 -16
- package/dist/index.js +13 -11
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/orchestration/run-spec.d.ts +4 -6
- package/dist/orchestration/run-spec.js +39 -63
- package/dist/orchestration/run-workflow-tool.js +1 -2
- package/dist/orchestration/workflow.d.ts +11 -3
- package/dist/orchestration/workflow.js +11 -2
- package/dist/prompt-assembly/artifact-store.d.ts +37 -56
- package/dist/prompt-assembly/artifact-store.js +31 -49
- package/dist/prompt-assembly/artifact.d.ts +89 -76
- package/dist/prompt-assembly/artifact.js +167 -146
- package/dist/prompt-assembly/assemble.d.ts +34 -29
- package/dist/prompt-assembly/assemble.js +33 -220
- package/dist/prompt-assembly/bands.d.ts +20 -0
- package/dist/prompt-assembly/bands.js +18 -0
- package/dist/prompt-assembly/catalog/constitution.d.ts +23 -0
- package/dist/prompt-assembly/catalog/constitution.js +69 -0
- package/dist/prompt-assembly/catalog/core-behavior.d.ts +9 -0
- package/dist/prompt-assembly/catalog/core-behavior.js +85 -0
- package/dist/prompt-assembly/catalog/index.d.ts +11 -0
- package/dist/prompt-assembly/catalog/index.js +59 -0
- package/dist/prompt-assembly/catalog/modes.d.ts +15 -0
- package/dist/prompt-assembly/catalog/modes.js +137 -0
- package/dist/prompt-assembly/catalog/role.d.ts +10 -0
- package/dist/prompt-assembly/catalog/role.js +157 -0
- package/dist/prompt-assembly/catalog/schema.d.ts +124 -0
- package/dist/prompt-assembly/catalog/schema.js +25 -0
- package/dist/prompt-assembly/catalog/sections.d.ts +9 -0
- package/dist/prompt-assembly/catalog/sections.js +98 -0
- package/dist/prompt-assembly/catalog/team.d.ts +4 -0
- package/dist/prompt-assembly/catalog/team.js +258 -0
- package/dist/prompt-assembly/composer.d.ts +24 -28
- package/dist/prompt-assembly/composer.js +124 -46
- package/dist/prompt-assembly/epoch.d.ts +89 -79
- package/dist/prompt-assembly/epoch.js +115 -142
- package/dist/prompt-assembly/explain.d.ts +58 -34
- package/dist/prompt-assembly/explain.js +21 -24
- package/dist/prompt-assembly/overlay.d.ts +127 -0
- package/dist/prompt-assembly/overlay.js +301 -0
- package/dist/prompt-assembly/renderers.d.ts +21 -0
- package/dist/prompt-assembly/renderers.js +39 -0
- package/dist/prompt-assembly/section-usage.d.ts +3 -3
- package/dist/prompt-assembly/section-usage.js +1 -1
- package/dist/prompt-assembly/select.d.ts +56 -0
- package/dist/prompt-assembly/select.js +69 -0
- package/dist/prompt-assembly/sugar.d.ts +31 -0
- package/dist/prompt-assembly/sugar.js +20 -0
- package/dist/prompt-assembly/turn-snapshot.d.ts +3 -2
- package/dist/prompt-assembly/types.d.ts +45 -148
- package/dist/prompts/coordinator.d.ts +2 -21
- package/dist/prompts/coordinator.js +3 -255
- package/dist/prompts/cowork.d.ts +27 -16
- package/dist/prompts/cowork.js +2 -23
- package/dist/prompts/default.d.ts +38 -500
- package/dist/prompts/default.js +20 -285
- package/dist/prompts/supervisor.d.ts +6 -71
- package/dist/prompts/supervisor.js +6 -117
- package/dist/tools/fs/bash-readonly-classifier.d.ts +6 -5
- package/dist/tools/fs/dir-entries.d.ts +4 -2
- package/dist/tools/fs/dir-entries.js +16 -4
- package/dist/tools/fs/fs-bash.d.ts +1 -1
- package/dist/tools/fs/fs-bash.js +22 -11
- package/dist/tools/fs/fs-pdf.js +17 -13
- package/dist/tools/fs/fs-read.js +4 -3
- package/dist/tools/fs/fs-shared.d.ts +1 -10
- package/dist/tools/fs/fs-shared.js +3 -4
- package/dist/tools/fs/fs-write.js +2 -1
- package/dist/tools/fs/notebook.js +1 -1
- package/dist/tools/fs/pdf.d.ts +20 -10
- package/dist/tools/fs/pdf.js +19 -10
- package/dist/tools/fs/program-read-model.d.ts +68 -8
- package/dist/tools/fs/program-read-model.js +112 -33
- package/dist/tools/fs/program-read-model.rows.js +30 -10
- package/dist/tools/fs/read-deny-home.d.ts +25 -9
- package/dist/tools/fs/read-deny-home.js +28 -27
- package/dist/tools/fs/read-deny.d.ts +41 -11
- package/dist/tools/fs/read-deny.js +51 -5
- package/dist/tools/fs/safety.d.ts +4 -26
- package/dist/tools/fs/safety.js +10 -32
- package/dist/tools/fs/search.js +15 -10
- package/dist/tools/fs/shell-read-argv.d.ts +3 -2
- package/dist/tools/fs/shell-read-argv.js +118 -38
- package/dist/tools/fs/shell-read-establish.d.ts +5 -5
- package/dist/tools/fs/shell-read-establish.js +11 -61
- package/dist/tools/fs/shell-read-identity.js +6 -3
- package/dist/tools/fs/shell-read-judge.d.ts +13 -15
- package/dist/tools/fs/shell-read-judge.js +18 -4
- package/dist/tools/fs/shell-read-plan.d.ts +2 -2
- package/dist/tools/web.js +1 -1
- package/package.json +13 -1
- package/test/export-surface.snapshot.json +242 -99
- package/wire-changes/core@7.52.0.json +5859 -0
- package/dist/core/hook-seats.d.ts +0 -66
- package/dist/core/hook-seats.js +0 -37
- package/dist/prompt-assembly/packs/sema-default.d.ts +0 -2
- package/dist/prompt-assembly/packs/sema-default.js +0 -147
- package/dist/prompts/simple-sections.d.ts +0 -58
- package/dist/prompts/simple-sections.js +0 -43
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { type BandId, type CatalogSection, type OverlayOp, type OverlaySource, type VariantWhen } from "./catalog/schema.js";
|
|
2
|
+
/** One overlay: an operation on a target, carrying text (or a catalog message reference). */
|
|
3
|
+
export interface PromptOverlay {
|
|
4
|
+
/** `<namespace>/<name>`; the `core/` namespace is the task sugar's alone. Names an added entry. */
|
|
5
|
+
readonly id: string;
|
|
6
|
+
readonly op: OverlayOp;
|
|
7
|
+
/** A message id (`replace` / `append`), a band id (`add`), or a section / added-entry id (`drop`). */
|
|
8
|
+
readonly target: string;
|
|
9
|
+
/** The overlay's text (`replace` / `append` / `add`); exclusive with `message`. */
|
|
10
|
+
readonly text?: string;
|
|
11
|
+
/** A catalog message whose selected variant is the overlay's text; exclusive with `text`. */
|
|
12
|
+
readonly message?: string;
|
|
13
|
+
/** Selects a center artifact's overlay by binding; carried by center artifacts only. */
|
|
14
|
+
readonly scope?: {
|
|
15
|
+
readonly binding?: string;
|
|
16
|
+
};
|
|
17
|
+
/** The overlay applies to this run only when this holds (the variant selector's own closed vocabulary). */
|
|
18
|
+
readonly when?: VariantWhen;
|
|
19
|
+
}
|
|
20
|
+
/** The source classes in application order (later wins). `bundled` is the catalog itself and writes no overlay. */
|
|
21
|
+
export declare const OVERLAY_SOURCE_ORDER: readonly ["bundled", "task", "center", "deploy"];
|
|
22
|
+
/** Who contributed an overlay: its source class and, within it, the contributor (`sugar`, a mods registration, the center). */
|
|
23
|
+
export interface OverlayOrigin {
|
|
24
|
+
readonly source: OverlaySource;
|
|
25
|
+
readonly by: string;
|
|
26
|
+
}
|
|
27
|
+
export interface SourcedOverlay {
|
|
28
|
+
readonly overlay: PromptOverlay;
|
|
29
|
+
readonly origin: OverlayOrigin;
|
|
30
|
+
}
|
|
31
|
+
/** An overlay a later one on the same target overrode (or a drop removed), or one that changed nothing this run. */
|
|
32
|
+
export interface SupersededOverlay {
|
|
33
|
+
readonly id: string;
|
|
34
|
+
readonly source: OverlaySource;
|
|
35
|
+
readonly by: string;
|
|
36
|
+
readonly target: string;
|
|
37
|
+
/** The overlay id that won, or {@link ABSENT_THIS_RUN}. */
|
|
38
|
+
readonly supersededBy: string;
|
|
39
|
+
}
|
|
40
|
+
/** `supersededBy` of an overlay that changed nothing this run: the selector chose no variant of its target, or of
|
|
41
|
+
* the catalog message it takes its text from. */
|
|
42
|
+
export declare const ABSENT_THIS_RUN = "(absent this run)";
|
|
43
|
+
/** The section a message id is placed by, when the catalog places it. */
|
|
44
|
+
export declare function sectionOfMessage(id: string): CatalogSection | undefined;
|
|
45
|
+
export interface LockedEntry {
|
|
46
|
+
readonly message: string;
|
|
47
|
+
readonly variant: string;
|
|
48
|
+
readonly text: string;
|
|
49
|
+
}
|
|
50
|
+
/** Every constitution entry the guard compares: each message a constitution section places, every variant, whole. */
|
|
51
|
+
export declare function lockedEntries(): readonly LockedEntry[];
|
|
52
|
+
/** The constitution entries (`message#variant`) whose canonical text `text` contains verbatim. */
|
|
53
|
+
export declare function lockedTextIn(text: string): string[];
|
|
54
|
+
/** The task sugar's one violation: a role-layer text that carries locked text (an already-assembled prompt). */
|
|
55
|
+
export declare function assembledRoleRefused(field: string, hits: readonly string[]): Error;
|
|
56
|
+
/** Receive a source's prompt data ({@link PROMPT_DATA}): its frozen copy, or the clause naming what in it is not data. */
|
|
57
|
+
export declare function receivePromptData(raw: unknown): {
|
|
58
|
+
readonly value: unknown;
|
|
59
|
+
} | {
|
|
60
|
+
readonly notData: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* The run's center binding (`TaskSpec.promptBinding`): the key a center artifact's scoped overlays are selected by.
|
|
64
|
+
* Its one writer is the task (a deployment names its scenario); absent ⇒ undefined. A value outside the grammar is
|
|
65
|
+
* refused by name (`config.prompt_selector_invalid`), never read as absent.
|
|
66
|
+
*/
|
|
67
|
+
export declare function resolvePromptBinding(task: {
|
|
68
|
+
readonly promptBinding?: unknown;
|
|
69
|
+
}): string | undefined;
|
|
70
|
+
/** What a validation needs besides the overlay: its source class, which mods event (if any) carries it, and the
|
|
71
|
+
* entries lower classes added (the only entries a `drop` may name besides a built-in section). */
|
|
72
|
+
export interface OverlayValidationContext {
|
|
73
|
+
readonly source: OverlaySource;
|
|
74
|
+
/** The mods event the overlay arrived on; absent for the sugar and the center. */
|
|
75
|
+
readonly event?: "prompt.compose";
|
|
76
|
+
/** The request-body sugar may use the `core/` namespace; nothing else may. */
|
|
77
|
+
readonly sugar?: boolean;
|
|
78
|
+
/** Ids of entries lower source classes added (`add`) and the band each landed in. */
|
|
79
|
+
readonly lowerAdds?: ReadonlyMap<string, BandId>;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Validate one overlay for one source class. Returns the overlay (a frozen copy of its known members) or why it is
|
|
83
|
+
* a violation: shape, namespace, op, text/message, `when`, `scope`, target existence, band authorization (and the
|
|
84
|
+
* band's mods write port), and the locked-text guard.
|
|
85
|
+
*/
|
|
86
|
+
export declare function validateOverlay(raw: unknown, ctx: OverlayValidationContext): {
|
|
87
|
+
readonly overlay: PromptOverlay;
|
|
88
|
+
} | {
|
|
89
|
+
readonly violation: string;
|
|
90
|
+
};
|
|
91
|
+
/** One added entry as the fold leaves it. */
|
|
92
|
+
export interface AddedEntry {
|
|
93
|
+
readonly id: string;
|
|
94
|
+
readonly band: BandId;
|
|
95
|
+
readonly rank: number;
|
|
96
|
+
readonly text: string;
|
|
97
|
+
readonly origin: OverlayOrigin;
|
|
98
|
+
}
|
|
99
|
+
/** One overlay in a section's history, in application order; `superseded` once a later one overrode it. The
|
|
100
|
+
* composition puts the catalog's own text (`bundled`) first for a catalog section. */
|
|
101
|
+
export interface ChainLink {
|
|
102
|
+
readonly source: "bundled" | OverlaySource;
|
|
103
|
+
readonly overlay?: string;
|
|
104
|
+
readonly op?: OverlayOp;
|
|
105
|
+
readonly superseded?: true;
|
|
106
|
+
}
|
|
107
|
+
/** The fold's result: per-message text the overlays set, dropped sections, added entries, superseded overlays. */
|
|
108
|
+
export interface OverlayFold {
|
|
109
|
+
/** Message id → its text after the overlays (absent ⇒ the selected variant's text stands). */
|
|
110
|
+
readonly messageText: ReadonlyMap<string, {
|
|
111
|
+
readonly text: string;
|
|
112
|
+
readonly origin: OverlayOrigin;
|
|
113
|
+
readonly replaced: boolean;
|
|
114
|
+
}>;
|
|
115
|
+
/** Built-in section ids a drop removed. */
|
|
116
|
+
readonly dropped: ReadonlySet<string>;
|
|
117
|
+
readonly added: readonly AddedEntry[];
|
|
118
|
+
readonly superseded: readonly SupersededOverlay[];
|
|
119
|
+
/** Section id (or added-entry id) → the overlays applied to it, in order, superseded ones marked. */
|
|
120
|
+
readonly chains: ReadonlyMap<string, readonly ChainLink[]>;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Apply sourced overlays, already validated and already in application order, over the selected texts.
|
|
124
|
+
* `selectedText(messageId)` answers the text the selector chose (undefined ⇒ the message is absent this run);
|
|
125
|
+
* `applies(overlay)` answers its `when`.
|
|
126
|
+
*/
|
|
127
|
+
export declare function foldOverlays(ordered: readonly SourcedOverlay[], selectedText: (messageId: string) => string | undefined, applies: (o: PromptOverlay) => boolean, overlayText: (o: PromptOverlay) => string | undefined): OverlayFold;
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { types } from "node:util";
|
|
2
|
+
import { describeFault, isPlainRecord, receive } from "../core/mods/kernel/receive.js";
|
|
3
|
+
import { egressText } from "../core/untrusted-egress.js";
|
|
4
|
+
import { bandOf, isBandId } from "./bands.js";
|
|
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";
|
|
7
|
+
import { RENDERERS } from "./renderers.js";
|
|
8
|
+
export const OVERLAY_SOURCE_ORDER = Object.freeze(["bundled", "task", "center", "deploy"]);
|
|
9
|
+
export const ABSENT_THIS_RUN = "(absent this run)";
|
|
10
|
+
const SECTION_BY_ID = new Map(SEMA_DEFAULT_CATALOG.sections.map((s) => [s.id, s]));
|
|
11
|
+
const MESSAGE_TARGETS = (() => {
|
|
12
|
+
const m = new Map();
|
|
13
|
+
for (const s of SEMA_DEFAULT_CATALOG.sections) {
|
|
14
|
+
const ids = "message" in s.body ? [s.body.message] : "lines" in s.body ? s.body.lines.map((l) => l.message) : (RENDERERS[s.body.renderer].messages ?? []);
|
|
15
|
+
for (const id of ids)
|
|
16
|
+
m.set(id, { section: s });
|
|
17
|
+
}
|
|
18
|
+
return m;
|
|
19
|
+
})();
|
|
20
|
+
const MESSAGE_IDS = new Set(SEMA_DEFAULT_CATALOG.messages.map((m) => m.id));
|
|
21
|
+
export function sectionOfMessage(id) {
|
|
22
|
+
return MESSAGE_TARGETS.get(id)?.section;
|
|
23
|
+
}
|
|
24
|
+
const LOCKED = Object.freeze(SEMA_DEFAULT_CATALOG.sections
|
|
25
|
+
.filter((s) => s.band === "constitution" && !("renderer" in s.body))
|
|
26
|
+
.flatMap((s) => ("message" in s.body ? [s.body.message] : "lines" in s.body ? s.body.lines.map((l) => l.message) : []))
|
|
27
|
+
.flatMap((id) => catalogMessage(id).variants.map((v) => Object.freeze({ message: id, variant: v.id, text: v.text }))));
|
|
28
|
+
export function lockedEntries() {
|
|
29
|
+
return LOCKED;
|
|
30
|
+
}
|
|
31
|
+
export function lockedTextIn(text) {
|
|
32
|
+
const hits = [];
|
|
33
|
+
for (const e of LOCKED)
|
|
34
|
+
if (text.includes(e.text))
|
|
35
|
+
hits.push(`${e.message}#${e.variant}`);
|
|
36
|
+
return hits;
|
|
37
|
+
}
|
|
38
|
+
export function assembledRoleRefused(field, hits) {
|
|
39
|
+
const named = [...new Set(hits.map((h) => h.split("#")[0]))];
|
|
40
|
+
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
|
+
const ID_GRAMMAR = /^[a-z0-9][a-z0-9/._-]*$/;
|
|
43
|
+
const OVERLAY_KEYS = new Set(["id", "op", "target", "text", "message", "scope", "when"]);
|
|
44
|
+
const OPS = new Set(OVERLAY_OPS);
|
|
45
|
+
const PROMPT_DATA = Object.freeze({ accessors: "refuse", depth: 4, others: "refuse", freeze: true, isProxy: (v) => types.isProxy(v) });
|
|
46
|
+
export function receivePromptData(raw) {
|
|
47
|
+
const r = receive(raw, PROMPT_DATA);
|
|
48
|
+
return r.ok ? { value: r.value } : { notData: describeFault(r.fault) };
|
|
49
|
+
}
|
|
50
|
+
const BINDING_MAX = 128;
|
|
51
|
+
function bindingProblem(v) {
|
|
52
|
+
return typeof v !== "string" || v.trim() === "" || v.length > BINDING_MAX ? `${str(v)} is not a non-blank string of at most ${BINDING_MAX} characters` : undefined;
|
|
53
|
+
}
|
|
54
|
+
export function resolvePromptBinding(task) {
|
|
55
|
+
if (task.promptBinding === undefined)
|
|
56
|
+
return undefined;
|
|
57
|
+
const why = bindingProblem(task.promptBinding);
|
|
58
|
+
if (why !== undefined)
|
|
59
|
+
throw Object.assign(new Error(`TaskSpec.promptBinding ${why} (or absent)`), { code: "config.prompt_selector_invalid" });
|
|
60
|
+
return task.promptBinding;
|
|
61
|
+
}
|
|
62
|
+
function str(v, max = 160) {
|
|
63
|
+
if (typeof v !== "string")
|
|
64
|
+
return typeof v;
|
|
65
|
+
const e = egressText("same-principal", v);
|
|
66
|
+
return JSON.stringify(e.length > max ? `${e.slice(0, max)}…` : e);
|
|
67
|
+
}
|
|
68
|
+
function whenViolation(when) {
|
|
69
|
+
if (typeof when !== "object" || when === null || Array.isArray(when))
|
|
70
|
+
return `"when" is ${str(when)}, not an object`;
|
|
71
|
+
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)`;
|
|
74
|
+
const w = when;
|
|
75
|
+
if (w["traits"] !== undefined) {
|
|
76
|
+
const t = w["traits"];
|
|
77
|
+
if (typeof t !== "object" || t === null || Array.isArray(t))
|
|
78
|
+
return `"when.traits" is not an object`;
|
|
79
|
+
for (const [k, list] of Object.entries(t)) {
|
|
80
|
+
if (k !== "allOf" && k !== "noneOf")
|
|
81
|
+
return `"when.traits" carries ${str(k)} (allOf, noneOf only)`;
|
|
82
|
+
if (!Array.isArray(list))
|
|
83
|
+
return `"when.traits.${k}" is not an array`;
|
|
84
|
+
for (const name of list)
|
|
85
|
+
if (!isWordOf(PROMPT_TRAITS, name))
|
|
86
|
+
return `"when.traits.${k}" names ${str(name)}, not a trait (${PROMPT_TRAITS.join(", ")})`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
if (w["host"] !== undefined) {
|
|
90
|
+
const h = w["host"];
|
|
91
|
+
if (typeof h !== "object" || h === null || Array.isArray(h))
|
|
92
|
+
return `"when.host" is not an object`;
|
|
93
|
+
for (const [k, v] of Object.entries(h)) {
|
|
94
|
+
if (k === "role" ? !isWordOf(HOST_ROLES, v) : k === "form" ? !isWordOf(HOST_FORMS, v) : true) {
|
|
95
|
+
return `"when.host" carries ${str(k)} = ${str(v)} (role: ${HOST_ROLES.join(" | ")}; form: ${HOST_FORMS.join(" | ")})`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (w["facts"] !== undefined) {
|
|
100
|
+
const f = w["facts"];
|
|
101
|
+
if (typeof f !== "object" || f === null || Array.isArray(f))
|
|
102
|
+
return `"when.facts" is not an object`;
|
|
103
|
+
for (const [k, v] of Object.entries(f)) {
|
|
104
|
+
if (!isWordOf(PROMPT_FACT_NAMES, k))
|
|
105
|
+
return `"when.facts" names ${str(k)}, not a fact`;
|
|
106
|
+
if (typeof v !== "boolean")
|
|
107
|
+
return `"when.facts.${k}" is ${str(v)}, not a boolean`;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
function textsOf(o) {
|
|
113
|
+
if (o.text !== undefined)
|
|
114
|
+
return [o.text];
|
|
115
|
+
if (o.message !== undefined && MESSAGE_IDS.has(o.message))
|
|
116
|
+
return catalogMessage(o.message).variants.map((v) => v.text);
|
|
117
|
+
return [];
|
|
118
|
+
}
|
|
119
|
+
export function validateOverlay(raw, ctx) {
|
|
120
|
+
const fail = (why) => ({ violation: why });
|
|
121
|
+
const received = receivePromptData(raw);
|
|
122
|
+
if ("notData" in received)
|
|
123
|
+
return fail(`an overlay is data (plain objects, arrays, strings, booleans); it holds ${received.notData}`);
|
|
124
|
+
const r = received.value;
|
|
125
|
+
if (!isPlainRecord(r))
|
|
126
|
+
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 (!OVERLAY_KEYS.has(k))
|
|
129
|
+
return fail(`an overlay carries ${str(k)} (id, op, target, text, message, scope, when only)`);
|
|
130
|
+
const { id, op, target, text, message, scope, when } = r;
|
|
131
|
+
if (typeof id !== "string" || id.length === 0 || id.length > 128 || !ID_GRAMMAR.test(id))
|
|
132
|
+
return fail(`overlay id ${str(id)} is not ^[a-z0-9][a-z0-9/._-]*$ of at most 128 characters`);
|
|
133
|
+
if (id.startsWith("core/") && ctx.sugar !== true)
|
|
134
|
+
return fail(`overlay id ${str(id)}: the core/ namespace is the engine's own`);
|
|
135
|
+
if (typeof op !== "string" || !OPS.has(op))
|
|
136
|
+
return fail(`overlay "${id}": op ${str(op)} is not one of ${OVERLAY_OPS.join(", ")}`);
|
|
137
|
+
if (typeof target !== "string" || target.length === 0)
|
|
138
|
+
return fail(`overlay "${id}": target ${str(target)} is not an id`);
|
|
139
|
+
const carries = op !== "drop";
|
|
140
|
+
if (!carries && (text !== undefined || message !== undefined))
|
|
141
|
+
return fail(`overlay "${id}": a drop carries no text or message`);
|
|
142
|
+
if (carries && (text === undefined) === (message === undefined))
|
|
143
|
+
return fail(`overlay "${id}": a ${op} carries exactly one of text, message`);
|
|
144
|
+
if (text !== undefined && (typeof text !== "string" || text.trim() === ""))
|
|
145
|
+
return fail(`overlay "${id}": text is ${typeof text === "string" ? "blank" : str(text)}`);
|
|
146
|
+
if (message !== undefined && (typeof message !== "string" || !MESSAGE_IDS.has(message)))
|
|
147
|
+
return fail(`overlay "${id}": message ${str(message)} is not a catalog message`);
|
|
148
|
+
if (when !== undefined) {
|
|
149
|
+
const why = whenViolation(when);
|
|
150
|
+
if (why !== undefined)
|
|
151
|
+
return fail(`overlay "${id}": ${why}`);
|
|
152
|
+
}
|
|
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
|
+
let band;
|
|
159
|
+
let where;
|
|
160
|
+
if (op === "add") {
|
|
161
|
+
if (!isBandId(target))
|
|
162
|
+
return fail(`overlay "${id}": an add targets a band; ${str(target)} is not one`);
|
|
163
|
+
if (bandOf(target).addRank === undefined)
|
|
164
|
+
return fail(`overlay "${id}": band "${target}" takes no additions`);
|
|
165
|
+
if (SECTION_BY_ID.has(id) || MESSAGE_IDS.has(id))
|
|
166
|
+
return fail(`overlay "${id}": an added entry cannot take a catalog id`);
|
|
167
|
+
band = target;
|
|
168
|
+
where = `band "${target}"`;
|
|
169
|
+
}
|
|
170
|
+
else if (op === "drop") {
|
|
171
|
+
const section = SECTION_BY_ID.get(target);
|
|
172
|
+
const added = ctx.lowerAdds?.get(target);
|
|
173
|
+
if (section !== undefined)
|
|
174
|
+
band = section.band;
|
|
175
|
+
else if (added !== undefined)
|
|
176
|
+
band = added;
|
|
177
|
+
else
|
|
178
|
+
return fail(`overlay "${id}": drop target ${str(target)} is neither a catalog section nor an entry a lower source added`);
|
|
179
|
+
where = `"${target}" (band "${band}")`;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const placed = MESSAGE_TARGETS.get(target);
|
|
183
|
+
if (placed === undefined)
|
|
184
|
+
return fail(`overlay "${id}": ${op} target ${str(target)} is not a message the catalog places`);
|
|
185
|
+
band = placed.section.band;
|
|
186
|
+
where = `"${target}" (band "${band}")`;
|
|
187
|
+
}
|
|
188
|
+
const row = bandOf(band);
|
|
189
|
+
if (!row.ops[ctx.source].includes(op)) {
|
|
190
|
+
return fail(`overlay "${id}": a ${ctx.source} overlay may not ${op} ${where} (the band grants ${ctx.source} ${row.ops[ctx.source].length > 0 ? row.ops[ctx.source].join(", ") : "nothing"})`);
|
|
191
|
+
}
|
|
192
|
+
if (ctx.event !== undefined && row.modsEvent !== ctx.event)
|
|
193
|
+
return fail(`overlay "${id}": ${where} is written through ${row.modsEvent ?? "no mods event"}, not ${ctx.event}`);
|
|
194
|
+
const overlay = Object.freeze({
|
|
195
|
+
id,
|
|
196
|
+
op: op,
|
|
197
|
+
target,
|
|
198
|
+
...(text !== undefined ? { text: text } : {}),
|
|
199
|
+
...(message !== undefined ? { message: message } : {}),
|
|
200
|
+
...(scope !== undefined ? { scope: scope } : {}),
|
|
201
|
+
...(when !== undefined ? { when: when } : {}),
|
|
202
|
+
});
|
|
203
|
+
for (const t of textsOf(overlay)) {
|
|
204
|
+
const hits = lockedTextIn(t);
|
|
205
|
+
if (hits.length > 0)
|
|
206
|
+
return fail(`overlay "${id}": its text contains, verbatim, the locked text of ${[...new Set(hits.map((h) => h.split("#")[0]))].join(", ")}`);
|
|
207
|
+
}
|
|
208
|
+
return { overlay };
|
|
209
|
+
}
|
|
210
|
+
export function foldOverlays(ordered, selectedText, applies, overlayText) {
|
|
211
|
+
const messageText = new Map();
|
|
212
|
+
const writers = new Map();
|
|
213
|
+
const dropped = new Map();
|
|
214
|
+
const added = new Map();
|
|
215
|
+
const addedBy = new Map();
|
|
216
|
+
const addCount = new Map();
|
|
217
|
+
const superseded = [];
|
|
218
|
+
const chains = new Map();
|
|
219
|
+
const supersede = (w, target, by) => {
|
|
220
|
+
superseded.push(Object.freeze({ id: w.id, source: w.origin.source, by: w.origin.by, target, supersededBy: by }));
|
|
221
|
+
if (w.link !== undefined)
|
|
222
|
+
w.link.superseded = true;
|
|
223
|
+
};
|
|
224
|
+
const applied = (key, o, origin) => {
|
|
225
|
+
const link = { source: origin.source, overlay: o.id, op: o.op };
|
|
226
|
+
chains.set(key, [...(chains.get(key) ?? []), link]);
|
|
227
|
+
return { id: o.id, origin, link };
|
|
228
|
+
};
|
|
229
|
+
const sectionMessages = (sectionId) => [...MESSAGE_TARGETS.entries()].filter(([, t]) => t.section.id === sectionId).map(([m]) => m);
|
|
230
|
+
for (const { overlay: o, origin } of ordered) {
|
|
231
|
+
if (!applies(o))
|
|
232
|
+
continue;
|
|
233
|
+
const me = { id: o.id, origin };
|
|
234
|
+
const text = o.op === "drop" ? "" : overlayText(o);
|
|
235
|
+
if (text === undefined) {
|
|
236
|
+
supersede(me, o.target, ABSENT_THIS_RUN);
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
if (o.op === "add") {
|
|
240
|
+
const prior = addedBy.get(o.id);
|
|
241
|
+
if (prior !== undefined)
|
|
242
|
+
supersede(prior, o.target, o.id);
|
|
243
|
+
const band = o.target;
|
|
244
|
+
const k = addCount.get(band) ?? 0;
|
|
245
|
+
addCount.set(band, k + 1);
|
|
246
|
+
added.set(o.id, Object.freeze({ id: o.id, band, rank: bandOf(band).addRank + k * 0.001, text, origin }));
|
|
247
|
+
addedBy.set(o.id, applied(o.id, o, origin));
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (o.op === "drop") {
|
|
251
|
+
const entry = addedBy.get(o.target);
|
|
252
|
+
if (entry !== undefined) {
|
|
253
|
+
supersede(entry, o.target, o.id);
|
|
254
|
+
added.delete(o.target);
|
|
255
|
+
addedBy.delete(o.target);
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
for (const m of sectionMessages(o.target)) {
|
|
259
|
+
for (const w of writers.get(m) ?? [])
|
|
260
|
+
supersede(w, m, o.id);
|
|
261
|
+
writers.delete(m);
|
|
262
|
+
messageText.delete(m);
|
|
263
|
+
}
|
|
264
|
+
dropped.set(o.target, applied(o.target, o, origin));
|
|
265
|
+
continue;
|
|
266
|
+
}
|
|
267
|
+
const section = MESSAGE_TARGETS.get(o.target).section;
|
|
268
|
+
const drop = dropped.get(section.id);
|
|
269
|
+
if (o.op === "append" && drop !== undefined) {
|
|
270
|
+
supersede(me, o.target, drop.id);
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
if (selectedText(o.target) === undefined && !messageText.has(o.target)) {
|
|
274
|
+
supersede(me, o.target, ABSENT_THIS_RUN);
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
if (drop !== undefined) {
|
|
278
|
+
supersede(drop, section.id, o.id);
|
|
279
|
+
dropped.delete(section.id);
|
|
280
|
+
}
|
|
281
|
+
const writer = applied(section.id, o, origin);
|
|
282
|
+
if (o.op === "replace") {
|
|
283
|
+
for (const w of writers.get(o.target) ?? [])
|
|
284
|
+
supersede(w, o.target, o.id);
|
|
285
|
+
writers.set(o.target, [writer]);
|
|
286
|
+
messageText.set(o.target, { text, origin, replaced: true });
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
const base = messageText.get(o.target)?.text ?? selectedText(o.target);
|
|
290
|
+
writers.set(o.target, [...(writers.get(o.target) ?? []), writer]);
|
|
291
|
+
messageText.set(o.target, { text: `${base}\n\n${text}`, origin, replaced: messageText.get(o.target)?.replaced ?? false });
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return {
|
|
295
|
+
messageText,
|
|
296
|
+
dropped: new Set(dropped.keys()),
|
|
297
|
+
added: [...added.values()],
|
|
298
|
+
superseded,
|
|
299
|
+
chains: new Map([...chains].map(([k, links]) => [k, Object.freeze(links.map((l) => Object.freeze({ ...l })))])),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RendererId } from "./catalog/schema.js";
|
|
2
|
+
import { type PromptSelectors } from "./select.js";
|
|
3
|
+
import type { SectionRenderInputs } from "./types.js";
|
|
4
|
+
export interface RendererSpec {
|
|
5
|
+
readonly id: RendererId;
|
|
6
|
+
readonly version: number;
|
|
7
|
+
readonly stability: "static" | "session" | "leg";
|
|
8
|
+
readonly reads: "inputs" | "facts" | "env" | "memory" | "mcp" | "mark" | "selectors";
|
|
9
|
+
readonly external: boolean;
|
|
10
|
+
/** The catalog messages this renderer's output is (an overlay targets them). */
|
|
11
|
+
readonly messages?: readonly string[];
|
|
12
|
+
}
|
|
13
|
+
export declare const RENDERERS: Readonly<Record<RendererId, RendererSpec>>;
|
|
14
|
+
/** The renderer version vector — the identity's renderer element (a changed output bumps a version). */
|
|
15
|
+
export declare function rendererVector(): Readonly<Record<RendererId, number>>;
|
|
16
|
+
/** One renderer's output for these inputs (and the variant it rendered, when it rendered a catalog message);
|
|
17
|
+
* undefined ⇒ the section is absent this run. */
|
|
18
|
+
export declare function runRenderer(id: RendererId, inputs: SectionRenderInputs, selectors: PromptSelectors): {
|
|
19
|
+
readonly text: string;
|
|
20
|
+
readonly variant?: string;
|
|
21
|
+
} | undefined;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { reminderMarkDeclaration } from "../core/reminder-mint.js";
|
|
2
|
+
import { renderCoworkBase } from "../prompts/cowork.js";
|
|
3
|
+
import { catalogMessage } from "./catalog/index.js";
|
|
4
|
+
import { selectVariant } from "./select.js";
|
|
5
|
+
export const RENDERERS = {
|
|
6
|
+
"role-base": { id: "role-base", version: 2, stability: "session", reads: "selectors", external: false, messages: ["core/role.base"] },
|
|
7
|
+
"model-guidance": { id: "model-guidance", version: 1, stability: "session", reads: "inputs", external: false },
|
|
8
|
+
"mcp-instructions": { id: "mcp-instructions", version: 1, stability: "session", reads: "mcp", external: true },
|
|
9
|
+
"reminder-mark": { id: "reminder-mark", version: 1, stability: "session", reads: "mark", external: false },
|
|
10
|
+
environment: { id: "environment", version: 2, stability: "leg", reads: "env", external: false },
|
|
11
|
+
memory: { id: "memory", version: 1, stability: "leg", reads: "memory", external: false },
|
|
12
|
+
};
|
|
13
|
+
export function rendererVector() {
|
|
14
|
+
return Object.fromEntries(Object.values(RENDERERS).map((r) => [r.id, r.version]));
|
|
15
|
+
}
|
|
16
|
+
export function runRenderer(id, inputs, selectors) {
|
|
17
|
+
const plain = (text) => (text === undefined ? undefined : { text });
|
|
18
|
+
switch (id) {
|
|
19
|
+
case "role-base": {
|
|
20
|
+
const v = selectVariant(catalogMessage("core/role.base"), selectors);
|
|
21
|
+
if (v === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (v.id !== "cowork")
|
|
24
|
+
return { text: v.text, variant: v.id };
|
|
25
|
+
const sections = renderCoworkBase({ tools: inputs.toolNames ?? [], workspaceFolder: inputs.workspaceFolder });
|
|
26
|
+
return sections.length === 0 ? undefined : { text: sections.map((s) => s.text).join("\n\n"), variant: v.id };
|
|
27
|
+
}
|
|
28
|
+
case "model-guidance":
|
|
29
|
+
return plain(inputs.modelGuidance);
|
|
30
|
+
case "mcp-instructions":
|
|
31
|
+
return plain(inputs.mcpInstructionsBlock);
|
|
32
|
+
case "reminder-mark":
|
|
33
|
+
return plain(inputs.facts.reminderMark !== undefined ? reminderMarkDeclaration(inputs.facts.reminderMark) : undefined);
|
|
34
|
+
case "environment":
|
|
35
|
+
return plain(inputs.environmentBlock);
|
|
36
|
+
case "memory":
|
|
37
|
+
return plain(inputs.memoryBlock);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -4,8 +4,8 @@ export interface ContextUsageSection {
|
|
|
4
4
|
id: string;
|
|
5
5
|
/** The section's ESTIMATED token weight (see {@link contextUsageSections} for what that promises). */
|
|
6
6
|
tokens: number;
|
|
7
|
-
/** The section's
|
|
8
|
-
* id. Absent only if the manifest entry carried no
|
|
7
|
+
/** The section's band (`role`, `constitution`, `core-behavior`, …), so a view can group without knowing
|
|
8
|
+
* every id. Absent only if the manifest entry carried no band. */
|
|
9
9
|
kind?: string;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
@@ -21,6 +21,6 @@ export interface ContextUsageSection {
|
|
|
21
21
|
*/
|
|
22
22
|
export declare function contextUsageSections(sections: ReadonlyArray<{
|
|
23
23
|
id: string;
|
|
24
|
-
|
|
24
|
+
band?: string;
|
|
25
25
|
chars: number;
|
|
26
26
|
}> | undefined): ContextUsageSection[] | undefined;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
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. Three dimensions, each with exactly one writer, so no value
|
|
4
|
+
* ever needs a precedence order:
|
|
5
|
+
*
|
|
6
|
+
* - `traits` — derived from the run's two prompt-shape axes by {@link promptTraitsOf} (the prompt profile and the
|
|
7
|
+
* fable-family model); catalog data reads traits, never the axes.
|
|
8
|
+
* - `host` — `role` (which role base the run is assembled for; `TaskSpec.promptRole`, absent ⇒ `general`) and
|
|
9
|
+
* `form` (`TaskSpec.promptForm`, which every engine-built child receives through the parent spec seat; absent ⇒
|
|
10
|
+
* `standard`).
|
|
11
|
+
* - `facts` — the runtime facts prepare produces (one derived: `executionEnvironmentDeclared`).
|
|
12
|
+
*
|
|
13
|
+
* A variant's `when` is a conjunction: every listed trait present, every `noneOf` trait absent, every host key
|
|
14
|
+
* equal, every fact equal. No disjunction, no expressions.
|
|
15
|
+
*/
|
|
16
|
+
import { type CatalogMessage, type FactConjunction, type HostForm, type HostRole, type PromptFactName, type PromptTrait, type Variant, type VariantWhen } from "./catalog/schema.js";
|
|
17
|
+
import type { PromptRuntimeFacts } from "./types.js";
|
|
18
|
+
/** The run's selector values, resolved once per assembly. */
|
|
19
|
+
export interface PromptSelectors {
|
|
20
|
+
readonly traits: ReadonlySet<PromptTrait>;
|
|
21
|
+
readonly host: {
|
|
22
|
+
readonly role: HostRole;
|
|
23
|
+
readonly form: HostForm;
|
|
24
|
+
};
|
|
25
|
+
readonly facts: Readonly<Record<PromptFactName, boolean>>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The run's prompt traits, derived from the two prompt-shape axes the engine resolves today: the simple
|
|
29
|
+
* profile is `lean_prompt`, a fable-family model is `fable_5_mitigations`. This is the only place those
|
|
30
|
+
* axes become traits.
|
|
31
|
+
*/
|
|
32
|
+
export declare function promptTraitsOf(facts: Pick<PromptRuntimeFacts, "promptProfile" | "fableMitigations">): ReadonlySet<PromptTrait>;
|
|
33
|
+
/** The predicate facts a condition may test; optional runtime facts read as false when absent. */
|
|
34
|
+
export declare function catalogFactsOf(facts: PromptRuntimeFacts): Readonly<Record<PromptFactName, boolean>>;
|
|
35
|
+
/**
|
|
36
|
+
* The host selector's two values as their one writer gave them: the task (`TaskSpec.promptRole` /
|
|
37
|
+
* `TaskSpec.promptForm`; an engine-built child's spec carries its parent's form through the parent spec seat).
|
|
38
|
+
* A value outside the closed set is refused by name (`config.prompt_selector_invalid`), never read as the default.
|
|
39
|
+
*/
|
|
40
|
+
export declare function resolveHost(task: {
|
|
41
|
+
readonly promptRole?: unknown;
|
|
42
|
+
readonly promptForm?: unknown;
|
|
43
|
+
}): {
|
|
44
|
+
readonly role?: HostRole;
|
|
45
|
+
readonly form?: HostForm;
|
|
46
|
+
};
|
|
47
|
+
/** The run's selectors: traits and facts from the runtime facts, the host from its two writers' values. */
|
|
48
|
+
export declare function selectorsOf(facts: PromptRuntimeFacts, host?: {
|
|
49
|
+
readonly role?: HostRole;
|
|
50
|
+
readonly form?: HostForm;
|
|
51
|
+
}): PromptSelectors;
|
|
52
|
+
export declare function factsHold(conj: FactConjunction | undefined, facts: Readonly<Record<PromptFactName, boolean>>): boolean;
|
|
53
|
+
/** Whether a `when` holds under the run's selectors. */
|
|
54
|
+
export declare function whenHolds(when: VariantWhen | undefined, s: PromptSelectors): boolean;
|
|
55
|
+
/** The variant this run receives, or undefined when no variant's `when` holds (the message is absent). */
|
|
56
|
+
export declare function selectVariant(message: CatalogMessage, s: PromptSelectors): Variant | undefined;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { HOST_ROLES, isWordOf } from "./catalog/schema.js";
|
|
2
|
+
export function promptTraitsOf(facts) {
|
|
3
|
+
const traits = new Set();
|
|
4
|
+
if (facts.promptProfile !== "classic")
|
|
5
|
+
traits.add("lean_prompt");
|
|
6
|
+
if (facts.fableMitigations === true)
|
|
7
|
+
traits.add("fable_5_mitigations");
|
|
8
|
+
return traits;
|
|
9
|
+
}
|
|
10
|
+
export function catalogFactsOf(facts) {
|
|
11
|
+
return {
|
|
12
|
+
policyEnabled: facts.policyEnabled,
|
|
13
|
+
hooksEnabled: facts.hooksEnabled,
|
|
14
|
+
isolationEnabled: facts.isolationEnabled,
|
|
15
|
+
readFaceOpen: facts.readFaceOpen === true,
|
|
16
|
+
writeFaceOpen: facts.writeFaceOpen === true,
|
|
17
|
+
withinTaskCompactionEnabled: facts.withinTaskCompactionEnabled,
|
|
18
|
+
supervisorEnabled: facts.supervisorEnabled,
|
|
19
|
+
orchestrationEnabled: facts.orchestrationEnabled,
|
|
20
|
+
orchestrationDeferred: facts.orchestrationDeferred === true,
|
|
21
|
+
awarenessEnabled: facts.awarenessEnabled,
|
|
22
|
+
goalEnabled: facts.goalEnabled,
|
|
23
|
+
worktreeIsolated: facts.worktreeIsolated,
|
|
24
|
+
teammateEnabled: facts.teammateEnabled,
|
|
25
|
+
isSubagent: facts.isSubagent === true,
|
|
26
|
+
executionEnvironmentDeclared: facts.policyEnabled || facts.isolationEnabled,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function resolveHost(task) {
|
|
30
|
+
const refuse = (key, value, allowed) => {
|
|
31
|
+
throw Object.assign(new Error(`TaskSpec.${key} is ${typeof value === "string" ? JSON.stringify(value.slice(0, 64)) : typeof value}; it is one of ${allowed.map((a) => `"${a}"`).join(", ")} (or absent)`), {
|
|
32
|
+
code: "config.prompt_selector_invalid",
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const role = task.promptRole === undefined ? undefined : isWordOf(HOST_ROLES, task.promptRole) ? task.promptRole : refuse("promptRole", task.promptRole, HOST_ROLES);
|
|
36
|
+
const form = task.promptForm === undefined ? undefined : task.promptForm === "minimal" ? "minimal" : refuse("promptForm", task.promptForm, ["minimal"]);
|
|
37
|
+
return Object.freeze({ ...(role !== undefined ? { role } : {}), ...(form !== undefined ? { form } : {}) });
|
|
38
|
+
}
|
|
39
|
+
export function selectorsOf(facts, host = {}) {
|
|
40
|
+
return Object.freeze({
|
|
41
|
+
traits: promptTraitsOf(facts),
|
|
42
|
+
host: Object.freeze({ role: host.role ?? "general", form: host.form ?? "standard" }),
|
|
43
|
+
facts: Object.freeze(catalogFactsOf(facts)),
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function factsHold(conj, facts) {
|
|
47
|
+
if (conj === undefined)
|
|
48
|
+
return true;
|
|
49
|
+
for (const [name, want] of Object.entries(conj))
|
|
50
|
+
if (facts[name] !== want)
|
|
51
|
+
return false;
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
function traitsHold(cond, traits) {
|
|
55
|
+
if (cond === undefined)
|
|
56
|
+
return true;
|
|
57
|
+
return (cond.allOf ?? []).every((t) => traits.has(t)) && !(cond.noneOf ?? []).some((t) => traits.has(t));
|
|
58
|
+
}
|
|
59
|
+
function hostHolds(cond, host) {
|
|
60
|
+
if (cond === undefined)
|
|
61
|
+
return true;
|
|
62
|
+
return (cond.role === undefined || cond.role === host.role) && (cond.form === undefined || cond.form === host.form);
|
|
63
|
+
}
|
|
64
|
+
export function whenHolds(when, s) {
|
|
65
|
+
return when === undefined || (traitsHold(when.traits, s.traits) && hostHolds(when.host, s.host) && factsHold(when.facts, s.facts));
|
|
66
|
+
}
|
|
67
|
+
export function selectVariant(message, s) {
|
|
68
|
+
return message.variants.find((v) => whenHolds(v.when, s));
|
|
69
|
+
}
|