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,648 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Builds agent-oriented JSON payloads for `files-compress` and `compress`.
|
|
4
|
+
* @details Converts compression results into deterministic JSON sections ordered for LLM traversal, including request metadata, repository scope, structured file metrics, structured compressed lines, symbols, and Doxygen fields. Runtime is O(F log F + S) where F is file count and S is total source size. Side effects are limited to filesystem reads and optional stderr logging.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import {
|
|
10
|
+
ElementType,
|
|
11
|
+
SourceAnalyzer,
|
|
12
|
+
type SourceElement,
|
|
13
|
+
collectElementDoxygenFields,
|
|
14
|
+
collectFileLevelDoxygenFields,
|
|
15
|
+
} from "./source-analyzer.js";
|
|
16
|
+
import { compressFileDetailed, detectLanguage, type CompressedLineEntry } from "./compress.js";
|
|
17
|
+
import {
|
|
18
|
+
countDoxygenFieldValues,
|
|
19
|
+
structureDoxygenFields,
|
|
20
|
+
type StructuredDoxygenFields,
|
|
21
|
+
} from "./doxygen-parser.js";
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @brief Enumerates supported compression-payload scopes.
|
|
25
|
+
* @details Distinguishes explicit-file requests from configured project scans while preserving one stable JSON contract. The alias is compile-time only and introduces no runtime cost.
|
|
26
|
+
*/
|
|
27
|
+
export type CompressToolScope = "explicit-files" | "configured-source-directories";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @brief Enumerates supported per-file compression statuses.
|
|
31
|
+
* @details Separates compressed files, hard failures, and skipped inputs so downstream agents can branch without reparsing stderr text. The alias is compile-time only and introduces no runtime cost.
|
|
32
|
+
*/
|
|
33
|
+
export type CompressFileStatus = "compressed" | "error" | "skipped";
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @brief Enumerates the rendered line-number mode for compression output.
|
|
37
|
+
* @details Distinguishes payloads whose display strings include original source line numbers from payloads whose display strings contain plain compressed text only. The alias is compile-time only and introduces no runtime cost.
|
|
38
|
+
*/
|
|
39
|
+
export type CompressLineNumberMode = "enabled" | "disabled";
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @brief Enumerates structured symbol-analysis statuses for compressed files.
|
|
43
|
+
* @details Separates successful symbol extraction from supplementary analysis failures so compression can still succeed when analyzer enrichment is unavailable. The alias is compile-time only and introduces no runtime cost.
|
|
44
|
+
*/
|
|
45
|
+
export type CompressSymbolAnalysisStatus = "analyzed" | "error" | "not_attempted";
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @brief Describes one numeric line range.
|
|
49
|
+
* @details Exposes start and end line numbers plus the same inclusive range as a numeric tuple for direct agent access. The interface is compile-time only and introduces no runtime cost.
|
|
50
|
+
*/
|
|
51
|
+
export interface CompressLineRange {
|
|
52
|
+
start_line_number: number;
|
|
53
|
+
end_line_number: number;
|
|
54
|
+
line_range: [number, number];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* @brief Describes one structured compressed line entry in the tool payload.
|
|
59
|
+
* @details Preserves output order, original source coordinates, raw compressed text, and rendered display text so agents can choose between normalized data and user-facing rendering without reparsing strings. The interface is compile-time only and introduces no runtime cost.
|
|
60
|
+
*/
|
|
61
|
+
export interface CompressToolLineEntry {
|
|
62
|
+
compressed_line_number: number;
|
|
63
|
+
source_line_number: number;
|
|
64
|
+
text: string;
|
|
65
|
+
display_text: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @brief Describes one structured symbol record inside the compression payload.
|
|
70
|
+
* @details Orders direct-access identity fields before hierarchy, locations, and Doxygen metadata so agents can branch without reparsing compressed source text. The interface is compile-time only and introduces no runtime cost.
|
|
71
|
+
*/
|
|
72
|
+
export interface CompressToolSymbolEntry extends CompressLineRange {
|
|
73
|
+
declaration_order_index: number;
|
|
74
|
+
canonical_path: string;
|
|
75
|
+
symbol_name: string;
|
|
76
|
+
qualified_name: string;
|
|
77
|
+
symbol_kind: string;
|
|
78
|
+
type_label: string;
|
|
79
|
+
signature_text?: string;
|
|
80
|
+
parent_symbol_name?: string;
|
|
81
|
+
parent_qualified_name?: string;
|
|
82
|
+
child_symbol_names: string[];
|
|
83
|
+
child_qualified_names: string[];
|
|
84
|
+
depth: number;
|
|
85
|
+
brief_text?: string;
|
|
86
|
+
doxygen?: StructuredDoxygenFields;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @brief Describes one per-file compression payload entry.
|
|
91
|
+
* @details Stores path identity, compression metrics, rendered line-number mode, optional file-level and symbol-level metadata, structured compressed lines, and stable failure facts. The interface is compile-time only and introduces no runtime cost.
|
|
92
|
+
*/
|
|
93
|
+
export interface CompressToolFileEntry extends CompressLineRange {
|
|
94
|
+
request_index: number;
|
|
95
|
+
input_path: string;
|
|
96
|
+
canonical_path: string;
|
|
97
|
+
absolute_path: string;
|
|
98
|
+
file_name: string;
|
|
99
|
+
file_extension: string;
|
|
100
|
+
language_id?: string;
|
|
101
|
+
language_name?: string;
|
|
102
|
+
status: CompressFileStatus;
|
|
103
|
+
exists: boolean;
|
|
104
|
+
is_file: boolean;
|
|
105
|
+
line_number_mode: CompressLineNumberMode;
|
|
106
|
+
source_line_count: number;
|
|
107
|
+
compressed_line_count: number;
|
|
108
|
+
removed_line_count: number;
|
|
109
|
+
symbol_analysis_status: CompressSymbolAnalysisStatus;
|
|
110
|
+
symbol_count: number;
|
|
111
|
+
doxygen_field_count: number;
|
|
112
|
+
file_description_text?: string;
|
|
113
|
+
file_doxygen?: StructuredDoxygenFields;
|
|
114
|
+
symbols: CompressToolSymbolEntry[];
|
|
115
|
+
compressed_lines: CompressToolLineEntry[];
|
|
116
|
+
compressed_source_text?: string;
|
|
117
|
+
error_reason?: string;
|
|
118
|
+
error_message?: string;
|
|
119
|
+
symbol_analysis_error_message?: string;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* @brief Describes the request section of the compression payload.
|
|
124
|
+
* @details Captures tool identity, scope, base directory, line-number mode, requested inputs, and configured source-directory scope so agents can reason about how the file set was selected. The interface is compile-time only and introduces no runtime cost.
|
|
125
|
+
*/
|
|
126
|
+
export interface CompressToolRequestSection {
|
|
127
|
+
tool_name: string;
|
|
128
|
+
scope: CompressToolScope;
|
|
129
|
+
base_dir_path: string;
|
|
130
|
+
line_number_mode: CompressLineNumberMode;
|
|
131
|
+
source_directory_count: number;
|
|
132
|
+
source_directory_paths: string[];
|
|
133
|
+
requested_file_count: number;
|
|
134
|
+
requested_input_paths: string[];
|
|
135
|
+
requested_canonical_paths: string[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @brief Describes the summary section of the compression payload.
|
|
140
|
+
* @details Exposes aggregate file, line, symbol, and Doxygen counts as numeric fields with explicit unit names so agents can branch on totals without reparsing display strings. The interface is compile-time only and introduces no runtime cost.
|
|
141
|
+
*/
|
|
142
|
+
export interface CompressToolSummarySection {
|
|
143
|
+
processable_file_count: number;
|
|
144
|
+
compressed_file_count: number;
|
|
145
|
+
error_file_count: number;
|
|
146
|
+
skipped_file_count: number;
|
|
147
|
+
symbol_analysis_error_count: number;
|
|
148
|
+
total_source_line_count: number;
|
|
149
|
+
total_compressed_line_count: number;
|
|
150
|
+
total_removed_line_count: number;
|
|
151
|
+
total_symbol_count: number;
|
|
152
|
+
total_doxygen_field_count: number;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @brief Describes the repository section of the compression payload.
|
|
157
|
+
* @details Stores the base path, configured source-directory scope, and canonical file list used during compression. The interface is compile-time only and introduces no runtime cost.
|
|
158
|
+
*/
|
|
159
|
+
export interface CompressToolRepositorySection {
|
|
160
|
+
root_directory_path: string;
|
|
161
|
+
source_directory_paths: string[];
|
|
162
|
+
file_count: number;
|
|
163
|
+
file_canonical_paths: string[];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @brief Describes the full agent-oriented compression payload.
|
|
168
|
+
* @details Orders the top-level sections as request, summary, repository, and files so execution metadata can be appended deterministically by the tool wrapper. The interface is compile-time only and introduces no runtime cost.
|
|
169
|
+
*/
|
|
170
|
+
export interface CompressToolPayload {
|
|
171
|
+
request: CompressToolRequestSection;
|
|
172
|
+
summary: CompressToolSummarySection;
|
|
173
|
+
repository: CompressToolRepositorySection;
|
|
174
|
+
files: CompressToolFileEntry[];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* @brief Describes the options required to build one compression payload.
|
|
179
|
+
* @details Supplies tool identity, scope, base directory, requested paths, line-number mode, and optional configured source directories while keeping payload construction deterministic. The interface is compile-time only and introduces no runtime cost.
|
|
180
|
+
*/
|
|
181
|
+
export interface BuildCompressToolPayloadOptions {
|
|
182
|
+
toolName: string;
|
|
183
|
+
scope: CompressToolScope;
|
|
184
|
+
baseDir: string;
|
|
185
|
+
requestedPaths: string[];
|
|
186
|
+
includeLineNumbers: boolean;
|
|
187
|
+
sourceDirectoryPaths?: string[];
|
|
188
|
+
verbose?: boolean;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* @brief Canonicalizes one filesystem path relative to the payload base directory.
|
|
193
|
+
* @details Emits a slash-normalized relative path when the target is under the base directory; otherwise emits the normalized absolute path. Runtime is O(p) in path length. No side effects occur.
|
|
194
|
+
* @param[in] targetPath {string} Absolute or relative filesystem path.
|
|
195
|
+
* @param[in] baseDir {string} Base directory used for relative canonicalization.
|
|
196
|
+
* @return {string} Canonicalized path string.
|
|
197
|
+
*/
|
|
198
|
+
function canonicalizeCompressionPath(targetPath: string, baseDir: string): string {
|
|
199
|
+
const absolutePath = path.resolve(targetPath);
|
|
200
|
+
const absoluteBaseDir = path.resolve(baseDir);
|
|
201
|
+
const relativePath = path.relative(absoluteBaseDir, absolutePath).split(path.sep).join("/");
|
|
202
|
+
if (relativePath !== "" && relativePath !== "." && !relativePath.startsWith("../") && relativePath !== "..") {
|
|
203
|
+
return relativePath;
|
|
204
|
+
}
|
|
205
|
+
return absolutePath.split(path.sep).join("/");
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @brief Builds one structured line-range record.
|
|
210
|
+
* @details Duplicates the inclusive range as start, end, and tuple fields so callers can address whichever shape is most convenient. Runtime is O(1). No side effects occur.
|
|
211
|
+
* @param[in] startLineNumber {number} Inclusive start line number.
|
|
212
|
+
* @param[in] endLineNumber {number} Inclusive end line number.
|
|
213
|
+
* @return {CompressLineRange} Structured line-range record.
|
|
214
|
+
*/
|
|
215
|
+
function buildLineRange(startLineNumber: number, endLineNumber: number): CompressLineRange {
|
|
216
|
+
return {
|
|
217
|
+
start_line_number: startLineNumber,
|
|
218
|
+
end_line_number: endLineNumber,
|
|
219
|
+
line_range: [startLineNumber, endLineNumber],
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* @brief Resolves one stable symbol name from an analyzed element.
|
|
225
|
+
* @details Prefers explicit analyzer name metadata, then falls back to the derived signature or the first source line so every symbol retains a direct-access identifier. Runtime is O(1). No side effects occur.
|
|
226
|
+
* @param[in] element {SourceElement} Source element.
|
|
227
|
+
* @return {string} Stable symbol name.
|
|
228
|
+
*/
|
|
229
|
+
function resolveSymbolName(element: SourceElement): string {
|
|
230
|
+
return element.name ?? element.signature ?? ((element.extract.split("\n")[0] ?? "").trim() || "?");
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @brief Resolves the direct parent element for one child symbol.
|
|
235
|
+
* @details Matches by parent name plus inclusive line containment and chooses the deepest enclosing definition. Runtime is O(n) in definition count. No side effects occur.
|
|
236
|
+
* @param[in] definitions {SourceElement[]} Sorted definition elements.
|
|
237
|
+
* @param[in] child {SourceElement} Candidate child symbol.
|
|
238
|
+
* @return {SourceElement | undefined} Matched parent definition when available.
|
|
239
|
+
*/
|
|
240
|
+
function resolveParentElement(definitions: SourceElement[], child: SourceElement): SourceElement | undefined {
|
|
241
|
+
if (!child.parentName) {
|
|
242
|
+
return undefined;
|
|
243
|
+
}
|
|
244
|
+
return definitions
|
|
245
|
+
.filter(
|
|
246
|
+
(candidate) => candidate.name === child.parentName && candidate.lineStart <= child.lineStart && candidate.lineEnd >= child.lineEnd,
|
|
247
|
+
)
|
|
248
|
+
.sort((left, right) => right.depth - left.depth || right.lineStart - left.lineStart)[0];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @brief Maps structured compression lines into the payload line-entry contract.
|
|
253
|
+
* @details Performs a shallow field copy so the payload remains decoupled from the core compression result type. Runtime is O(n) in compressed line count. No side effects occur.
|
|
254
|
+
* @param[in] compressedLines {CompressedLineEntry[]} Structured compression lines.
|
|
255
|
+
* @return {CompressToolLineEntry[]} Payload line entries.
|
|
256
|
+
*/
|
|
257
|
+
function mapCompressedLines(compressedLines: CompressedLineEntry[]): CompressToolLineEntry[] {
|
|
258
|
+
return compressedLines.map((entry) => ({
|
|
259
|
+
compressed_line_number: entry.compressed_line_number,
|
|
260
|
+
source_line_number: entry.source_line_number,
|
|
261
|
+
text: entry.text,
|
|
262
|
+
display_text: entry.display_text,
|
|
263
|
+
} satisfies CompressToolLineEntry));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* @brief Builds structured symbol entries for one successfully analyzed file.
|
|
268
|
+
* @details Extracts definition elements, computes parent-child relationships, attaches structured Doxygen metadata, and repeats the canonical file path inside each symbol record for direct-access agent indexing. Runtime is O(n log n) in definition count. No side effects occur.
|
|
269
|
+
* @param[in] analyzer {SourceAnalyzer} Shared analyzer instance.
|
|
270
|
+
* @param[in] absolutePath {string} Absolute file path.
|
|
271
|
+
* @param[in] canonicalPath {string} Canonical path emitted in the payload.
|
|
272
|
+
* @param[in] languageId {string} Canonical language identifier.
|
|
273
|
+
* @return {{ languageName: string | undefined; symbols: CompressToolSymbolEntry[]; fileDoxygen: StructuredDoxygenFields | undefined; fileDescriptionText: string | undefined; doxygenFieldCount: number }} Structured symbol-analysis result.
|
|
274
|
+
* @throws {Error} Throws when source analysis or enrichment fails.
|
|
275
|
+
*/
|
|
276
|
+
function analyzeCompressedFileSymbols(
|
|
277
|
+
analyzer: SourceAnalyzer,
|
|
278
|
+
absolutePath: string,
|
|
279
|
+
canonicalPath: string,
|
|
280
|
+
languageId: string,
|
|
281
|
+
): {
|
|
282
|
+
languageName: string | undefined;
|
|
283
|
+
symbols: CompressToolSymbolEntry[];
|
|
284
|
+
fileDoxygen: StructuredDoxygenFields | undefined;
|
|
285
|
+
fileDescriptionText: string | undefined;
|
|
286
|
+
doxygenFieldCount: number;
|
|
287
|
+
} {
|
|
288
|
+
const elements = analyzer.analyze(absolutePath, languageId);
|
|
289
|
+
analyzer.enrich(elements, languageId, absolutePath);
|
|
290
|
+
const languageSpec = analyzer.specs[languageId.toLowerCase().trim().replace(/^\./, "")];
|
|
291
|
+
const fileLevelDoxygen = collectFileLevelDoxygenFields(elements);
|
|
292
|
+
const structuredFileDoxygen = structureDoxygenFields(fileLevelDoxygen);
|
|
293
|
+
const definitions = elements
|
|
294
|
+
.filter((element) => ![ElementType.COMMENT_SINGLE, ElementType.COMMENT_MULTI, ElementType.IMPORT, ElementType.DECORATOR].includes(element.elementType))
|
|
295
|
+
.sort((left, right) => left.lineStart - right.lineStart);
|
|
296
|
+
const parentByLineStart = new Map<number, SourceElement | undefined>();
|
|
297
|
+
definitions.forEach((element) => parentByLineStart.set(element.lineStart, resolveParentElement(definitions, element)));
|
|
298
|
+
const qualifiedNameByLineStart = new Map<number, string>();
|
|
299
|
+
|
|
300
|
+
const symbols = definitions.map((element, index) => {
|
|
301
|
+
const symbolName = resolveSymbolName(element);
|
|
302
|
+
const parentElement = parentByLineStart.get(element.lineStart);
|
|
303
|
+
const parentSymbolName = parentElement ? resolveSymbolName(parentElement) : undefined;
|
|
304
|
+
const parentQualifiedName = parentElement ? qualifiedNameByLineStart.get(parentElement.lineStart) : undefined;
|
|
305
|
+
const qualifiedName = parentQualifiedName ? `${parentQualifiedName}.${symbolName}` : symbolName;
|
|
306
|
+
qualifiedNameByLineStart.set(element.lineStart, qualifiedName);
|
|
307
|
+
|
|
308
|
+
const aggregateDoxygen = collectElementDoxygenFields(element);
|
|
309
|
+
const structuredDoxygen = structureDoxygenFields(aggregateDoxygen);
|
|
310
|
+
|
|
311
|
+
return {
|
|
312
|
+
...buildLineRange(element.lineStart, element.lineEnd),
|
|
313
|
+
declaration_order_index: index,
|
|
314
|
+
canonical_path: canonicalPath,
|
|
315
|
+
symbol_name: symbolName,
|
|
316
|
+
qualified_name: qualifiedName,
|
|
317
|
+
symbol_kind: element.elementType,
|
|
318
|
+
type_label: element.typeLabel,
|
|
319
|
+
signature_text: element.signature,
|
|
320
|
+
parent_symbol_name: parentSymbolName,
|
|
321
|
+
parent_qualified_name: parentQualifiedName,
|
|
322
|
+
child_symbol_names: [],
|
|
323
|
+
child_qualified_names: [],
|
|
324
|
+
depth: element.depth,
|
|
325
|
+
brief_text: structuredDoxygen.brief?.[0],
|
|
326
|
+
doxygen: Object.keys(structuredDoxygen).length > 0 ? structuredDoxygen : undefined,
|
|
327
|
+
} satisfies CompressToolSymbolEntry;
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
const childrenByParentQualifiedName = new Map<string, CompressToolSymbolEntry[]>();
|
|
331
|
+
symbols.forEach((symbol) => {
|
|
332
|
+
if (!symbol.parent_qualified_name) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const children = childrenByParentQualifiedName.get(symbol.parent_qualified_name) ?? [];
|
|
336
|
+
children.push(symbol);
|
|
337
|
+
childrenByParentQualifiedName.set(symbol.parent_qualified_name, children);
|
|
338
|
+
});
|
|
339
|
+
symbols.forEach((symbol) => {
|
|
340
|
+
const children = (childrenByParentQualifiedName.get(symbol.qualified_name) ?? []).sort(
|
|
341
|
+
(left, right) => left.declaration_order_index - right.declaration_order_index,
|
|
342
|
+
);
|
|
343
|
+
symbol.child_symbol_names = children.map((child) => child.symbol_name);
|
|
344
|
+
symbol.child_qualified_names = children.map((child) => child.qualified_name);
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
const symbolDoxygenFieldCount = definitions.reduce(
|
|
348
|
+
(sum, element) => sum + countDoxygenFieldValues(collectElementDoxygenFields(element)),
|
|
349
|
+
0,
|
|
350
|
+
);
|
|
351
|
+
const fileDoxygenFieldCount = countDoxygenFieldValues(fileLevelDoxygen);
|
|
352
|
+
|
|
353
|
+
return {
|
|
354
|
+
languageName: languageSpec?.name,
|
|
355
|
+
symbols,
|
|
356
|
+
fileDoxygen: Object.keys(structuredFileDoxygen).length > 0 ? structuredFileDoxygen : undefined,
|
|
357
|
+
fileDescriptionText: structuredFileDoxygen.brief?.[0] ?? structuredFileDoxygen.details?.[0],
|
|
358
|
+
doxygenFieldCount: fileDoxygenFieldCount + symbolDoxygenFieldCount,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* @brief Analyzes one path into a structured compression file entry.
|
|
364
|
+
* @details Resolves path identity, performs compression, attempts supplementary symbol and Doxygen extraction, preserves stable skip or error reasons, and keeps compression success independent from symbol-analysis success. Runtime is dominated by file I/O and analyzer cost. Side effects are limited to filesystem reads and optional stderr logging.
|
|
365
|
+
* @param[in] analyzer {SourceAnalyzer} Shared analyzer instance.
|
|
366
|
+
* @param[in] inputPath {string} Caller-supplied path.
|
|
367
|
+
* @param[in] absolutePath {string} Absolute path resolved against the payload base directory.
|
|
368
|
+
* @param[in] requestIndex {number} Caller-order index.
|
|
369
|
+
* @param[in] baseDir {string} Base directory used for canonical path derivation.
|
|
370
|
+
* @param[in] includeLineNumbers {boolean} When `true`, rendered compressed text includes original source line numbers.
|
|
371
|
+
* @param[in] verbose {boolean} When `true`, emit per-file diagnostics to stderr.
|
|
372
|
+
* @return {CompressToolFileEntry} Structured file entry.
|
|
373
|
+
*/
|
|
374
|
+
function analyzeCompressFile(
|
|
375
|
+
analyzer: SourceAnalyzer,
|
|
376
|
+
inputPath: string,
|
|
377
|
+
absolutePath: string,
|
|
378
|
+
requestIndex: number,
|
|
379
|
+
baseDir: string,
|
|
380
|
+
includeLineNumbers: boolean,
|
|
381
|
+
verbose: boolean,
|
|
382
|
+
): CompressToolFileEntry {
|
|
383
|
+
const canonicalPath = canonicalizeCompressionPath(absolutePath, baseDir);
|
|
384
|
+
const fileName = path.basename(absolutePath);
|
|
385
|
+
const fileExtension = path.extname(absolutePath).toLowerCase();
|
|
386
|
+
const lineNumberMode: CompressLineNumberMode = includeLineNumbers ? "enabled" : "disabled";
|
|
387
|
+
const languageId = detectLanguage(absolutePath);
|
|
388
|
+
|
|
389
|
+
if (!languageId) {
|
|
390
|
+
if (verbose) {
|
|
391
|
+
console.error(` SKIP ${inputPath} (unsupported extension)`);
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
...buildLineRange(0, 0),
|
|
395
|
+
request_index: requestIndex,
|
|
396
|
+
input_path: inputPath,
|
|
397
|
+
canonical_path: canonicalPath,
|
|
398
|
+
absolute_path: absolutePath,
|
|
399
|
+
file_name: fileName,
|
|
400
|
+
file_extension: fileExtension,
|
|
401
|
+
status: "skipped",
|
|
402
|
+
exists: true,
|
|
403
|
+
is_file: true,
|
|
404
|
+
line_number_mode: lineNumberMode,
|
|
405
|
+
source_line_count: 0,
|
|
406
|
+
compressed_line_count: 0,
|
|
407
|
+
removed_line_count: 0,
|
|
408
|
+
symbol_analysis_status: "not_attempted",
|
|
409
|
+
symbol_count: 0,
|
|
410
|
+
doxygen_field_count: 0,
|
|
411
|
+
symbols: [],
|
|
412
|
+
compressed_lines: [],
|
|
413
|
+
error_reason: "unsupported_extension",
|
|
414
|
+
error_message: "unsupported extension",
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
const compression = compressFileDetailed(absolutePath, languageId, includeLineNumbers);
|
|
420
|
+
let languageName: string | undefined;
|
|
421
|
+
let symbols: CompressToolSymbolEntry[] = [];
|
|
422
|
+
let fileDoxygen: StructuredDoxygenFields | undefined;
|
|
423
|
+
let fileDescriptionText: string | undefined;
|
|
424
|
+
let doxygenFieldCount = 0;
|
|
425
|
+
let symbolAnalysisStatus: CompressSymbolAnalysisStatus = "not_attempted";
|
|
426
|
+
let symbolAnalysisErrorMessage: string | undefined;
|
|
427
|
+
|
|
428
|
+
try {
|
|
429
|
+
const symbolAnalysis = analyzeCompressedFileSymbols(analyzer, absolutePath, canonicalPath, languageId);
|
|
430
|
+
languageName = symbolAnalysis.languageName;
|
|
431
|
+
symbols = symbolAnalysis.symbols;
|
|
432
|
+
fileDoxygen = symbolAnalysis.fileDoxygen;
|
|
433
|
+
fileDescriptionText = symbolAnalysis.fileDescriptionText;
|
|
434
|
+
doxygenFieldCount = symbolAnalysis.doxygenFieldCount;
|
|
435
|
+
symbolAnalysisStatus = "analyzed";
|
|
436
|
+
} catch (error) {
|
|
437
|
+
symbolAnalysisStatus = "error";
|
|
438
|
+
symbolAnalysisErrorMessage = error instanceof Error ? error.message : String(error);
|
|
439
|
+
if (verbose) {
|
|
440
|
+
console.error(` WARN ${absolutePath} (symbol analysis failed: ${symbolAnalysisErrorMessage})`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
if (verbose) {
|
|
445
|
+
console.error(` OK ${absolutePath}`);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
return {
|
|
449
|
+
...buildLineRange(compression.source_start_line_number, compression.source_end_line_number),
|
|
450
|
+
request_index: requestIndex,
|
|
451
|
+
input_path: inputPath,
|
|
452
|
+
canonical_path: canonicalPath,
|
|
453
|
+
absolute_path: absolutePath,
|
|
454
|
+
file_name: fileName,
|
|
455
|
+
file_extension: fileExtension,
|
|
456
|
+
language_id: languageId,
|
|
457
|
+
language_name: languageName,
|
|
458
|
+
status: "compressed",
|
|
459
|
+
exists: true,
|
|
460
|
+
is_file: true,
|
|
461
|
+
line_number_mode: lineNumberMode,
|
|
462
|
+
source_line_count: compression.source_line_count,
|
|
463
|
+
compressed_line_count: compression.compressed_line_count,
|
|
464
|
+
removed_line_count: compression.removed_line_count,
|
|
465
|
+
symbol_analysis_status: symbolAnalysisStatus,
|
|
466
|
+
symbol_count: symbols.length,
|
|
467
|
+
doxygen_field_count: doxygenFieldCount,
|
|
468
|
+
file_description_text: fileDescriptionText,
|
|
469
|
+
file_doxygen: fileDoxygen,
|
|
470
|
+
symbols,
|
|
471
|
+
compressed_lines: mapCompressedLines(compression.compressed_lines),
|
|
472
|
+
compressed_source_text: compression.compressed_source_text,
|
|
473
|
+
symbol_analysis_error_message: symbolAnalysisErrorMessage,
|
|
474
|
+
};
|
|
475
|
+
} catch (error) {
|
|
476
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
477
|
+
if (verbose) {
|
|
478
|
+
console.error(` FAIL ${absolutePath} (${message})`);
|
|
479
|
+
}
|
|
480
|
+
return {
|
|
481
|
+
...buildLineRange(0, 0),
|
|
482
|
+
request_index: requestIndex,
|
|
483
|
+
input_path: inputPath,
|
|
484
|
+
canonical_path: canonicalPath,
|
|
485
|
+
absolute_path: absolutePath,
|
|
486
|
+
file_name: fileName,
|
|
487
|
+
file_extension: fileExtension,
|
|
488
|
+
language_id: languageId,
|
|
489
|
+
status: "error",
|
|
490
|
+
exists: true,
|
|
491
|
+
is_file: true,
|
|
492
|
+
line_number_mode: lineNumberMode,
|
|
493
|
+
source_line_count: 0,
|
|
494
|
+
compressed_line_count: 0,
|
|
495
|
+
removed_line_count: 0,
|
|
496
|
+
symbol_analysis_status: "not_attempted",
|
|
497
|
+
symbol_count: 0,
|
|
498
|
+
doxygen_field_count: 0,
|
|
499
|
+
symbols: [],
|
|
500
|
+
compressed_lines: [],
|
|
501
|
+
error_reason: "compression_failed",
|
|
502
|
+
error_message: message,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
/**
|
|
508
|
+
* @brief Builds the full agent-oriented compression payload.
|
|
509
|
+
* @details Validates requested paths against the filesystem, compresses processable files in caller order, preserves skipped and failed inputs in structured file entries, computes aggregate numeric totals, and emits repository scope metadata. Runtime is O(F log F + S). Side effects are limited to filesystem reads and optional stderr logging.
|
|
510
|
+
* @param[in] options {BuildCompressToolPayloadOptions} Payload-construction options.
|
|
511
|
+
* @return {CompressToolPayload} Structured compression payload ordered as request, summary, repository, and files.
|
|
512
|
+
* @satisfies REQ-081, REQ-082, REQ-083, REQ-084, REQ-085, REQ-087
|
|
513
|
+
*/
|
|
514
|
+
export function buildCompressToolPayload(options: BuildCompressToolPayloadOptions): CompressToolPayload {
|
|
515
|
+
const {
|
|
516
|
+
toolName,
|
|
517
|
+
scope,
|
|
518
|
+
baseDir,
|
|
519
|
+
requestedPaths,
|
|
520
|
+
includeLineNumbers,
|
|
521
|
+
sourceDirectoryPaths = [],
|
|
522
|
+
verbose = false,
|
|
523
|
+
} = options;
|
|
524
|
+
const absoluteBaseDir = path.resolve(baseDir);
|
|
525
|
+
const analyzer = new SourceAnalyzer();
|
|
526
|
+
const lineNumberMode: CompressLineNumberMode = includeLineNumbers ? "enabled" : "disabled";
|
|
527
|
+
const canonicalRequestedPaths = requestedPaths.map((requestedPath) => canonicalizeCompressionPath(requestedPath, absoluteBaseDir));
|
|
528
|
+
const files: CompressToolFileEntry[] = requestedPaths.map((requestedPath, requestIndex) => {
|
|
529
|
+
const absolutePath = path.resolve(absoluteBaseDir, requestedPath);
|
|
530
|
+
const canonicalPath = canonicalizeCompressionPath(absolutePath, absoluteBaseDir);
|
|
531
|
+
const fileName = path.basename(absolutePath);
|
|
532
|
+
const fileExtension = path.extname(absolutePath).toLowerCase();
|
|
533
|
+
if (!fs.existsSync(absolutePath)) {
|
|
534
|
+
if (verbose) {
|
|
535
|
+
console.error(` SKIP ${requestedPath} (file not found)`);
|
|
536
|
+
}
|
|
537
|
+
return {
|
|
538
|
+
...buildLineRange(0, 0),
|
|
539
|
+
request_index: requestIndex,
|
|
540
|
+
input_path: requestedPath,
|
|
541
|
+
canonical_path: canonicalPath,
|
|
542
|
+
absolute_path: absolutePath,
|
|
543
|
+
file_name: fileName,
|
|
544
|
+
file_extension: fileExtension,
|
|
545
|
+
status: "skipped",
|
|
546
|
+
exists: false,
|
|
547
|
+
is_file: false,
|
|
548
|
+
line_number_mode: lineNumberMode,
|
|
549
|
+
source_line_count: 0,
|
|
550
|
+
compressed_line_count: 0,
|
|
551
|
+
removed_line_count: 0,
|
|
552
|
+
symbol_analysis_status: "not_attempted",
|
|
553
|
+
symbol_count: 0,
|
|
554
|
+
doxygen_field_count: 0,
|
|
555
|
+
symbols: [],
|
|
556
|
+
compressed_lines: [],
|
|
557
|
+
error_reason: "not_found",
|
|
558
|
+
error_message: "not found",
|
|
559
|
+
} satisfies CompressToolFileEntry;
|
|
560
|
+
}
|
|
561
|
+
const stats = fs.statSync(absolutePath);
|
|
562
|
+
if (!stats.isFile()) {
|
|
563
|
+
if (verbose) {
|
|
564
|
+
console.error(` SKIP ${requestedPath} (not a file)`);
|
|
565
|
+
}
|
|
566
|
+
return {
|
|
567
|
+
...buildLineRange(0, 0),
|
|
568
|
+
request_index: requestIndex,
|
|
569
|
+
input_path: requestedPath,
|
|
570
|
+
canonical_path: canonicalPath,
|
|
571
|
+
absolute_path: absolutePath,
|
|
572
|
+
file_name: fileName,
|
|
573
|
+
file_extension: fileExtension,
|
|
574
|
+
status: "skipped",
|
|
575
|
+
exists: true,
|
|
576
|
+
is_file: false,
|
|
577
|
+
line_number_mode: lineNumberMode,
|
|
578
|
+
source_line_count: 0,
|
|
579
|
+
compressed_line_count: 0,
|
|
580
|
+
removed_line_count: 0,
|
|
581
|
+
symbol_analysis_status: "not_attempted",
|
|
582
|
+
symbol_count: 0,
|
|
583
|
+
doxygen_field_count: 0,
|
|
584
|
+
symbols: [],
|
|
585
|
+
compressed_lines: [],
|
|
586
|
+
error_reason: "not_file",
|
|
587
|
+
error_message: "not a file",
|
|
588
|
+
} satisfies CompressToolFileEntry;
|
|
589
|
+
}
|
|
590
|
+
return analyzeCompressFile(analyzer, requestedPath, absolutePath, requestIndex, absoluteBaseDir, includeLineNumbers, verbose);
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
const compressedFiles = files.filter((file) => file.status === "compressed");
|
|
594
|
+
const symbolAnalysisErrorCount = compressedFiles.filter((file) => file.symbol_analysis_status === "error").length;
|
|
595
|
+
|
|
596
|
+
return {
|
|
597
|
+
request: {
|
|
598
|
+
tool_name: toolName,
|
|
599
|
+
scope,
|
|
600
|
+
base_dir_path: absoluteBaseDir,
|
|
601
|
+
line_number_mode: lineNumberMode,
|
|
602
|
+
source_directory_count: sourceDirectoryPaths.length,
|
|
603
|
+
source_directory_paths: [...sourceDirectoryPaths],
|
|
604
|
+
requested_file_count: requestedPaths.length,
|
|
605
|
+
requested_input_paths: [...requestedPaths],
|
|
606
|
+
requested_canonical_paths: canonicalRequestedPaths,
|
|
607
|
+
},
|
|
608
|
+
summary: {
|
|
609
|
+
processable_file_count: files.filter((file) => file.status !== "skipped").length,
|
|
610
|
+
compressed_file_count: compressedFiles.length,
|
|
611
|
+
error_file_count: files.filter((file) => file.status === "error").length,
|
|
612
|
+
skipped_file_count: files.filter((file) => file.status === "skipped").length,
|
|
613
|
+
symbol_analysis_error_count: symbolAnalysisErrorCount,
|
|
614
|
+
total_source_line_count: compressedFiles.reduce((sum, file) => sum + file.source_line_count, 0),
|
|
615
|
+
total_compressed_line_count: compressedFiles.reduce((sum, file) => sum + file.compressed_line_count, 0),
|
|
616
|
+
total_removed_line_count: compressedFiles.reduce((sum, file) => sum + file.removed_line_count, 0),
|
|
617
|
+
total_symbol_count: compressedFiles.reduce((sum, file) => sum + file.symbol_count, 0),
|
|
618
|
+
total_doxygen_field_count: compressedFiles.reduce((sum, file) => sum + file.doxygen_field_count, 0),
|
|
619
|
+
},
|
|
620
|
+
repository: {
|
|
621
|
+
root_directory_path: absoluteBaseDir,
|
|
622
|
+
source_directory_paths: [...sourceDirectoryPaths],
|
|
623
|
+
file_count: files.length,
|
|
624
|
+
file_canonical_paths: files.map((file) => file.canonical_path),
|
|
625
|
+
},
|
|
626
|
+
files,
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* @brief Builds execution diagnostics for one compression payload.
|
|
632
|
+
* @details Serializes skipped inputs, hard compression failures, and supplementary symbol-analysis warnings into stable stderr lines while keeping successful compressed files silent. Runtime is O(n) in issue count. No side effects occur.
|
|
633
|
+
* @param[in] payload {CompressToolPayload} Structured compression payload.
|
|
634
|
+
* @return {string} Newline-delimited execution diagnostics.
|
|
635
|
+
* @satisfies REQ-087
|
|
636
|
+
*/
|
|
637
|
+
export function buildCompressToolExecutionStderr(payload: CompressToolPayload): string {
|
|
638
|
+
const skippedLines = payload.files
|
|
639
|
+
.filter((file) => file.status === "skipped")
|
|
640
|
+
.map((file) => `skipped: ${file.canonical_path}: ${file.error_reason ?? "skipped"}`);
|
|
641
|
+
const errorLines = payload.files
|
|
642
|
+
.filter((file) => file.status === "error")
|
|
643
|
+
.map((file) => `error: ${file.canonical_path}: ${file.error_reason ?? "error"}: ${file.error_message ?? "unknown error"}`);
|
|
644
|
+
const warningLines = payload.files
|
|
645
|
+
.filter((file) => file.status === "compressed" && file.symbol_analysis_status === "error")
|
|
646
|
+
.map((file) => `warning: ${file.canonical_path}: source_analysis_failed: ${file.symbol_analysis_error_message ?? "unknown error"}`);
|
|
647
|
+
return [...skippedLines, ...errorLines, ...warningLines].join("\n");
|
|
648
|
+
}
|