gentle-pi 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +122 -8
- package/assets/agents/gentle-ai-explore.md +11 -4
- package/assets/agents/gentle-ai-verify.md +23 -4
- package/assets/agents/gentle-ai-worker.md +6 -6
- package/assets/install-wizard/index.html +47 -0
- package/assets/install-wizard/wizard.css +1279 -0
- package/assets/install-wizard/wizard.js +951 -0
- package/assets/orchestrator-delegation.md +70 -163
- package/assets/orchestrator-memory.md +11 -4
- package/assets/orchestrator-prompts.md +48 -0
- package/assets/orchestrator-tracking.md +53 -0
- package/assets/orchestrator-verification.md +28 -0
- package/assets/orchestrator-writer.md +38 -0
- package/assets/orchestrator.md +29 -25
- package/assets/sounds/LICENSE.md +52 -0
- package/assets/sounds/attention.wav +0 -0
- package/assets/sounds/error.wav +0 -0
- package/assets/sounds/success.wav +0 -0
- package/bin/engram-guard +9 -0
- package/bin/gentle-shell-install.mjs +302 -0
- package/bin/gentle-shell.mjs +703 -22
- package/contracts/review-provider-contract-mirror/provider-contract.lock.json +7 -7
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/manifest.json +2 -2
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/orchestration/pi.md +16 -4
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-capabilities.baseline.json +2 -2
- package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/generated/provider-roles.baseline.json +1 -1
- package/docs/bundled-install.md +397 -0
- package/docs/delegated-verification.md +3 -5
- package/docs/gentle-agents-activity.md +513 -0
- package/docs/gentle-shell-uninstall.md +136 -0
- package/docs/gentle-shell.md +81 -31
- package/docs/install-wizard.md +2040 -0
- package/docs/native-authority-architecture.md +1 -1
- package/docs/permission-modes.md +82 -0
- package/docs/prompt-history.md +1 -1
- package/docs/readme-reference.md +267 -40
- package/docs/render-cache-performance.md +28 -0
- package/docs/sound-notifications-proposal.md +191 -0
- package/docs/sound-notifications.md +114 -0
- package/docs/yolo-mode.md +9 -9
- package/extensions/child-context.ts +11 -2
- package/extensions/child-safety.ts +4 -2
- package/extensions/codegraph-tools.ts +18 -5
- package/extensions/gentle-agents.ts +688 -88
- package/extensions/gentle-ai.ts +886 -238
- package/extensions/gentle-herdr-activity.ts +81 -0
- package/extensions/gentle-notifications.ts +104 -0
- package/extensions/gentle-shell.ts +265 -69
- package/extensions/gentle-todo.ts +108 -13
- package/extensions/history/index.ts +11 -6
- package/extensions/pi-pretty.ts +39 -3
- package/extensions/quiet-tools.ts +91 -21
- package/extensions/skill-registry.ts +175 -46
- package/extensions/startup-banner.ts +11 -2
- package/lib/agent-home.ts +10 -1
- package/lib/agent-model-resolution.ts +80 -0
- package/lib/agent-profiles.ts +13 -3
- package/lib/agents-completion-delivery.ts +11 -3
- package/lib/agents-messaging.ts +1 -1
- package/lib/agents-protocol.ts +40 -1
- package/lib/agents-runner.ts +90 -15
- package/lib/auto-permission-classifier.ts +280 -0
- package/lib/auto-permission-runtime.ts +268 -0
- package/lib/background-jobs-tools.ts +202 -0
- package/lib/background-jobs.ts +253 -0
- package/lib/background-monitor.ts +154 -0
- package/lib/bounded-writer-admission.ts +83 -10
- package/lib/builtin-codemode-optout.ts +166 -0
- package/lib/card-content-policy.ts +85 -0
- package/lib/child-package-injection.ts +62 -0
- package/lib/codemode-renderer.ts +14 -4
- package/lib/command-palette-catalog.ts +3 -2
- package/lib/context-threshold.ts +26 -0
- package/lib/gentle-ai-binary.ts +109 -4
- package/lib/gentle-shell-bundled.ts +517 -0
- package/lib/gentle-shell-launcher.ts +74 -23
- package/lib/gentle-shell-startup-flow.ts +54 -0
- package/lib/gentle-shell-startup-update.ts +92 -0
- package/lib/gentle-shell-uninstall.ts +840 -0
- package/lib/gentle-shell-update-panel.ts +231 -0
- package/lib/herdr-activity.ts +183 -0
- package/lib/inprocess-reviewer.ts +3 -0
- package/lib/jobs-sidebar-state.ts +20 -0
- package/lib/jobs-view.ts +161 -0
- package/lib/model-price-ratio.ts +83 -0
- package/lib/nan-provider.ts +33 -11
- package/lib/native-review-cli.ts +194 -73
- package/lib/notification-audio-native.ts +162 -0
- package/lib/notification-audio-windows.ts +399 -0
- package/lib/notification-audio.ts +332 -0
- package/lib/notification-customize.ts +241 -0
- package/lib/notification-events.ts +113 -0
- package/lib/notification-policy.ts +148 -0
- package/lib/notification-pulse-client.ts +367 -0
- package/lib/notification-pulse-protocol.ts +305 -0
- package/lib/notification-pulse-stream.ts +213 -0
- package/lib/notification-pulse-worker.ts +66 -0
- package/lib/notification-scheduler.ts +173 -0
- package/lib/notification-service.ts +202 -0
- package/lib/notification-ui.ts +87 -0
- package/lib/odd-phase.ts +1 -1
- package/lib/orchestrator-alias.ts +20 -0
- package/lib/orchestrator-catalog.ts +79 -0
- package/lib/orchestrator-consultation.ts +61 -0
- package/lib/orchestrator-discovery.ts +49 -0
- package/lib/orchestrator-helper-consent.ts +122 -0
- package/lib/orchestrator-helper.ts +167 -0
- package/lib/orchestrator-message-card.ts +105 -0
- package/lib/orchestrator-presence.ts +115 -14
- package/lib/orchestrator-scope.ts +80 -0
- package/lib/orchestrator-state.ts +107 -0
- package/lib/orchestrator-tool-card.ts +280 -0
- package/lib/orchestrator-work-search.ts +218 -0
- package/lib/orchestrator-work.ts +79 -0
- package/lib/permission-mode-policy.ts +59 -0
- package/lib/review-candidate-view-owner.ts +8 -6
- package/lib/review-candidate-view.ts +3 -2
- package/lib/review-compact-contract.ts +2 -2
- package/lib/review-host-relay.ts +7 -2
- package/lib/review-integration-v2.ts +100 -22
- package/lib/review-publication-gate.ts +1 -1
- package/lib/review-risk-assessment.ts +77 -51
- package/lib/review-sidebar-state.ts +2 -1
- package/lib/review-transaction.ts +72 -3
- package/lib/runtime-metrics-children.ts +1 -1
- package/lib/runtime-metrics-native.ts +3 -2
- package/lib/selection-engine.ts +18 -6
- package/lib/session-change-capture.ts +5 -4
- package/lib/session-changes.ts +27 -22
- package/lib/session-profile-binding.ts +83 -0
- package/lib/session-profile-freeze.ts +266 -0
- package/lib/session-worktree-registry.ts +74 -8
- package/lib/shell-bar.ts +41 -11
- package/lib/shell-changes-view.ts +40 -13
- package/lib/shell-changes.ts +86 -71
- package/lib/shell-sidebar-layout.ts +5 -1
- package/lib/shell-todo.ts +62 -19
- package/lib/shell-usage.ts +4 -3
- package/lib/status-timing-diagnostics.ts +201 -0
- package/lib/telemetry-trigger.ts +3 -1
- package/lib/vim-editor-adapter.ts +7 -3
- package/lib/visual-customization-policy.ts +20 -9
- package/lib/visual-customize-view.ts +171 -20
- package/lib/writer-surfaces.ts +162 -0
- package/lib/yolo-session-policy.ts +198 -121
- package/package.json +1 -1
- package/runtime/child-package-injection.mjs +63 -0
- package/runtime/gentle-ai-binary.mjs +109 -4
- package/runtime/gentle-shell-bundled.mjs +518 -0
- package/runtime/gentle-shell-launcher.mjs +73 -22
- package/runtime/gentle-shell-startup-flow.mjs +55 -0
- package/runtime/gentle-shell-startup-update.mjs +93 -0
- package/runtime/gentle-shell-uninstall.mjs +841 -0
- package/runtime/gentle-shell-update-panel.mjs +232 -0
- package/runtime/native-review-cli.mjs +191 -70
- package/runtime/review-integration-v2.mjs +100 -22
- package/runtime/review-risk-assessment.mjs +77 -51
- package/runtime/status-timing-diagnostics.mjs +202 -0
- package/runtime/telemetry-trigger.mjs +3 -1
- package/scripts/bootstrap.cmd +255 -0
- package/scripts/bootstrap.sh +168 -0
- package/scripts/build-distribution.mjs +157 -0
- package/scripts/build-installer-bundles.mjs +136 -0
- package/scripts/build-runtime-modules.mjs +7 -0
- package/scripts/bundled-install.mjs +1308 -0
- package/scripts/bundled-wizard.mjs +399 -0
- package/scripts/check-types.mjs +4 -6
- package/scripts/gentle-ai-installer.mjs +79 -32
- package/scripts/install-gentle-ai.mjs +48 -1
- package/scripts/install-tui-mode-setting.mjs +10 -1
- package/scripts/install-wizard-preview.mjs +154 -0
- package/scripts/installer-downloads.mjs +648 -0
- package/scripts/installer-preflight.mjs +387 -0
- package/scripts/installer-probes.mjs +564 -0
- package/scripts/installer-runner.mjs +1102 -0
- package/scripts/installer-server.mjs +881 -0
- package/scripts/installer-windows-artifacts.json +15 -0
- package/scripts/installer-windows.mjs +752 -0
- package/scripts/main-channel.mjs +452 -0
- package/scripts/npm-pack-result.mjs +31 -0
- package/scripts/render-cache-performance-worker.mjs +205 -0
- package/scripts/render-cache-performance.mjs +115 -0
- package/scripts/run-test-suite.mjs +22 -8
- package/scripts/test-installer-acceptance.sh +161 -0
- package/scripts/test-packed-runner.mjs +23 -5
- package/scripts/types-baseline.json +2 -92
- package/scripts/verify-package-files.mjs +82 -18
- package/skills/gentle-ai/SKILL.md +12 -11
- package/tests/agent-home.test.ts +56 -3
- package/tests/agent-model-resolution.test.ts +113 -0
- package/tests/agent-profiles.test.ts +12 -0
- package/tests/agent-risk-escalation.test.ts +123 -0
- package/tests/agents-completion-delivery.test.ts +17 -0
- package/tests/agents-protocol.test.ts +57 -0
- package/tests/agents-queries.test.ts +9 -9
- package/tests/agents-runner-process.test.ts +31 -0
- package/tests/agents-runner.test.ts +89 -4
- package/tests/auto-mode-invariants.test.ts +258 -0
- package/tests/auto-mode-sdk.test.ts +57 -0
- package/tests/auto-mode.test.ts +49 -0
- package/tests/auto-permission-classifier.test.ts +283 -0
- package/tests/auto-permission-runtime.test.ts +196 -0
- package/tests/background-cache-warming.test.ts +2 -1
- package/tests/background-jobs.test.ts +227 -0
- package/tests/background-monitor.test.ts +195 -0
- package/tests/background-subagents-default-mode.test.ts +28 -5
- package/tests/bounded-stop-contract.test.ts +85 -0
- package/tests/bounded-writer-admission.test.ts +52 -1
- package/tests/bridge-wake-lifecycle.test.ts +129 -0
- package/tests/bridge-wake-rendering.test.ts +56 -0
- package/tests/build-distribution.test.ts +269 -0
- package/tests/builtin-codemode-optout.test.ts +242 -0
- package/tests/bundled-install.test.ts +1319 -0
- package/tests/bundled-wizard.test.ts +505 -0
- package/tests/card-content-policy.test.ts +68 -0
- package/tests/card-style-policy.test.ts +34 -2
- package/tests/child-codegraph-bootstrap.test.ts +74 -0
- package/tests/child-package-entrypoints.test.ts +65 -0
- package/tests/child-package-injection.test.ts +74 -0
- package/tests/child-safety.test.ts +12 -0
- package/tests/child-web-package.test.ts +224 -0
- package/tests/codegraph-tools.test.ts +35 -0
- package/tests/codemode-rendering.test.ts +107 -2
- package/tests/command-palette.test.ts +5 -5
- package/tests/context-threshold.test.ts +31 -0
- package/tests/delegate-for-reason-contract.test.ts +327 -0
- package/tests/delegated-key-learnings-contract.test.ts +3 -2
- package/tests/devbinary/native-review-parity.devtest.ts +1 -1
- package/tests/devbinary/pi-host-relay.devtest.ts +173 -3
- package/tests/engram-safety.test.ts +288 -0
- package/tests/generic-agent-tools.test.ts +16 -1
- package/tests/gentle-agents.test.ts +1722 -59
- package/tests/gentle-ai-binary-isolation.test.ts +135 -0
- package/tests/gentle-ai-binary.test.ts +19 -2
- package/tests/gentle-ai-child-guards.test.ts +202 -0
- package/tests/gentle-ai-dev-binary-surfacing.test.ts +125 -15
- package/tests/gentle-ai-installer.test.ts +548 -58
- package/tests/gentle-ai-prompt-model-routing.test.ts +123 -0
- package/tests/gentle-ai-renderer.test.ts +6 -6
- package/tests/gentle-ai.test.ts +999 -31
- package/tests/gentle-herdr-activity.test.ts +100 -0
- package/tests/gentle-notifications.test.ts +427 -0
- package/tests/gentle-shell-bin.test.ts +249 -5
- package/tests/gentle-shell-bundled.test.ts +1002 -0
- package/tests/gentle-shell-launcher.test.ts +234 -13
- package/tests/gentle-shell-startup-flow.test.ts +75 -0
- package/tests/gentle-shell-startup-update.test.ts +85 -0
- package/tests/gentle-shell-uninstall.test.ts +978 -0
- package/tests/gentle-shell-update-panel.test.ts +158 -0
- package/tests/gentle-shell.test.ts +541 -96
- package/tests/gentle-todo.test.ts +253 -2
- package/tests/herdr-activity.test.ts +243 -0
- package/tests/history-agent-home.test.ts +81 -0
- package/tests/history-child-guard.test.ts +70 -0
- package/tests/inprocess-reviewer.test.ts +20 -0
- package/tests/install-gentle-ai-failure.test.ts +69 -0
- package/tests/install-tui-mode-setting.test.ts +15 -0
- package/tests/install-wizard.test.ts +1223 -0
- package/tests/installer-bundles.test.ts +122 -0
- package/tests/installer-posix-bootstrap.test.ts +1201 -0
- package/tests/installer-preflight.test.ts +750 -0
- package/tests/installer-probes.test.ts +1106 -0
- package/tests/installer-runner.test.ts +2158 -0
- package/tests/installer-server.test.ts +1567 -0
- package/tests/installer-windows-bootstrap.test.ts +2410 -0
- package/tests/jobs-view.test.ts +160 -0
- package/tests/main-channel-upgrade.test.ts +389 -0
- package/tests/main-channel.test.ts +344 -0
- package/tests/maintainer/provider-relay.maintest.ts +13 -12
- package/tests/model-price-ratio.test.ts +116 -0
- package/tests/model-profiles-preservation.test.ts +153 -0
- package/tests/model-routing-package.test.ts +10 -0
- package/tests/nan-provider-runtime.test.ts +156 -0
- package/tests/nan-provider.test.ts +28 -18
- package/tests/native-binary-gate.test.ts +2 -0
- package/tests/native-review-capability-contract.test.ts +7 -1
- package/tests/native-review-cli.test.ts +236 -1
- package/tests/native-review-consent.test.ts +2 -2
- package/tests/native-review-parity-runtime.test.ts +1 -1
- package/tests/native-review-parity.test.ts +12 -48
- package/tests/native-risk-evidence-parity.test.ts +21 -0
- package/tests/no-self-pause-contract.test.ts +87 -0
- package/tests/notification-audio-native.test.ts +281 -0
- package/tests/notification-audio-windows.test.ts +581 -0
- package/tests/notification-audio.test.ts +548 -0
- package/tests/notification-customize.test.ts +655 -0
- package/tests/notification-events.test.ts +115 -0
- package/tests/notification-policy.test.ts +201 -0
- package/tests/notification-pulse-client.test.ts +356 -0
- package/tests/notification-pulse-protocol.test.ts +213 -0
- package/tests/notification-pulse-stream.test.ts +320 -0
- package/tests/notification-scheduler.test.ts +258 -0
- package/tests/notification-ui.test.ts +157 -0
- package/tests/npm-pack-result.test.ts +41 -0
- package/tests/odd-integration.test.ts +14 -5
- package/tests/odd-routing-canonical-ratchet.test.ts +53 -12
- package/tests/odd-routing-contract.test.ts +80 -23
- package/tests/orchestrator-budget.test.ts +29 -6
- package/tests/orchestrator-catalog.test.ts +146 -0
- package/tests/orchestrator-consultation-sdk.test.ts +614 -0
- package/tests/orchestrator-consultation.test.ts +111 -0
- package/tests/orchestrator-discovery.test.ts +241 -0
- package/tests/orchestrator-helper-consent.test.ts +171 -0
- package/tests/orchestrator-helper.test.ts +297 -0
- package/tests/orchestrator-message-card.test.ts +190 -0
- package/tests/orchestrator-presence.test.ts +23 -0
- package/tests/orchestrator-rdd-ownership.test.ts +6 -5
- package/tests/orchestrator-scope.test.ts +107 -0
- package/tests/orchestrator-state.test.ts +114 -0
- package/tests/orchestrator-status-publication-contract.test.ts +34 -0
- package/tests/orchestrator-tool-card.test.ts +398 -0
- package/tests/orchestrator-work-search.test.ts +318 -0
- package/tests/orchestrator-work.test.ts +147 -0
- package/tests/package-manifest.test.ts +101 -17
- package/tests/packed-runner-owned-path.test.ts +35 -1
- package/tests/parallel-reason-contract.test.ts +21 -0
- package/tests/parallel-writer-admission.test.ts +210 -0
- package/tests/permission-mode-policy.test.ts +194 -0
- package/tests/persona-single-channel.test.ts +4 -12
- package/tests/pi-pretty.test.ts +56 -0
- package/tests/provider-defect-handoff.test.ts +4 -3
- package/tests/quiet-tool-rendering.test.ts +160 -3
- package/tests/rdd-aware-verification-contract.test.ts +29 -41
- package/tests/render-cache-performance.test.ts +48 -0
- package/tests/review-agent-end-preflight.test.ts +62 -10
- package/tests/review-candidate-view.test.ts +101 -12
- package/tests/review-contract-prompt.test.ts +33 -4
- package/tests/review-controller-native-recovery.test.ts +327 -17
- package/tests/review-controller-native-routing.test.ts +255 -1
- package/tests/review-controller-workspace-root.test.ts +43 -2
- package/tests/review-controller.test.ts +2 -2
- package/tests/review-correction-lifecycle.test.ts +2 -1
- package/tests/review-gate.test.ts +7 -4
- package/tests/review-graph-schema.test.ts +2 -2
- package/tests/review-host-relay-routing.test.ts +5 -3
- package/tests/review-host-relay.test.ts +49 -2
- package/tests/review-integration-v2-forward.test.ts +21 -1
- package/tests/review-json-arguments.test.ts +167 -0
- package/tests/review-last-event-closure.test.ts +157 -8
- package/tests/review-ledger-contract.test.ts +5 -4
- package/tests/review-policy-judgment-day.test.ts +1 -1
- package/tests/review-policy-ordinary.test.ts +2 -2
- package/tests/review-relay-transport-agent.test.ts +66 -1
- package/tests/review-risk-assessment.test.ts +109 -33
- package/tests/review-session-standing-permission-controller.test.ts +16 -17
- package/tests/review-session-standing-permission-ipc.test.ts +6 -5
- package/tests/review-test-fixtures.ts +7 -1
- package/tests/review-transaction.test.ts +18 -1
- package/tests/run-test-suite.test.ts +83 -5
- package/tests/runtime-harness.mjs +42 -15
- package/tests/runtime-metrics-extension.test.ts +1 -1
- package/tests/runtime-metrics-native.test.ts +31 -1
- package/tests/selection-engine.test.ts +30 -0
- package/tests/session-change-capture.test.ts +10 -10
- package/tests/session-changes-shell.test.ts +242 -48
- package/tests/session-changes.test.ts +17 -24
- package/tests/session-profile-binding.test.ts +163 -0
- package/tests/session-profile-freeze.test.ts +381 -0
- package/tests/session-subject-routing-contract.test.ts +34 -0
- package/tests/session-worktree-registry.test.ts +57 -2
- package/tests/shell-bar.test.ts +40 -0
- package/tests/shell-changes-view.test.ts +85 -34
- package/tests/shell-changes.test.ts +61 -62
- package/tests/shell-render-cache-runtime.test.ts +69 -0
- package/tests/shell-render-cache.test.ts +129 -0
- package/tests/shell-sidebar-layout.test.ts +27 -2
- package/tests/shell-todo.test.ts +120 -2
- package/tests/shell-usage-view.test.ts +1 -1
- package/tests/shell-usage.test.ts +35 -0
- package/tests/short-check-routing-contract.test.ts +49 -0
- package/tests/skill-registry-watcher.test.ts +119 -0
- package/tests/skill-registry.test.ts +311 -5
- package/tests/startup-banner.test.ts +117 -3
- package/tests/startup-home-repo.test.ts +170 -0
- package/tests/status-timing-diagnostics.test.ts +283 -0
- package/tests/support/orchestrator-modules.ts +19 -0
- package/tests/task-size-routing-contract.test.ts +241 -0
- package/tests/telemetry-trigger.test.ts +27 -1
- package/tests/test-strength-contract.test.ts +124 -0
- package/tests/verify-agent-contract.test.ts +90 -0
- package/tests/verify-first-launch-contract.test.ts +139 -0
- package/tests/verify-package-files.test.ts +56 -0
- package/tests/vim-editor-adapter.test.ts +7 -7
- package/tests/visual-customization-policy.test.ts +32 -3
- package/tests/visual-customize-view.test.ts +288 -10
- package/tests/writer-edit-surface-scope.test.ts +59 -2
- package/tests/writer-surfaces.test.ts +199 -0
- package/tests/yolo-customize.test.ts +18 -3
- package/tests/yolo-mode-runtime.test.ts +37 -10
- package/tests/yolo-mode.test.ts +32 -4
- package/tests/yolo-session-policy.test.ts +1 -1
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/README.md +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/lens.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/refuter.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/schemas/targeted-validator.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/lens.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/refuter.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.2.0 → v1.3.0}/bundle/vectors/targeted-validator.json +0 -0
|
@@ -30,6 +30,23 @@ const binUrl = new URL("../bin/gentle-shell.mjs", import.meta.url);
|
|
|
30
30
|
const binPath = fileURLToPath(binUrl);
|
|
31
31
|
const packageRoot = dirname(dirname(binPath));
|
|
32
32
|
|
|
33
|
+
test("Herdr activity is discoverable through the isolated launcher package", async () => {
|
|
34
|
+
const { buildPiInvocation } = await import("../lib/gentle-shell-launcher.ts");
|
|
35
|
+
const manifest = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
|
|
36
|
+
assert.ok(manifest.pi.extensions.includes("./extensions"));
|
|
37
|
+
assert.ok(existsSync(join(packageRoot, "extensions", "gentle-herdr-activity.ts")));
|
|
38
|
+
for (const takeOver of [false, true]) {
|
|
39
|
+
const invocation = buildPiInvocation({
|
|
40
|
+
runtime: { kind: "path", command: "fake-pi", args: [] },
|
|
41
|
+
home: { mode: "isolated", source: "default", dir: "/fake/home" },
|
|
42
|
+
packageRoot, declaration: undefined, takeOver, otherPackagePaths: [],
|
|
43
|
+
passthrough: [], baseEnv: {}, homedir: "/fake", cwd: "/fake/cwd",
|
|
44
|
+
});
|
|
45
|
+
assert.ok(invocation.args.includes(packageRoot));
|
|
46
|
+
assert.equal(invocation.env.PI_CODING_AGENT_DIR, "/fake/home");
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
33
50
|
test("real adjacent Pi resolves through its public entry without PATH or a runtime override", (t) => {
|
|
34
51
|
const f = fixture(t);
|
|
35
52
|
const result = spawnSync(process.execPath, [binPath, "--version"], {
|
|
@@ -53,13 +70,17 @@ function standaloneLauncher(t: test.TestContext) {
|
|
|
53
70
|
writeFileSync(join(root, "bin", "gentle-shell.mjs"), readFileSync(binPath));
|
|
54
71
|
writeFileSync(join(root, "package.json"), readFileSync(join(packageRoot, "package.json")));
|
|
55
72
|
for (const dir of ["runtime", "scripts"]) symlinkSync(join(packageRoot, dir), join(root, dir), "junction");
|
|
56
|
-
const env = {
|
|
73
|
+
const env = {
|
|
74
|
+
HOME: f.home, USERPROFILE: f.home, PATH: `${root}${delimiter}${dirname(process.execPath)}`, GENTLE_SHELL_NO_AUTO_SETUP: "1",
|
|
75
|
+
// Keep executable discovery isolated without making cmd shims unlaunchable.
|
|
76
|
+
...(process.platform === "win32" ? { ComSpec: process.env.ComSpec, SystemRoot: process.env.SystemRoot } : {}),
|
|
77
|
+
};
|
|
57
78
|
return { ...f, root, env, launcher: join(root, "bin", "gentle-shell.mjs") };
|
|
58
79
|
}
|
|
59
80
|
|
|
60
81
|
test("a genuinely absent adjacent peer falls back to PATH", (t) => {
|
|
61
82
|
const f = standaloneLauncher(t);
|
|
62
|
-
|
|
83
|
+
writePathPiScript(f.root, "0.99.2");
|
|
63
84
|
const result = spawnSync(process.execPath, [f.launcher, "--version"], { env: f.env, encoding: "utf8" });
|
|
64
85
|
assert.equal(result.status, 0, result.stderr);
|
|
65
86
|
assert.match(result.stdout, /pi 0\.99\.2/);
|
|
@@ -71,8 +92,7 @@ test("malformed adjacent metadata never silently falls back to PATH; env overrid
|
|
|
71
92
|
mkdirSync(join(peer, "dist", "bundle"), { recursive: true });
|
|
72
93
|
writeFileSync(join(peer, "dist", "index.js"), "");
|
|
73
94
|
writePiScript(join(peer, "dist", "bundle", "cli.js"), "0.99.1");
|
|
74
|
-
const fallback =
|
|
75
|
-
writePiScript(fallback, "0.99.2");
|
|
95
|
+
const fallback = writePathPiScript(f.root, "0.99.2");
|
|
76
96
|
const base = { name: "@earendil-works/pi-coding-agent", type: "module", exports: { ".": { import: "./dist/index.js" } }, bin: { pi: "dist/bundle/cli.js" } };
|
|
77
97
|
for (const metadata of [{ ...base, name: "impostor" }, { ...base, bin: { pi: "../outside.js" } }, { ...base, bin: {} }, "malformed"]) {
|
|
78
98
|
writeFileSync(join(peer, "package.json"), metadata === "malformed" ? "{" : JSON.stringify(metadata));
|
|
@@ -117,6 +137,9 @@ function fixture(t: test.TestContext) {
|
|
|
117
137
|
GENTLE_SHELL_PI: piScript,
|
|
118
138
|
GENTLE_SHELL_NO_AUTO_SETUP: "1",
|
|
119
139
|
};
|
|
140
|
+
// A suite launched from inside a Gentle Shell session inherits the outer
|
|
141
|
+
// session's recorded user Pi home, which --link now honours first (#2015).
|
|
142
|
+
delete env.GENTLE_SHELL_USER_PI_HOME;
|
|
120
143
|
return { root, home, gentleShellHome, piScript, env };
|
|
121
144
|
}
|
|
122
145
|
|
|
@@ -152,6 +175,7 @@ function writePiScript(path: string, version: string, removeExitCode = 0) {
|
|
|
152
175
|
" PI_CODING_AGENT_DIR: process.env.PI_CODING_AGENT_DIR,",
|
|
153
176
|
" GENTLE_PI_AGENT_HOME: process.env.GENTLE_PI_AGENT_HOME,",
|
|
154
177
|
" GENTLE_SHELL_USER_PI_HOME: process.env.GENTLE_SHELL_USER_PI_HOME,",
|
|
178
|
+
" GENTLE_SHELL_CHILD_PACKAGE_INJECTION: process.env.GENTLE_SHELL_CHILD_PACKAGE_INJECTION,",
|
|
155
179
|
"}));",
|
|
156
180
|
"process.exit(0);",
|
|
157
181
|
"",
|
|
@@ -160,6 +184,17 @@ function writePiScript(path: string, version: string, removeExitCode = 0) {
|
|
|
160
184
|
chmodSync(path, 0o755);
|
|
161
185
|
}
|
|
162
186
|
|
|
187
|
+
// Match the real platform lookup: POSIX accepts the shebang executable,
|
|
188
|
+
// Windows discovers a .cmd shim via PATHEXT. Bundled JS peers stay unchanged.
|
|
189
|
+
function writePathPiScript(root: string, version: string): string {
|
|
190
|
+
const script = join(root, process.platform === "win32" ? "pi-fixture.mjs" : "pi");
|
|
191
|
+
writePiScript(script, version);
|
|
192
|
+
if (process.platform !== "win32") return script;
|
|
193
|
+
const command = join(root, "pi.cmd");
|
|
194
|
+
writeFileSync(command, `@echo off\r\n"${process.execPath}" "${script}" %*\r\nexit /b %errorlevel%\r\n`);
|
|
195
|
+
return command;
|
|
196
|
+
}
|
|
197
|
+
|
|
163
198
|
function run(env: NodeJS.ProcessEnv, args: string[], options: { cwd?: string } = {}) {
|
|
164
199
|
return spawnSync(process.execPath, [binPath, ...args], { encoding: "utf8", env, ...options });
|
|
165
200
|
}
|
|
@@ -642,6 +677,20 @@ test("forwarded args reach pi after the injected extension flags, in order", (t)
|
|
|
642
677
|
assert.equal(payload.GENTLE_PI_AGENT_HOME, f.gentleShellHome);
|
|
643
678
|
});
|
|
644
679
|
|
|
680
|
+
// #1690: the spawned pi must carry the launcher's own -e set so the subagent
|
|
681
|
+
// runner can forward it to delegated children; a stale inherited value is replaced.
|
|
682
|
+
test("an isolated launch without a gentle-pi declaration signals its package injection to pi", (t) => {
|
|
683
|
+
const f = fixture(t);
|
|
684
|
+
const stale = JSON.stringify({ version: 1, noExtensions: true, extensionPaths: [join(f.root, "outer")] });
|
|
685
|
+
for (const inherited of [undefined, stale]) {
|
|
686
|
+
const result = run({ ...f.env, GENTLE_SHELL_CHILD_PACKAGE_INJECTION: inherited }, ["--mode", "rpc"]);
|
|
687
|
+
assert.equal(result.status, 0, result.stderr);
|
|
688
|
+
const payload = JSON.parse(result.stdout);
|
|
689
|
+
assert.deepEqual(payload.args.slice(0, 2), ["-e", packageRoot]);
|
|
690
|
+
assert.deepEqual(JSON.parse(payload.GENTLE_SHELL_CHILD_PACKAGE_INJECTION), { version: 1, noExtensions: false, extensionPaths: [packageRoot] });
|
|
691
|
+
}
|
|
692
|
+
});
|
|
693
|
+
|
|
645
694
|
test("an isolated launch keeps its own agent home and carries the user's original Pi home, even when nested", (t) => {
|
|
646
695
|
const f = fixture(t);
|
|
647
696
|
const base = { ...f.env };
|
|
@@ -667,6 +716,10 @@ test("an isolated launch keeps its own agent home and carries the user's origina
|
|
|
667
716
|
const linked = launch({ PI_CODING_AGENT_DIR: customHome }, ["--link"]);
|
|
668
717
|
assert.equal(linked.PI_CODING_AGENT_DIR, customHome);
|
|
669
718
|
assert.equal(linked.GENTLE_SHELL_USER_PI_HOME, customHome);
|
|
719
|
+
// --link from inside an isolated session reuses the preserved original home (#2015).
|
|
720
|
+
const nestedLinked = launch({ PI_CODING_AGENT_DIR: f.gentleShellHome, GENTLE_SHELL_USER_PI_HOME: customHome }, ["--link"]);
|
|
721
|
+
assert.equal(nestedLinked.PI_CODING_AGENT_DIR, customHome);
|
|
722
|
+
assert.equal(nestedLinked.GENTLE_SHELL_USER_PI_HOME, customHome);
|
|
670
723
|
assert.equal(existsSync(join(customHome, "sessions")), false);
|
|
671
724
|
});
|
|
672
725
|
|
|
@@ -801,7 +854,10 @@ test("gentle-shell setup provisions the resolved home through the pinned gentle-
|
|
|
801
854
|
assert.deepEqual(payload.args, ["install", "--agent", "pi", "--scope", "global"]);
|
|
802
855
|
assert.equal(payload.PI_CODING_AGENT_DIR, f.gentleShellHome);
|
|
803
856
|
assert.equal(payload.GENTLE_PI_AGENT_HOME, f.gentleShellHome);
|
|
804
|
-
|
|
857
|
+
// First the temporary `pi` that runs the resolved runtime, then the runtime's own folder.
|
|
858
|
+
const [launcher, runtimeDir] = payload.PATH.split(delimiter);
|
|
859
|
+
assert.match(launcher, /gentle-shell-pi-/, payload.PATH);
|
|
860
|
+
assert.equal(runtimeDir, dirname(f.piScript), payload.PATH);
|
|
805
861
|
|
|
806
862
|
// Home resolution runs exactly as a normal run: the isolated home gets
|
|
807
863
|
// created with its bootstrap TUI setting, same as a plain `gentle-shell`.
|
|
@@ -847,6 +903,119 @@ test("gentle-shell setup passes through the gentle-ai exit code", (t) => {
|
|
|
847
903
|
assert.equal(result.status, 3);
|
|
848
904
|
});
|
|
849
905
|
|
|
906
|
+
// Windows cannot execute a shebang fixture directly; use the launcher's
|
|
907
|
+
// existing .cmd support without changing the runtime under test.
|
|
908
|
+
function setupMCPExecutable(path: string): string {
|
|
909
|
+
chmodSync(path, 0o755);
|
|
910
|
+
if (process.platform !== "win32") return path;
|
|
911
|
+
const wrapper = `${path}.cmd`;
|
|
912
|
+
writeFileSync(wrapper, `@echo off\r\n"${process.execPath}" "${path}" %*\r\n`);
|
|
913
|
+
return wrapper;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
test("setup MCP migration warns without re-enabling configured servers", async (t) => {
|
|
917
|
+
for (const mode of ["link", "path"] as const) {
|
|
918
|
+
await t.test(mode, (t) => {
|
|
919
|
+
const f = fixture(t);
|
|
920
|
+
const target = mode === "link" ? join(f.home, ".pi", "agent") : f.gentleShellHome;
|
|
921
|
+
mkdirSync(join(target, "npm"), { recursive: true });
|
|
922
|
+
const settingsPath = join(target, "settings.json");
|
|
923
|
+
const settings = { theme: "kanagawa", packages: ["npm:pi-mcp-adapter", "npm:other"], extensions: ["-builtin:mcp", "user-extension.ts"] };
|
|
924
|
+
writeFileSync(settingsPath, JSON.stringify(settings));
|
|
925
|
+
const npmPath = join(target, "npm", "package.json");
|
|
926
|
+
writeFileSync(npmPath, JSON.stringify({ dependencies: { "pi-mcp-adapter": "^3.0.0", other: "1.0.0" } }));
|
|
927
|
+
const mcpPath = join(target, "mcp.json");
|
|
928
|
+
const mcpText = '{"mcpServers":{"context7":{"command":"npx","args":["context7-mcp"]}}}';
|
|
929
|
+
writeFileSync(mcpPath, mcpText);
|
|
930
|
+
const installer = join(f.root, "retire-adapter.mjs");
|
|
931
|
+
writeFileSync(installer, [
|
|
932
|
+
"#!/usr/bin/env node",
|
|
933
|
+
'import { readFileSync, writeFileSync } from "node:fs";',
|
|
934
|
+
'import { join } from "node:path";',
|
|
935
|
+
'const home = process.env.PI_CODING_AGENT_DIR;',
|
|
936
|
+
'const settingsPath = join(home, "settings.json");',
|
|
937
|
+
'const settings = JSON.parse(readFileSync(settingsPath, "utf8"));',
|
|
938
|
+
'settings.packages = settings.packages.filter(p => p !== "npm:pi-mcp-adapter");',
|
|
939
|
+
'writeFileSync(settingsPath, JSON.stringify(settings));',
|
|
940
|
+
'const npmPath = join(home, "npm", "package.json");',
|
|
941
|
+
'const manifest = JSON.parse(readFileSync(npmPath, "utf8"));',
|
|
942
|
+
'delete manifest.dependencies["pi-mcp-adapter"];',
|
|
943
|
+
'writeFileSync(npmPath, JSON.stringify(manifest));',
|
|
944
|
+
'console.log("installed");',
|
|
945
|
+
].join("\n"));
|
|
946
|
+
assert.equal(readFileSync(installer, "utf8").split("\n")[0], "#!/usr/bin/env node");
|
|
947
|
+
const args = mode === "link" ? ["--link", "setup"] : ["--home", target, "setup"];
|
|
948
|
+
const result = run({ ...f.env, PI_CODING_AGENT_DIR: target, GENTLE_SHELL_PI: setupMCPExecutable(f.piScript), GENTLE_SHELL_GENTLE_AI_BIN: setupMCPExecutable(installer) }, args);
|
|
949
|
+
assert.equal(result.status, 0, result.stderr);
|
|
950
|
+
assert.equal(result.stdout, "installed\n");
|
|
951
|
+
assert.equal(result.stderr, `gentle-shell: provisioning ${target} with the gentle-ai companion packages\n` +
|
|
952
|
+
`gentle-shell: WARNING: Pi built-in MCP is disabled in ${settingsPath}; pi-mcp-adapter is absent or inactive, so servers in ${mcpPath} will not load. If you want these servers enabled, remove -builtin:mcp from extensions in ${settingsPath}, then restart Pi. If MCP is intentionally disabled, keep the setting.\n`);
|
|
953
|
+
assert.deepEqual(JSON.parse(readFileSync(settingsPath, "utf8")), { ...settings, packages: ["npm:other"] });
|
|
954
|
+
assert.deepEqual(JSON.parse(readFileSync(npmPath, "utf8")), { dependencies: { other: "1.0.0" } });
|
|
955
|
+
assert.equal(readFileSync(mcpPath, "utf8"), mcpText);
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
test("setup MCP migration keeps enabled, unconfigured and dry-run homes unchanged", async (t) => {
|
|
961
|
+
for (const scenario of ["enabled", "unconfigured", "dry-run", "active-adapter"] as const) {
|
|
962
|
+
await t.test(scenario, (t) => {
|
|
963
|
+
const f = fixture(t);
|
|
964
|
+
const target = join(f.home, ".pi", "agent");
|
|
965
|
+
mkdirSync(target, { recursive: true });
|
|
966
|
+
const settingsPath = join(target, "settings.json");
|
|
967
|
+
const settingsText = JSON.stringify({ extensions: scenario === "enabled" ? [] : ["-builtin:mcp"], packages: scenario === "active-adapter" ? ["npm:pi-mcp-adapter@3.0.0"] : [] });
|
|
968
|
+
writeFileSync(settingsPath, settingsText);
|
|
969
|
+
const mcpPath = join(target, "mcp.json");
|
|
970
|
+
const mcpText = JSON.stringify({ mcpServers: scenario === "unconfigured" ? {} : { context7: { command: "npx" } } });
|
|
971
|
+
writeFileSync(mcpPath, mcpText);
|
|
972
|
+
const installer = join(f.root, "fake-gentle-ai.mjs");
|
|
973
|
+
writeGentleAiScript(installer);
|
|
974
|
+
const dryRun = scenario === "dry-run";
|
|
975
|
+
const result = run({ ...f.env, PI_CODING_AGENT_DIR: target, GENTLE_SHELL_PI: setupMCPExecutable(f.piScript), GENTLE_SHELL_GENTLE_AI_BIN: setupMCPExecutable(installer) }, ["--link", "setup", ...(dryRun ? ["--dry-run"] : [])]);
|
|
976
|
+
assert.equal(result.status, 0, result.stderr);
|
|
977
|
+
assert.deepEqual(JSON.parse(result.stdout).args, ["install", "--agent", "pi", "--scope", "global", ...(dryRun ? ["--dry-run"] : [])]);
|
|
978
|
+
assert.doesNotMatch(result.stderr, /WARNING:|built-in MCP/);
|
|
979
|
+
assert.equal(readFileSync(settingsPath, "utf8"), settingsText);
|
|
980
|
+
assert.equal(readFileSync(mcpPath, "utf8"), mcpText);
|
|
981
|
+
});
|
|
982
|
+
}
|
|
983
|
+
});
|
|
984
|
+
|
|
985
|
+
test("setup MCP migration warns when adapter resource loading is disabled", async (t) => {
|
|
986
|
+
for (const adapter of [
|
|
987
|
+
{ source: "npm:pi-mcp-adapter", autoload: false },
|
|
988
|
+
{ source: "npm:pi-mcp-adapter", autoload: false, extensions: ["!**"] },
|
|
989
|
+
{ source: "npm:pi-mcp-adapter", extensions: ["!**"] },
|
|
990
|
+
{ source: "npm:pi-mcp-adapter", extensions: ["index.ts"] },
|
|
991
|
+
]) {
|
|
992
|
+
await t.test(JSON.stringify(adapter), (t) => {
|
|
993
|
+
const f = fixture(t);
|
|
994
|
+
const target = join(f.home, ".pi", "agent");
|
|
995
|
+
mkdirSync(target, { recursive: true });
|
|
996
|
+
const settingsPath = join(target, "settings.json");
|
|
997
|
+
const uncertain = "extensions" in adapter && adapter.extensions.includes("index.ts");
|
|
998
|
+
const settingsText = JSON.stringify({ extensions: ["-builtin:mcp"], packages: [adapter] });
|
|
999
|
+
writeFileSync(settingsPath, settingsText);
|
|
1000
|
+
const mcpPath = join(target, "mcp.json");
|
|
1001
|
+
const mcpText = '{"mcpServers":{"context7":{"command":"npx"}}}';
|
|
1002
|
+
writeFileSync(mcpPath, mcpText);
|
|
1003
|
+
const installer = join(f.root, "fake-gentle-ai.mjs");
|
|
1004
|
+
writeGentleAiScript(installer);
|
|
1005
|
+
const result = run({ ...f.env, PI_CODING_AGENT_DIR: target, GENTLE_SHELL_PI: setupMCPExecutable(f.piScript), GENTLE_SHELL_GENTLE_AI_BIN: setupMCPExecutable(installer) }, ["--link", "setup"]);
|
|
1006
|
+
assert.equal(result.status, 0, result.stderr);
|
|
1007
|
+
assert.deepEqual(JSON.parse(result.stdout).args, ["install", "--agent", "pi", "--scope", "global"]);
|
|
1008
|
+
const diagnosis = uncertain
|
|
1009
|
+
? "pi-mcp-adapter activity cannot be confirmed from its extension filters, so servers in " + mcpPath + " may not load"
|
|
1010
|
+
: "pi-mcp-adapter is absent or inactive, so servers in " + mcpPath + " will not load";
|
|
1011
|
+
assert.equal(result.stderr, `gentle-shell: provisioning ${target} with the gentle-ai companion packages\n` +
|
|
1012
|
+
`gentle-shell: WARNING: Pi built-in MCP is disabled in ${settingsPath}; ${diagnosis}. If you want these servers enabled, remove -builtin:mcp from extensions in ${settingsPath}, then restart Pi. If MCP is intentionally disabled, keep the setting.\n`);
|
|
1013
|
+
assert.equal(readFileSync(settingsPath, "utf8"), settingsText);
|
|
1014
|
+
assert.equal(readFileSync(mcpPath, "utf8"), mcpText);
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
|
|
850
1019
|
// --- setup subcommand's self-heal for a missing package-local binary -------
|
|
851
1020
|
//
|
|
852
1021
|
// `npm install -g <tarball>` on a machine whose npm config disables lifecycle
|
|
@@ -1676,6 +1845,81 @@ test("an empty or nonexistent --home is still auto-provisioned", (t) => {
|
|
|
1676
1845
|
assert.equal(readFileSync(counterPath, "utf8").trim().split("\n").length, 1, "a fresh --home must still be auto-provisioned");
|
|
1677
1846
|
});
|
|
1678
1847
|
|
|
1848
|
+
// #2106: both installers finish with `gentle-shell setup`; the first launch
|
|
1849
|
+
// after it must not install the companion packages again.
|
|
1850
|
+
// Gentle AI requires a `pi` on its PATH and runs `pi install npm:gentle-pi`.
|
|
1851
|
+
// When gentle-shell runs a Pi that is not itself on PATH (the adjacent
|
|
1852
|
+
// package, or GENTLE_SHELL_PI), setup must give Gentle AI that same Pi.
|
|
1853
|
+
test("setup gives Gentle AI a `pi` on its PATH that runs the same Pi gentle-shell resolved", { skip: process.platform === "win32" }, (t) => {
|
|
1854
|
+
const f = fixture(t);
|
|
1855
|
+
const probe = join(f.root, "pi-from-gentle-ai.txt");
|
|
1856
|
+
const gentleAiScript = join(f.root, "fake-gentle-ai.mjs");
|
|
1857
|
+
writeFileSync(gentleAiScript, ["#!/usr/bin/env node", "import { spawnSync } from 'node:child_process';", "import { writeFileSync } from 'node:fs';",
|
|
1858
|
+
"const pi = spawnSync('pi', ['--version'], { encoding: 'utf8' });",
|
|
1859
|
+
`writeFileSync(${JSON.stringify(probe)}, JSON.stringify({ status: pi.status, error: pi.error?.code ?? null, stdout: pi.stdout }));`,
|
|
1860
|
+
"process.exit(0);", ""].join("\n"), { mode: 0o755 });
|
|
1861
|
+
// No `pi` anywhere on the user's PATH: only node and the system tools.
|
|
1862
|
+
const temp = join(f.root, "tmp");
|
|
1863
|
+
mkdirSync(temp);
|
|
1864
|
+
const env = { ...f.env, TMPDIR: temp, PATH: [dirname(process.execPath), "/usr/bin", "/bin"].join(":"), GENTLE_SHELL_GENTLE_AI_BIN: gentleAiScript, GENTLE_SHELL_GENTLE_AI_PIN: "3.6.0" };
|
|
1865
|
+
|
|
1866
|
+
const result = run(env, ["setup"]);
|
|
1867
|
+
assert.equal(result.status, 0, result.stderr);
|
|
1868
|
+
assert.deepEqual(JSON.parse(readFileSync(probe, "utf8")), { status: 0, error: null, stdout: "0.99.1\n" });
|
|
1869
|
+
// The launcher is temporary: nothing is left behind in the temp folder it used.
|
|
1870
|
+
assert.deepEqual(readdirSync(temp), []);
|
|
1871
|
+
});
|
|
1872
|
+
|
|
1873
|
+
test("setup without a usable temp folder runs as before, without the temporary pi", { skip: process.platform === "win32" }, (t) => {
|
|
1874
|
+
const f = fixture(t);
|
|
1875
|
+
const gentleAiScript = join(f.root, "fake-gentle-ai.mjs");
|
|
1876
|
+
writeGentleAiScriptCountingRuns(gentleAiScript, join(f.root, "runs.log"));
|
|
1877
|
+
const env = { ...f.env, TMPDIR: join(f.root, "missing-tmp"), GENTLE_SHELL_GENTLE_AI_BIN: gentleAiScript, GENTLE_SHELL_GENTLE_AI_PIN: "3.6.0" };
|
|
1878
|
+
const result = run(env, ["setup"]);
|
|
1879
|
+
assert.equal(result.status, 0, result.stderr);
|
|
1880
|
+
assert.doesNotMatch(result.stderr, /mkdtemp|gentle-shell-pi-/);
|
|
1881
|
+
});
|
|
1882
|
+
|
|
1883
|
+
test("a successful manual setup records the isolated home, so the first launch does not set it up again", (t) => {
|
|
1884
|
+
const f = fixture(t);
|
|
1885
|
+
const gentleAiScript = join(f.root, "fake-gentle-ai.mjs");
|
|
1886
|
+
const counterPath = join(f.root, "gentle-ai-runs.log");
|
|
1887
|
+
writeGentleAiScriptCountingRuns(gentleAiScript, counterPath);
|
|
1888
|
+
const env = enableAutoProvision({ ...f.env, GENTLE_SHELL_GENTLE_AI_BIN: gentleAiScript, GENTLE_SHELL_GENTLE_AI_PIN: "3.6.0" });
|
|
1889
|
+
|
|
1890
|
+
const setup = run(env, ["setup"]);
|
|
1891
|
+
assert.equal(setup.status, 0, setup.stderr);
|
|
1892
|
+
const config = JSON.parse(readFileSync(join(f.home, ".gentle-shell", "config.json"), "utf8"));
|
|
1893
|
+
const homeKey = realpathSync(f.gentleShellHome);
|
|
1894
|
+
assert.equal(config.provisioned[homeKey].gentleAi, "3.6.0");
|
|
1895
|
+
assert.equal(config.provisioned[homeKey].gentlePi, ownGentlePiVersion());
|
|
1896
|
+
|
|
1897
|
+
const launch = run(env, ["--mode", "rpc"]);
|
|
1898
|
+
assert.equal(launch.status, 0, launch.stderr);
|
|
1899
|
+
assert.doesNotMatch(launch.stderr, /first run in/);
|
|
1900
|
+
assert.equal(readFileSync(counterPath, "utf8").trim().split("\n").length, 1, "gentle-ai ran only for the manual setup");
|
|
1901
|
+
});
|
|
1902
|
+
|
|
1903
|
+
test("manual setup records nothing for a dry run, a failed setup or pi's own default agent home", (t) => {
|
|
1904
|
+
const f = fixture(t);
|
|
1905
|
+
const configPath = join(f.home, ".gentle-shell", "config.json");
|
|
1906
|
+
const provisioned = () => (existsSync(configPath) ? JSON.parse(readFileSync(configPath, "utf8")).provisioned ?? {} : {});
|
|
1907
|
+
const gentleAiScript = join(f.root, "fake-gentle-ai.mjs");
|
|
1908
|
+
const failingScript = join(f.root, "failing-gentle-ai.mjs");
|
|
1909
|
+
writeGentleAiScriptCountingRuns(gentleAiScript, join(f.root, "runs.log"));
|
|
1910
|
+
writeGentleAiScriptCountingRuns(failingScript, join(f.root, "failed-runs.log"), 3);
|
|
1911
|
+
const env = { ...f.env, PI_CODING_AGENT_DIR: undefined, GENTLE_SHELL_GENTLE_AI_BIN: gentleAiScript, GENTLE_SHELL_GENTLE_AI_PIN: "3.6.0" };
|
|
1912
|
+
|
|
1913
|
+
assert.equal(run(env, ["setup", "--dry-run"]).status, 0);
|
|
1914
|
+
assert.deepEqual(provisioned(), {}, "dry run");
|
|
1915
|
+
assert.notEqual(run({ ...env, GENTLE_SHELL_GENTLE_AI_BIN: failingScript }, ["setup"]).status, 0);
|
|
1916
|
+
assert.deepEqual(provisioned(), {}, "failed setup");
|
|
1917
|
+
const defaultPiHome = join(f.home, ".pi", "agent");
|
|
1918
|
+
const own = run(env, ["--home", defaultPiHome, "setup"]);
|
|
1919
|
+
assert.equal(own.status, 0, own.stderr);
|
|
1920
|
+
assert.deepEqual(provisioned(), {}, "pi's own default agent home is never recorded, so it is never auto-provisioned later");
|
|
1921
|
+
});
|
|
1922
|
+
|
|
1679
1923
|
test("a --home equal to pi's own default agent home is never auto-provisioned, even when empty", (t) => {
|
|
1680
1924
|
const f = fixture(t);
|
|
1681
1925
|
const defaultPiHome = join(f.home, ".pi", "agent");
|