@selvakumaresra/specship 0.1.1 → 0.1.3
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/package.json +8 -7
- package/scripts/sync-shim-version.mjs +64 -0
- package/dist/bin/node-version-check.d.ts +0 -37
- package/dist/bin/node-version-check.d.ts.map +0 -1
- package/dist/bin/node-version-check.js +0 -79
- package/dist/bin/node-version-check.js.map +0 -1
- package/dist/bin/specship.d.ts +0 -25
- package/dist/bin/specship.d.ts.map +0 -1
- package/dist/bin/specship.js +0 -2018
- package/dist/bin/specship.js.map +0 -1
- package/dist/bin/uninstall.d.ts +0 -13
- package/dist/bin/uninstall.d.ts.map +0 -1
- package/dist/bin/uninstall.js +0 -35
- package/dist/bin/uninstall.js.map +0 -1
- package/dist/context/formatter.d.ts +0 -30
- package/dist/context/formatter.d.ts.map +0 -1
- package/dist/context/formatter.js +0 -263
- package/dist/context/formatter.js.map +0 -1
- package/dist/context/index.d.ts +0 -119
- package/dist/context/index.d.ts.map +0 -1
- package/dist/context/index.js +0 -1289
- package/dist/context/index.js.map +0 -1
- package/dist/context/markers.d.ts +0 -19
- package/dist/context/markers.d.ts.map +0 -1
- package/dist/context/markers.js +0 -22
- package/dist/context/markers.js.map +0 -1
- package/dist/db/index.d.ts +0 -101
- package/dist/db/index.d.ts.map +0 -1
- package/dist/db/index.js +0 -276
- package/dist/db/index.js.map +0 -1
- package/dist/db/migrations.d.ts +0 -44
- package/dist/db/migrations.d.ts.map +0 -1
- package/dist/db/migrations.js +0 -427
- package/dist/db/migrations.js.map +0 -1
- package/dist/db/queries.d.ts +0 -357
- package/dist/db/queries.d.ts.map +0 -1
- package/dist/db/queries.js +0 -1504
- package/dist/db/queries.js.map +0 -1
- package/dist/db/schema.sql +0 -410
- package/dist/db/spec-queries.d.ts +0 -101
- package/dist/db/spec-queries.d.ts.map +0 -1
- package/dist/db/spec-queries.js +0 -675
- package/dist/db/spec-queries.js.map +0 -1
- package/dist/db/sqlite-adapter.d.ts +0 -65
- package/dist/db/sqlite-adapter.d.ts.map +0 -1
- package/dist/db/sqlite-adapter.js +0 -214
- package/dist/db/sqlite-adapter.js.map +0 -1
- package/dist/directory.d.ts +0 -57
- package/dist/directory.d.ts.map +0 -1
- package/dist/directory.js +0 -253
- package/dist/directory.js.map +0 -1
- package/dist/errors.d.ts +0 -136
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -219
- package/dist/errors.js.map +0 -1
- package/dist/extraction/dfm-extractor.d.ts +0 -31
- package/dist/extraction/dfm-extractor.d.ts.map +0 -1
- package/dist/extraction/dfm-extractor.js +0 -151
- package/dist/extraction/dfm-extractor.js.map +0 -1
- package/dist/extraction/generated-detection.d.ts +0 -30
- package/dist/extraction/generated-detection.d.ts.map +0 -1
- package/dist/extraction/generated-detection.js +0 -80
- package/dist/extraction/generated-detection.js.map +0 -1
- package/dist/extraction/grammars.d.ts +0 -100
- package/dist/extraction/grammars.d.ts.map +0 -1
- package/dist/extraction/grammars.js +0 -426
- package/dist/extraction/grammars.js.map +0 -1
- package/dist/extraction/index.d.ts +0 -138
- package/dist/extraction/index.d.ts.map +0 -1
- package/dist/extraction/index.js +0 -1394
- package/dist/extraction/index.js.map +0 -1
- package/dist/extraction/languages/c-cpp.d.ts +0 -4
- package/dist/extraction/languages/c-cpp.d.ts.map +0 -1
- package/dist/extraction/languages/c-cpp.js +0 -171
- package/dist/extraction/languages/c-cpp.js.map +0 -1
- package/dist/extraction/languages/csharp.d.ts +0 -3
- package/dist/extraction/languages/csharp.d.ts.map +0 -1
- package/dist/extraction/languages/csharp.js +0 -73
- package/dist/extraction/languages/csharp.js.map +0 -1
- package/dist/extraction/languages/dart.d.ts +0 -3
- package/dist/extraction/languages/dart.d.ts.map +0 -1
- package/dist/extraction/languages/dart.js +0 -192
- package/dist/extraction/languages/dart.js.map +0 -1
- package/dist/extraction/languages/go.d.ts +0 -3
- package/dist/extraction/languages/go.d.ts.map +0 -1
- package/dist/extraction/languages/go.js +0 -74
- package/dist/extraction/languages/go.js.map +0 -1
- package/dist/extraction/languages/index.d.ts +0 -10
- package/dist/extraction/languages/index.d.ts.map +0 -1
- package/dist/extraction/languages/index.js +0 -51
- package/dist/extraction/languages/index.js.map +0 -1
- package/dist/extraction/languages/java.d.ts +0 -3
- package/dist/extraction/languages/java.d.ts.map +0 -1
- package/dist/extraction/languages/java.js +0 -70
- package/dist/extraction/languages/java.js.map +0 -1
- package/dist/extraction/languages/javascript.d.ts +0 -3
- package/dist/extraction/languages/javascript.d.ts.map +0 -1
- package/dist/extraction/languages/javascript.js +0 -90
- package/dist/extraction/languages/javascript.js.map +0 -1
- package/dist/extraction/languages/kotlin.d.ts +0 -3
- package/dist/extraction/languages/kotlin.d.ts.map +0 -1
- package/dist/extraction/languages/kotlin.js +0 -259
- package/dist/extraction/languages/kotlin.js.map +0 -1
- package/dist/extraction/languages/lua.d.ts +0 -3
- package/dist/extraction/languages/lua.d.ts.map +0 -1
- package/dist/extraction/languages/lua.js +0 -150
- package/dist/extraction/languages/lua.js.map +0 -1
- package/dist/extraction/languages/luau.d.ts +0 -3
- package/dist/extraction/languages/luau.d.ts.map +0 -1
- package/dist/extraction/languages/luau.js +0 -37
- package/dist/extraction/languages/luau.js.map +0 -1
- package/dist/extraction/languages/objc.d.ts +0 -3
- package/dist/extraction/languages/objc.d.ts.map +0 -1
- package/dist/extraction/languages/objc.js +0 -133
- package/dist/extraction/languages/objc.js.map +0 -1
- package/dist/extraction/languages/pascal.d.ts +0 -3
- package/dist/extraction/languages/pascal.d.ts.map +0 -1
- package/dist/extraction/languages/pascal.js +0 -66
- package/dist/extraction/languages/pascal.js.map +0 -1
- package/dist/extraction/languages/php.d.ts +0 -3
- package/dist/extraction/languages/php.d.ts.map +0 -1
- package/dist/extraction/languages/php.js +0 -107
- package/dist/extraction/languages/php.js.map +0 -1
- package/dist/extraction/languages/python.d.ts +0 -3
- package/dist/extraction/languages/python.d.ts.map +0 -1
- package/dist/extraction/languages/python.js +0 -56
- package/dist/extraction/languages/python.js.map +0 -1
- package/dist/extraction/languages/ruby.d.ts +0 -3
- package/dist/extraction/languages/ruby.d.ts.map +0 -1
- package/dist/extraction/languages/ruby.js +0 -114
- package/dist/extraction/languages/ruby.js.map +0 -1
- package/dist/extraction/languages/rust.d.ts +0 -3
- package/dist/extraction/languages/rust.d.ts.map +0 -1
- package/dist/extraction/languages/rust.js +0 -109
- package/dist/extraction/languages/rust.js.map +0 -1
- package/dist/extraction/languages/scala.d.ts +0 -3
- package/dist/extraction/languages/scala.d.ts.map +0 -1
- package/dist/extraction/languages/scala.js +0 -139
- package/dist/extraction/languages/scala.js.map +0 -1
- package/dist/extraction/languages/swift.d.ts +0 -3
- package/dist/extraction/languages/swift.d.ts.map +0 -1
- package/dist/extraction/languages/swift.js +0 -91
- package/dist/extraction/languages/swift.js.map +0 -1
- package/dist/extraction/languages/typescript.d.ts +0 -3
- package/dist/extraction/languages/typescript.d.ts.map +0 -1
- package/dist/extraction/languages/typescript.js +0 -129
- package/dist/extraction/languages/typescript.js.map +0 -1
- package/dist/extraction/liquid-extractor.d.ts +0 -52
- package/dist/extraction/liquid-extractor.d.ts.map +0 -1
- package/dist/extraction/liquid-extractor.js +0 -313
- package/dist/extraction/liquid-extractor.js.map +0 -1
- package/dist/extraction/mybatis-extractor.d.ts +0 -48
- package/dist/extraction/mybatis-extractor.d.ts.map +0 -1
- package/dist/extraction/mybatis-extractor.js +0 -198
- package/dist/extraction/mybatis-extractor.js.map +0 -1
- package/dist/extraction/parse-worker.d.ts +0 -8
- package/dist/extraction/parse-worker.d.ts.map +0 -1
- package/dist/extraction/parse-worker.js +0 -94
- package/dist/extraction/parse-worker.js.map +0 -1
- package/dist/extraction/specs/markdown-spec-extractor.d.ts +0 -59
- package/dist/extraction/specs/markdown-spec-extractor.d.ts.map +0 -1
- package/dist/extraction/specs/markdown-spec-extractor.js +0 -327
- package/dist/extraction/specs/markdown-spec-extractor.js.map +0 -1
- package/dist/extraction/specs/types.d.ts +0 -39
- package/dist/extraction/specs/types.d.ts.map +0 -1
- package/dist/extraction/specs/types.js +0 -8
- package/dist/extraction/specs/types.js.map +0 -1
- package/dist/extraction/svelte-extractor.d.ts +0 -56
- package/dist/extraction/svelte-extractor.d.ts.map +0 -1
- package/dist/extraction/svelte-extractor.js +0 -272
- package/dist/extraction/svelte-extractor.js.map +0 -1
- package/dist/extraction/tree-sitter-helpers.d.ts +0 -28
- package/dist/extraction/tree-sitter-helpers.d.ts.map +0 -1
- package/dist/extraction/tree-sitter-helpers.js +0 -103
- package/dist/extraction/tree-sitter-helpers.js.map +0 -1
- package/dist/extraction/tree-sitter-types.d.ts +0 -193
- package/dist/extraction/tree-sitter-types.d.ts.map +0 -1
- package/dist/extraction/tree-sitter-types.js +0 -10
- package/dist/extraction/tree-sitter-types.js.map +0 -1
- package/dist/extraction/tree-sitter.d.ts +0 -317
- package/dist/extraction/tree-sitter.d.ts.map +0 -1
- package/dist/extraction/tree-sitter.js +0 -3092
- package/dist/extraction/tree-sitter.js.map +0 -1
- package/dist/extraction/vue-extractor.d.ts +0 -51
- package/dist/extraction/vue-extractor.d.ts.map +0 -1
- package/dist/extraction/vue-extractor.js +0 -251
- package/dist/extraction/vue-extractor.js.map +0 -1
- package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
- package/dist/extraction/wasm-runtime-flags.d.ts +0 -38
- package/dist/extraction/wasm-runtime-flags.d.ts.map +0 -1
- package/dist/extraction/wasm-runtime-flags.js +0 -106
- package/dist/extraction/wasm-runtime-flags.js.map +0 -1
- package/dist/graph/index.d.ts +0 -8
- package/dist/graph/index.d.ts.map +0 -1
- package/dist/graph/index.js +0 -13
- package/dist/graph/index.js.map +0 -1
- package/dist/graph/queries.d.ts +0 -106
- package/dist/graph/queries.d.ts.map +0 -1
- package/dist/graph/queries.js +0 -366
- package/dist/graph/queries.js.map +0 -1
- package/dist/graph/traversal.d.ts +0 -127
- package/dist/graph/traversal.d.ts.map +0 -1
- package/dist/graph/traversal.js +0 -531
- package/dist/graph/traversal.js.map +0 -1
- package/dist/index.d.ts +0 -551
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -1165
- package/dist/index.js.map +0 -1
- package/dist/installer/config-writer.d.ts +0 -28
- package/dist/installer/config-writer.d.ts.map +0 -1
- package/dist/installer/config-writer.js +0 -91
- package/dist/installer/config-writer.js.map +0 -1
- package/dist/installer/index.d.ts +0 -87
- package/dist/installer/index.d.ts.map +0 -1
- package/dist/installer/index.js +0 -409
- package/dist/installer/index.js.map +0 -1
- package/dist/installer/instructions-template.d.ts +0 -18
- package/dist/installer/instructions-template.d.ts.map +0 -1
- package/dist/installer/instructions-template.js +0 -21
- package/dist/installer/instructions-template.js.map +0 -1
- package/dist/installer/targets/claude.d.ts +0 -88
- package/dist/installer/targets/claude.d.ts.map +0 -1
- package/dist/installer/targets/claude.js +0 -582
- package/dist/installer/targets/claude.js.map +0 -1
- package/dist/installer/targets/registry.d.ts +0 -19
- package/dist/installer/targets/registry.d.ts.map +0 -1
- package/dist/installer/targets/registry.js +0 -31
- package/dist/installer/targets/registry.js.map +0 -1
- package/dist/installer/targets/shared.d.ts +0 -62
- package/dist/installer/targets/shared.d.ts.map +0 -1
- package/dist/installer/targets/shared.js +0 -207
- package/dist/installer/targets/shared.js.map +0 -1
- package/dist/installer/targets/types.d.ts +0 -76
- package/dist/installer/targets/types.d.ts.map +0 -1
- package/dist/installer/targets/types.js +0 -12
- package/dist/installer/targets/types.js.map +0 -1
- package/dist/isolation/worktree.d.ts +0 -65
- package/dist/isolation/worktree.d.ts.map +0 -1
- package/dist/isolation/worktree.js +0 -231
- package/dist/isolation/worktree.js.map +0 -1
- package/dist/mcp/daemon-paths.d.ts +0 -46
- package/dist/mcp/daemon-paths.d.ts.map +0 -1
- package/dist/mcp/daemon-paths.js +0 -125
- package/dist/mcp/daemon-paths.js.map +0 -1
- package/dist/mcp/daemon.d.ts +0 -161
- package/dist/mcp/daemon.d.ts.map +0 -1
- package/dist/mcp/daemon.js +0 -403
- package/dist/mcp/daemon.js.map +0 -1
- package/dist/mcp/engine.d.ts +0 -105
- package/dist/mcp/engine.d.ts.map +0 -1
- package/dist/mcp/engine.js +0 -270
- package/dist/mcp/engine.js.map +0 -1
- package/dist/mcp/index.d.ts +0 -112
- package/dist/mcp/index.d.ts.map +0 -1
- package/dist/mcp/index.js +0 -477
- package/dist/mcp/index.js.map +0 -1
- package/dist/mcp/proxy.d.ts +0 -81
- package/dist/mcp/proxy.d.ts.map +0 -1
- package/dist/mcp/proxy.js +0 -510
- package/dist/mcp/proxy.js.map +0 -1
- package/dist/mcp/server-instructions.d.ts +0 -18
- package/dist/mcp/server-instructions.d.ts.map +0 -1
- package/dist/mcp/server-instructions.js +0 -77
- package/dist/mcp/server-instructions.js.map +0 -1
- package/dist/mcp/session.d.ts +0 -77
- package/dist/mcp/session.d.ts.map +0 -1
- package/dist/mcp/session.js +0 -294
- package/dist/mcp/session.js.map +0 -1
- package/dist/mcp/spec-tools.d.ts +0 -39
- package/dist/mcp/spec-tools.d.ts.map +0 -1
- package/dist/mcp/spec-tools.js +0 -326
- package/dist/mcp/spec-tools.js.map +0 -1
- package/dist/mcp/tools.d.ts +0 -404
- package/dist/mcp/tools.d.ts.map +0 -1
- package/dist/mcp/tools.js +0 -3066
- package/dist/mcp/tools.js.map +0 -1
- package/dist/mcp/transport.d.ts +0 -188
- package/dist/mcp/transport.d.ts.map +0 -1
- package/dist/mcp/transport.js +0 -343
- package/dist/mcp/transport.js.map +0 -1
- package/dist/mcp/version.d.ts +0 -19
- package/dist/mcp/version.d.ts.map +0 -1
- package/dist/mcp/version.js +0 -71
- package/dist/mcp/version.js.map +0 -1
- package/dist/resolution/callback-synthesizer.d.ts +0 -10
- package/dist/resolution/callback-synthesizer.d.ts.map +0 -1
- package/dist/resolution/callback-synthesizer.js +0 -1300
- package/dist/resolution/callback-synthesizer.js.map +0 -1
- package/dist/resolution/frameworks/cargo-workspace.d.ts +0 -18
- package/dist/resolution/frameworks/cargo-workspace.d.ts.map +0 -1
- package/dist/resolution/frameworks/cargo-workspace.js +0 -225
- package/dist/resolution/frameworks/cargo-workspace.js.map +0 -1
- package/dist/resolution/frameworks/csharp.d.ts +0 -8
- package/dist/resolution/frameworks/csharp.d.ts.map +0 -1
- package/dist/resolution/frameworks/csharp.js +0 -241
- package/dist/resolution/frameworks/csharp.js.map +0 -1
- package/dist/resolution/frameworks/drupal.d.ts +0 -51
- package/dist/resolution/frameworks/drupal.d.ts.map +0 -1
- package/dist/resolution/frameworks/drupal.js +0 -367
- package/dist/resolution/frameworks/drupal.js.map +0 -1
- package/dist/resolution/frameworks/expo-modules.d.ts +0 -3
- package/dist/resolution/frameworks/expo-modules.d.ts.map +0 -1
- package/dist/resolution/frameworks/expo-modules.js +0 -143
- package/dist/resolution/frameworks/expo-modules.js.map +0 -1
- package/dist/resolution/frameworks/express.d.ts +0 -8
- package/dist/resolution/frameworks/express.d.ts.map +0 -1
- package/dist/resolution/frameworks/express.js +0 -308
- package/dist/resolution/frameworks/express.js.map +0 -1
- package/dist/resolution/frameworks/fabric.d.ts +0 -3
- package/dist/resolution/frameworks/fabric.d.ts.map +0 -1
- package/dist/resolution/frameworks/fabric.js +0 -354
- package/dist/resolution/frameworks/fabric.js.map +0 -1
- package/dist/resolution/frameworks/go.d.ts +0 -8
- package/dist/resolution/frameworks/go.d.ts.map +0 -1
- package/dist/resolution/frameworks/go.js +0 -161
- package/dist/resolution/frameworks/go.js.map +0 -1
- package/dist/resolution/frameworks/index.d.ts +0 -48
- package/dist/resolution/frameworks/index.d.ts.map +0 -1
- package/dist/resolution/frameworks/index.js +0 -161
- package/dist/resolution/frameworks/index.js.map +0 -1
- package/dist/resolution/frameworks/java.d.ts +0 -8
- package/dist/resolution/frameworks/java.d.ts.map +0 -1
- package/dist/resolution/frameworks/java.js +0 -504
- package/dist/resolution/frameworks/java.js.map +0 -1
- package/dist/resolution/frameworks/laravel.d.ts +0 -13
- package/dist/resolution/frameworks/laravel.d.ts.map +0 -1
- package/dist/resolution/frameworks/laravel.js +0 -257
- package/dist/resolution/frameworks/laravel.js.map +0 -1
- package/dist/resolution/frameworks/nestjs.d.ts +0 -26
- package/dist/resolution/frameworks/nestjs.d.ts.map +0 -1
- package/dist/resolution/frameworks/nestjs.js +0 -698
- package/dist/resolution/frameworks/nestjs.js.map +0 -1
- package/dist/resolution/frameworks/play.d.ts +0 -19
- package/dist/resolution/frameworks/play.d.ts.map +0 -1
- package/dist/resolution/frameworks/play.js +0 -111
- package/dist/resolution/frameworks/play.js.map +0 -1
- package/dist/resolution/frameworks/python.d.ts +0 -10
- package/dist/resolution/frameworks/python.d.ts.map +0 -1
- package/dist/resolution/frameworks/python.js +0 -396
- package/dist/resolution/frameworks/python.js.map +0 -1
- package/dist/resolution/frameworks/react-native.d.ts +0 -3
- package/dist/resolution/frameworks/react-native.d.ts.map +0 -1
- package/dist/resolution/frameworks/react-native.js +0 -360
- package/dist/resolution/frameworks/react-native.js.map +0 -1
- package/dist/resolution/frameworks/react.d.ts +0 -8
- package/dist/resolution/frameworks/react.d.ts.map +0 -1
- package/dist/resolution/frameworks/react.js +0 -365
- package/dist/resolution/frameworks/react.js.map +0 -1
- package/dist/resolution/frameworks/ruby.d.ts +0 -8
- package/dist/resolution/frameworks/ruby.d.ts.map +0 -1
- package/dist/resolution/frameworks/ruby.js +0 -302
- package/dist/resolution/frameworks/ruby.js.map +0 -1
- package/dist/resolution/frameworks/rust.d.ts +0 -8
- package/dist/resolution/frameworks/rust.d.ts.map +0 -1
- package/dist/resolution/frameworks/rust.js +0 -304
- package/dist/resolution/frameworks/rust.js.map +0 -1
- package/dist/resolution/frameworks/svelte.d.ts +0 -9
- package/dist/resolution/frameworks/svelte.d.ts.map +0 -1
- package/dist/resolution/frameworks/svelte.js +0 -249
- package/dist/resolution/frameworks/svelte.js.map +0 -1
- package/dist/resolution/frameworks/swift-objc.d.ts +0 -37
- package/dist/resolution/frameworks/swift-objc.d.ts.map +0 -1
- package/dist/resolution/frameworks/swift-objc.js +0 -252
- package/dist/resolution/frameworks/swift-objc.js.map +0 -1
- package/dist/resolution/frameworks/swift.d.ts +0 -10
- package/dist/resolution/frameworks/swift.d.ts.map +0 -1
- package/dist/resolution/frameworks/swift.js +0 -400
- package/dist/resolution/frameworks/swift.js.map +0 -1
- package/dist/resolution/frameworks/vue.d.ts +0 -9
- package/dist/resolution/frameworks/vue.d.ts.map +0 -1
- package/dist/resolution/frameworks/vue.js +0 -306
- package/dist/resolution/frameworks/vue.js.map +0 -1
- package/dist/resolution/go-module.d.ts +0 -26
- package/dist/resolution/go-module.d.ts.map +0 -1
- package/dist/resolution/go-module.js +0 -78
- package/dist/resolution/go-module.js.map +0 -1
- package/dist/resolution/import-resolver.d.ts +0 -68
- package/dist/resolution/import-resolver.d.ts.map +0 -1
- package/dist/resolution/import-resolver.js +0 -1275
- package/dist/resolution/import-resolver.js.map +0 -1
- package/dist/resolution/index.d.ts +0 -117
- package/dist/resolution/index.d.ts.map +0 -1
- package/dist/resolution/index.js +0 -895
- package/dist/resolution/index.js.map +0 -1
- package/dist/resolution/lru-cache.d.ts +0 -24
- package/dist/resolution/lru-cache.d.ts.map +0 -1
- package/dist/resolution/lru-cache.js +0 -62
- package/dist/resolution/lru-cache.js.map +0 -1
- package/dist/resolution/name-matcher.d.ts +0 -32
- package/dist/resolution/name-matcher.d.ts.map +0 -1
- package/dist/resolution/name-matcher.js +0 -596
- package/dist/resolution/name-matcher.js.map +0 -1
- package/dist/resolution/path-aliases.d.ts +0 -68
- package/dist/resolution/path-aliases.d.ts.map +0 -1
- package/dist/resolution/path-aliases.js +0 -238
- package/dist/resolution/path-aliases.js.map +0 -1
- package/dist/resolution/spec-link-resolver.d.ts +0 -103
- package/dist/resolution/spec-link-resolver.d.ts.map +0 -1
- package/dist/resolution/spec-link-resolver.js +0 -259
- package/dist/resolution/spec-link-resolver.js.map +0 -1
- package/dist/resolution/strip-comments.d.ts +0 -27
- package/dist/resolution/strip-comments.d.ts.map +0 -1
- package/dist/resolution/strip-comments.js +0 -441
- package/dist/resolution/strip-comments.js.map +0 -1
- package/dist/resolution/swift-objc-bridge.d.ts +0 -134
- package/dist/resolution/swift-objc-bridge.d.ts.map +0 -1
- package/dist/resolution/swift-objc-bridge.js +0 -256
- package/dist/resolution/swift-objc-bridge.js.map +0 -1
- package/dist/resolution/types.d.ts +0 -216
- package/dist/resolution/types.d.ts.map +0 -1
- package/dist/resolution/types.js +0 -8
- package/dist/resolution/types.js.map +0 -1
- package/dist/resolution/workspace-packages.d.ts +0 -48
- package/dist/resolution/workspace-packages.d.ts.map +0 -1
- package/dist/resolution/workspace-packages.js +0 -208
- package/dist/resolution/workspace-packages.js.map +0 -1
- package/dist/search/query-parser.d.ts +0 -57
- package/dist/search/query-parser.d.ts.map +0 -1
- package/dist/search/query-parser.js +0 -177
- package/dist/search/query-parser.js.map +0 -1
- package/dist/search/query-utils.d.ts +0 -71
- package/dist/search/query-utils.d.ts.map +0 -1
- package/dist/search/query-utils.js +0 -380
- package/dist/search/query-utils.js.map +0 -1
- package/dist/server/cli.js +0 -152
- package/dist/server/index.js +0 -12
- package/dist/server/ingest/index.js +0 -18
- package/dist/server/ingest/ingestor.js +0 -406
- package/dist/server/ingest/parser.js +0 -104
- package/dist/server/ingest/pricing.js +0 -78
- package/dist/server/ingest/types.js +0 -9
- package/dist/server/ingest/watcher.js +0 -77
- package/dist/server/package.json +0 -3
- package/dist/server/project-registry.js +0 -101
- package/dist/server/routes/claude.js +0 -480
- package/dist/server/routes/graph.js +0 -149
- package/dist/server/routes/memory.js +0 -272
- package/dist/server/routes/projects.js +0 -197
- package/dist/server/routes/spec.js +0 -105
- package/dist/server/routes/status.js +0 -35
- package/dist/server/routes/workflow.js +0 -184
- package/dist/server/server.js +0 -202
- package/dist/sync/git-hooks.d.ts +0 -45
- package/dist/sync/git-hooks.d.ts.map +0 -1
- package/dist/sync/git-hooks.js +0 -225
- package/dist/sync/git-hooks.js.map +0 -1
- package/dist/sync/index.d.ts +0 -19
- package/dist/sync/index.d.ts.map +0 -1
- package/dist/sync/index.js +0 -35
- package/dist/sync/index.js.map +0 -1
- package/dist/sync/watch-policy.d.ts +0 -48
- package/dist/sync/watch-policy.d.ts.map +0 -1
- package/dist/sync/watch-policy.js +0 -124
- package/dist/sync/watch-policy.js.map +0 -1
- package/dist/sync/watcher.d.ts +0 -283
- package/dist/sync/watcher.d.ts.map +0 -1
- package/dist/sync/watcher.js +0 -606
- package/dist/sync/watcher.js.map +0 -1
- package/dist/sync/worktree.d.ts +0 -54
- package/dist/sync/worktree.d.ts.map +0 -1
- package/dist/sync/worktree.js +0 -137
- package/dist/sync/worktree.js.map +0 -1
- package/dist/types.d.ts +0 -623
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -108
- package/dist/types.js.map +0 -1
- package/dist/ui/glyphs.d.ts +0 -42
- package/dist/ui/glyphs.d.ts.map +0 -1
- package/dist/ui/glyphs.js +0 -78
- package/dist/ui/glyphs.js.map +0 -1
- package/dist/ui/shimmer-progress.d.ts +0 -11
- package/dist/ui/shimmer-progress.d.ts.map +0 -1
- package/dist/ui/shimmer-progress.js +0 -90
- package/dist/ui/shimmer-progress.js.map +0 -1
- package/dist/ui/shimmer-worker.d.ts +0 -2
- package/dist/ui/shimmer-worker.d.ts.map +0 -1
- package/dist/ui/shimmer-worker.js +0 -118
- package/dist/ui/shimmer-worker.js.map +0 -1
- package/dist/ui/types.d.ts +0 -17
- package/dist/ui/types.d.ts.map +0 -1
- package/dist/ui/types.js +0 -3
- package/dist/ui/types.js.map +0 -1
- package/dist/utils.d.ts +0 -205
- package/dist/utils.d.ts.map +0 -1
- package/dist/utils.js +0 -549
- package/dist/utils.js.map +0 -1
- package/dist/web/chunk-2YZXEHZ2.js +0 -1
- package/dist/web/chunk-3GIC555L.js +0 -18
- package/dist/web/chunk-3IIIGRMT.js +0 -1
- package/dist/web/chunk-47QYKLE5.js +0 -1
- package/dist/web/chunk-4LHBWWP7.js +0 -1
- package/dist/web/chunk-4OAZLD5W.js +0 -1
- package/dist/web/chunk-5OQKAJAE.js +0 -1
- package/dist/web/chunk-7B525GKQ.js +0 -1
- package/dist/web/chunk-BPDXCOOZ.js +0 -1
- package/dist/web/chunk-DT37HTZB.js +0 -1
- package/dist/web/chunk-EIMUHJND.js +0 -1
- package/dist/web/chunk-FTESTUEO.js +0 -1
- package/dist/web/chunk-GLJZV6MU.js +0 -1
- package/dist/web/chunk-I7LS67U5.js +0 -1
- package/dist/web/chunk-L4TVIPSR.js +0 -1
- package/dist/web/chunk-MASCULC2.js +0 -1
- package/dist/web/chunk-MW7ICSRM.js +0 -1
- package/dist/web/chunk-OI5VP2A3.js +0 -1
- package/dist/web/chunk-RA6EBF6I.js +0 -1
- package/dist/web/chunk-RP3WU5Y6.js +0 -1
- package/dist/web/chunk-RQDRMTXN.js +0 -1
- package/dist/web/chunk-TQMT6UDU.js +0 -1
- package/dist/web/chunk-U7IYOV7T.js +0 -1
- package/dist/web/chunk-UE227MWF.js +0 -1
- package/dist/web/chunk-WV573J4K.js +0 -1
- package/dist/web/chunk-WVCKOJZL.js +0 -4
- package/dist/web/chunk-XZKLVPHE.js +0 -1
- package/dist/web/chunk-ZABKKHJ3.js +0 -1
- package/dist/web/favicon-16.png +0 -0
- package/dist/web/favicon-180.png +0 -0
- package/dist/web/favicon-32.png +0 -0
- package/dist/web/favicon-512.png +0 -0
- package/dist/web/favicon-small.svg +0 -15
- package/dist/web/favicon.ico +0 -0
- package/dist/web/favicon.svg +0 -20
- package/dist/web/index.html +0 -145
- package/dist/web/main-RI5CO5Z4.js +0 -1
- package/dist/web/styles-CYN7IKT4.css +0 -1
- package/dist/workflows/condition-evaluator.d.ts +0 -75
- package/dist/workflows/condition-evaluator.d.ts.map +0 -1
- package/dist/workflows/condition-evaluator.js +0 -282
- package/dist/workflows/condition-evaluator.js.map +0 -1
- package/dist/workflows/defaults/index.d.ts +0 -26
- package/dist/workflows/defaults/index.d.ts.map +0 -1
- package/dist/workflows/defaults/index.js +0 -94
- package/dist/workflows/defaults/index.js.map +0 -1
- package/dist/workflows/defaults/spec-fix.yaml +0 -110
- package/dist/workflows/defaults/spec-implement.yaml +0 -150
- package/dist/workflows/defaults/spec-relink.yaml +0 -81
- package/dist/workflows/defaults/spec-verify.yaml +0 -51
- package/dist/workflows/discovery.d.ts +0 -46
- package/dist/workflows/discovery.d.ts.map +0 -1
- package/dist/workflows/discovery.js +0 -193
- package/dist/workflows/discovery.js.map +0 -1
- package/dist/workflows/executor.d.ts +0 -83
- package/dist/workflows/executor.d.ts.map +0 -1
- package/dist/workflows/executor.js +0 -623
- package/dist/workflows/executor.js.map +0 -1
- package/dist/workflows/runners/approval.d.ts +0 -18
- package/dist/workflows/runners/approval.d.ts.map +0 -1
- package/dist/workflows/runners/approval.js +0 -34
- package/dist/workflows/runners/approval.js.map +0 -1
- package/dist/workflows/runners/bash.d.ts +0 -13
- package/dist/workflows/runners/bash.d.ts.map +0 -1
- package/dist/workflows/runners/bash.js +0 -143
- package/dist/workflows/runners/bash.js.map +0 -1
- package/dist/workflows/runners/cancel.d.ts +0 -10
- package/dist/workflows/runners/cancel.d.ts.map +0 -1
- package/dist/workflows/runners/cancel.js +0 -19
- package/dist/workflows/runners/cancel.js.map +0 -1
- package/dist/workflows/runners/prompt.d.ts +0 -28
- package/dist/workflows/runners/prompt.d.ts.map +0 -1
- package/dist/workflows/runners/prompt.js +0 -212
- package/dist/workflows/runners/prompt.js.map +0 -1
- package/dist/workflows/runners/script.d.ts +0 -17
- package/dist/workflows/runners/script.d.ts.map +0 -1
- package/dist/workflows/runners/script.js +0 -155
- package/dist/workflows/runners/script.js.map +0 -1
- package/dist/workflows/runners/types.d.ts +0 -51
- package/dist/workflows/runners/types.d.ts.map +0 -1
- package/dist/workflows/runners/types.js +0 -13
- package/dist/workflows/runners/types.js.map +0 -1
- package/dist/workflows/schemas/workflow.d.ts +0 -166
- package/dist/workflows/schemas/workflow.d.ts.map +0 -1
- package/dist/workflows/schemas/workflow.js +0 -437
- package/dist/workflows/schemas/workflow.js.map +0 -1
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ProjectRegistry — lazy-opens and caches SpecShip instances per project
|
|
3
|
-
* path, keyed by absolute path. LRU evicts when the cache exceeds maxOpen
|
|
4
|
-
* so a long-running server doesn't hold every project's SQLite handle
|
|
5
|
-
* forever.
|
|
6
|
-
*
|
|
7
|
-
* Used by the Fastify routes (via `app.activeCg(req)`) to back the desktop
|
|
8
|
-
* app's project picker: when the user switches projects in the UI, the
|
|
9
|
-
* specship-scoped surfaces (graph, specs, drift, workflows, status) start
|
|
10
|
-
* reading from the matching instance — opened on demand if it isn't
|
|
11
|
-
* already cached.
|
|
12
|
-
*
|
|
13
|
-
* Analytics endpoints (`/api/claude/*`, `/api/memory`) read from a single
|
|
14
|
-
* "primary" instance instead, since their data (JSONL ingest, CLAUDE.md
|
|
15
|
-
* hierarchy) is global to the user, not scoped to one project.
|
|
16
|
-
*/
|
|
17
|
-
import { decodeProjectSlug } from './ingest/ingestor.js';
|
|
18
|
-
export class ProjectRegistry {
|
|
19
|
-
cache = new Map();
|
|
20
|
-
maxOpen;
|
|
21
|
-
verbose;
|
|
22
|
-
openImpl;
|
|
23
|
-
constructor(opts, defaultOpenImpl) {
|
|
24
|
-
this.maxOpen = opts.maxOpen ?? 5;
|
|
25
|
-
this.verbose = opts.verbose ?? false;
|
|
26
|
-
this.openImpl = opts.openImpl ?? defaultOpenImpl;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Return the cached SpecShip for `projectPath`, opening it on demand.
|
|
30
|
-
* Returns null when the path isn't initialized (no `.specship/`) or
|
|
31
|
-
* the open throws — callers surface a friendly UI error.
|
|
32
|
-
*/
|
|
33
|
-
async get(projectPath) {
|
|
34
|
-
const existing = this.cache.get(projectPath);
|
|
35
|
-
if (existing) {
|
|
36
|
-
existing.lastAccess = Date.now();
|
|
37
|
-
return existing.cg;
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
const cg = await this.openImpl(projectPath);
|
|
41
|
-
this.cache.set(projectPath, { cg, lastAccess: Date.now() });
|
|
42
|
-
this.evictIfNeeded();
|
|
43
|
-
if (this.verbose)
|
|
44
|
-
console.error(`[registry] opened ${projectPath} (cache size ${this.cache.size})`);
|
|
45
|
-
return cg;
|
|
46
|
-
}
|
|
47
|
-
catch (err) {
|
|
48
|
-
if (this.verbose)
|
|
49
|
-
console.error(`[registry] open failed for ${projectPath}: ${err instanceof Error ? err.message : String(err)}`);
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Look up by Claude Code's slug-encoded project name
|
|
55
|
-
* (`-Users-alice-foo` → `/Users/alice/foo`).
|
|
56
|
-
*/
|
|
57
|
-
async getBySlug(slug) {
|
|
58
|
-
return this.get(decodeProjectSlug(slug));
|
|
59
|
-
}
|
|
60
|
-
/** Currently-cached project paths (most-recent-access first). */
|
|
61
|
-
openPaths() {
|
|
62
|
-
return [...this.cache.entries()]
|
|
63
|
-
.sort((a, b) => b[1].lastAccess - a[1].lastAccess)
|
|
64
|
-
.map(([k]) => k);
|
|
65
|
-
}
|
|
66
|
-
has(projectPath) { return this.cache.has(projectPath); }
|
|
67
|
-
/** Close + drop every cached instance. Called on server shutdown. */
|
|
68
|
-
closeAll() {
|
|
69
|
-
for (const [, v] of this.cache) {
|
|
70
|
-
try {
|
|
71
|
-
v.cg.close();
|
|
72
|
-
}
|
|
73
|
-
catch { /* ignore */ }
|
|
74
|
-
}
|
|
75
|
-
this.cache.clear();
|
|
76
|
-
}
|
|
77
|
-
evictIfNeeded() {
|
|
78
|
-
if (this.cache.size <= this.maxOpen)
|
|
79
|
-
return;
|
|
80
|
-
let oldestKey = null;
|
|
81
|
-
let oldestTime = Infinity;
|
|
82
|
-
for (const [k, v] of this.cache) {
|
|
83
|
-
if (v.lastAccess < oldestTime) {
|
|
84
|
-
oldestTime = v.lastAccess;
|
|
85
|
-
oldestKey = k;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
if (oldestKey) {
|
|
89
|
-
const entry = this.cache.get(oldestKey);
|
|
90
|
-
if (entry) {
|
|
91
|
-
try {
|
|
92
|
-
entry.cg.close();
|
|
93
|
-
}
|
|
94
|
-
catch { /* ignore */ }
|
|
95
|
-
}
|
|
96
|
-
this.cache.delete(oldestKey);
|
|
97
|
-
if (this.verbose)
|
|
98
|
-
console.error(`[registry] evicted ${oldestKey}`);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
@@ -1,480 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Claude Code analytics routes.
|
|
3
|
-
*
|
|
4
|
-
* All queries hit specship's SQLite directly. The ingest worker
|
|
5
|
-
* (`@selvakumaresra/specship-ingest`) writes to claude_* tables; this layer
|
|
6
|
-
* just rolls up.
|
|
7
|
-
*
|
|
8
|
-
* Endpoints:
|
|
9
|
-
* GET /api/claude/projects — every indexed Claude project
|
|
10
|
-
* GET /api/claude/sessions?project=&limit= — sessions list
|
|
11
|
-
* GET /api/claude/session/:id — session detail (prompts + tools)
|
|
12
|
-
* GET /api/claude/heatmap?range= — file/tool/subagent heatmaps
|
|
13
|
-
* GET /api/claude/costs?range= — cost rollup, timeseries, per-model
|
|
14
|
-
* GET /api/claude/compare — per-project cost comparison
|
|
15
|
-
* GET /api/claude/tips — rule-based tips engine output
|
|
16
|
-
* POST /api/claude/ingest — force a one-shot ingest pass
|
|
17
|
-
*/
|
|
18
|
-
const RANGE_WINDOW_MS = {
|
|
19
|
-
today: 24 * 60 * 60 * 1000,
|
|
20
|
-
week: 7 * 24 * 60 * 60 * 1000,
|
|
21
|
-
month: 30 * 24 * 60 * 60 * 1000,
|
|
22
|
-
all: Number.MAX_SAFE_INTEGER,
|
|
23
|
-
};
|
|
24
|
-
function rangeKey(input) {
|
|
25
|
-
if (input === 'today' || input === 'week' || input === 'month' || input === 'all')
|
|
26
|
-
return input;
|
|
27
|
-
return 'week';
|
|
28
|
-
}
|
|
29
|
-
function rangeStart(key) {
|
|
30
|
-
if (key === 'all')
|
|
31
|
-
return 0;
|
|
32
|
-
return Date.now() - RANGE_WINDOW_MS[key];
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Get the internal SQLite handle off the DatabaseConnection so we can run
|
|
36
|
-
* Claude-specific aggregate queries directly. SpecShip exposes this via
|
|
37
|
-
* `getDb()`-style accessors. Falls back to digging via the queries property.
|
|
38
|
-
*/
|
|
39
|
-
function getDb(cg) {
|
|
40
|
-
// SpecShip exposes the underlying DB via its DatabaseConnection. Look it
|
|
41
|
-
// up via the private field as a fallback — works because it's the same
|
|
42
|
-
// shape regardless of which adapter (better-sqlite3 / node:sqlite) is active.
|
|
43
|
-
const anyCg = cg;
|
|
44
|
-
if (anyCg.db?.getDb)
|
|
45
|
-
return anyCg.db.getDb();
|
|
46
|
-
if (anyCg.queries?.db)
|
|
47
|
-
return anyCg.queries.db;
|
|
48
|
-
throw new Error('specship DB handle not accessible from server context');
|
|
49
|
-
}
|
|
50
|
-
export async function registerClaudeRoutes(app) {
|
|
51
|
-
/**
|
|
52
|
-
* Analytics routes share one SQLite — the boot-time "primary" project's
|
|
53
|
-
* specship.db hosts the cross-project claude_* tables. Without a primary
|
|
54
|
-
* the JSONL ingest has nowhere to write and there's nothing to query, so
|
|
55
|
-
* every analytics handler asks here first.
|
|
56
|
-
*/
|
|
57
|
-
function requirePrimary(reply) {
|
|
58
|
-
if (!app.primaryCg) {
|
|
59
|
-
reply.code(409).send({ error: 'analytics unavailable: no primary project configured', code: 'no_primary' });
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
return app.primaryCg;
|
|
63
|
-
}
|
|
64
|
-
app.get('/api/claude/projects', async (_req, reply) => {
|
|
65
|
-
const cg = requirePrimary(reply);
|
|
66
|
-
if (!cg)
|
|
67
|
-
return;
|
|
68
|
-
const db = getDb(cg);
|
|
69
|
-
const rows = db.prepare(`
|
|
70
|
-
SELECT p.path, p.name, p.first_seen, p.last_seen,
|
|
71
|
-
COUNT(s.id) as sessions,
|
|
72
|
-
COALESCE(SUM(s.total_cost_usd), 0) as cost,
|
|
73
|
-
COALESCE(SUM(s.total_cache_read_tokens), 0) as cacheRead,
|
|
74
|
-
COALESCE(SUM(s.total_cache_creation_tokens + s.total_input_tokens), 0) as totalInput,
|
|
75
|
-
COALESCE(SUM(s.prompt_count), 0) as prompts
|
|
76
|
-
FROM claude_projects p
|
|
77
|
-
LEFT JOIN claude_sessions s ON s.project_path = p.path
|
|
78
|
-
GROUP BY p.path
|
|
79
|
-
ORDER BY cost DESC
|
|
80
|
-
`).all();
|
|
81
|
-
return { projects: rows };
|
|
82
|
-
});
|
|
83
|
-
app.get('/api/claude/sessions', async (req, reply) => {
|
|
84
|
-
const cg = requirePrimary(reply);
|
|
85
|
-
if (!cg)
|
|
86
|
-
return;
|
|
87
|
-
const db = getDb(cg);
|
|
88
|
-
const limit = Math.min(parseInt(req.query.limit ?? '100', 10) || 100, 500);
|
|
89
|
-
const since = rangeStart(rangeKey(req.query.range));
|
|
90
|
-
const params = [since];
|
|
91
|
-
let whereProject = '';
|
|
92
|
-
if (req.query.project) {
|
|
93
|
-
whereProject = ' AND project_path = ?';
|
|
94
|
-
params.push(req.query.project);
|
|
95
|
-
}
|
|
96
|
-
params.push(limit);
|
|
97
|
-
const sessions = db.prepare(`
|
|
98
|
-
SELECT * FROM claude_sessions
|
|
99
|
-
WHERE started_at >= ?${whereProject}
|
|
100
|
-
ORDER BY started_at DESC
|
|
101
|
-
LIMIT ?
|
|
102
|
-
`).all(...params);
|
|
103
|
-
return { sessions };
|
|
104
|
-
});
|
|
105
|
-
app.get('/api/claude/session/:id', async (req, reply) => {
|
|
106
|
-
const cg = requirePrimary(reply);
|
|
107
|
-
if (!cg)
|
|
108
|
-
return;
|
|
109
|
-
const db = getDb(cg);
|
|
110
|
-
const session = db.prepare('SELECT * FROM claude_sessions WHERE id = ?').get(req.params.id);
|
|
111
|
-
if (!session)
|
|
112
|
-
return reply.code(404).send({ error: 'session not found' });
|
|
113
|
-
const prompts = db.prepare(`
|
|
114
|
-
SELECT * FROM claude_prompts WHERE session_id = ? ORDER BY ts ASC
|
|
115
|
-
`).all(req.params.id);
|
|
116
|
-
const toolCalls = db.prepare(`
|
|
117
|
-
SELECT * FROM claude_tool_calls WHERE session_id = ? ORDER BY ts ASC
|
|
118
|
-
`).all(req.params.id);
|
|
119
|
-
return { session, prompts, toolCalls };
|
|
120
|
-
});
|
|
121
|
-
app.get('/api/claude/heatmap', async (req, reply) => {
|
|
122
|
-
const cg = requirePrimary(reply);
|
|
123
|
-
if (!cg)
|
|
124
|
-
return;
|
|
125
|
-
const db = getDb(cg);
|
|
126
|
-
const since = rangeStart(rangeKey(req.query.range));
|
|
127
|
-
// Files heatmap — input_summary doubles as the file path for Read/Edit/Write.
|
|
128
|
-
const files = db.prepare(`
|
|
129
|
-
SELECT input_summary as path, COUNT(*) as calls, SUM(result_length) as resultBytes
|
|
130
|
-
FROM claude_tool_calls
|
|
131
|
-
WHERE ts >= ? AND tool_name IN ('Read','Edit','Write','NotebookEdit') AND input_summary != ''
|
|
132
|
-
GROUP BY input_summary
|
|
133
|
-
ORDER BY calls DESC
|
|
134
|
-
LIMIT 100
|
|
135
|
-
`).all(since);
|
|
136
|
-
// Tools heatmap.
|
|
137
|
-
const tools = db.prepare(`
|
|
138
|
-
SELECT tool_name as name, COUNT(*) as calls, SUM(result_length) as resultBytes
|
|
139
|
-
FROM claude_tool_calls
|
|
140
|
-
WHERE ts >= ?
|
|
141
|
-
GROUP BY tool_name
|
|
142
|
-
ORDER BY calls DESC
|
|
143
|
-
`).all(since);
|
|
144
|
-
// Subagent attribution (is_sidechain at the prompt level — main vs. sidechain rollup).
|
|
145
|
-
const subagents = db.prepare(`
|
|
146
|
-
SELECT
|
|
147
|
-
CASE WHEN p.is_sidechain = 1 THEN 'subagent' ELSE 'main' END as type,
|
|
148
|
-
COUNT(*) as prompts,
|
|
149
|
-
SUM(p.input_tokens + p.output_tokens + p.cache_creation_tokens + p.cache_read_tokens) as tokens,
|
|
150
|
-
SUM(p.cost_usd) as cost
|
|
151
|
-
FROM claude_prompts p
|
|
152
|
-
WHERE p.ts >= ?
|
|
153
|
-
GROUP BY type
|
|
154
|
-
`).all(since);
|
|
155
|
-
// Subagent breakdown by name — Task tool calls grouped by subagent_type.
|
|
156
|
-
// input_summary is the JSON-serialized tool input; json_extract pulls
|
|
157
|
-
// out subagent_type (defaults to 'general-purpose' when unset).
|
|
158
|
-
const subagentByName = db.prepare(`
|
|
159
|
-
SELECT
|
|
160
|
-
COALESCE(NULLIF(json_extract(input_summary, '$.subagent_type'), ''), 'general-purpose') as name,
|
|
161
|
-
COUNT(*) as calls,
|
|
162
|
-
MIN(ts) as firstSeen,
|
|
163
|
-
MAX(ts) as lastSeen
|
|
164
|
-
FROM claude_tool_calls
|
|
165
|
-
WHERE ts >= ? AND tool_name = 'Task'
|
|
166
|
-
GROUP BY name
|
|
167
|
-
ORDER BY calls DESC
|
|
168
|
-
`).all(since);
|
|
169
|
-
return { files, tools, subagents, subagentByName };
|
|
170
|
-
});
|
|
171
|
-
/**
|
|
172
|
-
* Drill-down: which sessions touched a given file (via Read/Edit/Write).
|
|
173
|
-
* Used by the heatmap page when the user clicks a file cell.
|
|
174
|
-
*/
|
|
175
|
-
app.get('/api/claude/heatmap/file', async (req, reply) => {
|
|
176
|
-
const path = req.query.path;
|
|
177
|
-
if (!path)
|
|
178
|
-
return reply.code(400).send({ error: 'path required' });
|
|
179
|
-
const cg = requirePrimary(reply);
|
|
180
|
-
if (!cg)
|
|
181
|
-
return;
|
|
182
|
-
const db = getDb(cg);
|
|
183
|
-
const since = rangeStart(rangeKey(req.query.range));
|
|
184
|
-
const sessions = db.prepare(`
|
|
185
|
-
SELECT t.session_id, s.last_model, s.project_path,
|
|
186
|
-
COUNT(*) as calls, COALESCE(SUM(t.result_length), 0) as bytes,
|
|
187
|
-
MAX(t.ts) as lastTs, MIN(t.ts) as firstTs
|
|
188
|
-
FROM claude_tool_calls t
|
|
189
|
-
LEFT JOIN claude_sessions s ON s.id = t.session_id
|
|
190
|
-
WHERE t.input_summary = ? AND t.ts >= ? AND t.tool_name IN ('Read','Edit','Write','NotebookEdit')
|
|
191
|
-
GROUP BY t.session_id
|
|
192
|
-
ORDER BY calls DESC
|
|
193
|
-
LIMIT 50
|
|
194
|
-
`).all(path, since);
|
|
195
|
-
const byTool = db.prepare(`
|
|
196
|
-
SELECT tool_name as name, COUNT(*) as calls, COALESCE(SUM(result_length), 0) as bytes
|
|
197
|
-
FROM claude_tool_calls
|
|
198
|
-
WHERE input_summary = ? AND ts >= ? AND tool_name IN ('Read','Edit','Write','NotebookEdit')
|
|
199
|
-
GROUP BY tool_name
|
|
200
|
-
ORDER BY calls DESC
|
|
201
|
-
`).all(path, since);
|
|
202
|
-
return { path, sessions, byTool };
|
|
203
|
-
});
|
|
204
|
-
/**
|
|
205
|
-
* Drill-down: the top distinct inputs for a given tool (file paths for
|
|
206
|
-
* Read/Edit/Write, patterns for Grep/Glob, commands for Bash).
|
|
207
|
-
*/
|
|
208
|
-
app.get('/api/claude/heatmap/tool', async (req, reply) => {
|
|
209
|
-
const name = req.query.name;
|
|
210
|
-
if (!name)
|
|
211
|
-
return reply.code(400).send({ error: 'name required' });
|
|
212
|
-
const cg = requirePrimary(reply);
|
|
213
|
-
if (!cg)
|
|
214
|
-
return;
|
|
215
|
-
const db = getDb(cg);
|
|
216
|
-
const since = rangeStart(rangeKey(req.query.range));
|
|
217
|
-
const totals = db.prepare(`
|
|
218
|
-
SELECT COUNT(*) as calls, COALESCE(SUM(result_length), 0) as bytes,
|
|
219
|
-
COUNT(DISTINCT session_id) as sessions
|
|
220
|
-
FROM claude_tool_calls
|
|
221
|
-
WHERE tool_name = ? AND ts >= ?
|
|
222
|
-
`).get(name, since);
|
|
223
|
-
const inputs = db.prepare(`
|
|
224
|
-
SELECT
|
|
225
|
-
CASE WHEN length(input_summary) > 120 THEN substr(input_summary, 1, 120) || '…'
|
|
226
|
-
ELSE input_summary END as input,
|
|
227
|
-
COUNT(*) as calls,
|
|
228
|
-
COALESCE(SUM(result_length), 0) as bytes,
|
|
229
|
-
MAX(ts) as lastTs
|
|
230
|
-
FROM claude_tool_calls
|
|
231
|
-
WHERE tool_name = ? AND ts >= ? AND input_summary != ''
|
|
232
|
-
GROUP BY input_summary
|
|
233
|
-
ORDER BY calls DESC
|
|
234
|
-
LIMIT 30
|
|
235
|
-
`).all(name, since);
|
|
236
|
-
const recentSessions = db.prepare(`
|
|
237
|
-
SELECT t.session_id, s.last_model, s.project_path, COUNT(*) as calls, MAX(t.ts) as lastTs
|
|
238
|
-
FROM claude_tool_calls t
|
|
239
|
-
LEFT JOIN claude_sessions s ON s.id = t.session_id
|
|
240
|
-
WHERE t.tool_name = ? AND t.ts >= ?
|
|
241
|
-
GROUP BY t.session_id
|
|
242
|
-
ORDER BY lastTs DESC
|
|
243
|
-
LIMIT 20
|
|
244
|
-
`).all(name, since);
|
|
245
|
-
return { tool: name, totals, inputs, recentSessions };
|
|
246
|
-
});
|
|
247
|
-
/**
|
|
248
|
-
* Drill-down: invocations of a specific subagent (by subagent_type name).
|
|
249
|
-
*/
|
|
250
|
-
app.get('/api/claude/heatmap/subagent', async (req, reply) => {
|
|
251
|
-
const type = req.query.type;
|
|
252
|
-
if (!type)
|
|
253
|
-
return reply.code(400).send({ error: 'type required' });
|
|
254
|
-
const cg = requirePrimary(reply);
|
|
255
|
-
if (!cg)
|
|
256
|
-
return;
|
|
257
|
-
const db = getDb(cg);
|
|
258
|
-
const since = rangeStart(rangeKey(req.query.range));
|
|
259
|
-
const totals = db.prepare(`
|
|
260
|
-
SELECT COUNT(*) as calls, COUNT(DISTINCT session_id) as sessions
|
|
261
|
-
FROM claude_tool_calls
|
|
262
|
-
WHERE tool_name = 'Task' AND ts >= ?
|
|
263
|
-
AND COALESCE(NULLIF(json_extract(input_summary, '$.subagent_type'), ''), 'general-purpose') = ?
|
|
264
|
-
`).get(since, type);
|
|
265
|
-
const invocations = db.prepare(`
|
|
266
|
-
SELECT
|
|
267
|
-
t.session_id,
|
|
268
|
-
t.ts,
|
|
269
|
-
COALESCE(json_extract(t.input_summary, '$.description'), '') as description,
|
|
270
|
-
COALESCE(json_extract(t.input_summary, '$.prompt'), '') as prompt,
|
|
271
|
-
s.last_model
|
|
272
|
-
FROM claude_tool_calls t
|
|
273
|
-
LEFT JOIN claude_sessions s ON s.id = t.session_id
|
|
274
|
-
WHERE t.tool_name = 'Task' AND t.ts >= ?
|
|
275
|
-
AND COALESCE(NULLIF(json_extract(t.input_summary, '$.subagent_type'), ''), 'general-purpose') = ?
|
|
276
|
-
ORDER BY t.ts DESC
|
|
277
|
-
LIMIT 50
|
|
278
|
-
`).all(since, type);
|
|
279
|
-
return { subagent: type, totals, invocations };
|
|
280
|
-
});
|
|
281
|
-
app.get('/api/claude/cache', async (req, reply) => {
|
|
282
|
-
const cg = requirePrimary(reply);
|
|
283
|
-
if (!cg)
|
|
284
|
-
return;
|
|
285
|
-
const db = getDb(cg);
|
|
286
|
-
const since = rangeStart(rangeKey(req.query.range));
|
|
287
|
-
// Aggregate cache totals from claude_sessions for sessions in window.
|
|
288
|
-
const agg = db.prepare(`
|
|
289
|
-
SELECT
|
|
290
|
-
COALESCE(SUM(total_input_tokens), 0) as inp,
|
|
291
|
-
COALESCE(SUM(total_output_tokens), 0) as out,
|
|
292
|
-
COALESCE(SUM(total_cache_creation_tokens), 0) as cw,
|
|
293
|
-
COALESCE(SUM(total_cache_read_tokens), 0) as cr,
|
|
294
|
-
COALESCE(SUM(total_cost_usd), 0) as cost
|
|
295
|
-
FROM claude_sessions
|
|
296
|
-
WHERE started_at >= ?
|
|
297
|
-
`).get(since);
|
|
298
|
-
const total = (agg.inp ?? 0) + (agg.cw ?? 0) + (agg.cr ?? 0);
|
|
299
|
-
const readRate = total > 0 ? agg.cr / total : 0;
|
|
300
|
-
// Dollars saved estimate: cache_read tokens billed at ~10% of input;
|
|
301
|
-
// savings vs charging them at input rate ≈ 0.9 × (cr / 1M) × inputRate.
|
|
302
|
-
// Use Opus 4-7 input ($15/M) as a generous upper bound — the UI shows
|
|
303
|
-
// this as an approximation.
|
|
304
|
-
const dollarsSaved = ((agg.cr ?? 0) / 1_000_000) * 15 * 0.9;
|
|
305
|
-
return {
|
|
306
|
-
readRate,
|
|
307
|
-
creationTokens: agg.cw ?? 0,
|
|
308
|
-
readTokens: agg.cr ?? 0,
|
|
309
|
-
inputTokens: agg.inp ?? 0,
|
|
310
|
-
outputTokens: agg.out ?? 0,
|
|
311
|
-
totalCost: agg.cost ?? 0,
|
|
312
|
-
dollarsSaved,
|
|
313
|
-
// wowDelta would need historical snapshotting; placeholder until we
|
|
314
|
-
// add a rolling-window aggregate table. UI shows 0% with no arrow.
|
|
315
|
-
wowDelta: 0,
|
|
316
|
-
};
|
|
317
|
-
});
|
|
318
|
-
app.get('/api/claude/costs', async (req, reply) => {
|
|
319
|
-
const cg = requirePrimary(reply);
|
|
320
|
-
if (!cg)
|
|
321
|
-
return;
|
|
322
|
-
const db = getDb(cg);
|
|
323
|
-
const since = rangeStart(rangeKey(req.query.range));
|
|
324
|
-
const total = db.prepare(`SELECT SUM(total_cost_usd) as t FROM claude_sessions WHERE started_at >= ?`).get(since);
|
|
325
|
-
// Top prompts by cost.
|
|
326
|
-
const topPrompts = db.prepare(`
|
|
327
|
-
SELECT id, session_id, substr(text, 1, 200) as text, model, cost_usd,
|
|
328
|
-
input_tokens, output_tokens, cache_creation_tokens, cache_read_tokens, ts
|
|
329
|
-
FROM claude_prompts
|
|
330
|
-
WHERE ts >= ? AND cost_usd > 0
|
|
331
|
-
ORDER BY cost_usd DESC
|
|
332
|
-
LIMIT 50
|
|
333
|
-
`).all(since);
|
|
334
|
-
// Daily timeseries: bucket by 24h windows.
|
|
335
|
-
const days = 30;
|
|
336
|
-
const dayMs = 24 * 60 * 60 * 1000;
|
|
337
|
-
const dayBoundary = Math.floor(Date.now() / dayMs) * dayMs - (days - 1) * dayMs;
|
|
338
|
-
const series = db.prepare(`
|
|
339
|
-
SELECT
|
|
340
|
-
CAST((ts - ?) / ? AS INTEGER) as bucket,
|
|
341
|
-
SUM(cost_usd) as cost,
|
|
342
|
-
COUNT(*) as prompts
|
|
343
|
-
FROM claude_prompts
|
|
344
|
-
WHERE ts >= ?
|
|
345
|
-
GROUP BY bucket
|
|
346
|
-
ORDER BY bucket ASC
|
|
347
|
-
`).all(dayBoundary, dayMs, dayBoundary);
|
|
348
|
-
// Densify with zeros for missing days.
|
|
349
|
-
const dense = [];
|
|
350
|
-
for (let i = 0; i < days; i++) {
|
|
351
|
-
const found = series.find((s) => s.bucket === i);
|
|
352
|
-
dense.push({ day: days - 1 - i, cost: found?.cost ?? 0, prompts: found?.prompts ?? 0 });
|
|
353
|
-
}
|
|
354
|
-
// By model.
|
|
355
|
-
const byModel = db.prepare(`
|
|
356
|
-
SELECT model, COUNT(*) as prompts, SUM(cost_usd) as cost
|
|
357
|
-
FROM claude_prompts
|
|
358
|
-
WHERE ts >= ? AND model IS NOT NULL
|
|
359
|
-
GROUP BY model
|
|
360
|
-
ORDER BY cost DESC
|
|
361
|
-
`).all(since);
|
|
362
|
-
return { total: total.t ?? 0, topPrompts, series: dense, byModel };
|
|
363
|
-
});
|
|
364
|
-
app.get('/api/claude/compare', async (_req, reply) => {
|
|
365
|
-
const cg = requirePrimary(reply);
|
|
366
|
-
if (!cg)
|
|
367
|
-
return;
|
|
368
|
-
const db = getDb(cg);
|
|
369
|
-
const rows = db.prepare(`
|
|
370
|
-
SELECT
|
|
371
|
-
p.path, p.name,
|
|
372
|
-
COUNT(s.id) as sessions,
|
|
373
|
-
COALESCE(SUM(s.total_cost_usd), 0) as cost,
|
|
374
|
-
COALESCE(AVG(s.total_cost_usd), 0) as avgCost,
|
|
375
|
-
COALESCE(SUM(s.prompt_count), 0) as prompts,
|
|
376
|
-
CASE WHEN SUM(s.total_input_tokens + s.total_cache_creation_tokens + s.total_cache_read_tokens) > 0
|
|
377
|
-
THEN CAST(SUM(s.total_cache_read_tokens) AS REAL) / SUM(s.total_input_tokens + s.total_cache_creation_tokens + s.total_cache_read_tokens)
|
|
378
|
-
ELSE 0 END as cacheHit
|
|
379
|
-
FROM claude_projects p
|
|
380
|
-
LEFT JOIN claude_sessions s ON s.project_path = p.path
|
|
381
|
-
GROUP BY p.path
|
|
382
|
-
ORDER BY cost DESC
|
|
383
|
-
`).all();
|
|
384
|
-
return { projects: rows };
|
|
385
|
-
});
|
|
386
|
-
/**
|
|
387
|
-
* Rule-based tips engine. Each rule is a SQL query that finds a wasteful
|
|
388
|
-
* pattern in the user's recent transcripts; the result is shaped into a
|
|
389
|
-
* tip card matching the design system's voice.
|
|
390
|
-
*/
|
|
391
|
-
app.get('/api/claude/tips', async (_req, reply) => {
|
|
392
|
-
const cg = requirePrimary(reply);
|
|
393
|
-
if (!cg)
|
|
394
|
-
return;
|
|
395
|
-
const db = getDb(cg);
|
|
396
|
-
const tips = [];
|
|
397
|
-
// Rule 1: "you read X N times" — same file path Read more than 10 times in
|
|
398
|
-
// a single session.
|
|
399
|
-
const wastefulReads = db.prepare(`
|
|
400
|
-
SELECT session_id, input_summary as file, COUNT(*) as n
|
|
401
|
-
FROM claude_tool_calls
|
|
402
|
-
WHERE tool_name = 'Read' AND input_summary != ''
|
|
403
|
-
GROUP BY session_id, input_summary
|
|
404
|
-
HAVING n >= 10
|
|
405
|
-
ORDER BY n DESC
|
|
406
|
-
LIMIT 5
|
|
407
|
-
`).all();
|
|
408
|
-
for (const r of wastefulReads) {
|
|
409
|
-
tips.push({
|
|
410
|
-
id: 'wasteful_reads:' + r.session_id + ':' + r.file,
|
|
411
|
-
severity: 'error',
|
|
412
|
-
icon: 'wrench',
|
|
413
|
-
title: `You read ${r.file.split('/').pop()} ${r.n}× in one session — specship_explore covers it`,
|
|
414
|
-
why: 'Re-reading the same file burns input tokens every turn. A single structural query returns callers, callees, and linked specs at once.',
|
|
415
|
-
evidence: { session: r.session_id, detail: `Read(${r.file}) × ${r.n}` },
|
|
416
|
-
fix: `specship_explore --symbol ${r.file.replace(/\.\w+$/, '').split('/').pop()}`,
|
|
417
|
-
saving: '≈$0.10/read avoided',
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
// Rule 2: "tool returned X tokens" — any single tool call with result_length > 50000.
|
|
421
|
-
const heavyResults = db.prepare(`
|
|
422
|
-
SELECT id, session_id, tool_name, input_summary, result_length
|
|
423
|
-
FROM claude_tool_calls
|
|
424
|
-
WHERE result_length > 50000
|
|
425
|
-
ORDER BY result_length DESC
|
|
426
|
-
LIMIT 5
|
|
427
|
-
`).all();
|
|
428
|
-
for (const r of heavyResults) {
|
|
429
|
-
tips.push({
|
|
430
|
-
id: 'heavy_result:' + r.id,
|
|
431
|
-
severity: 'error',
|
|
432
|
-
icon: 'flame',
|
|
433
|
-
title: `${r.tool_name} returned ${Math.round(r.result_length / 1000)}k tokens — try a structural query`,
|
|
434
|
-
why: 'Tools that dump raw content into context are the dominant cost driver. A structural query returns just what the agent needs.',
|
|
435
|
-
evidence: { session: r.session_id, detail: `${r.tool_name}(${r.input_summary.slice(0, 100)}) → ${r.result_length} tokens` },
|
|
436
|
-
fix: r.tool_name === 'Bash' ? 'specship_search instead of Bash(grep)' : 'specship_explore on the symbol',
|
|
437
|
-
saving: `~$${((r.result_length / 1_000_000) * 15).toFixed(2)} on this call`,
|
|
438
|
-
});
|
|
439
|
-
}
|
|
440
|
-
// Rule 3: "cache miss rate" — sessions with > 10 prompts and cache_read_rate < 0.3.
|
|
441
|
-
const lowCache = db.prepare(`
|
|
442
|
-
SELECT s.id, s.total_cache_read_tokens as cr, s.total_input_tokens as ti, s.total_cache_creation_tokens as cw, s.prompt_count, s.last_model
|
|
443
|
-
FROM claude_sessions s
|
|
444
|
-
WHERE s.prompt_count >= 10
|
|
445
|
-
AND (s.total_input_tokens + s.total_cache_creation_tokens + s.total_cache_read_tokens) > 0
|
|
446
|
-
ORDER BY (CAST(s.total_cache_read_tokens AS REAL) / (s.total_input_tokens + s.total_cache_creation_tokens + s.total_cache_read_tokens)) ASC
|
|
447
|
-
LIMIT 3
|
|
448
|
-
`).all();
|
|
449
|
-
for (const r of lowCache) {
|
|
450
|
-
const total = r.ti + r.cw + r.cr;
|
|
451
|
-
const rate = total > 0 ? r.cr / total : 0;
|
|
452
|
-
if (rate >= 0.3)
|
|
453
|
-
continue;
|
|
454
|
-
tips.push({
|
|
455
|
-
id: 'low_cache:' + r.id,
|
|
456
|
-
severity: 'warn',
|
|
457
|
-
icon: 'database',
|
|
458
|
-
title: `Cache read rate is ${Math.round(rate * 100)}% on a ${r.prompt_count}-prompt session`,
|
|
459
|
-
why: 'When the prompt prefix changes every turn, the 1h cache gets invalidated. Pinning a stable system-prompt prefix lets the cache absorb most of your input.',
|
|
460
|
-
evidence: { session: r.id, detail: `cache_read=${(r.cr / 1_000_000).toFixed(2)}M / total=${(total / 1_000_000).toFixed(2)}M` },
|
|
461
|
-
fix: 'Pin a stable system-prompt prefix in .claude/settings.json',
|
|
462
|
-
saving: '~$X.XX / session (model-dependent)',
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
// Sort: errors before warns before info, then within bucket by saving heuristic.
|
|
466
|
-
const order = { error: 0, warn: 1, info: 2 };
|
|
467
|
-
tips.sort((a, b) => (order[a.severity] ?? 9) - (order[b.severity] ?? 9));
|
|
468
|
-
return { tips };
|
|
469
|
-
});
|
|
470
|
-
/**
|
|
471
|
-
* Force a one-shot ingest pass. Useful for "Refresh" button in the UI.
|
|
472
|
-
*/
|
|
473
|
-
app.post('/api/claude/ingest', async () => {
|
|
474
|
-
const watcher = app.watcher;
|
|
475
|
-
if (!watcher)
|
|
476
|
-
return { ok: false, error: 'watcher not running' };
|
|
477
|
-
const stats = watcher.ingestNow();
|
|
478
|
-
return { ok: true, stats };
|
|
479
|
-
});
|
|
480
|
-
}
|