pi-usereq 0.4.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/.g.conf +20 -0
- package/.github/workflows/release-npm.yml +131 -0
- package/.gitignore +270 -0
- package/CHANGELOG.md +221 -0
- package/LICENSE +674 -0
- package/README.md +260 -0
- package/TODO.md +20 -0
- package/docs/pi.dev/agent-document-manifest.json +6399 -0
- package/docs/pi.dev/coding-agent-docs/compaction.md +394 -0
- package/docs/pi.dev/coding-agent-docs/custom-provider.md +596 -0
- package/docs/pi.dev/coding-agent-docs/development.md +71 -0
- package/docs/pi.dev/coding-agent-docs/extensions.md +2262 -0
- package/docs/pi.dev/coding-agent-docs/images/doom-extension.png +0 -0
- package/docs/pi.dev/coding-agent-docs/images/exy.png +0 -0
- package/docs/pi.dev/coding-agent-docs/images/interactive-mode.png +0 -0
- package/docs/pi.dev/coding-agent-docs/images/tree-view.png +0 -0
- package/docs/pi.dev/coding-agent-docs/json.md +82 -0
- package/docs/pi.dev/coding-agent-docs/keybindings.md +175 -0
- package/docs/pi.dev/coding-agent-docs/models.md +392 -0
- package/docs/pi.dev/coding-agent-docs/packages.md +218 -0
- package/docs/pi.dev/coding-agent-docs/prompt-templates.md +67 -0
- package/docs/pi.dev/coding-agent-docs/providers.md +195 -0
- package/docs/pi.dev/coding-agent-docs/rpc.md +1377 -0
- package/docs/pi.dev/coding-agent-docs/sdk.md +1124 -0
- package/docs/pi.dev/coding-agent-docs/session.md +412 -0
- package/docs/pi.dev/coding-agent-docs/settings.md +247 -0
- package/docs/pi.dev/coding-agent-docs/shell-aliases.md +13 -0
- package/docs/pi.dev/coding-agent-docs/skills.md +232 -0
- package/docs/pi.dev/coding-agent-docs/terminal-setup.md +106 -0
- package/docs/pi.dev/coding-agent-docs/termux.md +127 -0
- package/docs/pi.dev/coding-agent-docs/themes.md +295 -0
- package/docs/pi.dev/coding-agent-docs/tmux.md +61 -0
- package/docs/pi.dev/coding-agent-docs/tree.md +231 -0
- package/docs/pi.dev/coding-agent-docs/tui.md +887 -0
- package/docs/pi.dev/coding-agent-docs/windows.md +17 -0
- package/docs/pi.dev/mom-docs/artifacts-server.md +475 -0
- package/docs/pi.dev/mom-docs/events.md +307 -0
- package/docs/pi.dev/mom-docs/new.md +970 -0
- package/docs/pi.dev/mom-docs/sandbox.md +153 -0
- package/docs/pi.dev/mom-docs/slack-bot-minimal-guide.md +399 -0
- package/docs/pi.dev/mom-docs/v86.md +319 -0
- package/docs/pi.dev/pods-docs/gml-4.5.md +189 -0
- package/docs/pi.dev/pods-docs/gpt-oss.md +233 -0
- package/docs/pi.dev/pods-docs/implementation-plan.md +183 -0
- package/docs/pi.dev/pods-docs/kimi-k2.md +197 -0
- package/docs/pi.dev/pods-docs/models.md +116 -0
- package/docs/pi.dev/pods-docs/plan.md +166 -0
- package/docs/pi.dev/pods-docs/qwen3-coder.md +132 -0
- package/images/flowchart-bw.png +0 -0
- package/images/flowchart-bw.svg +102 -0
- package/images/flowchart.md +100 -0
- package/images/flowchart.png +0 -0
- package/images/flowchart.svg +3 -0
- package/package.json +46 -0
- package/req/docs/REFERENCES.md +4554 -0
- package/req/docs/REQUIREMENTS.md +475 -0
- package/req/docs/WORKFLOW.md +1059 -0
- package/scripts/debug-extension.ts +497 -0
- package/scripts/lib/extension-debug-harness.ts +450 -0
- package/scripts/lib/recording-extension-api.ts +786 -0
- package/scripts/lib/sdk-smoke.ts +503 -0
- package/scripts/pi-usereq-debug.sh +330 -0
- package/scripts/tool-args-to-params.ts +208 -0
- package/src/cli.ts +349 -0
- package/src/core/agent-tool-json.ts +621 -0
- package/src/core/compress-files.ts +72 -0
- package/src/core/compress-payload.ts +648 -0
- package/src/core/compress.ts +464 -0
- package/src/core/config.ts +272 -0
- package/src/core/doxygen-parser.ts +318 -0
- package/src/core/errors.ts +31 -0
- package/src/core/extension-status.ts +660 -0
- package/src/core/find-constructs.ts +319 -0
- package/src/core/find-payload.ts +915 -0
- package/src/core/generate-markdown.ts +120 -0
- package/src/core/path-context.ts +196 -0
- package/src/core/pi-notify.ts +430 -0
- package/src/core/pi-usereq-tools.ts +140 -0
- package/src/core/prompts.ts +184 -0
- package/src/core/reference-payload.ts +818 -0
- package/src/core/resources.ts +63 -0
- package/src/core/runtime-project-paths.ts +99 -0
- package/src/core/settings-menu.ts +233 -0
- package/src/core/source-analyzer.ts +1721 -0
- package/src/core/static-check.ts +674 -0
- package/src/core/token-counter.ts +729 -0
- package/src/core/tool-runner.ts +717 -0
- package/src/core/utils.ts +185 -0
- package/src/index.ts +2209 -0
- package/src/resources/guidelines/Google_C++_Style_Guide.md +3711 -0
- package/src/resources/guidelines/Google_Python_Style_Guide.md +3709 -0
- package/src/resources/prompts/analyze.md +130 -0
- package/src/resources/prompts/change.md +227 -0
- package/src/resources/prompts/check.md +139 -0
- package/src/resources/prompts/cover.md +219 -0
- package/src/resources/prompts/create.md +104 -0
- package/src/resources/prompts/fix.md +221 -0
- package/src/resources/prompts/flowchart.md +220 -0
- package/src/resources/prompts/implement.md +163 -0
- package/src/resources/prompts/new.md +226 -0
- package/src/resources/prompts/readme.md +182 -0
- package/src/resources/prompts/recreate.md +213 -0
- package/src/resources/prompts/refactor.md +213 -0
- package/src/resources/prompts/references.md +100 -0
- package/src/resources/prompts/renumber.md +119 -0
- package/src/resources/prompts/workflow.md +202 -0
- package/src/resources/prompts/write.md +99 -0
- package/src/resources/sounds/Machine-alert-beep-sound-effect.mp3 +0 -0
- package/src/resources/sounds/Soft-high-tech-notification-sound-effect.mp3 +0 -0
- package/src/resources/templates/Document_Source_Code_in_Doxygen_Style.md +130 -0
- package/src/resources/templates/HDT_Test_Authoring_Guide.md +318 -0
- package/src/resources/templates/Requirements_Template.md +78 -0
- package/tests/attended-results-scenarios.ts +758 -0
- package/tests/attended-results.test.ts +39 -0
- package/tests/cli-command-option-parity.test.ts +815 -0
- package/tests/debug-extension-harness.test.ts +463 -0
- package/tests/extension-registration.test.ts +2006 -0
- package/tests/fixtures/fixture_c.c +361 -0
- package/tests/fixtures/fixture_cpp.cpp +407 -0
- package/tests/fixtures/fixture_csharp.cs +411 -0
- package/tests/fixtures/fixture_elixir.ex +409 -0
- package/tests/fixtures/fixture_go.go +341 -0
- package/tests/fixtures/fixture_haskell.hs +250 -0
- package/tests/fixtures/fixture_java.java +430 -0
- package/tests/fixtures/fixture_javascript.js +383 -0
- package/tests/fixtures/fixture_kotlin.kt +451 -0
- package/tests/fixtures/fixture_lua.lua +276 -0
- package/tests/fixtures/fixture_perl.pl +310 -0
- package/tests/fixtures/fixture_php.php +433 -0
- package/tests/fixtures/fixture_python.py +502 -0
- package/tests/fixtures/fixture_ruby.rb +345 -0
- package/tests/fixtures/fixture_rust.rs +380 -0
- package/tests/fixtures/fixture_scala.scala +398 -0
- package/tests/fixtures/fixture_shell.sh +276 -0
- package/tests/fixtures/fixture_swift.swift +397 -0
- package/tests/fixtures/fixture_typescript.ts +434 -0
- package/tests/fixtures/fixture_zig.zig +295 -0
- package/tests/fixtures_attended_results/project/compress-line-numbers.json +5 -0
- package/tests/fixtures_attended_results/project/compress.json +5 -0
- package/tests/fixtures_attended_results/project/enable-static-check-invalid-command.json +5 -0
- package/tests/fixtures_attended_results/project/enable-static-check-valid.json +5 -0
- package/tests/fixtures_attended_results/project/files-static-check.json +5 -0
- package/tests/fixtures_attended_results/project/find-line-numbers.json +5 -0
- package/tests/fixtures_attended_results/project/find.json +5 -0
- package/tests/fixtures_attended_results/project/get-base-path.json +5 -0
- package/tests/fixtures_attended_results/project/git-check-clean.json +5 -0
- package/tests/fixtures_attended_results/project/git-check-dirty.json +5 -0
- package/tests/fixtures_attended_results/project/git-path.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-create-invalid.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-create-valid.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-delete-nonexistent.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-delete-valid.json +5 -0
- package/tests/fixtures_attended_results/project/git-wt-name.json +5 -0
- package/tests/fixtures_attended_results/project/references.json +5 -0
- package/tests/fixtures_attended_results/project/static-check.json +5 -0
- package/tests/fixtures_attended_results/project/tokens.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-compress-line-numbers/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-find-line-numbers/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-references/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/files-tokens/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-command/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-dummy/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-pylance/fixture_zig.zig.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_c.c.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_cpp.cpp.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_csharp.cs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_elixir.ex.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_go.go.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_haskell.hs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_java.java.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_javascript.js.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_kotlin.kt.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_lua.lua.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_perl.pl.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_php.php.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_python.py.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_ruby.rb.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_rust.rs.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_scala.scala.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_shell.sh.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_swift.swift.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_typescript.ts.json +5 -0
- package/tests/fixtures_attended_results/standalone/test-static-check-ruff/fixture_zig.zig.json +5 -0
- package/tests/helpers.ts +204 -0
- package/tests/oracle-project.test.ts +63 -0
- package/tests/oracle-standalone.test.ts +48 -0
- package/tests/prompt-rendering.test.ts +66 -0
- package/tests/release-workflow.test.ts +133 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Resolves installation-owned bundled resource locations.
|
|
4
|
+
* @details Encapsulates installation-path discovery, bundled-resource validation, prompt enumeration, and prompt loading directly from the installed extension payload. Runtime is proportional to directory-entry enumeration and prompt file size. Side effects are limited to filesystem reads.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { getInstallationPath, RESOURCE_ROOT_DIRNAME } from "./path-context.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @brief Resolves the bundled resource directory inside the installed extension payload.
|
|
13
|
+
* @details Joins the installation path with `resources`, producing the immutable source tree used for prompt, template, and guideline access during runtime. Time complexity is O(1). No I/O side effects occur.
|
|
14
|
+
* @return {string} Absolute bundled resource root path.
|
|
15
|
+
*/
|
|
16
|
+
export function getBundledResourceRoot(): string {
|
|
17
|
+
return path.join(getInstallationPath(), RESOURCE_ROOT_DIRNAME);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @brief Validates that installed bundled resources are accessible.
|
|
22
|
+
* @details Verifies that the installation-owned resource root plus `prompts`, `templates`, and `guidelines` directories exist before prompt or tool execution. Runtime is O(1) plus bounded filesystem metadata checks. Side effects are limited to filesystem reads.
|
|
23
|
+
* @return {string} Absolute bundled resource root path.
|
|
24
|
+
* @throws {Error} Propagates a deterministic error when required installed resource directories are missing.
|
|
25
|
+
*/
|
|
26
|
+
export function ensureBundledResourcesAccessible(): string {
|
|
27
|
+
const resourceRoot = getBundledResourceRoot();
|
|
28
|
+
if (!fs.existsSync(resourceRoot) || !fs.statSync(resourceRoot).isDirectory()) {
|
|
29
|
+
throw new Error(`Missing bundled resources at ${resourceRoot}`);
|
|
30
|
+
}
|
|
31
|
+
for (const requiredDirectoryName of ["prompts", "templates", "guidelines"]) {
|
|
32
|
+
const requiredDirectoryPath = path.join(resourceRoot, requiredDirectoryName);
|
|
33
|
+
if (!fs.existsSync(requiredDirectoryPath) || !fs.statSync(requiredDirectoryPath).isDirectory()) {
|
|
34
|
+
throw new Error(`Missing bundled resource directory at ${requiredDirectoryPath}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return resourceRoot;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @brief Reads one bundled markdown prompt by logical prompt name.
|
|
42
|
+
* @details Resolves the prompt file under the installation-owned `resources/prompts` directory, validates resource accessibility, and loads it as UTF-8 text. Time complexity is O(n) in file size. Side effects are limited to filesystem reads.
|
|
43
|
+
* @param[in] promptName {string} Prompt identifier without the `.md` suffix.
|
|
44
|
+
* @return {string} Raw prompt markdown content.
|
|
45
|
+
* @throws {Error} Propagates `fs.readFileSync` errors when the prompt file is missing or unreadable.
|
|
46
|
+
*/
|
|
47
|
+
export function readBundledPrompt(promptName: string): string {
|
|
48
|
+
const filePath = path.join(ensureBundledResourcesAccessible(), "prompts", `${promptName}.md`);
|
|
49
|
+
return fs.readFileSync(filePath, "utf8");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @brief Lists bundled prompt identifiers available in the installed extension payload.
|
|
54
|
+
* @details Scans the installation-owned prompt directory, keeps visible markdown files only, strips the `.md` suffix, and returns a lexicographically sorted list. Time complexity is O(n log n). Side effects are limited to filesystem reads.
|
|
55
|
+
* @return {string[]} Sorted prompt names without file extensions.
|
|
56
|
+
*/
|
|
57
|
+
export function listBundledPromptNames(): string[] {
|
|
58
|
+
return fs
|
|
59
|
+
.readdirSync(path.join(ensureBundledResourcesAccessible(), "prompts"), { withFileTypes: true })
|
|
60
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith(".md") && !entry.name.startsWith("."))
|
|
61
|
+
.map((entry) => entry.name.slice(0, -3))
|
|
62
|
+
.sort((left, right) => left.localeCompare(right));
|
|
63
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Derives runtime-only repository and base-path facts.
|
|
4
|
+
* @details Centralizes git-repository probing, repository-root resolution, and base-path-to-git-path formatting for extension status, tool execution, and CLI flows. Runtime is dominated by git subprocess execution plus path normalization. Side effects are limited to subprocess spawning.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { spawnSync } from "node:child_process";
|
|
9
|
+
import { ReqError } from "./errors.js";
|
|
10
|
+
import { isSameOrAncestorPath, normalizePathSlashes } from "./path-context.js";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @brief Executes one git subprocess and captures UTF-8 output.
|
|
14
|
+
* @details Delegates to `spawnSync`, keeps execution synchronous for deterministic command flows, and supports an optional working directory. Runtime is dominated by the spawned git process. Side effects include subprocess creation.
|
|
15
|
+
* @param[in] command {string[]} Git executable plus argument vector.
|
|
16
|
+
* @param[in] cwd {string | undefined} Optional working directory.
|
|
17
|
+
* @return {ReturnType<typeof spawnSync>} Captured subprocess result.
|
|
18
|
+
*/
|
|
19
|
+
function runGitCapture(command: string[], cwd?: string): ReturnType<typeof spawnSync> {
|
|
20
|
+
return spawnSync(command[0]!, command.slice(1), {
|
|
21
|
+
cwd,
|
|
22
|
+
encoding: "utf8",
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @brief Tests whether one path is inside a git work tree.
|
|
28
|
+
* @details Executes `git rev-parse --is-inside-work-tree` in the supplied directory and returns `true` only for a successful literal `true` response. Runtime is dominated by git execution. Side effects include subprocess creation.
|
|
29
|
+
* @param[in] targetPath {string} Directory to probe.
|
|
30
|
+
* @return {boolean} `true` when the directory belongs to a git work tree.
|
|
31
|
+
* @satisfies REQ-145
|
|
32
|
+
*/
|
|
33
|
+
export function isInsideGitRepo(targetPath: string): boolean {
|
|
34
|
+
const result = runGitCapture(["git", "rev-parse", "--is-inside-work-tree"], targetPath);
|
|
35
|
+
return result.status === 0 && result.stdout.trim() === "true";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @brief Resolves the repository root for one path inside a git work tree.
|
|
40
|
+
* @details Executes `git rev-parse --show-toplevel`, normalizes the result to an absolute path, and rejects non-repository paths with `ReqError`. Runtime is dominated by git execution. Side effects include subprocess creation.
|
|
41
|
+
* @param[in] targetPath {string} Directory inside the target repository.
|
|
42
|
+
* @return {string} Absolute repository-root path.
|
|
43
|
+
* @throws {ReqError} Throws when the path is not inside a git repository.
|
|
44
|
+
* @satisfies REQ-145
|
|
45
|
+
*/
|
|
46
|
+
export function resolveGitRoot(targetPath: string): string {
|
|
47
|
+
const result = runGitCapture(["git", "rev-parse", "--show-toplevel"], targetPath);
|
|
48
|
+
if (result.error || result.status !== 0) {
|
|
49
|
+
throw new ReqError(`Error: '${targetPath}' is not inside a git repository.`, 3);
|
|
50
|
+
}
|
|
51
|
+
return path.resolve(result.stdout.trim());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @brief Resolves the runtime git root for one execution path.
|
|
56
|
+
* @details Returns `undefined` when the path is outside a git repository. Otherwise resolves the repository root and rejects roots that are not identical to or ancestors of the execution path. Runtime is dominated by git execution. Side effects include subprocess creation.
|
|
57
|
+
* @param[in] executionPath {string} Runtime execution path.
|
|
58
|
+
* @return {string | undefined} Absolute repository-root path or `undefined` when unavailable.
|
|
59
|
+
* @satisfies REQ-105, REQ-145
|
|
60
|
+
*/
|
|
61
|
+
export function resolveRuntimeGitPath(executionPath: string): string | undefined {
|
|
62
|
+
const normalizedExecutionPath = path.resolve(executionPath);
|
|
63
|
+
if (!isInsideGitRepo(normalizedExecutionPath)) {
|
|
64
|
+
return undefined;
|
|
65
|
+
}
|
|
66
|
+
const gitRoot = resolveGitRoot(normalizedExecutionPath);
|
|
67
|
+
return isSameOrAncestorPath(gitRoot, normalizedExecutionPath) ? gitRoot : undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @brief Formats the runtime `base-path` relative to the runtime `git-path`.
|
|
72
|
+
* @details Returns `.` when the repository root is unavailable or identical to the base path. Otherwise returns the slash-normalized relative path from `git-path` to `base-path`. Runtime is O(p) in path length. No external state is mutated.
|
|
73
|
+
* @param[in] basePath {string} Runtime base path.
|
|
74
|
+
* @param[in] gitPath {string | undefined} Runtime repository root.
|
|
75
|
+
* @return {string} Relative base-path token for status rendering.
|
|
76
|
+
* @satisfies REQ-148
|
|
77
|
+
*/
|
|
78
|
+
export function formatBasePathRelativeToGitPath(basePath: string, gitPath: string | undefined): string {
|
|
79
|
+
const normalizedBasePath = path.resolve(basePath);
|
|
80
|
+
if (!gitPath) {
|
|
81
|
+
return ".";
|
|
82
|
+
}
|
|
83
|
+
const normalizedGitPath = path.resolve(gitPath);
|
|
84
|
+
if (normalizedBasePath === normalizedGitPath) {
|
|
85
|
+
return ".";
|
|
86
|
+
}
|
|
87
|
+
return normalizePathSlashes(path.relative(normalizedGitPath, normalizedBasePath)) || ".";
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* @brief Formats the runtime git path for status rendering.
|
|
92
|
+
* @details Returns a slash-normalized absolute path or an empty string when no repository root is available. Runtime is O(p) in path length. No external state is mutated.
|
|
93
|
+
* @param[in] gitPath {string | undefined} Runtime repository root.
|
|
94
|
+
* @return {string} Absolute repository path or an empty string.
|
|
95
|
+
* @satisfies REQ-147
|
|
96
|
+
*/
|
|
97
|
+
export function formatAbsoluteGitPath(gitPath: string | undefined): string {
|
|
98
|
+
return gitPath ? normalizePathSlashes(path.resolve(gitPath)) : "";
|
|
99
|
+
}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Renders pi-usereq configuration menus with the shared pi.dev settings style.
|
|
4
|
+
* @details Wraps `SettingsList` in one extension-command helper that exposes right-aligned current values, built-in circular scrolling, bottom-line descriptions, and a deterministic bridge for offline test harnesses. Runtime is O(n) in visible choice count plus user interaction cost. Side effects are limited to transient custom-UI rendering.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { getSettingsListTheme, type ThemeColor, type ExtensionCommandContext } from "@mariozechner/pi-coding-agent";
|
|
8
|
+
import { Container, SettingsList, Text, type Component, type SettingItem, type SettingsListTheme } from "@mariozechner/pi-tui";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @brief Describes one selectable pi-usereq settings-menu choice.
|
|
12
|
+
* @details Stores the stable action identifier, left-column label, right-column current value, and bottom-line description consumed by the shared settings-menu renderer. The interface is compile-time only and introduces no runtime cost.
|
|
13
|
+
*/
|
|
14
|
+
export interface PiUsereqSettingsMenuChoice {
|
|
15
|
+
id: string;
|
|
16
|
+
label: string;
|
|
17
|
+
value: string;
|
|
18
|
+
description: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @brief Describes the offline bridge exposed by shared settings-menu components.
|
|
23
|
+
* @details Lets deterministic harnesses and unit tests drive the same settings-menu choices by label without simulating raw terminal key streams. The interface is runtime-facing but carries no side effects by itself.
|
|
24
|
+
*/
|
|
25
|
+
export interface PiUsereqSettingsMenuBridge {
|
|
26
|
+
title: string;
|
|
27
|
+
choices: PiUsereqSettingsMenuChoice[];
|
|
28
|
+
selectByLabel: (label: string) => boolean;
|
|
29
|
+
cancel: () => void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @brief Represents a custom menu component augmented with the offline bridge.
|
|
34
|
+
* @details Extends the generic TUI `Component` contract with one optional bridge field consumed only by deterministic test and debug harness adapters. The interface is compile-time only and introduces no runtime cost.
|
|
35
|
+
*/
|
|
36
|
+
export interface PiUsereqSettingsMenuComponent extends Component {
|
|
37
|
+
__piUsereqSettingsMenu?: PiUsereqSettingsMenuBridge;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @brief Enumerates the CLI-supported theme tokens consumed by settings menus.
|
|
42
|
+
* @details Narrows callback-local theme calls to the documented settings-list
|
|
43
|
+
* semantics used by the pi CLI. Compile-time only and introduces no runtime
|
|
44
|
+
* cost.
|
|
45
|
+
*/
|
|
46
|
+
type PiUsereqSettingsThemeColor = Extract<ThemeColor, "accent" | "muted" | "dim">;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* @brief Describes the callback-local theme surface required by settings menus.
|
|
50
|
+
* @details Captures the subset of the custom-UI theme API needed to rebuild
|
|
51
|
+
* title and fallback settings-list styling when the shared global theme is not
|
|
52
|
+
* available in tests or offline replay. Compile-time only and introduces no
|
|
53
|
+
* runtime cost.
|
|
54
|
+
*/
|
|
55
|
+
interface PiUsereqSettingsTheme {
|
|
56
|
+
fg: (color: PiUsereqSettingsThemeColor, text: string) => string;
|
|
57
|
+
bold: (text: string) => string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @brief Builds the fallback settings-list theme matching CLI settings semantics.
|
|
62
|
+
* @details Mirrors the shared CLI settings theme token mapping for labels,
|
|
63
|
+
* values, descriptions, cursor, and hints while avoiding the global theme
|
|
64
|
+
* singleton used by the live pi runtime. Runtime is O(1). No external state is
|
|
65
|
+
* mutated.
|
|
66
|
+
* @param[in] theme {PiUsereqSettingsTheme} Callback-local pi theme adapter.
|
|
67
|
+
* @return {SettingsListTheme} Fallback settings-list theme.
|
|
68
|
+
* @satisfies REQ-151, REQ-156
|
|
69
|
+
*/
|
|
70
|
+
function buildFallbackPiUsereqSettingsListTheme(
|
|
71
|
+
theme: PiUsereqSettingsTheme,
|
|
72
|
+
): SettingsListTheme {
|
|
73
|
+
return {
|
|
74
|
+
label: (text: string, selected: boolean): string =>
|
|
75
|
+
selected ? theme.fg("accent", text) : text,
|
|
76
|
+
value: (text: string, selected: boolean): string =>
|
|
77
|
+
selected ? theme.fg("accent", text) : theme.fg("muted", text),
|
|
78
|
+
description: (text: string): string => theme.fg("dim", text),
|
|
79
|
+
cursor: theme.fg("accent", "→ "),
|
|
80
|
+
hint: (text: string): string => theme.fg("dim", text),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* @brief Resolves the settings-list theme used by pi-usereq configuration menus.
|
|
86
|
+
* @details Prefers the shared CLI `getSettingsListTheme()` API so extension
|
|
87
|
+
* menus inherit active-theme behavior from pi itself, then falls back to an
|
|
88
|
+
* equivalent callback-local mapping when the shared theme singleton is
|
|
89
|
+
* unavailable in deterministic tests or offline replay. Runtime is O(1). No
|
|
90
|
+
* external state is mutated.
|
|
91
|
+
* @param[in] theme {PiUsereqSettingsTheme} Callback-local pi theme adapter.
|
|
92
|
+
* @return {SettingsListTheme} Settings-list theme used by pi-usereq menus.
|
|
93
|
+
* @satisfies REQ-151, REQ-156
|
|
94
|
+
*/
|
|
95
|
+
function buildPiUsereqSettingsListTheme(
|
|
96
|
+
theme: PiUsereqSettingsTheme,
|
|
97
|
+
): SettingsListTheme {
|
|
98
|
+
try {
|
|
99
|
+
const sharedTheme = getSettingsListTheme();
|
|
100
|
+
void sharedTheme.label("", false);
|
|
101
|
+
void sharedTheme.value("", false);
|
|
102
|
+
void sharedTheme.description("");
|
|
103
|
+
void sharedTheme.cursor;
|
|
104
|
+
void sharedTheme.hint("");
|
|
105
|
+
return sharedTheme;
|
|
106
|
+
} catch {
|
|
107
|
+
return buildFallbackPiUsereqSettingsListTheme(theme);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* @brief Formats the settings-menu title with active-theme semantics.
|
|
113
|
+
* @details Applies the callback-local `accent` token and bold styling on every
|
|
114
|
+
* rebuild so custom-menu titles stay synchronized with live theme changes.
|
|
115
|
+
* Runtime is O(n) in title length. No external state is mutated.
|
|
116
|
+
* @param[in] theme {PiUsereqSettingsTheme} Callback-local pi theme adapter.
|
|
117
|
+
* @param[in] title {string} Menu title.
|
|
118
|
+
* @return {string} Styled title text.
|
|
119
|
+
* @satisfies REQ-151, REQ-156
|
|
120
|
+
*/
|
|
121
|
+
function formatPiUsereqSettingsMenuTitle(
|
|
122
|
+
theme: PiUsereqSettingsTheme,
|
|
123
|
+
title: string,
|
|
124
|
+
): string {
|
|
125
|
+
return theme.fg("accent", theme.bold(title));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @brief Closes a settings menu immediately with one selected action identifier.
|
|
130
|
+
* @details Provides the submenu callback used by `SettingsList` so pressing Enter on any menu row resolves the outer custom UI promise with the row identifier. Runtime is O(1). Side effects are limited to one custom-UI completion callback.
|
|
131
|
+
* @param[in] choiceId {string} Stable choice identifier to emit.
|
|
132
|
+
* @param[in] done {(value?: string) => void} Outer custom-UI completion callback.
|
|
133
|
+
* @return {Component} Immediate-completion submenu component.
|
|
134
|
+
*/
|
|
135
|
+
function createImmediateSelectionComponent(choiceId: string, done: (value?: string) => void): Component {
|
|
136
|
+
queueMicrotask(() => {
|
|
137
|
+
done(choiceId);
|
|
138
|
+
});
|
|
139
|
+
return {
|
|
140
|
+
render(): string[] {
|
|
141
|
+
return [];
|
|
142
|
+
},
|
|
143
|
+
invalidate(): void {
|
|
144
|
+
return;
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @brief Builds `SettingsList` items from one menu-choice vector.
|
|
151
|
+
* @details Copies labels, current values, and descriptions into `SettingItem` records and attaches a submenu that resolves the outer custom UI with the selected choice identifier. Runtime is O(n) in choice count. No external state is mutated.
|
|
152
|
+
* @param[in] choices {PiUsereqSettingsMenuChoice[]} Ordered menu-choice vector.
|
|
153
|
+
* @param[in] done {(value?: string) => void} Outer custom-UI completion callback.
|
|
154
|
+
* @return {SettingItem[]} `SettingsList` item vector.
|
|
155
|
+
*/
|
|
156
|
+
function buildSettingItems(
|
|
157
|
+
choices: PiUsereqSettingsMenuChoice[],
|
|
158
|
+
done: (value?: string) => void,
|
|
159
|
+
): SettingItem[] {
|
|
160
|
+
return choices.map((choice) => ({
|
|
161
|
+
id: choice.id,
|
|
162
|
+
label: choice.label,
|
|
163
|
+
description: choice.description,
|
|
164
|
+
currentValue: choice.value,
|
|
165
|
+
submenu: () => createImmediateSelectionComponent(choice.id, done),
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @brief Renders one shared pi-usereq settings menu and resolves the selected action.
|
|
171
|
+
* @details Uses `ctx.ui.custom(...)` plus `SettingsList` so every configuration menu shares pi.dev styling, right-aligned current values, circular scrolling, and bottom-line descriptions. The returned custom component also exposes an offline bridge for deterministic tests and debug harnesses. Runtime is O(n) in visible choice count plus user interaction cost. Side effects are limited to transient custom-UI rendering.
|
|
172
|
+
* @param[in] ctx {ExtensionCommandContext} Active command context.
|
|
173
|
+
* @param[in] title {string} Menu title displayed in the heading and offline bridge.
|
|
174
|
+
* @param[in] choices {PiUsereqSettingsMenuChoice[]} Ordered menu-choice vector.
|
|
175
|
+
* @return {Promise<string | undefined>} Selected choice identifier or `undefined` when cancelled.
|
|
176
|
+
* @satisfies REQ-151, REQ-152, REQ-153, REQ-154, REQ-156
|
|
177
|
+
*/
|
|
178
|
+
export async function showPiUsereqSettingsMenu(
|
|
179
|
+
ctx: ExtensionCommandContext,
|
|
180
|
+
title: string,
|
|
181
|
+
choices: PiUsereqSettingsMenuChoice[],
|
|
182
|
+
): Promise<string | undefined> {
|
|
183
|
+
return ctx.ui.custom<string | undefined>((tui, theme, _keybindings, done) => {
|
|
184
|
+
const container = new Container();
|
|
185
|
+
const titleText = new Text(
|
|
186
|
+
formatPiUsereqSettingsMenuTitle(theme, title),
|
|
187
|
+
0,
|
|
188
|
+
0,
|
|
189
|
+
);
|
|
190
|
+
const settingsList = new SettingsList(
|
|
191
|
+
buildSettingItems(choices, done),
|
|
192
|
+
Math.min(Math.max(choices.length, 1), 12),
|
|
193
|
+
buildPiUsereqSettingsListTheme(theme),
|
|
194
|
+
() => undefined,
|
|
195
|
+
() => done(undefined),
|
|
196
|
+
);
|
|
197
|
+
container.addChild(titleText);
|
|
198
|
+
container.addChild(new Text("", 0, 0));
|
|
199
|
+
container.addChild(settingsList);
|
|
200
|
+
|
|
201
|
+
const component: PiUsereqSettingsMenuComponent = {
|
|
202
|
+
render(width: number): string[] {
|
|
203
|
+
return container.render(width);
|
|
204
|
+
},
|
|
205
|
+
invalidate(): void {
|
|
206
|
+
container.invalidate();
|
|
207
|
+
titleText.setText(formatPiUsereqSettingsMenuTitle(theme, title));
|
|
208
|
+
},
|
|
209
|
+
handleInput(data: string): void {
|
|
210
|
+
settingsList.handleInput(data);
|
|
211
|
+
tui.requestRender();
|
|
212
|
+
},
|
|
213
|
+
__piUsereqSettingsMenu: {
|
|
214
|
+
title,
|
|
215
|
+
choices,
|
|
216
|
+
selectByLabel(label: string): boolean {
|
|
217
|
+
const choice = choices.find(
|
|
218
|
+
(candidate) => candidate.label === label || candidate.id === label,
|
|
219
|
+
);
|
|
220
|
+
if (!choice) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
done(choice.id);
|
|
224
|
+
return true;
|
|
225
|
+
},
|
|
226
|
+
cancel(): void {
|
|
227
|
+
done(undefined);
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
return component;
|
|
232
|
+
});
|
|
233
|
+
}
|