@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
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import { isFrontmatterFence, UNCLOSED_FRONTMATTER_REASON } from "./frontmatter-fence.js";
|
|
3
4
|
import { physicalPathOf } from "./physical-path.js";
|
|
4
5
|
import { isPhysicallyWithin } from "../tools/fs/path-containment.js";
|
|
5
6
|
import { assertNoRetiredKeys } from "./retired-keys.js";
|
|
7
|
+
import { ruleSpellingOf } from "./permission-rule-syntax.js";
|
|
8
|
+
import { inlineUntrusted } from "./untrusted-text.js";
|
|
6
9
|
import { thrownText } from "./thrown-value.js";
|
|
7
10
|
const SKILL_FILE = "SKILL.md";
|
|
8
11
|
const RESOURCE_DIRS = ["assets", "references", "scripts"];
|
|
@@ -10,84 +13,685 @@ const NAME_MAX_CHARS = 64;
|
|
|
10
13
|
const NAME_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
11
14
|
const DESCRIPTION_MAX_CHARS = 1024;
|
|
12
15
|
const DEFAULT_MAX_ATTACHMENT_BYTES = 256 * 1024;
|
|
13
|
-
const
|
|
16
|
+
const ALLOWED_TOOLS_KEY = "allowed-tools";
|
|
17
|
+
const DISALLOWED_TOOLS_KEY = "disallowed-tools";
|
|
18
|
+
const DISALLOWED_TOOLS_ALIAS = "disallowedTools";
|
|
19
|
+
const TOOL_LIST_KEYS = new Set([ALLOWED_TOOLS_KEY, DISALLOWED_TOOLS_KEY, DISALLOWED_TOOLS_ALIAS]);
|
|
20
|
+
const UNREAD_CONTINUATION = "it is followed by indented lines the frontmatter reader does not read";
|
|
21
|
+
const TEXT_AFTER_END = "text follows its closing quote or its closing `]` on the same line";
|
|
22
|
+
const SEQUENCE_NOT_AN_ENTRY = "its `- name` entries are not indented alike";
|
|
23
|
+
const SEQUENCE_NOT_A_NAME = "an entry is not a plain or quoted name (nested, mapping, anchor, tag, flow and block-scalar entries, and number, boolean and null entries, are not read)";
|
|
24
|
+
const VALUE_IS_A_MAPPING = "its value is a mapping or holds one (`key: value` or `{…}`), not a list of names";
|
|
25
|
+
const VALUE_NOT_A_STRING = "its value is a number or a boolean, not a list of names";
|
|
26
|
+
const QUOTE_NOT_CLOSED = "a quote in it does not close";
|
|
27
|
+
const flowNotClosed = (opener) => `its \`${opener}\` does not close within its lines`;
|
|
28
|
+
const strayLine = (line) => `a flush-left line that is no key follows it (line ${line})`;
|
|
29
|
+
const NOT_A_KEY_LINE = "a flush-left frontmatter line is a key — letters, digits, `_` and `-`, or one quoted scalar — then `:` and a blank or nothing; a comment starts with `#`";
|
|
30
|
+
const PARENS_NOT_ONE_ZONE = "an entry's parentheses are not one group that closes it (a `(` that does not close, a `)` with no `(`, or text after the closing `)` — `\\(` / `\\)` are a rule's own text)";
|
|
31
|
+
const KEY_REPEATED = "the key is written more than once";
|
|
32
|
+
const notARule = (position) => `entry ${position} is no rule spelling (a tool name of ASCII letters, digits and \`_ - . : *\`, starting with a letter, a digit or \`_\`, then at most one parenthesized rule)`;
|
|
33
|
+
const keyInsideValue = (inner) => `an indented line under its value is a mapping key, \`${inlineUntrusted(inner, 64)}\` — YAML reads no key there (under a value that is not a mapping, or indented less than the nested block it follows)`;
|
|
34
|
+
const toolListOutOfPlace = (inner) => `it holds the tool-list key \`${inner}\` — a tool list is read only as a key of the frontmatter, written flush left; anywhere else its list would be lost`;
|
|
35
|
+
const isBlank = (ch) => ch === " " || ch === "\t";
|
|
36
|
+
function leadingBlanks(text) {
|
|
37
|
+
let n = 0;
|
|
38
|
+
while (n < text.length && isBlank(text.charAt(n)))
|
|
39
|
+
n++;
|
|
40
|
+
return n;
|
|
41
|
+
}
|
|
42
|
+
const trimLeadingBlanks = (text) => text.slice(leadingBlanks(text));
|
|
43
|
+
function trimTrailingBlanks(text) {
|
|
44
|
+
let to = text.length;
|
|
45
|
+
while (to > 0 && isBlank(text.charAt(to - 1)))
|
|
46
|
+
to--;
|
|
47
|
+
return text.slice(0, to);
|
|
48
|
+
}
|
|
49
|
+
const trimBlanks = (text) => trimLeadingBlanks(trimTrailingBlanks(text));
|
|
50
|
+
function isSkippable(line) {
|
|
51
|
+
const body = trimLeadingBlanks(line);
|
|
52
|
+
return body === "" || body.startsWith("#");
|
|
53
|
+
}
|
|
54
|
+
function keyTokenOf(line) {
|
|
55
|
+
const quote = line.charAt(0);
|
|
56
|
+
const close = quote === '"' || quote === "'" ? closingQuote(line, 0) : -1;
|
|
57
|
+
const key = close > 0 ? decodeQuoted(line.slice(1, close), quote) : /^[A-Za-z][A-Za-z0-9_-]*/.exec(line)?.[0];
|
|
58
|
+
if (key === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
return { key, after: trimLeadingBlanks(line.slice(close > 0 ? close + 1 : key.length)) };
|
|
61
|
+
}
|
|
62
|
+
function keyLineOf(line) {
|
|
63
|
+
const token = keyTokenOf(line);
|
|
64
|
+
return token !== undefined && token.after.startsWith(":") ? { key: token.key, rest: token.after.slice(1) } : undefined;
|
|
65
|
+
}
|
|
66
|
+
function yamlKeyLineOf(text) {
|
|
67
|
+
const line = keyLineOf(text);
|
|
68
|
+
return line !== undefined && (line.rest === "" || isBlank(line.rest.charAt(0))) ? line : undefined;
|
|
69
|
+
}
|
|
70
|
+
const yamlKeyOf = (text) => yamlKeyLineOf(text)?.key;
|
|
71
|
+
const isDashEntry = (text) => text.charAt(0) === "-" && (text.length === 1 || isBlank(text.charAt(1)));
|
|
72
|
+
function nestedLineHead(line) {
|
|
73
|
+
let text = trimLeadingBlanks(line);
|
|
74
|
+
let explicit = false;
|
|
75
|
+
for (;;) {
|
|
76
|
+
const marker = text.charAt(0);
|
|
77
|
+
if (text.length < 2 || (marker !== "-" && marker !== "?") || !isBlank(text.charAt(1)))
|
|
78
|
+
break;
|
|
79
|
+
explicit ||= marker === "?";
|
|
80
|
+
text = trimLeadingBlanks(text.slice(1));
|
|
81
|
+
}
|
|
82
|
+
const token = keyTokenOf(text);
|
|
83
|
+
const keyLine = yamlKeyLineOf(text);
|
|
84
|
+
const key = keyLine?.key ?? (explicit && token !== undefined && (token.after === "" || token.after.startsWith("#")) ? token.key : undefined);
|
|
85
|
+
if (key !== undefined && TOOL_LIST_KEYS.has(key))
|
|
86
|
+
return { key };
|
|
87
|
+
const value = trimLeadingBlanks(keyLine !== undefined ? keyLine.rest : text);
|
|
88
|
+
return value.charAt(0) === "{" || value.charAt(0) === "[" ? { flow: value } : {};
|
|
89
|
+
}
|
|
90
|
+
function toolListKeyIn(line) {
|
|
91
|
+
const head = nestedLineHead(line);
|
|
92
|
+
return head.key ?? (head.flow !== undefined ? scanValue(head.flow, "value").flowKey : undefined);
|
|
93
|
+
}
|
|
94
|
+
function nestedFlowAt(lines, at, end, flow, holds) {
|
|
95
|
+
const floor = Math.max(holds - 1, 0);
|
|
96
|
+
for (let budget = flow.length + 1;; budget *= 2) {
|
|
97
|
+
const region = valueRegion(lines, at, end, flow, floor, budget, false);
|
|
98
|
+
const scan = scanValue(region.lines.join("\n"), "value");
|
|
99
|
+
if (scan.unterminated === undefined || !region.capped)
|
|
100
|
+
return { ...(scan.flowKey !== undefined ? { key: scan.flowKey } : {}), held: Math.max(1, scan.held) };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function toolListKeyAfter(trailing) {
|
|
104
|
+
for (let p = 0; p < trailing.length; p++) {
|
|
105
|
+
if (isBlank(trailing.charAt(p)) || (p > 0 && !isBlank(trailing.charAt(p - 1))))
|
|
106
|
+
continue;
|
|
107
|
+
const key = yamlKeyOf(trailing.slice(p));
|
|
108
|
+
if (key !== undefined && TOOL_LIST_KEYS.has(key))
|
|
109
|
+
return key;
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
const opensNestedBlock = (text) => isDashEntry(text) || (text.charAt(0) === "?" && (text.length === 1 || isBlank(text.charAt(1)))) || yamlKeyOf(text) !== undefined || scanValue(text, "value").mapping === true;
|
|
14
114
|
function parseSkillFile(text) {
|
|
15
115
|
const fields = new Map();
|
|
16
|
-
const
|
|
116
|
+
const lists = new Map();
|
|
117
|
+
const normalized = (text.charCodeAt(0) === 0xfeff ? text.slice(1) : text).replace(/\r\n/g, "\n");
|
|
17
118
|
const lines = normalized.split("\n");
|
|
18
|
-
|
|
19
|
-
|
|
119
|
+
const unread = [];
|
|
120
|
+
const refused = new Set();
|
|
121
|
+
const refuse = (key, why, list) => {
|
|
122
|
+
if (refused.has(key))
|
|
123
|
+
return;
|
|
124
|
+
refused.add(key);
|
|
125
|
+
unread.push({ key, why, list });
|
|
126
|
+
};
|
|
127
|
+
let strayRefused = false;
|
|
128
|
+
const keep = (key, value) => {
|
|
129
|
+
if (!fields.has(key))
|
|
130
|
+
fields.set(key, value);
|
|
131
|
+
};
|
|
132
|
+
if (!isFrontmatterFence(lineAt(lines, 0)))
|
|
133
|
+
return { fields, lists, body: normalized, hadFrontmatter: false, unclosed: false, unread };
|
|
20
134
|
let end = -1;
|
|
21
135
|
for (let i = 1; i < lines.length; i++) {
|
|
22
|
-
if (lines
|
|
136
|
+
if (isFrontmatterFence(lineAt(lines, i))) {
|
|
23
137
|
end = i;
|
|
24
138
|
break;
|
|
25
139
|
}
|
|
26
140
|
}
|
|
27
141
|
if (end === -1)
|
|
28
|
-
return { fields, body: normalized, hadFrontmatter: false };
|
|
142
|
+
return { fields, lists, body: normalized, hadFrontmatter: false, unclosed: true, unread };
|
|
143
|
+
const front = [];
|
|
144
|
+
const fileLine = [];
|
|
145
|
+
for (let k = 0; k < end; k++) {
|
|
146
|
+
for (const piece of lineAt(lines, k).split("\r")) {
|
|
147
|
+
front.push(piece);
|
|
148
|
+
fileLine.push(k + 1);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const frontEnd = front.length;
|
|
29
152
|
let i = 1;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
153
|
+
let owner;
|
|
154
|
+
const listKeysSeen = new Set();
|
|
155
|
+
const valued = new Set();
|
|
156
|
+
let aliasSwallows;
|
|
157
|
+
const lost = (at, why) => {
|
|
158
|
+
refuse(at.key, why, at.list);
|
|
159
|
+
if (at.key === DISALLOWED_TOOLS_ALIAS)
|
|
160
|
+
aliasSwallows ??= why;
|
|
161
|
+
};
|
|
162
|
+
const listLostAfter = (at, trailing) => {
|
|
163
|
+
const inner = trailing !== undefined ? toolListKeyAfter(trailing) : undefined;
|
|
164
|
+
if (inner !== undefined)
|
|
165
|
+
lost(at, toolListOutOfPlace(inner));
|
|
166
|
+
};
|
|
167
|
+
while (i < frontEnd) {
|
|
168
|
+
const line = lineAt(front, i);
|
|
169
|
+
if (isSkippable(line)) {
|
|
34
170
|
i++;
|
|
35
171
|
continue;
|
|
36
172
|
}
|
|
37
|
-
if (
|
|
173
|
+
if (owner !== undefined && (isBlank(line.charAt(0)) ? leadingBlanks(line) >= owner.holds : owner.holds === 0 && isDashEntry(line))) {
|
|
174
|
+
const head = nestedLineHead(line);
|
|
175
|
+
const flow = head.key === undefined && head.flow !== undefined ? nestedFlowAt(front, i, frontEnd, head.flow, owner.holds) : undefined;
|
|
176
|
+
const held = flow?.held ?? 1;
|
|
177
|
+
let inner = head.key ?? flow?.key;
|
|
178
|
+
for (let at = i + 1; inner === undefined && at < i + held; at++)
|
|
179
|
+
inner = toolListKeyIn(lineAt(front, at));
|
|
180
|
+
if (inner !== undefined)
|
|
181
|
+
lost(owner, toolListOutOfPlace(inner));
|
|
182
|
+
i += held;
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (isBlank(line.charAt(0))) {
|
|
186
|
+
if (owner !== undefined) {
|
|
187
|
+
const inner = yamlKeyOf(trimLeadingBlanks(line));
|
|
188
|
+
const list = inner === undefined ? toolListKeyIn(line) : undefined;
|
|
189
|
+
if (inner !== undefined)
|
|
190
|
+
lost(owner, keyInsideValue(inner));
|
|
191
|
+
else if (list !== undefined)
|
|
192
|
+
lost(owner, toolListOutOfPlace(list));
|
|
193
|
+
else if (owner.list)
|
|
194
|
+
refuse(owner.key, UNREAD_CONTINUATION, true);
|
|
195
|
+
}
|
|
38
196
|
i++;
|
|
39
197
|
continue;
|
|
40
198
|
}
|
|
41
|
-
const
|
|
42
|
-
if (
|
|
199
|
+
const keyLine = yamlKeyLineOf(line);
|
|
200
|
+
if (keyLine === undefined) {
|
|
201
|
+
if (owner?.list === true)
|
|
202
|
+
lost(owner, strayLine(fileLine[i] ?? i + 1));
|
|
203
|
+
else if (!strayRefused) {
|
|
204
|
+
strayRefused = true;
|
|
205
|
+
unread.push({ line: fileLine[i] ?? i + 1, why: NOT_A_KEY_LINE });
|
|
206
|
+
}
|
|
207
|
+
owner = undefined;
|
|
43
208
|
i++;
|
|
44
209
|
continue;
|
|
45
210
|
}
|
|
46
|
-
const
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
if (
|
|
50
|
-
|
|
211
|
+
const { key, rest } = keyLine;
|
|
212
|
+
const tail = trimBlanks(rest);
|
|
213
|
+
owner = { key, list: TOOL_LIST_KEYS.has(key), holds: Number.POSITIVE_INFINITY };
|
|
214
|
+
if (owner.list) {
|
|
215
|
+
if (listKeysSeen.has(key))
|
|
216
|
+
refuse(key, KEY_REPEATED, true);
|
|
217
|
+
listKeysSeen.add(key);
|
|
218
|
+
const read = readToolList(front, i, frontEnd, trimLeadingBlanks(rest));
|
|
51
219
|
i = read.next;
|
|
52
|
-
|
|
53
|
-
|
|
220
|
+
listLostAfter(owner, read.trailing);
|
|
221
|
+
if (key === DISALLOWED_TOOLS_ALIAS)
|
|
222
|
+
aliasSwallows ??= read.unterminated;
|
|
223
|
+
const unspelled = read.problem === undefined ? read.entries.findIndex((e) => ruleSpellingOf(e) === undefined) : -1;
|
|
224
|
+
const problem = read.problem ?? (unspelled >= 0 ? notARule(unspelled + 1) : undefined);
|
|
225
|
+
if (problem !== undefined || read.null !== true)
|
|
226
|
+
valued.add(key);
|
|
227
|
+
if (problem !== undefined)
|
|
228
|
+
refuse(key, problem, true);
|
|
229
|
+
else if (read.null !== true && !lists.has(key))
|
|
230
|
+
lists.set(key, read.entries);
|
|
54
231
|
continue;
|
|
55
232
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
233
|
+
const start = valueStartOf(front, i, frontEnd, trimLeadingBlanks(rest));
|
|
234
|
+
if (start === undefined || (start.at > i && opensNestedBlock(start.first))) {
|
|
235
|
+
owner.holds = start === undefined ? 0 : leadingBlanks(lineAt(front, start.at));
|
|
236
|
+
keep(key, tail);
|
|
237
|
+
i++;
|
|
61
238
|
continue;
|
|
62
239
|
}
|
|
63
|
-
|
|
64
|
-
if (
|
|
240
|
+
const block = parseBlockScalarHeader(trimBlanks(start.first));
|
|
241
|
+
if (block !== undefined) {
|
|
242
|
+
const read = readBlockScalar(front, start.at + 1, frontEnd, block);
|
|
243
|
+
keep(key, start.at > i ? tail : read.value);
|
|
244
|
+
i = read.next;
|
|
65
245
|
continue;
|
|
66
|
-
|
|
246
|
+
}
|
|
247
|
+
const region = valueRegion(front, start.at, frontEnd, start.first, 0);
|
|
248
|
+
const scan = scanValue(region.lines.join("\n"), "value");
|
|
249
|
+
if (scan.unterminated !== undefined)
|
|
250
|
+
refuse(key, scan.unterminated, false);
|
|
251
|
+
listLostAfter(owner, scan.trailing);
|
|
252
|
+
if (scan.flowKey !== undefined)
|
|
253
|
+
lost(owner, toolListOutOfPlace(scan.flowKey));
|
|
254
|
+
const flowLines = region.lines.slice(0, scan.held).filter((l) => !isSkippable(l)).map(trimBlanks);
|
|
255
|
+
keep(key, start.at > i ? tail : (scan.quoted ?? (tail.startsWith("[") && flowLines.length > 1 ? flowLines.join(" ") : tail)));
|
|
256
|
+
i = start.at + scan.held;
|
|
257
|
+
}
|
|
258
|
+
if (valued.has(DISALLOWED_TOOLS_KEY) && listKeysSeen.has(DISALLOWED_TOOLS_ALIAS)) {
|
|
259
|
+
lists.delete(DISALLOWED_TOOLS_ALIAS);
|
|
260
|
+
const at = unread.findIndex((u) => "key" in u && u.key === DISALLOWED_TOOLS_ALIAS);
|
|
261
|
+
if (at >= 0)
|
|
262
|
+
unread.splice(at, 1);
|
|
263
|
+
if (aliasSwallows !== undefined)
|
|
264
|
+
unread.push({ key: DISALLOWED_TOOLS_ALIAS, why: aliasSwallows, list: false });
|
|
67
265
|
}
|
|
68
266
|
let body = lines.slice(end + 1).join("\n");
|
|
69
267
|
if (body.startsWith("\n"))
|
|
70
268
|
body = body.slice(1);
|
|
71
|
-
return { fields, body, hadFrontmatter: true };
|
|
269
|
+
return { fields, lists, body, hadFrontmatter: true, unclosed: false, unread };
|
|
270
|
+
}
|
|
271
|
+
function lineAt(lines, index) {
|
|
272
|
+
return lines[index] ?? "";
|
|
273
|
+
}
|
|
274
|
+
function valueStartOf(lines, keyIdx, end, value) {
|
|
275
|
+
if (!isSkippable(value))
|
|
276
|
+
return { at: keyIdx, first: value };
|
|
277
|
+
let j = keyIdx + 1;
|
|
278
|
+
while (j < end && isSkippable(lineAt(lines, j)))
|
|
279
|
+
j++;
|
|
280
|
+
const line = lineAt(lines, j);
|
|
281
|
+
return j < end && isBlank(line.charAt(0)) ? { at: j, first: trimLeadingBlanks(line) } : undefined;
|
|
282
|
+
}
|
|
283
|
+
function readToolList(lines, keyIdx, end, value) {
|
|
284
|
+
const start = valueStartOf(lines, keyIdx, end, value);
|
|
285
|
+
if (start === undefined || (start.at > keyIdx && start.first.startsWith("-")))
|
|
286
|
+
return readBlockSequence(lines, keyIdx + 1, end);
|
|
287
|
+
return readValue(lines, start.at, end, start.first);
|
|
288
|
+
}
|
|
289
|
+
function readValue(lines, valueIdx, end, first) {
|
|
290
|
+
const header = parseBlockScalarHeader(trimBlanks(first));
|
|
291
|
+
if (header !== undefined) {
|
|
292
|
+
const read = readBlockScalar(lines, valueIdx + 1, end, header);
|
|
293
|
+
const cut = new EntryCutter();
|
|
294
|
+
for (const line of read.value.split("\n")) {
|
|
295
|
+
for (const ch of line)
|
|
296
|
+
cut.push(ch);
|
|
297
|
+
cut.endScalar();
|
|
298
|
+
}
|
|
299
|
+
return { entries: cut.entries, ...(cut.problem !== undefined ? { problem: cut.problem } : {}), next: read.next };
|
|
300
|
+
}
|
|
301
|
+
const region = valueRegion(lines, valueIdx, end, first, 0);
|
|
302
|
+
const { held, mapping: _mapping, quoted: _quoted, flowKey: _flowKey, ...scan } = scanValue(region.lines.join("\n"), "value");
|
|
303
|
+
void _mapping;
|
|
304
|
+
void _quoted;
|
|
305
|
+
void _flowKey;
|
|
306
|
+
return { ...scan, next: valueIdx + held };
|
|
307
|
+
}
|
|
308
|
+
function valueRegion(lines, from, end, first, floor, budget = Number.POSITIVE_INFINITY, flushLeftCloses = true) {
|
|
309
|
+
const taken = [first];
|
|
310
|
+
const flow = first.startsWith("[") || first.startsWith("{");
|
|
311
|
+
let size = first.length + 1;
|
|
312
|
+
let j = from + 1;
|
|
313
|
+
for (; j < end; j++) {
|
|
314
|
+
if (size >= budget)
|
|
315
|
+
return { lines: taken, next: j, capped: true };
|
|
316
|
+
const line = lineAt(lines, j);
|
|
317
|
+
const body = trimLeadingBlanks(line);
|
|
318
|
+
const closes = flow && (body.startsWith("]") || body.startsWith("}")) && (flushLeftCloses || body.length < line.length);
|
|
319
|
+
if (!isSkippable(line) && leadingBlanks(line) <= floor && !closes)
|
|
320
|
+
break;
|
|
321
|
+
taken.push(body);
|
|
322
|
+
size += body.length + 1;
|
|
323
|
+
}
|
|
324
|
+
return { lines: taken, next: j, capped: false };
|
|
325
|
+
}
|
|
326
|
+
function readBlockSequence(lines, start, end) {
|
|
327
|
+
const entries = [];
|
|
328
|
+
let indent;
|
|
329
|
+
let j = start;
|
|
330
|
+
while (j < end) {
|
|
331
|
+
const line = lineAt(lines, j);
|
|
332
|
+
if (isSkippable(line)) {
|
|
333
|
+
j++;
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const dashAt = leadingBlanks(line);
|
|
337
|
+
if (!isDashEntry(line.slice(dashAt)))
|
|
338
|
+
break;
|
|
339
|
+
const dashIndent = line.slice(0, dashAt);
|
|
340
|
+
if (indent !== undefined && dashIndent !== indent)
|
|
341
|
+
return { entries, next: j, problem: SEQUENCE_NOT_AN_ENTRY };
|
|
342
|
+
indent = dashIndent;
|
|
343
|
+
const item = valueRegion(lines, j, end, trimLeadingBlanks(line.slice(dashAt + 1)), dashAt);
|
|
344
|
+
const scan = scanValue(item.lines.join("\n"), "item");
|
|
345
|
+
if (scan.problem !== undefined)
|
|
346
|
+
return { entries, next: j + scan.held, problem: scan.problem, ...(scan.unterminated !== undefined ? { unterminated: scan.unterminated } : {}), ...(scan.trailing !== undefined ? { trailing: scan.trailing } : {}) };
|
|
347
|
+
for (const entry of scan.entries)
|
|
348
|
+
entries.push(entry);
|
|
349
|
+
j += scan.held;
|
|
350
|
+
}
|
|
351
|
+
return { entries, next: j, ...(indent === undefined ? { null: true } : {}) };
|
|
352
|
+
}
|
|
353
|
+
const YAML_NULL = /^(?:null|Null|NULL|~)$/;
|
|
354
|
+
const YAML_BOOL_OR_NUMBER = /^(?:true|True|TRUE|false|False|FALSE|[-+]?[0-9]+|0o[0-7]+|0x[0-9a-fA-F]+|[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)(?:[eE][-+]?[0-9]+)?|[-+]?\.(?:inf|Inf|INF)|\.(?:nan|NaN|NAN))$/;
|
|
355
|
+
class EntryCutter {
|
|
356
|
+
entries = [];
|
|
357
|
+
problem;
|
|
358
|
+
depth = 0;
|
|
359
|
+
closed = false;
|
|
360
|
+
current = "";
|
|
361
|
+
blanks = "";
|
|
362
|
+
escaping = false;
|
|
363
|
+
push(ch) {
|
|
364
|
+
const escaped = this.escaping;
|
|
365
|
+
this.escaping = ch === "\\" && !escaped;
|
|
366
|
+
if (this.depth === 0 && (ch === "," || ch === " ")) {
|
|
367
|
+
this.cut();
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
if (isBlank(ch)) {
|
|
371
|
+
if (this.current !== "")
|
|
372
|
+
this.blanks += ch;
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
if (this.closed)
|
|
376
|
+
this.fail(PARENS_NOT_ONE_ZONE);
|
|
377
|
+
if (ch === "(" && !escaped)
|
|
378
|
+
this.depth++;
|
|
379
|
+
else if (ch === ")" && !escaped) {
|
|
380
|
+
if (this.depth === 0)
|
|
381
|
+
this.fail(PARENS_NOT_ONE_ZONE);
|
|
382
|
+
else
|
|
383
|
+
this.closed = --this.depth === 0;
|
|
384
|
+
}
|
|
385
|
+
this.current += this.blanks + ch;
|
|
386
|
+
this.blanks = "";
|
|
387
|
+
}
|
|
388
|
+
fold(breaks) {
|
|
389
|
+
this.blanks = "";
|
|
390
|
+
if (breaks === 1)
|
|
391
|
+
this.push(" ");
|
|
392
|
+
else
|
|
393
|
+
for (let n = 1; n < breaks; n++)
|
|
394
|
+
this.push("\n");
|
|
395
|
+
}
|
|
396
|
+
endScalar() {
|
|
397
|
+
if (this.depth > 0)
|
|
398
|
+
this.fail(PARENS_NOT_ONE_ZONE);
|
|
399
|
+
this.depth = 0;
|
|
400
|
+
this.escaping = false;
|
|
401
|
+
this.cut();
|
|
402
|
+
}
|
|
403
|
+
fail(why) {
|
|
404
|
+
this.problem ??= why;
|
|
405
|
+
}
|
|
406
|
+
cut() {
|
|
407
|
+
const entry = this.current;
|
|
408
|
+
this.current = "";
|
|
409
|
+
this.blanks = "";
|
|
410
|
+
this.closed = false;
|
|
411
|
+
if (entry !== "")
|
|
412
|
+
this.entries.push(entry);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
function scanValue(text, seat) {
|
|
416
|
+
const cut = new EntryCutter();
|
|
417
|
+
let state = "start";
|
|
418
|
+
const opened = [];
|
|
419
|
+
const closes = (ch) => opened.length > 0 && ch === (opened[opened.length - 1] === "{" ? "}" : "]");
|
|
420
|
+
let held = text.split("\n").length;
|
|
421
|
+
let mapping = false;
|
|
422
|
+
let inComment = false;
|
|
423
|
+
let crossedLine = false;
|
|
424
|
+
let plain = "";
|
|
425
|
+
let breaks = 0;
|
|
426
|
+
let itemFrom = 0;
|
|
427
|
+
let isNull = false;
|
|
428
|
+
let unterminated;
|
|
429
|
+
let quoted;
|
|
430
|
+
let trailing;
|
|
431
|
+
let flowKey;
|
|
432
|
+
let quotedItem;
|
|
433
|
+
const endPlain = () => {
|
|
434
|
+
const written = trimBlanks(plain);
|
|
435
|
+
plain = "";
|
|
436
|
+
breaks = 0;
|
|
437
|
+
if (opened.length > 0 || seat === "item") {
|
|
438
|
+
if (YAML_NULL.test(written) || YAML_BOOL_OR_NUMBER.test(written))
|
|
439
|
+
cut.fail(SEQUENCE_NOT_A_NAME);
|
|
440
|
+
}
|
|
441
|
+
else if (YAML_NULL.test(written))
|
|
442
|
+
isNull = true;
|
|
443
|
+
else if (YAML_BOOL_OR_NUMBER.test(written))
|
|
444
|
+
cut.fail(VALUE_NOT_A_STRING);
|
|
445
|
+
cut.endScalar();
|
|
446
|
+
};
|
|
447
|
+
const mappingMarkAt = (at) => {
|
|
448
|
+
const next = text.charAt(at + 1);
|
|
449
|
+
return next === "" || next === "\n" || isBlank(next) || (opened.length > 0 && (next === "," || next === "]" || next === "}"));
|
|
450
|
+
};
|
|
451
|
+
const ended = (item) => {
|
|
452
|
+
quotedItem = undefined;
|
|
453
|
+
if (item && opened.length > 0 && cut.entries.length === itemFrom)
|
|
454
|
+
cut.fail(SEQUENCE_NOT_A_NAME);
|
|
455
|
+
state = opened.length > 0 ? "after" : "done";
|
|
456
|
+
crossedLine = false;
|
|
457
|
+
};
|
|
458
|
+
for (let k = 0; k < text.length; k++) {
|
|
459
|
+
const ch = text.charAt(k);
|
|
460
|
+
if (inComment && ch !== "\n")
|
|
461
|
+
continue;
|
|
462
|
+
inComment = false;
|
|
463
|
+
const comment = ch === "#" && (k === 0 || isBlank(text.charAt(k - 1)) || text.charAt(k - 1) === "\n");
|
|
464
|
+
if (state !== "plain") {
|
|
465
|
+
if (isBlank(ch))
|
|
466
|
+
continue;
|
|
467
|
+
if (ch === "\n" || comment) {
|
|
468
|
+
crossedLine ||= ch === "\n";
|
|
469
|
+
inComment = comment;
|
|
470
|
+
continue;
|
|
471
|
+
}
|
|
472
|
+
if (state === "done") {
|
|
473
|
+
if (crossedLine) {
|
|
474
|
+
held = linesBefore(text, k);
|
|
475
|
+
break;
|
|
476
|
+
}
|
|
477
|
+
cut.fail(TEXT_AFTER_END);
|
|
478
|
+
quoted = undefined;
|
|
479
|
+
trailing ??= text.slice(k, lineEndOf(text, k));
|
|
480
|
+
continue;
|
|
481
|
+
}
|
|
482
|
+
if (opened.length > 0 && (ch === "," || ch === "]" || ch === "}")) {
|
|
483
|
+
if (ch === ",")
|
|
484
|
+
state = "start";
|
|
485
|
+
else if (closes(ch)) {
|
|
486
|
+
opened.pop();
|
|
487
|
+
ended(false);
|
|
488
|
+
}
|
|
489
|
+
else
|
|
490
|
+
cut.fail(SEQUENCE_NOT_A_NAME);
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
if (state === "after" && ch === ":") {
|
|
494
|
+
cut.fail(VALUE_IS_A_MAPPING);
|
|
495
|
+
if (quotedItem !== undefined && TOOL_LIST_KEYS.has(quotedItem))
|
|
496
|
+
flowKey ??= quotedItem;
|
|
497
|
+
state = "start";
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (state === "after")
|
|
501
|
+
cut.fail(TEXT_AFTER_END);
|
|
502
|
+
const opens = state === "start";
|
|
503
|
+
itemFrom = cut.entries.length;
|
|
504
|
+
if (opens && (ch === '"' || ch === "'")) {
|
|
505
|
+
const close = closingQuote(text, k);
|
|
506
|
+
if (close < 0) {
|
|
507
|
+
cut.fail((unterminated = QUOTE_NOT_CLOSED));
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
const decoded = decodeQuoted(text.slice(k + 1, close), ch);
|
|
511
|
+
if (opened.length === 0)
|
|
512
|
+
quoted = decoded;
|
|
513
|
+
for (const c of decoded)
|
|
514
|
+
cut.push(c);
|
|
515
|
+
cut.endScalar();
|
|
516
|
+
ended(true);
|
|
517
|
+
if (opened.length > 0)
|
|
518
|
+
quotedItem = decoded;
|
|
519
|
+
k = close;
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (opens && (ch === "[" || ch === "{") && (opened.length > 0 || seat === "value")) {
|
|
523
|
+
if (opened.length > 0)
|
|
524
|
+
cut.fail(SEQUENCE_NOT_A_NAME);
|
|
525
|
+
else if (ch === "{")
|
|
526
|
+
cut.fail(VALUE_IS_A_MAPPING);
|
|
527
|
+
opened.push(ch);
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
state = "plain";
|
|
531
|
+
}
|
|
532
|
+
if (ch === "\n") {
|
|
533
|
+
breaks++;
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
if (breaks > 0 && opened.length === 0 && yamlKeyOf(trimLeadingBlanks(text.slice(k, lineEndOf(text, k)))) !== undefined) {
|
|
537
|
+
endPlain();
|
|
538
|
+
ended(true);
|
|
539
|
+
held = linesBefore(text, k);
|
|
540
|
+
break;
|
|
541
|
+
}
|
|
542
|
+
if (comment) {
|
|
543
|
+
endPlain();
|
|
544
|
+
ended(true);
|
|
545
|
+
inComment = true;
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
if (opened.length > 0 && (ch === "," || closes(ch))) {
|
|
549
|
+
endPlain();
|
|
550
|
+
ended(true);
|
|
551
|
+
if (ch === ",")
|
|
552
|
+
state = "start";
|
|
553
|
+
else {
|
|
554
|
+
opened.pop();
|
|
555
|
+
ended(false);
|
|
556
|
+
}
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
if (opened.length > 0 && (ch === "[" || ch === "{" || ch === "]" || ch === "}")) {
|
|
560
|
+
cut.fail(SEQUENCE_NOT_A_NAME);
|
|
561
|
+
if (ch === "[" || ch === "{")
|
|
562
|
+
opened.push(ch);
|
|
563
|
+
}
|
|
564
|
+
if (ch === ":" && mappingMarkAt(k)) {
|
|
565
|
+
cut.fail(VALUE_IS_A_MAPPING);
|
|
566
|
+
if (opened.length === 0)
|
|
567
|
+
mapping = true;
|
|
568
|
+
else {
|
|
569
|
+
const written = trimBlanks(plain);
|
|
570
|
+
if (TOOL_LIST_KEYS.has(written))
|
|
571
|
+
flowKey ??= written;
|
|
572
|
+
endPlain();
|
|
573
|
+
state = "start";
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (breaks > 0) {
|
|
578
|
+
cut.fold(breaks);
|
|
579
|
+
plain += breaks === 1 ? " " : "\n".repeat(breaks - 1);
|
|
580
|
+
breaks = 0;
|
|
581
|
+
}
|
|
582
|
+
cut.push(ch);
|
|
583
|
+
plain += ch;
|
|
584
|
+
}
|
|
585
|
+
if (opened.length > 0) {
|
|
586
|
+
const why = flowNotClosed(opened[0] ?? "[");
|
|
587
|
+
cut.fail(why);
|
|
588
|
+
unterminated ??= why;
|
|
589
|
+
}
|
|
590
|
+
if (state === "plain")
|
|
591
|
+
endPlain();
|
|
592
|
+
if (seat === "item" && cut.entries.length === 0)
|
|
593
|
+
cut.fail(SEQUENCE_NOT_A_NAME);
|
|
594
|
+
return {
|
|
595
|
+
entries: isNull ? [] : cut.entries,
|
|
596
|
+
...(cut.problem !== undefined ? { problem: cut.problem } : {}),
|
|
597
|
+
...(unterminated !== undefined ? { unterminated } : {}),
|
|
598
|
+
...(isNull ? { null: true } : {}),
|
|
599
|
+
held,
|
|
600
|
+
...(mapping ? { mapping: true } : {}),
|
|
601
|
+
...(quoted !== undefined ? { quoted } : {}),
|
|
602
|
+
...(trailing !== undefined ? { trailing } : {}),
|
|
603
|
+
...(flowKey !== undefined ? { flowKey } : {}),
|
|
604
|
+
};
|
|
605
|
+
}
|
|
606
|
+
function linesBefore(text, at) {
|
|
607
|
+
let n = 0;
|
|
608
|
+
for (let k = text.indexOf("\n"); k >= 0 && k < at; k = text.indexOf("\n", k + 1))
|
|
609
|
+
n++;
|
|
610
|
+
return n;
|
|
611
|
+
}
|
|
612
|
+
function lineEndOf(text, at) {
|
|
613
|
+
const k = text.indexOf("\n", at);
|
|
614
|
+
return k < 0 ? text.length : k;
|
|
615
|
+
}
|
|
616
|
+
function closingQuote(text, open) {
|
|
617
|
+
const quote = text.charAt(open);
|
|
618
|
+
for (let k = open + 1; k < text.length; k++) {
|
|
619
|
+
const ch = text.charAt(k);
|
|
620
|
+
if (quote === '"' && ch === "\\")
|
|
621
|
+
k++;
|
|
622
|
+
else if (ch === quote) {
|
|
623
|
+
if (quote === "'" && text.charAt(k + 1) === "'")
|
|
624
|
+
k++;
|
|
625
|
+
else
|
|
626
|
+
return k;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return -1;
|
|
630
|
+
}
|
|
631
|
+
const DOUBLE_QUOTE_ESCAPES = new Map(Object.entries({ 0: 0, a: 7, b: 8, t: 9, "\t": 9, n: 10, v: 11, f: 12, r: 13, e: 0x1b, " ": 32, '"': 34, "/": 47, "\\": 92, N: 0x85, _: 0xa0, L: 0x2028, P: 0x2029 }).map(([letter, code]) => [letter, String.fromCharCode(code)]));
|
|
632
|
+
function decodeQuoted(inner, quote) {
|
|
633
|
+
let out = "";
|
|
634
|
+
let blanks = "";
|
|
635
|
+
let breaks = 0;
|
|
636
|
+
let joined = false;
|
|
637
|
+
const fold = () => (breaks === 0 ? blanks : joined ? "\n".repeat(breaks) : breaks === 1 ? " " : "\n".repeat(breaks - 1));
|
|
638
|
+
for (let k = 0; k < inner.length; k++) {
|
|
639
|
+
const ch = inner.charAt(k);
|
|
640
|
+
if (ch === "\n") {
|
|
641
|
+
blanks = "";
|
|
642
|
+
breaks++;
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
if (isBlank(ch)) {
|
|
646
|
+
if (breaks === 0 && !joined)
|
|
647
|
+
blanks += ch;
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
out += fold();
|
|
651
|
+
blanks = "";
|
|
652
|
+
breaks = 0;
|
|
653
|
+
joined = false;
|
|
654
|
+
if (quote === "'" || ch !== "\\") {
|
|
655
|
+
out += ch;
|
|
656
|
+
if (quote === "'" && ch === "'")
|
|
657
|
+
k++;
|
|
658
|
+
continue;
|
|
659
|
+
}
|
|
660
|
+
const escape = /^(?:x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8}|[\s\S])/.exec(inner.slice(k + 1, k + 10))?.[0] ?? "";
|
|
661
|
+
const code = escape.length > 1 ? Number.parseInt(escape.slice(1), 16) : -1;
|
|
662
|
+
if (code > 0x10ffff || (code >= 0xd800 && code <= 0xdfff)) {
|
|
663
|
+
out += `\\${escape.charAt(0)}`;
|
|
664
|
+
k += 1;
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
k += escape.length;
|
|
668
|
+
joined = escape === "\n";
|
|
669
|
+
if (joined)
|
|
670
|
+
continue;
|
|
671
|
+
out += code >= 0 ? String.fromCodePoint(code) : (DOUBLE_QUOTE_ESCAPES.get(escape) ?? `\\${escape}`);
|
|
672
|
+
}
|
|
673
|
+
return out + fold();
|
|
72
674
|
}
|
|
73
675
|
function parseBlockScalarHeader(value) {
|
|
74
|
-
const m = /^([|>])([0-9+-]*)$/.exec(value);
|
|
676
|
+
const m = /^([|>])([0-9+-]*)([\s\S]*)$/.exec(value);
|
|
75
677
|
if (!m)
|
|
76
678
|
return undefined;
|
|
77
|
-
const rest = m
|
|
679
|
+
const [, style = "", rest = "", comment = ""] = m;
|
|
680
|
+
if (comment !== "" && !(isBlank(comment.charAt(0)) && trimLeadingBlanks(comment).startsWith("#")))
|
|
681
|
+
return undefined;
|
|
78
682
|
if (!/^(?:[1-9]?[+-]?|[+-][1-9]?)$/.test(rest))
|
|
79
683
|
return undefined;
|
|
80
684
|
const digit = /[1-9]/.exec(rest)?.[0];
|
|
81
|
-
return { style:
|
|
685
|
+
return { style: style === "|" ? "literal" : "folded", ...(digit !== undefined ? { indent: Number(digit) } : {}) };
|
|
82
686
|
}
|
|
83
687
|
function readBlockScalar(lines, start, end, header) {
|
|
84
|
-
const indentOf =
|
|
688
|
+
const indentOf = leadingBlanks;
|
|
85
689
|
let indent = header.indent;
|
|
86
690
|
if (indent === undefined) {
|
|
87
691
|
for (let j = start; j < end; j++) {
|
|
88
|
-
if (lines
|
|
692
|
+
if (trimBlanks(lineAt(lines, j)) === "")
|
|
89
693
|
continue;
|
|
90
|
-
indent = indentOf(lines
|
|
694
|
+
indent = indentOf(lineAt(lines, j));
|
|
91
695
|
break;
|
|
92
696
|
}
|
|
93
697
|
}
|
|
@@ -96,8 +700,8 @@ function readBlockScalar(lines, start, end, header) {
|
|
|
96
700
|
const taken = [];
|
|
97
701
|
let j = start;
|
|
98
702
|
for (; j < end; j++) {
|
|
99
|
-
const line = lines
|
|
100
|
-
if (line
|
|
703
|
+
const line = lineAt(lines, j);
|
|
704
|
+
if (trimBlanks(line) === "") {
|
|
101
705
|
taken.push("");
|
|
102
706
|
continue;
|
|
103
707
|
}
|
|
@@ -137,37 +741,6 @@ function readBlockScalar(lines, start, end, header) {
|
|
|
137
741
|
}
|
|
138
742
|
return { value: folded, next: j };
|
|
139
743
|
}
|
|
140
|
-
function isFlowSequenceClosed(text) {
|
|
141
|
-
let depth = 0;
|
|
142
|
-
for (const ch of text) {
|
|
143
|
-
if (ch === "[")
|
|
144
|
-
depth++;
|
|
145
|
-
else if (ch === "]")
|
|
146
|
-
depth--;
|
|
147
|
-
}
|
|
148
|
-
return depth <= 0;
|
|
149
|
-
}
|
|
150
|
-
function readFlowSequenceContinuation(lines, start, end, head) {
|
|
151
|
-
let acc = head;
|
|
152
|
-
let j = start;
|
|
153
|
-
for (; j < end; j++) {
|
|
154
|
-
acc += ` ${lines[j].trim()}`;
|
|
155
|
-
if (isFlowSequenceClosed(acc)) {
|
|
156
|
-
j++;
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return { value: acc, next: j };
|
|
161
|
-
}
|
|
162
|
-
function unquote(value) {
|
|
163
|
-
if (value.length < 2)
|
|
164
|
-
return value;
|
|
165
|
-
const q = value[0];
|
|
166
|
-
if ((q !== '"' && q !== "'") || value[value.length - 1] !== q)
|
|
167
|
-
return value;
|
|
168
|
-
const inner = value.slice(1, -1);
|
|
169
|
-
return q === '"' ? inner.replace(/\\t/g, "\t").replace(/\\n/g, "\n") : inner;
|
|
170
|
-
}
|
|
171
744
|
function listRelativeFiles(base, dir, prefix, out, walk) {
|
|
172
745
|
let entries;
|
|
173
746
|
try {
|
|
@@ -280,39 +853,6 @@ function isDecodableText(bytes) {
|
|
|
280
853
|
function errText(err) {
|
|
281
854
|
return thrownText(err);
|
|
282
855
|
}
|
|
283
|
-
function splitToolNames(declared) {
|
|
284
|
-
let text = declared.trim();
|
|
285
|
-
if (text.startsWith("[") && text.endsWith("]"))
|
|
286
|
-
text = text.slice(1, -1);
|
|
287
|
-
const names = [];
|
|
288
|
-
let current = "";
|
|
289
|
-
let depth = 0;
|
|
290
|
-
const flush = () => {
|
|
291
|
-
const name = unquote(current.trim());
|
|
292
|
-
if (name !== "")
|
|
293
|
-
names.push(name);
|
|
294
|
-
current = "";
|
|
295
|
-
};
|
|
296
|
-
for (const ch of text) {
|
|
297
|
-
if (ch === "(") {
|
|
298
|
-
depth++;
|
|
299
|
-
current += ch;
|
|
300
|
-
}
|
|
301
|
-
else if (ch === ")") {
|
|
302
|
-
if (depth > 0)
|
|
303
|
-
depth--;
|
|
304
|
-
current += ch;
|
|
305
|
-
}
|
|
306
|
-
else if (depth === 0 && (ch === "," || /\s/.test(ch))) {
|
|
307
|
-
flush();
|
|
308
|
-
}
|
|
309
|
-
else {
|
|
310
|
-
current += ch;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
flush();
|
|
314
|
-
return names;
|
|
315
|
-
}
|
|
316
856
|
const RETIRED_SKILLS_DIRECTORY_OPTION_KEYS = Object.freeze({
|
|
317
857
|
deployedTools: "the loader copies a skill's `allowed-tools` / `disallowed-tools` into `SkillSpec.allowedTools` / `disallowedTools` as written and the run's grant table judges them (an entry naming a tool nothing mounts simply never matches) — drop the option",
|
|
318
858
|
});
|
|
@@ -376,7 +916,18 @@ export function createSkillsFromDirectory(dir, options = {}) {
|
|
|
376
916
|
}
|
|
377
917
|
const parsed = parseSkillFile(text);
|
|
378
918
|
if (!parsed.hadFrontmatter) {
|
|
379
|
-
|
|
919
|
+
const detail = parsed.unclosed ? `${SKILL_FILE} ${UNCLOSED_FRONTMATTER_REASON} — skipped` : `${SKILL_FILE} has no fenced --- frontmatter block — skipped`;
|
|
920
|
+
warn({ code: "no_frontmatter", skill: name, detail });
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
if (parsed.unread.length > 0) {
|
|
924
|
+
const lists = parsed.unread.some((u) => "list" in u && u.list);
|
|
925
|
+
const said = parsed.unread.map((u) => ("line" in u ? `${SKILL_FILE} line ${u.line} is no key line (${u.why})` : `\`${u.key}\` has a value the reader cannot read${u.list ? " as a list" : ""} (${u.why})`));
|
|
926
|
+
warn({
|
|
927
|
+
code: "no_frontmatter",
|
|
928
|
+
skill: name,
|
|
929
|
+
detail: `${said.join("; ")}${lists ? " — write each list as one value (`a b`, `a, b`, `[a, b]`), a block scalar, or `- name` lines under the key" : ""} — skipped${lists ? ", not installed with a missing or shorter list" : ""}`,
|
|
930
|
+
});
|
|
380
931
|
continue;
|
|
381
932
|
}
|
|
382
933
|
const declaredName = parsed.fields.get("name");
|
|
@@ -405,8 +956,8 @@ export function createSkillsFromDirectory(dir, options = {}) {
|
|
|
405
956
|
warn({ code: "description_too_long", skill: name, detail: `\`description\` is ${description.length} chars, over the ${DESCRIPTION_MAX_CHARS} cap — skipped` });
|
|
406
957
|
continue;
|
|
407
958
|
}
|
|
408
|
-
const allowedTools =
|
|
409
|
-
const disallowedTools =
|
|
959
|
+
const allowedTools = parsed.lists.get(ALLOWED_TOOLS_KEY) ?? [];
|
|
960
|
+
const disallowedTools = parsed.lists.get(DISALLOWED_TOOLS_KEY) ?? parsed.lists.get(DISALLOWED_TOOLS_ALIAS) ?? [];
|
|
410
961
|
const baseDir = skillPhysicalRoot(skillDir, name, warn);
|
|
411
962
|
const files = baseDir === undefined ? [] : readAttachments(skillDir, baseDir, name, budget, warn);
|
|
412
963
|
skills.push({
|