gsd-pi 2.76.0-dev.4100bd590 → 2.76.0-dev.479ad0e78
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/dist/claude-cli-check.js +32 -3
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.js +35 -1
- package/dist/onboarding.js +45 -0
- package/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +2 -8
- package/dist/resources/extensions/claude-code-cli/readiness.js +4 -3
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +77 -17
- package/dist/resources/extensions/gsd/auto/loop.js +9 -0
- package/dist/resources/extensions/gsd/auto/phases.js +58 -5
- package/dist/resources/extensions/gsd/auto/run-unit.js +38 -2
- package/dist/resources/extensions/gsd/auto/session.js +22 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -3
- package/dist/resources/extensions/gsd/auto-model-selection.js +14 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +25 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +32 -1
- package/dist/resources/extensions/gsd/auto-start.js +58 -57
- package/dist/resources/extensions/gsd/auto-worktree.js +51 -53
- package/dist/resources/extensions/gsd/auto.js +70 -28
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +17 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
- package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
- package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
- package/dist/resources/extensions/gsd/error-classifier.js +10 -3
- package/dist/resources/extensions/gsd/exec-history.js +120 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +149 -31
- package/dist/resources/extensions/gsd/guided-flow.js +190 -1
- package/dist/resources/extensions/gsd/health-widget.js +4 -1
- package/dist/resources/extensions/gsd/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/key-manager.js +28 -0
- package/dist/resources/extensions/gsd/model-router.js +36 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +44 -9
- package/dist/resources/extensions/gsd/preferences-types.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
- package/dist/resources/extensions/gsd/preferences.js +17 -17
- package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +13 -5
- package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
- package/dist/resources/extensions/gsd/token-counter.js +22 -5
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +20 -3
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
- package/dist/resources/skills/verify-before-complete/SKILL.md +2 -1
- package/dist/resources/skills/write-docs/SKILL.md +2 -1
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +17 -17
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +17 -17
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +6 -1
- package/dist/wizard.js +2 -0
- package/package.json +1 -1
- package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
- package/packages/mcp-server/dist/remote-questions.js +732 -0
- package/packages/mcp-server/dist/remote-questions.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +7 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +70 -8
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.d.ts +14 -0
- package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +49 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -25
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -1
- package/packages/mcp-server/src/mcp-server.test.ts +67 -0
- package/packages/mcp-server/src/remote-questions.test.ts +294 -0
- package/packages/mcp-server/src/remote-questions.ts +916 -0
- package/packages/mcp-server/src/server.ts +89 -14
- package/packages/mcp-server/src/session-manager.ts +43 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
- package/packages/mcp-server/src/workflow-tools.ts +84 -43
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/custom.d.ts +38 -0
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/custom.js +41 -0
- package/packages/pi-ai/dist/models/custom.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +8 -3
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +16 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
- package/packages/pi-ai/src/models/custom.ts +42 -0
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
- package/packages/pi-ai/src/providers/anthropic.ts +9 -3
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
- package/packages/pi-ai/src/providers/simple-options.ts +17 -1
- package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
- package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +7 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +7 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
- package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +90 -10
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +10 -6
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +45 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
- package/packages/pi-coding-agent/src/core/agent-session.ts +11 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +7 -0
- package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
- package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
- package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
- package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +102 -10
- package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -1
- package/packages/pi-coding-agent/src/core/session-manager.ts +10 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/scripts/link-workspace-packages.cjs +1 -0
- package/src/resources/extensions/claude-code-cli/readiness.ts +4 -3
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +78 -17
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +149 -5
- package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -0
- package/src/resources/extensions/gsd/auto/loop.ts +9 -0
- package/src/resources/extensions/gsd/auto/phases.ts +82 -4
- package/src/resources/extensions/gsd/auto/run-unit.ts +40 -2
- package/src/resources/extensions/gsd/auto/session.ts +35 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -3
- package/src/resources/extensions/gsd/auto-model-selection.ts +17 -2
- package/src/resources/extensions/gsd/auto-post-unit.ts +29 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +26 -1
- package/src/resources/extensions/gsd/auto-start.ts +60 -68
- package/src/resources/extensions/gsd/auto-worktree.ts +62 -63
- package/src/resources/extensions/gsd/auto.ts +73 -28
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +23 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +2 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
- package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
- package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
- package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
- package/src/resources/extensions/gsd/error-classifier.ts +10 -3
- package/src/resources/extensions/gsd/exec-history.ts +153 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -1
- package/src/resources/extensions/gsd/gsd-db.ts +157 -33
- package/src/resources/extensions/gsd/guided-flow.ts +222 -1
- package/src/resources/extensions/gsd/health-widget.ts +3 -1
- package/src/resources/extensions/gsd/init-wizard.ts +15 -1
- package/src/resources/extensions/gsd/journal.ts +2 -1
- package/src/resources/extensions/gsd/key-manager.ts +28 -0
- package/src/resources/extensions/gsd/model-router.ts +42 -1
- package/src/resources/extensions/gsd/pre-execution-checks.ts +46 -10
- package/src/resources/extensions/gsd/preferences-types.ts +46 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
- package/src/resources/extensions/gsd/preferences.ts +17 -17
- package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +17 -4
- package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +188 -2
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +237 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +447 -1
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
- package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
- package/src/resources/extensions/gsd/token-counter.ts +22 -5
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +26 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
- package/src/resources/skills/verify-before-complete/SKILL.md +2 -1
- package/src/resources/skills/write-docs/SKILL.md +2 -1
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → JgU2F-5N9mTyB7kUSSk9A}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{YnUwu2WWaT0_hyTLUF4nq → JgU2F-5N9mTyB7kUSSk9A}/_ssgManifest.js +0 -0
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
},
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "tsc",
|
|
28
|
-
"test": "
|
|
28
|
+
"build:test": "tsc -p tsconfig.test.json",
|
|
29
|
+
"test": "npm run build:test && node --test dist/mcp-server.test.js dist/remote-questions.test.js"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
32
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
buildAskUserQuestionsElicitRequest,
|
|
21
21
|
createMcpServer,
|
|
22
22
|
formatAskUserQuestionsElicitResult,
|
|
23
|
+
withElicitTimeout,
|
|
23
24
|
} from './server.js';
|
|
24
25
|
import { MAX_EVENTS } from './types.js';
|
|
25
26
|
import type { ManagedSession, CostAccumulator, PendingBlocker } from './types.js';
|
|
@@ -668,6 +669,43 @@ describe('createMcpServer tool registration', () => {
|
|
|
668
669
|
assert.equal(session.status, 'cancelled');
|
|
669
670
|
});
|
|
670
671
|
|
|
672
|
+
it('gsd_cancel can cancel an interactive session (no sessionId) via projectDir fallback', async () => {
|
|
673
|
+
// Simulate an interactive session: registered by projectDir but with an empty sessionId
|
|
674
|
+
// (e.g. started via `/gsd auto` in terminal or from a restarted MCP server that lost its session registry)
|
|
675
|
+
const projectDir = resolve('/tmp/interactive-session');
|
|
676
|
+
const mockClient = new MockRpcClient({ cwd: projectDir, args: [] });
|
|
677
|
+
const interactiveSession: ManagedSession = {
|
|
678
|
+
sessionId: '', // no sessionId — interactive/restarted scenario
|
|
679
|
+
projectDir,
|
|
680
|
+
status: 'running',
|
|
681
|
+
client: mockClient as any,
|
|
682
|
+
events: [],
|
|
683
|
+
pendingBlocker: null,
|
|
684
|
+
cost: { totalCost: 0, tokens: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 } },
|
|
685
|
+
startTime: Date.now(),
|
|
686
|
+
};
|
|
687
|
+
sm._putSession(projectDir, interactiveSession);
|
|
688
|
+
|
|
689
|
+
// cancelSession('') should fail — no session found by empty sessionId
|
|
690
|
+
// cancelSessionByDir should succeed — finds session by projectDir
|
|
691
|
+
await sm.cancelSessionByDir(projectDir);
|
|
692
|
+
|
|
693
|
+
const session = sm.getSessionByDir(projectDir)!;
|
|
694
|
+
assert.equal(session.status, 'cancelled');
|
|
695
|
+
assert.ok(mockClient.aborted, 'client.abort() should have been called');
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
it('gsd_cancel via projectDir works even when sessionId lookup returns undefined', async () => {
|
|
699
|
+
// Start a normal session to get its projectDir
|
|
700
|
+
const sessionId = await sm.startSession('/tmp/cancel-by-dir', { cliPath: '/usr/bin/gsd' });
|
|
701
|
+
const session = sm.getSession(sessionId)!;
|
|
702
|
+
const { projectDir } = session;
|
|
703
|
+
|
|
704
|
+
// cancelSessionByDir should find it by dir and cancel it
|
|
705
|
+
await sm.cancelSessionByDir(projectDir);
|
|
706
|
+
assert.equal(session.status, 'cancelled');
|
|
707
|
+
});
|
|
708
|
+
|
|
671
709
|
it('buildAskUserQuestionsElicitRequest adds None of the above note field for single-select questions', () => {
|
|
672
710
|
const request = buildAskUserQuestionsElicitRequest([
|
|
673
711
|
{
|
|
@@ -746,3 +784,32 @@ describe('createMcpServer tool registration', () => {
|
|
|
746
784
|
);
|
|
747
785
|
});
|
|
748
786
|
});
|
|
787
|
+
|
|
788
|
+
// ---------------------------------------------------------------------------
|
|
789
|
+
// withElicitTimeout
|
|
790
|
+
// ---------------------------------------------------------------------------
|
|
791
|
+
|
|
792
|
+
describe('withElicitTimeout', () => {
|
|
793
|
+
it('resolves with the promise value when it settles before the timeout', async () => {
|
|
794
|
+
const result = await withElicitTimeout(Promise.resolve(42), 'test', 5000);
|
|
795
|
+
assert.equal(result, 42);
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
it('rejects with a timeout error when the promise does not settle in time', async () => {
|
|
799
|
+
const never = new Promise<never>(() => {});
|
|
800
|
+
await assert.rejects(
|
|
801
|
+
() => withElicitTimeout(never, 'ask_user_questions', 1),
|
|
802
|
+
(err: Error) => {
|
|
803
|
+
assert.ok(err.message.includes('ask_user_questions'));
|
|
804
|
+
assert.ok(err.message.includes('timed out'));
|
|
805
|
+
return true;
|
|
806
|
+
},
|
|
807
|
+
);
|
|
808
|
+
});
|
|
809
|
+
|
|
810
|
+
it('clears the timer when the promise resolves (no dangling timer)', async () => {
|
|
811
|
+
const start = Date.now();
|
|
812
|
+
await withElicitTimeout(Promise.resolve('done'), 'test', 50);
|
|
813
|
+
assert.ok(Date.now() - start < 40, 'should not wait for the timeout');
|
|
814
|
+
});
|
|
815
|
+
});
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* packages/mcp-server — remote-questions regression tests (#4364)
|
|
3
|
+
*
|
|
4
|
+
* Verifies that the ask_user_questions MCP handler delegates to
|
|
5
|
+
* tryRemoteQuestions when a remote channel is configured, instead of going
|
|
6
|
+
* straight to elicitInput (which is unreachable in Claude Code-under-gsd
|
|
7
|
+
* sessions).
|
|
8
|
+
*
|
|
9
|
+
* Strategy: we cannot mock ES modules without --experimental-test-module-mocks,
|
|
10
|
+
* so we test the exported helpers from remote-questions.ts directly and verify
|
|
11
|
+
* the handler routing by observing mock side-effects injected via environment
|
|
12
|
+
* variables and a fake PREFERENCES.md file.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, it, before, after, beforeEach, afterEach } from 'node:test';
|
|
16
|
+
import assert from 'node:assert/strict';
|
|
17
|
+
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs';
|
|
18
|
+
import { tmpdir } from 'node:os';
|
|
19
|
+
import { join } from 'node:path';
|
|
20
|
+
|
|
21
|
+
// We test the module's exported helpers directly.
|
|
22
|
+
// The real createMcpServer routing is tested separately via the
|
|
23
|
+
// ask_user_questions handler integration test further below.
|
|
24
|
+
import {
|
|
25
|
+
isRemoteConfigured,
|
|
26
|
+
tryRemoteQuestions,
|
|
27
|
+
type RemoteQuestion,
|
|
28
|
+
} from './remote-questions.js';
|
|
29
|
+
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Helpers
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
const SAMPLE_QUESTIONS: RemoteQuestion[] = [
|
|
35
|
+
{
|
|
36
|
+
id: 'approach',
|
|
37
|
+
header: 'Approach',
|
|
38
|
+
question: 'Which implementation approach should I use?',
|
|
39
|
+
options: [
|
|
40
|
+
{ label: 'Option A (Recommended)', description: 'Faster, simpler path.' },
|
|
41
|
+
{ label: 'Option B', description: 'More flexible but complex.' },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
function makePrefsFile(dir: string, content: string): void {
|
|
47
|
+
writeFileSync(join(dir, 'PREFERENCES.md'), content, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// isRemoteConfigured — unit tests
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
|
|
54
|
+
describe('isRemoteConfigured', () => {
|
|
55
|
+
let tmpDir: string;
|
|
56
|
+
const origGsdHome = process.env['GSD_HOME'];
|
|
57
|
+
const origToken = process.env['DISCORD_BOT_TOKEN'];
|
|
58
|
+
|
|
59
|
+
before(() => {
|
|
60
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'gsd-rq-test-'));
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
after(() => {
|
|
64
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
65
|
+
if (origGsdHome !== undefined) {
|
|
66
|
+
process.env['GSD_HOME'] = origGsdHome;
|
|
67
|
+
} else {
|
|
68
|
+
delete process.env['GSD_HOME'];
|
|
69
|
+
}
|
|
70
|
+
if (origToken !== undefined) {
|
|
71
|
+
process.env['DISCORD_BOT_TOKEN'] = origToken;
|
|
72
|
+
} else {
|
|
73
|
+
delete process.env['DISCORD_BOT_TOKEN'];
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
beforeEach(() => {
|
|
78
|
+
process.env['GSD_HOME'] = tmpDir;
|
|
79
|
+
delete process.env['DISCORD_BOT_TOKEN'];
|
|
80
|
+
delete process.env['SLACK_BOT_TOKEN'];
|
|
81
|
+
delete process.env['TELEGRAM_BOT_TOKEN'];
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('returns false when PREFERENCES.md is absent', () => {
|
|
85
|
+
assert.equal(isRemoteConfigured(), false);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('returns false when PREFERENCES.md has no remote_questions block', () => {
|
|
89
|
+
makePrefsFile(tmpDir, '---\nsome_other_key: value\n---\n');
|
|
90
|
+
assert.equal(isRemoteConfigured(), false);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('returns false when remote_questions lacks channel or channel_id', () => {
|
|
94
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: discord\n---\n');
|
|
95
|
+
assert.equal(isRemoteConfigured(), false);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('returns false when discord channel_id format is invalid', () => {
|
|
99
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: discord\n channel_id: "not-a-snowflake"\n---\n');
|
|
100
|
+
process.env['DISCORD_BOT_TOKEN'] = 'Bot fake-token';
|
|
101
|
+
assert.equal(isRemoteConfigured(), false);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('returns false when env token is absent even if prefs are valid', () => {
|
|
105
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: discord\n channel_id: "123456789012345678"\n---\n');
|
|
106
|
+
// DISCORD_BOT_TOKEN not set
|
|
107
|
+
assert.equal(isRemoteConfigured(), false);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('returns true when discord config and token are both present', () => {
|
|
111
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: discord\n channel_id: "123456789012345678"\n---\n');
|
|
112
|
+
process.env['DISCORD_BOT_TOKEN'] = 'Bot fake-token';
|
|
113
|
+
assert.equal(isRemoteConfigured(), true);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('returns true for slack config with valid channel ID and token', () => {
|
|
117
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: slack\n channel_id: "C0123456789"\n---\n');
|
|
118
|
+
process.env['SLACK_BOT_TOKEN'] = 'xoxb-fake';
|
|
119
|
+
assert.equal(isRemoteConfigured(), true);
|
|
120
|
+
delete process.env['SLACK_BOT_TOKEN'];
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('returns true for telegram config with valid chat ID and token', () => {
|
|
124
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: telegram\n channel_id: "-1001234567890"\n---\n');
|
|
125
|
+
process.env['TELEGRAM_BOT_TOKEN'] = 'fake-telegram-token';
|
|
126
|
+
assert.equal(isRemoteConfigured(), true);
|
|
127
|
+
delete process.env['TELEGRAM_BOT_TOKEN'];
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('returns false for unknown channel type', () => {
|
|
131
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: whatsapp\n channel_id: "123456"\n---\n');
|
|
132
|
+
assert.equal(isRemoteConfigured(), false);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// ---------------------------------------------------------------------------
|
|
137
|
+
// tryRemoteQuestions — routing: returns null when not configured
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
|
|
140
|
+
describe('tryRemoteQuestions returns null when remote is not configured', () => {
|
|
141
|
+
let tmpDir: string;
|
|
142
|
+
const origGsdHome = process.env['GSD_HOME'];
|
|
143
|
+
|
|
144
|
+
before(() => {
|
|
145
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'gsd-rq-null-test-'));
|
|
146
|
+
process.env['GSD_HOME'] = tmpDir;
|
|
147
|
+
// No PREFERENCES.md, no tokens
|
|
148
|
+
delete process.env['DISCORD_BOT_TOKEN'];
|
|
149
|
+
delete process.env['SLACK_BOT_TOKEN'];
|
|
150
|
+
delete process.env['TELEGRAM_BOT_TOKEN'];
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
after(() => {
|
|
154
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
155
|
+
if (origGsdHome !== undefined) {
|
|
156
|
+
process.env['GSD_HOME'] = origGsdHome;
|
|
157
|
+
} else {
|
|
158
|
+
delete process.env['GSD_HOME'];
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('returns null when no remote channel is configured', async () => {
|
|
163
|
+
const result = await tryRemoteQuestions(SAMPLE_QUESTIONS);
|
|
164
|
+
assert.equal(result, null);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// ---------------------------------------------------------------------------
|
|
169
|
+
// tryRemoteQuestions — auth failure path
|
|
170
|
+
// ---------------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
describe('tryRemoteQuestions returns error result on auth failure', () => {
|
|
173
|
+
let tmpDir: string;
|
|
174
|
+
const origGsdHome = process.env['GSD_HOME'];
|
|
175
|
+
const origToken = process.env['DISCORD_BOT_TOKEN'];
|
|
176
|
+
|
|
177
|
+
before(() => {
|
|
178
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'gsd-rq-auth-test-'));
|
|
179
|
+
// Set up a valid discord config pointing at an unreachable/fake endpoint
|
|
180
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: discord\n channel_id: "123456789012345678"\n---\n');
|
|
181
|
+
process.env['GSD_HOME'] = tmpDir;
|
|
182
|
+
// Use an obviously invalid token — the Discord API will reject it
|
|
183
|
+
// but we don't actually call the live Discord API in unit tests.
|
|
184
|
+
// Instead we rely on the fact that fetch() to Discord API will fail
|
|
185
|
+
// in a test environment (no network or invalid token → error result).
|
|
186
|
+
process.env['DISCORD_BOT_TOKEN'] = 'invalid-fake-token-for-test';
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
after(() => {
|
|
190
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
191
|
+
if (origGsdHome !== undefined) {
|
|
192
|
+
process.env['GSD_HOME'] = origGsdHome;
|
|
193
|
+
} else {
|
|
194
|
+
delete process.env['GSD_HOME'];
|
|
195
|
+
}
|
|
196
|
+
if (origToken !== undefined) {
|
|
197
|
+
process.env['DISCORD_BOT_TOKEN'] = origToken;
|
|
198
|
+
} else {
|
|
199
|
+
delete process.env['DISCORD_BOT_TOKEN'];
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('returns an error result (not null) when auth fails', async () => {
|
|
204
|
+
const controller = new AbortController();
|
|
205
|
+
// Abort immediately so we don't actually poll
|
|
206
|
+
controller.abort();
|
|
207
|
+
|
|
208
|
+
const result = await tryRemoteQuestions(SAMPLE_QUESTIONS, controller.signal);
|
|
209
|
+
|
|
210
|
+
// When configured but auth/dispatch fails, we get a non-null error result
|
|
211
|
+
// rather than null (null means "not configured").
|
|
212
|
+
// The exact failure mode (network error vs HTTP 401) depends on the test
|
|
213
|
+
// environment, but the contract is: non-null result with error details or
|
|
214
|
+
// timed_out details.
|
|
215
|
+
assert.ok(result !== null, 'should return a result, not null, when configured');
|
|
216
|
+
assert.ok(Array.isArray(result.content), 'result.content should be an array');
|
|
217
|
+
assert.ok(result.content.length > 0, 'result.content should be non-empty');
|
|
218
|
+
assert.equal(result.content[0].type, 'text');
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
// ---------------------------------------------------------------------------
|
|
223
|
+
// Frontmatter parser — unit tests
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
|
|
226
|
+
describe('remote-questions YAML frontmatter parsing (via isRemoteConfigured)', () => {
|
|
227
|
+
let tmpDir: string;
|
|
228
|
+
const origGsdHome = process.env['GSD_HOME'];
|
|
229
|
+
|
|
230
|
+
before(() => {
|
|
231
|
+
tmpDir = mkdtempSync(join(tmpdir(), 'gsd-rq-yaml-test-'));
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
after(() => {
|
|
235
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
236
|
+
if (origGsdHome !== undefined) {
|
|
237
|
+
process.env['GSD_HOME'] = origGsdHome;
|
|
238
|
+
} else {
|
|
239
|
+
delete process.env['GSD_HOME'];
|
|
240
|
+
}
|
|
241
|
+
delete process.env['DISCORD_BOT_TOKEN'];
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
beforeEach(() => {
|
|
245
|
+
process.env['GSD_HOME'] = tmpDir;
|
|
246
|
+
process.env['DISCORD_BOT_TOKEN'] = 'Bot fake-token';
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
afterEach(() => {
|
|
250
|
+
delete process.env['DISCORD_BOT_TOKEN'];
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
it('parses channel_id as a quoted string', () => {
|
|
254
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: discord\n channel_id: "987654321098765432"\n---\n');
|
|
255
|
+
assert.equal(isRemoteConfigured(), true);
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
it('parses channel_id as a bare number', () => {
|
|
259
|
+
makePrefsFile(tmpDir, '---\nremote_questions:\n channel: discord\n channel_id: 987654321098765432\n---\n');
|
|
260
|
+
assert.equal(isRemoteConfigured(), true);
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('respects timeout_minutes and poll_interval_seconds presence without crashing', () => {
|
|
264
|
+
makePrefsFile(tmpDir, [
|
|
265
|
+
'---',
|
|
266
|
+
'remote_questions:',
|
|
267
|
+
' channel: discord',
|
|
268
|
+
' channel_id: "123456789012345678"',
|
|
269
|
+
' timeout_minutes: 10',
|
|
270
|
+
' poll_interval_seconds: 3',
|
|
271
|
+
'---',
|
|
272
|
+
].join('\n'));
|
|
273
|
+
assert.equal(isRemoteConfigured(), true);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
it('ignores content after the closing --- fence', () => {
|
|
277
|
+
makePrefsFile(tmpDir, [
|
|
278
|
+
'---',
|
|
279
|
+
'remote_questions:',
|
|
280
|
+
' channel: discord',
|
|
281
|
+
' channel_id: "123456789012345678"',
|
|
282
|
+
'---',
|
|
283
|
+
'# Markdown content after the fence is ignored',
|
|
284
|
+
'Some prose text.',
|
|
285
|
+
].join('\n'));
|
|
286
|
+
assert.equal(isRemoteConfigured(), true);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it('returns false when PREFERENCES.md has content but no frontmatter delimiters', () => {
|
|
290
|
+
makePrefsFile(tmpDir, 'remote_questions:\n channel: discord\n channel_id: "123456789012345678"\n');
|
|
291
|
+
// No --- fences — not recognized as frontmatter
|
|
292
|
+
assert.equal(isRemoteConfigured(), false);
|
|
293
|
+
});
|
|
294
|
+
});
|