@asterxsk/kiln 0.2.0 → 0.3.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/LICENSE +21 -21
- package/README.md +3 -18
- package/agent/extensions/AGENTS.md +68 -68
- package/agent/extensions/ask-user/install.ps1 +4 -0
- package/agent/extensions/ask-user/install.sh +3 -0
- package/agent/extensions/background-terminals/install.ps1 +4 -0
- package/agent/extensions/background-terminals/install.sh +3 -0
- package/agent/extensions/destructive/install.ps1 +4 -0
- package/agent/extensions/destructive/install.sh +3 -0
- package/agent/extensions/file-search/install.ps1 +4 -0
- package/agent/extensions/file-search/install.sh +3 -0
- package/agent/extensions/goal/install.ps1 +4 -0
- package/agent/extensions/goal/install.sh +3 -0
- package/agent/extensions/herdr-agent-state.ts +257 -0
- package/agent/extensions/kiln-update/README.md +25 -0
- package/agent/extensions/kiln-update/index.ts +99 -0
- package/agent/extensions/kiln-update/install.ps1 +27 -0
- package/agent/extensions/kiln-update/install.sh +24 -0
- package/agent/extensions/modelconf/install.ps1 +4 -0
- package/agent/extensions/modelconf/install.sh +3 -0
- package/agent/extensions/shared/install.ps1 +4 -0
- package/agent/extensions/shared/install.sh +3 -0
- package/agent/extensions/skillsconf/install.ps1 +4 -0
- package/agent/extensions/skillsconf/install.sh +3 -0
- package/agent/extensions/statusline/install.ps1 +4 -0
- package/agent/extensions/statusline/install.sh +3 -0
- package/agent/extensions/subagents/install.ps1 +4 -0
- package/agent/extensions/subagents/install.sh +3 -0
- package/agent/extensions/taste/index.ts +443 -0
- package/agent/extensions/taste/install.ps1 +27 -0
- package/agent/extensions/taste/install.sh +24 -0
- package/agent/extensions/todo/install.ps1 +4 -0
- package/agent/extensions/todo/install.sh +3 -0
- package/agent/extensions/trim-context/install.ps1 +4 -0
- package/agent/extensions/trim-context/install.sh +3 -0
- package/agent/version.txt +1 -0
- package/agent.bak.20260905-190020/AGENTS.md +67 -0
- package/agent.bak.20260905-190020/README.md +5 -0
- package/agent.bak.20260905-190020/extensions/ask-user/index.ts +418 -0
- package/agent.bak.20260905-190020/extensions/ask-user/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/ask-user/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/ask-user/package-lock.json +769 -0
- package/agent.bak.20260905-190020/extensions/ask-user/package.json +19 -0
- package/agent.bak.20260905-190020/extensions/ask-user/prompt.ts +45 -0
- package/agent.bak.20260905-190020/extensions/ask-user/tsconfig.json +7 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/docs/implementation-guide.md +942 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/index.ts +629 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/package-lock.json +769 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/package.json +17 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/domain.ts +87 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/manager.ts +907 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/output.ts +84 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/prompt.ts +142 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/result-delivery.ts +27 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/runtime.ts +36 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/ui/output-view.ts +79 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/ui/ps.ts +621 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/src/widget-order.ts +121 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/test/manager.test.ts +735 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/test/output.test.ts +109 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/test/prompt.test.ts +125 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/test/ps.test.ts +82 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/test/result-delivery.test.ts +44 -0
- package/agent.bak.20260905-190020/extensions/background-terminals/tsconfig.json +7 -0
- package/agent.bak.20260905-190020/extensions/destructive/README.md +34 -0
- package/agent.bak.20260905-190020/extensions/destructive/index.ts +124 -0
- package/agent.bak.20260905-190020/extensions/destructive/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/destructive/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/file-search/index.ts +459 -0
- package/agent.bak.20260905-190020/extensions/file-search/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/file-search/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/file-search/package-lock.json +2253 -0
- package/agent.bak.20260905-190020/extensions/file-search/package.json +23 -0
- package/agent.bak.20260905-190020/extensions/file-search/src/args.ts +122 -0
- package/agent.bak.20260905-190020/extensions/file-search/src/binaries.ts +422 -0
- package/agent.bak.20260905-190020/extensions/file-search/src/output.ts +126 -0
- package/agent.bak.20260905-190020/extensions/file-search/src/process.ts +146 -0
- package/agent.bak.20260905-190020/extensions/file-search/src/prompt.ts +52 -0
- package/agent.bak.20260905-190020/extensions/file-search/test/index.spec.ts +443 -0
- package/agent.bak.20260905-190020/extensions/file-search/tsconfig.json +7 -0
- package/agent.bak.20260905-190020/extensions/goal/README.md +50 -0
- package/agent.bak.20260905-190020/extensions/goal/index.ts +155 -0
- package/agent.bak.20260905-190020/extensions/goal/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/goal/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/kiln-update/README.md +25 -0
- package/agent.bak.20260905-190020/extensions/kiln-update/index.ts +99 -0
- package/agent.bak.20260905-190020/extensions/kiln-update/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/kiln-update/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/modelconf/PLAN.md +915 -0
- package/agent.bak.20260905-190020/extensions/modelconf/README.md +66 -0
- package/agent.bak.20260905-190020/extensions/modelconf/index.ts +296 -0
- package/agent.bak.20260905-190020/extensions/modelconf/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/modelconf/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/modelconf/package-lock.json +1809 -0
- package/agent.bak.20260905-190020/extensions/modelconf/package.json +13 -0
- package/agent.bak.20260905-190020/extensions/modelconf/src/fuzzy.ts +26 -0
- package/agent.bak.20260905-190020/extensions/modelconf/src/glob.ts +13 -0
- package/agent.bak.20260905-190020/extensions/modelconf/src/persistence.test.ts +46 -0
- package/agent.bak.20260905-190020/extensions/modelconf/src/persistence.ts +164 -0
- package/agent.bak.20260905-190020/extensions/modelconf/src/ui/ModelConfView.test.ts +75 -0
- package/agent.bak.20260905-190020/extensions/modelconf/src/ui/ModelConfView.ts +1101 -0
- package/agent.bak.20260905-190020/extensions/modelconf/tsconfig.json +15 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/CHANGELOG.md +690 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/LICENSE +21 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/README.md +470 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/SECURITY.md +5 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/activity.ts +101 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/auth-fetch.ts +148 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/banner.png +0 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/brightdata-unlocker.ts +272 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/chrome-cookies.ts +669 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/content-find.ts +139 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/credential-source.ts +191 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/data-uri-sanitize.ts +406 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/datalab-pdf-extract.ts +568 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/declared-web-links.ts +173 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/evidence/CONTRACT-EVIDENCE.md +496 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/evidence/contract-probe.mjs +140 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/exa.ts +526 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/extract.ts +1196 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/feature-config.ts +29 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/fetch-params.ts +111 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-adc.ts +298 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-api.ts +353 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-pdf-extract.ts +108 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-search.ts +21 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-url-context.ts +128 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-web-config.ts +101 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/gemini-web.ts +487 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/github-api.ts +197 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/github-extract.ts +746 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/github-issue-pr.ts +700 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/index.ts +1737 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/package-lock.json +5808 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/package.json +64 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/page-query.ts +96 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/pdf-extract.ts +409 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/pi-web-fetch-demo.mp4 +0 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/promise-try.d.ts +7 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/query-rewrite.ts +51 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/render-search-error.ts +170 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/rsc-extract.ts +338 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/search-types.ts +20 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/source-check.ts +282 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/ssrf-protection.ts +526 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/storage.ts +521 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/summary-model-scope.ts +125 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/auth-fetch.test.mjs +208 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/brightdata-unlocker.test.mjs +840 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/chrome-cookie-extraction.test.mjs +441 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/config-path.test.mjs +283 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/content-find.test.mjs +25 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/credential-source.test.mjs +118 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/data-uri-sanitize.test.mjs +210 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/datalab-pdf-extract.test.mjs +552 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/declared-web-links.test.mjs +212 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-answer-storage.test.mjs +40 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-cache-storage.test.mjs +334 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-content-domain-policy.test.mjs +95 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-modes.test.mjs +53 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-not-found-guidance.test.mjs +92 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-params.test.mjs +86 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-render-call.test.mjs +34 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/fetch-routing.test.mjs +173 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-adc-auth.test.mjs +257 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-api-transport.test.mjs +170 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-pdf-extract.test.mjs +133 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-web-cookie-opt-in.test.mjs +178 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/gemini-web-header-overflow.test.mjs +148 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/get-search-content.test.mjs +223 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/github-extract.test.mjs +378 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/github-issue-pr.test.mjs +565 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/inline-content-config.test.mjs +99 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/lazy-extract-load.test.mjs +118 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/local-video-oversize.test.mjs +52 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/package-typebox-dependency.test.mjs +50 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/page-query.test.mjs +51 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/pdf-config.test.mjs +140 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/pdf-extract.test.mjs +500 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/proxy-transport.test.mjs +286 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/query-rewrite.test.mjs +52 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/rsc-fallback.test.mjs +102 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/search-error-render.test.mjs +152 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/search-providers.test.mjs +274 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/source-check.test.mjs +179 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/ssrf-allow-ranges-config.test.mjs +205 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/ssrf-protection.test.mjs +456 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/summary-model-scope.test.mjs +106 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/tool-registration-config.test.mjs +182 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/web-search-answer-render.test.mjs +66 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/test/youtube-extract-errors.test.mjs +64 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/tsconfig.json +11 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/utils.ts +451 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/video-extract.ts +392 -0
- package/agent.bak.20260905-190020/extensions/pi-web-access/youtube-extract.ts +328 -0
- package/agent.bak.20260905-190020/extensions/shared/activity-status.ts +31 -0
- package/agent.bak.20260905-190020/extensions/shared/child-session.ts +148 -0
- package/agent.bak.20260905-190020/extensions/shared/context-utilization.ts +47 -0
- package/agent.bak.20260905-190020/extensions/shared/dashboard-state.ts +99 -0
- package/agent.bak.20260905-190020/extensions/shared/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/shared/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/shared/test/child-session.test.ts +270 -0
- package/agent.bak.20260905-190020/extensions/shared/test/context-utilization.test.ts +48 -0
- package/agent.bak.20260905-190020/extensions/shared/test/tool-call-timeout.test.ts +117 -0
- package/agent.bak.20260905-190020/extensions/shared/test/widget-order.test.ts +167 -0
- package/agent.bak.20260905-190020/extensions/shared/tool-call-timeout.ts +104 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/README.md +74 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/index.ts +92 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/package-lock.json +1809 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/package.json +18 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/delete-skill.test.ts +64 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/delete-skill.ts +45 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/filter.test.ts +80 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/filter.ts +74 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/fuzzy.ts +26 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/persistence.test.ts +72 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/persistence.ts +169 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/SkillConfView.test.ts +337 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/SkillConfView.ts +758 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/text-input.ts +91 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/src/ui/tui-helpers.ts +144 -0
- package/agent.bak.20260905-190020/extensions/skillsconf/tsconfig.json +15 -0
- package/agent.bak.20260905-190020/extensions/statusline/index.ts +282 -0
- package/agent.bak.20260905-190020/extensions/statusline/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/statusline/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/subagents/docs/design-plan.md +568 -0
- package/agent.bak.20260905-190020/extensions/subagents/docs/effect-v4-extension-guide.md +354 -0
- package/agent.bak.20260905-190020/extensions/subagents/docs/effect-v4-notes.md +571 -0
- package/agent.bak.20260905-190020/extensions/subagents/index.ts +826 -0
- package/agent.bak.20260905-190020/extensions/subagents/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/subagents/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/subagents/package-lock.json +2244 -0
- package/agent.bak.20260905-190020/extensions/subagents/package.json +19 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/backend.ts +73 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/backends/claude.ts +701 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/backends/codex.ts +1060 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/backends/pi.ts +575 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/backends/stub.ts +300 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/by-the-way.ts +21 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/domain.ts +253 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/format.ts +74 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/manager.ts +736 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/prompt.ts +92 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/result-delivery.ts +20 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/runtime.ts +53 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/ui/takeover.ts +583 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/ui/transcript.ts +201 -0
- package/agent.bak.20260905-190020/extensions/subagents/src/widget-order.ts +121 -0
- package/agent.bak.20260905-190020/extensions/subagents/test/by-the-way.test.ts +29 -0
- package/agent.bak.20260905-190020/extensions/subagents/test/claude.test.ts +119 -0
- package/agent.bak.20260905-190020/extensions/subagents/test/codex.test.ts +102 -0
- package/agent.bak.20260905-190020/extensions/subagents/test/context-usage.test.ts +107 -0
- package/agent.bak.20260905-190020/extensions/subagents/test/manager.test.ts +276 -0
- package/agent.bak.20260905-190020/extensions/subagents/test/result-delivery.test.ts +27 -0
- package/agent.bak.20260905-190020/extensions/subagents/test/takeover.test.ts +29 -0
- package/agent.bak.20260905-190020/extensions/subagents/tsconfig.json +7 -0
- package/agent.bak.20260905-190020/extensions/taste/index.ts +443 -0
- package/agent.bak.20260905-190020/extensions/taste/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/taste/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/todo/AGENTS.md +38 -0
- package/agent.bak.20260905-190020/extensions/todo/LICENSE +21 -0
- package/agent.bak.20260905-190020/extensions/todo/config.ts +55 -0
- package/agent.bak.20260905-190020/extensions/todo/index.ts +151 -0
- package/agent.bak.20260905-190020/extensions/todo/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/todo/install.sh +21 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/de.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/en.json +15 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/es.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/fr.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/pt-BR.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/pt.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/ru.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/uk.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/locales/zh.json +17 -0
- package/agent.bak.20260905-190020/extensions/todo/package-lock.json +3358 -0
- package/agent.bak.20260905-190020/extensions/todo/package.json +67 -0
- package/agent.bak.20260905-190020/extensions/todo/state/i18n-bridge.ts +64 -0
- package/agent.bak.20260905-190020/extensions/todo/state/invariants.ts +20 -0
- package/agent.bak.20260905-190020/extensions/todo/state/replay.ts +38 -0
- package/agent.bak.20260905-190020/extensions/todo/state/selectors.ts +107 -0
- package/agent.bak.20260905-190020/extensions/todo/state/state-reducer.ts +326 -0
- package/agent.bak.20260905-190020/extensions/todo/state/state.ts +18 -0
- package/agent.bak.20260905-190020/extensions/todo/state/store.ts +82 -0
- package/agent.bak.20260905-190020/extensions/todo/state/task-graph.ts +57 -0
- package/agent.bak.20260905-190020/extensions/todo/todo-overlay.ts +204 -0
- package/agent.bak.20260905-190020/extensions/todo/todo.ts +155 -0
- package/agent.bak.20260905-190020/extensions/todo/tool/response-envelope.ts +109 -0
- package/agent.bak.20260905-190020/extensions/todo/tool/types.ts +206 -0
- package/agent.bak.20260905-190020/extensions/todo/view/format.ts +177 -0
- package/agent.bak.20260905-190020/extensions/todo/widget-order.ts +121 -0
- package/agent.bak.20260905-190020/extensions/trim-context/README.md +54 -0
- package/agent.bak.20260905-190020/extensions/trim-context/index.ts +487 -0
- package/agent.bak.20260905-190020/extensions/trim-context/install.ps1 +23 -0
- package/agent.bak.20260905-190020/extensions/trim-context/install.sh +21 -0
- package/agent.bak.20260905-190020/keybindings.json +7 -0
- package/bin/kiln.js +588 -471
- package/package.json +27 -27
- package/agent/install.ps1 +0 -637
- package/agent/install.sh +0 -620
package/bin/kiln.js
CHANGED
|
@@ -1,472 +1,589 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// kiln installer —
|
|
3
|
-
// 1) Install/update pi (@earendil-works/pi-coding-agent)
|
|
4
|
-
// 2) Install pi packages (pi-context-usage, @baretread/pi-forge)
|
|
5
|
-
// 3) Install custom config (AGENTS.md, keybindings, extensions …)
|
|
6
|
-
// 4) Install per-extension npm deps via each extension's own installer
|
|
7
|
-
//
|
|
8
|
-
// Usage:
|
|
9
|
-
// npx @asterxsk/kiln --yes
|
|
10
|
-
// npm i -g @asterxsk/kiln && kiln --yes
|
|
11
|
-
// bunx @asterxsk/kiln --yes
|
|
12
|
-
// node bin/kiln.js --target /tmp/pi-test --skip-pi --skip-packages --yes
|
|
13
|
-
// node bin/kiln.js --overwrite-settings # replace settings.json (asks by default)
|
|
14
|
-
//
|
|
15
|
-
// Already-installed items are skipped; outdated global packages are updated.
|
|
16
|
-
// Only one timestamped backup (<target>.bak.*) is kept; the clone temp dir
|
|
17
|
-
// under ~/.pi/tmp/kiln-* is always removed.
|
|
18
|
-
//
|
|
19
|
-
// Safe to re-run. Managed files are force-overwritten; per-user files
|
|
20
|
-
// (settings.json, taste.md, auth.json, sessions, etc.) are preserved.
|
|
21
|
-
"use strict";
|
|
22
|
-
|
|
23
|
-
const { spawn, spawnSync } = require("node:child_process");
|
|
24
|
-
const fs = require("node:fs");
|
|
25
|
-
const os = require("node:os");
|
|
26
|
-
const path = require("node:path");
|
|
27
|
-
const crypto = require("node:crypto");
|
|
28
|
-
|
|
29
|
-
const PI_PACKAGE = "@earendil-works/pi-coding-agent";
|
|
30
|
-
const NODE_MIN = [22, 19, 0];
|
|
31
|
-
const DEFAULT_REPO = "https://github.com/asterxsk/kiln";
|
|
32
|
-
const DEFAULT_BRANCH = "main";
|
|
33
|
-
const PACKAGES = ["pi-context-usage@latest", "@baretread/pi-forge@latest"];
|
|
34
|
-
const SETTINGS_PACKAGES = ["npm:pi-context-usage", "npm:@baretread/pi-forge"];
|
|
35
|
-
|
|
36
|
-
const startTime = Date.now();
|
|
37
|
-
let clonedTmp = "";
|
|
38
|
-
let tmpLog = "";
|
|
39
|
-
let ok = true; // hard failures flip this; warnings don't
|
|
40
|
-
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
} catch
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
// ──
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if (
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
else
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// kiln installer (npm) — installs pi, the forge + context packages, and the curated agent config.
|
|
3
|
+
// 1) Install/update pi (@earendil-works/pi-coding-agent)
|
|
4
|
+
// 2) Install pi packages (pi-context-usage, @baretread/pi-forge)
|
|
5
|
+
// 3) Install custom config (AGENTS.md, keybindings, extensions …)
|
|
6
|
+
// 4) Install per-extension npm deps via each extension's own installer
|
|
7
|
+
//
|
|
8
|
+
// Usage:
|
|
9
|
+
// npx @asterxsk/kiln --yes
|
|
10
|
+
// npm i -g @asterxsk/kiln && kiln --yes
|
|
11
|
+
// bunx @asterxsk/kiln --yes
|
|
12
|
+
// node bin/kiln.js --target /tmp/pi-test --skip-pi --skip-packages --yes
|
|
13
|
+
// node bin/kiln.js --overwrite-settings # replace settings.json (asks by default)
|
|
14
|
+
//
|
|
15
|
+
// Already-installed items are skipped; outdated global packages are updated.
|
|
16
|
+
// Only one timestamped backup (<target>.bak.*) is kept; the clone temp dir
|
|
17
|
+
// under ~/.pi/tmp/kiln-* is always removed.
|
|
18
|
+
//
|
|
19
|
+
// Safe to re-run. Managed files are force-overwritten; per-user files
|
|
20
|
+
// (settings.json, taste.md, auth.json, sessions, etc.) are preserved.
|
|
21
|
+
"use strict";
|
|
22
|
+
|
|
23
|
+
const { spawn, spawnSync } = require("node:child_process");
|
|
24
|
+
const fs = require("node:fs");
|
|
25
|
+
const os = require("node:os");
|
|
26
|
+
const path = require("node:path");
|
|
27
|
+
const crypto = require("node:crypto");
|
|
28
|
+
|
|
29
|
+
const PI_PACKAGE = "@earendil-works/pi-coding-agent";
|
|
30
|
+
const NODE_MIN = [22, 19, 0];
|
|
31
|
+
const DEFAULT_REPO = "https://github.com/asterxsk/kiln";
|
|
32
|
+
const DEFAULT_BRANCH = "main";
|
|
33
|
+
const PACKAGES = ["pi-context-usage@latest", "@baretread/pi-forge@latest"];
|
|
34
|
+
const SETTINGS_PACKAGES = ["npm:pi-context-usage", "npm:@baretread/pi-forge"];
|
|
35
|
+
|
|
36
|
+
const startTime = Date.now();
|
|
37
|
+
let clonedTmp = "";
|
|
38
|
+
let tmpLog = "";
|
|
39
|
+
let ok = true; // hard failures flip this; warnings don't
|
|
40
|
+
|
|
41
|
+
// npm >=11 rejects `npm_config_allow_scripts` inherited from a parent npm/npx
|
|
42
|
+
// process ("--allow-scripts is not allowed in project-scoped installs"). This
|
|
43
|
+
// happens when kiln itself runs under npx/npm exec and the user has
|
|
44
|
+
// `allow-scripts` in ~/.npmrc: npm forwards it as env to every child, so each
|
|
45
|
+
// per-extension `npm ci` fails with EALLOWSCRIPTS. Drop it; file-based config
|
|
46
|
+
// (~/.npmrc, per-package `allowScripts`) still applies to child npm processes.
|
|
47
|
+
for (const k of ["npm_config_allow_scripts", "NPM_CONFIG_ALLOW_SCRIPTS"]) delete process.env[k];
|
|
48
|
+
|
|
49
|
+
// ── summary buckets ─────────────────────────────────────────────────────
|
|
50
|
+
// Every completed item is recorded here; the final Summary prints them all.
|
|
51
|
+
const buckets = { skipped: [], updated: [], installed: [], "npm modules": [] };
|
|
52
|
+
const FRIENDLY = { "pi-context-usage": "context extension", "@baretread/pi-forge": "forge extension" };
|
|
53
|
+
function note(bucket, name) { buckets[bucket].push(name); }
|
|
54
|
+
function prettyPkg(spec) { return FRIENDLY[spec.replace(/^npm:/, "")] || spec; }
|
|
55
|
+
|
|
56
|
+
// ── args ────────────────────────────────────────────────────────────────
|
|
57
|
+
function parseArgs(argv) {
|
|
58
|
+
const o = {
|
|
59
|
+
repo: process.env.PI_CONFIG_REPO || "",
|
|
60
|
+
branch: process.env.PI_CONFIG_BRANCH || DEFAULT_BRANCH,
|
|
61
|
+
target: process.env.PI_AGENT_DIR || "",
|
|
62
|
+
skipPi: false, skipPackages: false, yes: false, local: false,
|
|
63
|
+
settingsMode: "ask", // ask | overwrite | keep
|
|
64
|
+
};
|
|
65
|
+
for (let i = 0; i < argv.length; i++) {
|
|
66
|
+
const a = argv[i];
|
|
67
|
+
if (a === "--repo") o.repo = argv[++i] ?? "";
|
|
68
|
+
else if (a === "--branch") o.branch = argv[++i] ?? "";
|
|
69
|
+
else if (a === "--target") o.target = argv[++i] ?? "";
|
|
70
|
+
else if (a === "--skip-pi") o.skipPi = true;
|
|
71
|
+
else if (a === "--skip-packages") o.skipPackages = true;
|
|
72
|
+
else if (a === "--local") o.local = true;
|
|
73
|
+
else if (a === "--overwrite-settings") o.settingsMode = "overwrite";
|
|
74
|
+
else if (a === "--keep-settings") o.settingsMode = "keep";
|
|
75
|
+
else if (a === "--yes" || a === "-y") o.yes = true;
|
|
76
|
+
else if (a === "--help" || a === "-h") {
|
|
77
|
+
console.log("Usage: kiln [--repo URL] [--branch BRANCH] [--target DIR] [--local] [--skip-pi] [--skip-packages] [--overwrite-settings|--keep-settings] [--yes]");
|
|
78
|
+
process.exit(0);
|
|
79
|
+
} else if (a === "--") break;
|
|
80
|
+
else if (a.startsWith("-")) { console.error(`unknown arg: ${a}`); process.exit(1); }
|
|
81
|
+
}
|
|
82
|
+
if (!o.repo) o.repo = DEFAULT_REPO;
|
|
83
|
+
return o;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ── output ──────────────────────────────────────────────────────────────
|
|
87
|
+
const isTTY = !!process.stdout.isTTY && process.env.TERM !== "dumb";
|
|
88
|
+
const C = isTTY
|
|
89
|
+
? { reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m", green: "\x1b[32m", yellow: "\x1b[33m", red: "\x1b[31m", cyan: "\x1b[36m", gray: "\x1b[90m" }
|
|
90
|
+
: { reset: "", bold: "", dim: "", green: "", yellow: "", red: "", cyan: "", gray: "" };
|
|
91
|
+
const line = (s) => process.stdout.write(s + "\n");
|
|
92
|
+
const log = (s) => { try { fs.appendFileSync(tmpLog, s + "\n"); } catch {} };
|
|
93
|
+
// Mid-run output: plain lines when piped, swallowed (→ log + summary) when live.
|
|
94
|
+
function detail(s) { try { log(String(s).replace(/\x1b\[[0-9;]*m/g, "")); } catch {} if (!isTTY) line(s); }
|
|
95
|
+
|
|
96
|
+
// ── forge art + live status ─────────────────────────────────────────────
|
|
97
|
+
const ART = [
|
|
98
|
+
" █▌ █▌",
|
|
99
|
+
" ██████████████",
|
|
100
|
+
" ██ ██",
|
|
101
|
+
" ██ ██",
|
|
102
|
+
" ██ ██",
|
|
103
|
+
" ██ ██ ",
|
|
104
|
+
];
|
|
105
|
+
// Phase 0 = ember (dim), phase 1 = stoked (bright). Non-TTY → plain art.
|
|
106
|
+
function artLines(phase) {
|
|
107
|
+
if (!isTTY) return ART.slice();
|
|
108
|
+
const m = phase ? 1 : 2; // bold vs dim
|
|
109
|
+
const cream = `\x1b[${m};38;5;230m`, orange = `\x1b[${m};38;5;208m`, brown = `\x1b[${m};38;5;94m`, R = "\x1b[0m";
|
|
110
|
+
return [
|
|
111
|
+
` ${cream}█▌${R} ${cream}█▌${R}`,
|
|
112
|
+
` ${orange}██████████████${R}`,
|
|
113
|
+
` ${orange}██${R} ${orange}██${R}`,
|
|
114
|
+
` ${orange}██${R} ${orange}██${R}`,
|
|
115
|
+
` ${orange}██${R} ${orange}██${R}`,
|
|
116
|
+
` ${brown}██ ██${R} `,
|
|
117
|
+
];
|
|
118
|
+
}
|
|
119
|
+
const SPIN = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠰", "⠠", "⠦", "⠧", "⠇", "⠏"];
|
|
120
|
+
let liveLabel = "", liveTimer = null, liveTickN = 0;
|
|
121
|
+
function liveDraw() {
|
|
122
|
+
if (!isTTY) return;
|
|
123
|
+
const rows = [...artLines(liveTickN % 10 < 5 ? 0 : 1), ` ${C.yellow}${SPIN[liveTickN % SPIN.length]}${C.reset} ${C.dim}${liveLabel}${C.reset}`];
|
|
124
|
+
process.stdout.write("\x1b[7A");
|
|
125
|
+
for (const r of rows) process.stdout.write(`\r\x1b[K${r}\n`);
|
|
126
|
+
}
|
|
127
|
+
function liveStart() {
|
|
128
|
+
if (!isTTY) return;
|
|
129
|
+
process.stdout.write("\n".repeat(7));
|
|
130
|
+
liveTickN = 0;
|
|
131
|
+
liveDraw();
|
|
132
|
+
liveTimer = setInterval(() => { liveTickN++; liveDraw(); }, 100);
|
|
133
|
+
}
|
|
134
|
+
function liveSet(label) { liveLabel = label; }
|
|
135
|
+
function liveStop() {
|
|
136
|
+
if (!isTTY) return;
|
|
137
|
+
if (liveTimer) { clearInterval(liveTimer); liveTimer = null; }
|
|
138
|
+
liveTickN = 5; // stoked final frame
|
|
139
|
+
liveDraw();
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function title() {
|
|
143
|
+
line("");
|
|
144
|
+
line(` ${C.bold}◆ Pi Setup${C.reset}`);
|
|
145
|
+
line(` ${C.dim}custom agent config · pi + forge + extensions${C.reset}`);
|
|
146
|
+
if (!isTTY) for (const r of artLines(0)) line(` ${r}`);
|
|
147
|
+
line("");
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Run a command: the live status line shows it on TTY, plain lines when piped. Output always → log.
|
|
151
|
+
function runStep(step, label, cmd, args, opts = {}) {
|
|
152
|
+
return new Promise((resolve) => {
|
|
153
|
+
liveSet(`[${step}] ${label}`);
|
|
154
|
+
if (!isTTY) line(` · ${label}`);
|
|
155
|
+
const child = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], shell: false, ...opts });
|
|
156
|
+
child.stdout.on("data", (d) => log(d.toString().trimEnd()));
|
|
157
|
+
child.stderr.on("data", (d) => log(d.toString().trimEnd()));
|
|
158
|
+
child.on("error", (e) => { log(`spawn failed: ${e.message}`); resolve(1); });
|
|
159
|
+
child.on("close", (code) => { resolve(code ?? 1); });
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function have(cmd) {
|
|
164
|
+
try {
|
|
165
|
+
if (process.platform === "win32") return spawnSync("where", [cmd], { stdio: "ignore" }).status === 0;
|
|
166
|
+
return spawnSync("sh", ["-c", `command -v "${cmd}"`], { stdio: "ignore" }).status === 0;
|
|
167
|
+
} catch { return false; }
|
|
168
|
+
}
|
|
169
|
+
function cmdOut(cmd, args) {
|
|
170
|
+
try { return spawnSync(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).stdout.trim(); }
|
|
171
|
+
catch { return ""; }
|
|
172
|
+
}
|
|
173
|
+
function sleep(ms) { return new Promise((r) => setTimeout(r, ms)); }
|
|
174
|
+
// Quote one shell word (cmd.exe + sh compatible for our controlled args).
|
|
175
|
+
const q = (a) => (/[\s"']/.test(a) ? `"${a.replace(/"/g, '\\"')}"` : a);
|
|
176
|
+
function cmdOutShell(command) {
|
|
177
|
+
try { return spawnSync(command, { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], shell: true }).stdout.trim(); }
|
|
178
|
+
catch { return ""; }
|
|
179
|
+
}
|
|
180
|
+
// npm on Windows is npm.cmd (a batch shim) — it cannot be spawned directly,
|
|
181
|
+
// so run it through the shell as a single pre-quoted command string.
|
|
182
|
+
function npmStep(step, label, args) {
|
|
183
|
+
if (process.platform === "win32") return runStep(step, label, "npm.cmd " + args.map(q).join(" "), [], { shell: true });
|
|
184
|
+
return runStep(step, label, "npm", args);
|
|
185
|
+
}
|
|
186
|
+
// pi is also a cmd shim on Windows — same shell treatment.
|
|
187
|
+
function piOut(args) {
|
|
188
|
+
if (process.platform === "win32") return cmdOutShell("pi " + args.map(q).join(" "));
|
|
189
|
+
return cmdOut("pi", args);
|
|
190
|
+
}
|
|
191
|
+
function piStep(label, args) {
|
|
192
|
+
if (process.platform === "win32") return runStep("pkg", label, "pi " + args.map(q).join(" "), [], { shell: true });
|
|
193
|
+
return runStep("pkg", label, "pi", args);
|
|
194
|
+
}
|
|
195
|
+
const npmVer = process.platform === "win32" ? cmdOutShell("npm.cmd --version") : cmdOut("npm", ["--version"]);
|
|
196
|
+
|
|
197
|
+
// Installed global version of a package ("" when not installed).
|
|
198
|
+
function globalPkgVersion(name) {
|
|
199
|
+
const out = process.platform === "win32"
|
|
200
|
+
? cmdOutShell(`npm.cmd ls -g "${name}" --depth=0`)
|
|
201
|
+
: cmdOut("npm", ["ls", "-g", name, "--depth=0"]);
|
|
202
|
+
const m = out.match(new RegExp(name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + "@(\\S+)"));
|
|
203
|
+
return m ? m[1].replace(/[^0-9A-Za-z.+-].*$/, "") : "";
|
|
204
|
+
}
|
|
205
|
+
// Latest registry version ("" when offline / unknown).
|
|
206
|
+
function latestPkgVersion(name) {
|
|
207
|
+
const out = process.platform === "win32"
|
|
208
|
+
? cmdOutShell(`npm.cmd view "${name}" version`)
|
|
209
|
+
: cmdOut("npm", ["view", name, "version"]);
|
|
210
|
+
const v = (out || "").split(/\s+/)[0].trim();
|
|
211
|
+
return /^[0-9][0-9A-Za-z.+-]*$/.test(v) ? v : "";
|
|
212
|
+
}
|
|
213
|
+
// Synchronous Y/N prompt (default N). False when non-interactive.
|
|
214
|
+
function askYN(question) {
|
|
215
|
+
try {
|
|
216
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) return false;
|
|
217
|
+
process.stdout.write(question);
|
|
218
|
+
const buf = Buffer.alloc(16);
|
|
219
|
+
const n = fs.readSync(0, buf, 0, 16);
|
|
220
|
+
const ans = buf.slice(0, n).toString().trim().toLowerCase();
|
|
221
|
+
return ans === "y" || ans === "yes";
|
|
222
|
+
} catch { return false; }
|
|
223
|
+
}
|
|
224
|
+
// Keep only the newest sibling backup (<target>.bak.*); delete the rest.
|
|
225
|
+
function pruneBackups(targetDir, keep) {
|
|
226
|
+
try {
|
|
227
|
+
const parent = path.dirname(targetDir);
|
|
228
|
+
const base = path.basename(targetDir);
|
|
229
|
+
const keepBase = keep ? path.basename(keep) : "";
|
|
230
|
+
for (const b of fs.readdirSync(parent)) {
|
|
231
|
+
if (!b.startsWith(base + ".bak.")) continue;
|
|
232
|
+
if (b === keepBase) continue;
|
|
233
|
+
try { fs.rmSync(path.join(parent, b), { recursive: true, force: true }); } catch {}
|
|
234
|
+
}
|
|
235
|
+
} catch (e) { log(`prune backups failed: ${e.message}`); }
|
|
236
|
+
}
|
|
237
|
+
// Remove stale clone dirs (~/.pi/tmp/kiln-*) except the active one.
|
|
238
|
+
function sweepStaleCloneTmp(tmpBase, active) {
|
|
239
|
+
try {
|
|
240
|
+
for (const e of fs.readdirSync(tmpBase)) {
|
|
241
|
+
if (!e.startsWith("kiln-")) continue;
|
|
242
|
+
if (active && e === path.basename(active)) continue;
|
|
243
|
+
try { fs.rmSync(path.join(tmpBase, e), { recursive: true, force: true }); } catch {}
|
|
244
|
+
}
|
|
245
|
+
} catch {}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Recursive copy, excluding names (node_modules, .git). Returns false on error.
|
|
249
|
+
function copyTree(src, dst, exclude = new Set(["node_modules", ".git"])) {
|
|
250
|
+
try {
|
|
251
|
+
if (path.resolve(src) === path.resolve(dst)) return true;
|
|
252
|
+
fs.rmSync(dst, { recursive: true, force: true });
|
|
253
|
+
fs.mkdirSync(dst, { recursive: true });
|
|
254
|
+
for (const e of fs.readdirSync(src, { withFileTypes: true })) {
|
|
255
|
+
if (exclude.has(e.name)) continue;
|
|
256
|
+
const s = path.join(src, e.name), d = path.join(dst, e.name);
|
|
257
|
+
if (e.isDirectory()) { if (!copyTree(s, d, exclude)) return false; }
|
|
258
|
+
else if (e.isFile()) fs.copyFileSync(s, d);
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
} catch (e) { log(`copy failed ${src} → ${dst}: ${e.message}`); return false; }
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function resolveTarget(opt) {
|
|
265
|
+
if (opt) return opt;
|
|
266
|
+
return path.join(os.homedir(), ".pi", "agent");
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Source root: bundled payload (npm tarball or dev checkout) → else git clone.
|
|
270
|
+
function resolveSourceRoot(args) {
|
|
271
|
+
const pkgRoot = path.resolve(__dirname, ".."); // bin/ → package root
|
|
272
|
+
const cands = [path.join(pkgRoot, "agent"), pkgRoot, process.cwd(), path.join(process.cwd(), "agent")];
|
|
273
|
+
for (const r of cands) {
|
|
274
|
+
if (fs.existsSync(path.join(r, "extensions")) && fs.existsSync(path.join(r, "AGENTS.md"))) return r;
|
|
275
|
+
}
|
|
276
|
+
if (args.local) throw new Error(`local checkout not found (tried: ${cands.join(", ")})`);
|
|
277
|
+
const base = path.join(os.homedir(), ".pi", "tmp");
|
|
278
|
+
fs.mkdirSync(base, { recursive: true });
|
|
279
|
+
const tmp = path.join(base, "kiln-" + crypto.randomBytes(4).toString("hex"));
|
|
280
|
+
fs.mkdirSync(tmp, { recursive: true });
|
|
281
|
+
liveSet(`cloning repo…`);
|
|
282
|
+
detail(` · cloning ${args.repo} (branch ${args.branch})`);
|
|
283
|
+
const r = spawnSync("git", ["clone", "--depth", "1", "--branch", args.branch, args.repo, tmp],
|
|
284
|
+
{ stdio: ["ignore", "pipe", "pipe"], encoding: "utf8", env: { ...process.env, GIT_TERMINAL_PROMPT: "0", GCM_INTERACTIVE: "never", GIT_ASKPASS: "echo" } });
|
|
285
|
+
if (r.stdout) log(r.stdout.trimEnd());
|
|
286
|
+
if (r.stderr) log(r.stderr.trimEnd());
|
|
287
|
+
if (r.status !== 0) throw new Error(`git clone failed (exit ${r.status}). See ${tmpLog}`);
|
|
288
|
+
clonedTmp = tmp;
|
|
289
|
+
if (fs.existsSync(path.join(tmp, "agent"))) return path.join(tmp, "agent");
|
|
290
|
+
return tmp;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
async function main() {
|
|
294
|
+
const args = parseArgs(process.argv.slice(2));
|
|
295
|
+
const tmpBase = path.join(os.homedir(), ".pi", "tmp");
|
|
296
|
+
fs.mkdirSync(tmpBase, { recursive: true });
|
|
297
|
+
tmpLog = path.join(tmpBase, `pi-setup-${crypto.randomBytes(4).toString("hex")}.log`);
|
|
298
|
+
fs.writeFileSync(tmpLog, "");
|
|
299
|
+
process.on("exit", () => { if (clonedTmp && clonedTmp.startsWith(path.join(tmpBase, "kiln-"))) fs.rmSync(clonedTmp, { recursive: true, force: true }); });
|
|
300
|
+
|
|
301
|
+
title();
|
|
302
|
+
const targetDir = resolveTarget(args.target);
|
|
303
|
+
// Settings decision up front (only when interactive with no explicit flag).
|
|
304
|
+
if (args.settingsMode === "ask" && !args.yes && process.stdin.isTTY && process.stdout.isTTY
|
|
305
|
+
&& fs.existsSync(path.join(targetDir, "settings.json"))) {
|
|
306
|
+
args.settingsMode = askYN(" Overwrite settings (y/n): ") ? "overwrite" : "keep";
|
|
307
|
+
} else if (args.settingsMode === "ask" && (args.yes || !process.stdin.isTTY)) {
|
|
308
|
+
args.settingsMode = "keep";
|
|
309
|
+
}
|
|
310
|
+
line(`${C.dim} target ${C.reset}${targetDir}`);
|
|
311
|
+
line(`${C.dim} repo ${C.reset}${args.repo} ${C.dim}(${args.branch})${C.reset}`);
|
|
312
|
+
line(`${C.dim} log ${C.reset}${tmpLog}\n`);
|
|
313
|
+
|
|
314
|
+
// ── preflight ──
|
|
315
|
+
const nodeVer = process.versions.node.split("-")[0];
|
|
316
|
+
const nv = nodeVer.split(".").map(Number);
|
|
317
|
+
const nodeOk = nv[0] > NODE_MIN[0] || (nv[0] === NODE_MIN[0] && (nv[1] > NODE_MIN[1] || (nv[1] === NODE_MIN[1] && nv[2] >= NODE_MIN[2])));
|
|
318
|
+
if (!nodeOk) {
|
|
319
|
+
line(`${C.yellow} ⚠ Node ${nodeVer} < ${NODE_MIN.join(".")} — please upgrade to Node ${NODE_MIN.join(".")}+${C.reset}`);
|
|
320
|
+
if (!args.yes) { line(" continue anyway in 3s…"); await sleep(3000); }
|
|
321
|
+
}
|
|
322
|
+
if (!have("npm")) { line(`${C.red} ✖ npm not found (Node installed but npm missing)${C.reset}`); process.exit(1); }
|
|
323
|
+
line(`${C.dim} node ${nodeVer} · npm ${npmVer} · ${cmdOut("git", ["--version"]) || "git n/a"}${C.reset}\n`);
|
|
324
|
+
|
|
325
|
+
// git is only needed when we must clone (no bundled payload and not --local)
|
|
326
|
+
const pkgAgent = path.join(path.resolve(__dirname, ".."), "agent");
|
|
327
|
+
const haveSource = fs.existsSync(path.join(pkgAgent, "extensions")) && fs.existsSync(path.join(pkgAgent, "AGENTS.md"));
|
|
328
|
+
if (!have("git") && !haveSource && !args.local) { line(`${C.red} ✖ git not found — required to fetch config${C.reset}`); process.exit(1); }
|
|
329
|
+
liveStart();
|
|
330
|
+
|
|
331
|
+
// ── [1/4] pi ──
|
|
332
|
+
if (args.skipPi) {
|
|
333
|
+
detail(` · Install pi — skipped`);
|
|
334
|
+
note("skipped", "pi");
|
|
335
|
+
} else if (have("pi")) {
|
|
336
|
+
const installed = globalPkgVersion(PI_PACKAGE) || cmdOut("pi", ["--version"]).replace(/^[vV]/, "").trim();
|
|
337
|
+
const latest = latestPkgVersion(PI_PACKAGE);
|
|
338
|
+
if (installed && latest && installed === latest) {
|
|
339
|
+
detail(` · pi ${installed} — already installed, skipping`);
|
|
340
|
+
note("skipped", "pi");
|
|
341
|
+
} else if (installed && !latest) {
|
|
342
|
+
detail(` · pi ${installed} — already installed, skipping version check (offline)`);
|
|
343
|
+
note("skipped", "pi");
|
|
344
|
+
} else {
|
|
345
|
+
const label = installed ? `updating pi ${installed} → ${latest || "latest"}` : `installing pi`;
|
|
346
|
+
const code = await npmStep("1/4", label, ["install", "-g", `${PI_PACKAGE}@latest`, "--no-audit", "--no-fund", "--min-release-age=0"]);
|
|
347
|
+
if (code === 0) {
|
|
348
|
+
detail(` · ${label} — ${cmdOut("pi", ["--version"]) || "?"}`);
|
|
349
|
+
note(installed ? "updated" : "installed", "pi");
|
|
350
|
+
} else {
|
|
351
|
+
detail(` ✖ ${label} failed (exit ${code}) — see log`);
|
|
352
|
+
note("updated", "pi (failed — see log)");
|
|
353
|
+
ok = false;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
} else {
|
|
357
|
+
const label = `installing pi`;
|
|
358
|
+
const code = await npmStep("1/4", label, ["install", "-g", `${PI_PACKAGE}@latest`, "--no-audit", "--no-fund", "--min-release-age=0"]);
|
|
359
|
+
if (code === 0) {
|
|
360
|
+
detail(` · ${label} — ${cmdOut("pi", ["--version"]) || "?"}`);
|
|
361
|
+
note("installed", "pi");
|
|
362
|
+
} else {
|
|
363
|
+
detail(` ✖ ${label} failed (exit ${code}) — see log`);
|
|
364
|
+
note("installed", "pi (failed — see log)");
|
|
365
|
+
ok = false;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
// ── [2/4] pi packages (global best-effort; pi-side ensure runs after step 3) ──
|
|
369
|
+
if (args.skipPackages) {
|
|
370
|
+
detail(` · pi packages — skipped`);
|
|
371
|
+
} else {
|
|
372
|
+
const bare = PACKAGES.map((p) => p.replace(/@latest$/, ""));
|
|
373
|
+
const need = [];
|
|
374
|
+
for (const name of bare) {
|
|
375
|
+
const inst = globalPkgVersion(name);
|
|
376
|
+
const latest = latestPkgVersion(name);
|
|
377
|
+
if (inst && latest && inst === latest) {
|
|
378
|
+
detail(` · ${name}@${inst} already installed globally, skipping`);
|
|
379
|
+
} else if (inst && !latest) {
|
|
380
|
+
detail(` · ${name}@${inst} already installed globally, skipping version check (offline)`);
|
|
381
|
+
} else {
|
|
382
|
+
if (inst) detail(` · ${name} ${inst} → ${latest || "latest"} — will update globally`);
|
|
383
|
+
need.push(`${name}@latest`);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
if (!need.length) {
|
|
387
|
+
detail(` · pi packages — already installed globally, skipping`);
|
|
388
|
+
} else {
|
|
389
|
+
const label = `installing ${need.join(" ")} (-g)`;
|
|
390
|
+
const code = await npmStep("2/4", label, ["install", "-g", ...need, "--no-audit", "--no-fund"]);
|
|
391
|
+
if (code === 0) detail(` · pi packages — global install done`);
|
|
392
|
+
else detail(` ⚠ ${label} exit ${code} — continuing (pi-side ensure runs later)`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
// ── [3/4] custom config ──
|
|
396
|
+
try {
|
|
397
|
+
const sourceRoot = resolveSourceRoot(args);
|
|
398
|
+
detail(` · source ${sourceRoot}`);
|
|
399
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
400
|
+
let bak = "";
|
|
401
|
+
if (fs.existsSync(path.join(targetDir, "AGENTS.md")) || fs.existsSync(path.join(targetDir, "extensions"))) {
|
|
402
|
+
const d = new Date(), p2 = (n) => String(n).padStart(2, "0");
|
|
403
|
+
bak = `${targetDir}.bak.${d.getFullYear()}${p2(d.getMonth() + 1)}${p2(d.getDate())}-${p2(d.getHours())}${p2(d.getMinutes())}${p2(d.getSeconds())}`;
|
|
404
|
+
detail(` · backup ${targetDir}/extensions → ${bak}`);
|
|
405
|
+
fs.mkdirSync(bak, { recursive: true });
|
|
406
|
+
for (const f of ["AGENTS.md", "keybindings.json", "README.md"]) {
|
|
407
|
+
const s = path.join(targetDir, f);
|
|
408
|
+
if (fs.existsSync(s)) try { fs.copyFileSync(s, path.join(bak, f)); } catch {}
|
|
409
|
+
}
|
|
410
|
+
const extSrc = path.join(targetDir, "extensions");
|
|
411
|
+
if (fs.existsSync(extSrc)) {
|
|
412
|
+
fs.mkdirSync(path.join(bak, "extensions"), { recursive: true });
|
|
413
|
+
for (const e of fs.readdirSync(extSrc, { withFileTypes: true })) {
|
|
414
|
+
if (!e.isDirectory()) continue;
|
|
415
|
+
copyTree(path.join(extSrc, e.name), path.join(bak, "extensions", e.name));
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
pruneBackups(targetDir, bak); // only one backup at a time
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
let copied = 0;
|
|
422
|
+
const selfInstall = path.resolve(sourceRoot) === path.resolve(targetDir);
|
|
423
|
+
if (selfInstall) detail(` · source == target — skipping file copy (self-install)`);
|
|
424
|
+
for (const f of ["AGENTS.md", "keybindings.json", "README.md"]) {
|
|
425
|
+
if (!fs.existsSync(path.join(sourceRoot, f))) continue;
|
|
426
|
+
if (!selfInstall) fs.copyFileSync(path.join(sourceRoot, f), path.join(targetDir, f));
|
|
427
|
+
copied++;
|
|
428
|
+
}
|
|
429
|
+
let freshSettings = false;
|
|
430
|
+
const settingsPath = path.join(targetDir, "settings.json");
|
|
431
|
+
const repoSettings = path.join(sourceRoot, "settings.json");
|
|
432
|
+
if (!fs.existsSync(settingsPath) && fs.existsSync(repoSettings)) {
|
|
433
|
+
fs.copyFileSync(repoSettings, settingsPath);
|
|
434
|
+
detail(` · created settings.json from repo defaults`);
|
|
435
|
+
note("installed", "settings.json");
|
|
436
|
+
freshSettings = true;
|
|
437
|
+
} else if (fs.existsSync(settingsPath)) {
|
|
438
|
+
const mode = args.settingsMode === "ask" ? "keep" : args.settingsMode; // decided up front
|
|
439
|
+
if (mode === "overwrite" && fs.existsSync(repoSettings)) {
|
|
440
|
+
if (bak) { try { fs.copyFileSync(settingsPath, path.join(bak, "settings.json")); } catch {} }
|
|
441
|
+
fs.copyFileSync(repoSettings, settingsPath);
|
|
442
|
+
detail(` · overwrote settings.json from repo defaults`);
|
|
443
|
+
note("updated", "settings.json");
|
|
444
|
+
freshSettings = true;
|
|
445
|
+
} else {
|
|
446
|
+
detail(` · kept existing settings.json`);
|
|
447
|
+
note("skipped", "settings.json");
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (freshSettings) {
|
|
451
|
+
try {
|
|
452
|
+
const p = path.join(targetDir, "settings.json");
|
|
453
|
+
const j = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
454
|
+
j.packages = j.packages || [];
|
|
455
|
+
let changed = false;
|
|
456
|
+
for (const pkg of SETTINGS_PACKAGES) if (!j.packages.includes(pkg)) { j.packages.push(pkg); changed = true; }
|
|
457
|
+
if (changed) { fs.writeFileSync(p, JSON.stringify(j, null, 2) + "\n"); detail(" · patched settings.json packages → forge + context"); }
|
|
458
|
+
} catch {}
|
|
459
|
+
}
|
|
460
|
+
for (const t of ["taste.md", "taste", "taste.json"]) {
|
|
461
|
+
const tp = path.join(targetDir, t);
|
|
462
|
+
if (fs.existsSync(tp)) detail(` · kept existing ${t}`);
|
|
463
|
+
else if (fs.existsSync(path.join(sourceRoot, t))) {
|
|
464
|
+
const s = path.join(sourceRoot, t);
|
|
465
|
+
if (fs.statSync(s).isDirectory()) copyTree(s, tp, new Set());
|
|
466
|
+
else fs.copyFileSync(s, tp);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
if (fs.existsSync(path.join(sourceRoot, "extensions"))) {
|
|
471
|
+
fs.mkdirSync(path.join(targetDir, "extensions"), { recursive: true });
|
|
472
|
+
for (const e of fs.readdirSync(path.join(sourceRoot, "extensions"), { withFileTypes: true })) {
|
|
473
|
+
if (!e.isDirectory() || e.name.endsWith(".md")) continue;
|
|
474
|
+
const dst = path.join(targetDir, "extensions", e.name);
|
|
475
|
+
const existed = fs.existsSync(dst);
|
|
476
|
+
if (copyTree(path.join(sourceRoot, "extensions", e.name), dst)) { copied++; note(existed ? "updated" : "installed", e.name); }
|
|
477
|
+
else detail(` ⚠ copy extensions/${e.name} failed`);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (!selfInstall && fs.existsSync(path.join(sourceRoot, "themes"))) {
|
|
482
|
+
fs.rmSync(path.join(targetDir, "themes"), { recursive: true, force: true });
|
|
483
|
+
fs.mkdirSync(path.join(targetDir, "themes"), { recursive: true });
|
|
484
|
+
for (const e of fs.readdirSync(path.join(sourceRoot, "themes"), { withFileTypes: true })) {
|
|
485
|
+
if (e.name === ".pi" || e.name === "nul") continue;
|
|
486
|
+
const s = path.join(sourceRoot, "themes", e.name), dd = path.join(targetDir, "themes", e.name);
|
|
487
|
+
if (e.isDirectory()) copyTree(s, dd, new Set());
|
|
488
|
+
else if (e.isFile()) try { fs.copyFileSync(s, dd); } catch {}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
detail(` · custom config — ${copied} items → ${targetDir}`);
|
|
493
|
+
if (clonedTmp) { fs.rmSync(clonedTmp, { recursive: true, force: true }); clonedTmp = ""; }
|
|
494
|
+
sweepStaleCloneTmp(tmpBase, ""); // delete any leftover kiln-* temp dirs
|
|
495
|
+
const repoReadme = path.resolve(sourceRoot, "..", "README.md");
|
|
496
|
+
const parentReadme = path.resolve(targetDir, "..", "README.md");
|
|
497
|
+
if (repoReadme !== parentReadme && fs.existsSync(repoReadme)) {
|
|
498
|
+
try { fs.copyFileSync(repoReadme, parentReadme); } catch {}
|
|
499
|
+
}
|
|
500
|
+
} catch (e) {
|
|
501
|
+
detail(` ✖ custom config failed: ${e.message}`);
|
|
502
|
+
ok = false;
|
|
503
|
+
}
|
|
504
|
+
// ── [4/4] per-extension deps ──
|
|
505
|
+
const extRoot = path.join(targetDir, "extensions");
|
|
506
|
+
if (!fs.existsSync(extRoot)) {
|
|
507
|
+
detail(` ⚠ no extensions found at ${extRoot}`);
|
|
508
|
+
} else {
|
|
509
|
+
const failed = [];
|
|
510
|
+
let installed = 0, skipped = 0;
|
|
511
|
+
for (const e of fs.readdirSync(extRoot, { withFileTypes: true })) {
|
|
512
|
+
if (!e.isDirectory() || e.name.endsWith(".md")) continue;
|
|
513
|
+
const dir = path.join(extRoot, e.name), label = `extensions/${e.name}`;
|
|
514
|
+
if (fs.existsSync(path.join(dir, "node_modules"))) {
|
|
515
|
+
detail(` · ${label} — already installed, skipping`);
|
|
516
|
+
note("skipped", e.name);
|
|
517
|
+
skipped++;
|
|
518
|
+
continue;
|
|
519
|
+
}
|
|
520
|
+
const hasPkg = fs.existsSync(path.join(dir, "package.json"));
|
|
521
|
+
const sh = path.join(dir, "install.sh"), ps1 = path.join(dir, "install.ps1");
|
|
522
|
+
let code;
|
|
523
|
+
if (process.platform === "win32" && fs.existsSync(ps1)) {
|
|
524
|
+
const shell = have("pwsh") ? "pwsh" : "powershell";
|
|
525
|
+
code = await runStep("4/4", label, shell, ["-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ps1]);
|
|
526
|
+
} else if (process.platform !== "win32" && fs.existsSync(sh)) {
|
|
527
|
+
code = await runStep("4/4", label, "sh", [sh]);
|
|
528
|
+
} else if (hasPkg) {
|
|
529
|
+
const a = ["--prefix", dir, fs.existsSync(path.join(dir, "package-lock.json")) ? "ci" : "install", "--no-audit", "--no-fund"];
|
|
530
|
+
code = await npmStep("4/4", label, a);
|
|
531
|
+
} else {
|
|
532
|
+
detail(` · ${label} — no package.json, skipping`);
|
|
533
|
+
continue;
|
|
534
|
+
}
|
|
535
|
+
if (code === 0) { detail(` · ${label} — done`); if (hasPkg) note("npm modules", e.name); installed++; }
|
|
536
|
+
else { detail(` ✖ ${label} failed (exit ${code}) — see log`); note("npm modules", `${e.name} (failed — see log)`); failed.push(e.name); }
|
|
537
|
+
}
|
|
538
|
+
if (!failed.length) detail(` · extension deps — ${installed} installed, ${skipped} skipped`);
|
|
539
|
+
else detail(` ⚠ extension deps ${failed.length} failed: ${failed.join(", ")} — see log`);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// ── pi package ensure (forge + context actually registered with pi) ──
|
|
543
|
+
// `pi list` is truth: global installs mean nothing to pi (it uses its own dir).
|
|
544
|
+
const defaultDir = path.join(os.homedir(), ".pi", "agent");
|
|
545
|
+
if (args.skipPackages) {
|
|
546
|
+
for (const s of SETTINGS_PACKAGES) note("skipped", prettyPkg(s));
|
|
547
|
+
} else if (!have("pi")) {
|
|
548
|
+
detail(` ⚠ pi binary not found — packages registered for next launch`);
|
|
549
|
+
for (const s of SETTINGS_PACKAGES) note("skipped", prettyPkg(s));
|
|
550
|
+
} else if (path.resolve(targetDir) !== path.resolve(defaultDir)) {
|
|
551
|
+
detail(` · custom target — packages registered for next launch`);
|
|
552
|
+
for (const s of SETTINGS_PACKAGES) note("skipped", prettyPkg(s));
|
|
553
|
+
} else {
|
|
554
|
+
let list = "";
|
|
555
|
+
try { list = piOut(["list"]); } catch { list = ""; }
|
|
556
|
+
for (const spec of SETTINGS_PACKAGES) {
|
|
557
|
+
const pretty = prettyPkg(spec);
|
|
558
|
+
if (list.includes(spec)) { note("skipped", pretty); continue; }
|
|
559
|
+
const code = await piStep(`pi install ${spec}`, ["install", spec]);
|
|
560
|
+
let now = "";
|
|
561
|
+
try { now = piOut(["list"]); } catch { now = ""; }
|
|
562
|
+
if (code === 0 && now.includes(spec)) { detail(` · ${pretty} — registered with pi`); note("installed", pretty); }
|
|
563
|
+
else { detail(` ✖ ${pretty} not registered — see log (pi retries on next launch)`); note("updated", `${pretty} (failed — see log)`); }
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// ── summary ──
|
|
568
|
+
liveStop();
|
|
569
|
+
const secs = Math.round((Date.now() - startTime) / 1000);
|
|
570
|
+
const elapsed = secs >= 60 ? `${Math.floor(secs / 60)}m ${secs % 60}s` : `${secs}s`;
|
|
571
|
+
line("");
|
|
572
|
+
if (ok) line(`${C.green}${C.bold} ✓ Setup complete${C.reset} ${C.dim}→ ${targetDir}${C.reset}`);
|
|
573
|
+
else line(`${C.yellow}${C.bold} ⚠ Setup finished with warnings${C.reset} ${C.dim}see ${tmpLog}${C.reset}`);
|
|
574
|
+
line("");
|
|
575
|
+
line("Summary:");
|
|
576
|
+
line("");
|
|
577
|
+
for (const name of ["skipped", "updated", "installed", "npm modules"]) {
|
|
578
|
+
line(`[${name}]`);
|
|
579
|
+
const items = buckets[name];
|
|
580
|
+
if (!items.length) line("(none)");
|
|
581
|
+
else for (const item of items) line(item);
|
|
582
|
+
line("");
|
|
583
|
+
}
|
|
584
|
+
line(`Done in ${elapsed}`);
|
|
585
|
+
line(`${C.dim} log: ${tmpLog}${C.reset}\n`);
|
|
586
|
+
process.exitCode = ok ? 0 : 1;
|
|
587
|
+
}
|
|
588
|
+
|
|
472
589
|
main().catch((e) => { console.error(`\n ✖ ${e.message}`); process.exit(1); });
|