@cairn-tool/cairn 2.0.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/.markdownlintrc +7 -0
- package/LICENSE +21 -0
- package/README.md +1431 -0
- package/dist/agent/audit/baseline.d.ts +69 -0
- package/dist/agent/audit/baseline.js +128 -0
- package/dist/agent/audit/baseline.js.map +1 -0
- package/dist/agent/audit/index.d.ts +126 -0
- package/dist/agent/audit/index.js +625 -0
- package/dist/agent/audit/index.js.map +1 -0
- package/dist/agent/import/detect.d.ts +49 -0
- package/dist/agent/import/detect.js +159 -0
- package/dist/agent/import/detect.js.map +1 -0
- package/dist/agent/import/normalize.d.ts +72 -0
- package/dist/agent/import/normalize.js +475 -0
- package/dist/agent/import/normalize.js.map +1 -0
- package/dist/agent/install/index.d.ts +211 -0
- package/dist/agent/install/index.js +907 -0
- package/dist/agent/install/index.js.map +1 -0
- package/dist/agent/manifest.d.ts +75 -0
- package/dist/agent/manifest.js +210 -0
- package/dist/agent/manifest.js.map +1 -0
- package/dist/agent/marketplace/index.d.ts +69 -0
- package/dist/agent/marketplace/index.js +212 -0
- package/dist/agent/marketplace/index.js.map +1 -0
- package/dist/agent/marketplace/spec.d.ts +48 -0
- package/dist/agent/marketplace/spec.js +237 -0
- package/dist/agent/marketplace/spec.js.map +1 -0
- package/dist/agent/output.d.ts +36 -0
- package/dist/agent/output.js +56 -0
- package/dist/agent/output.js.map +1 -0
- package/dist/agent/overlays.d.ts +38 -0
- package/dist/agent/overlays.js +223 -0
- package/dist/agent/overlays.js.map +1 -0
- package/dist/agent/package/index.d.ts +105 -0
- package/dist/agent/package/index.js +339 -0
- package/dist/agent/package/index.js.map +1 -0
- package/dist/agent/package/tar.d.ts +36 -0
- package/dist/agent/package/tar.js +137 -0
- package/dist/agent/package/tar.js.map +1 -0
- package/dist/agent/parser.d.ts +13 -0
- package/dist/agent/parser.js +559 -0
- package/dist/agent/parser.js.map +1 -0
- package/dist/agent/render.d.ts +16 -0
- package/dist/agent/render.js +721 -0
- package/dist/agent/render.js.map +1 -0
- package/dist/agent/sarif.d.ts +18 -0
- package/dist/agent/sarif.js +56 -0
- package/dist/agent/sarif.js.map +1 -0
- package/dist/agent/scaffold.d.ts +86 -0
- package/dist/agent/scaffold.js +250 -0
- package/dist/agent/scaffold.js.map +1 -0
- package/dist/agent/targets/antigravity.d.ts +17 -0
- package/dist/agent/targets/antigravity.js +218 -0
- package/dist/agent/targets/antigravity.js.map +1 -0
- package/dist/agent/targets/claude-code.d.ts +2 -0
- package/dist/agent/targets/claude-code.js +220 -0
- package/dist/agent/targets/claude-code.js.map +1 -0
- package/dist/agent/targets/codex.d.ts +2 -0
- package/dist/agent/targets/codex.js +212 -0
- package/dist/agent/targets/codex.js.map +1 -0
- package/dist/agent/targets/cursor.d.ts +2 -0
- package/dist/agent/targets/cursor.js +210 -0
- package/dist/agent/targets/cursor.js.map +1 -0
- package/dist/agent/targets/index.d.ts +31 -0
- package/dist/agent/targets/index.js +64 -0
- package/dist/agent/targets/index.js.map +1 -0
- package/dist/agent/targets/opencode.d.ts +15 -0
- package/dist/agent/targets/opencode.js +215 -0
- package/dist/agent/targets/opencode.js.map +1 -0
- package/dist/agent/targets/schema.d.ts +315 -0
- package/dist/agent/targets/schema.js +179 -0
- package/dist/agent/targets/schema.js.map +1 -0
- package/dist/agent/test/assert.d.ts +46 -0
- package/dist/agent/test/assert.js +288 -0
- package/dist/agent/test/assert.js.map +1 -0
- package/dist/agent/test/index.d.ts +73 -0
- package/dist/agent/test/index.js +181 -0
- package/dist/agent/test/index.js.map +1 -0
- package/dist/agent/test/schema.d.ts +81 -0
- package/dist/agent/test/schema.js +235 -0
- package/dist/agent/test/schema.js.map +1 -0
- package/dist/agent/types.d.ts +204 -0
- package/dist/agent/types.js +11 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/agent/upgrade.d.ts +29 -0
- package/dist/agent/upgrade.js +72 -0
- package/dist/agent/upgrade.js.map +1 -0
- package/dist/agent/writer.d.ts +30 -0
- package/dist/agent/writer.js +73 -0
- package/dist/agent/writer.js.map +1 -0
- package/dist/archive/db.d.ts +20 -0
- package/dist/archive/db.js +98 -0
- package/dist/archive/db.js.map +1 -0
- package/dist/archive/progress.d.ts +62 -0
- package/dist/archive/progress.js +151 -0
- package/dist/archive/progress.js.map +1 -0
- package/dist/archive/query.d.ts +86 -0
- package/dist/archive/query.js +241 -0
- package/dist/archive/query.js.map +1 -0
- package/dist/archive/run.d.ts +91 -0
- package/dist/archive/run.js +331 -0
- package/dist/archive/run.js.map +1 -0
- package/dist/archive/segments.d.ts +89 -0
- package/dist/archive/segments.js +144 -0
- package/dist/archive/segments.js.map +1 -0
- package/dist/archive/sets.d.ts +58 -0
- package/dist/archive/sets.js +344 -0
- package/dist/archive/sets.js.map +1 -0
- package/dist/archive/tar-read.d.ts +35 -0
- package/dist/archive/tar-read.js +90 -0
- package/dist/archive/tar-read.js.map +1 -0
- package/dist/audit-baseline.d.ts +66 -0
- package/dist/audit-baseline.js +124 -0
- package/dist/audit-baseline.js.map +1 -0
- package/dist/automation.d.ts +16 -0
- package/dist/automation.js +38 -0
- package/dist/automation.js.map +1 -0
- package/dist/backlinks.d.ts +15 -0
- package/dist/backlinks.js +30 -0
- package/dist/backlinks.js.map +1 -0
- package/dist/checkers/katex.d.ts +3 -0
- package/dist/checkers/katex.js +71 -0
- package/dist/checkers/katex.js.map +1 -0
- package/dist/checkers/markdown-lint.d.ts +28 -0
- package/dist/checkers/markdown-lint.js +53 -0
- package/dist/checkers/markdown-lint.js.map +1 -0
- package/dist/checkers/mermaid.d.ts +6 -0
- package/dist/checkers/mermaid.js +53 -0
- package/dist/checkers/mermaid.js.map +1 -0
- package/dist/checkers/references.d.ts +3 -0
- package/dist/checkers/references.js +55 -0
- package/dist/checkers/references.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1117 -0
- package/dist/cli.js.map +1 -0
- package/dist/command-result.d.ts +6 -0
- package/dist/command-result.js +13 -0
- package/dist/command-result.js.map +1 -0
- package/dist/commands/agent-audit.d.ts +21 -0
- package/dist/commands/agent-audit.js +119 -0
- package/dist/commands/agent-audit.js.map +1 -0
- package/dist/commands/agent-doctor.d.ts +25 -0
- package/dist/commands/agent-doctor.js +217 -0
- package/dist/commands/agent-doctor.js.map +1 -0
- package/dist/commands/agent-import.d.ts +21 -0
- package/dist/commands/agent-import.js +212 -0
- package/dist/commands/agent-import.js.map +1 -0
- package/dist/commands/agent-install.d.ts +18 -0
- package/dist/commands/agent-install.js +59 -0
- package/dist/commands/agent-install.js.map +1 -0
- package/dist/commands/agent-installed.d.ts +6 -0
- package/dist/commands/agent-installed.js +17 -0
- package/dist/commands/agent-installed.js.map +1 -0
- package/dist/commands/agent-marketplace.d.ts +11 -0
- package/dist/commands/agent-marketplace.js +178 -0
- package/dist/commands/agent-marketplace.js.map +1 -0
- package/dist/commands/agent-package.d.ts +16 -0
- package/dist/commands/agent-package.js +159 -0
- package/dist/commands/agent-package.js.map +1 -0
- package/dist/commands/agent-scaffold.d.ts +17 -0
- package/dist/commands/agent-scaffold.js +181 -0
- package/dist/commands/agent-scaffold.js.map +1 -0
- package/dist/commands/agent-specs.d.ts +7 -0
- package/dist/commands/agent-specs.js +20 -0
- package/dist/commands/agent-specs.js.map +1 -0
- package/dist/commands/agent-test.d.ts +21 -0
- package/dist/commands/agent-test.js +50 -0
- package/dist/commands/agent-test.js.map +1 -0
- package/dist/commands/agent-uninstall.d.ts +6 -0
- package/dist/commands/agent-uninstall.js +45 -0
- package/dist/commands/agent-uninstall.js.map +1 -0
- package/dist/commands/agent-upgrade.d.ts +5 -0
- package/dist/commands/agent-upgrade.js +105 -0
- package/dist/commands/agent-upgrade.js.map +1 -0
- package/dist/commands/agent.d.ts +27 -0
- package/dist/commands/agent.js +549 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/archive.d.ts +47 -0
- package/dist/commands/archive.js +311 -0
- package/dist/commands/archive.js.map +1 -0
- package/dist/commands/audit.d.ts +25 -0
- package/dist/commands/audit.js +325 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/check-snippets.d.ts +58 -0
- package/dist/commands/check-snippets.js +247 -0
- package/dist/commands/check-snippets.js.map +1 -0
- package/dist/commands/check-urls.d.ts +52 -0
- package/dist/commands/check-urls.js +205 -0
- package/dist/commands/check-urls.js.map +1 -0
- package/dist/commands/code-blocks.d.ts +8 -0
- package/dist/commands/code-blocks.js +66 -0
- package/dist/commands/code-blocks.js.map +1 -0
- package/dist/commands/completion.d.ts +15 -0
- package/dist/commands/completion.js +20 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/context.d.ts +16 -0
- package/dist/commands/context.js +131 -0
- package/dist/commands/context.js.map +1 -0
- package/dist/commands/describe.d.ts +12 -0
- package/dist/commands/describe.js +62 -0
- package/dist/commands/describe.js.map +1 -0
- package/dist/commands/diff.d.ts +11 -0
- package/dist/commands/diff.js +185 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/fix.d.ts +59 -0
- package/dist/commands/fix.js +173 -0
- package/dist/commands/fix.js.map +1 -0
- package/dist/commands/frontmatter.d.ts +7 -0
- package/dist/commands/frontmatter.js +84 -0
- package/dist/commands/frontmatter.js.map +1 -0
- package/dist/commands/graph.d.ts +12 -0
- package/dist/commands/graph.js +122 -0
- package/dist/commands/graph.js.map +1 -0
- package/dist/commands/headers.d.ts +7 -0
- package/dist/commands/headers.js +48 -0
- package/dist/commands/headers.js.map +1 -0
- package/dist/commands/index.d.ts +8 -0
- package/dist/commands/index.js +32 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/links.d.ts +9 -0
- package/dist/commands/links.js +123 -0
- package/dist/commands/links.js.map +1 -0
- package/dist/commands/lint-dir.d.ts +15 -0
- package/dist/commands/lint-dir.js +156 -0
- package/dist/commands/lint-dir.js.map +1 -0
- package/dist/commands/lint.d.ts +14 -0
- package/dist/commands/lint.js +45 -0
- package/dist/commands/lint.js.map +1 -0
- package/dist/commands/orphans.d.ts +10 -0
- package/dist/commands/orphans.js +74 -0
- package/dist/commands/orphans.js.map +1 -0
- package/dist/commands/outline.d.ts +7 -0
- package/dist/commands/outline.js +54 -0
- package/dist/commands/outline.js.map +1 -0
- package/dist/commands/query.d.ts +18 -0
- package/dist/commands/query.js +341 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/commands/refs-to.d.ts +8 -0
- package/dist/commands/refs-to.js +65 -0
- package/dist/commands/refs-to.js.map +1 -0
- package/dist/commands/refs.d.ts +10 -0
- package/dist/commands/refs.js +103 -0
- package/dist/commands/refs.js.map +1 -0
- package/dist/commands/rename-file.d.ts +16 -0
- package/dist/commands/rename-file.js +215 -0
- package/dist/commands/rename-file.js.map +1 -0
- package/dist/commands/rename-heading.d.ts +10 -0
- package/dist/commands/rename-heading.js +182 -0
- package/dist/commands/rename-heading.js.map +1 -0
- package/dist/commands/schema.d.ts +10 -0
- package/dist/commands/schema.js +34 -0
- package/dist/commands/schema.js.map +1 -0
- package/dist/commands/scripts.d.ts +59 -0
- package/dist/commands/scripts.js +222 -0
- package/dist/commands/scripts.js.map +1 -0
- package/dist/commands/section.d.ts +9 -0
- package/dist/commands/section.js +49 -0
- package/dist/commands/section.js.map +1 -0
- package/dist/commands/serve.d.ts +6 -0
- package/dist/commands/serve.js +48 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/stats.d.ts +6 -0
- package/dist/commands/stats.js +109 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/commands/structure.d.ts +6 -0
- package/dist/commands/structure.js +130 -0
- package/dist/commands/structure.js.map +1 -0
- package/dist/commands/tables.d.ts +8 -0
- package/dist/commands/tables.js +77 -0
- package/dist/commands/tables.js.map +1 -0
- package/dist/commands/tasks.d.ts +8 -0
- package/dist/commands/tasks.js +59 -0
- package/dist/commands/tasks.js.map +1 -0
- package/dist/commands/toc.d.ts +18 -0
- package/dist/commands/toc.js +105 -0
- package/dist/commands/toc.js.map +1 -0
- package/dist/commands/update-check.d.ts +36 -0
- package/dist/commands/update-check.js +119 -0
- package/dist/commands/update-check.js.map +1 -0
- package/dist/commands/usage.d.ts +56 -0
- package/dist/commands/usage.js +883 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/validate-frontmatter.d.ts +13 -0
- package/dist/commands/validate-frontmatter.js +34 -0
- package/dist/commands/validate-frontmatter.js.map +1 -0
- package/dist/completion/model.d.ts +49 -0
- package/dist/completion/model.js +194 -0
- package/dist/completion/model.js.map +1 -0
- package/dist/completion/shells.d.ts +2 -0
- package/dist/completion/shells.js +280 -0
- package/dist/completion/shells.js.map +1 -0
- package/dist/config-schema.d.ts +15 -0
- package/dist/config-schema.js +44 -0
- package/dist/config-schema.js.map +1 -0
- package/dist/config.d.ts +102 -0
- package/dist/config.js +614 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +106 -0
- package/dist/context.js +202 -0
- package/dist/context.js.map +1 -0
- package/dist/contract/describe.d.ts +84 -0
- package/dist/contract/describe.js +104 -0
- package/dist/contract/describe.js.map +1 -0
- package/dist/contract/registry.d.ts +2 -0
- package/dist/contract/registry.js +622 -0
- package/dist/contract/registry.js.map +1 -0
- package/dist/contract/schemas/agent.d.ts +2 -0
- package/dist/contract/schemas/agent.js +572 -0
- package/dist/contract/schemas/agent.js.map +1 -0
- package/dist/contract/schemas/archive.d.ts +3 -0
- package/dist/contract/schemas/archive.js +227 -0
- package/dist/contract/schemas/archive.js.map +1 -0
- package/dist/contract/schemas/index.d.ts +11 -0
- package/dist/contract/schemas/index.js +49 -0
- package/dist/contract/schemas/index.js.map +1 -0
- package/dist/contract/schemas/markdown.d.ts +15 -0
- package/dist/contract/schemas/markdown.js +1035 -0
- package/dist/contract/schemas/markdown.js.map +1 -0
- package/dist/contract/schemas/meta.d.ts +5 -0
- package/dist/contract/schemas/meta.js +233 -0
- package/dist/contract/schemas/meta.js.map +1 -0
- package/dist/contract/schemas/scripts.d.ts +4 -0
- package/dist/contract/schemas/scripts.js +183 -0
- package/dist/contract/schemas/scripts.js.map +1 -0
- package/dist/contract/schemas/shared.d.ts +11 -0
- package/dist/contract/schemas/shared.js +26 -0
- package/dist/contract/schemas/shared.js.map +1 -0
- package/dist/contract/schemas/usage.d.ts +6 -0
- package/dist/contract/schemas/usage.js +489 -0
- package/dist/contract/schemas/usage.js.map +1 -0
- package/dist/contract/types.d.ts +63 -0
- package/dist/contract/types.js +2 -0
- package/dist/contract/types.js.map +1 -0
- package/dist/contract/version.d.ts +20 -0
- package/dist/contract/version.js +21 -0
- package/dist/contract/version.js.map +1 -0
- package/dist/diff.d.ts +156 -0
- package/dist/diff.js +500 -0
- package/dist/diff.js.map +1 -0
- package/dist/edit-plan.d.ts +133 -0
- package/dist/edit-plan.js +245 -0
- package/dist/edit-plan.js.map +1 -0
- package/dist/fix/markdownlint-fixer.d.ts +34 -0
- package/dist/fix/markdownlint-fixer.js +125 -0
- package/dist/fix/markdownlint-fixer.js.map +1 -0
- package/dist/fix/registry.d.ts +48 -0
- package/dist/fix/registry.js +28 -0
- package/dist/fix/registry.js.map +1 -0
- package/dist/fix/relative-links-fixer.d.ts +21 -0
- package/dist/fix/relative-links-fixer.js +96 -0
- package/dist/fix/relative-links-fixer.js.map +1 -0
- package/dist/fix/snippets-fixer.d.ts +2 -0
- package/dist/fix/snippets-fixer.js +64 -0
- package/dist/fix/snippets-fixer.js.map +1 -0
- package/dist/fix/toc-fixer.d.ts +2 -0
- package/dist/fix/toc-fixer.js +94 -0
- package/dist/fix/toc-fixer.js.map +1 -0
- package/dist/formats.d.ts +22 -0
- package/dist/formats.js +34 -0
- package/dist/formats.js.map +1 -0
- package/dist/formatters.d.ts +11 -0
- package/dist/formatters.js +48 -0
- package/dist/formatters.js.map +1 -0
- package/dist/frontmatter-validation.d.ts +11 -0
- package/dist/frontmatter-validation.js +188 -0
- package/dist/frontmatter-validation.js.map +1 -0
- package/dist/git.d.ts +40 -0
- package/dist/git.js +124 -0
- package/dist/git.js.map +1 -0
- package/dist/graph.d.ts +50 -0
- package/dist/graph.js +200 -0
- package/dist/graph.js.map +1 -0
- package/dist/input-selection.d.ts +9 -0
- package/dist/input-selection.js +122 -0
- package/dist/input-selection.js.map +1 -0
- package/dist/input.d.ts +2 -0
- package/dist/input.js +32 -0
- package/dist/input.js.map +1 -0
- package/dist/link-target.d.ts +39 -0
- package/dist/link-target.js +68 -0
- package/dist/link-target.js.map +1 -0
- package/dist/lint.d.ts +13 -0
- package/dist/lint.js +27 -0
- package/dist/lint.js.map +1 -0
- package/dist/markdown-ast.d.ts +73 -0
- package/dist/markdown-ast.js +187 -0
- package/dist/markdown-ast.js.map +1 -0
- package/dist/object-path.d.ts +14 -0
- package/dist/object-path.js +14 -0
- package/dist/object-path.js.map +1 -0
- package/dist/option-utils.d.ts +13 -0
- package/dist/option-utils.js +25 -0
- package/dist/option-utils.js.map +1 -0
- package/dist/outline.d.ts +16 -0
- package/dist/outline.js +32 -0
- package/dist/outline.js.map +1 -0
- package/dist/query/entities.d.ts +60 -0
- package/dist/query/entities.js +219 -0
- package/dist/query/entities.js.map +1 -0
- package/dist/query/execute.d.ts +22 -0
- package/dist/query/execute.js +0 -0
- package/dist/query/execute.js.map +1 -0
- package/dist/query/plan.d.ts +76 -0
- package/dist/query/plan.js +183 -0
- package/dist/query/plan.js.map +1 -0
- package/dist/query/render.d.ts +3 -0
- package/dist/query/render.js +39 -0
- package/dist/query/render.js.map +1 -0
- package/dist/refs.d.ts +19 -0
- package/dist/refs.js +10 -0
- package/dist/refs.js.map +1 -0
- package/dist/result.d.ts +49 -0
- package/dist/result.js +47 -0
- package/dist/result.js.map +1 -0
- package/dist/runtime.d.ts +35 -0
- package/dist/runtime.js +77 -0
- package/dist/runtime.js.map +1 -0
- package/dist/sarif.d.ts +36 -0
- package/dist/sarif.js +30 -0
- package/dist/sarif.js.map +1 -0
- package/dist/scripts/execute.d.ts +65 -0
- package/dist/scripts/execute.js +235 -0
- package/dist/scripts/execute.js.map +1 -0
- package/dist/scripts/registry.d.ts +55 -0
- package/dist/scripts/registry.js +103 -0
- package/dist/scripts/registry.js.map +1 -0
- package/dist/scripts/resolve.d.ts +90 -0
- package/dist/scripts/resolve.js +288 -0
- package/dist/scripts/resolve.js.map +1 -0
- package/dist/sections.d.ts +53 -0
- package/dist/sections.js +100 -0
- package/dist/sections.js.map +1 -0
- package/dist/serve/errors.d.ts +25 -0
- package/dist/serve/errors.js +45 -0
- package/dist/serve/errors.js.map +1 -0
- package/dist/serve/paths.d.ts +32 -0
- package/dist/serve/paths.js +71 -0
- package/dist/serve/paths.js.map +1 -0
- package/dist/serve/server.d.ts +31 -0
- package/dist/serve/server.js +123 -0
- package/dist/serve/server.js.map +1 -0
- package/dist/serve/tools.d.ts +19 -0
- package/dist/serve/tools.js +597 -0
- package/dist/serve/tools.js.map +1 -0
- package/dist/snippets.d.ts +184 -0
- package/dist/snippets.js +454 -0
- package/dist/snippets.js.map +1 -0
- package/dist/sqlite-store.d.ts +62 -0
- package/dist/sqlite-store.js +104 -0
- package/dist/sqlite-store.js.map +1 -0
- package/dist/sqlite.d.ts +59 -0
- package/dist/sqlite.js +51 -0
- package/dist/sqlite.js.map +1 -0
- package/dist/toc.d.ts +58 -0
- package/dist/toc.js +83 -0
- package/dist/toc.js.map +1 -0
- package/dist/types.d.ts +7 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/update-notifier.d.ts +95 -0
- package/dist/update-notifier.js +301 -0
- package/dist/update-notifier.js.map +1 -0
- package/dist/url-cache.d.ts +14 -0
- package/dist/url-cache.js +70 -0
- package/dist/url-cache.js.map +1 -0
- package/dist/usage/aggregate.d.ts +107 -0
- package/dist/usage/aggregate.js +435 -0
- package/dist/usage/aggregate.js.map +1 -0
- package/dist/usage/db/index.d.ts +49 -0
- package/dist/usage/db/index.js +118 -0
- package/dist/usage/db/index.js.map +1 -0
- package/dist/usage/db/migrations.d.ts +29 -0
- package/dist/usage/db/migrations.js +38 -0
- package/dist/usage/db/migrations.js.map +1 -0
- package/dist/usage/db/open.d.ts +33 -0
- package/dist/usage/db/open.js +37 -0
- package/dist/usage/db/open.js.map +1 -0
- package/dist/usage/db/schema.d.ts +18 -0
- package/dist/usage/db/schema.js +147 -0
- package/dist/usage/db/schema.js.map +1 -0
- package/dist/usage/db/store.d.ts +74 -0
- package/dist/usage/db/store.js +280 -0
- package/dist/usage/db/store.js.map +1 -0
- package/dist/usage/events.d.ts +202 -0
- package/dist/usage/events.js +243 -0
- package/dist/usage/events.js.map +1 -0
- package/dist/usage/filter.d.ts +43 -0
- package/dist/usage/filter.js +97 -0
- package/dist/usage/filter.js.map +1 -0
- package/dist/usage/providers/antigravity.d.ts +2 -0
- package/dist/usage/providers/antigravity.js +431 -0
- package/dist/usage/providers/antigravity.js.map +1 -0
- package/dist/usage/providers/claude-code.d.ts +2 -0
- package/dist/usage/providers/claude-code.js +400 -0
- package/dist/usage/providers/claude-code.js.map +1 -0
- package/dist/usage/providers/codex.d.ts +2 -0
- package/dist/usage/providers/codex.js +387 -0
- package/dist/usage/providers/codex.js.map +1 -0
- package/dist/usage/providers/gemini-cli.d.ts +2 -0
- package/dist/usage/providers/gemini-cli.js +466 -0
- package/dist/usage/providers/gemini-cli.js.map +1 -0
- package/dist/usage/providers/index.d.ts +23 -0
- package/dist/usage/providers/index.js +46 -0
- package/dist/usage/providers/index.js.map +1 -0
- package/dist/usage/providers/opencode.d.ts +2 -0
- package/dist/usage/providers/opencode.js +422 -0
- package/dist/usage/providers/opencode.js.map +1 -0
- package/dist/usage/providers/protobuf.d.ts +35 -0
- package/dist/usage/providers/protobuf.js +125 -0
- package/dist/usage/providers/protobuf.js.map +1 -0
- package/dist/usage/providers/types.d.ts +74 -0
- package/dist/usage/providers/types.js +2 -0
- package/dist/usage/providers/types.js.map +1 -0
- package/dist/usage/scan.d.ts +54 -0
- package/dist/usage/scan.js +216 -0
- package/dist/usage/scan.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/dist/workspace-index.d.ts +39 -0
- package/dist/workspace-index.js +265 -0
- package/dist/workspace-index.js.map +1 -0
- package/dist/workspace.d.ts +89 -0
- package/dist/workspace.js +219 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +92 -0
|
@@ -0,0 +1,883 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import { terminate } from "../command-result.js";
|
|
3
|
+
import { BASE_FORMATS } from "../formats.js";
|
|
4
|
+
import { boundedInteger } from "../option-utils.js";
|
|
5
|
+
import { jsonPayload } from "../result.js";
|
|
6
|
+
import { TOOL_KINDS, totalTokens } from "../usage/events.js";
|
|
7
|
+
import { parseProject, resolveWindow } from "../usage/filter.js";
|
|
8
|
+
import { clearDatabase, databaseStatus, getUsageDatabasePath, LATEST_VERSION, MIGRATIONS, openUsageDatabase, storeStatus, } from "../usage/db/index.js";
|
|
9
|
+
import { ALL_PROVIDERS, DEFAULT_PROVIDER, PROVIDERS, resolveProviders, } from "../usage/providers/index.js";
|
|
10
|
+
import { keepRecentSessions, scan } from "../usage/scan.js";
|
|
11
|
+
import { AGENT_DIMENSIONS, SESSION_SORTS, TOKEN_DIMENSIONS, TOOL_DIMENSIONS, rollupAgents, rollupCommands, rollupHooks, rollupProjects, rollupSessions, rollupSkills, rollupTokens, rollupTools, summarize, } from "../usage/aggregate.js";
|
|
12
|
+
/**
|
|
13
|
+
* Formats are validated here rather than through `commandOptions`, which is
|
|
14
|
+
* keyed on bare `md` subcommand names and whose error text says `md <command>`.
|
|
15
|
+
* The `agent` and `scripts` subcommands validate inline for the same reason.
|
|
16
|
+
*
|
|
17
|
+
* `usage` is also deliberately absent from `COMMAND_OPTIONS`: it reports on logs
|
|
18
|
+
* outside the workspace entirely, so a checked-in configuration file has no
|
|
19
|
+
* business steering what it reads.
|
|
20
|
+
*/
|
|
21
|
+
function resolveFormat(opts) {
|
|
22
|
+
const format = (opts.format ?? "llm");
|
|
23
|
+
if (!BASE_FORMATS.includes(format)) {
|
|
24
|
+
throw new Error(`Invalid output format: ${String(opts.format)}`);
|
|
25
|
+
}
|
|
26
|
+
if (opts.envelope && format !== "json") {
|
|
27
|
+
throw new Error("--envelope requires --format json");
|
|
28
|
+
}
|
|
29
|
+
return format;
|
|
30
|
+
}
|
|
31
|
+
function choice(value, allowed, flag, fallback) {
|
|
32
|
+
if (value === undefined)
|
|
33
|
+
return fallback;
|
|
34
|
+
if (allowed.includes(value))
|
|
35
|
+
return value;
|
|
36
|
+
throw new Error(`Invalid ${flag} value: ${value} (expected ${allowed.join(", ")})`);
|
|
37
|
+
}
|
|
38
|
+
function rootOf(provider, override) {
|
|
39
|
+
return provider.root({
|
|
40
|
+
env: process.env,
|
|
41
|
+
home: os.homedir(),
|
|
42
|
+
...(override ? { override } : {}),
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
function resolveScope(opts) {
|
|
46
|
+
const selector = opts.provider ?? DEFAULT_PROVIDER;
|
|
47
|
+
const selected = resolveProviders(opts.provider);
|
|
48
|
+
const last = opts.last === undefined ? null : boundedInteger(opts.last, "last");
|
|
49
|
+
// `--logs` names one directory, which cannot be the log root of several
|
|
50
|
+
// providers at once.
|
|
51
|
+
if (opts.logs && selected.length > 1) {
|
|
52
|
+
throw new Error(`--logs cannot be combined with --provider ${ALL_PROVIDERS}`);
|
|
53
|
+
}
|
|
54
|
+
const sources = [];
|
|
55
|
+
for (const provider of selected) {
|
|
56
|
+
const root = rootOf(provider, opts.logs);
|
|
57
|
+
if (root)
|
|
58
|
+
sources.push({ provider, root });
|
|
59
|
+
}
|
|
60
|
+
// Naming one provider that is not here is an error; `all` finding nothing is
|
|
61
|
+
// an empty report, because asking for everything cannot be a mistake.
|
|
62
|
+
if (sources.length === 0 && selected.length === 1) {
|
|
63
|
+
const provider = selected[0];
|
|
64
|
+
throw new Error(`No ${provider.title} logs found. ${provider.source}. Pass --logs <dir> to point at them explicitly.`);
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
selector,
|
|
68
|
+
selected,
|
|
69
|
+
sources,
|
|
70
|
+
window: resolveWindow(opts.since, opts.until),
|
|
71
|
+
selectors: (opts.project ?? []).map((value) => parseProject(value)),
|
|
72
|
+
subagents: opts.subagents !== false,
|
|
73
|
+
last,
|
|
74
|
+
useIndex: opts.index !== false,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function scopePayload(scope) {
|
|
78
|
+
return {
|
|
79
|
+
provider: scope.selector,
|
|
80
|
+
providers: scope.sources.map((source) => source.provider.name),
|
|
81
|
+
root: scope.sources[0]?.root ?? "",
|
|
82
|
+
roots: Object.fromEntries(scope.sources.map((source) => [source.provider.name, source.root])),
|
|
83
|
+
window: { since: scope.window.since, until: scope.window.until },
|
|
84
|
+
projects: scope.selectors.map((selector) => selector.raw),
|
|
85
|
+
subagents: scope.subagents,
|
|
86
|
+
last: scope.last,
|
|
87
|
+
index: scope.useIndex,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Scans every selected provider and merges the results.
|
|
92
|
+
*
|
|
93
|
+
* Each keeps its own cache, and every aggregate already carries the provider
|
|
94
|
+
* that produced it, so the rollups need no further help to separate them.
|
|
95
|
+
*/
|
|
96
|
+
async function collect(scope) {
|
|
97
|
+
const merged = {
|
|
98
|
+
files: [],
|
|
99
|
+
counters: { discovered: 0, cached: 0, parsed: 0, skipped: 0, malformed: 0, selected: 0 },
|
|
100
|
+
failures: [],
|
|
101
|
+
cacheRoot: null,
|
|
102
|
+
};
|
|
103
|
+
for (const source of scope.sources) {
|
|
104
|
+
const result = await scan({
|
|
105
|
+
provider: source.provider,
|
|
106
|
+
root: source.root,
|
|
107
|
+
subagents: scope.subagents,
|
|
108
|
+
window: scope.window,
|
|
109
|
+
projects: scope.selectors,
|
|
110
|
+
...(scope.last !== null ? { last: scope.last } : {}),
|
|
111
|
+
useIndex: scope.useIndex,
|
|
112
|
+
});
|
|
113
|
+
merged.files.push(...result.files);
|
|
114
|
+
merged.failures.push(...result.failures);
|
|
115
|
+
merged.cacheRoot ??= result.cacheRoot;
|
|
116
|
+
for (const key of Object.keys(merged.counters)) {
|
|
117
|
+
merged.counters[key] += result.counters[key];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// `--last` means the n most recent sessions overall, not n per provider.
|
|
121
|
+
if (scope.last !== null && scope.last > 0) {
|
|
122
|
+
merged.files = keepRecentSessions(merged.files, scope.last);
|
|
123
|
+
merged.counters.selected = merged.files.length;
|
|
124
|
+
}
|
|
125
|
+
return merged;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Whether any scanned provider records the thing a report is about.
|
|
129
|
+
*
|
|
130
|
+
* This is the whole point of `capabilities` being data: a command that a
|
|
131
|
+
* provider cannot answer says so, rather than printing an empty table that
|
|
132
|
+
* reads as "you never did this".
|
|
133
|
+
*/
|
|
134
|
+
function supportedBy(scope, capability) {
|
|
135
|
+
const sources = scope.sources.length > 0 ? scope.sources.map((s) => s.provider) : scope.selected;
|
|
136
|
+
return sources.some((provider) => provider.capabilities[capability]);
|
|
137
|
+
}
|
|
138
|
+
function unsupportedMessage(scope, capability) {
|
|
139
|
+
const providers = scope.sources.length > 0 ? scope.sources.map((s) => s.provider) : scope.selected;
|
|
140
|
+
const names = providers.map((provider) => provider.title).join(", ");
|
|
141
|
+
const available = CAPABILITY_REPORTS.filter(([, key]) => providers.some((provider) => provider.capabilities[key])).map(([report]) => report);
|
|
142
|
+
return [
|
|
143
|
+
`${names} does not record ${CAPABILITY_LABELS[capability]}.`,
|
|
144
|
+
available.length > 0 ? `Available: ${available.join(", ")}` : "",
|
|
145
|
+
].filter(Boolean);
|
|
146
|
+
}
|
|
147
|
+
const CAPABILITY_LABELS = {
|
|
148
|
+
tokens: "token usage",
|
|
149
|
+
cacheTokens: "cache token detail",
|
|
150
|
+
tools: "tool calls",
|
|
151
|
+
skills: "skill invocations",
|
|
152
|
+
subagents: "subagent activity",
|
|
153
|
+
hooks: "hook executions",
|
|
154
|
+
mcp: "MCP tool calls",
|
|
155
|
+
slashCommands: "slash commands",
|
|
156
|
+
projects: "working directories",
|
|
157
|
+
};
|
|
158
|
+
/** Subcommands whose availability is worth listing when another is refused. */
|
|
159
|
+
const CAPABILITY_REPORTS = [
|
|
160
|
+
["tokens", "tokens"],
|
|
161
|
+
["tools", "tools"],
|
|
162
|
+
["skills", "skills"],
|
|
163
|
+
["agents", "subagents"],
|
|
164
|
+
["hooks", "hooks"],
|
|
165
|
+
["commands", "slashCommands"],
|
|
166
|
+
["projects", "projects"],
|
|
167
|
+
];
|
|
168
|
+
/**
|
|
169
|
+
* A report over thousands of transcripts is expected to meet a few it cannot
|
|
170
|
+
* read: a file removed mid-scan, a truncated final line in a session still being
|
|
171
|
+
* written. Those are counted and reported, never fatal, because blocking on them
|
|
172
|
+
* by default would make the command useless in exactly the automated context
|
|
173
|
+
* where it is most wanted. `--strict` is how a caller opts into caring.
|
|
174
|
+
*/
|
|
175
|
+
function decideExit(counters, failures, strict) {
|
|
176
|
+
if (!strict)
|
|
177
|
+
return 0;
|
|
178
|
+
return counters.skipped > 0 || counters.malformed > 0 || failures.length > 0 ? 2 : 0;
|
|
179
|
+
}
|
|
180
|
+
/** The counters a report that never scanned should still publish. */
|
|
181
|
+
function emptyScan() {
|
|
182
|
+
return {
|
|
183
|
+
files: [],
|
|
184
|
+
counters: { discovered: 0, cached: 0, parsed: 0, skipped: 0, malformed: 0, selected: 0 },
|
|
185
|
+
failures: [],
|
|
186
|
+
cacheRoot: null,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function scanPayload(result) {
|
|
190
|
+
return { ...result.counters, failures: result.failures };
|
|
191
|
+
}
|
|
192
|
+
// ---------------------------------------------------------------------------
|
|
193
|
+
// Rendering
|
|
194
|
+
// ---------------------------------------------------------------------------
|
|
195
|
+
const BOLD = "\x1b[1m";
|
|
196
|
+
const DIM = "\x1b[2m";
|
|
197
|
+
const CYAN = "\x1b[36m";
|
|
198
|
+
const RED = "\x1b[31m";
|
|
199
|
+
const RESET = "\x1b[0m";
|
|
200
|
+
function style(text, code, human) {
|
|
201
|
+
return human ? `${code}${text}${RESET}` : text;
|
|
202
|
+
}
|
|
203
|
+
/** Human output abbreviates; llm output stays exact so a consumer can do arithmetic. */
|
|
204
|
+
function num(value, human) {
|
|
205
|
+
if (!human)
|
|
206
|
+
return String(value);
|
|
207
|
+
const abs = Math.abs(value);
|
|
208
|
+
if (abs >= 1_000_000_000)
|
|
209
|
+
return `${(value / 1_000_000_000).toFixed(1)}G`;
|
|
210
|
+
if (abs >= 1_000_000)
|
|
211
|
+
return `${(value / 1_000_000).toFixed(1)}M`;
|
|
212
|
+
if (abs >= 10_000)
|
|
213
|
+
return `${(value / 1_000).toFixed(1)}k`;
|
|
214
|
+
return String(value);
|
|
215
|
+
}
|
|
216
|
+
function duration(ms) {
|
|
217
|
+
if (ms < 1000)
|
|
218
|
+
return `${ms}ms`;
|
|
219
|
+
const seconds = Math.round(ms / 1000);
|
|
220
|
+
if (seconds < 60)
|
|
221
|
+
return `${seconds}s`;
|
|
222
|
+
const minutes = Math.floor(seconds / 60);
|
|
223
|
+
if (minutes < 60)
|
|
224
|
+
return `${minutes}m${String(seconds % 60).padStart(2, "0")}s`;
|
|
225
|
+
return `${Math.floor(minutes / 60)}h${String(minutes % 60).padStart(2, "0")}m`;
|
|
226
|
+
}
|
|
227
|
+
function table(columns, rows, human) {
|
|
228
|
+
if (rows.length === 0)
|
|
229
|
+
return [];
|
|
230
|
+
const widths = columns.map((column, index) => Math.max(column.header.length, ...rows.map((row) => (row[index] ?? "").length)));
|
|
231
|
+
const pad = (text, index) => columns[index].right ? text.padStart(widths[index]) : text.padEnd(widths[index]);
|
|
232
|
+
const lines = [
|
|
233
|
+
style(columns.map((column, index) => pad(column.header, index)).join(" "), BOLD, human).trimEnd(),
|
|
234
|
+
];
|
|
235
|
+
for (const row of rows) {
|
|
236
|
+
lines.push(columns
|
|
237
|
+
.map((_, index) => pad(row[index] ?? "", index))
|
|
238
|
+
.join(" ")
|
|
239
|
+
.trimEnd());
|
|
240
|
+
}
|
|
241
|
+
return lines;
|
|
242
|
+
}
|
|
243
|
+
function scanLine(result, human) {
|
|
244
|
+
const { discovered, cached, parsed, skipped, malformed } = result.counters;
|
|
245
|
+
const parts = [
|
|
246
|
+
`${discovered} transcript${discovered === 1 ? "" : "s"}`,
|
|
247
|
+
`${cached} cached`,
|
|
248
|
+
`${parsed} parsed`,
|
|
249
|
+
];
|
|
250
|
+
if (skipped > 0)
|
|
251
|
+
parts.push(`${skipped} unreadable`);
|
|
252
|
+
if (malformed > 0)
|
|
253
|
+
parts.push(`${malformed} malformed line${malformed === 1 ? "" : "s"}`);
|
|
254
|
+
return style(parts.join(", "), DIM, human);
|
|
255
|
+
}
|
|
256
|
+
function windowLine(scope, human) {
|
|
257
|
+
const since = scope.window.since ?? "beginning";
|
|
258
|
+
const until = scope.window.until ?? "now";
|
|
259
|
+
const projects = scope.selectors.length > 0 ? `, projects: ${scope.selectors.map((s) => s.raw).join(", ")}` : "";
|
|
260
|
+
const subagents = scope.subagents ? "" : ", subagents excluded";
|
|
261
|
+
return style(`${since} → ${until}${projects}${subagents}`, DIM, human);
|
|
262
|
+
}
|
|
263
|
+
function write(lines, exitCode) {
|
|
264
|
+
const stream = exitCode === 0 ? process.stdout : process.stderr;
|
|
265
|
+
stream.write(lines.join("\n") + "\n");
|
|
266
|
+
if (exitCode !== 0)
|
|
267
|
+
terminate(exitCode);
|
|
268
|
+
}
|
|
269
|
+
function totalsOfRows(rows) {
|
|
270
|
+
const tokens = {
|
|
271
|
+
input: 0,
|
|
272
|
+
output: 0,
|
|
273
|
+
cacheRead: 0,
|
|
274
|
+
cacheWrite: 0,
|
|
275
|
+
cacheWrite5m: 0,
|
|
276
|
+
cacheWrite1h: 0,
|
|
277
|
+
thinking: 0,
|
|
278
|
+
webSearch: 0,
|
|
279
|
+
webFetch: 0,
|
|
280
|
+
requests: 0,
|
|
281
|
+
};
|
|
282
|
+
let count = 0;
|
|
283
|
+
for (const row of rows) {
|
|
284
|
+
count += row.count;
|
|
285
|
+
if (!row.tokens)
|
|
286
|
+
continue;
|
|
287
|
+
tokens.input += row.tokens.input;
|
|
288
|
+
tokens.output += row.tokens.output;
|
|
289
|
+
tokens.cacheRead += row.tokens.cacheRead;
|
|
290
|
+
tokens.cacheWrite += row.tokens.cacheWrite;
|
|
291
|
+
tokens.cacheWrite5m += row.tokens.cacheWrite5m;
|
|
292
|
+
tokens.cacheWrite1h += row.tokens.cacheWrite1h;
|
|
293
|
+
tokens.thinking += row.tokens.thinking;
|
|
294
|
+
tokens.webSearch += row.tokens.webSearch;
|
|
295
|
+
tokens.webFetch += row.tokens.webFetch;
|
|
296
|
+
tokens.requests += row.tokens.requests;
|
|
297
|
+
}
|
|
298
|
+
return { rows: rows.length, count, tokens };
|
|
299
|
+
}
|
|
300
|
+
function clip(rows, opts) {
|
|
301
|
+
const top = opts.top === undefined ? 20 : boundedInteger(opts.top, "top");
|
|
302
|
+
if (top === 0 || rows.length <= top)
|
|
303
|
+
return { rows, truncated: false };
|
|
304
|
+
return { rows: rows.slice(0, top), truncated: true };
|
|
305
|
+
}
|
|
306
|
+
/** Every tabular subcommand funnels through here so they share one payload shape. */
|
|
307
|
+
async function emitRollup(command, dimension, capability, build, render, opts) {
|
|
308
|
+
const format = resolveFormat(opts);
|
|
309
|
+
const scope = resolveScope(opts);
|
|
310
|
+
const supported = capability === null || supportedBy(scope, capability);
|
|
311
|
+
const result = supported ? await collect(scope) : emptyScan();
|
|
312
|
+
const all = supported ? build(result.files) : [];
|
|
313
|
+
const { rows, truncated } = clip(all, opts);
|
|
314
|
+
const exitCode = decideExit(result.counters, result.failures, Boolean(opts.strict));
|
|
315
|
+
const payload = {
|
|
316
|
+
provider: scope.selector,
|
|
317
|
+
scope: scopePayload(scope),
|
|
318
|
+
dimension,
|
|
319
|
+
supported,
|
|
320
|
+
rows,
|
|
321
|
+
truncated,
|
|
322
|
+
totals: totalsOfRows(all),
|
|
323
|
+
scan: scanPayload(result),
|
|
324
|
+
};
|
|
325
|
+
if (format === "json") {
|
|
326
|
+
const output = jsonPayload(command, payload, opts, {
|
|
327
|
+
exitCode,
|
|
328
|
+
summary: { rows: all.length, transcripts: result.counters.discovered },
|
|
329
|
+
});
|
|
330
|
+
(exitCode === 0 ? process.stdout : process.stderr).write(output);
|
|
331
|
+
if (exitCode !== 0)
|
|
332
|
+
terminate(exitCode);
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
const human = format === "human";
|
|
336
|
+
const lines = [windowLine(scope, human)];
|
|
337
|
+
if (!supported) {
|
|
338
|
+
lines.push(...unsupportedMessage(scope, capability));
|
|
339
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
if (rows.length === 0)
|
|
343
|
+
lines.push("No matching activity.");
|
|
344
|
+
else
|
|
345
|
+
lines.push(...render(rows, human));
|
|
346
|
+
if (truncated) {
|
|
347
|
+
lines.push(style(`… ${all.length - rows.length} more (use --top 0 for all)`, DIM, human));
|
|
348
|
+
}
|
|
349
|
+
lines.push(scanLine(result, human));
|
|
350
|
+
write(lines, exitCode);
|
|
351
|
+
}
|
|
352
|
+
const TOKEN_COLUMNS = [
|
|
353
|
+
{ header: "key" },
|
|
354
|
+
{ header: "requests", right: true },
|
|
355
|
+
{ header: "input", right: true },
|
|
356
|
+
{ header: "output", right: true },
|
|
357
|
+
{ header: "cache-r", right: true },
|
|
358
|
+
{ header: "cache-w", right: true },
|
|
359
|
+
{ header: "total", right: true },
|
|
360
|
+
];
|
|
361
|
+
function tokenRows(rows, human) {
|
|
362
|
+
return rows.map((row) => {
|
|
363
|
+
const tokens = row.tokens;
|
|
364
|
+
return [
|
|
365
|
+
row.key,
|
|
366
|
+
num(row.count, human),
|
|
367
|
+
num(tokens?.input ?? 0, human),
|
|
368
|
+
num(tokens?.output ?? 0, human),
|
|
369
|
+
num(tokens?.cacheRead ?? 0, human),
|
|
370
|
+
num(tokens?.cacheWrite ?? 0, human),
|
|
371
|
+
num(tokens ? totalTokens(tokens) : 0, human),
|
|
372
|
+
];
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
// ---------------------------------------------------------------------------
|
|
376
|
+
// usage summary
|
|
377
|
+
// ---------------------------------------------------------------------------
|
|
378
|
+
export async function usageSummaryAction(opts) {
|
|
379
|
+
const format = resolveFormat(opts);
|
|
380
|
+
const scope = resolveScope(opts);
|
|
381
|
+
const result = await collect(scope);
|
|
382
|
+
const summary = summarize(result.files);
|
|
383
|
+
const exitCode = decideExit(result.counters, result.failures, Boolean(opts.strict));
|
|
384
|
+
const payload = {
|
|
385
|
+
provider: scope.selector,
|
|
386
|
+
scope: scopePayload(scope),
|
|
387
|
+
summary: {
|
|
388
|
+
...summary,
|
|
389
|
+
models: summary.models.slice(0, 10),
|
|
390
|
+
tools: summary.tools.slice(0, 10),
|
|
391
|
+
},
|
|
392
|
+
scan: scanPayload(result),
|
|
393
|
+
};
|
|
394
|
+
if (format === "json") {
|
|
395
|
+
const output = jsonPayload("usage summary", payload, opts, {
|
|
396
|
+
exitCode,
|
|
397
|
+
summary: { sessions: summary.sessions, tokens: totalTokens(summary.tokens) },
|
|
398
|
+
});
|
|
399
|
+
(exitCode === 0 ? process.stdout : process.stderr).write(output);
|
|
400
|
+
if (exitCode !== 0)
|
|
401
|
+
terminate(exitCode);
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
const human = format === "human";
|
|
405
|
+
const lines = [windowLine(scope, human)];
|
|
406
|
+
const span = summary.firstDay && summary.lastDay
|
|
407
|
+
? `${summary.firstDay} → ${summary.lastDay} (${summary.days} active day${summary.days === 1 ? "" : "s"})`
|
|
408
|
+
: "no activity";
|
|
409
|
+
lines.push("");
|
|
410
|
+
lines.push(style("Activity", BOLD, human));
|
|
411
|
+
lines.push(...table([{ header: "metric" }, { header: "value", right: true }], [
|
|
412
|
+
["span", span],
|
|
413
|
+
["sessions", num(summary.sessions, human)],
|
|
414
|
+
[
|
|
415
|
+
"transcripts",
|
|
416
|
+
`${num(summary.transcripts, human)} (${num(summary.subagentTranscripts, human)} subagent)`,
|
|
417
|
+
],
|
|
418
|
+
["projects", num(summary.projects, human)],
|
|
419
|
+
["prompts", num(summary.prompts, human)],
|
|
420
|
+
["requests", num(summary.tokens.requests, human)],
|
|
421
|
+
["compactions", num(summary.compactions, human)],
|
|
422
|
+
["api errors", num(summary.errors, human)],
|
|
423
|
+
], human));
|
|
424
|
+
lines.push("");
|
|
425
|
+
lines.push(style("Tokens", BOLD, human));
|
|
426
|
+
lines.push(...table([{ header: "class" }, { header: "tokens", right: true }], [
|
|
427
|
+
["input", num(summary.tokens.input, human)],
|
|
428
|
+
["output", num(summary.tokens.output, human)],
|
|
429
|
+
[" of which thinking", num(summary.tokens.thinking, human)],
|
|
430
|
+
["cache read", num(summary.tokens.cacheRead, human)],
|
|
431
|
+
["cache write", num(summary.tokens.cacheWrite, human)],
|
|
432
|
+
[" 5m ttl", num(summary.tokens.cacheWrite5m, human)],
|
|
433
|
+
[" 1h ttl", num(summary.tokens.cacheWrite1h, human)],
|
|
434
|
+
["total", num(totalTokens(summary.tokens), human)],
|
|
435
|
+
[" main", num(totalTokens(summary.tokensByKind.main), human)],
|
|
436
|
+
[" subagent", num(totalTokens(summary.tokensByKind.subagent), human)],
|
|
437
|
+
], human));
|
|
438
|
+
if (summary.models.length > 0) {
|
|
439
|
+
lines.push("");
|
|
440
|
+
lines.push(style("Models", BOLD, human));
|
|
441
|
+
lines.push(...table(TOKEN_COLUMNS, tokenRows(summary.models.slice(0, 10), human), human));
|
|
442
|
+
}
|
|
443
|
+
if (summary.tools.length > 0) {
|
|
444
|
+
lines.push("");
|
|
445
|
+
lines.push(style("Top tools", BOLD, human));
|
|
446
|
+
lines.push(...table([{ header: "tool" }, { header: "kind" }, { header: "calls", right: true }], summary.tools.slice(0, 10).map((row) => [row.key, row.kind ?? "", num(row.count, human)]), human));
|
|
447
|
+
}
|
|
448
|
+
lines.push("");
|
|
449
|
+
lines.push(style("Features", BOLD, human));
|
|
450
|
+
lines.push(...table([{ header: "feature" }, { header: "count", right: true }], [
|
|
451
|
+
["skill invocations", num(summary.features.skills, human)],
|
|
452
|
+
["subagents spawned", num(summary.features.subagents, human)],
|
|
453
|
+
["hook executions", num(summary.features.hooks, human)],
|
|
454
|
+
[" failures", num(summary.features.hookFailures, human)],
|
|
455
|
+
["mcp tool calls", num(summary.features.mcpCalls, human)],
|
|
456
|
+
["slash commands", num(summary.features.slashCommands, human)],
|
|
457
|
+
], human));
|
|
458
|
+
lines.push("");
|
|
459
|
+
lines.push(scanLine(result, human));
|
|
460
|
+
write(lines, exitCode);
|
|
461
|
+
}
|
|
462
|
+
// ---------------------------------------------------------------------------
|
|
463
|
+
// Tabular subcommands
|
|
464
|
+
// ---------------------------------------------------------------------------
|
|
465
|
+
export async function usageTokensAction(opts) {
|
|
466
|
+
const dimension = choice(opts.by, TOKEN_DIMENSIONS, "--by", "model");
|
|
467
|
+
await emitRollup("usage tokens", dimension, "tokens", (files) => rollupTokens(files, dimension), (rows, human) => table(TOKEN_COLUMNS, tokenRows(rows, human), human), opts);
|
|
468
|
+
}
|
|
469
|
+
export async function usageToolsAction(opts) {
|
|
470
|
+
const dimension = choice(opts.by, TOOL_DIMENSIONS, "--by", "name");
|
|
471
|
+
const kind = opts.kind === undefined
|
|
472
|
+
? undefined
|
|
473
|
+
: choice(opts.kind, TOOL_KINDS, "--kind", "builtin");
|
|
474
|
+
await emitRollup("usage tools", dimension, "tools", (files) => rollupTools(files, dimension, kind), (rows, human) => table(dimension === "name"
|
|
475
|
+
? [
|
|
476
|
+
{ header: "tool" },
|
|
477
|
+
{ header: "kind" },
|
|
478
|
+
{ header: "server" },
|
|
479
|
+
{ header: "calls", right: true },
|
|
480
|
+
]
|
|
481
|
+
: [{ header: dimension }, { header: "calls", right: true }], rows.map((row) => dimension === "name"
|
|
482
|
+
? [row.key, row.kind ?? "", row.server ?? "", num(row.count, human)]
|
|
483
|
+
: [row.key, num(row.count, human)]), human), opts);
|
|
484
|
+
}
|
|
485
|
+
export async function usageSessionsAction(opts) {
|
|
486
|
+
const sort = choice(opts.sort, SESSION_SORTS, "--sort", "recent");
|
|
487
|
+
await emitRollup("usage sessions", "session", null, (files) => rollupSessions(files, sort), (rows, human) => table([
|
|
488
|
+
{ header: "session" },
|
|
489
|
+
{ header: "last" },
|
|
490
|
+
{ header: "project" },
|
|
491
|
+
{ header: "tokens", right: true },
|
|
492
|
+
{ header: "tools", right: true },
|
|
493
|
+
{ header: "sub", right: true },
|
|
494
|
+
{ header: "duration", right: true },
|
|
495
|
+
{ header: "title" },
|
|
496
|
+
], rows.map((row) => [
|
|
497
|
+
row.key.slice(0, 8),
|
|
498
|
+
(row.lastTs ?? "").slice(0, 16).replace("T", " "),
|
|
499
|
+
row.project ? (row.project.split("/").pop() ?? "") : "",
|
|
500
|
+
num(row.tokens ? totalTokens(row.tokens) : 0, human),
|
|
501
|
+
num(row.toolCalls ?? 0, human),
|
|
502
|
+
num(row.subagents ?? 0, human),
|
|
503
|
+
duration(row.durationMs ?? 0),
|
|
504
|
+
row.title ?? "",
|
|
505
|
+
]), human), opts);
|
|
506
|
+
}
|
|
507
|
+
export async function usageProjectsAction(opts) {
|
|
508
|
+
await emitRollup("usage projects", "project", "projects", (files) => rollupProjects(files), (rows, human) => table([
|
|
509
|
+
{ header: "project" },
|
|
510
|
+
{ header: "sessions", right: true },
|
|
511
|
+
{ header: "requests", right: true },
|
|
512
|
+
{ header: "tools", right: true },
|
|
513
|
+
{ header: "tokens", right: true },
|
|
514
|
+
], rows.map((row) => [
|
|
515
|
+
row.key,
|
|
516
|
+
num(row.sessions ?? 0, human),
|
|
517
|
+
num(row.count, human),
|
|
518
|
+
num(row.toolCalls ?? 0, human),
|
|
519
|
+
num(row.tokens ? totalTokens(row.tokens) : 0, human),
|
|
520
|
+
]), human), opts);
|
|
521
|
+
}
|
|
522
|
+
export async function usageSkillsAction(opts) {
|
|
523
|
+
await emitRollup("usage skills", "skill", "skills", (files) => rollupSkills(files), (rows, human) => table([
|
|
524
|
+
{ header: "skill" },
|
|
525
|
+
{ header: "invocations", right: true },
|
|
526
|
+
{ header: "sessions", right: true },
|
|
527
|
+
], rows.map((row) => [row.key, num(row.count, human), num(row.sessions ?? 0, human)]), human), opts);
|
|
528
|
+
}
|
|
529
|
+
export async function usageAgentsAction(opts) {
|
|
530
|
+
const dimension = choice(opts.by, AGENT_DIMENSIONS, "--by", "role");
|
|
531
|
+
await emitRollup("usage agents", dimension, "subagents", (files) => rollupAgents(files, dimension), (rows, human) => table([
|
|
532
|
+
{ header: dimension },
|
|
533
|
+
{ header: "spawns", right: true },
|
|
534
|
+
{ header: "transcripts", right: true },
|
|
535
|
+
{ header: "depth", right: true },
|
|
536
|
+
{ header: "tools", right: true },
|
|
537
|
+
{ header: "tokens", right: true },
|
|
538
|
+
], rows.map((row) => [
|
|
539
|
+
row.key,
|
|
540
|
+
num(row.count, human),
|
|
541
|
+
num(row.sessions ?? 0, human),
|
|
542
|
+
num(row.maxDepth ?? 0, human),
|
|
543
|
+
num(row.toolCalls ?? 0, human),
|
|
544
|
+
num(row.tokens ? totalTokens(row.tokens) : 0, human),
|
|
545
|
+
]), human), opts);
|
|
546
|
+
}
|
|
547
|
+
export async function usageHooksAction(opts) {
|
|
548
|
+
await emitRollup("usage hooks", "hook", "hooks", (files) => rollupHooks(files), (rows, human) => table([
|
|
549
|
+
{ header: "hook" },
|
|
550
|
+
{ header: "runs", right: true },
|
|
551
|
+
{ header: "failures", right: true },
|
|
552
|
+
{ header: "cancelled", right: true },
|
|
553
|
+
{ header: "mean", right: true },
|
|
554
|
+
{ header: "max", right: true },
|
|
555
|
+
], rows.map((row) => [
|
|
556
|
+
row.key,
|
|
557
|
+
num(row.count, human),
|
|
558
|
+
style(num(row.failures ?? 0, human), (row.failures ?? 0) > 0 ? RED : RESET, human),
|
|
559
|
+
num(row.cancelled ?? 0, human),
|
|
560
|
+
duration(row.meanMs ?? 0),
|
|
561
|
+
duration(row.maxMs ?? 0),
|
|
562
|
+
]), human), opts);
|
|
563
|
+
}
|
|
564
|
+
export async function usageCommandsAction(opts) {
|
|
565
|
+
await emitRollup("usage commands", "command", "slashCommands", (files) => rollupCommands(files), (rows, human) => table([
|
|
566
|
+
{ header: "command" },
|
|
567
|
+
{ header: "uses", right: true },
|
|
568
|
+
{ header: "sessions", right: true },
|
|
569
|
+
], rows.map((row) => [row.key, num(row.count, human), num(row.sessions ?? 0, human)]), human), opts);
|
|
570
|
+
}
|
|
571
|
+
// ---------------------------------------------------------------------------
|
|
572
|
+
// usage providers
|
|
573
|
+
// ---------------------------------------------------------------------------
|
|
574
|
+
export async function usageProvidersAction(opts) {
|
|
575
|
+
const format = resolveFormat(opts);
|
|
576
|
+
const providers = PROVIDERS.map((provider) => {
|
|
577
|
+
const root = rootOf(provider, opts.logs);
|
|
578
|
+
return {
|
|
579
|
+
name: provider.name,
|
|
580
|
+
title: provider.title,
|
|
581
|
+
source: provider.source,
|
|
582
|
+
default: provider.name === DEFAULT_PROVIDER,
|
|
583
|
+
available: root !== null,
|
|
584
|
+
root,
|
|
585
|
+
capabilities: provider.capabilities,
|
|
586
|
+
};
|
|
587
|
+
});
|
|
588
|
+
const payload = { providers };
|
|
589
|
+
if (format === "json") {
|
|
590
|
+
process.stdout.write(jsonPayload("usage providers", payload, opts, {
|
|
591
|
+
summary: { providers: providers.length },
|
|
592
|
+
}));
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const human = format === "human";
|
|
596
|
+
const lines = table([
|
|
597
|
+
{ header: "provider" },
|
|
598
|
+
{ header: "available" },
|
|
599
|
+
{ header: "root" },
|
|
600
|
+
{ header: "capabilities" },
|
|
601
|
+
], providers.map((provider) => [
|
|
602
|
+
provider.default ? `${provider.name} (default)` : provider.name,
|
|
603
|
+
provider.available ? "yes" : "no",
|
|
604
|
+
provider.root ?? "—",
|
|
605
|
+
Object.entries(provider.capabilities)
|
|
606
|
+
.filter(([, enabled]) => enabled)
|
|
607
|
+
.map(([name]) => name)
|
|
608
|
+
.join(","),
|
|
609
|
+
]), human);
|
|
610
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
611
|
+
}
|
|
612
|
+
// ---------------------------------------------------------------------------
|
|
613
|
+
// usage index
|
|
614
|
+
// ---------------------------------------------------------------------------
|
|
615
|
+
export async function usageIndexAction(opts) {
|
|
616
|
+
const format = resolveFormat(opts);
|
|
617
|
+
const providers = resolveProviders(opts.provider);
|
|
618
|
+
if (opts.clear && opts.rebuild) {
|
|
619
|
+
throw new Error("--clear and --rebuild are mutually exclusive");
|
|
620
|
+
}
|
|
621
|
+
const action = opts.clear
|
|
622
|
+
? "clear"
|
|
623
|
+
: opts.rebuild
|
|
624
|
+
? "rebuild"
|
|
625
|
+
: "status";
|
|
626
|
+
// One store holds every provider, but the actions and the counts stay per
|
|
627
|
+
// provider: `usage index --clear --provider codex` must not discard the rest.
|
|
628
|
+
const databasePath = getUsageDatabasePath();
|
|
629
|
+
const caches = providers.map((provider) => ({
|
|
630
|
+
provider: provider.name,
|
|
631
|
+
root: databasePath,
|
|
632
|
+
removed: 0,
|
|
633
|
+
}));
|
|
634
|
+
let scanned = null;
|
|
635
|
+
if (action === "clear") {
|
|
636
|
+
for (const entry of caches)
|
|
637
|
+
entry.removed = clearDatabase(databasePath, entry.provider);
|
|
638
|
+
}
|
|
639
|
+
else if (action === "rebuild") {
|
|
640
|
+
const scope = resolveScope({ ...opts, index: true });
|
|
641
|
+
scanned = emptyScan();
|
|
642
|
+
for (const source of scope.sources) {
|
|
643
|
+
const result = await scan({
|
|
644
|
+
provider: source.provider,
|
|
645
|
+
root: source.root,
|
|
646
|
+
subagents: scope.subagents,
|
|
647
|
+
window: scope.window,
|
|
648
|
+
projects: scope.selectors,
|
|
649
|
+
useIndex: true,
|
|
650
|
+
rebuild: true,
|
|
651
|
+
});
|
|
652
|
+
scanned.failures.push(...result.failures);
|
|
653
|
+
for (const key of Object.keys(scanned.counters)) {
|
|
654
|
+
scanned.counters[key] += result.counters[key];
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
const statuses = caches.map((entry) => ({
|
|
659
|
+
provider: entry.provider,
|
|
660
|
+
...databaseStatus(databasePath, entry.provider),
|
|
661
|
+
...(action === "clear" ? { removed: entry.removed } : {}),
|
|
662
|
+
}));
|
|
663
|
+
// `cache` describes the store: one provider's rows when one was selected, the
|
|
664
|
+
// total across them otherwise. `bytes`, `days` and `events` are whole-store
|
|
665
|
+
// figures and so are taken once rather than summed — several providers share
|
|
666
|
+
// one SQLite file, and a provider's share of it is not a real number.
|
|
667
|
+
const whole = databaseStatus(databasePath);
|
|
668
|
+
const total = statuses.reduce((into, entry) => ({
|
|
669
|
+
...into,
|
|
670
|
+
present: into.present || entry.present,
|
|
671
|
+
entries: into.entries + entry.entries,
|
|
672
|
+
updatedAt: entry.updatedAt && (!into.updatedAt || entry.updatedAt > into.updatedAt)
|
|
673
|
+
? entry.updatedAt
|
|
674
|
+
: into.updatedAt,
|
|
675
|
+
}), {
|
|
676
|
+
root: databasePath,
|
|
677
|
+
present: false,
|
|
678
|
+
// Retained at 0: it described the JSON shard store this replaced, and is a
|
|
679
|
+
// required property of the published schema. See docs/contract.md.
|
|
680
|
+
shards: 0,
|
|
681
|
+
entries: 0,
|
|
682
|
+
bytes: whole.bytes,
|
|
683
|
+
days: whole.days,
|
|
684
|
+
events: whole.events,
|
|
685
|
+
schemaVersion: whole.schemaVersion,
|
|
686
|
+
updatedAt: null,
|
|
687
|
+
});
|
|
688
|
+
const removed = caches.reduce((sum, entry) => sum + entry.removed, 0);
|
|
689
|
+
const payload = {
|
|
690
|
+
provider: opts.provider ?? DEFAULT_PROVIDER,
|
|
691
|
+
action,
|
|
692
|
+
cache: total,
|
|
693
|
+
caches: statuses,
|
|
694
|
+
...(action === "clear" ? { removed } : {}),
|
|
695
|
+
...(scanned ? { scan: scanPayload(scanned) } : {}),
|
|
696
|
+
};
|
|
697
|
+
if (format === "json") {
|
|
698
|
+
process.stdout.write(jsonPayload("usage index", payload, opts, {
|
|
699
|
+
summary: { entries: total.entries, shards: total.shards },
|
|
700
|
+
}));
|
|
701
|
+
return;
|
|
702
|
+
}
|
|
703
|
+
const human = format === "human";
|
|
704
|
+
const lines = [];
|
|
705
|
+
for (const entry of statuses) {
|
|
706
|
+
lines.push(`${style(entry.provider, BOLD, human)} ${style(entry.root, CYAN, human)}`);
|
|
707
|
+
lines.push(` present: ${entry.present ? "yes" : "no"}`);
|
|
708
|
+
lines.push(` transcripts: ${entry.entries}`);
|
|
709
|
+
lines.push(` days: ${entry.days}`);
|
|
710
|
+
lines.push(` events: ${entry.events}`);
|
|
711
|
+
lines.push(` schema: v${entry.schemaVersion}`);
|
|
712
|
+
lines.push(` size: ${num(entry.bytes, human)} bytes`);
|
|
713
|
+
lines.push(` updated: ${entry.updatedAt ?? "never"}`);
|
|
714
|
+
if (action === "clear") {
|
|
715
|
+
const removed = entry.removed ?? 0;
|
|
716
|
+
lines.push(` removed: ${removed} transcript${removed === 1 ? "" : "s"}`);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (scanned)
|
|
720
|
+
lines.push(`rebuilt: ${scanLine(scanned, human)}`);
|
|
721
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
722
|
+
}
|
|
723
|
+
// ---------------------------------------------------------------------------
|
|
724
|
+
// usage import / usage migrate
|
|
725
|
+
// ---------------------------------------------------------------------------
|
|
726
|
+
/**
|
|
727
|
+
* The store as both commands report it.
|
|
728
|
+
*
|
|
729
|
+
* Read through a fresh read-only handle rather than the one that just wrote, so
|
|
730
|
+
* the figures are what a later reader would see rather than what this process
|
|
731
|
+
* has pending.
|
|
732
|
+
*/
|
|
733
|
+
function databasePayload(path) {
|
|
734
|
+
const status = databaseStatus(path);
|
|
735
|
+
return {
|
|
736
|
+
path,
|
|
737
|
+
present: status.present,
|
|
738
|
+
schemaVersion: status.schemaVersion,
|
|
739
|
+
files: status.entries,
|
|
740
|
+
days: status.days,
|
|
741
|
+
events: status.events,
|
|
742
|
+
bytes: status.bytes,
|
|
743
|
+
updatedAt: status.updatedAt,
|
|
744
|
+
...(status.present ? { providers: providerCounts(path) } : {}),
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
function providerCounts(path) {
|
|
748
|
+
let opened;
|
|
749
|
+
try {
|
|
750
|
+
opened = openUsageDatabase({ path, readOnly: true, migrate: false });
|
|
751
|
+
}
|
|
752
|
+
catch {
|
|
753
|
+
return {};
|
|
754
|
+
}
|
|
755
|
+
try {
|
|
756
|
+
return storeStatus(opened.db).providers;
|
|
757
|
+
}
|
|
758
|
+
catch {
|
|
759
|
+
return {};
|
|
760
|
+
}
|
|
761
|
+
finally {
|
|
762
|
+
try {
|
|
763
|
+
opened.db.close();
|
|
764
|
+
}
|
|
765
|
+
catch {
|
|
766
|
+
// Best-effort.
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* Imports every selected provider's transcripts into the store.
|
|
772
|
+
*
|
|
773
|
+
* This is the same work a report does on its way to producing numbers — the
|
|
774
|
+
* store populates itself on first use — so `usage import` exists to do it
|
|
775
|
+
* deliberately rather than as a side effect: to warm a cold store before a
|
|
776
|
+
* timed report, to run it on a schedule, and to see the counters on their own.
|
|
777
|
+
*/
|
|
778
|
+
export async function usageImportAction(opts) {
|
|
779
|
+
const format = resolveFormat(opts);
|
|
780
|
+
const scope = resolveScope({ ...opts, index: true });
|
|
781
|
+
const databasePath = getUsageDatabasePath();
|
|
782
|
+
const opened = openUsageDatabase({ path: databasePath });
|
|
783
|
+
const migrations = { from: opened.from, to: opened.to, applied: opened.applied, pending: [] };
|
|
784
|
+
opened.db.close();
|
|
785
|
+
const result = emptyScan();
|
|
786
|
+
for (const source of scope.sources) {
|
|
787
|
+
const scanned = await scan({
|
|
788
|
+
provider: source.provider,
|
|
789
|
+
root: source.root,
|
|
790
|
+
subagents: scope.subagents,
|
|
791
|
+
window: scope.window,
|
|
792
|
+
projects: scope.selectors,
|
|
793
|
+
useIndex: true,
|
|
794
|
+
...(opts.rebuild ? { rebuild: true } : {}),
|
|
795
|
+
});
|
|
796
|
+
result.failures.push(...scanned.failures);
|
|
797
|
+
for (const key of Object.keys(result.counters)) {
|
|
798
|
+
result.counters[key] += scanned.counters[key];
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
const exitCode = decideExit(result.counters, result.failures, opts.strict === true);
|
|
802
|
+
const payload = {
|
|
803
|
+
provider: opts.provider ?? DEFAULT_PROVIDER,
|
|
804
|
+
action: "import",
|
|
805
|
+
database: databasePayload(databasePath),
|
|
806
|
+
migrations,
|
|
807
|
+
sources: scope.sources.map((source) => ({ provider: source.provider.name, root: source.root })),
|
|
808
|
+
scan: scanPayload(result),
|
|
809
|
+
};
|
|
810
|
+
if (format === "json") {
|
|
811
|
+
const output = jsonPayload("usage import", payload, opts, {
|
|
812
|
+
exitCode,
|
|
813
|
+
summary: { parsed: result.counters.parsed, cached: result.counters.cached },
|
|
814
|
+
});
|
|
815
|
+
(exitCode === 0 ? process.stdout : process.stderr).write(output);
|
|
816
|
+
if (exitCode !== 0)
|
|
817
|
+
terminate(exitCode);
|
|
818
|
+
return;
|
|
819
|
+
}
|
|
820
|
+
const human = format === "human";
|
|
821
|
+
const lines = [
|
|
822
|
+
`${style("store", BOLD, human)} ${style(databasePath, CYAN, human)}`,
|
|
823
|
+
` schema: v${payload.database.schemaVersion}`,
|
|
824
|
+
` transcripts: ${payload.database.files}`,
|
|
825
|
+
` days: ${payload.database.days}`,
|
|
826
|
+
` events: ${num(payload.database.events, human)}`,
|
|
827
|
+
` size: ${num(payload.database.bytes, human)} bytes`,
|
|
828
|
+
];
|
|
829
|
+
if (migrations.applied.length > 0) {
|
|
830
|
+
lines.push(` migrated: v${migrations.from} to v${migrations.to}`);
|
|
831
|
+
}
|
|
832
|
+
lines.push(`imported: ${scanLine(result, human)}`);
|
|
833
|
+
write(lines, exitCode);
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* Applies pending store migrations.
|
|
837
|
+
*
|
|
838
|
+
* Opening the store for any other command already migrates it, so this exists
|
|
839
|
+
* for the two cases that need it separately: `--check`, which reports what is
|
|
840
|
+
* pending without writing, and migrating a store deliberately before a run
|
|
841
|
+
* rather than discovering mid-report that it needed it.
|
|
842
|
+
*/
|
|
843
|
+
export async function usageMigrateAction(opts) {
|
|
844
|
+
const format = resolveFormat(opts);
|
|
845
|
+
const databasePath = getUsageDatabasePath();
|
|
846
|
+
const check = opts.check === true;
|
|
847
|
+
const opened = openUsageDatabase({
|
|
848
|
+
path: databasePath,
|
|
849
|
+
...(check ? { migrate: false } : {}),
|
|
850
|
+
});
|
|
851
|
+
const from = opened.from;
|
|
852
|
+
const applied = opened.applied;
|
|
853
|
+
const to = opened.to;
|
|
854
|
+
opened.db.close();
|
|
855
|
+
const pending = check
|
|
856
|
+
? MIGRATIONS.filter((migration) => migration.version > from)
|
|
857
|
+
.map((migration) => migration.version)
|
|
858
|
+
.sort((a, b) => a - b)
|
|
859
|
+
: [];
|
|
860
|
+
const payload = {
|
|
861
|
+
action: "migrate",
|
|
862
|
+
database: databasePayload(databasePath),
|
|
863
|
+
migrations: { from, to, applied, pending },
|
|
864
|
+
};
|
|
865
|
+
if (format === "json") {
|
|
866
|
+
process.stdout.write(jsonPayload("usage migrate", payload, opts, {
|
|
867
|
+
summary: { applied: applied.length, pending: pending.length },
|
|
868
|
+
}));
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
const human = format === "human";
|
|
872
|
+
const lines = [`${style("store", BOLD, human)} ${style(databasePath, CYAN, human)}`];
|
|
873
|
+
lines.push(` schema: v${to}`);
|
|
874
|
+
lines.push(` latest: v${LATEST_VERSION}`);
|
|
875
|
+
if (applied.length > 0)
|
|
876
|
+
lines.push(` applied: ${applied.map((v) => `v${v}`).join(", ")}`);
|
|
877
|
+
else if (pending.length > 0)
|
|
878
|
+
lines.push(` pending: ${pending.map((v) => `v${v}`).join(", ")}`);
|
|
879
|
+
else
|
|
880
|
+
lines.push(" pending: none");
|
|
881
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
882
|
+
}
|
|
883
|
+
//# sourceMappingURL=usage.js.map
|