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,464 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* @brief Removes comments and redundant whitespace from source code while preserving semantic structure.
|
|
4
|
+
* @details Provides extension-based language detection and language-aware source compression backed by analyzer language specs. Runtime is linear in processed source size. Side effects are limited to filesystem reads in file-based helpers.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import fs from "node:fs";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
import { buildLanguageSpecs } from "./source-analyzer.js";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @brief Maps filename extensions to compression language identifiers.
|
|
13
|
+
* @details Used by `detectLanguage`, `compressFile`, and `compressFileDetailed` to route files into the correct comment-stripping rules. Lookup complexity is O(1).
|
|
14
|
+
*/
|
|
15
|
+
const EXT_LANG_MAP: Record<string, string> = {
|
|
16
|
+
".py": "python",
|
|
17
|
+
".js": "javascript",
|
|
18
|
+
".mjs": "javascript",
|
|
19
|
+
".ts": "typescript",
|
|
20
|
+
".rs": "rust",
|
|
21
|
+
".go": "go",
|
|
22
|
+
".c": "c",
|
|
23
|
+
".cpp": "cpp",
|
|
24
|
+
".h": "c",
|
|
25
|
+
".hpp": "cpp",
|
|
26
|
+
".java": "java",
|
|
27
|
+
".rb": "ruby",
|
|
28
|
+
".php": "php",
|
|
29
|
+
".swift": "swift",
|
|
30
|
+
".kt": "kotlin",
|
|
31
|
+
".scala": "scala",
|
|
32
|
+
".lua": "lua",
|
|
33
|
+
".sh": "shell",
|
|
34
|
+
".pl": "perl",
|
|
35
|
+
".hs": "haskell",
|
|
36
|
+
".zig": "zig",
|
|
37
|
+
".ex": "elixir",
|
|
38
|
+
".cs": "csharp",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @brief Identifies languages whose indentation must be preserved during compression.
|
|
43
|
+
* @details These languages encode block structure via indentation, so whitespace normalization keeps leading indentation intact. Membership checks are O(1).
|
|
44
|
+
*/
|
|
45
|
+
const INDENT_SIGNIFICANT = new Set(["python", "haskell", "elixir"]);
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* @brief Caches analyzer language specifications for reuse.
|
|
49
|
+
* @details Lazy initialization avoids rebuilding the large language-spec table on every compression request. Access complexity is O(1) after first load.
|
|
50
|
+
*/
|
|
51
|
+
let specsCache: ReturnType<typeof buildLanguageSpecs> | undefined;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @brief Describes one structured compressed output line.
|
|
55
|
+
* @details Separates source coordinates, output order, raw compressed text, and rendered display text so downstream JSON payloads can expose line facts without reparsing prefixed strings. The interface is compile-time only and introduces no runtime cost.
|
|
56
|
+
*/
|
|
57
|
+
export interface CompressedLineEntry {
|
|
58
|
+
compressed_line_number: number;
|
|
59
|
+
source_line_number: number;
|
|
60
|
+
text: string;
|
|
61
|
+
display_text: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @brief Describes one structured compression result.
|
|
66
|
+
* @details Exposes language identity, source line metrics, removed-line totals, structured compressed lines, and the final rendered excerpt text so CLI and agent-tool layers can share one canonical compression model. The interface is compile-time only and introduces no runtime cost.
|
|
67
|
+
*/
|
|
68
|
+
export interface CompressedSourceResult {
|
|
69
|
+
language_id: string;
|
|
70
|
+
include_line_numbers: boolean;
|
|
71
|
+
source_line_count: number;
|
|
72
|
+
source_start_line_number: number;
|
|
73
|
+
source_end_line_number: number;
|
|
74
|
+
source_line_range: [number, number];
|
|
75
|
+
compressed_line_count: number;
|
|
76
|
+
removed_line_count: number;
|
|
77
|
+
compressed_lines: CompressedLineEntry[];
|
|
78
|
+
compressed_source_text: string;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @brief Returns the cached language specification table.
|
|
83
|
+
* @details Initializes the cache on first access by calling `buildLanguageSpecs`, then reuses the result for all subsequent calls. Time complexity is O(1) after cold start. Mutates module-local cache state only.
|
|
84
|
+
* @return {ReturnType<typeof buildLanguageSpecs>} Cached language specification map.
|
|
85
|
+
*/
|
|
86
|
+
function getSpecs() {
|
|
87
|
+
specsCache ??= buildLanguageSpecs();
|
|
88
|
+
return specsCache;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* @brief Infers a compression language from a file path extension.
|
|
93
|
+
* @details Lowercases the file extension and looks it up in `EXT_LANG_MAP`. Time complexity is O(1). No I/O side effects occur.
|
|
94
|
+
* @param[in] filePath {string} Source file path.
|
|
95
|
+
* @return {string | undefined} Canonical compression language identifier, or `undefined` when unsupported.
|
|
96
|
+
*/
|
|
97
|
+
export function detectLanguage(filePath: string): string | undefined {
|
|
98
|
+
return EXT_LANG_MAP[path.extname(filePath).toLowerCase()];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @brief Counts logical lines in one text payload.
|
|
103
|
+
* @details Counts newline separators while treating a trailing newline as line termination instead of an extra empty logical line. Runtime is O(n) in text length. No side effects occur.
|
|
104
|
+
* @param[in] content {string} Source text.
|
|
105
|
+
* @return {number} Logical line count; `0` for empty content.
|
|
106
|
+
*/
|
|
107
|
+
function countLogicalLines(content: string): number {
|
|
108
|
+
if (content.length === 0) {
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
const newlineCount = content.match(/\r\n|\r|\n/g)?.length ?? 0;
|
|
112
|
+
return /(?:\r\n|\r|\n)$/.test(content) ? newlineCount : newlineCount + 1;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* @brief Tests whether a character position falls inside a string literal.
|
|
117
|
+
* @details Scans the line left-to-right while tracking active string delimiters and escaped quote characters. Runtime is O(n) in inspected prefix length. No side effects occur.
|
|
118
|
+
* @param[in] line {string} Source line to inspect.
|
|
119
|
+
* @param[in] pos {number} Zero-based character position.
|
|
120
|
+
* @param[in] stringDelimiters {string[]} Supported string delimiters for the language.
|
|
121
|
+
* @return {boolean} `true` when the position is inside a string literal.
|
|
122
|
+
*/
|
|
123
|
+
function isInString(line: string, pos: number, stringDelimiters: string[]): boolean {
|
|
124
|
+
let inString: string | undefined;
|
|
125
|
+
let i = 0;
|
|
126
|
+
const sortedDelimiters = [...stringDelimiters].sort((a, b) => b.length - a.length);
|
|
127
|
+
while (i < pos) {
|
|
128
|
+
if (inString) {
|
|
129
|
+
if (line.slice(i).startsWith(inString)) {
|
|
130
|
+
if (inString.length === 1 && i > 0 && line[i - 1] === "\\") {
|
|
131
|
+
let backslashes = 0;
|
|
132
|
+
let j = i - 1;
|
|
133
|
+
while (j >= 0 && line[j] === "\\") {
|
|
134
|
+
backslashes += 1;
|
|
135
|
+
j -= 1;
|
|
136
|
+
}
|
|
137
|
+
if (backslashes % 2 === 1) {
|
|
138
|
+
i += 1;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
i += inString.length;
|
|
143
|
+
inString = undefined;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
i += 1;
|
|
147
|
+
} else {
|
|
148
|
+
const matched = sortedDelimiters.find((delimiter) => line.slice(i).startsWith(delimiter));
|
|
149
|
+
if (matched) {
|
|
150
|
+
inString = matched;
|
|
151
|
+
i += matched.length;
|
|
152
|
+
} else {
|
|
153
|
+
i += 1;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return inString !== undefined;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @brief Removes a trailing single-line comment from a source line.
|
|
162
|
+
* @details Scans the line while respecting string literals so comment markers inside strings are preserved. Runtime is O(n) in line length. No external state is mutated.
|
|
163
|
+
* @param[in] line {string} Source line to strip.
|
|
164
|
+
* @param[in] singleComment {string | undefined} Language single-line comment marker.
|
|
165
|
+
* @param[in] stringDelimiters {string[]} Supported string delimiters for the language.
|
|
166
|
+
* @return {string} Line content before the first real comment marker.
|
|
167
|
+
*/
|
|
168
|
+
function removeInlineComment(line: string, singleComment: string | undefined, stringDelimiters: string[]): string {
|
|
169
|
+
if (!singleComment) return line;
|
|
170
|
+
const sortedDelimiters = [...stringDelimiters].sort((a, b) => b.length - a.length);
|
|
171
|
+
let inString: string | undefined;
|
|
172
|
+
let i = 0;
|
|
173
|
+
while (i < line.length) {
|
|
174
|
+
if (inString) {
|
|
175
|
+
if (line.slice(i).startsWith(inString)) {
|
|
176
|
+
if (inString.length === 1 && i > 0 && line[i - 1] === "\\") {
|
|
177
|
+
let backslashes = 0;
|
|
178
|
+
let j = i - 1;
|
|
179
|
+
while (j >= 0 && line[j] === "\\") {
|
|
180
|
+
backslashes += 1;
|
|
181
|
+
j -= 1;
|
|
182
|
+
}
|
|
183
|
+
if (backslashes % 2 === 1) {
|
|
184
|
+
i += 1;
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
i += inString.length;
|
|
189
|
+
inString = undefined;
|
|
190
|
+
} else {
|
|
191
|
+
i += 1;
|
|
192
|
+
}
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (line.slice(i, i + singleComment.length) === singleComment) {
|
|
197
|
+
return line.slice(0, i);
|
|
198
|
+
}
|
|
199
|
+
const matched = sortedDelimiters.find((delimiter) => line.slice(i).startsWith(delimiter));
|
|
200
|
+
if (matched) {
|
|
201
|
+
inString = matched;
|
|
202
|
+
i += matched.length;
|
|
203
|
+
} else {
|
|
204
|
+
i += 1;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return line;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @brief Builds one rendered compressed line entry.
|
|
212
|
+
* @details Materializes both the raw compressed text and the display text that optionally prefixes the original source line number. Runtime is O(n) in line length. No side effects occur.
|
|
213
|
+
* @param[in] text {string} Compressed source text for one retained line.
|
|
214
|
+
* @param[in] sourceLineNumber {number} Original source line number.
|
|
215
|
+
* @param[in] compressedLineNumber {number} One-based output line number inside the compressed excerpt.
|
|
216
|
+
* @param[in] includeLineNumbers {boolean} When `true`, prefix the display text with the original source line number.
|
|
217
|
+
* @return {CompressedLineEntry} Structured compressed line entry.
|
|
218
|
+
*/
|
|
219
|
+
function buildCompressedLineEntry(
|
|
220
|
+
text: string,
|
|
221
|
+
sourceLineNumber: number,
|
|
222
|
+
compressedLineNumber: number,
|
|
223
|
+
includeLineNumbers: boolean,
|
|
224
|
+
): CompressedLineEntry {
|
|
225
|
+
return {
|
|
226
|
+
compressed_line_number: compressedLineNumber,
|
|
227
|
+
source_line_number: sourceLineNumber,
|
|
228
|
+
text,
|
|
229
|
+
display_text: includeLineNumbers ? `${sourceLineNumber}: ${text}` : text,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* @brief Formats compressed line entries as newline-delimited text.
|
|
235
|
+
* @details Joins pre-rendered display lines without adding headers, fences, or other presentation artifacts. Runtime is O(n) in entry count and aggregate content length. No side effects occur.
|
|
236
|
+
* @param[in] entries {CompressedLineEntry[]} Structured compressed line entries.
|
|
237
|
+
* @return {string} Final compressed source text.
|
|
238
|
+
*/
|
|
239
|
+
function formatCompressedSourceText(entries: CompressedLineEntry[]): string {
|
|
240
|
+
return entries.map((entry) => entry.display_text).join("\n");
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* @brief Compresses in-memory source text into the structured compression model.
|
|
245
|
+
* @details Removes blank lines and comments, preserves shebangs, respects string-literal boundaries, retains leading indentation for indentation-significant languages, and emits both structured line entries and a rendered text excerpt. Runtime is O(n) in source length. No external state is mutated.
|
|
246
|
+
* @param[in] source {string} Raw source text.
|
|
247
|
+
* @param[in] language {string} Canonical compression language identifier.
|
|
248
|
+
* @param[in] includeLineNumbers {boolean} When `true`, prefix rendered text lines with original source line numbers.
|
|
249
|
+
* @return {CompressedSourceResult} Structured compression result.
|
|
250
|
+
* @throws {Error} Throws when the language is unsupported.
|
|
251
|
+
*/
|
|
252
|
+
export function compressSourceDetailed(source: string, language: string, includeLineNumbers = true): CompressedSourceResult {
|
|
253
|
+
const specs = getSpecs();
|
|
254
|
+
const langKey = language.toLowerCase().trim().replace(/^\./, "");
|
|
255
|
+
const spec = specs[langKey];
|
|
256
|
+
if (!spec) {
|
|
257
|
+
throw new Error(`Unsupported language: ${language}`);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const preserveIndent = INDENT_SIGNIFICANT.has(langKey);
|
|
261
|
+
const lines = source.split("\n");
|
|
262
|
+
const retainedEntries: Array<[number, string]> = [];
|
|
263
|
+
|
|
264
|
+
let inMultiComment = false;
|
|
265
|
+
const multiCommentStart = spec.multiCommentStart;
|
|
266
|
+
const multiCommentEnd = spec.multiCommentEnd;
|
|
267
|
+
const stringDelimiters = spec.stringDelimiters;
|
|
268
|
+
|
|
269
|
+
const isPython = langKey === "python";
|
|
270
|
+
let inPythonDocstring = false;
|
|
271
|
+
let pythonDocstringDelimiter: string | undefined;
|
|
272
|
+
|
|
273
|
+
let index = 0;
|
|
274
|
+
while (index < lines.length) {
|
|
275
|
+
let line = lines[index] ?? "";
|
|
276
|
+
|
|
277
|
+
if (inMultiComment) {
|
|
278
|
+
if (multiCommentEnd && line.includes(multiCommentEnd)) {
|
|
279
|
+
const endPos = line.indexOf(multiCommentEnd) + multiCommentEnd.length;
|
|
280
|
+
const remainder = line.slice(endPos);
|
|
281
|
+
inMultiComment = false;
|
|
282
|
+
if (remainder.trim()) {
|
|
283
|
+
lines[index] = remainder;
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
index += 1;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (isPython && inPythonDocstring) {
|
|
292
|
+
if (pythonDocstringDelimiter && line.includes(pythonDocstringDelimiter)) {
|
|
293
|
+
const endPos = line.indexOf(pythonDocstringDelimiter) + pythonDocstringDelimiter.length;
|
|
294
|
+
const remainder = line.slice(endPos);
|
|
295
|
+
inPythonDocstring = false;
|
|
296
|
+
pythonDocstringDelimiter = undefined;
|
|
297
|
+
if (remainder.trim()) {
|
|
298
|
+
lines[index] = remainder;
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
index += 1;
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const stripped = line.trim();
|
|
307
|
+
if (!stripped) {
|
|
308
|
+
index += 1;
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (multiCommentStart) {
|
|
313
|
+
if (isPython) {
|
|
314
|
+
let dropped = false;
|
|
315
|
+
for (const quote of ['"""', "'''"]) {
|
|
316
|
+
if (!stripped.startsWith(quote)) continue;
|
|
317
|
+
if (stripped.endsWith(quote) && stripped.length >= 6 && stripped.split(quote).length - 1 >= 2) {
|
|
318
|
+
const codeBefore = line.slice(0, line.indexOf(quote)).trim();
|
|
319
|
+
if (!codeBefore) {
|
|
320
|
+
dropped = true;
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
} else if ((stripped.match(new RegExp(quote.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "g"))?.length ?? 0) === 1) {
|
|
324
|
+
const codeBefore = line.slice(0, line.indexOf(quote)).trim();
|
|
325
|
+
if (!codeBefore) {
|
|
326
|
+
inPythonDocstring = true;
|
|
327
|
+
pythonDocstringDelimiter = quote;
|
|
328
|
+
dropped = true;
|
|
329
|
+
break;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (dropped) {
|
|
334
|
+
index += 1;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
} else {
|
|
338
|
+
const multiCommentPos = stripped.indexOf(multiCommentStart);
|
|
339
|
+
if (multiCommentPos !== -1) {
|
|
340
|
+
const fullPos = line.indexOf(multiCommentStart);
|
|
341
|
+
if (!isInString(line, fullPos, stringDelimiters)) {
|
|
342
|
+
const afterStart = line.slice(fullPos + multiCommentStart.length);
|
|
343
|
+
const closePos = multiCommentEnd ? afterStart.indexOf(multiCommentEnd) : -1;
|
|
344
|
+
if (closePos !== -1 && multiCommentStart !== multiCommentEnd) {
|
|
345
|
+
line = line.slice(0, fullPos) + afterStart.slice(closePos + multiCommentEnd!.length);
|
|
346
|
+
if (!line.trim()) {
|
|
347
|
+
index += 1;
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
lines[index] = line;
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
const before = line.slice(0, fullPos);
|
|
354
|
+
inMultiComment = true;
|
|
355
|
+
if (before.trim()) {
|
|
356
|
+
line = before;
|
|
357
|
+
} else {
|
|
358
|
+
index += 1;
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
if (spec.singleComment && stripped.startsWith(spec.singleComment)) {
|
|
367
|
+
if (stripped.startsWith("#!") && index === 0) {
|
|
368
|
+
retainedEntries.push([index + 1, stripped]);
|
|
369
|
+
}
|
|
370
|
+
index += 1;
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (spec.singleComment) {
|
|
375
|
+
line = removeInlineComment(line, spec.singleComment, stringDelimiters);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
if (preserveIndent) {
|
|
379
|
+
const leading = line.slice(0, line.length - line.trimStart().length);
|
|
380
|
+
const content = line.trim();
|
|
381
|
+
if (!content) {
|
|
382
|
+
index += 1;
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
line = `${leading}${content}`;
|
|
386
|
+
} else {
|
|
387
|
+
line = line.trim();
|
|
388
|
+
if (!line) {
|
|
389
|
+
index += 1;
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
line = line.replace(/[ \t]+$/g, "");
|
|
395
|
+
if (line) {
|
|
396
|
+
retainedEntries.push([index + 1, line]);
|
|
397
|
+
}
|
|
398
|
+
index += 1;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const compressedLines = retainedEntries.map(([sourceLineNumber, text], outputIndex) =>
|
|
402
|
+
buildCompressedLineEntry(text, sourceLineNumber, outputIndex + 1, includeLineNumbers),
|
|
403
|
+
);
|
|
404
|
+
const sourceLineCount = countLogicalLines(source);
|
|
405
|
+
const sourceStartLineNumber = compressedLines[0]?.source_line_number ?? 0;
|
|
406
|
+
const sourceEndLineNumber = compressedLines[compressedLines.length - 1]?.source_line_number ?? 0;
|
|
407
|
+
|
|
408
|
+
return {
|
|
409
|
+
language_id: langKey,
|
|
410
|
+
include_line_numbers: includeLineNumbers,
|
|
411
|
+
source_line_count: sourceLineCount,
|
|
412
|
+
source_start_line_number: sourceStartLineNumber,
|
|
413
|
+
source_end_line_number: sourceEndLineNumber,
|
|
414
|
+
source_line_range: [sourceStartLineNumber, sourceEndLineNumber],
|
|
415
|
+
compressed_line_count: compressedLines.length,
|
|
416
|
+
removed_line_count: Math.max(sourceLineCount - compressedLines.length, 0),
|
|
417
|
+
compressed_lines: compressedLines,
|
|
418
|
+
compressed_source_text: formatCompressedSourceText(compressedLines),
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* @brief Compresses in-memory source text for one language.
|
|
424
|
+
* @details Delegates to `compressSourceDetailed(...)` and returns only the rendered compressed source text so legacy CLI and markdown-oriented paths keep their existing behavior. Runtime is O(n) in source length. No external state is mutated.
|
|
425
|
+
* @param[in] source {string} Raw source text.
|
|
426
|
+
* @param[in] language {string} Canonical compression language identifier.
|
|
427
|
+
* @param[in] includeLineNumbers {boolean} When `true`, include original line-number prefixes in the output.
|
|
428
|
+
* @return {string} Compressed source text.
|
|
429
|
+
* @throws {Error} Throws when the language is unsupported.
|
|
430
|
+
*/
|
|
431
|
+
export function compressSource(source: string, language: string, includeLineNumbers = true): string {
|
|
432
|
+
return compressSourceDetailed(source, language, includeLineNumbers).compressed_source_text;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/**
|
|
436
|
+
* @brief Compresses one source file from disk into the structured compression model.
|
|
437
|
+
* @details Detects the language when not supplied, reads the file as UTF-8, and delegates to `compressSourceDetailed(...)`. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
|
|
438
|
+
* @param[in] filePath {string} Source file path.
|
|
439
|
+
* @param[in] language {string | undefined} Optional explicit language override.
|
|
440
|
+
* @param[in] includeLineNumbers {boolean} When `true`, prefix rendered text lines with original source line numbers.
|
|
441
|
+
* @return {CompressedSourceResult} Structured compression result.
|
|
442
|
+
* @throws {Error} Throws when the language cannot be detected or the file cannot be read.
|
|
443
|
+
*/
|
|
444
|
+
export function compressFileDetailed(filePath: string, language?: string, includeLineNumbers = true): CompressedSourceResult {
|
|
445
|
+
const detectedLanguage = language ?? detectLanguage(filePath);
|
|
446
|
+
if (!detectedLanguage) {
|
|
447
|
+
throw new Error(`Cannot detect language for '${filePath}'. Use --lang to specify explicitly.`);
|
|
448
|
+
}
|
|
449
|
+
const source = fs.readFileSync(filePath, "utf8");
|
|
450
|
+
return compressSourceDetailed(source, detectedLanguage, includeLineNumbers);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/**
|
|
454
|
+
* @brief Compresses one source file from disk.
|
|
455
|
+
* @details Delegates to `compressFileDetailed(...)` and returns only the rendered compressed source text so CLI and markdown emitters can retain their established text contract. Runtime is O(n) in file size. Side effects are limited to filesystem reads.
|
|
456
|
+
* @param[in] filePath {string} Source file path.
|
|
457
|
+
* @param[in] language {string | undefined} Optional explicit language override.
|
|
458
|
+
* @param[in] includeLineNumbers {boolean} When `true`, include original line-number prefixes in the output.
|
|
459
|
+
* @return {string} Compressed source text.
|
|
460
|
+
* @throws {Error} Throws when the language cannot be detected or the file cannot be read.
|
|
461
|
+
*/
|
|
462
|
+
export function compressFile(filePath: string, language?: string, includeLineNumbers = true): string {
|
|
463
|
+
return compressFileDetailed(filePath, language, includeLineNumbers).compressed_source_text;
|
|
464
|
+
}
|