salmon-loop 0.2.3
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/LICENSE +21 -0
- package/README.md +144 -0
- package/README.zh-CN.md +144 -0
- package/dist/cli/argv/headless-detection.js +60 -0
- package/dist/cli/argv/print-mode.js +60 -0
- package/dist/cli/authorization/allowlist.js +908 -0
- package/dist/cli/authorization/non-interactive.js +166 -0
- package/dist/cli/authorization/provider.js +416 -0
- package/dist/cli/chat-interface.js +83 -0
- package/dist/cli/chat.js +492 -0
- package/dist/cli/cli-runtime-context.js +12 -0
- package/dist/cli/commander-error-adapter.js +35 -0
- package/dist/cli/commander-error-meta.js +13 -0
- package/dist/cli/commands/allowlist.js +270 -0
- package/dist/cli/commands/chat.js +120 -0
- package/dist/cli/commands/config.js +250 -0
- package/dist/cli/commands/context.js +57 -0
- package/dist/cli/commands/dispatcher.js +53 -0
- package/dist/cli/commands/exit.js +9 -0
- package/dist/cli/commands/llm-output.js +135 -0
- package/dist/cli/commands/log-mode.js +143 -0
- package/dist/cli/commands/mode.js +136 -0
- package/dist/cli/commands/new.js +18 -0
- package/dist/cli/commands/parallel.js +256 -0
- package/dist/cli/commands/queue.js +130 -0
- package/dist/cli/commands/registry.js +85 -0
- package/dist/cli/commands/restore.js +26 -0
- package/dist/cli/commands/run/assistant-message.js +14 -0
- package/dist/cli/commands/run/config-resolution.js +37 -0
- package/dist/cli/commands/run/early-errors.js +108 -0
- package/dist/cli/commands/run/execute.js +73 -0
- package/dist/cli/commands/run/extensions-resolution.js +22 -0
- package/dist/cli/commands/run/handler.js +434 -0
- package/dist/cli/commands/run/headless-error-writer.js +182 -0
- package/dist/cli/commands/run/instruction-guard.js +24 -0
- package/dist/cli/commands/run/loop-params.js +46 -0
- package/dist/cli/commands/run/mode.js +8 -0
- package/dist/cli/commands/run/parse-options.js +67 -0
- package/dist/cli/commands/run/persist-session.js +35 -0
- package/dist/cli/commands/run/preflight.js +156 -0
- package/dist/cli/commands/run/reporter-factory.js +52 -0
- package/dist/cli/commands/run/runtime-llm.js +56 -0
- package/dist/cli/commands/run/runtime-options.js +30 -0
- package/dist/cli/commands/run/session.js +19 -0
- package/dist/cli/commands/run/structured-output.js +106 -0
- package/dist/cli/commands/run/types.js +2 -0
- package/dist/cli/commands/run/validate-options.js +28 -0
- package/dist/cli/commands/run/verbose.js +36 -0
- package/dist/cli/commands/run.js +2 -0
- package/dist/cli/commands/serve.js +323 -0
- package/dist/cli/commands/session.js +77 -0
- package/dist/cli/commands/snapshot-interactive.js +165 -0
- package/dist/cli/commands/snapshot.js +159 -0
- package/dist/cli/commands/status.js +17 -0
- package/dist/cli/commands/subagent.js +178 -0
- package/dist/cli/commands/subcommand-suggestions.js +63 -0
- package/dist/cli/commands/tool-names.js +155 -0
- package/dist/cli/commands/types.js +2 -0
- package/dist/cli/commands/utils.js +42 -0
- package/dist/cli/config.js +16 -0
- package/dist/cli/crash-reporter.js +5 -0
- package/dist/cli/headless/anthropic-stream-normalized-encoder.js +164 -0
- package/dist/cli/headless/anthropic-stream-protocol.js +62 -0
- package/dist/cli/headless/json-protocol.js +124 -0
- package/dist/cli/headless/native-stream-normalized-encoder.js +206 -0
- package/dist/cli/headless/openai-responses-canonical-applier.js +94 -0
- package/dist/cli/headless/openai-responses-state.js +294 -0
- package/dist/cli/headless/openai-stream-encoder.js +152 -0
- package/dist/cli/headless/stdout-writer.js +9 -0
- package/dist/cli/headless/stream-json-protocol.js +136 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/locales/en.js +409 -0
- package/dist/cli/locales/index.js +7 -0
- package/dist/cli/program-bootstrap.js +14 -0
- package/dist/cli/program-commands.js +106 -0
- package/dist/cli/program-options.js +15 -0
- package/dist/cli/program-output-mode.js +11 -0
- package/dist/cli/program-parse.js +24 -0
- package/dist/cli/reporters/anthropic-stream.js +77 -0
- package/dist/cli/reporters/base.js +2 -0
- package/dist/cli/reporters/json.js +69 -0
- package/dist/cli/reporters/openai-stream.js +72 -0
- package/dist/cli/reporters/standard.js +226 -0
- package/dist/cli/reporters/stderr-log-reporter.js +71 -0
- package/dist/cli/reporters/stream-json.js +111 -0
- package/dist/cli/run-cli.js +25 -0
- package/dist/cli/slash/runtime.js +240 -0
- package/dist/cli/ui/App.js +273 -0
- package/dist/cli/ui/authorization/bus.js +35 -0
- package/dist/cli/ui/components/CommandInput.js +200 -0
- package/dist/cli/ui/components/CommandSuggestionList.js +20 -0
- package/dist/cli/ui/components/Markdown.js +423 -0
- package/dist/cli/ui/components/MessageList.js +34 -0
- package/dist/cli/ui/components/StatusBannerLine.js +7 -0
- package/dist/cli/ui/components/TodoDrawer.js +60 -0
- package/dist/cli/ui/components/WelcomeMessage.js +14 -0
- package/dist/cli/ui/components/animations/StretchingThinking.js +51 -0
- package/dist/cli/ui/components/animations/ThinkingWave.js +15 -0
- package/dist/cli/ui/components/animations/TypeIndicator.js +30 -0
- package/dist/cli/ui/components/layout/SplitPane.js +11 -0
- package/dist/cli/ui/components/messageList/MessageItem.js +27 -0
- package/dist/cli/ui/components/messageList/QueuePreviewList.js +11 -0
- package/dist/cli/ui/components/messageList/items/EmphasisMessageItem.js +20 -0
- package/dist/cli/ui/components/messageList/items/InterruptMessageItem.js +10 -0
- package/dist/cli/ui/components/messageList/items/LightweightMessageItem.js +12 -0
- package/dist/cli/ui/components/messageList/items/StandardMessageItem.js +23 -0
- package/dist/cli/ui/components/messageList/items/WelcomeMessageItem.js +7 -0
- package/dist/cli/ui/components/messageList/messageListLayout.js +27 -0
- package/dist/cli/ui/components/messageList/streaming.js +51 -0
- package/dist/cli/ui/components/messageList/types.js +2 -0
- package/dist/cli/ui/components/messageList/utils.js +7 -0
- package/dist/cli/ui/components/sidebar/FileContext.js +8 -0
- package/dist/cli/ui/components/sidebar/MissionControl.js +8 -0
- package/dist/cli/ui/config.js +59 -0
- package/dist/cli/ui/hooks/useCommandLifecycle.js +110 -0
- package/dist/cli/ui/hooks/useCommandSuggestions.js +87 -0
- package/dist/cli/ui/hooks/useInputHistory.js +57 -0
- package/dist/cli/ui/hooks/useLoopEvents.js +382 -0
- package/dist/cli/ui/hooks/useLoopState.js +73 -0
- package/dist/cli/ui/hooks/useOnionExit.js +31 -0
- package/dist/cli/ui/hooks/useTerminalDimensions.js +34 -0
- package/dist/cli/ui/index.js +136 -0
- package/dist/cli/ui/selection/bus.js +35 -0
- package/dist/cli/ui/status/formatStatusBanner.js +8 -0
- package/dist/cli/ui/store/context.js +17 -0
- package/dist/cli/ui/store/reducer.js +264 -0
- package/dist/cli/ui/store/types.js +81 -0
- package/dist/cli/ui/styles/theme.js +295 -0
- package/dist/cli/ui/types.js +2 -0
- package/dist/cli/ui/utils/sanitizer.js +122 -0
- package/dist/cli/ui/utils/transcript.js +28 -0
- package/dist/cli/utils/asyncQueue.js +125 -0
- package/dist/cli/utils/audit-scope.js +10 -0
- package/dist/cli/utils/detectors/index.js +38 -0
- package/dist/cli/utils/llm-output.js +34 -0
- package/dist/cli/utils/outcome-reporter.js +17 -0
- package/dist/cli/utils/safe-fs.js +184 -0
- package/dist/cli/utils/verify-resolver.js +34 -0
- package/dist/cli/utils/worktree-prepare-resolver.js +18 -0
- package/dist/core/adapters/fs/atomic-file-writer.js +129 -0
- package/dist/core/adapters/fs/file-adapter.js +95 -0
- package/dist/core/adapters/fs/filesystem.js +31 -0
- package/dist/core/adapters/fs/index.js +5 -0
- package/dist/core/adapters/fs/node-fs.js +7 -0
- package/dist/core/adapters/fs/readonly-filesystem.js +23 -0
- package/dist/core/adapters/git/git-adapter.js +704 -0
- package/dist/core/adapters/git/git-runner.js +119 -0
- package/dist/core/adapters/git/lock-manager.js +314 -0
- package/dist/core/adapters/git/types.js +2 -0
- package/dist/core/adapters/path/index.js +2 -0
- package/dist/core/adapters/path/path-adapter.js +23 -0
- package/dist/core/ast/guard.js +116 -0
- package/dist/core/ast/index.js +4 -0
- package/dist/core/ast/parser.js +284 -0
- package/dist/core/ast/validator.js +46 -0
- package/dist/core/backends/salmon-loop/task-executor.js +68 -0
- package/dist/core/checkpoint-domain/manifest-store.js +379 -0
- package/dist/core/checkpoint-domain/service.js +84 -0
- package/dist/core/checkpoint-domain/types.js +2 -0
- package/dist/core/config/defaults.js +50 -0
- package/dist/core/config/errors.js +11 -0
- package/dist/core/config/file-format.js +108 -0
- package/dist/core/config/index.js +7 -0
- package/dist/core/config/limits.js +77 -0
- package/dist/core/config/load.js +34 -0
- package/dist/core/config/normalize.js +35 -0
- package/dist/core/config/paths.js +20 -0
- package/dist/core/config/redact.js +16 -0
- package/dist/core/config/resolve-env.js +43 -0
- package/dist/core/config/resolve-llm.js +130 -0
- package/dist/core/config/resolve.js +68 -0
- package/dist/core/config/resolvers/ast-validation.js +8 -0
- package/dist/core/config/resolvers/context.js +21 -0
- package/dist/core/config/resolvers/observability.js +45 -0
- package/dist/core/config/resolvers/output.js +8 -0
- package/dist/core/config/resolvers/permission-mode.js +6 -0
- package/dist/core/config/resolvers/security.js +14 -0
- package/dist/core/config/resolvers/server.js +36 -0
- package/dist/core/config/resolvers/tool-authorization.js +39 -0
- package/dist/core/config/resolvers/ui.js +26 -0
- package/dist/core/config/types/config-file.js +2 -0
- package/dist/core/config/types/primitives.js +9 -0
- package/dist/core/config/types/resolved.js +2 -0
- package/dist/core/config/types.js +4 -0
- package/dist/core/config/validate.js +852 -0
- package/dist/core/context/assembly/default-prompt-assembler.js +7 -0
- package/dist/core/context/assembly/prompt-assembler.js +2 -0
- package/dist/core/context/ast/import-extractor.js +28 -0
- package/dist/core/context/ast/module-resolver.js +61 -0
- package/dist/core/context/ast/source-outline.js +25 -0
- package/dist/core/context/audit-constants.js +23 -0
- package/dist/core/context/audit.js +54 -0
- package/dist/core/context/budget/dynamic-adjuster.js +149 -0
- package/dist/core/context/budget/example-integration.js +49 -0
- package/dist/core/context/budget/integration.js +93 -0
- package/dist/core/context/builder.js +289 -0
- package/dist/core/context/cache/errors.js +16 -0
- package/dist/core/context/cache/incremental-updater.js +131 -0
- package/dist/core/context/cache/index.js +25 -0
- package/dist/core/context/cache/path-resolver.js +127 -0
- package/dist/core/context/cache/prompt-caching.js +207 -0
- package/dist/core/context/cache/store-factory.js +63 -0
- package/dist/core/context/cache/store.js +193 -0
- package/dist/core/context/cache/types.js +15 -0
- package/dist/core/context/compression/js-like-comments.js +139 -0
- package/dist/core/context/compression/smart-compress.js +61 -0
- package/dist/core/context/compression/whitespace.js +26 -0
- package/dist/core/context/dependencies.js +102 -0
- package/dist/core/context/effectiveness/index.js +25 -0
- package/dist/core/context/effectiveness/tracker.js +253 -0
- package/dist/core/context/effectiveness/types.js +15 -0
- package/dist/core/context/formatters/index.js +7 -0
- package/dist/core/context/formatters/json-converter.js +662 -0
- package/dist/core/context/formatters/types.js +6 -0
- package/dist/core/context/formatters/xml-context.js +296 -0
- package/dist/core/context/gatherers/architecture-gatherer.js +75 -0
- package/dist/core/context/gatherers/artifact-gatherer.js +53 -0
- package/dist/core/context/gatherers/ast-gatherer.js +370 -0
- package/dist/core/context/gatherers/ghost-dependency-gatherer.js +46 -0
- package/dist/core/context/gatherers/git-diff-gatherer.js +91 -0
- package/dist/core/context/gatherers/git-history-gatherer.js +57 -0
- package/dist/core/context/gatherers/knowledge-gatherer.js +101 -0
- package/dist/core/context/gatherers/metadata-gatherer.js +59 -0
- package/dist/core/context/gatherers/primary-text-gatherer.js +36 -0
- package/dist/core/context/gatherers/ripgrep-gatherer.js +104 -0
- package/dist/core/context/hash.js +52 -0
- package/dist/core/context/index.js +3 -0
- package/dist/core/context/keywords.js +179 -0
- package/dist/core/context/policies/budget-policy.js +36 -0
- package/dist/core/context/policies/pack-until-full.js +419 -0
- package/dist/core/context/scoring/relevance.js +191 -0
- package/dist/core/context/service-deps.js +32 -0
- package/dist/core/context/service-helpers.js +32 -0
- package/dist/core/context/service.js +265 -0
- package/dist/core/context/steps/context-budget.js +157 -0
- package/dist/core/context/steps/context-gather.js +71 -0
- package/dist/core/context/steps/context-primary.js +19 -0
- package/dist/core/context/steps/context-promotion.js +78 -0
- package/dist/core/context/steps/context-targets.js +85 -0
- package/dist/core/context/steps/types.js +2 -0
- package/dist/core/context/summarization/index.js +27 -0
- package/dist/core/context/summarization/prompts.js +80 -0
- package/dist/core/context/summarization/summarizer.js +377 -0
- package/dist/core/context/summarization/types.js +29 -0
- package/dist/core/context/targeting/churn-policy.js +27 -0
- package/dist/core/context/targeting/target-resolver.js +491 -0
- package/dist/core/context/token/adaptive-budget.js +364 -0
- package/dist/core/context/token/cache.js +163 -0
- package/dist/core/context/token/counter.js +190 -0
- package/dist/core/context/token/encoding-registry.js +173 -0
- package/dist/core/context/token/index.js +31 -0
- package/dist/core/context/token/token-budget.js +213 -0
- package/dist/core/context/token/types.js +10 -0
- package/dist/core/context/truncation/index.js +23 -0
- package/dist/core/context/truncation/semantic-truncator.js +103 -0
- package/dist/core/context/truncation/strategies/error-stack.js +94 -0
- package/dist/core/context/truncation/strategies/generic.js +48 -0
- package/dist/core/context/truncation/strategies/git-diff.js +99 -0
- package/dist/core/context/truncation/strategies/index.js +10 -0
- package/dist/core/context/truncation/strategies/json.js +142 -0
- package/dist/core/context/truncation/strategies/log.js +131 -0
- package/dist/core/context/truncation/strategies/test-result.js +140 -0
- package/dist/core/context/truncation/type-detector.js +133 -0
- package/dist/core/context/truncation/types.js +16 -0
- package/dist/core/context/types.js +2 -0
- package/dist/core/extensions/index.js +118 -0
- package/dist/core/extensions/load.js +36 -0
- package/dist/core/extensions/merge.js +29 -0
- package/dist/core/extensions/paths.js +40 -0
- package/dist/core/extensions/redact.js +37 -0
- package/dist/core/extensions/schemas.js +70 -0
- package/dist/core/extensions/types.js +2 -0
- package/dist/core/facades/cli-authorization-allowlist.js +3 -0
- package/dist/core/facades/cli-authorization-non-interactive.js +3 -0
- package/dist/core/facades/cli-authorization-provider.js +2 -0
- package/dist/core/facades/cli-chat.js +11 -0
- package/dist/core/facades/cli-command-allowlist.js +3 -0
- package/dist/core/facades/cli-command-chat.js +8 -0
- package/dist/core/facades/cli-command-checkpoint.js +3 -0
- package/dist/core/facades/cli-command-config.js +10 -0
- package/dist/core/facades/cli-command-dispatcher.js +2 -0
- package/dist/core/facades/cli-command-parallel.js +8 -0
- package/dist/core/facades/cli-command-session.js +2 -0
- package/dist/core/facades/cli-command-tool-names.js +6 -0
- package/dist/core/facades/cli-context.js +8 -0
- package/dist/core/facades/cli-headless.js +3 -0
- package/dist/core/facades/cli-observability.js +3 -0
- package/dist/core/facades/cli-program-bootstrap.js +2 -0
- package/dist/core/facades/cli-reporters.js +5 -0
- package/dist/core/facades/cli-run-execute.js +3 -0
- package/dist/core/facades/cli-run-handler.js +7 -0
- package/dist/core/facades/cli-run-headless-error-writer.js +2 -0
- package/dist/core/facades/cli-run-loop-params.js +2 -0
- package/dist/core/facades/cli-run-persist-session.js +2 -0
- package/dist/core/facades/cli-run-runtime-llm.js +5 -0
- package/dist/core/facades/cli-serve.js +21 -0
- package/dist/core/facades/cli-slash-runtime.js +9 -0
- package/dist/core/facades/cli-subagent.js +2 -0
- package/dist/core/facades/cli-ui.js +5 -0
- package/dist/core/facades/cli-utils-llm-output.js +3 -0
- package/dist/core/facades/cli-utils-path.js +2 -0
- package/dist/core/facades/cli-utils-worktree.js +2 -0
- package/dist/core/failure/diagnostics.js +221 -0
- package/dist/core/feedback/index.js +28 -0
- package/dist/core/feedback/parsers.js +59 -0
- package/dist/core/feedback/patterns.js +26 -0
- package/dist/core/feedback/types.js +2 -0
- package/dist/core/grizzco/domain/grizzco-types.js +41 -0
- package/dist/core/grizzco/dsl/DecisionEngine.js +149 -0
- package/dist/core/grizzco/dsl/MicroTaskRunner.js +39 -0
- package/dist/core/grizzco/dsl/llm-strategy.js +80 -0
- package/dist/core/grizzco/dsl/strategies.js +69 -0
- package/dist/core/grizzco/dsl/types.js +2 -0
- package/dist/core/grizzco/engine/observability/event-adapter.js +41 -0
- package/dist/core/grizzco/engine/observability/index.js +3 -0
- package/dist/core/grizzco/engine/observability/loop-telemetry.js +51 -0
- package/dist/core/grizzco/engine/outcome/index.js +2 -0
- package/dist/core/grizzco/engine/outcome/loop-result-mapper.js +167 -0
- package/dist/core/grizzco/engine/pipeline/pipeline.js +335 -0
- package/dist/core/grizzco/engine/pipeline/types.js +2 -0
- package/dist/core/grizzco/engine/transaction/attempt-failure.js +242 -0
- package/dist/core/grizzco/engine/transaction/authorization-summary.js +44 -0
- package/dist/core/grizzco/engine/transaction/index.js +3 -0
- package/dist/core/grizzco/engine/transaction/report-mapper.js +50 -0
- package/dist/core/grizzco/engine/transaction/retry-policy.js +19 -0
- package/dist/core/grizzco/engine/transaction/runner-builder.js +45 -0
- package/dist/core/grizzco/engine/transaction/session.js +58 -0
- package/dist/core/grizzco/engine/transaction/transaction-runner.js +193 -0
- package/dist/core/grizzco/engine/transaction/types.js +2 -0
- package/dist/core/grizzco/execution/Executor.js +58 -0
- package/dist/core/grizzco/execution/RejectionManager.js +71 -0
- package/dist/core/grizzco/execution/WorkerFactory.js +31 -0
- package/dist/core/grizzco/flows/SalmonLoopFlow.js +102 -0
- package/dist/core/grizzco/runtime/apply-back-runtime.js +136 -0
- package/dist/core/grizzco/runtime/apply-back-utils.js +13 -0
- package/dist/core/grizzco/runtime/host/host-runner.js +99 -0
- package/dist/core/grizzco/runtime/host/index.js +2 -0
- package/dist/core/grizzco/runtime/host/types.js +2 -0
- package/dist/core/grizzco/services/CachedService.js +42 -0
- package/dist/core/grizzco/services/implementations/default/GitConfigService.js +38 -0
- package/dist/core/grizzco/services/implementations/mock/MockLockService.js +11 -0
- package/dist/core/grizzco/services/implementations/mock/MockUserQuotaService.js +11 -0
- package/dist/core/grizzco/services/registry.js +30 -0
- package/dist/core/grizzco/services/types.js +2 -0
- package/dist/core/grizzco/steps/answer.js +75 -0
- package/dist/core/grizzco/steps/apply-back.js +46 -0
- package/dist/core/grizzco/steps/apply.js +136 -0
- package/dist/core/grizzco/steps/ast-validate.js +37 -0
- package/dist/core/grizzco/steps/audit.js +311 -0
- package/dist/core/grizzco/steps/context.js +74 -0
- package/dist/core/grizzco/steps/display-answer.js +6 -0
- package/dist/core/grizzco/steps/display-report.js +158 -0
- package/dist/core/grizzco/steps/display-research.js +6 -0
- package/dist/core/grizzco/steps/displayReview.js +6 -0
- package/dist/core/grizzco/steps/explore.js +245 -0
- package/dist/core/grizzco/steps/extractIssues.js +27 -0
- package/dist/core/grizzco/steps/generateFixPlan.js +13 -0
- package/dist/core/grizzco/steps/generateReview.js +71 -0
- package/dist/core/grizzco/steps/patch.js +220 -0
- package/dist/core/grizzco/steps/plan.js +191 -0
- package/dist/core/grizzco/steps/preflight.js +93 -0
- package/dist/core/grizzco/steps/prepare-deps.js +49 -0
- package/dist/core/grizzco/steps/read-only-shrink.js +4 -0
- package/dist/core/grizzco/steps/research.js +188 -0
- package/dist/core/grizzco/steps/rollback.js +138 -0
- package/dist/core/grizzco/steps/shrink.js +64 -0
- package/dist/core/grizzco/steps/validate.js +40 -0
- package/dist/core/grizzco/steps/verify.js +136 -0
- package/dist/core/grizzco/validation/AstValidationService.js +133 -0
- package/dist/core/grizzco/validation/ContextValidator.js +17 -0
- package/dist/core/grizzco/validation/ast-validation-policy.js +11 -0
- package/dist/core/grizzco/workers/direct-write-worker.js +44 -0
- package/dist/core/grizzco/workers/git-apply-worker.js +75 -0
- package/dist/core/grizzco/workers/i-merge-worker.js +2 -0
- package/dist/core/grizzco/workers/mm-three-way-worker.js +117 -0
- package/dist/core/grizzco/workers/no-op-worker.js +18 -0
- package/dist/core/grizzco/workers/overwrite-binary-worker.js +29 -0
- package/dist/core/grizzco/workers/strata-sync-worker.js +69 -0
- package/dist/core/grizzco/workers/three-way-merge-worker.js +84 -0
- package/dist/core/grizzco/workers/three-way-staged-worker.js +93 -0
- package/dist/core/grizzco/workers/union-merge-worker.js +71 -0
- package/dist/core/history/input-history.js +55 -0
- package/dist/core/intent/chat-intent.js +250 -0
- package/dist/core/interaction/events/bus.js +52 -0
- package/dist/core/interaction/model/events.js +2 -0
- package/dist/core/interaction/model/index.js +3 -0
- package/dist/core/interaction/model/task-state.js +9 -0
- package/dist/core/interaction/model/transition-policy.js +50 -0
- package/dist/core/interaction/model/types.js +2 -0
- package/dist/core/interaction/orchestration/facade.js +190 -0
- package/dist/core/interaction/orchestration/index.js +2 -0
- package/dist/core/interaction/orchestration/store.js +32 -0
- package/dist/core/interaction/sync/task-sync-engine.js +57 -0
- package/dist/core/interaction/turn-stop-reason.js +27 -0
- package/dist/core/language-support/index.js +3 -0
- package/dist/core/language-support/orchestrator.js +37 -0
- package/dist/core/language-support/strategies/extension-candidate-strategy.js +27 -0
- package/dist/core/language-support/strategies/index.js +3 -0
- package/dist/core/language-support/strategies/language-query-strategy.js +26 -0
- package/dist/core/llm/ai-sdk/chat-executor.js +88 -0
- package/dist/core/llm/ai-sdk/langfuse-headers.js +28 -0
- package/dist/core/llm/ai-sdk/message-mapper.js +240 -0
- package/dist/core/llm/ai-sdk/observation-context.js +16 -0
- package/dist/core/llm/ai-sdk/provider-factory.js +29 -0
- package/dist/core/llm/ai-sdk/request-params.js +18 -0
- package/dist/core/llm/ai-sdk/request-runtime.js +168 -0
- package/dist/core/llm/ai-sdk/result-mapper.js +31 -0
- package/dist/core/llm/ai-sdk/retry-classifier.js +82 -0
- package/dist/core/llm/ai-sdk/retry-executor.js +38 -0
- package/dist/core/llm/ai-sdk.js +92 -0
- package/dist/core/llm/audit.js +2 -0
- package/dist/core/llm/base-url.js +18 -0
- package/dist/core/llm/contracts/repair.js +68 -0
- package/dist/core/llm/errors.js +172 -0
- package/dist/core/llm/factory.js +21 -0
- package/dist/core/llm/http/index.js +2 -0
- package/dist/core/llm/index.js +6 -0
- package/dist/core/llm/message-composition.js +25 -0
- package/dist/core/llm/openai.js +69 -0
- package/dist/core/llm/output-policy.js +192 -0
- package/dist/core/llm/phase-router.js +55 -0
- package/dist/core/llm/redact.js +37 -0
- package/dist/core/llm/registry.js +81 -0
- package/dist/core/llm/retry-utils.js +114 -0
- package/dist/core/llm/stream-utils.js +87 -0
- package/dist/core/llm/utils.js +82 -0
- package/dist/core/observability/audit-file.js +199 -0
- package/dist/core/observability/audit-trail.js +125 -0
- package/dist/core/observability/authorization-decisions.js +54 -0
- package/dist/core/observability/debug-artifacts.js +61 -0
- package/dist/core/observability/error-envelope.js +63 -0
- package/dist/core/observability/error-mapping.js +271 -0
- package/dist/core/observability/ignored-error.js +6 -0
- package/dist/core/observability/logger.js +457 -0
- package/dist/core/observability/loop-event-reporter.js +46 -0
- package/dist/core/observability/monitor.js +240 -0
- package/dist/core/observability/run-outcome-reporter.js +15 -0
- package/dist/core/observability/token-usage.js +36 -0
- package/dist/core/observability/ui-log-sanitize.js +35 -0
- package/dist/core/patch/aggregator.js +93 -0
- package/dist/core/patch/diff.js +298 -0
- package/dist/core/permission-gate/default-gate.js +115 -0
- package/dist/core/permission-gate/gate.js +2 -0
- package/dist/core/permission-gate/types.js +2 -0
- package/dist/core/plan/index.js +2 -0
- package/dist/core/plan/manager.js +123 -0
- package/dist/core/plan/markdown-editor.js +238 -0
- package/dist/core/plan/storage.js +75 -0
- package/dist/core/plan/types.js +2 -0
- package/dist/core/plugin/interface.js +2 -0
- package/dist/core/plugin/loader.js +130 -0
- package/dist/core/plugin/registry.js +90 -0
- package/dist/core/plugin/validator.js +98 -0
- package/dist/core/prompts/registry.js +189 -0
- package/dist/core/prompts/runtime.js +69 -0
- package/dist/core/prompts/schema.js +2 -0
- package/dist/core/prompts/templates/phases/explore_user.hbs +26 -0
- package/dist/core/prompts/templates/phases/patch_user.hbs +57 -0
- package/dist/core/prompts/templates/phases/plan_user.hbs +33 -0
- package/dist/core/prompts/templates/system/_context_json_legend.hbs +21 -0
- package/dist/core/prompts/templates/system/_tool_defs.hbs +60 -0
- package/dist/core/prompts/templates/system/explore_system.hbs +26 -0
- package/dist/core/prompts/templates/system/main_system.hbs +18 -0
- package/dist/core/prompts/templates/system/patch_system.hbs +10 -0
- package/dist/core/prompts/templates/system/plan_system.hbs +1 -0
- package/dist/core/prompts/templates/system/reflection.hbs +39 -0
- package/dist/core/protocols/a2a/agent-card.js +30 -0
- package/dist/core/protocols/a2a/mapper.js +14 -0
- package/dist/core/protocols/a2a/sdk/auth-middleware.js +31 -0
- package/dist/core/protocols/a2a/sdk/executor.js +301 -0
- package/dist/core/protocols/a2a/sdk/server.js +24 -0
- package/dist/core/protocols/a2a/task-projection.js +45 -0
- package/dist/core/protocols/acp/acp-command-runner.js +204 -0
- package/dist/core/protocols/acp/acp-filesystem.js +43 -0
- package/dist/core/protocols/acp/checkpoint-meta.js +2 -0
- package/dist/core/protocols/acp/formal-agent.js +1201 -0
- package/dist/core/protocols/acp/handlers.js +51 -0
- package/dist/core/protocols/acp/permission-provider.js +122 -0
- package/dist/core/protocols/acp/stdio-server.js +116 -0
- package/dist/core/reflection/engine.js +55 -0
- package/dist/core/reflection/types.js +2 -0
- package/dist/core/runtime/agent-server-runtime.js +88 -0
- package/dist/core/runtime/bun-runtime.js +26 -0
- package/dist/core/runtime/command-runner-context.js +16 -0
- package/dist/core/runtime/exit-codes.js +11 -0
- package/dist/core/runtime/fastify-fetch-bridge.js +51 -0
- package/dist/core/runtime/fastify-server-bundle.js +26 -0
- package/dist/core/runtime/initialize.js +132 -0
- package/dist/core/runtime/loop-finalize.js +71 -0
- package/dist/core/runtime/loop-run-lifecycle.js +73 -0
- package/dist/core/runtime/loop-run-reporter.js +19 -0
- package/dist/core/runtime/loop-runtime-config.js +26 -0
- package/dist/core/runtime/loop-session-runner.js +30 -0
- package/dist/core/runtime/loop.js +84 -0
- package/dist/core/runtime/paths.js +84 -0
- package/dist/core/runtime/process-runner.js +16 -0
- package/dist/core/runtime/process-types.js +2 -0
- package/dist/core/runtime/semaphore.js +41 -0
- package/dist/core/runtime/sidecar-fastify-plugin.js +35 -0
- package/dist/core/runtime/sidecar-paths.js +47 -0
- package/dist/core/runtime/sidecar-route-catalog.js +103 -0
- package/dist/core/runtime/spawn-command.js +392 -0
- package/dist/core/runtime/spawn-interactive.js +71 -0
- package/dist/core/security/redaction.js +160 -0
- package/dist/core/session/compression.js +323 -0
- package/dist/core/session/flow.js +85 -0
- package/dist/core/session/manager.js +313 -0
- package/dist/core/session/pruning-strategy.js +153 -0
- package/dist/core/session/session-context-builder.js +122 -0
- package/dist/core/session/summary-sync.js +82 -0
- package/dist/core/session/token-tracker.js +82 -0
- package/dist/core/session/types.js +2 -0
- package/dist/core/skills/bridge.js +33 -0
- package/dist/core/skills/index.js +8 -0
- package/dist/core/skills/loader.js +80 -0
- package/dist/core/skills/parser.js +66 -0
- package/dist/core/skills/runtime/MicroTaskRunner.js +102 -0
- package/dist/core/skills/runtime/SkillRunner.js +108 -0
- package/dist/core/skills/strategy.js +29 -0
- package/dist/core/skills/types.js +2 -0
- package/dist/core/slash/index.js +6 -0
- package/dist/core/slash/parser.js +33 -0
- package/dist/core/slash/registry.js +78 -0
- package/dist/core/slash/router.js +76 -0
- package/dist/core/slash/steps/slash-decide.js +19 -0
- package/dist/core/slash/steps/slash-execute.js +73 -0
- package/dist/core/slash/steps/types.js +2 -0
- package/dist/core/slash/strategy.js +33 -0
- package/dist/core/slash/types.js +2 -0
- package/dist/core/strata/checkpoint/manager.js +492 -0
- package/dist/core/strata/checkpoint/snapshot-audit.js +88 -0
- package/dist/core/strata/checkpoint/snapshot-create.js +79 -0
- package/dist/core/strata/checkpoint/snapshot-write-tree.js +72 -0
- package/dist/core/strata/engine/shadow-merge-engine.js +394 -0
- package/dist/core/strata/index.js +15 -0
- package/dist/core/strata/interaction/content-guardian.js +59 -0
- package/dist/core/strata/interaction/file-system-provider.js +89 -0
- package/dist/core/strata/layers/file-state-resolver.js +157 -0
- package/dist/core/strata/layers/immutable-git-layer.js +42 -0
- package/dist/core/strata/layers/shadow-driver/copy-backend.js +114 -0
- package/dist/core/strata/layers/shadow-driver/env.js +29 -0
- package/dist/core/strata/layers/shadow-driver/error-classifier.js +41 -0
- package/dist/core/strata/layers/shadow-driver/index.js +17 -0
- package/dist/core/strata/layers/shadow-driver/readonly-lock.js +221 -0
- package/dist/core/strata/layers/shadow-driver/shadow-driver.js +234 -0
- package/dist/core/strata/layers/shadow-driver/strategy.js +86 -0
- package/dist/core/strata/layers/sidecar-layer.js +96 -0
- package/dist/core/strata/layers/worktree.js +240 -0
- package/dist/core/strata/runtime/environment.js +377 -0
- package/dist/core/strata/runtime/synchronizer.js +819 -0
- package/dist/core/strata/types.js +46 -0
- package/dist/core/streaming/canonical/canonical-responses-event-emitter.js +326 -0
- package/dist/core/streaming/canonical/function-call-item-id.js +13 -0
- package/dist/core/streaming/canonical/parts-from-llm-stream-chunk.js +54 -0
- package/dist/core/streaming/canonical/responses-event-emitter.js +127 -0
- package/dist/core/streaming/canonical/responses-events.js +2 -0
- package/dist/core/streaming/normalized-events.js +9 -0
- package/dist/core/streaming/normalized-from-text.js +47 -0
- package/dist/core/streaming/stream-assembler.js +347 -0
- package/dist/core/structured-output/index.js +3 -0
- package/dist/core/structured-output/json-extract.js +70 -0
- package/dist/core/structured-output/json-schema-validator.js +90 -0
- package/dist/core/structured-output/types.js +2 -0
- package/dist/core/sub-agent/artifacts/store.js +141 -0
- package/dist/core/sub-agent/artifacts/types.js +2 -0
- package/dist/core/sub-agent/controller.js +69 -0
- package/dist/core/sub-agent/core/loop.js +79 -0
- package/dist/core/sub-agent/core/manager.js +246 -0
- package/dist/core/sub-agent/registry-defaults.js +52 -0
- package/dist/core/sub-agent/registry.js +35 -0
- package/dist/core/sub-agent/tools/task-spawn.js +29 -0
- package/dist/core/sub-agent/types.js +23 -0
- package/dist/core/target-runtime/command-resolver.js +42 -0
- package/dist/core/target-runtime/index.js +3 -0
- package/dist/core/target-runtime/profile.js +73 -0
- package/dist/core/testgen/detector.js +17 -0
- package/dist/core/testgen/index.js +38 -0
- package/dist/core/testgen/templates.js +46 -0
- package/dist/core/tools/audit.js +140 -0
- package/dist/core/tools/authorization/types.js +2 -0
- package/dist/core/tools/budget.js +118 -0
- package/dist/core/tools/builtin/artifact.js +29 -0
- package/dist/core/tools/builtin/ast-grep.js +107 -0
- package/dist/core/tools/builtin/ast.js +62 -0
- package/dist/core/tools/builtin/code-search/backends/powershell.js +84 -0
- package/dist/core/tools/builtin/code-search/backends/rg.js +85 -0
- package/dist/core/tools/builtin/code-search/executor.js +87 -0
- package/dist/core/tools/builtin/code-search/parse/plain-grep.js +59 -0
- package/dist/core/tools/builtin/code-search/parse/rg-json.js +31 -0
- package/dist/core/tools/builtin/code-search/spec.js +82 -0
- package/dist/core/tools/builtin/fs.js +243 -0
- package/dist/core/tools/builtin/git.js +118 -0
- package/dist/core/tools/builtin/index.js +80 -0
- package/dist/core/tools/builtin/interaction.js +120 -0
- package/dist/core/tools/builtin/knowledge.js +98 -0
- package/dist/core/tools/builtin/plan.js +148 -0
- package/dist/core/tools/builtin/proposal.js +207 -0
- package/dist/core/tools/builtin/shell.js +71 -0
- package/dist/core/tools/builtin/verify.js +41 -0
- package/dist/core/tools/capability/executor.js +84 -0
- package/dist/core/tools/capability/runner.js +50 -0
- package/dist/core/tools/capability/types.js +2 -0
- package/dist/core/tools/dispatcher.js +80 -0
- package/dist/core/tools/headless-payload.js +37 -0
- package/dist/core/tools/loader.js +100 -0
- package/dist/core/tools/mapper.js +142 -0
- package/dist/core/tools/mcp/client.js +308 -0
- package/dist/core/tools/mcp/loader.js +110 -0
- package/dist/core/tools/mcp/schema.js +54 -0
- package/dist/core/tools/mcp/streamable-http.js +101 -0
- package/dist/core/tools/mcp/types.js +26 -0
- package/dist/core/tools/parallel/isolation.js +25 -0
- package/dist/core/tools/parallel/lock-manager.js +124 -0
- package/dist/core/tools/parallel/persistence.js +126 -0
- package/dist/core/tools/parallel/plan-builder.js +66 -0
- package/dist/core/tools/parallel/plan.js +2 -0
- package/dist/core/tools/parallel/refs.js +7 -0
- package/dist/core/tools/parallel/resolve-args.js +50 -0
- package/dist/core/tools/parallel/resource-helpers.js +35 -0
- package/dist/core/tools/parallel/resources.js +2 -0
- package/dist/core/tools/parallel/scheduler.js +372 -0
- package/dist/core/tools/parser.js +89 -0
- package/dist/core/tools/permissions/permission-rules.js +503 -0
- package/dist/core/tools/plugins/loader.js +102 -0
- package/dist/core/tools/policy.js +87 -0
- package/dist/core/tools/registry.js +29 -0
- package/dist/core/tools/router.js +514 -0
- package/dist/core/tools/sanitize.js +78 -0
- package/dist/core/tools/schema-utils.js +71 -0
- package/dist/core/tools/session.js +1105 -0
- package/dist/core/tools/streaming/ToolCallAccumulator.js +64 -0
- package/dist/core/tools/types.js +2 -0
- package/dist/core/types/authorization.js +2 -0
- package/dist/core/types/context.js +2 -0
- package/dist/core/types/errors.js +29 -0
- package/dist/core/types/execution.js +65 -0
- package/dist/core/types/index.js +9 -0
- package/dist/core/types/llm.js +9 -0
- package/dist/core/types/loop.js +2 -0
- package/dist/core/types/planning.js +2 -0
- package/dist/core/types/runtime.js +2 -0
- package/dist/core/types/usage.js +2 -0
- package/dist/core/ui/kaomoji.js +5 -0
- package/dist/core/utils/path.js +116 -0
- package/dist/core/utils/platform-shell.js +10 -0
- package/dist/core/utils/sanitizer.js +107 -0
- package/dist/core/verification/runner.js +265 -0
- package/dist/integrations/langfuse/litellm-langfuse-outcome-reporter.js +272 -0
- package/dist/integrations/langfuse/outcome-proxy.js +68 -0
- package/dist/interfaces/cli/task-runner.js +11 -0
- package/dist/languages/typescript/index.js +178 -0
- package/dist/locales/en.js +679 -0
- package/dist/locales/index.js +11 -0
- package/dist/utils/eol.js +35 -0
- package/package.json +153 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { randomBytes } from 'crypto';
|
|
2
|
+
const STEP_ID_RE = /^[a-zA-Z0-9_.:-]{3,128}$/;
|
|
3
|
+
export function assertValidStepId(stepId) {
|
|
4
|
+
if (!STEP_ID_RE.test(stepId)) {
|
|
5
|
+
throw new Error('Invalid stepId.');
|
|
6
|
+
// test
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const toCheckboxChar = (state) => (state === 'checked' ? 'x' : ' ');
|
|
10
|
+
const fromCheckboxChar = (raw) => raw.toLowerCase() === 'x' ? 'checked' : 'unchecked';
|
|
11
|
+
export function generateStepId(prefix = 'stp') {
|
|
12
|
+
return `${prefix}_${randomBytes(6).toString('hex')}`;
|
|
13
|
+
}
|
|
14
|
+
function updateCheckboxOnLine(line, checkbox) {
|
|
15
|
+
if (!checkbox)
|
|
16
|
+
return line;
|
|
17
|
+
const re = /(-\s*)\[( |x|X)\]/;
|
|
18
|
+
const match = line.match(re);
|
|
19
|
+
if (!match)
|
|
20
|
+
return line;
|
|
21
|
+
return line.replace(re, `$1[${toCheckboxChar(checkbox)}]`);
|
|
22
|
+
}
|
|
23
|
+
function updateStatusInComment(line, status) {
|
|
24
|
+
if (!status)
|
|
25
|
+
return { line, ok: true };
|
|
26
|
+
const open = '<!--';
|
|
27
|
+
const close = '-->';
|
|
28
|
+
// Find the metadata comment containing sl:id=...
|
|
29
|
+
let idx = 0;
|
|
30
|
+
while (idx < line.length) {
|
|
31
|
+
const start = line.indexOf(open, idx);
|
|
32
|
+
if (start === -1)
|
|
33
|
+
break;
|
|
34
|
+
const end = line.indexOf(close, start + open.length);
|
|
35
|
+
if (end === -1)
|
|
36
|
+
return { line, ok: false };
|
|
37
|
+
const comment = line.slice(start, end + close.length);
|
|
38
|
+
if (!comment.includes('sl:id=')) {
|
|
39
|
+
idx = end + close.length;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const key = 'sl:status=';
|
|
43
|
+
if (comment.includes(key)) {
|
|
44
|
+
const keyIdx = comment.indexOf(key);
|
|
45
|
+
const valueStart = keyIdx + key.length;
|
|
46
|
+
let valueEnd = valueStart;
|
|
47
|
+
while (valueEnd < comment.length) {
|
|
48
|
+
const ch = comment[valueEnd];
|
|
49
|
+
if (ch === ' ' || ch === '\t' || ch === '\r' || ch === '\n' || ch === '-')
|
|
50
|
+
break;
|
|
51
|
+
if (comment.startsWith(close, valueEnd))
|
|
52
|
+
break;
|
|
53
|
+
valueEnd++;
|
|
54
|
+
}
|
|
55
|
+
const replaced = comment.slice(0, valueStart) + status + comment.slice(valueEnd);
|
|
56
|
+
const nextLine = line.slice(0, start) + replaced + line.slice(end + close.length);
|
|
57
|
+
return { line: nextLine, ok: true };
|
|
58
|
+
}
|
|
59
|
+
// Insert status before -->
|
|
60
|
+
const beforeClose = comment.slice(0, comment.length - close.length);
|
|
61
|
+
const trimmed = beforeClose.endsWith(' ') ? beforeClose : `${beforeClose} `;
|
|
62
|
+
const injected = `${trimmed}sl:status=${status} ${close}`;
|
|
63
|
+
const nextLine = line.slice(0, start) + injected + line.slice(end + close.length);
|
|
64
|
+
return { line: nextLine, ok: true };
|
|
65
|
+
}
|
|
66
|
+
return { line, ok: false };
|
|
67
|
+
}
|
|
68
|
+
function extractIndent(line) {
|
|
69
|
+
const m = line.match(/^(\s*)/);
|
|
70
|
+
return m ? m[1] : '';
|
|
71
|
+
}
|
|
72
|
+
function ensureConflictsSection(lines) {
|
|
73
|
+
const headingPrefix = '## ⚠️ Conflicts';
|
|
74
|
+
let idx = lines.findIndex((l) => l.trim().startsWith(headingPrefix));
|
|
75
|
+
if (idx !== -1)
|
|
76
|
+
return idx;
|
|
77
|
+
if (lines.length > 0 && lines[lines.length - 1].trim() !== '')
|
|
78
|
+
lines.push('');
|
|
79
|
+
idx = lines.length;
|
|
80
|
+
lines.push('## ⚠️ Conflicts (Auto-generated)');
|
|
81
|
+
lines.push('- (empty)');
|
|
82
|
+
return idx;
|
|
83
|
+
}
|
|
84
|
+
function appendConflict(lines, message) {
|
|
85
|
+
const idx = ensureConflictsSection(lines);
|
|
86
|
+
// Replace placeholder if it's still empty.
|
|
87
|
+
if (lines[idx + 1] && lines[idx + 1].trim() === '- (empty)') {
|
|
88
|
+
lines[idx + 1] = `- ${message}`;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
lines.splice(idx + 1, 0, `- ${message}`);
|
|
92
|
+
}
|
|
93
|
+
export function appendPlanConflictOnly(raw, params) {
|
|
94
|
+
const lines = raw.split('\n');
|
|
95
|
+
appendConflict(lines, params.message);
|
|
96
|
+
if (params.note && params.note.trim()) {
|
|
97
|
+
appendFieldNote(lines, params.note.trim(), params.now);
|
|
98
|
+
}
|
|
99
|
+
return lines.join('\n');
|
|
100
|
+
}
|
|
101
|
+
function appendFieldNote(lines, note, now) {
|
|
102
|
+
const headingRe = /^##\s+/;
|
|
103
|
+
const heading = '## 📝 Field Notes (Reflections)';
|
|
104
|
+
let idx = lines.findIndex((l) => l.trim() === heading);
|
|
105
|
+
if (idx === -1) {
|
|
106
|
+
if (lines.length > 0 && lines[lines.length - 1].trim() !== '')
|
|
107
|
+
lines.push('');
|
|
108
|
+
idx = lines.length;
|
|
109
|
+
lines.push(heading);
|
|
110
|
+
}
|
|
111
|
+
// Insert before next heading, or at EOF.
|
|
112
|
+
let insertAt = idx + 1;
|
|
113
|
+
while (insertAt < lines.length && !headingRe.test(lines[insertAt]))
|
|
114
|
+
insertAt++;
|
|
115
|
+
const stamp = now.toISOString().slice(0, 16).replace('T', ' ');
|
|
116
|
+
lines.splice(insertAt, 0, `- *${stamp}*: ${note}`);
|
|
117
|
+
}
|
|
118
|
+
export function appendPlanNoteOnly(raw, params) {
|
|
119
|
+
const lines = raw.split('\n');
|
|
120
|
+
appendFieldNote(lines, params.note, params.now);
|
|
121
|
+
return lines.join('\n');
|
|
122
|
+
}
|
|
123
|
+
function parseStatusFromLine(line) {
|
|
124
|
+
const m = line.match(/sl:status=([a-zA-Z_]+)/);
|
|
125
|
+
if (!m)
|
|
126
|
+
return 'todo';
|
|
127
|
+
const raw = m[1];
|
|
128
|
+
switch (raw) {
|
|
129
|
+
case 'todo':
|
|
130
|
+
case 'active':
|
|
131
|
+
case 'done':
|
|
132
|
+
case 'failed':
|
|
133
|
+
case 'skipped':
|
|
134
|
+
case 'conflict':
|
|
135
|
+
return raw;
|
|
136
|
+
default:
|
|
137
|
+
return 'todo';
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function parseCheckboxFromLine(line) {
|
|
141
|
+
const m = line.match(/-\s*\[( |x|X)\]/);
|
|
142
|
+
if (!m)
|
|
143
|
+
return 'unchecked';
|
|
144
|
+
return fromCheckboxChar(m[1]);
|
|
145
|
+
}
|
|
146
|
+
function parseTextFromLine(line) {
|
|
147
|
+
// Strip leading "- [ ]" and trailing metadata comment (if any)
|
|
148
|
+
const stripped = line.replace(/^\s*-\s*\[(?: |x|X)\]\s*/, '');
|
|
149
|
+
return stripped.replace(/\s*<!--[\s\S]*?-->\s*$/, '').trim();
|
|
150
|
+
}
|
|
151
|
+
function parseStepIdFromLine(line) {
|
|
152
|
+
const m = line.match(/sl:id=([a-zA-Z0-9_.:-]+)/);
|
|
153
|
+
return m?.[1] ?? null;
|
|
154
|
+
}
|
|
155
|
+
export function applyPlanUpdate(raw, params) {
|
|
156
|
+
const { stepId, patch, now } = params;
|
|
157
|
+
assertValidStepId(stepId);
|
|
158
|
+
const lines = raw.split('\n');
|
|
159
|
+
const idx = lines.findIndex((l) => l.includes(`sl:id=${stepId}`));
|
|
160
|
+
if (idx === -1) {
|
|
161
|
+
appendConflict(lines, `STEP_NOT_FOUND: sl:id=${stepId}`);
|
|
162
|
+
return { ok: false, content: lines.join('\n'), error: 'STEP_NOT_FOUND' };
|
|
163
|
+
}
|
|
164
|
+
let line = lines[idx];
|
|
165
|
+
line = updateCheckboxOnLine(line, patch.checkbox);
|
|
166
|
+
const statusRes = updateStatusInComment(line, patch.status);
|
|
167
|
+
if (!statusRes.ok) {
|
|
168
|
+
appendConflict(lines, `MALFORMED_METADATA: sl:id=${stepId}`);
|
|
169
|
+
return { ok: false, content: lines.join('\n'), error: 'MALFORMED_METADATA' };
|
|
170
|
+
}
|
|
171
|
+
line = statusRes.line;
|
|
172
|
+
lines[idx] = line;
|
|
173
|
+
if (patch.appendSubtasks && patch.appendSubtasks.length > 0) {
|
|
174
|
+
const parentIndent = extractIndent(lines[idx]);
|
|
175
|
+
let subIndent = `${parentIndent} `;
|
|
176
|
+
// Detect existing subtask indentation style (first immediate child list item)
|
|
177
|
+
for (let i = idx + 1; i < lines.length; i++) {
|
|
178
|
+
const next = lines[i];
|
|
179
|
+
if (next.trim() === '')
|
|
180
|
+
continue;
|
|
181
|
+
const nextIndent = extractIndent(next);
|
|
182
|
+
if (nextIndent.length <= parentIndent.length)
|
|
183
|
+
break;
|
|
184
|
+
if (/^\s*-\s*\[( |x|X)\]/.test(next)) {
|
|
185
|
+
subIndent = nextIndent;
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Insert after the last child line belonging to this step (block with deeper indent)
|
|
190
|
+
let insertAt = idx + 1;
|
|
191
|
+
while (insertAt < lines.length) {
|
|
192
|
+
const next = lines[insertAt];
|
|
193
|
+
if (next.trim() === '') {
|
|
194
|
+
insertAt++;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const nextIndent = extractIndent(next);
|
|
198
|
+
if (nextIndent.length <= parentIndent.length)
|
|
199
|
+
break;
|
|
200
|
+
insertAt++;
|
|
201
|
+
}
|
|
202
|
+
const newLines = patch.appendSubtasks.map((t) => {
|
|
203
|
+
const id = generateStepId(`${stepId}`);
|
|
204
|
+
return `${subIndent}- [ ] ${t} <!-- sl:id=${id} -->`;
|
|
205
|
+
});
|
|
206
|
+
lines.splice(insertAt, 0, ...newLines);
|
|
207
|
+
}
|
|
208
|
+
if (typeof patch.note === 'string' && patch.note.trim()) {
|
|
209
|
+
appendFieldNote(lines, patch.note.trim(), now);
|
|
210
|
+
}
|
|
211
|
+
return { ok: true, content: lines.join('\n') };
|
|
212
|
+
}
|
|
213
|
+
export function summarizePlan(raw, limits) {
|
|
214
|
+
const maxActive = limits?.maxActive ?? 8;
|
|
215
|
+
const maxPending = limits?.maxPending ?? 12;
|
|
216
|
+
const lines = raw.split('\n');
|
|
217
|
+
const steps = lines
|
|
218
|
+
.filter((l) => l.includes('sl:id=') && /^\s*-\s*\[( |x|X)\]/.test(l))
|
|
219
|
+
.map((l) => {
|
|
220
|
+
const stepId = parseStepIdFromLine(l);
|
|
221
|
+
if (!stepId)
|
|
222
|
+
return null;
|
|
223
|
+
return {
|
|
224
|
+
stepId,
|
|
225
|
+
text: parseTextFromLine(l),
|
|
226
|
+
checkbox: parseCheckboxFromLine(l),
|
|
227
|
+
status: parseStatusFromLine(l),
|
|
228
|
+
};
|
|
229
|
+
})
|
|
230
|
+
.filter(Boolean);
|
|
231
|
+
const active = steps.filter((s) => s.status === 'active').slice(0, maxActive);
|
|
232
|
+
const pending = steps.filter((s) => s.status === 'todo').slice(0, maxPending);
|
|
233
|
+
const recentDone = steps.filter((s) => s.checkbox === 'checked' || s.status === 'done').slice(-3);
|
|
234
|
+
const conflictsHeading = lines.findIndex((l) => l.trim().startsWith('## ⚠️ Conflicts'));
|
|
235
|
+
const conflicts = { present: conflictsHeading !== -1 };
|
|
236
|
+
return { active, pending, recentDone, conflicts };
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=markdown-editor.js.map
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { randomBytes, createHash } from 'crypto';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { mkdir, readFile, rename, stat, writeFile } from '../adapters/fs/node-fs.js';
|
|
4
|
+
const SESSION_ID_RE = /^[a-zA-Z0-9_-]{6,64}$/;
|
|
5
|
+
export function assertValidSessionId(sessionId) {
|
|
6
|
+
if (!SESSION_ID_RE.test(sessionId)) {
|
|
7
|
+
throw new Error('Invalid sessionId (expected 6-64 chars of [a-zA-Z0-9_-]).');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function resolvePlanFilePath(params) {
|
|
11
|
+
const { persistenceRoot, sessionId } = params;
|
|
12
|
+
assertValidSessionId(sessionId);
|
|
13
|
+
const planDir = path.resolve(persistenceRoot, '.salmonloop', 'plans', sessionId);
|
|
14
|
+
const planFile = path.join(planDir, 'SALMONLOOP_PLAN.md');
|
|
15
|
+
const planFileRelHint = path.posix.join('.salmonloop', 'plans', sessionId, 'SALMONLOOP_PLAN.md');
|
|
16
|
+
return { planDir, planFile, planFileRelHint };
|
|
17
|
+
}
|
|
18
|
+
export async function readPlanFile(planFile) {
|
|
19
|
+
return readFile(planFile, 'utf-8');
|
|
20
|
+
}
|
|
21
|
+
export async function writePlanFileAtomic(planDir, planFile, content) {
|
|
22
|
+
await mkdir(planDir, { recursive: true });
|
|
23
|
+
const tmp = path.join(planDir, `.tmp-${process.pid}-${randomBytes(6).toString('hex')}.md`);
|
|
24
|
+
await writeFile(tmp, content, 'utf-8');
|
|
25
|
+
await rename(tmp, planFile);
|
|
26
|
+
}
|
|
27
|
+
async function resolveGitDir(repoRoot) {
|
|
28
|
+
const dotGit = path.join(repoRoot, '.git');
|
|
29
|
+
try {
|
|
30
|
+
const st = await stat(dotGit);
|
|
31
|
+
if (st.isDirectory())
|
|
32
|
+
return dotGit;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// ignore
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const raw = await readFile(dotGit, 'utf-8');
|
|
39
|
+
const line = raw.split('\n')[0] ?? '';
|
|
40
|
+
const m = line.match(/^gitdir:\s*(.+)\s*$/);
|
|
41
|
+
if (!m)
|
|
42
|
+
return null;
|
|
43
|
+
const gitdir = m[1].trim();
|
|
44
|
+
return path.isAbsolute(gitdir) ? gitdir : path.resolve(repoRoot, gitdir);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Ensure `.salmonloop/` is ignored locally so runtime artifacts do not dirty user repos.
|
|
52
|
+
* Uses `.git/info/exclude` (local-only) rather than modifying tracked `.gitignore`.
|
|
53
|
+
*/
|
|
54
|
+
export async function ensureSalmonloopIgnored(repoRoot) {
|
|
55
|
+
const gitDir = await resolveGitDir(repoRoot);
|
|
56
|
+
if (!gitDir)
|
|
57
|
+
return;
|
|
58
|
+
const excludePath = path.join(gitDir, 'info', 'exclude');
|
|
59
|
+
await mkdir(path.dirname(excludePath), { recursive: true });
|
|
60
|
+
let existing = '';
|
|
61
|
+
try {
|
|
62
|
+
existing = await readFile(excludePath, 'utf-8');
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
existing = '';
|
|
66
|
+
}
|
|
67
|
+
if (existing.split('\n').some((l) => l.trim() === '.salmonloop/'))
|
|
68
|
+
return;
|
|
69
|
+
const next = `${existing.replace(/\s*$/, '')}\n.salmonloop/\n`;
|
|
70
|
+
await writeFile(excludePath, next, 'utf-8');
|
|
71
|
+
}
|
|
72
|
+
export function sha256(content) {
|
|
73
|
+
return createHash('sha256').update(content).digest('hex');
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { join } from 'path';
|
|
2
|
+
import { typescriptPlugin, tsxPlugin, javascriptPlugin } from '../../languages/typescript/index.js';
|
|
3
|
+
import { readdir } from '../adapters/fs/node-fs.js';
|
|
4
|
+
import { getLogger } from '../observability/logger.js';
|
|
5
|
+
import { validateQueryPack } from './validator.js';
|
|
6
|
+
// Import built-in plugins (Phase 1: explicit import)
|
|
7
|
+
export class PluginLoader {
|
|
8
|
+
static loaded = new WeakSet();
|
|
9
|
+
/**
|
|
10
|
+
* Initialize and load all available plugins.
|
|
11
|
+
* This should be called early in the application startup (e.g., Preflight).
|
|
12
|
+
*
|
|
13
|
+
* @param repoPath - Optional repository path to scan for user plugins
|
|
14
|
+
*/
|
|
15
|
+
static async loadPlugins(registry, repoPath) {
|
|
16
|
+
if (this.loaded.has(registry))
|
|
17
|
+
return;
|
|
18
|
+
try {
|
|
19
|
+
// Phase 1: Manually register TypeScript/JavaScript plugins
|
|
20
|
+
getLogger().debug('Loading built-in plugins...');
|
|
21
|
+
this.registerWithValidation(registry, typescriptPlugin);
|
|
22
|
+
this.registerWithValidation(registry, tsxPlugin);
|
|
23
|
+
this.registerWithValidation(registry, javascriptPlugin);
|
|
24
|
+
getLogger().debug(`Plugins loaded: ${typescriptPlugin.meta.name}, ${tsxPlugin.meta.name}, ${javascriptPlugin.meta.name}`);
|
|
25
|
+
// Phase 2: Load user plugins from .salmonloop/languages/
|
|
26
|
+
if (repoPath) {
|
|
27
|
+
await this.loadUserPlugins(registry, repoPath);
|
|
28
|
+
}
|
|
29
|
+
this.loaded.add(registry);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
// In test environment, we want to know why it failed
|
|
33
|
+
if (process.env.NODE_ENV === 'test') {
|
|
34
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
35
|
+
getLogger().error(`CRITICAL: Failed to load plugins: ${errorMsg}`);
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
getLogger().error(`Failed to load plugins: ${error instanceof Error ? error.message : String(error)}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Scan and load user plugins from .salmonloop/languages/
|
|
43
|
+
*/
|
|
44
|
+
static async loadUserPlugins(registry, repoPath) {
|
|
45
|
+
const userPluginDir = join(repoPath, '.salmonloop', 'languages');
|
|
46
|
+
try {
|
|
47
|
+
// Check if directory exists
|
|
48
|
+
const entries = await readdir(userPluginDir, { withFileTypes: true });
|
|
49
|
+
const pluginDirs = entries
|
|
50
|
+
.filter((ent) => ent.isDirectory())
|
|
51
|
+
.map((ent) => ent.name);
|
|
52
|
+
if (pluginDirs.length === 0)
|
|
53
|
+
return;
|
|
54
|
+
getLogger().info(`Found ${pluginDirs.length} potential user plugins in ${userPluginDir}`);
|
|
55
|
+
for (const dirName of pluginDirs) {
|
|
56
|
+
const entryPoint = join(userPluginDir, dirName, 'index.js');
|
|
57
|
+
try {
|
|
58
|
+
// Dynamic import (ESM)
|
|
59
|
+
// We use file:// protocol for Windows compatibility with absolute paths in import()
|
|
60
|
+
const modulePath = process.platform === 'win32' ? `file://${entryPoint}` : entryPoint;
|
|
61
|
+
const pluginModule = await import(modulePath);
|
|
62
|
+
const plugin = pluginModule.default;
|
|
63
|
+
if (this.isValidPlugin(plugin)) {
|
|
64
|
+
this.registerWithValidation(registry, plugin);
|
|
65
|
+
getLogger().info(`Loaded user plugin: ${plugin.meta.name} (${plugin.meta.id})`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
getLogger().warn(`Skipping invalid user plugin in ${dirName}: missing required fields.`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
if (err && typeof err === 'object' && 'code' in err && err.code !== 'ENOENT') {
|
|
73
|
+
getLogger().warn(`Failed to load user plugin from ${dirName}: ${err instanceof Error ? (err instanceof Error ? err.message : String(err)) : String(err)}`);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (err) {
|
|
79
|
+
// Ignore if directory doesn't exist
|
|
80
|
+
if (err && typeof err === 'object' && 'code' in err && err.code !== 'ENOENT') {
|
|
81
|
+
getLogger().debug(`Error scanning for user plugins: ${err instanceof Error ? err.message : String(err)}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Reset loader state (useful for testing)
|
|
87
|
+
*/
|
|
88
|
+
static reset() {
|
|
89
|
+
this.loaded = new WeakSet();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Runtime validation of the plugin interface (Duck Typing)
|
|
93
|
+
*/
|
|
94
|
+
static isValidPlugin(obj) {
|
|
95
|
+
if (!obj || typeof obj !== 'object')
|
|
96
|
+
return false;
|
|
97
|
+
// Check Metadata
|
|
98
|
+
if (!obj.meta || typeof obj.meta.id !== 'string' || !Array.isArray(obj.meta.extensions)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
// Check Detection
|
|
102
|
+
if (!obj.detection || typeof obj.detection.matches !== 'function') {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
// Check Parsing
|
|
106
|
+
if (!obj.parsing || typeof obj.parsing.getTreeSitterWasm !== 'function') {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
// Check Dependency
|
|
110
|
+
if (!obj.dependency || typeof obj.dependency.extractImports !== 'function') {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
// Check Diagnostics
|
|
114
|
+
if (!obj.diagnostics || typeof obj.diagnostics.classifyError !== 'function') {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Register plugin with queryPack validation
|
|
121
|
+
*/
|
|
122
|
+
static registerWithValidation(registry, plugin) {
|
|
123
|
+
const validation = validateQueryPack(plugin);
|
|
124
|
+
if (!validation.valid) {
|
|
125
|
+
getLogger().warn(`Plugin ${plugin.meta.id} has queryPack validation errors: ${validation.errors.join(', ')}`);
|
|
126
|
+
}
|
|
127
|
+
registry.register(plugin);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { getLogger } from '../observability/logger.js';
|
|
2
|
+
export class PluginRegistry {
|
|
3
|
+
plugins = new Map();
|
|
4
|
+
extensionMap = new Map();
|
|
5
|
+
changeListeners = [];
|
|
6
|
+
/**
|
|
7
|
+
* Register a new language plugin
|
|
8
|
+
*/
|
|
9
|
+
register(plugin) {
|
|
10
|
+
if (this.plugins.has(plugin.meta.id)) {
|
|
11
|
+
getLogger().warn(`Plugin ${plugin.meta.id} is already registered. Overwriting.`);
|
|
12
|
+
}
|
|
13
|
+
this.plugins.set(plugin.meta.id, plugin);
|
|
14
|
+
// Map extensions to this plugin for quick lookup
|
|
15
|
+
for (const ext of plugin.meta.extensions) {
|
|
16
|
+
// normalize extension to start with dot
|
|
17
|
+
const normalizedExt = ext.startsWith('.') ? ext : `.${ext}`;
|
|
18
|
+
this.extensionMap.set(normalizedExt, plugin);
|
|
19
|
+
}
|
|
20
|
+
this.emitChange();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get all registered plugins
|
|
24
|
+
*/
|
|
25
|
+
getAll() {
|
|
26
|
+
return Array.from(this.plugins.values());
|
|
27
|
+
}
|
|
28
|
+
onChange(listener) {
|
|
29
|
+
this.changeListeners.push(listener);
|
|
30
|
+
return () => {
|
|
31
|
+
this.changeListeners = this.changeListeners.filter((l) => l !== listener);
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
emitChange() {
|
|
35
|
+
for (const listener of this.changeListeners) {
|
|
36
|
+
listener();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get plugin by ID
|
|
41
|
+
*/
|
|
42
|
+
getById(id) {
|
|
43
|
+
return this.plugins.get(id);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Get plugin by file extension
|
|
47
|
+
*/
|
|
48
|
+
getByExtension(filepath) {
|
|
49
|
+
// Extract extension from filepath (e.g., 'src/main.ts' -> '.ts')
|
|
50
|
+
// Simple extraction, can be improved
|
|
51
|
+
const match = filepath.match(/(\.[^.]+)$/);
|
|
52
|
+
if (!match)
|
|
53
|
+
return undefined;
|
|
54
|
+
const ext = match[1];
|
|
55
|
+
return this.extensionMap.get(ext);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Detect language for a repository
|
|
59
|
+
*/
|
|
60
|
+
async detectLanguage(repoPath) {
|
|
61
|
+
// Sort plugins? Maybe by some priority if added later.
|
|
62
|
+
// For now, return the first match.
|
|
63
|
+
for (const plugin of this.plugins.values()) {
|
|
64
|
+
if (await plugin.detection.matches(repoPath)) {
|
|
65
|
+
return plugin;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function createPluginRegistry() {
|
|
72
|
+
return new PluginRegistry();
|
|
73
|
+
}
|
|
74
|
+
let activePluginRegistry = null;
|
|
75
|
+
export function setPluginRegistry(registry) {
|
|
76
|
+
activePluginRegistry = registry;
|
|
77
|
+
}
|
|
78
|
+
export function getPluginRegistry() {
|
|
79
|
+
if (!activePluginRegistry) {
|
|
80
|
+
throw new Error('PluginRegistry is not initialized. Call setPluginRegistry() at startup.');
|
|
81
|
+
}
|
|
82
|
+
return activePluginRegistry;
|
|
83
|
+
}
|
|
84
|
+
export function tryGetPluginRegistry() {
|
|
85
|
+
return activePluginRegistry;
|
|
86
|
+
}
|
|
87
|
+
export function clearPluginRegistry() {
|
|
88
|
+
activePluginRegistry = null;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { getLogger } from '../observability/logger.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validate queryPack queries at plugin load time.
|
|
4
|
+
* Checks for:
|
|
5
|
+
* - Valid tree-sitter query syntax (basic validation)
|
|
6
|
+
* - Required capture names are present
|
|
7
|
+
* - Version compatibility (if specified)
|
|
8
|
+
*/
|
|
9
|
+
export function validateQueryPack(plugin) {
|
|
10
|
+
const errors = [];
|
|
11
|
+
const queryPack = plugin.parsing.queryPack;
|
|
12
|
+
if (!queryPack) {
|
|
13
|
+
return { valid: true, errors: [] };
|
|
14
|
+
}
|
|
15
|
+
// Validate version (if present)
|
|
16
|
+
if (queryPack.version) {
|
|
17
|
+
const version = queryPack.version;
|
|
18
|
+
if (!/^\d+\.\d+\.\d+$/.test(version)) {
|
|
19
|
+
errors.push(`queryPack version must follow semver format (e.g., '1.0.0'), got: ${version}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Validate symbols.calls query
|
|
23
|
+
if (queryPack.symbols?.calls) {
|
|
24
|
+
const callsQuery = queryPack.symbols.calls;
|
|
25
|
+
if (!callsQuery.includes('@callee')) {
|
|
26
|
+
errors.push('symbols.calls query must include @callee capture');
|
|
27
|
+
}
|
|
28
|
+
if (!isValidQuerySyntax(callsQuery)) {
|
|
29
|
+
errors.push('symbols.calls query has invalid syntax');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Validate flow.control query
|
|
33
|
+
if (queryPack.flow?.control) {
|
|
34
|
+
const controlQuery = queryPack.flow.control;
|
|
35
|
+
const requiredCaptures = ['@branch', '@loop', '@async'];
|
|
36
|
+
for (const capture of requiredCaptures) {
|
|
37
|
+
if (!controlQuery.includes(capture)) {
|
|
38
|
+
errors.push(`flow.control query must include ${capture} capture`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!isValidQuerySyntax(controlQuery)) {
|
|
42
|
+
errors.push('flow.control query has invalid syntax');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// Validate flow.exceptions query
|
|
46
|
+
if (queryPack.flow?.exceptions) {
|
|
47
|
+
const exceptionsQuery = queryPack.flow.exceptions;
|
|
48
|
+
const requiredCaptures = ['@trycatch', '@throw', '@catch'];
|
|
49
|
+
for (const capture of requiredCaptures) {
|
|
50
|
+
if (!exceptionsQuery.includes(capture)) {
|
|
51
|
+
errors.push(`flow.exceptions query must include ${capture} capture`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (!isValidQuerySyntax(exceptionsQuery)) {
|
|
55
|
+
errors.push('flow.exceptions query has invalid syntax');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (errors.length > 0) {
|
|
59
|
+
getLogger().warn(`Plugin ${plugin.meta.id} queryPack validation failed: ${errors.join(', ')}`);
|
|
60
|
+
}
|
|
61
|
+
return { valid: errors.length === 0, errors };
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Basic tree-sitter query syntax validation.
|
|
65
|
+
* Checks for balanced parentheses and basic structure.
|
|
66
|
+
*/
|
|
67
|
+
function isValidQuerySyntax(query) {
|
|
68
|
+
let depth = 0;
|
|
69
|
+
let inString = false;
|
|
70
|
+
let escaped = false;
|
|
71
|
+
for (let i = 0; i < query.length; i++) {
|
|
72
|
+
const char = query[i];
|
|
73
|
+
if (escaped) {
|
|
74
|
+
escaped = false;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (char === '\\') {
|
|
78
|
+
escaped = true;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (char === '"') {
|
|
82
|
+
inString = !inString;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (inString)
|
|
86
|
+
continue;
|
|
87
|
+
if (char === '(') {
|
|
88
|
+
depth++;
|
|
89
|
+
}
|
|
90
|
+
else if (char === ')') {
|
|
91
|
+
depth--;
|
|
92
|
+
if (depth < 0)
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return depth === 0 && !inString;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=validator.js.map
|