@code-yeongyu/senpi 2026.6.14 → 2026.6.16
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 +92 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +5 -0
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/index.js +3 -1
- package/dist/core/extensions/builtin/bash-timeout/index.js.map +1 -1
- package/dist/core/extensions/builtin/bash-timeout/timeout.js +2 -2
- package/dist/core/extensions/builtin/bash-timeout/timeout.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +24 -12
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/goal/command.d.ts +14 -0
- package/dist/core/extensions/builtin/goal/command.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/command.js +16 -0
- package/dist/core/extensions/builtin/goal/command.js.map +1 -0
- package/dist/core/extensions/builtin/goal/continuation.d.ts +4 -0
- package/dist/core/extensions/builtin/goal/continuation.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/continuation.js +7 -0
- package/dist/core/extensions/builtin/goal/continuation.js.map +1 -0
- package/dist/core/extensions/builtin/goal/errors.d.ts +13 -0
- package/dist/core/extensions/builtin/goal/errors.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/errors.js +25 -0
- package/dist/core/extensions/builtin/goal/errors.js.map +1 -0
- package/dist/core/extensions/builtin/goal/format.d.ts +8 -0
- package/dist/core/extensions/builtin/goal/format.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/format.js +71 -0
- package/dist/core/extensions/builtin/goal/format.js.map +1 -0
- package/dist/core/extensions/builtin/goal/index.d.ts +3 -0
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/index.js +322 -0
- package/dist/core/extensions/builtin/goal/index.js.map +1 -0
- package/dist/core/extensions/builtin/goal/prompt.d.ts +3 -0
- package/dist/core/extensions/builtin/goal/prompt.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/prompt.js +34 -0
- package/dist/core/extensions/builtin/goal/prompt.js.map +1 -0
- package/dist/core/extensions/builtin/goal/store.d.ts +9 -0
- package/dist/core/extensions/builtin/goal/store.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/store.js +173 -0
- package/dist/core/extensions/builtin/goal/store.js.map +1 -0
- package/dist/core/extensions/builtin/goal/types.d.ts +50 -0
- package/dist/core/extensions/builtin/goal/types.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/types.js +6 -0
- package/dist/core/extensions/builtin/goal/types.js.map +1 -0
- package/dist/core/extensions/builtin/goal/ui.d.ts +6 -0
- package/dist/core/extensions/builtin/goal/ui.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/ui.js +20 -0
- package/dist/core/extensions/builtin/goal/ui.js.map +1 -0
- package/dist/core/extensions/builtin/goal/validation.d.ts +3 -0
- package/dist/core/extensions/builtin/goal/validation.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/validation.js +13 -0
- package/dist/core/extensions/builtin/goal/validation.js.map +1 -0
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +10 -2
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/nested-agents-md/core/containment.d.ts +10 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/containment.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/containment.js +23 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/containment.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/errors.d.ts +5 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/errors.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/errors.js +9 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/errors.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.d.ts +7 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.js +44 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/find-agents-md-up.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/format.d.ts +7 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/format.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/format.js +7 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/format.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.d.ts +11 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.js +77 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/inject-directory-context.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.d.ts +11 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.js +33 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/injection-cache.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/session-key.d.ts +8 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/session-key.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/session-key.js +8 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/session-key.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/truncate.d.ts +8 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/truncate.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/truncate.js +26 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/truncate.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/types.d.ts +25 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/types.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/types.js +4 -0
- package/dist/core/extensions/builtin/nested-agents-md/core/types.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/index.d.ts +3 -0
- package/dist/core/extensions/builtin/nested-agents-md/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/index.js +102 -0
- package/dist/core/extensions/builtin/nested-agents-md/index.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.d.ts +32 -0
- package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.d.ts.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.js +66 -0
- package/dist/core/extensions/builtin/nested-agents-md/ui/reporter.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.js +2 -2
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/rules/commands.d.ts +4 -0
- package/dist/core/extensions/builtin/rules/commands.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/commands.js +87 -0
- package/dist/core/extensions/builtin/rules/commands.js.map +1 -0
- package/dist/core/extensions/builtin/rules/index.d.ts +3 -0
- package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/index.js +127 -0
- package/dist/core/extensions/builtin/rules/index.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/cache.d.ts +10 -0
- package/dist/core/extensions/builtin/rules/rules/cache.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/cache.js +51 -0
- package/dist/core/extensions/builtin/rules/rules/cache.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/constants.d.ts +57 -0
- package/dist/core/extensions/builtin/rules/rules/constants.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/constants.js +96 -0
- package/dist/core/extensions/builtin/rules/rules/constants.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/engine.d.ts +67 -0
- package/dist/core/extensions/builtin/rules/rules/engine.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/engine.js +443 -0
- package/dist/core/extensions/builtin/rules/rules/engine.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/errors.d.ts +7 -0
- package/dist/core/extensions/builtin/rules/rules/errors.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/errors.js +13 -0
- package/dist/core/extensions/builtin/rules/rules/errors.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/finder.d.ts +27 -0
- package/dist/core/extensions/builtin/rules/rules/finder.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/finder.js +241 -0
- package/dist/core/extensions/builtin/rules/rules/finder.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/formatter.d.ts +8 -0
- package/dist/core/extensions/builtin/rules/rules/formatter.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/formatter.js +44 -0
- package/dist/core/extensions/builtin/rules/rules/formatter.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/matcher.d.ts +25 -0
- package/dist/core/extensions/builtin/rules/rules/matcher.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/matcher.js +107 -0
- package/dist/core/extensions/builtin/rules/rules/matcher.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/ordering.d.ts +4 -0
- package/dist/core/extensions/builtin/rules/rules/ordering.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/ordering.js +28 -0
- package/dist/core/extensions/builtin/rules/rules/ordering.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/parser.d.ts +4 -0
- package/dist/core/extensions/builtin/rules/rules/parser.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/parser.js +290 -0
- package/dist/core/extensions/builtin/rules/rules/parser.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/project-root.d.ts +2 -0
- package/dist/core/extensions/builtin/rules/rules/project-root.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/project-root.js +24 -0
- package/dist/core/extensions/builtin/rules/rules/project-root.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/scanner.d.ts +14 -0
- package/dist/core/extensions/builtin/rules/rules/scanner.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/scanner.js +96 -0
- package/dist/core/extensions/builtin/rules/rules/scanner.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/tool-paths.d.ts +4 -0
- package/dist/core/extensions/builtin/rules/rules/tool-paths.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/tool-paths.js +37 -0
- package/dist/core/extensions/builtin/rules/rules/tool-paths.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/truncator.d.ts +18 -0
- package/dist/core/extensions/builtin/rules/rules/truncator.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/truncator.js +46 -0
- package/dist/core/extensions/builtin/rules/rules/truncator.js.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/types.d.ts +124 -0
- package/dist/core/extensions/builtin/rules/rules/types.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/rules/types.js +9 -0
- package/dist/core/extensions/builtin/rules/rules/types.js.map +1 -0
- package/dist/core/extensions/builtin/rules/ui/dynamic-border.d.ts +8 -0
- package/dist/core/extensions/builtin/rules/ui/dynamic-border.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/ui/dynamic-border.js +10 -0
- package/dist/core/extensions/builtin/rules/ui/dynamic-border.js.map +1 -0
- package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts +22 -0
- package/dist/core/extensions/builtin/rules/ui/rules-banner.d.ts.map +1 -0
- package/dist/core/extensions/builtin/rules/ui/rules-banner.js +51 -0
- package/dist/core/extensions/builtin/rules/ui/rules-banner.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/index.d.ts +10 -0
- package/dist/core/extensions/builtin/webfetch/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/index.js +53 -0
- package/dist/core/extensions/builtin/webfetch/index.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.d.ts +4 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.js +60 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/content.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/errors.d.ts +13 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/errors.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/errors.js +25 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/errors.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts +24 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js +148 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/renderers.d.ts +15 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/renderers.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/renderers.js +110 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/renderers.js.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts +28 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts.map +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +79 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/index.d.ts +3 -0
- package/dist/core/extensions/builtin/websearch/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/index.js +76 -0
- package/dist/core/extensions/builtin/websearch/index.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/config.d.ts +12 -0
- package/dist/core/extensions/builtin/websearch/websearch/config.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/config.js +245 -0
- package/dist/core/extensions/builtin/websearch/websearch/config.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts +19 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.js +65 -0
- package/dist/core/extensions/builtin/websearch/websearch/native.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.d.ts +5 -0
- package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.js +58 -0
- package/dist/core/extensions/builtin/websearch/websearch/provider-endpoints.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/providers.d.ts +4 -0
- package/dist/core/extensions/builtin/websearch/websearch/providers.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/providers.js +464 -0
- package/dist/core/extensions/builtin/websearch/websearch/providers.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts +26 -0
- package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js +66 -0
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts +9 -0
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/search.js +261 -0
- package/dist/core/extensions/builtin/websearch/websearch/search.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts +18 -0
- package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/tool.js +88 -0
- package/dist/core/extensions/builtin/websearch/websearch/tool.js.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +115 -0
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -0
- package/dist/core/extensions/builtin/websearch/websearch/types.js +2 -0
- package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +8 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +4 -0
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +8 -4
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts +14 -0
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js +65 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +0 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +0 -4
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +87 -12
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +6 -17
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/utils/child-process.d.ts +7 -4
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +23 -5
- package/dist/utils/child-process.js.map +1 -1
- package/docs/containerization.md +36 -36
- package/docs/extensions.md +4 -4
- package/docs/index.md +1 -1
- package/docs/security.md +13 -13
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/question.ts +39 -18
- package/examples/extensions/questionnaire.ts +49 -28
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +5 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +140 -47
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +169 -122
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js +4 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +18 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +20 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.js +41 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/tool-choice-fallback.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +14 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/npm-shrinkwrap.json +45 -12
- package/package.json +8 -4
- package/dist/core/extensions/builtin/kimi-web-search/index.d.ts +0 -3
- package/dist/core/extensions/builtin/kimi-web-search/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/kimi-web-search/index.js +0 -208
- package/dist/core/extensions/builtin/kimi-web-search/index.js.map +0 -1
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { RuleFrontmatterParseError } from "./errors.js";
|
|
2
|
+
const FRONTMATTER_OPENING = "---\n";
|
|
3
|
+
const FRONTMATTER_OPENING_CRLF = "---\r\n";
|
|
4
|
+
/** Parse markdown rule content and extract the supported YAML frontmatter subset. */
|
|
5
|
+
export function parseRule(content) {
|
|
6
|
+
const normalizedContent = stripBom(content);
|
|
7
|
+
const openingLength = getOpeningDelimiterLength(normalizedContent);
|
|
8
|
+
if (openingLength === 0) {
|
|
9
|
+
return { frontmatter: {}, body: normalizedContent };
|
|
10
|
+
}
|
|
11
|
+
const closingDelimiter = findClosingDelimiter(normalizedContent, openingLength);
|
|
12
|
+
if (closingDelimiter === null) {
|
|
13
|
+
return {
|
|
14
|
+
frontmatter: {},
|
|
15
|
+
body: normalizedContent,
|
|
16
|
+
diagnostic: "Missing closing frontmatter delimiter",
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
const yamlContent = normalizedContent.slice(openingLength, closingDelimiter.start);
|
|
20
|
+
const body = normalizedContent.slice(closingDelimiter.bodyStart);
|
|
21
|
+
try {
|
|
22
|
+
return { frontmatter: parseYamlFrontmatter(yamlContent), body };
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
const message = error instanceof Error ? error.message : "Invalid YAML frontmatter";
|
|
26
|
+
return {
|
|
27
|
+
frontmatter: {},
|
|
28
|
+
body: normalizedContent,
|
|
29
|
+
diagnostic: `Malformed frontmatter: ${message}`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function stripBom(content) {
|
|
34
|
+
return content.startsWith("\uFEFF") ? content.slice(1) : content;
|
|
35
|
+
}
|
|
36
|
+
function getOpeningDelimiterLength(content) {
|
|
37
|
+
if (content.startsWith(FRONTMATTER_OPENING_CRLF))
|
|
38
|
+
return FRONTMATTER_OPENING_CRLF.length;
|
|
39
|
+
if (content.startsWith(FRONTMATTER_OPENING))
|
|
40
|
+
return FRONTMATTER_OPENING.length;
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
function findClosingDelimiter(content, openingLength) {
|
|
44
|
+
let lineStart = openingLength;
|
|
45
|
+
while (lineStart <= content.length) {
|
|
46
|
+
const nextNewline = content.indexOf("\n", lineStart);
|
|
47
|
+
const lineEnd = nextNewline === -1 ? content.length : nextNewline;
|
|
48
|
+
const line = content.slice(lineStart, lineEnd).replace(/\r$/, "");
|
|
49
|
+
if (line === "---") {
|
|
50
|
+
return {
|
|
51
|
+
start: lineStart,
|
|
52
|
+
bodyStart: nextNewline === -1 ? content.length : nextNewline + 1,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (nextNewline === -1)
|
|
56
|
+
break;
|
|
57
|
+
lineStart = nextNewline + 1;
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
function parseYamlFrontmatter(yamlContent) {
|
|
62
|
+
const lines = yamlContent.replace(/\r\n/g, "\n").split("\n");
|
|
63
|
+
const frontmatter = {};
|
|
64
|
+
const globValues = [];
|
|
65
|
+
let lineIndex = 0;
|
|
66
|
+
while (lineIndex < lines.length) {
|
|
67
|
+
const rawLine = lines[lineIndex];
|
|
68
|
+
if (rawLine === undefined)
|
|
69
|
+
break;
|
|
70
|
+
const line = stripComment(rawLine).trim();
|
|
71
|
+
if (line.length === 0) {
|
|
72
|
+
lineIndex += 1;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const colonIndex = line.indexOf(":");
|
|
76
|
+
if (colonIndex === -1) {
|
|
77
|
+
throw new RuleFrontmatterParseError(`Expected key-value pair on line ${lineIndex + 1}`);
|
|
78
|
+
}
|
|
79
|
+
const key = line.slice(0, colonIndex).trim();
|
|
80
|
+
const rawValue = line.slice(colonIndex + 1).trim();
|
|
81
|
+
if (key === "description") {
|
|
82
|
+
frontmatter.description = parseStringValue(rawValue);
|
|
83
|
+
lineIndex += 1;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (key === "alwaysApply") {
|
|
87
|
+
frontmatter.alwaysApply = parseBooleanValue(rawValue, lineIndex + 1);
|
|
88
|
+
lineIndex += 1;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (key === "globs" || key === "paths" || key === "applyTo") {
|
|
92
|
+
const parsed = parseGlobValue(rawValue, lines, lineIndex);
|
|
93
|
+
for (const glob of parsed.values) {
|
|
94
|
+
if (!globValues.includes(glob))
|
|
95
|
+
globValues.push(glob);
|
|
96
|
+
}
|
|
97
|
+
lineIndex += parsed.consumed;
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
lineIndex += 1;
|
|
101
|
+
}
|
|
102
|
+
if (globValues.length === 1) {
|
|
103
|
+
const singleGlob = globValues[0];
|
|
104
|
+
if (singleGlob !== undefined)
|
|
105
|
+
frontmatter.globs = singleGlob;
|
|
106
|
+
}
|
|
107
|
+
else if (globValues.length > 1) {
|
|
108
|
+
frontmatter.globs = globValues;
|
|
109
|
+
}
|
|
110
|
+
return frontmatter;
|
|
111
|
+
}
|
|
112
|
+
function parseBooleanValue(value, lineNumber) {
|
|
113
|
+
if (value === "true")
|
|
114
|
+
return true;
|
|
115
|
+
if (value === "false")
|
|
116
|
+
return false;
|
|
117
|
+
throw new RuleFrontmatterParseError(`Expected boolean on line ${lineNumber}`);
|
|
118
|
+
}
|
|
119
|
+
function parseGlobValue(rawValue, lines, lineIndex) {
|
|
120
|
+
if (rawValue.startsWith("[")) {
|
|
121
|
+
return { values: parseInlineArray(rawValue), consumed: 1 };
|
|
122
|
+
}
|
|
123
|
+
if (rawValue.length === 0) {
|
|
124
|
+
return parseMultilineArray(lines, lineIndex);
|
|
125
|
+
}
|
|
126
|
+
const value = parseStringValue(rawValue);
|
|
127
|
+
if (value.includes(",")) {
|
|
128
|
+
return {
|
|
129
|
+
values: value
|
|
130
|
+
.split(",")
|
|
131
|
+
.map((item) => item.trim())
|
|
132
|
+
.filter(Boolean),
|
|
133
|
+
consumed: 1,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return { values: [value], consumed: 1 };
|
|
137
|
+
}
|
|
138
|
+
function parseMultilineArray(lines, lineIndex) {
|
|
139
|
+
const values = [];
|
|
140
|
+
let consumed = 1;
|
|
141
|
+
for (let index = lineIndex + 1; index < lines.length; index += 1) {
|
|
142
|
+
const rawLine = lines[index];
|
|
143
|
+
if (rawLine === undefined)
|
|
144
|
+
break;
|
|
145
|
+
const lineWithoutComment = stripComment(rawLine);
|
|
146
|
+
if (lineWithoutComment.trim().length === 0) {
|
|
147
|
+
consumed += 1;
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const arrayItem = lineWithoutComment.match(/^\s+-\s*(.*)$/);
|
|
151
|
+
if (arrayItem === null)
|
|
152
|
+
break;
|
|
153
|
+
values.push(parseStringValue(arrayItem[1] ?? ""));
|
|
154
|
+
consumed += 1;
|
|
155
|
+
}
|
|
156
|
+
return { values: values.filter(Boolean), consumed };
|
|
157
|
+
}
|
|
158
|
+
function parseInlineArray(value) {
|
|
159
|
+
const closingBracketIndex = findClosingBracket(value);
|
|
160
|
+
if (closingBracketIndex === -1) {
|
|
161
|
+
throw new RuleFrontmatterParseError("Unclosed inline array");
|
|
162
|
+
}
|
|
163
|
+
const trailing = value.slice(closingBracketIndex + 1).trim();
|
|
164
|
+
if (trailing.length > 0) {
|
|
165
|
+
throw new RuleFrontmatterParseError("Unexpected content after inline array");
|
|
166
|
+
}
|
|
167
|
+
const content = value.slice(1, closingBracketIndex).trim();
|
|
168
|
+
if (content.length === 0)
|
|
169
|
+
return [];
|
|
170
|
+
return splitCommaSeparated(content).map(parseStringValue).filter(Boolean);
|
|
171
|
+
}
|
|
172
|
+
function findClosingBracket(value) {
|
|
173
|
+
let quote = null;
|
|
174
|
+
let escaped = false;
|
|
175
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
176
|
+
const character = value[index];
|
|
177
|
+
if (character === undefined)
|
|
178
|
+
continue;
|
|
179
|
+
if (escaped) {
|
|
180
|
+
escaped = false;
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (quote !== null && character === "\\") {
|
|
184
|
+
escaped = true;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
if (character === '"' || character === "'") {
|
|
188
|
+
if (quote === null)
|
|
189
|
+
quote = character;
|
|
190
|
+
else if (quote === character)
|
|
191
|
+
quote = null;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (quote === null && character === "]")
|
|
195
|
+
return index;
|
|
196
|
+
}
|
|
197
|
+
return -1;
|
|
198
|
+
}
|
|
199
|
+
function splitCommaSeparated(value) {
|
|
200
|
+
const values = [];
|
|
201
|
+
let current = "";
|
|
202
|
+
let quote = null;
|
|
203
|
+
let escaped = false;
|
|
204
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
205
|
+
const character = value[index];
|
|
206
|
+
if (character === undefined)
|
|
207
|
+
continue;
|
|
208
|
+
if (escaped) {
|
|
209
|
+
current += character;
|
|
210
|
+
escaped = false;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
if (quote !== null && character === "\\") {
|
|
214
|
+
current += character;
|
|
215
|
+
escaped = true;
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
if (character === '"' || character === "'") {
|
|
219
|
+
if (quote === null)
|
|
220
|
+
quote = character;
|
|
221
|
+
else if (quote === character)
|
|
222
|
+
quote = null;
|
|
223
|
+
current += character;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (quote === null && character === ",") {
|
|
227
|
+
values.push(current.trim());
|
|
228
|
+
current = "";
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
current += character;
|
|
232
|
+
}
|
|
233
|
+
if (quote !== null) {
|
|
234
|
+
throw new RuleFrontmatterParseError("Unclosed quoted value");
|
|
235
|
+
}
|
|
236
|
+
values.push(current.trim());
|
|
237
|
+
return values.filter(Boolean);
|
|
238
|
+
}
|
|
239
|
+
function parseStringValue(value) {
|
|
240
|
+
if (value.length === 0)
|
|
241
|
+
return "";
|
|
242
|
+
if (value.startsWith('"'))
|
|
243
|
+
return parseJsonString(value);
|
|
244
|
+
if (value.startsWith("'") && value.endsWith("'"))
|
|
245
|
+
return value.slice(1, -1);
|
|
246
|
+
if (value.startsWith("'"))
|
|
247
|
+
throw new RuleFrontmatterParseError("Unclosed quoted value");
|
|
248
|
+
return value;
|
|
249
|
+
}
|
|
250
|
+
function parseJsonString(value) {
|
|
251
|
+
let parsedValue;
|
|
252
|
+
try {
|
|
253
|
+
parsedValue = JSON.parse(value);
|
|
254
|
+
}
|
|
255
|
+
catch {
|
|
256
|
+
throw new RuleFrontmatterParseError("Invalid JSON-quoted string");
|
|
257
|
+
}
|
|
258
|
+
if (typeof parsedValue !== "string") {
|
|
259
|
+
throw new RuleFrontmatterParseError("Expected JSON-quoted string");
|
|
260
|
+
}
|
|
261
|
+
return parsedValue;
|
|
262
|
+
}
|
|
263
|
+
function stripComment(line) {
|
|
264
|
+
let quote = null;
|
|
265
|
+
let escaped = false;
|
|
266
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
267
|
+
const character = line[index];
|
|
268
|
+
if (character === undefined)
|
|
269
|
+
continue;
|
|
270
|
+
if (escaped) {
|
|
271
|
+
escaped = false;
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (quote !== null && character === "\\") {
|
|
275
|
+
escaped = true;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (character === '"' || character === "'") {
|
|
279
|
+
if (quote === null)
|
|
280
|
+
quote = character;
|
|
281
|
+
else if (quote === character)
|
|
282
|
+
quote = null;
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
if (quote === null && character === "#")
|
|
286
|
+
return line.slice(0, index);
|
|
287
|
+
}
|
|
288
|
+
return line;
|
|
289
|
+
}
|
|
290
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/parser.ts"],"names":[],"mappings":"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","sourcesContent":["import { RuleFrontmatterParseError } from \"./errors.ts\";\nimport type { ParsedRule, RuleFrontmatter } from \"./types.ts\";\n\nconst FRONTMATTER_OPENING = \"---\\n\";\nconst FRONTMATTER_OPENING_CRLF = \"---\\r\\n\";\n\n/** Parse markdown rule content and extract the supported YAML frontmatter subset. */\nexport function parseRule(content: string): ParsedRule {\n\tconst normalizedContent = stripBom(content);\n\tconst openingLength = getOpeningDelimiterLength(normalizedContent);\n\tif (openingLength === 0) {\n\t\treturn { frontmatter: {}, body: normalizedContent };\n\t}\n\n\tconst closingDelimiter = findClosingDelimiter(normalizedContent, openingLength);\n\tif (closingDelimiter === null) {\n\t\treturn {\n\t\t\tfrontmatter: {},\n\t\t\tbody: normalizedContent,\n\t\t\tdiagnostic: \"Missing closing frontmatter delimiter\",\n\t\t};\n\t}\n\n\tconst yamlContent = normalizedContent.slice(openingLength, closingDelimiter.start);\n\tconst body = normalizedContent.slice(closingDelimiter.bodyStart);\n\n\ttry {\n\t\treturn { frontmatter: parseYamlFrontmatter(yamlContent), body };\n\t} catch (error) {\n\t\tconst message = error instanceof Error ? error.message : \"Invalid YAML frontmatter\";\n\t\treturn {\n\t\t\tfrontmatter: {},\n\t\t\tbody: normalizedContent,\n\t\t\tdiagnostic: `Malformed frontmatter: ${message}`,\n\t\t};\n\t}\n}\n\nfunction stripBom(content: string): string {\n\treturn content.startsWith(\"\\uFEFF\") ? content.slice(1) : content;\n}\n\nfunction getOpeningDelimiterLength(content: string): number {\n\tif (content.startsWith(FRONTMATTER_OPENING_CRLF)) return FRONTMATTER_OPENING_CRLF.length;\n\tif (content.startsWith(FRONTMATTER_OPENING)) return FRONTMATTER_OPENING.length;\n\treturn 0;\n}\n\nfunction findClosingDelimiter(content: string, openingLength: number): { start: number; bodyStart: number } | null {\n\tlet lineStart = openingLength;\n\n\twhile (lineStart <= content.length) {\n\t\tconst nextNewline = content.indexOf(\"\\n\", lineStart);\n\t\tconst lineEnd = nextNewline === -1 ? content.length : nextNewline;\n\t\tconst line = content.slice(lineStart, lineEnd).replace(/\\r$/, \"\");\n\n\t\tif (line === \"---\") {\n\t\t\treturn {\n\t\t\t\tstart: lineStart,\n\t\t\t\tbodyStart: nextNewline === -1 ? content.length : nextNewline + 1,\n\t\t\t};\n\t\t}\n\n\t\tif (nextNewline === -1) break;\n\t\tlineStart = nextNewline + 1;\n\t}\n\n\treturn null;\n}\n\nfunction parseYamlFrontmatter(yamlContent: string): RuleFrontmatter {\n\tconst lines = yamlContent.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\tconst frontmatter: RuleFrontmatter = {};\n\tconst globValues: string[] = [];\n\tlet lineIndex = 0;\n\n\twhile (lineIndex < lines.length) {\n\t\tconst rawLine = lines[lineIndex];\n\t\tif (rawLine === undefined) break;\n\n\t\tconst line = stripComment(rawLine).trim();\n\t\tif (line.length === 0) {\n\t\t\tlineIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst colonIndex = line.indexOf(\":\");\n\t\tif (colonIndex === -1) {\n\t\t\tthrow new RuleFrontmatterParseError(`Expected key-value pair on line ${lineIndex + 1}`);\n\t\t}\n\n\t\tconst key = line.slice(0, colonIndex).trim();\n\t\tconst rawValue = line.slice(colonIndex + 1).trim();\n\n\t\tif (key === \"description\") {\n\t\t\tfrontmatter.description = parseStringValue(rawValue);\n\t\t\tlineIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (key === \"alwaysApply\") {\n\t\t\tfrontmatter.alwaysApply = parseBooleanValue(rawValue, lineIndex + 1);\n\t\t\tlineIndex += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (key === \"globs\" || key === \"paths\" || key === \"applyTo\") {\n\t\t\tconst parsed = parseGlobValue(rawValue, lines, lineIndex);\n\t\t\tfor (const glob of parsed.values) {\n\t\t\t\tif (!globValues.includes(glob)) globValues.push(glob);\n\t\t\t}\n\t\t\tlineIndex += parsed.consumed;\n\t\t\tcontinue;\n\t\t}\n\n\t\tlineIndex += 1;\n\t}\n\n\tif (globValues.length === 1) {\n\t\tconst singleGlob = globValues[0];\n\t\tif (singleGlob !== undefined) frontmatter.globs = singleGlob;\n\t} else if (globValues.length > 1) {\n\t\tfrontmatter.globs = globValues;\n\t}\n\n\treturn frontmatter;\n}\n\nfunction parseBooleanValue(value: string, lineNumber: number): boolean {\n\tif (value === \"true\") return true;\n\tif (value === \"false\") return false;\n\tthrow new RuleFrontmatterParseError(`Expected boolean on line ${lineNumber}`);\n}\n\nfunction parseGlobValue(rawValue: string, lines: string[], lineIndex: number): { values: string[]; consumed: number } {\n\tif (rawValue.startsWith(\"[\")) {\n\t\treturn { values: parseInlineArray(rawValue), consumed: 1 };\n\t}\n\n\tif (rawValue.length === 0) {\n\t\treturn parseMultilineArray(lines, lineIndex);\n\t}\n\n\tconst value = parseStringValue(rawValue);\n\tif (value.includes(\",\")) {\n\t\treturn {\n\t\t\tvalues: value\n\t\t\t\t.split(\",\")\n\t\t\t\t.map((item) => item.trim())\n\t\t\t\t.filter(Boolean),\n\t\t\tconsumed: 1,\n\t\t};\n\t}\n\n\treturn { values: [value], consumed: 1 };\n}\n\nfunction parseMultilineArray(lines: string[], lineIndex: number): { values: string[]; consumed: number } {\n\tconst values: string[] = [];\n\tlet consumed = 1;\n\n\tfor (let index = lineIndex + 1; index < lines.length; index += 1) {\n\t\tconst rawLine = lines[index];\n\t\tif (rawLine === undefined) break;\n\n\t\tconst lineWithoutComment = stripComment(rawLine);\n\t\tif (lineWithoutComment.trim().length === 0) {\n\t\t\tconsumed += 1;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst arrayItem = lineWithoutComment.match(/^\\s+-\\s*(.*)$/);\n\t\tif (arrayItem === null) break;\n\n\t\tvalues.push(parseStringValue(arrayItem[1] ?? \"\"));\n\t\tconsumed += 1;\n\t}\n\n\treturn { values: values.filter(Boolean), consumed };\n}\n\nfunction parseInlineArray(value: string): string[] {\n\tconst closingBracketIndex = findClosingBracket(value);\n\tif (closingBracketIndex === -1) {\n\t\tthrow new RuleFrontmatterParseError(\"Unclosed inline array\");\n\t}\n\n\tconst trailing = value.slice(closingBracketIndex + 1).trim();\n\tif (trailing.length > 0) {\n\t\tthrow new RuleFrontmatterParseError(\"Unexpected content after inline array\");\n\t}\n\n\tconst content = value.slice(1, closingBracketIndex).trim();\n\tif (content.length === 0) return [];\n\n\treturn splitCommaSeparated(content).map(parseStringValue).filter(Boolean);\n}\n\nfunction findClosingBracket(value: string): number {\n\tlet quote: string | null = null;\n\tlet escaped = false;\n\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst character = value[index];\n\t\tif (character === undefined) continue;\n\n\t\tif (escaped) {\n\t\t\tescaped = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote !== null && character === \"\\\\\") {\n\t\t\tescaped = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tif (quote === null) quote = character;\n\t\t\telse if (quote === character) quote = null;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === null && character === \"]\") return index;\n\t}\n\n\treturn -1;\n}\n\nfunction splitCommaSeparated(value: string): string[] {\n\tconst values: string[] = [];\n\tlet current = \"\";\n\tlet quote: string | null = null;\n\tlet escaped = false;\n\n\tfor (let index = 0; index < value.length; index += 1) {\n\t\tconst character = value[index];\n\t\tif (character === undefined) continue;\n\n\t\tif (escaped) {\n\t\t\tcurrent += character;\n\t\t\tescaped = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote !== null && character === \"\\\\\") {\n\t\t\tcurrent += character;\n\t\t\tescaped = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tif (quote === null) quote = character;\n\t\t\telse if (quote === character) quote = null;\n\t\t\tcurrent += character;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === null && character === \",\") {\n\t\t\tvalues.push(current.trim());\n\t\t\tcurrent = \"\";\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrent += character;\n\t}\n\n\tif (quote !== null) {\n\t\tthrow new RuleFrontmatterParseError(\"Unclosed quoted value\");\n\t}\n\n\tvalues.push(current.trim());\n\treturn values.filter(Boolean);\n}\n\nfunction parseStringValue(value: string): string {\n\tif (value.length === 0) return \"\";\n\tif (value.startsWith('\"')) return parseJsonString(value);\n\tif (value.startsWith(\"'\") && value.endsWith(\"'\")) return value.slice(1, -1);\n\tif (value.startsWith(\"'\")) throw new RuleFrontmatterParseError(\"Unclosed quoted value\");\n\treturn value;\n}\n\nfunction parseJsonString(value: string): string {\n\tlet parsedValue: unknown;\n\ttry {\n\t\tparsedValue = JSON.parse(value);\n\t} catch {\n\t\tthrow new RuleFrontmatterParseError(\"Invalid JSON-quoted string\");\n\t}\n\n\tif (typeof parsedValue !== \"string\") {\n\t\tthrow new RuleFrontmatterParseError(\"Expected JSON-quoted string\");\n\t}\n\n\treturn parsedValue;\n}\n\nfunction stripComment(line: string): string {\n\tlet quote: string | null = null;\n\tlet escaped = false;\n\n\tfor (let index = 0; index < line.length; index += 1) {\n\t\tconst character = line[index];\n\t\tif (character === undefined) continue;\n\n\t\tif (escaped) {\n\t\t\tescaped = false;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote !== null && character === \"\\\\\") {\n\t\t\tescaped = true;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tif (quote === null) quote = character;\n\t\t\telse if (quote === character) quote = null;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (quote === null && character === \"#\") return line.slice(0, index);\n\t}\n\n\treturn line;\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-root.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/project-root.ts"],"names":[],"mappings":"AAKA,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,aAAa,CAAC,MAAM,CAAmB,GAAG,MAAM,GAAG,IAAI,CAwBlH"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { existsSync, statSync } from "node:fs";
|
|
2
|
+
import { dirname, join, resolve } from "node:path";
|
|
3
|
+
import { PROJECT_MARKERS } from "./constants.js";
|
|
4
|
+
export function findProjectRoot(startPath, markers = PROJECT_MARKERS) {
|
|
5
|
+
const resolvedStartPath = resolve(startPath);
|
|
6
|
+
if (!existsSync(resolvedStartPath)) {
|
|
7
|
+
return null;
|
|
8
|
+
}
|
|
9
|
+
const startStats = statSync(resolvedStartPath);
|
|
10
|
+
let currentDirectory = startStats.isDirectory() ? resolvedStartPath : dirname(resolvedStartPath);
|
|
11
|
+
const filesystemRoot = resolve("/");
|
|
12
|
+
while (true) {
|
|
13
|
+
for (const marker of markers) {
|
|
14
|
+
if (existsSync(join(currentDirectory, marker))) {
|
|
15
|
+
return currentDirectory;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (currentDirectory === filesystemRoot) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
currentDirectory = dirname(currentDirectory);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=project-root.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-root.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/project-root.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,UAAU,eAAe,CAAC,SAAiB,EAAE,OAAO,GAA0B,eAAe;IAClG,MAAM,iBAAiB,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAE7C,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,UAAU,GAAG,QAAQ,CAAC,iBAAiB,CAAC,CAAC;IAC/C,IAAI,gBAAgB,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACjG,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpC,OAAO,IAAI,EAAE,CAAC;QACb,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC9B,IAAI,UAAU,CAAC,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;gBAChD,OAAO,gBAAgB,CAAC;YACzB,CAAC;QACF,CAAC;QAED,IAAI,gBAAgB,KAAK,cAAc,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QACb,CAAC;QAED,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9C,CAAC;AACF,CAAC","sourcesContent":["import { existsSync, statSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport { PROJECT_MARKERS } from \"./constants.ts\";\n\nexport function findProjectRoot(startPath: string, markers: ReadonlyArray<string> = PROJECT_MARKERS): string | null {\n\tconst resolvedStartPath = resolve(startPath);\n\n\tif (!existsSync(resolvedStartPath)) {\n\t\treturn null;\n\t}\n\n\tconst startStats = statSync(resolvedStartPath);\n\tlet currentDirectory = startStats.isDirectory() ? resolvedStartPath : dirname(resolvedStartPath);\n\tconst filesystemRoot = resolve(\"/\");\n\n\twhile (true) {\n\t\tfor (const marker of markers) {\n\t\t\tif (existsSync(join(currentDirectory, marker))) {\n\t\t\t\treturn currentDirectory;\n\t\t\t}\n\t\t}\n\n\t\tif (currentDirectory === filesystemRoot) {\n\t\t\treturn null;\n\t\t}\n\n\t\tcurrentDirectory = dirname(currentDirectory);\n\t}\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ScanOptions {
|
|
2
|
+
rootDir: string;
|
|
3
|
+
excludedDirs?: ReadonlyArray<string>;
|
|
4
|
+
/** Maximum recursion depth. Default: 10 */
|
|
5
|
+
maxDepth?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ScannedFile {
|
|
8
|
+
/** Absolute path as encountered (may be a symlink). */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Real (resolved) path; same as path if not a symlink. */
|
|
11
|
+
realPath: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function scanRuleFiles(options: ScanOptions): ScannedFile[];
|
|
14
|
+
//# sourceMappingURL=scanner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/scanner.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACrC,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC3B,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,GAAG,WAAW,EAAE,CAwBjE"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { existsSync, lstatSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
3
|
+
import { RULE_FILE_EXTENSIONS, SCANNER_EXCLUDED_DIRS } from "./constants.js";
|
|
4
|
+
export function scanRuleFiles(options) {
|
|
5
|
+
const rootPath = toAbsolutePath(options.rootDir);
|
|
6
|
+
if (!existsSync(rootPath)) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
let rootStats;
|
|
10
|
+
try {
|
|
11
|
+
rootStats = statSync(rootPath);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return [];
|
|
15
|
+
}
|
|
16
|
+
if (!rootStats.isDirectory()) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
19
|
+
const results = [];
|
|
20
|
+
const visitedDirectories = new Set();
|
|
21
|
+
const excludedDirs = new Set(options.excludedDirs ?? SCANNER_EXCLUDED_DIRS);
|
|
22
|
+
const maxDepth = options.maxDepth ?? 10;
|
|
23
|
+
scanDirectory(rootPath, 0, maxDepth, excludedDirs, visitedDirectories, results);
|
|
24
|
+
return results;
|
|
25
|
+
}
|
|
26
|
+
function toAbsolutePath(filePath) {
|
|
27
|
+
return isAbsolute(filePath) ? filePath : resolve(filePath);
|
|
28
|
+
}
|
|
29
|
+
function scanDirectory(directoryPath, depth, maxDepth, excludedDirs, visitedDirectories, results) {
|
|
30
|
+
let realDirectoryPath;
|
|
31
|
+
try {
|
|
32
|
+
realDirectoryPath = realpathSync.native(directoryPath);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (visitedDirectories.has(realDirectoryPath)) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
visitedDirectories.add(realDirectoryPath);
|
|
41
|
+
let entries;
|
|
42
|
+
try {
|
|
43
|
+
entries = readdirSync(directoryPath, { withFileTypes: true }).sort((leftEntry, rightEntry) => leftEntry.name.localeCompare(rightEntry.name));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
for (const entry of entries) {
|
|
49
|
+
const entryPath = join(directoryPath, entry.name);
|
|
50
|
+
if (entry.isDirectory()) {
|
|
51
|
+
if (!excludedDirs.has(entry.name) && depth < maxDepth) {
|
|
52
|
+
scanDirectory(entryPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);
|
|
53
|
+
}
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (entry.isSymbolicLink()) {
|
|
57
|
+
scanSymbolicLink(entryPath, entry.name, depth, maxDepth, excludedDirs, visitedDirectories, results);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (entry.isFile() && isRuleFile(entry.name)) {
|
|
61
|
+
results.push({ path: entryPath, realPath: resolveRealPath(entryPath) });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function scanSymbolicLink(linkPath, linkName, depth, maxDepth, excludedDirs, visitedDirectories, results) {
|
|
66
|
+
let targetStats;
|
|
67
|
+
try {
|
|
68
|
+
targetStats = statSync(linkPath);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
if (targetStats.isDirectory()) {
|
|
74
|
+
if (!excludedDirs.has(linkName) && depth < maxDepth) {
|
|
75
|
+
scanDirectory(linkPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (targetStats.isFile() && isRuleFile(linkName)) {
|
|
80
|
+
results.push({ path: linkPath, realPath: resolveRealPath(linkPath) });
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function isRuleFile(fileName) {
|
|
84
|
+
return RULE_FILE_EXTENSIONS.some((extension) => fileName.endsWith(extension));
|
|
85
|
+
}
|
|
86
|
+
function resolveRealPath(filePath) {
|
|
87
|
+
try {
|
|
88
|
+
const realPath = realpathSync.native(filePath);
|
|
89
|
+
const fileStats = lstatSync(filePath);
|
|
90
|
+
return fileStats.isSymbolicLink() ? realPath : filePath;
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return filePath;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=scanner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/scanner.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Dirent, existsSync, lstatSync, readdirSync, realpathSync, type Stats, statSync } from \"node:fs\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\nimport { RULE_FILE_EXTENSIONS, SCANNER_EXCLUDED_DIRS } from \"./constants.ts\";\n\nexport interface ScanOptions {\n\trootDir: string;\n\texcludedDirs?: ReadonlyArray<string>;\n\t/** Maximum recursion depth. Default: 10 */\n\tmaxDepth?: number;\n}\n\nexport interface ScannedFile {\n\t/** Absolute path as encountered (may be a symlink). */\n\tpath: string;\n\t/** Real (resolved) path; same as path if not a symlink. */\n\trealPath: string;\n}\n\nexport function scanRuleFiles(options: ScanOptions): ScannedFile[] {\n\tconst rootPath = toAbsolutePath(options.rootDir);\n\tif (!existsSync(rootPath)) {\n\t\treturn [];\n\t}\n\n\tlet rootStats: Stats;\n\ttry {\n\t\trootStats = statSync(rootPath);\n\t} catch {\n\t\treturn [];\n\t}\n\n\tif (!rootStats.isDirectory()) {\n\t\treturn [];\n\t}\n\n\tconst results: ScannedFile[] = [];\n\tconst visitedDirectories = new Set<string>();\n\tconst excludedDirs = new Set(options.excludedDirs ?? SCANNER_EXCLUDED_DIRS);\n\tconst maxDepth = options.maxDepth ?? 10;\n\n\tscanDirectory(rootPath, 0, maxDepth, excludedDirs, visitedDirectories, results);\n\treturn results;\n}\n\nfunction toAbsolutePath(filePath: string): string {\n\treturn isAbsolute(filePath) ? filePath : resolve(filePath);\n}\n\nfunction scanDirectory(\n\tdirectoryPath: string,\n\tdepth: number,\n\tmaxDepth: number,\n\texcludedDirs: ReadonlySet<string>,\n\tvisitedDirectories: Set<string>,\n\tresults: ScannedFile[],\n): void {\n\tlet realDirectoryPath: string;\n\ttry {\n\t\trealDirectoryPath = realpathSync.native(directoryPath);\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (visitedDirectories.has(realDirectoryPath)) {\n\t\treturn;\n\t}\n\tvisitedDirectories.add(realDirectoryPath);\n\n\tlet entries: Dirent[];\n\ttry {\n\t\tentries = readdirSync(directoryPath, { withFileTypes: true }).sort((leftEntry, rightEntry) =>\n\t\t\tleftEntry.name.localeCompare(rightEntry.name),\n\t\t);\n\t} catch {\n\t\treturn;\n\t}\n\n\tfor (const entry of entries) {\n\t\tconst entryPath = join(directoryPath, entry.name);\n\n\t\tif (entry.isDirectory()) {\n\t\t\tif (!excludedDirs.has(entry.name) && depth < maxDepth) {\n\t\t\t\tscanDirectory(entryPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.isSymbolicLink()) {\n\t\t\tscanSymbolicLink(entryPath, entry.name, depth, maxDepth, excludedDirs, visitedDirectories, results);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (entry.isFile() && isRuleFile(entry.name)) {\n\t\t\tresults.push({ path: entryPath, realPath: resolveRealPath(entryPath) });\n\t\t}\n\t}\n}\n\nfunction scanSymbolicLink(\n\tlinkPath: string,\n\tlinkName: string,\n\tdepth: number,\n\tmaxDepth: number,\n\texcludedDirs: ReadonlySet<string>,\n\tvisitedDirectories: Set<string>,\n\tresults: ScannedFile[],\n): void {\n\tlet targetStats: Stats;\n\ttry {\n\t\ttargetStats = statSync(linkPath);\n\t} catch {\n\t\treturn;\n\t}\n\n\tif (targetStats.isDirectory()) {\n\t\tif (!excludedDirs.has(linkName) && depth < maxDepth) {\n\t\t\tscanDirectory(linkPath, depth + 1, maxDepth, excludedDirs, visitedDirectories, results);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (targetStats.isFile() && isRuleFile(linkName)) {\n\t\tresults.push({ path: linkPath, realPath: resolveRealPath(linkPath) });\n\t}\n}\n\nfunction isRuleFile(fileName: string): boolean {\n\treturn RULE_FILE_EXTENSIONS.some((extension) => fileName.endsWith(extension));\n}\n\nfunction resolveRealPath(filePath: string): string {\n\ttry {\n\t\tconst realPath = realpathSync.native(filePath);\n\t\tconst fileStats = lstatSync(filePath);\n\t\treturn fileStats.isSymbolicLink() ? realPath : filePath;\n\t} catch {\n\t\treturn filePath;\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-paths.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/tool-paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAkB9E"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from "node:path";
|
|
2
|
+
import { TRACKED_BUILTIN_TOOL_SET } from "./constants.js";
|
|
3
|
+
export function isTrackedTool(toolName) {
|
|
4
|
+
return TRACKED_BUILTIN_TOOL_SET.has(toolName);
|
|
5
|
+
}
|
|
6
|
+
export function extractToolPaths(event, cwd) {
|
|
7
|
+
if (event.isError || !isTrackedTool(event.toolName)) {
|
|
8
|
+
return [];
|
|
9
|
+
}
|
|
10
|
+
const filePaths = new Set();
|
|
11
|
+
if (event.toolName === "read" || event.toolName === "edit") {
|
|
12
|
+
addPath(filePaths, getStringProperty(event.details, "filePath"), cwd);
|
|
13
|
+
addPath(filePaths, getStringProperty(event.input, "path"), cwd);
|
|
14
|
+
}
|
|
15
|
+
if (event.toolName === "write") {
|
|
16
|
+
addPath(filePaths, getStringProperty(event.input, "filePath"), cwd);
|
|
17
|
+
addPath(filePaths, getStringProperty(event.input, "path"), cwd);
|
|
18
|
+
}
|
|
19
|
+
return [...filePaths];
|
|
20
|
+
}
|
|
21
|
+
function addPath(filePaths, filePath, cwd) {
|
|
22
|
+
if (filePath === undefined || filePath.length === 0) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
filePaths.add(isAbsolute(filePath) ? filePath : resolve(cwd, filePath));
|
|
26
|
+
}
|
|
27
|
+
function getStringProperty(value, propertyName) {
|
|
28
|
+
if (!isRecord(value)) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const propertyValue = value[propertyName];
|
|
32
|
+
return typeof propertyValue === "string" ? propertyValue : undefined;
|
|
33
|
+
}
|
|
34
|
+
function isRecord(value) {
|
|
35
|
+
return typeof value === "object" && value !== null;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=tool-paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-paths.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/tool-paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIhD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC7C,OAAO,wBAAwB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAsB,EAAE,GAAW;IACnE,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,OAAO,EAAE,CAAC;IACX,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IAEpC,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC5D,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;QACtE,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAChC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,GAAG,CAAC,CAAC;QACpE,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IACjE,CAAC;IAED,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,OAAO,CAAC,SAAsB,EAAE,QAA4B,EAAE,GAAW;IACjF,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO;IACR,CAAC;IAED,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,SAAS,iBAAiB,CAAC,KAAc,EAAE,YAAoB;IAC9D,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,MAAM,aAAa,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;IAC1C,OAAO,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;AACtE,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACpD,CAAC","sourcesContent":["import { isAbsolute, resolve } from \"node:path\";\n\nimport type { ToolResultEvent } from \"../../../types.ts\";\n\nimport { TRACKED_BUILTIN_TOOL_SET } from \"./constants.ts\";\n\nexport function isTrackedTool(toolName: string): boolean {\n\treturn TRACKED_BUILTIN_TOOL_SET.has(toolName);\n}\n\nexport function extractToolPaths(event: ToolResultEvent, cwd: string): string[] {\n\tif (event.isError || !isTrackedTool(event.toolName)) {\n\t\treturn [];\n\t}\n\n\tconst filePaths = new Set<string>();\n\n\tif (event.toolName === \"read\" || event.toolName === \"edit\") {\n\t\taddPath(filePaths, getStringProperty(event.details, \"filePath\"), cwd);\n\t\taddPath(filePaths, getStringProperty(event.input, \"path\"), cwd);\n\t}\n\n\tif (event.toolName === \"write\") {\n\t\taddPath(filePaths, getStringProperty(event.input, \"filePath\"), cwd);\n\t\taddPath(filePaths, getStringProperty(event.input, \"path\"), cwd);\n\t}\n\n\treturn [...filePaths];\n}\n\nfunction addPath(filePaths: Set<string>, filePath: string | undefined, cwd: string): void {\n\tif (filePath === undefined || filePath.length === 0) {\n\t\treturn;\n\t}\n\n\tfilePaths.add(isAbsolute(filePath) ? filePath : resolve(cwd, filePath));\n}\n\nfunction getStringProperty(value: unknown, propertyName: string): string | undefined {\n\tif (!isRecord(value)) {\n\t\treturn undefined;\n\t}\n\n\tconst propertyValue = value[propertyName];\n\treturn typeof propertyValue === \"string\" ? propertyValue : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null;\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { TruncationResult } from "./types.ts";
|
|
2
|
+
type BudgetRule = {
|
|
3
|
+
body: string;
|
|
4
|
+
relativePath: string;
|
|
5
|
+
};
|
|
6
|
+
type BudgetResult = BudgetRule & {
|
|
7
|
+
truncated: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function truncateRule(body: string, options: {
|
|
10
|
+
maxChars: number;
|
|
11
|
+
relativePath: string;
|
|
12
|
+
}): TruncationResult;
|
|
13
|
+
export declare function truncateBudget(input: {
|
|
14
|
+
rules: ReadonlyArray<BudgetRule>;
|
|
15
|
+
maxResultChars: number;
|
|
16
|
+
}): BudgetResult[];
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=truncator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncator.d.ts","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/truncator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,KAAK,UAAU,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,YAAY,GAAG,UAAU,GAAG;IAChC,SAAS,EAAE,OAAO,CAAC;CACnB,CAAC;AAmBF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAYhH;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,EAAE,CAuBlH"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { TRUNCATION_NOTICE } from "./constants.js";
|
|
2
|
+
function truncationNotice(relativePath) {
|
|
3
|
+
return TRUNCATION_NOTICE.replace("{path}", relativePath);
|
|
4
|
+
}
|
|
5
|
+
function safeSliceEnd(body, end) {
|
|
6
|
+
if (end <= 0) {
|
|
7
|
+
return 0;
|
|
8
|
+
}
|
|
9
|
+
const lastCodeUnit = body.charCodeAt(end - 1);
|
|
10
|
+
if (lastCodeUnit >= 0xd800 && lastCodeUnit <= 0xdbff) {
|
|
11
|
+
return end - 1;
|
|
12
|
+
}
|
|
13
|
+
return end;
|
|
14
|
+
}
|
|
15
|
+
export function truncateRule(body, options) {
|
|
16
|
+
if (body.length <= options.maxChars) {
|
|
17
|
+
return { body, truncated: false, originalLength: body.length };
|
|
18
|
+
}
|
|
19
|
+
const notice = truncationNotice(options.relativePath);
|
|
20
|
+
if (options.maxChars < notice.length) {
|
|
21
|
+
return { body: notice, truncated: true, originalLength: body.length };
|
|
22
|
+
}
|
|
23
|
+
const sliceEnd = safeSliceEnd(body, options.maxChars - notice.length);
|
|
24
|
+
return { body: `${body.slice(0, sliceEnd)}${notice}`, truncated: true, originalLength: body.length };
|
|
25
|
+
}
|
|
26
|
+
export function truncateBudget(input) {
|
|
27
|
+
const results = [];
|
|
28
|
+
let remainingBudget = input.maxResultChars;
|
|
29
|
+
for (const rule of input.rules) {
|
|
30
|
+
if (remainingBudget >= rule.body.length) {
|
|
31
|
+
results.push({ body: rule.body, truncated: false, relativePath: rule.relativePath });
|
|
32
|
+
remainingBudget -= rule.body.length;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const notice = truncationNotice(rule.relativePath);
|
|
36
|
+
if (remainingBudget <= notice.length) {
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
const sliceEnd = safeSliceEnd(rule.body, remainingBudget - notice.length);
|
|
40
|
+
const body = `${rule.body.slice(0, sliceEnd)}${notice}`;
|
|
41
|
+
results.push({ body, truncated: true, relativePath: rule.relativePath });
|
|
42
|
+
remainingBudget -= body.length;
|
|
43
|
+
}
|
|
44
|
+
return results;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=truncator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncator.js","sourceRoot":"","sources":["../../../../../../src/core/extensions/builtin/rules/rules/truncator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAYnD,SAAS,gBAAgB,CAAC,YAAoB;IAC7C,OAAO,iBAAiB,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;AAC1D,CAAC;AAED,SAAS,YAAY,CAAC,IAAY,EAAE,GAAW;IAC9C,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;QACd,OAAO,CAAC,CAAC;IACV,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC9C,IAAI,YAAY,IAAI,MAAM,IAAI,YAAY,IAAI,MAAM,EAAE,CAAC;QACtD,OAAO,GAAG,GAAG,CAAC,CAAC;IAChB,CAAC;IAED,OAAO,GAAG,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAmD;IAC7F,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IAChE,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACtD,IAAI,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;IACvE,CAAC;IAED,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACtE,OAAO,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AACtG,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAmE;IACjG,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,IAAI,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC;IAE3C,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;YACrF,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YACpC,SAAS;QACV,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACnD,IAAI,eAAe,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACtC,MAAM;QACP,CAAC;QAED,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1E,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,MAAM,EAAE,CAAC;QACxD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;QACzE,eAAe,IAAI,IAAI,CAAC,MAAM,CAAC;IAChC,CAAC;IAED,OAAO,OAAO,CAAC;AAChB,CAAC","sourcesContent":["import { TRUNCATION_NOTICE } from \"./constants.ts\";\nimport type { TruncationResult } from \"./types.ts\";\n\ntype BudgetRule = {\n\tbody: string;\n\trelativePath: string;\n};\n\ntype BudgetResult = BudgetRule & {\n\ttruncated: boolean;\n};\n\nfunction truncationNotice(relativePath: string): string {\n\treturn TRUNCATION_NOTICE.replace(\"{path}\", relativePath);\n}\n\nfunction safeSliceEnd(body: string, end: number): number {\n\tif (end <= 0) {\n\t\treturn 0;\n\t}\n\n\tconst lastCodeUnit = body.charCodeAt(end - 1);\n\tif (lastCodeUnit >= 0xd800 && lastCodeUnit <= 0xdbff) {\n\t\treturn end - 1;\n\t}\n\n\treturn end;\n}\n\nexport function truncateRule(body: string, options: { maxChars: number; relativePath: string }): TruncationResult {\n\tif (body.length <= options.maxChars) {\n\t\treturn { body, truncated: false, originalLength: body.length };\n\t}\n\n\tconst notice = truncationNotice(options.relativePath);\n\tif (options.maxChars < notice.length) {\n\t\treturn { body: notice, truncated: true, originalLength: body.length };\n\t}\n\n\tconst sliceEnd = safeSliceEnd(body, options.maxChars - notice.length);\n\treturn { body: `${body.slice(0, sliceEnd)}${notice}`, truncated: true, originalLength: body.length };\n}\n\nexport function truncateBudget(input: { rules: ReadonlyArray<BudgetRule>; maxResultChars: number }): BudgetResult[] {\n\tconst results: BudgetResult[] = [];\n\tlet remainingBudget = input.maxResultChars;\n\n\tfor (const rule of input.rules) {\n\t\tif (remainingBudget >= rule.body.length) {\n\t\t\tresults.push({ body: rule.body, truncated: false, relativePath: rule.relativePath });\n\t\t\tremainingBudget -= rule.body.length;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst notice = truncationNotice(rule.relativePath);\n\t\tif (remainingBudget <= notice.length) {\n\t\t\tbreak;\n\t\t}\n\n\t\tconst sliceEnd = safeSliceEnd(rule.body, remainingBudget - notice.length);\n\t\tconst body = `${rule.body.slice(0, sliceEnd)}${notice}`;\n\t\tresults.push({ body, truncated: true, relativePath: rule.relativePath });\n\t\tremainingBudget -= body.length;\n\t}\n\n\treturn results;\n}\n"]}
|