@vpxa/kb 0.1.24 → 0.1.26

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.
Files changed (209) hide show
  1. package/README.md +3 -3
  2. package/package.json +9 -2
  3. package/packages/analyzers/dist/symbol-analyzer.js +5 -5
  4. package/packages/cli/dist/commands/init/adapters.js +1 -1
  5. package/packages/cli/dist/commands/init/constants.d.ts +4 -1
  6. package/packages/cli/dist/commands/init/constants.js +1 -1
  7. package/packages/cli/dist/commands/init/frontmatter.d.ts +54 -0
  8. package/packages/cli/dist/commands/init/frontmatter.js +2 -0
  9. package/packages/cli/dist/commands/init/index.js +4 -4
  10. package/packages/cli/dist/commands/init/manifest.d.ts +71 -0
  11. package/packages/cli/dist/commands/init/manifest.js +1 -0
  12. package/packages/cli/dist/commands/init/scaffold.d.ts +28 -5
  13. package/packages/cli/dist/commands/init/scaffold.js +1 -1
  14. package/packages/cli/dist/commands/init/templates.js +38 -9
  15. package/packages/cli/dist/commands/init/user.d.ts +3 -3
  16. package/packages/cli/dist/commands/init/user.js +4 -4
  17. package/packages/cli/dist/commands/system.js +2 -2
  18. package/packages/cli/dist/kb-init.js +1 -1
  19. package/packages/core/dist/errors.d.ts +2 -2
  20. package/packages/core/dist/errors.js +1 -1
  21. package/packages/core/dist/logger.d.ts +2 -1
  22. package/packages/core/dist/logger.js +1 -1
  23. package/packages/core/dist/types.d.ts +6 -0
  24. package/packages/dashboard/dist/assets/index-9ysCkze9.js +21 -0
  25. package/packages/dashboard/dist/assets/index-9ysCkze9.js.map +1 -0
  26. package/packages/dashboard/dist/assets/index-CHpVij2M.css +1 -0
  27. package/packages/dashboard/dist/index.html +18 -0
  28. package/packages/elicitation/dist/__tests__/build.test.d.ts +1 -0
  29. package/packages/elicitation/dist/__tests__/build.test.js +35 -0
  30. package/packages/elicitation/dist/__tests__/fields.test.d.ts +1 -0
  31. package/packages/elicitation/dist/__tests__/fields.test.js +81 -0
  32. package/packages/elicitation/dist/__tests__/normalize.test.d.ts +1 -0
  33. package/packages/elicitation/dist/__tests__/normalize.test.js +60 -0
  34. package/packages/elicitation/dist/build.d.ts +13 -0
  35. package/packages/elicitation/dist/build.js +23 -0
  36. package/packages/elicitation/dist/fields.d.ts +41 -0
  37. package/packages/elicitation/dist/fields.js +62 -0
  38. package/packages/elicitation/dist/index.d.ts +10 -0
  39. package/packages/elicitation/dist/index.js +12 -0
  40. package/packages/elicitation/dist/normalize.d.ts +15 -0
  41. package/packages/elicitation/dist/normalize.js +31 -0
  42. package/packages/elicitation/dist/types.d.ts +85 -0
  43. package/packages/elicitation/dist/types.js +8 -0
  44. package/packages/kb-client/dist/direct-client.d.ts +37 -0
  45. package/packages/kb-client/dist/direct-client.js +1 -0
  46. package/packages/kb-client/dist/index.d.ts +5 -0
  47. package/packages/kb-client/dist/index.js +1 -0
  48. package/packages/kb-client/dist/mcp-client.d.ts +19 -0
  49. package/packages/kb-client/dist/mcp-client.js +4 -0
  50. package/packages/kb-client/dist/parsers.d.ts +35 -0
  51. package/packages/kb-client/dist/parsers.js +2 -0
  52. package/packages/kb-client/dist/types.d.ts +62 -0
  53. package/packages/kb-client/dist/types.js +1 -0
  54. package/packages/present/dist/index.html +384 -0
  55. package/packages/server/dist/completions.d.ts +14 -0
  56. package/packages/server/dist/completions.js +1 -0
  57. package/packages/server/dist/dashboard-static.d.ts +27 -0
  58. package/packages/server/dist/dashboard-static.js +1 -0
  59. package/packages/server/dist/elicitor.d.ts +18 -0
  60. package/packages/server/dist/elicitor.js +1 -0
  61. package/packages/server/dist/index.js +1 -1
  62. package/packages/server/dist/mcp-logging.js +1 -1
  63. package/packages/server/dist/output-schemas.d.ts +118 -1
  64. package/packages/server/dist/output-schemas.js +1 -1
  65. package/packages/server/dist/prompts.d.ts +9 -2
  66. package/packages/server/dist/prompts.js +13 -7
  67. package/packages/server/dist/resources/curated-resources.js +1 -1
  68. package/packages/server/dist/resources/resource-notifier.d.ts +45 -0
  69. package/packages/server/dist/resources/resource-notifier.js +1 -0
  70. package/packages/server/dist/sampling.d.ts +41 -0
  71. package/packages/server/dist/sampling.js +2 -0
  72. package/packages/server/dist/server.d.ts +5 -2
  73. package/packages/server/dist/server.js +2 -2
  74. package/packages/server/dist/task-manager.d.ts +40 -0
  75. package/packages/server/dist/task-manager.js +1 -0
  76. package/packages/server/dist/tool-metadata.js +1 -1
  77. package/packages/server/dist/tool-prefix.d.ts +12 -0
  78. package/packages/server/dist/tool-prefix.js +1 -0
  79. package/packages/server/dist/tools/analyze.tools.js +4 -4
  80. package/packages/server/dist/tools/audit.tool.js +1 -1
  81. package/packages/server/dist/tools/brainstorm.tool.d.ts +7 -0
  82. package/packages/server/dist/tools/brainstorm.tool.js +9 -0
  83. package/packages/server/dist/tools/context.tools.js +9 -9
  84. package/packages/server/dist/tools/execution.tools.d.ts +2 -1
  85. package/packages/server/dist/tools/execution.tools.js +4 -4
  86. package/packages/server/dist/tools/forge.tools.js +10 -10
  87. package/packages/server/dist/tools/forget.tool.d.ts +2 -1
  88. package/packages/server/dist/tools/forget.tool.js +1 -1
  89. package/packages/server/dist/tools/graph.tool.js +2 -2
  90. package/packages/server/dist/tools/manipulation.tools.js +4 -4
  91. package/packages/server/dist/tools/onboard.tool.js +2 -2
  92. package/packages/server/dist/tools/present-blocks.d.ts +46 -0
  93. package/packages/server/dist/tools/present-blocks.js +27 -0
  94. package/packages/server/dist/tools/present-charts.d.ts +31 -0
  95. package/packages/server/dist/tools/present-charts.js +34 -0
  96. package/packages/server/dist/tools/present-theme.d.ts +14 -0
  97. package/packages/server/dist/tools/present-theme.js +395 -0
  98. package/packages/server/dist/tools/present-utils.d.ts +11 -0
  99. package/packages/server/dist/tools/present-utils.js +1 -0
  100. package/packages/server/dist/tools/present.tool.d.ts +7 -0
  101. package/packages/server/dist/tools/present.tool.js +113 -0
  102. package/packages/server/dist/tools/produce.tool.js +2 -2
  103. package/packages/server/dist/tools/reindex.tool.d.ts +2 -1
  104. package/packages/server/dist/tools/reindex.tool.js +2 -2
  105. package/packages/server/dist/tools/remember.tool.d.ts +2 -1
  106. package/packages/server/dist/tools/remember.tool.js +2 -2
  107. package/packages/server/dist/tools/replay.tool.js +1 -1
  108. package/packages/server/dist/tools/search.tool.d.ts +2 -1
  109. package/packages/server/dist/tools/search.tool.js +5 -4
  110. package/packages/server/dist/tools/status.tool.js +2 -2
  111. package/packages/server/dist/tools/update.tool.d.ts +2 -1
  112. package/packages/server/dist/tools/update.tool.js +1 -1
  113. package/packages/server/dist/tools/utility.tools.js +1 -1
  114. package/packages/tools/dist/batch.js +1 -1
  115. package/packages/tools/dist/checkpoint.js +1 -1
  116. package/packages/tools/dist/config-extractor.d.ts +9 -0
  117. package/packages/tools/dist/config-extractor.js +7 -0
  118. package/packages/tools/dist/dead-symbols.js +2 -2
  119. package/packages/tools/dist/diagram-builder.d.ts +9 -0
  120. package/packages/tools/dist/diagram-builder.js +9 -0
  121. package/packages/tools/dist/evidence-map.d.ts +12 -1
  122. package/packages/tools/dist/evidence-map.js +2 -2
  123. package/packages/tools/dist/find-examples.js +2 -2
  124. package/packages/tools/dist/forge-classify.d.ts +4 -0
  125. package/packages/tools/dist/forge-classify.js +1 -1
  126. package/packages/tools/dist/git-context.d.ts +1 -0
  127. package/packages/tools/dist/git-context.js +3 -3
  128. package/packages/tools/dist/index.d.ts +3 -2
  129. package/packages/tools/dist/index.js +1 -1
  130. package/packages/tools/dist/onboard-utils.d.ts +12 -0
  131. package/packages/tools/dist/onboard-utils.js +1 -0
  132. package/packages/tools/dist/onboard.js +2 -21
  133. package/packages/tools/dist/regex-utils.d.ts +8 -0
  134. package/packages/tools/dist/regex-utils.js +1 -0
  135. package/packages/tools/dist/rename.js +2 -2
  136. package/packages/tools/dist/replay.d.ts +2 -1
  137. package/packages/tools/dist/replay.js +4 -4
  138. package/packages/tools/dist/symbol.js +3 -3
  139. package/packages/tools/dist/synthesis-engine.d.ts +13 -0
  140. package/packages/tools/dist/synthesis-engine.js +6 -0
  141. package/packages/tools/dist/trace.js +2 -2
  142. package/packages/tui/dist/App-DXY0-tlW.js +2 -0
  143. package/packages/tui/dist/App.d.ts +3 -3
  144. package/packages/tui/dist/App.js +1 -1
  145. package/packages/tui/dist/CuratedPanel-BIamXLNy.js +2 -0
  146. package/packages/tui/dist/LogPanel-D6u6o84n.js +3 -0
  147. package/packages/tui/dist/SearchPanel-CpJGczAc.js +2 -0
  148. package/packages/tui/dist/StatusPanel-BAbUxyqQ.js +2 -0
  149. package/packages/tui/dist/hooks/useKBClient.d.ts +9 -0
  150. package/packages/tui/dist/hooks/useKBClient.js +2 -0
  151. package/packages/tui/dist/hooks/usePolling.d.ts +8 -0
  152. package/packages/tui/dist/hooks/usePolling.js +2 -0
  153. package/packages/tui/dist/index.d.ts +6 -2
  154. package/packages/tui/dist/index.js +1 -1
  155. package/packages/tui/dist/jsx-runtime-y6Gdq5PZ.js +294 -0
  156. package/packages/tui/dist/panels/CuratedPanel.d.ts +1 -7
  157. package/packages/tui/dist/panels/CuratedPanel.js +1 -1
  158. package/packages/tui/dist/panels/LogPanel.js +1 -1
  159. package/packages/tui/dist/panels/SearchPanel.d.ts +1 -10
  160. package/packages/tui/dist/panels/SearchPanel.js +1 -1
  161. package/packages/tui/dist/panels/StatusPanel.d.ts +1 -7
  162. package/packages/tui/dist/panels/StatusPanel.js +1 -1
  163. package/packages/tui/dist/react-D__J1GQe.js +24 -0
  164. package/packages/tui/dist/types-VcTHNV6s.d.ts +64 -0
  165. package/packages/tui/dist/useKBClient-C35iA4uG.js +2 -0
  166. package/packages/tui/dist/usePolling-BbjnRWgx.js +2 -0
  167. package/scaffold/adapters/copilot.mjs +9 -81
  168. package/scaffold/definitions/agents.mjs +12 -0
  169. package/scaffold/definitions/bodies.mjs +39 -14
  170. package/scaffold/definitions/protocols.mjs +149 -0
  171. package/scaffold/definitions/tools.mjs +40 -5
  172. package/scaffold/general/agents/Architect-Reviewer-Alpha.agent.md +1 -1
  173. package/scaffold/general/agents/Architect-Reviewer-Beta.agent.md +1 -1
  174. package/scaffold/general/agents/Code-Reviewer-Alpha.agent.md +1 -1
  175. package/scaffold/general/agents/Code-Reviewer-Beta.agent.md +1 -1
  176. package/scaffold/general/agents/Debugger.agent.md +2 -2
  177. package/scaffold/general/agents/Documenter.agent.md +2 -2
  178. package/scaffold/general/agents/Explorer.agent.md +4 -3
  179. package/scaffold/general/agents/Frontend.agent.md +1 -1
  180. package/scaffold/general/agents/Implementer.agent.md +1 -1
  181. package/scaffold/general/agents/Orchestrator.agent.md +16 -1
  182. package/scaffold/general/agents/Planner.agent.md +11 -4
  183. package/scaffold/general/agents/Refactor.agent.md +1 -1
  184. package/scaffold/general/agents/Researcher-Alpha.agent.md +1 -1
  185. package/scaffold/general/agents/Researcher-Beta.agent.md +1 -1
  186. package/scaffold/general/agents/Researcher-Delta.agent.md +1 -1
  187. package/scaffold/general/agents/Researcher-Gamma.agent.md +1 -1
  188. package/scaffold/general/agents/Security.agent.md +10 -8
  189. package/scaffold/general/agents/_shared/architect-reviewer-base.md +1 -0
  190. package/scaffold/general/agents/_shared/code-agent-base.md +28 -0
  191. package/scaffold/general/agents/_shared/code-reviewer-base.md +1 -0
  192. package/scaffold/general/agents/_shared/forge-protocol.md +44 -0
  193. package/scaffold/general/agents/_shared/researcher-base.md +14 -0
  194. package/scaffold/general/agents/templates/adr-template.md +1 -0
  195. package/scaffold/general/agents/templates/execution-state.md +1 -0
  196. package/skills/knowledge-base/SKILL.md +19 -6
  197. package/skills/present/SKILL.md +153 -0
  198. package/packages/server/dist/tools/toolkit.tools.d.ts +0 -36
  199. package/packages/server/dist/tools/toolkit.tools.js +0 -20
  200. package/packages/tui/dist/App-DE_tdOhs.js +0 -2
  201. package/packages/tui/dist/CuratedPanel-sYdZAICX.js +0 -2
  202. package/packages/tui/dist/LogPanel-Ce3jMQbH.js +0 -3
  203. package/packages/tui/dist/SearchPanel-DREo6zgt.js +0 -2
  204. package/packages/tui/dist/StatusPanel-2ex8fLOO.js +0 -2
  205. package/packages/tui/dist/embedder.interface-IFCBpOlX.d.ts +0 -28
  206. package/packages/tui/dist/index-C8NmOF18.d.ts +0 -13
  207. package/packages/tui/dist/jsx-runtime-Cof-kwFn.js +0 -316
  208. package/packages/tui/dist/store.interface-CnY6SPOH.d.ts +0 -150
  209. /package/packages/tui/dist/{devtools-DUyj952l.js → devtools-DMOZMn70.js} +0 -0
@@ -44,3 +44,47 @@ evidence_map({ action: "gate", task_id: "my-task" }) → YIELD / HOLD / HARD_BL
44
44
 
45
45
  Status values: **V** (Verified + receipt), **A** (Assumed + reasoning), **U** (Unresolved).
46
46
 
47
+ ## Safety Gates (Standard+ only)
48
+
49
+ Three mandatory checks before YIELD:
50
+
51
+ | Gate | Rule | Failure |
52
+ |------|------|---------|
53
+ | **Provenance** | Every verified claim (V) has a non-empty receipt | HOLD — missing evidence trail |
54
+ | **Commitment** | Every commitment-tagged entry is verified | HOLD — unconfirmed promises |
55
+ | **Coverage** | No coverage-tagged entry is unresolved (U) | HOLD — dropped requirements |
56
+
57
+ Tag entries: `evidence_map({ action: "add", ..., safety_gate: "provenance" })`
58
+
59
+ Safety gates are evaluated automatically during `evidence_map({ action: "gate" })`. Failures produce HOLD — fixable in one retry.
60
+
61
+ ## Score-Driven Iteration
62
+
63
+ For quality-sensitive tasks, use the execute→score→fix→re-score pattern:
64
+
65
+ 1. Execute task (Build phase)
66
+ 2. Score: check({}) + test_run({}) + evidence_map({ action: "gate" })
67
+ 3. If gate != YIELD → fix issues → re-score (max 3 iterations)
68
+ 4. Track progress: stash({ key: "iteration-N", value: { score, issues } })
69
+
70
+ Agents iterate until quality threshold is met, with diminishing returns tracked via stash.
71
+
72
+ ## Example Evidence Map (Standard Tier)
73
+
74
+ ```
75
+ evidence_map({ action: "create", task_id: "add-user-api", tier: "standard" })
76
+ evidence_map({ action: "add", ..., claim: "User schema matches existing patterns", status: "V", receipt: "search → models/user.ts#L12", safety_gate: "provenance" })
77
+ evidence_map({ action: "add", ..., claim: "API route follows REST conventions", status: "V", receipt: "compact → routes/index.ts confirms RESTful pattern" })
78
+ evidence_map({ action: "add", ..., claim: "Input validation covers edge cases", status: "V", receipt: "test_run → 8/8 pass", safety_gate: "coverage" })
79
+ evidence_map({ action: "add", ..., claim: "No breaking changes to existing API", status: "V", receipt: "blast_radius → 0 affected", safety_gate: "commitment" })
80
+ evidence_map({ action: "gate", task_id: "add-user-api" }) → YIELD ✅
81
+ ```
82
+
83
+ ## Quick Start
84
+
85
+ 1. **Every task**: `forge_classify({ task: "description", files: ["path"], root_path: "." })`
86
+ 2. **Floor**: Just implement — no evidence map needed
87
+ 3. **Standard**: `evidence_map create` → add 3-8 claims during work → `evidence_map gate`
88
+ 4. **Critical**: Full 4-phase flow with comprehensive evidence
89
+ 5. **After gate**: YIELD = done, HOLD = fix + re-gate, HARD_BLOCK = escalate
90
+
@@ -2,6 +2,7 @@
2
2
 
3
3
  > Shared methodology for all Researcher variants. Each variant's definition contains only its unique identity and model assignment. **Do not duplicate.**
4
4
 
5
+
5
6
  ## Research Methodology
6
7
 
7
8
  ### Phase 1: KB Recall (BLOCKING)
@@ -35,6 +36,19 @@ Return structured findings. Always include:
35
36
 
36
37
  ---
37
38
 
39
+ ## FORGE-Aware Research
40
+
41
+ When investigating tasks that involve code changes (architecture decisions, design analysis, subsystem investigation):
42
+
43
+ 1. **Classify** — Run `forge_classify({ task, files, root_path })` to determine the complexity tier
44
+ 2. **Track findings** (Standard+) — Use `evidence_map` to record critical findings as verified claims with receipts
45
+ 3. **Flag risks** — If research reveals security, contract, or cross-boundary concerns, note the FORGE tier upgrade implications
46
+ 4. **Report tier recommendation** — Include FORGE tier and triggers in your research report
47
+
48
+ This ensures the Orchestrator and Planner have tier context when planning implementation.
49
+
50
+ ---
51
+
38
52
  ## Multi-Model Decision Context
39
53
 
40
54
  When invoked for a decision analysis, you receive a specific question. You MUST:
@@ -25,3 +25,4 @@
25
25
 
26
26
  ## Alternatives Considered
27
27
  {Other approaches evaluated and why they were rejected — keeps the "why not" alongside the "why"}
28
+
@@ -23,3 +23,4 @@
23
23
 
24
24
  | Issue | Severity | Assigned |
25
25
  |-------|----------|----------|
26
+
@@ -1,11 +1,11 @@
1
1
  ---
2
2
  name: knowledge-base
3
- description: "Use the @anvpx/kb Knowledge Base MCP server for codebase search, analysis, and persistent memory. Load this skill when using kb_search, kb_remember, kb_analyze_*, or any kb_* tool. Covers all 64 MCP tools: search (hybrid/semantic/keyword), code analysis (structure, dependencies, symbols, patterns, entry points, diagrams, blast radius), knowledge graph (auto-populated module/symbol/import graph with traversal), context management (worksets, stash, checkpoints, lanes), code manipulation (rename, codemod, eval), knowledge management (remember/read/update/forget), web access (fetch, search, http), FORGE protocol (ground, classify, evidence map, stratum cards, digest), onboarding (full codebase analysis in one call), and developer utilities (regex, encode, measure, changelog, schema-validate, snippet, env, time)."
3
+ description: "Use the @anvpx/kb Knowledge Base MCP server for codebase search, analysis, and persistent memory. Load this skill when using kb_search, kb_remember, kb_analyze_*, or any kb_* tool. Covers all 67 MCP tools: search (hybrid/semantic/keyword), code analysis (structure, dependencies, symbols, patterns, entry points, diagrams, blast radius), knowledge graph (auto-populated module/symbol/import graph with traversal), context management (worksets, stash, checkpoints, restore, lanes), code manipulation (rename, codemod, eval), knowledge management (remember/read/update/forget), web access (fetch, search, http), FORGE protocol (ground, classify, evidence map, stratum cards, digest), brainstorming (interactive ideation sessions), presentation (rich dashboards via present tool), onboarding (full codebase analysis in one call), and developer utilities (regex, encode, measure, changelog, schema-validate, snippet, env, time)."
4
4
  ---
5
5
 
6
6
  # @vpxa/kb — Knowledge Base Toolkit
7
7
 
8
- Local-first AI developer toolkit — 64 MCP tools for search, analysis, context compression, FORGE quality gates, knowledge management, code manipulation, execution, web access, and developer utilities.
8
+ Local-first AI developer toolkit — 67 MCP tools for search, analysis, context compression, FORGE quality gates, knowledge management, code manipulation, execution, web access, brainstorming, presentation, and developer utilities.
9
9
 
10
10
  ## When to Use
11
11
 
@@ -30,7 +30,7 @@ Local-first AI developer toolkit — 64 MCP tools for search, analysis, context
30
30
  core → store → embeddings → chunker → indexer → analyzers → tools → server → cli → tui
31
31
  ```
32
32
 
33
- - **MCP server**: 64 tools + 2 resources (via `@modelcontextprotocol/sdk`)
33
+ - **MCP server**: 67 tools + 2 resources (via `@modelcontextprotocol/sdk`)
34
34
  - **CLI**: 45 commands (thin dispatcher + 10 command groups)
35
35
  - **Search**: Hybrid vector + keyword + RRF fusion
36
36
  - **Embeddings**: ONNX local (mxbai-embed-large-v1, 1024 dimensions)
@@ -59,7 +59,7 @@ remember (capture insights)
59
59
  remember({ title: "Session checkpoint: <topic>", content: "<what was done, decisions made, next steps>", category: "conventions" })
60
60
  ```
61
61
 
62
- ## Tool Catalog (64 tools)
62
+ ## Tool Catalog (67 tools)
63
63
 
64
64
  ### Search & Discovery (8)
65
65
  | Tool | CLI | Purpose |
@@ -84,13 +84,14 @@ remember({ title: "Session checkpoint: <topic>", content: "<what was done, decis
84
84
  | `analyze_diagram` | `kb analyze diagram` | Generate Mermaid diagrams |
85
85
  | `blast_radius` | `kb analyze blast-radius` | Change impact analysis |
86
86
 
87
- ### Context Management (5)
87
+ ### Context Management (6)
88
88
  | Tool | CLI | Purpose |
89
89
  |------|-----|---------|
90
90
  | `compact` | `kb compact` | Compress text to relevant sections using embeddings (no LLM). Accepts `path` for server-side file read. |
91
91
  | `workset` | `kb workset` | Named file set management (save/load/add/remove) |
92
92
  | `stash` | `kb stash` | Named key-value store for session data |
93
93
  | `checkpoint` | `kb checkpoint` | Save/restore session checkpoints |
94
+ | `restore` | `kb restore` | Restore a previously saved checkpoint |
94
95
  | `parse_output` | `kb parse-output` | Parse tsc/vitest/biome/git output → structured JSON |
95
96
 
96
97
  ### Code Manipulation (4)
@@ -159,7 +160,7 @@ Lane actions: `create` (copy files to lane), `list`, `status` (modified/added/de
159
160
  |------|-----|---------|
160
161
  | `forge_ground` | — | Full Ground phase: classify tier, scope map, unknowns, constraints |
161
162
  | `forge_classify` | — | Quick tier classification (Floor/Standard/Critical) |
162
- | `evidence_map` | — | CRUD + Gate evaluation for verified/assumed/unknown claims |
163
+ | `evidence_map` | — | CRUD + Gate evaluation for verified/assumed/unknown claims. Safety gate tags (`provenance`/`commitment`/`coverage`) enable mandatory pre-YIELD checks |
163
164
  | `stratum_card` | — | Generate T1/T2 compressed context cards from files (10-100x token reduction) |
164
165
  | `digest` | — | Compress N text sources into token-budgeted summary |
165
166
 
@@ -175,6 +176,16 @@ Lane actions: `create` (copy files to lane), `list`, `status` (modified/added/de
175
176
  | `queue` | `kb queue` | Task queue for sequential agent operations (create/push/next/done/fail) |
176
177
  | `replay` | `kb replay` | View or clear the audit trail of tool invocations (action: list/clear) |
177
178
 
179
+ ### Presentation (1)
180
+ | Tool | CLI | Purpose |
181
+ |------|-----|---------|
182
+ | `present` | — | Rich dashboards, charts, tables, timelines. Use `format: "browser"` then `openBrowserPage` to display |
183
+
184
+ ### Brainstorming (1)
185
+ | Tool | CLI | Purpose |
186
+ |------|-----|---------|
187
+ | `brainstorm` | — | Interactive brainstorming and ideation sessions with structured output |
188
+
178
189
  ## Search Strategy
179
190
 
180
191
  ## CRITICAL: Use KB Tools Instead of Native IDE Tools
@@ -195,6 +206,8 @@ KB tools provide **10x richer output** than native IDE tools — with AST-analyz
195
206
  | Line counting / `wc` | `measure` | Lines, complexity, **cognitive complexity**, functions |
196
207
  | Grep for unused exports | `dead_symbols` | AST-powered export detection with regex fallback |
197
208
  | Repeated file reads | `stratum_card` | Reusable compressed context — **10-100x reduction** |
209
+ | `fetch_webpage` | `web_fetch` | Readability extract + token budget — richer output |
210
+ | Web research / browsing | `web_search` | Structured web results without browser — **unique to KB** |
198
211
 
199
212
  ### Decision Tree — How to Read Code
200
213
 
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: present
3
+ description: "Use the KB `present` tool to display rich interactive dashboards, charts, timelines, status boards, and data visualizations in the browser or in-chat. Covers all block types, chart types, actions, and composition patterns. Load this skill before calling the present tool to ensure professional output."
4
+ argument-hint: "Content to present — data, analysis results, status report, comparison"
5
+ ---
6
+
7
+ # Present Tool — Rich Interactive Dashboards
8
+
9
+ The `present` tool renders structured content as a professional dark-themed dashboard. It supports two output modes:
10
+
11
+ - **`browser`** (recommended) — Serves a themed dashboard on a local URL and returns it in the response. **You must open the URL** using the `openBrowserPage` browser tool to display it in VS Code's integrated browser. Supports interactive action buttons that block until the user clicks.
12
+ - **`html`** — Renders an embedded UIResource for MCP-UI hosts. Actions shown as numbered text choices.
13
+
14
+ **Always prefer `format: "browser"`** for rich content. Use `"html"` only when the host doesn't support browser mode.
15
+
16
+ ---
17
+
18
+ ## Browser Workflow (IMPORTANT)
19
+
20
+ When using `format: "browser"`, the `present` tool does **not** open the page automatically. Follow this workflow:
21
+
22
+ 1. Call `present` with `format: "browser"` — it returns text containing `🌐 **Dashboard opened in browser:** http://127.0.0.1:{port}`
23
+ 2. Extract the URL from the response
24
+ 3. Call `openBrowserPage` with that URL to display the dashboard in VS Code's integrated browser
25
+
26
+ ```
27
+ // Step 1: Call present
28
+ result = present({ format: "browser", title: "...", content: [...] })
29
+
30
+ // Step 2: Open in VS Code integrated browser
31
+ openBrowserPage({ url: "http://127.0.0.1:{port}" })
32
+ ```
33
+
34
+ **Note:** The HTTP server auto-closes after 5 minutes. Open the page promptly after receiving the URL.
35
+
36
+ ---
37
+
38
+ ## Content Architecture
39
+
40
+ Content is an array of **typed blocks**. Each block has `{ type, title?, value }`. All blocks compose into a single unified page — use multiple blocks for sections.
41
+
42
+ ### Core Block Types
43
+
44
+ | Type | Value Shape | Renders As |
45
+ |------|------------|------------|
46
+ | `markdown` | `string` (markdown text) | Rendered HTML with full GFM support |
47
+ | `code` | `string` (source code) | Syntax-highlighted code block |
48
+ | `mermaid` | `string` (mermaid syntax) | Interactive diagram |
49
+ | `table` | `Array<Record<string, unknown>>` | Sortable/filterable table |
50
+ | `metrics` | `Array<{ label, value }>` | KPI metric cards grid |
51
+ | `cards` | `Array<{ title, body, badge? }>` | Card grid layout |
52
+ | `tree` | `Record<string, unknown>` | Expandable tree view |
53
+ | `graph` | `{ nodes: [], edges: [] }` | Mermaid graph diagram |
54
+
55
+ ### Chart Block
56
+
57
+ ```json
58
+ {
59
+ "type": "chart",
60
+ "title": "Revenue Trend",
61
+ "value": {
62
+ "chartType": "line",
63
+ "data": [{"month": "Jan", "revenue": 1200}, {"month": "Feb", "revenue": 1800}],
64
+ "xKey": "month",
65
+ "yKeys": ["revenue"],
66
+ "showLegend": true,
67
+ "showGrid": true,
68
+ "height": 300
69
+ }
70
+ }
71
+ ```
72
+
73
+ **Chart types:** `line`, `area`, `bar`, `horizontal-bar`, `pie`, `donut`, `sparkline`, `heatmap`
74
+
75
+ ### New Block Types
76
+
77
+ | Type | Value Shape | Renders As |
78
+ |------|------------|------------|
79
+ | `timeline` | `{ items: [{ phase?, title, description?, status? }] }` | Vertical timeline with status dots (done/active/pending/error) |
80
+ | `checklist` | `{ items: [{ label, checked?, note? }] }` | Interactive checklist with checkmarks |
81
+ | `comparison` | `{ columns: [{ title, items: [string] }] }` | Side-by-side comparison grid |
82
+ | `status-board` | `{ items: [{ label, status, detail? }] }` | Status indicator rows (success/warning/error/info/pending) |
83
+ | `prompt` | `{ question, context?, placeholder? }` | Highlighted question/prompt block |
84
+ | `progress` | `{ items: [{ label, value, max? }] }` | Progress bars with percentages |
85
+
86
+ ---
87
+
88
+ ## Actions
89
+
90
+ Actions are interactive buttons/selects. In `browser` mode, they render as clickable elements and the tool blocks until the user clicks, returning the selection.
91
+
92
+ ```json
93
+ {
94
+ "actions": [
95
+ { "type": "button", "id": "approve", "label": "Approve", "variant": "primary" },
96
+ { "type": "button", "id": "reject", "label": "Reject", "variant": "danger" },
97
+ { "type": "select", "id": "priority", "label": "Priority", "options": ["Low", "Medium", "High"] }
98
+ ]
99
+ }
100
+ ```
101
+
102
+ **Variants:** `primary` (indigo), `danger` (red), `default` (neutral)
103
+
104
+ ---
105
+
106
+ ## Composition Pattern
107
+
108
+ Compose a full dashboard by combining multiple blocks in the `content` array:
109
+
110
+ ```json
111
+ {
112
+ "format": "browser",
113
+ "title": "Sprint Review",
114
+ "content": [
115
+ { "type": "metrics", "title": "Key Metrics", "value": [...] },
116
+ { "type": "chart", "title": "Velocity", "value": { "chartType": "area", ... } },
117
+ { "type": "timeline", "title": "Milestones", "value": { "items": [...] } },
118
+ { "type": "status-board", "title": "Service Health", "value": { "items": [...] } },
119
+ { "type": "table", "title": "Tasks", "value": [...] },
120
+ { "type": "markdown", "value": "## Notes\n\nAdditional context..." }
121
+ ],
122
+ "actions": [
123
+ { "type": "button", "id": "next-sprint", "label": "Plan Next Sprint", "variant": "primary" }
124
+ ]
125
+ }
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Design System
131
+
132
+ The dashboard uses a professional dark theme:
133
+ - **Font:** Plus Jakarta Sans (body), JetBrains Mono (code)
134
+ - **Colors:** Deep navy background (`#182030`), indigo primary (`#818cf8`), no gradients
135
+ - **12 chart colors** for multi-series data
136
+ - **Status colors:** green (success), amber (warning), red (error), sky (info)
137
+ - Clean borders, subtle hover states, no visual noise
138
+
139
+ ---
140
+
141
+ ## Best Practices
142
+
143
+ 1. **Use `browser` format** for data-rich content — charts, tables, dashboards
144
+ 2. **Combine block types** — metrics + charts + tables in one page
145
+ 3. **Add titles** to every block for clear section headings
146
+ 4. **Use actions** when you need user decisions — the tool returns the selection
147
+ 5. **Keep markdown blocks** for narrative context between data sections
148
+ 6. **Chart tips:**
149
+ - Use `area` for trends over time
150
+ - Use `bar` for comparisons between categories
151
+ - Use `donut` for proportions/distributions
152
+ - Use `sparkline` inline with metrics for mini trends
153
+ 7. **Table auto-features:** Tables with 5+ rows get automatic search/filter. Columns are sortable by click.
@@ -1,36 +0,0 @@
1
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
- import { IEmbedder } from "@kb/embeddings";
3
- import { IGraphStore, IKnowledgeStore } from "@kb/store";
4
- import { FileCache } from "@kb/tools";
5
-
6
- //#region packages/server/src/tools/toolkit.tools.d.ts
7
- declare function registerCompactTool(server: McpServer, embedder: IEmbedder, cache: FileCache): void;
8
- declare function registerScopeMapTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
9
- declare function registerFindTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
10
- declare function registerParseOutputTool(server: McpServer): void;
11
- declare function registerWorksetTool(server: McpServer): void;
12
- declare function registerCheckTool(server: McpServer): void;
13
- declare function registerBatchTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
14
- declare function registerSymbolTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore, graphStore?: IGraphStore): void;
15
- declare function registerEvalTool(server: McpServer): void;
16
- declare function registerTestRunTool(server: McpServer): void;
17
- declare function registerStashTool(server: McpServer): void;
18
- declare function registerGitContextTool(server: McpServer): void;
19
- declare function registerDiffParseTool(server: McpServer): void;
20
- declare function registerRenameTool(server: McpServer): void;
21
- declare function registerCodemodTool(server: McpServer): void;
22
- declare function registerFileSummaryTool(server: McpServer, cache: FileCache): void;
23
- declare function registerCheckpointTool(server: McpServer): void;
24
- declare function registerDataTransformTool(server: McpServer): void;
25
- declare function registerTraceTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
26
- declare function registerProcessTool(server: McpServer): void;
27
- declare function registerWatchTool(server: McpServer): void;
28
- declare function registerDeadSymbolsTool(server: McpServer, embedder: IEmbedder, store: IKnowledgeStore): void;
29
- declare function registerDelegateTool(server: McpServer): void;
30
- declare function registerLaneTool(server: McpServer): void;
31
- declare function registerHealthTool(server: McpServer): void;
32
- declare function registerQueueTool(server: McpServer): void;
33
- declare function registerWebFetchTool(server: McpServer): void;
34
- declare function registerGuideTool(server: McpServer): void;
35
- //#endregion
36
- export { registerBatchTool, registerCheckTool, registerCheckpointTool, registerCodemodTool, registerCompactTool, registerDataTransformTool, registerDeadSymbolsTool, registerDelegateTool, registerDiffParseTool, registerEvalTool, registerFileSummaryTool, registerFindTool, registerGitContextTool, registerGuideTool, registerHealthTool, registerLaneTool, registerParseOutputTool, registerProcessTool, registerQueueTool, registerRenameTool, registerScopeMapTool, registerStashTool, registerSymbolTool, registerTestRunTool, registerTraceTool, registerWatchTool, registerWebFetchTool, registerWorksetTool };
@@ -1,20 +0,0 @@
1
- import{getToolMeta as e}from"../tool-metadata.js";import{fanOutSearch as t,openWorkspaceStores as n,resolveWorkspaces as r}from"../cross-workspace.js";import{HealthOutputSchema as i}from"../output-schemas.js";import{z as a}from"zod";import{CONTENT_TYPES as o,computePartitionKey as s,createLogger as c,serializeError as l}from"../../../core/dist/index.js";import{addToWorkset as u,batch as d,check as f,checkpointLatest as p,checkpointList as m,checkpointLoad as h,checkpointSave as g,codemod as _,compact as ee,dataTransform as te,delegate as ne,delegateListModels as re,deleteWorkset as ie,diffParse as ae,evaluate as oe,fileSummary as v,find as y,findDeadSymbols as b,findExamples as x,getWorkset as S,gitContext as C,guide as w,health as T,laneCreate as E,laneDiff as D,laneDiscard as O,laneList as k,laneMerge as A,laneStatus as j,listWorksets as M,parseOutput as N,processList as P,processLogs as F,processStart as I,processStatus as L,processStop as R,queueClear as z,queueCreate as B,queueDelete as V,queueDone as H,queueFail as U,queueGet as W,queueList as G,queueNext as K,queuePush as q,removeFromWorkset as se,rename as ce,saveWorkset as le,scopeMap as ue,stashClear as de,stashDelete as fe,stashGet as pe,stashList as me,stashSet as he,summarizeCheckResult as ge,symbol as J,testRun as _e,trace as ve,truncateToTokenBudget as Y,watchList as ye,watchStart as be,watchStop as xe,webFetch as Se}from"../../../tools/dist/index.js";const X=c(`tools`);function Ce(t,n,r){let i=e(`compact`);t.registerTool(`compact`,{title:i.title,description:"Compress text to relevant sections using embedding similarity (no LLM). Provide either `text` or `path` (server reads the file — saves a round-trip). Segments by paragraph/sentence/line.",inputSchema:{text:a.string().optional().describe(`The text to compress (provide this OR path, not both)`),path:a.string().optional().describe(`File path to read server-side — avoids read_file round-trip + token doubling (provide this OR text)`),query:a.string().describe(`Focus query — what are you trying to understand?`),max_chars:a.number().min(100).max(5e4).default(3e3).describe(`Target output size in characters`),segmentation:a.enum([`paragraph`,`sentence`,`line`]).default(`paragraph`).describe(`How to split the text for scoring`)},annotations:i.annotations},async({text:e,path:t,query:i,max_chars:a,segmentation:o})=>{try{if(!e&&!t)return{content:[{type:`text`,text:`Error: Either "text" or "path" must be provided.`}],isError:!0};let s=await ee(n,{text:e,path:t,query:i,maxChars:a,segmentation:o,cache:r});return{content:[{type:`text`,text:[`Compressed ${s.originalChars} → ${s.compressedChars} chars (${(s.ratio*100).toFixed(0)}%)`,`Kept ${s.segmentsKept}/${s.segmentsTotal} segments`,``,s.text].join(`
2
- `)}]}}catch(e){return X.error(`Compact failed`,l(e)),{content:[{type:`text`,text:`Compact failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function we(t,n,r){let i=e(`scope_map`);t.registerTool(`scope_map`,{title:i.title,description:`Generate a task-scoped reading plan. Given a task description, identifies which files and sections are relevant, with estimated token counts and suggested reading order.`,inputSchema:{task:a.string().describe(`Description of the task to scope`),max_files:a.number().min(1).max(50).default(15).describe(`Maximum files to include`),content_type:a.enum(o).optional().describe(`Filter by content type`),max_tokens:a.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`)},annotations:i.annotations},async({task:e,max_files:t,content_type:i,max_tokens:a})=>{try{let o=await ue(n,r,{task:e,maxFiles:t,contentType:i}),s=[`## Scope Map: ${e}`,`Total estimated tokens: ~${o.totalEstimatedTokens}`,``,`### Files (by relevance)`,...o.files.map((e,t)=>`${t+1}. **${e.path}** (~${e.estimatedTokens} tokens, ${(e.relevance*100).toFixed(0)}% relevant)\n ${e.reason}\n Focus: ${e.focusRanges.map(e=>`L${e.start}-${e.end}`).join(`, `)}`),``,`### Suggested Reading Order`,...o.readingOrder.map((e,t)=>`${t+1}. ${e}`),``,`### Suggested Compact Calls`,`_Estimated compressed total: ~${Math.ceil(o.totalEstimatedTokens/5)} tokens_`,...o.compactCommands.map((e,t)=>`${t+1}. ${e}`)].join(`
3
- `)+"\n\n---\n_Next: Use `search` to dive into specific files, or `compact` to compress file contents for context._";return{content:[{type:`text`,text:a?Y(s,a):s}]}}catch(e){return X.error(`Scope map failed`,l(e)),{content:[{type:`text`,text:`Scope map failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Te(i,c,u){let d=e(`find`);i.registerTool(`find`,{title:d.title,description:`Federated search across vector similarity, keyword (FTS), file glob, and regex pattern. Combines strategies, deduplicates, and returns unified results. Use mode "examples" to find real usage examples of a symbol or pattern.`,inputSchema:{query:a.string().optional().describe(`Semantic/keyword search query (required for mode "examples")`),glob:a.string().optional().describe(`File glob pattern (search mode only)`),pattern:a.string().optional().describe(`Regex pattern to match in content (search mode only)`),limit:a.number().min(1).max(50).default(10).describe(`Max results`),content_type:a.enum(o).optional().describe(`Filter by content type`),mode:a.enum([`search`,`examples`]).default(`search`).describe(`Mode: "search" (default) for federated search, "examples" to find usage examples of a symbol/pattern`),max_tokens:a.number().min(100).max(5e4).optional().describe(`Maximum token budget for the response. When set, output is truncated to fit.`),workspaces:a.array(a.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all. User-level mode only.`)},annotations:d.annotations},async({query:e,glob:i,pattern:a,limit:o,content_type:d,mode:f,max_tokens:p,workspaces:m})=>{try{if(f===`examples`){if(!e)return{content:[{type:`text`,text:`Error: "query" is required for mode "examples".`}],isError:!0};let t=await x(c,u,{query:e,limit:o,contentType:d}),n=JSON.stringify(t);return{content:[{type:`text`,text:p?Y(n,p):n}]}}let l=await y(c,u,{query:e,glob:i,pattern:a,limit:o,contentType:d}),h=``;if(m&&m.length>0&&e){let i=r(m,s(process.cwd()));if(i.length>0){let{stores:r,closeAll:a}=await n(i);try{let n=await t(r,await c.embedQuery(e),{limit:o,contentType:d});for(let e of n)l.results.push({path:`[${e.workspace}] ${e.record.sourcePath}`,score:e.score,source:`cross-workspace`,lineRange:e.record.startLine?{start:e.record.startLine,end:e.record.endLine}:void 0,preview:e.record.content.slice(0,200)});l.results.sort((e,t)=>t.score-e.score),l.results=l.results.slice(0,o),l.totalFound=l.results.length,h=` + ${i.length} workspace(s)`}finally{await a()}}}if(l.results.length===0)return{content:[{type:`text`,text:`No results found.`}]};let g=[`Found ${l.totalFound} results via ${l.strategies.join(` + `)}${h}`,``,...l.results.map(e=>{let t=e.lineRange?`:${e.lineRange.start}-${e.lineRange.end}`:``,n=e.preview?`\n ${e.preview.slice(0,100)}...`:``;return`- [${e.source}] ${e.path}${t} (${(e.score*100).toFixed(0)}%)${n}`})];return{content:[{type:`text`,text:p?Y(g.join(`
4
- `),p):g.join(`
5
- `)}]}}catch(e){return X.error(`Find failed`,l(e)),{content:[{type:`text`,text:`Find failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ee(t){let n=e(`parse_output`);t.registerTool(`parse_output`,{title:n.title,description:`Parse structured data from build tool output. Supports tsc, vitest, biome, and git status. Auto-detects the tool or specify explicitly.`,inputSchema:{output:a.string().max(5e5).describe(`Raw output text from a build tool`),tool:a.enum([`tsc`,`vitest`,`biome`,`git-status`]).optional().describe(`Tool to parse as (auto-detects if omitted)`)},annotations:n.annotations},async({output:e,tool:t})=>{try{let n=N(e.replace(/\\n/g,`
6
- `).replace(/\\t/g,` `),t);return{content:[{type:`text`,text:JSON.stringify(n)}]}}catch(e){return X.error(`Parse failed`,l(e)),{content:[{type:`text`,text:`Parse failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function De(t){let n=e(`workset`);t.registerTool(`workset`,{title:n.title,description:`Manage named file sets (worksets). Save, load, list, add/remove files. Worksets persist across sessions in .kb-state/worksets.json.`,inputSchema:{action:a.enum([`save`,`get`,`list`,`delete`,`add`,`remove`]).describe(`Operation to perform`),name:a.string().optional().describe(`Workset name (required for all except list)`),files:a.array(a.string()).optional().describe(`File paths (required for save, add, remove)`),description:a.string().optional().describe(`Description (for save)`)},annotations:n.annotations},async({action:e,name:t,files:n,description:r})=>{try{switch(e){case`save`:{if(!t||!n)throw Error(`name and files required for save`);let e=le(t,n,{description:r});return{content:[{type:`text`,text:`Saved workset "${e.name}" with ${e.files.length} files.`}]}}case`get`:{if(!t)throw Error(`name required for get`);let e=S(t);return e?{content:[{type:`text`,text:JSON.stringify(e)}]}:{content:[{type:`text`,text:`Workset "${t}" not found.`}]}}case`list`:{let e=M();return e.length===0?{content:[{type:`text`,text:`No worksets.`}]}:{content:[{type:`text`,text:e.map(e=>`- **${e.name}** (${e.files.length} files) — ${e.description??`no description`}`).join(`
7
- `)}]}}case`delete`:if(!t)throw Error(`name required for delete`);return{content:[{type:`text`,text:ie(t)?`Deleted workset "${t}".`:`Workset "${t}" not found.`}]};case`add`:{if(!t||!n)throw Error(`name and files required for add`);let e=u(t,n);return{content:[{type:`text`,text:`Added to workset "${e.name}": now ${e.files.length} files.`}]}}case`remove`:{if(!t||!n)throw Error(`name and files required for remove`);let e=se(t,n);return e?{content:[{type:`text`,text:`Removed from workset "${e.name}": now ${e.files.length} files.`}]}:{content:[{type:`text`,text:`Workset "${t}" not found.`}]}}}}catch(e){return X.error(`Workset operation failed`,l(e)),{content:[{type:`text`,text:`Workset operation failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Oe(t){let n=e(`check`);t.registerTool(`check`,{title:n.title,description:`Run incremental typecheck (tsc) and lint (biome) on the project or specific files. Returns structured error and warning lists. Default detail level is "summary" (~300 tokens).`,inputSchema:{files:a.array(a.string()).optional().describe(`Specific files to check (if omitted, checks all)`),cwd:a.string().optional().describe(`Working directory`),skip_types:a.boolean().default(!1).describe(`Skip TypeScript typecheck`),skip_lint:a.boolean().default(!1).describe(`Skip Biome lint`),detail:a.enum([`summary`,`errors`,`full`]).default(`summary`).describe(`Output detail level: summary (default, ~300 tokens — pass/fail + counts + top errors), errors (parsed error objects), full (includes raw terminal output)`)},annotations:n.annotations},async({files:e,cwd:t,skip_types:n,skip_lint:r,detail:i})=>{try{let a=await f({files:e,cwd:t,skipTypes:n,skipLint:r,detail:i===`summary`?`errors`:i});if(i===`summary`){let e=ge(a),t=[];if(a.passed)t.push({tool:`test_run`,reason:`Types and lint clean — run tests next`});else{let e=a.tsc.errors[0]?.file??a.biome.errors[0]?.file;e&&t.push({tool:`symbol`,reason:`Resolve failing symbol in ${e}`,suggested_args:{name:e}}),t.push({tool:`check`,reason:`Re-check after fixing errors`,suggested_args:{detail:`errors`}})}return{content:[{type:`text`,text:JSON.stringify({...e,_next:t})}]}}return{content:[{type:`text`,text:JSON.stringify(a)}]}}catch(e){return X.error(`Check failed`,l(e)),{content:[{type:`text`,text:`Check failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function ke(t,n,r){let i=e(`batch`);t.registerTool(`batch`,{title:i.title,description:`Execute multiple built-in operations in parallel with concurrency control. Supported operation types: search, find, and check.`,inputSchema:{operations:a.array(a.object({id:a.string().describe(`Unique ID for this operation`),type:a.enum([`search`,`find`,`check`]).describe(`Built-in operation type`),args:a.record(a.string(),a.unknown()).describe(`Arguments for the operation`)})).min(1).max(100).describe(`Operations to execute`),concurrency:a.number().min(1).max(20).default(4).describe(`Max concurrent operations`)},annotations:i.annotations},async({operations:e,concurrency:t})=>{try{let i=await d(e,async e=>Ze(e,n,r),{concurrency:t});return{content:[{type:`text`,text:JSON.stringify(i)}]}}catch(e){return X.error(`Batch failed`,l(e)),{content:[{type:`text`,text:`Batch failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ae(t,i,o,c){let u=e(`symbol`);t.registerTool(`symbol`,{title:u.title,description:`Resolve a symbol: find where it is defined, who imports it, and where it is referenced. Works on TypeScript and JavaScript codebases.`,inputSchema:{name:a.string().describe(`Symbol name to look up (function, class, type, etc.)`),limit:a.number().min(1).max(50).default(20).describe(`Max results per category`),workspaces:a.array(a.string()).optional().describe(`Cross-workspace search: partition names or folder basenames to include. Use ["*"] for all. User-level mode only.`)},annotations:u.annotations},async({name:e,limit:t,workspaces:a})=>{try{let l=await J(i,o,{name:e,limit:t,graphStore:c});if(a&&a.length>0){let o=r(a,s(process.cwd()));if(o.length>0){let{stores:r,closeAll:a}=await n(o);try{for(let[n,a]of r){let r=await J(i,a,{name:e,limit:t});r.definedIn&&!l.definedIn&&(l.definedIn={...r.definedIn,path:`[${n}] ${r.definedIn.path}`});for(let e of r.referencedIn)l.referencedIn.push({...e,path:`[${n}] ${e.path}`});if(r.importedBy){l.importedBy=l.importedBy??[];for(let e of r.importedBy)l.importedBy.push({...e,path:`[${n}] ${e.path}`})}}}finally{await a()}}}return{content:[{type:`text`,text:et(l)}]}}catch(e){return X.error(`Symbol lookup failed`,l(e)),{content:[{type:`text`,text:`Symbol lookup failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function je(t){let n=e(`eval`);t.registerTool(`eval`,{title:n.title,description:`Execute a JavaScript or TypeScript snippet in a constrained VM sandbox with a timeout. Captures console output and returned values.`,inputSchema:{code:a.string().max(1e5).describe(`Code snippet to execute`),lang:a.enum([`js`,`ts`]).default(`js`).optional().describe(`Language mode: js executes directly, ts strips common type syntax first`),timeout:a.number().min(1).max(6e4).default(5e3).optional().describe(`Execution timeout in milliseconds`)},annotations:n.annotations},async({code:e,lang:t,timeout:n})=>{try{let r=oe({code:e,lang:t,timeout:n});return r.success?{content:[{type:`text`,text:`Eval succeeded in ${r.durationMs}ms\n\n${r.output}`}]}:{content:[{type:`text`,text:`Eval failed in ${r.durationMs}ms: ${r.error??`Unknown error`}`}],isError:!0}}catch(e){return X.error(`Eval failed`,l(e)),{content:[{type:`text`,text:`Eval failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Me(t){let n=e(`test_run`);t.registerTool(`test_run`,{title:n.title,description:`Run Vitest for the current project or a subset of files, then return a structured summary of passing and failing tests.`,inputSchema:{files:a.array(a.string()).optional().describe(`Specific test files or patterns to run`),grep:a.string().optional().describe(`Only run tests whose names match this pattern`),cwd:a.string().optional().describe(`Working directory for the test run`)},annotations:n.annotations},async({files:e,grep:t,cwd:n})=>{try{let r=await _e({files:e,grep:t,cwd:n});return{content:[{type:`text`,text:tt(r)}],isError:!r.passed}}catch(e){return X.error(`Test run failed`,l(e)),{content:[{type:`text`,text:`Test run failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ne(t){let n=e(`stash`);t.registerTool(`stash`,{title:n.title,description:`Persist and retrieve named values in .kb-state/stash.json for intermediate results between tool calls.`,inputSchema:{action:a.enum([`set`,`get`,`list`,`delete`,`clear`]).describe(`Operation to perform on the stash`),key:a.string().optional().describe(`Entry key for set/get/delete operations`),value:a.string().optional().describe(`String or JSON value for set operations`)},annotations:n.annotations},async({action:e,key:t,value:n})=>{try{switch(e){case`set`:{if(!t)throw Error(`key required for set`);let e=he(t,at(n??``));return{content:[{type:`text`,text:`Stored stash entry "${e.key}" (${e.type}) at ${e.storedAt}.`}]}}case`get`:{if(!t)throw Error(`key required for get`);let e=pe(t);return{content:[{type:`text`,text:e?JSON.stringify(e):`Stash entry "${t}" not found.`}]}}case`list`:{let e=me();return{content:[{type:`text`,text:e.length===0?`Stash is empty.`:e.map(e=>`- ${e.key} (${e.type}) — ${e.storedAt}`).join(`
8
- `)}]}}case`delete`:if(!t)throw Error(`key required for delete`);return{content:[{type:`text`,text:fe(t)?`Deleted stash entry "${t}".`:`Stash entry "${t}" not found.`}]};case`clear`:{let e=de();return{content:[{type:`text`,text:`Cleared ${e} stash entr${e===1?`y`:`ies`}.`}]}}}}catch(e){return X.error(`Stash operation failed`,l(e)),{content:[{type:`text`,text:`Stash operation failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Pe(t){let n=e(`git_context`);t.registerTool(`git_context`,{title:n.title,description:`Summarize the current Git branch, working tree state, recent commits, and optional diff statistics for the repository.`,inputSchema:{cwd:a.string().optional().describe(`Repository root or working directory`),commit_count:a.number().min(1).max(50).default(5).optional().describe(`How many recent commits to include`),include_diff:a.boolean().default(!1).optional().describe(`Include diff stat for working tree changes`)},annotations:n.annotations},async({cwd:e,commit_count:t,include_diff:n})=>{try{return{content:[{type:`text`,text:nt(await C({cwd:e,commitCount:t,includeDiff:n}))}]}}catch(e){return X.error(`Git context failed`,l(e)),{content:[{type:`text`,text:`Git context failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Fe(t){let n=e(`diff_parse`);t.registerTool(`diff_parse`,{title:n.title,description:`Parse raw unified diff text into file-level and hunk-level structural changes.`,inputSchema:{diff:a.string().max(1e6).describe(`Raw unified diff text`)},annotations:n.annotations},async({diff:e})=>{try{return{content:[{type:`text`,text:rt(ae({diff:e.replace(/\\n/g,`
9
- `).replace(/\\t/g,` `)}))}]}}catch(e){return X.error(`Diff parse failed`,l(e)),{content:[{type:`text`,text:`Diff parse failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ie(t){let n=e(`rename`);t.registerTool(`rename`,{title:n.title,description:`Rename a symbol across files using whole-word regex matching for exports, imports, and general usage references.`,inputSchema:{old_name:a.string().describe(`Existing symbol name to replace`),new_name:a.string().describe(`New symbol name to use`),root_path:a.string().describe(`Root directory to search within`),extensions:a.array(a.string()).optional().describe(`Optional file extensions to include, such as .ts,.tsx,.js,.jsx`),dry_run:a.boolean().default(!0).describe(`Preview changes without writing files`)},annotations:n.annotations},async({old_name:e,new_name:t,root_path:n,extensions:r,dry_run:i})=>{try{let a=await ce({oldName:e,newName:t,rootPath:n,extensions:r,dryRun:i});return{content:[{type:`text`,text:JSON.stringify(a)}]}}catch(e){return X.error(`Rename failed`,l(e)),{content:[{type:`text`,text:`Rename failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Le(t){let n=e(`codemod`);t.registerTool(`codemod`,{title:n.title,description:`Apply regex-based codemod rules across files and return structured before/after changes for each affected line.`,inputSchema:{root_path:a.string().describe(`Root directory to transform within`),rules:a.array(a.object({description:a.string().describe(`What the codemod rule does`),pattern:a.string().describe(`Regex pattern in string form`),replacement:a.string().describe(`Replacement string with optional capture groups`)})).min(1).describe(`Codemod rules to apply`),dry_run:a.boolean().default(!0).describe(`Preview changes without writing files`)},annotations:n.annotations},async({root_path:e,rules:t,dry_run:n})=>{try{let r=await _({rootPath:e,rules:t,dryRun:n});return{content:[{type:`text`,text:JSON.stringify(r)}]}}catch(e){return X.error(`Codemod failed`,l(e)),{content:[{type:`text`,text:`Codemod failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Re(t,n){let r=e(`file_summary`);t.registerTool(`file_summary`,{title:r.title,description:`Create a concise structural summary of a source file: imports, exports, functions, classes, interfaces, and types.`,inputSchema:{path:a.string().describe(`Absolute path to the file to summarize`)},annotations:r.annotations},async({path:e})=>{try{return{content:[{type:`text`,text:it(await v({path:e,content:(await n.get(e)).content}))}]}}catch(e){return X.error(`File summary failed`,l(e)),{content:[{type:`text`,text:`File summary failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function ze(t){let n=e(`checkpoint`);t.registerTool(`checkpoint`,{title:n.title,description:`Save and restore lightweight session checkpoints in .kb-state/checkpoints for cross-session continuity.`,inputSchema:{action:a.enum([`save`,`load`,`list`,`latest`]).describe(`Checkpoint action to perform`),label:a.string().optional().describe(`Checkpoint label for save, or checkpoint id for load`),data:a.string().max(5e5).optional().describe(`JSON object string for save actions`),notes:a.string().max(1e4).optional().describe(`Optional notes for save actions`)},annotations:n.annotations},async({action:e,label:t,data:n,notes:r})=>{try{switch(e){case`save`:if(!t)throw Error(`label required for save`);return{content:[{type:`text`,text:Q(g(t,ot(n),{notes:r}))}]};case`load`:{if(!t)throw Error(`label required for load`);let e=h(t);return{content:[{type:`text`,text:e?Q(e):`Checkpoint "${t}" not found.`}]}}case`list`:{let e=m();return{content:[{type:`text`,text:e.length===0?`No checkpoints saved.`:e.map(e=>`- ${e.id} — ${e.label} (${e.createdAt})`).join(`
10
- `)}]}}case`latest`:{let e=p();return{content:[{type:`text`,text:e?Q(e):`No checkpoints saved.`}]}}}}catch(e){return X.error(`Checkpoint failed`,l(e)),{content:[{type:`text`,text:`Checkpoint failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Be(t){let n=e(`data_transform`);t.registerTool(`data_transform`,{title:n.title,description:`Apply small jq-like transforms to JSON input for filtering, projection, grouping, and path extraction.`,inputSchema:{input:a.string().max(5e5).describe(`Input JSON string`),expression:a.string().max(1e4).describe(`Transform expression to apply`)},annotations:n.annotations},async({input:e,expression:t})=>{try{return{content:[{type:`text`,text:te({input:e,expression:t}).outputString}]}}catch(e){return X.error(`Data transform failed`,l(e)),{content:[{type:`text`,text:`Data transform failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ve(t,n,r){let i=e(`trace`);t.registerTool(`trace`,{title:i.title,description:`Trace data flow through a codebase by following imports, call sites, and references from a starting symbol or file location.`,inputSchema:{start:a.string().describe(`Starting point — symbol name or file:line reference`),direction:a.enum([`forward`,`backward`,`both`]).describe(`Which direction to trace relationships`),max_depth:a.number().min(1).max(10).default(3).optional().describe(`Maximum trace depth`)},annotations:i.annotations},async({start:e,direction:t,max_depth:i})=>{try{let a=await ve(n,r,{start:e,direction:t,maxDepth:i}),o=[`## Trace: ${a.start}`,`Direction: ${a.direction} | Depth: ${a.depth}`,``];if(a.nodes.length===0)o.push(`No connections found.`);else{let e=a.nodes.filter(e=>e.relationship===`calls`),t=a.nodes.filter(e=>e.relationship===`called-by`),n=a.nodes.filter(e=>e.relationship===`imports`),r=a.nodes.filter(e=>e.relationship===`imported-by`),i=a.nodes.filter(e=>e.relationship===`references`);if(e.length>0){o.push(`### Calls (${e.length})`);for(let t of e){let e=t.scope?` (from ${t.scope}())`:``;o.push(`- ${t.symbol}() — ${t.path}:${t.line}${e}`)}o.push(``)}if(t.length>0){o.push(`### Called by (${t.length})`);for(let e of t){let t=e.scope?` in ${e.scope}()`:``;o.push(`- ${e.symbol}()${t} — ${e.path}:${e.line}`)}o.push(``)}if(n.length>0){o.push(`### Imports (${n.length})`);for(let e of n)o.push(`- ${e.symbol} — ${e.path}:${e.line}`);o.push(``)}if(r.length>0){o.push(`### Imported by (${r.length})`);for(let e of r)o.push(`- ${e.path}:${e.line}`);o.push(``)}if(i.length>0){o.push(`### References (${i.length})`);for(let e of i)o.push(`- ${e.path}:${e.line}`);o.push(``)}}return o.push(`---`,"_Next: `symbol` for definition details | `compact` to read a referenced file | `blast_radius` for impact analysis_"),{content:[{type:`text`,text:o.join(`
11
- `)}]}}catch(e){return X.error(`Trace failed`,l(e)),{content:[{type:`text`,text:`Trace failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function He(t){let n=e(`process`);t.registerTool(`process`,{title:n.title,description:`Start, stop, inspect, list, and tail logs for in-memory managed child processes.`,inputSchema:{action:a.enum([`start`,`stop`,`status`,`list`,`logs`]).describe(`Process action to perform`),id:a.string().optional().describe(`Managed process ID`),command:a.string().optional().describe(`Executable to start`),args:a.array(a.string()).optional().describe(`Arguments for start actions`),tail:a.number().min(1).max(500).optional().describe(`Log lines to return for logs actions`)},annotations:n.annotations},async({action:e,id:t,command:n,args:r,tail:i})=>{try{switch(e){case`start`:if(!t||!n)throw Error(`id and command are required for start`);return{content:[{type:`text`,text:JSON.stringify(I(t,n,r??[]))}]};case`stop`:if(!t)throw Error(`id is required for stop`);return{content:[{type:`text`,text:JSON.stringify(R(t)??null)}]};case`status`:if(!t)throw Error(`id is required for status`);return{content:[{type:`text`,text:JSON.stringify(L(t)??null)}]};case`list`:return{content:[{type:`text`,text:JSON.stringify(P())}]};case`logs`:if(!t)throw Error(`id is required for logs`);return{content:[{type:`text`,text:JSON.stringify(F(t,i))}]}}}catch(e){return X.error(`Process action failed`,l(e)),{content:[{type:`text`,text:`Process action failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ue(t){let n=e(`watch`);t.registerTool(`watch`,{title:n.title,description:`Start, stop, and list in-memory filesystem watchers for a directory.`,inputSchema:{action:a.enum([`start`,`stop`,`list`]).describe(`Watch action to perform`),path:a.string().optional().describe(`Directory path to watch for start actions`),id:a.string().optional().describe(`Watcher ID for stop actions`)},annotations:n.annotations},async({action:e,path:t,id:n})=>{try{switch(e){case`start`:if(!t)throw Error(`path is required for start`);return{content:[{type:`text`,text:JSON.stringify(be({path:t}))}]};case`stop`:if(!n)throw Error(`id is required for stop`);return{content:[{type:`text`,text:JSON.stringify({stopped:xe(n)})}]};case`list`:return{content:[{type:`text`,text:JSON.stringify(ye())}]}}}catch(e){return X.error(`Watch action failed`,l(e)),{content:[{type:`text`,text:`Watch action failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function We(t,n,r){let i=e(`dead_symbols`);t.registerTool(`dead_symbols`,{title:i.title,description:`Find exported symbols that appear to be unused because they are never imported or re-exported.`,inputSchema:{path:a.string().optional().describe(`Root path to scope the search (default: cwd)`),limit:a.number().min(1).max(500).default(100).optional().describe(`Maximum exported symbols to scan`)},annotations:i.annotations},async({path:e,limit:t})=>{try{let i=await b(n,r,{rootPath:e,limit:t}),a=[`## Dead Symbol Analysis`,``,`**Exports scanned:** ${i.totalExports}`,`**Dead in source:** ${i.totalDeadSource} (actionable)`,`**Dead in docs:** ${i.totalDeadDocs} (informational — code samples in .md files)`,``];if(i.deadInSource.length>0){a.push(`### Dead in Source (actionable)`);for(let e of i.deadInSource)a.push(`- \`${e.name}\` (${e.kind}) — ${e.path}:${e.line}`);a.push(``)}if(i.deadInDocs.length>0){a.push(`### Dead in Docs (informational)`),a.push(`_${i.totalDeadDocs} symbol(s) found only in documentation code samples — not actionable dead code._`);for(let e of i.deadInDocs.slice(0,5))a.push(`- \`${e.name}\` — ${e.path}:${e.line}`);i.deadInDocs.length>5&&a.push(`- _... ${i.deadInDocs.length-5} more omitted_`)}return i.totalDeadSource>0?a.push(``,`---`,`_Next: \`codemod\` to remove ${i.totalDeadSource} unused exports | \`symbol\` to verify usage before removing_`):a.push(``,`---`,"_Next: `check` — no dead symbols found, validate types and lint_"),{content:[{type:`text`,text:a.join(`
12
- `)}]}}catch(e){return X.error(`Dead symbol scan failed`,l(e)),{content:[{type:`text`,text:`Dead symbol scan failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ge(t){let n=e(`delegate`);t.registerTool(`delegate`,{title:n.title,description:`Delegate a subtask to a local Ollama model. Use for summarization, classification, naming, or any task that can offload work from the host agent. Fails fast if Ollama is not running.`,inputSchema:{prompt:a.string().max(2e5).describe(`The task or question to send to the local model`),model:a.string().optional().describe(`Ollama model name (default: first available model)`),system:a.string().optional().describe(`System prompt for the model`),context:a.string().max(5e5).optional().describe(`Context text to include before the prompt (e.g. file contents)`),temperature:a.number().min(0).max(2).default(.3).optional().describe(`Sampling temperature (0=deterministic, default 0.3)`),timeout:a.number().min(1e3).max(6e5).default(12e4).optional().describe(`Timeout in milliseconds (default 120000)`),action:a.enum([`generate`,`list_models`]).default(`generate`).optional().describe(`Action: generate a response or list available models`)},annotations:n.annotations},async({prompt:e,model:t,system:n,context:r,temperature:i,timeout:a,action:o})=>{try{if(o===`list_models`){let e=await re();return{content:[{type:`text`,text:JSON.stringify({models:e,count:e.length,_Next:`Use delegate with a model name`},null,2)}]}}let s=await ne({prompt:e,model:t,system:n,context:r,temperature:i,timeout:a});return s.error?{content:[{type:`text`,text:JSON.stringify({error:s.error,model:s.model,durationMs:s.durationMs},null,2)}],isError:!0}:{content:[{type:`text`,text:JSON.stringify({model:s.model,response:s.response,durationMs:s.durationMs,tokenCount:s.tokenCount,_Next:`Use the response in your workflow. stash to save it.`},null,2)}]}}catch(e){return X.error(`Delegate failed`,l(e)),{content:[{type:`text`,text:`Delegate failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Ke(t){let n=e(`lane`);t.registerTool(`lane`,{title:n.title,description:`Manage verified lanes — isolated file copies for parallel exploration. Create a lane, make changes, diff, merge back, or discard.`,inputSchema:{action:a.enum([`create`,`list`,`status`,`diff`,`merge`,`discard`]).describe(`Lane action to perform`),name:a.string().optional().describe(`Lane name (required for create/status/diff/merge/discard)`),files:a.array(a.string()).optional().describe(`File paths to copy into the lane (required for create)`)},annotations:n.annotations},async({action:e,name:t,files:n})=>{try{switch(e){case`create`:{if(!t)throw Error(`name is required for create`);if(!n||n.length===0)throw Error(`files are required for create`);let e=E(t,n);return{content:[{type:`text`,text:JSON.stringify(e)}]}}case`list`:return{content:[{type:`text`,text:JSON.stringify(k())}]};case`status`:if(!t)throw Error(`name is required for status`);return{content:[{type:`text`,text:JSON.stringify(j(t))}]};case`diff`:if(!t)throw Error(`name is required for diff`);return{content:[{type:`text`,text:JSON.stringify(D(t))}]};case`merge`:if(!t)throw Error(`name is required for merge`);return{content:[{type:`text`,text:JSON.stringify(A(t))}]};case`discard`:if(!t)throw Error(`name is required for discard`);return{content:[{type:`text`,text:JSON.stringify({discarded:O(t)})}]}}}catch(e){return X.error(`Lane action failed`,l(e)),{content:[{type:`text`,text:`Lane action failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function qe(t){let n=e(`health`);t.registerTool(`health`,{title:n.title,description:`Run project health checks — verifies package.json, tsconfig, scripts, lockfile, README, LICENSE, .gitignore.`,outputSchema:i,inputSchema:{path:a.string().optional().describe(`Root directory to check (defaults to cwd)`)},annotations:n.annotations},async({path:e})=>{try{let t=T(e),n={ok:t.checks.every(e=>e.status!==`fail`),checks:t.checks.map(e=>({name:e.name,ok:e.status===`pass`,message:e.message}))};return{content:[{type:`text`,text:JSON.stringify(t)}],structuredContent:n}}catch(e){return X.error(`Health check failed`,l(e)),{content:[{type:`text`,text:`Health check failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function Je(t){let n=e(`queue`);t.registerTool(`queue`,{title:n.title,description:`Manage task queues for sequential agent operations. Push items, take next, mark done/failed, list queues.`,inputSchema:{action:a.enum([`create`,`push`,`next`,`done`,`fail`,`get`,`list`,`clear`,`delete`]).describe(`Queue action`),name:a.string().optional().describe(`Queue name (required for most actions)`),title:a.string().optional().describe(`Item title (required for push)`),id:a.string().optional().describe(`Item ID (required for done/fail)`),data:a.unknown().optional().describe(`Arbitrary data to attach to a queue item`),error:a.string().optional().describe(`Error message (required for fail)`)},annotations:n.annotations},async({action:e,name:t,title:n,id:r,data:i,error:a})=>{try{switch(e){case`create`:if(!t)throw Error(`name is required for create`);return{content:[{type:`text`,text:JSON.stringify(B(t))}]};case`push`:if(!t)throw Error(`name is required for push`);if(!n)throw Error(`title is required for push`);return{content:[{type:`text`,text:JSON.stringify(q(t,n,i))}]};case`next`:{if(!t)throw Error(`name is required for next`);let e=K(t);return{content:[{type:`text`,text:JSON.stringify(e)}]}}case`done`:if(!t)throw Error(`name is required for done`);if(!r)throw Error(`id is required for done`);return{content:[{type:`text`,text:JSON.stringify(H(t,r))}]};case`fail`:if(!t)throw Error(`name is required for fail`);if(!r)throw Error(`id is required for fail`);if(!a)throw Error(`error is required for fail`);return{content:[{type:`text`,text:JSON.stringify(U(t,r,a))}]};case`get`:if(!t)throw Error(`name is required for get`);return{content:[{type:`text`,text:JSON.stringify(W(t))}]};case`list`:return{content:[{type:`text`,text:JSON.stringify(G())}]};case`clear`:if(!t)throw Error(`name is required for clear`);return{content:[{type:`text`,text:JSON.stringify({cleared:z(t)})}]};case`delete`:if(!t)throw Error(`name is required for delete`);return{content:[{type:`text`,text:JSON.stringify({deleted:V(t)})}]}}}catch(e){return X.error(`Queue action failed`,l(e)),{content:[{type:`text`,text:`Queue action failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}const Ye=a.object({query:a.string(),limit:a.number().min(1).max(20).default(5).optional(),search_mode:a.enum([`hybrid`,`semantic`,`keyword`]).default(`hybrid`).optional(),content_type:a.enum(o).optional(),origin:a.enum([`indexed`,`curated`,`produced`]).optional(),category:a.string().optional(),tags:a.array(a.string()).optional(),min_score:a.number().min(0).max(1).default(.25).optional()}),Xe=a.object({query:a.string().optional(),glob:a.string().optional(),pattern:a.string().optional(),limit:a.number().min(1).max(50).default(10).optional(),content_type:a.enum(o).optional(),cwd:a.string().optional()}),Z=a.object({files:a.array(a.string()).optional(),cwd:a.string().optional(),skip_types:a.boolean().optional(),skip_lint:a.boolean().optional()});async function Ze(e,t,n){switch(e.type){case`search`:return Qe(t,n,Ye.parse(e.args));case`find`:{let r=Xe.parse(e.args);if(!r.query&&!r.glob&&!r.pattern)throw Error(`find operation requires query, glob, or pattern`);return y(t,n,{query:r.query,glob:r.glob,pattern:r.pattern,limit:r.limit,contentType:r.content_type,cwd:r.cwd})}case`check`:{let t=Z.parse(e.args);return f({files:t.files,cwd:t.cwd,skipTypes:t.skip_types,skipLint:t.skip_lint})}default:throw Error(`Unsupported batch operation type: ${e.type}`)}}async function Qe(e,t,n){let r=n.limit??5,i={limit:r,minScore:n.min_score??.25,contentType:n.content_type,origin:n.origin,category:n.category,tags:n.tags},a=e.embedQuery?.bind(e)??e.embed.bind(e);if(n.search_mode===`keyword`)return(await t.ftsSearch(n.query,i)).slice(0,r);let o=await a(n.query);if(n.search_mode===`semantic`)return t.search(o,i);let[s,c]=await Promise.all([t.search(o,{...i,limit:r*2}),t.ftsSearch(n.query,{...i,limit:r*2})]);return $e(s,c).slice(0,r)}function $e(e,t,n=60){let r=new Map;for(let t=0;t<e.length;t++){let i=e[t];r.set(i.record.id,{record:i.record,score:1/(n+t+1)})}for(let e=0;e<t.length;e++){let i=t[e],a=r.get(i.record.id);if(a){a.score+=1/(n+e+1);continue}r.set(i.record.id,{record:i.record,score:1/(n+e+1)})}return[...r.values()].sort((e,t)=>t.score-e.score)}function et(e){let t=[`Symbol: ${e.name}`];if(e.definedIn){let n=`Defined in: ${e.definedIn.path}:${e.definedIn.line} (${e.definedIn.kind})`;e.definedIn.signature&&(n+=`\nSignature: ${e.definedIn.signature}`),t.push(n)}else t.push(`Defined in: not found`);if(t.push(``,`Imported by:`),e.importedBy.length===0)t.push(` none`);else for(let n of e.importedBy)t.push(` - ${n.path}:${n.line} ${n.importStatement}`);if(t.push(``,`Referenced in:`),e.referencedIn.length===0)t.push(` none`);else for(let n of e.referencedIn){let e=`scope`in n&&n.scope?` in ${n.scope}()`:``;t.push(` - ${n.path}:${n.line}${e} ${n.context}`)}if(e.graphContext){let n=e.graphContext;t.push(``,`Graph context:`),n.definingModule&&t.push(` Module: ${n.definingModule}`),n.importedByModules.length>0&&t.push(` Imported by modules: ${n.importedByModules.join(`, `)}`),n.siblingSymbols.length>0&&t.push(` Sibling symbols: ${n.siblingSymbols.join(`, `)}`)}return t.join(`
13
- `)}function tt(e){let t=[`Vitest run: ${e.passed?`passed`:`failed`}`,`Duration: ${e.durationMs}ms`,`Passed: ${e.summary.passed}`,`Failed: ${e.summary.failed}`,`Skipped: ${e.summary.skipped}`];e.summary.suites!==void 0&&t.push(`Suites: ${e.summary.suites}`);let n=e.summary.tests.filter(e=>e.status===`fail`);if(n.length>0){t.push(``,`Failed tests:`);for(let e of n)t.push(`- ${e.name}${e.file?` (${e.file})`:``}`),e.error&&t.push(` ${e.error}`)}return t.join(`
14
- `)}function nt(e){let t=[`Branch: ${e.branch}`,`Staged: ${e.status.staged.length}`,...e.status.staged.map(e=>` - ${e}`),`Modified: ${e.status.modified.length}`,...e.status.modified.map(e=>` - ${e}`),`Untracked: ${e.status.untracked.length}`,...e.status.untracked.map(e=>` - ${e}`),``,`Recent commits:`];if(e.recentCommits.length===0)t.push(` none`);else for(let n of e.recentCommits)t.push(` - ${n.hash} ${n.message}`),t.push(` ${n.author} @ ${n.date}`);return e.diff&&t.push(``,`Diff stat:`,e.diff),t.join(`
15
- `)}function rt(e){if(e.length===0)return`No diff files found.`;let t=[];for(let n of e){let e=n.oldPath?` (from ${n.oldPath})`:``;t.push(`${n.path}${e} [${n.status}] +${n.additions} -${n.deletions} (${n.hunks.length} hunks)`);for(let e of n.hunks){let n=e.header?` ${e.header}`:``;t.push(` @@ -${e.oldStart},${e.oldLines} +${e.newStart},${e.newLines} @@${n}`)}}return t.join(`
16
- `)}function it(e){let t=[e.path,`Language: ${e.language}`,`Lines: ${e.lines}`,`Estimated tokens: ~${e.estimatedTokens}`,``,`Imports (${e.imports.length}):`,...$(e.imports),``,`Exports (${e.exports.length}):`,...$(e.exports),``,`Functions (${e.functions.length}):`,...$(e.functions.map(e=>`${e.name} @ line ${e.line}${e.exported?` [exported]`:``}${`signature`in e&&e.signature?` — ${e.signature}`:``}`)),``,`Classes (${e.classes.length}):`,...$(e.classes.map(e=>`${e.name} @ line ${e.line}${e.exported?` [exported]`:``}${e.signature?` — ${e.signature}`:``}`)),``,`Interfaces (${e.interfaces.length}):`,...$(e.interfaces.map(e=>`${e.name} @ line ${e.line}${`exported`in e&&e.exported?` [exported]`:``}`)),``,`Types (${e.types.length}):`,...$(e.types.map(e=>`${e.name} @ line ${e.line}${`exported`in e&&e.exported?` [exported]`:``}`))];if(`importDetails`in e&&e.importDetails&&e.importDetails.length>0){let n=e.importDetails.filter(e=>e.isExternal).length,r=e.importDetails.length-n;t.push(``,`Import breakdown: ${n} external, ${r} internal`)}if(`callEdges`in e&&e.callEdges&&e.callEdges.length>0){t.push(``,`Call edges (${e.callEdges.length} intra-file):`);for(let n of e.callEdges.slice(0,30))t.push(` - ${n.caller}() → ${n.callee}() @ line ${n.line}`);e.callEdges.length>30&&t.push(` - ... ${e.callEdges.length-30} more`)}return t.join(`
17
- `)}function Q(e){let t=[e.id,`Label: ${e.label}`,`Created: ${e.createdAt}`];if(e.notes&&t.push(`Notes: ${e.notes}`),e.files?.length){t.push(`Files: ${e.files.length}`);for(let n of e.files)t.push(` - ${n}`)}return t.push(``,`Data:`,JSON.stringify(e.data)),t.join(`
18
- `)}function $(e){return e.length===0?[` none`]:e.map(e=>` - ${e}`)}function at(e){let t=e.trim();if(!t)return``;try{return JSON.parse(t)}catch{return e}}function ot(e){let t=e?.trim();if(!t)return{};let n;try{n=JSON.parse(t)}catch{throw Error(`data must be a valid JSON object string`)}if(!n||typeof n!=`object`||Array.isArray(n))throw Error(`data must be a JSON object string`);return n}function st(t){let n=e(`web_fetch`);t.registerTool(`web_fetch`,{title:n.title,description:`PREFERRED web fetcher — fetch any URL and convert to LLM-optimized markdown. Supports CSS selectors, 4 output modes (markdown/raw/links/outline), smart paragraph-boundary truncation. Strips scripts/styles/nav automatically.`,inputSchema:{url:a.string().url().describe(`URL to fetch (http/https only)`),mode:a.enum([`markdown`,`raw`,`links`,`outline`]).default(`markdown`).describe(`Output mode: markdown (clean content), raw (HTML), links (extracted URLs), outline (heading hierarchy)`),selector:a.string().optional().describe(`CSS selector to extract a specific element instead of auto-detecting main content`),max_length:a.number().min(500).max(1e5).default(15e3).describe(`Max characters in output — truncates at paragraph boundaries`),include_metadata:a.boolean().default(!0).describe(`Include page title, description, and URL as a header`),include_links:a.boolean().default(!1).describe(`Append extracted links list at the end`),include_images:a.boolean().default(!1).describe(`Include image alt texts inline`),timeout:a.number().min(1e3).max(6e4).default(15e3).describe(`Request timeout in milliseconds`)},annotations:n.annotations},async({url:e,mode:t,selector:n,max_length:r,include_metadata:i,include_links:a,include_images:o,timeout:s})=>{try{let c=await Se({url:e,mode:t,selector:n,maxLength:r,includeMetadata:i,includeLinks:a,includeImages:o,timeout:s}),l=[`## ${c.title||`Web Page`}`,``,c.content];return c.truncated&&l.push(``,`_Original length: ${c.originalLength.toLocaleString()} chars_`),l.push(``,`---`,"_Next: Use `remember` to save key findings, or `web_fetch` with a `selector` to extract a specific section._"),{content:[{type:`text`,text:l.join(`
19
- `)}]}}catch(e){return X.error(`Web fetch failed`,l(e)),{content:[{type:`text`,text:`Web fetch failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}function ct(t){let n=e(`guide`);t.registerTool(`guide`,{title:n.title,description:`Tool discovery — given a goal description, recommends which KB tools to use and in what order. Matches against 10 predefined workflows: onboard, audit, bugfix, implement, refactor, search, context, memory, validate, analyze.`,inputSchema:{goal:a.string().describe(`What you want to accomplish (e.g., "audit this monorepo", "fix a failing test")`),max_recommendations:a.number().min(1).max(10).default(5).describe(`Maximum number of tool recommendations`)},annotations:n.annotations},async({goal:e,max_recommendations:t})=>{try{let n=w(e,t),r=[`## Recommended Workflow: **${n.workflow}**`,n.description,``,`### Tools`,...n.tools.map(e=>{let t=e.suggestedArgs?` — \`${JSON.stringify(e.suggestedArgs)}\``:``;return`${e.order}. **${e.tool}** — ${e.reason}${t}`})];return n.alternativeWorkflows.length>0&&r.push(``,`_Alternative workflows: ${n.alternativeWorkflows.join(`, `)}_`),r.push(``,`---`,"_Next: Run the first recommended tool, or use `guide` again with a more specific goal._"),{content:[{type:`text`,text:r.join(`
20
- `)}]}}catch(e){return X.error(`Guide failed`,l(e)),{content:[{type:`text`,text:`Guide failed: ${e instanceof Error?e.message:String(e)}`}],isError:!0}}})}export{ke as registerBatchTool,Oe as registerCheckTool,ze as registerCheckpointTool,Le as registerCodemodTool,Ce as registerCompactTool,Be as registerDataTransformTool,We as registerDeadSymbolsTool,Ge as registerDelegateTool,Fe as registerDiffParseTool,je as registerEvalTool,Re as registerFileSummaryTool,Te as registerFindTool,Pe as registerGitContextTool,ct as registerGuideTool,qe as registerHealthTool,Ke as registerLaneTool,Ee as registerParseOutputTool,He as registerProcessTool,Je as registerQueueTool,Ie as registerRenameTool,we as registerScopeMapTool,Ne as registerStashTool,Ae as registerSymbolTool,Me as registerTestRunTool,Ve as registerTraceTool,Ue as registerWatchTool,st as registerWebFetchTool,De as registerWorksetTool};
@@ -1,2 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{a as t,i as n,n as r,s as i,t as a}from"./jsx-runtime-Cof-kwFn.js";import{t as o}from"./StatusPanel-2ex8fLOO.js";import{t as s}from"./SearchPanel-DREo6zgt.js";import{t as c}from"./CuratedPanel-sYdZAICX.js";import{t as l}from"./LogPanel-Ce3jMQbH.js";var u=e(i()),d=a();const f=[`status`,`search`,`curated`,`log`];function p({context:e}){let[i,a]=(0,u.useState)(`status`);return r((e,t)=>{t.tab&&a(f[(f.indexOf(i)+1)%f.length]),e===`1`&&a(`status`),e===`2`&&a(`search`),e===`3`&&a(`curated`),e===`4`&&a(`log`)}),(0,d.jsxs)(t,{flexDirection:`column`,width:`100%`,children:[(0,d.jsxs)(t,{borderStyle:`single`,paddingX:1,children:[(0,d.jsx)(n,{bold:!0,color:`cyan`,children:`KB Dashboard`}),(0,d.jsx)(n,{children:` │ `}),f.map(e=>(0,d.jsxs)(u.Fragment,{children:[(0,d.jsxs)(n,{color:e===i?`green`:`gray`,bold:e===i,children:[`[`,f.indexOf(e)+1,`] `,e]}),(0,d.jsx)(n,{children:` `})]},e)),(0,d.jsx)(n,{color:`gray`,children:` │ Tab: switch │ Ctrl+C: quit`})]}),(0,d.jsxs)(t,{flexGrow:1,minHeight:10,children:[i===`status`&&(0,d.jsx)(o,{store:e.store}),i===`search`&&(0,d.jsx)(s,{store:e.store,embedder:e.embedder}),i===`curated`&&(0,d.jsx)(c,{store:e.store}),i===`log`&&(0,d.jsx)(l,{})]})]})}export{p as t};
@@ -1,2 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{a as t,i as n,s as r,t as i}from"./jsx-runtime-Cof-kwFn.js";var a=e(r()),o=i();function s({store:e}){let[r,i]=(0,a.useState)([]),[s,c]=(0,a.useState)(null);return(0,a.useEffect)(()=>{let t=!0,n=async()=>{try{let n=(await e.listSourcePaths()).filter(e=>e.includes(`curated`));t&&(i(n.slice(-20).map(e=>({title:e.split(`/`).pop()??e,category:e.split(`/`).at(-2)??`uncategorized`}))),c(null))}catch(e){t&&c(e instanceof Error?e.message:String(e))}};n();let r=setInterval(n,1e4);return()=>{t=!1,clearInterval(r)}},[e]),(0,o.jsxs)(t,{flexDirection:`column`,borderStyle:`round`,paddingX:1,children:[(0,o.jsx)(n,{bold:!0,color:`cyan`,children:`Curated Knowledge`}),(0,o.jsx)(n,{children:` `}),s&&(0,o.jsxs)(n,{color:`red`,children:[`Error: `,s]}),r.length===0&&!s&&(0,o.jsx)(n,{color:`gray`,children:`No curated entries found`}),r.map(e=>(0,o.jsxs)(n,{children:[(0,o.jsx)(n,{color:`magenta`,children:`•`}),` `,e.title,` `,(0,o.jsxs)(n,{color:`gray`,children:[`(`,e.category,`)`]})]},e.title)),(0,o.jsx)(n,{children:` `}),(0,o.jsx)(n,{color:`gray`,children:`Refreshes every 10s`})]})}export{s as t};
@@ -1,3 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{a as t,i as n,s as r,t as i}from"./jsx-runtime-Cof-kwFn.js";import{exec as a,execFile as o}from"node:child_process";import{appendFileSync as s,existsSync as c,mkdirSync as l,readFileSync as u,readdirSync as d,unlinkSync as f}from"node:fs";import{dirname as p,join as m,resolve as h}from"node:path";import{promisify as g}from"node:util";import{fileURLToPath as _}from"node:url";import"turndown";g(a),m(p(_(import.meta.url)),`..`,`..`,`wasm`),new Set(Object.keys({".ts":`tree-sitter-typescript.wasm`,".tsx":`tree-sitter-typescript.wasm`,".mts":`tree-sitter-typescript.wasm`,".cts":`tree-sitter-typescript.wasm`,".js":`tree-sitter-javascript.wasm`,".jsx":`tree-sitter-javascript.wasm`,".mjs":`tree-sitter-javascript.wasm`,".cjs":`tree-sitter-javascript.wasm`,".py":`tree-sitter-python.wasm`,".go":`tree-sitter-go.wasm`,".rs":`tree-sitter-rust.wasm`,".java":`tree-sitter-java.wasm`}));const v={ai:`.ai`,aiKb:`.ai/kb`,aiCurated:`.ai/curated`,restorePoints:`.ai/restore-points`,data:`.kb-data`,state:`.kb-state`,logs:`.kb-state/logs`,brainstorm:`.brainstorm`,handoffs:`.handoffs`};v.data;const y={debug:0,info:1,warn:2,error:3},b=[];let x=process.env.KB_LOG_LEVEL??`info`,S=process.env.KB_LOG_FILE_SINK===`true`||process.env.KB_LOG_FILE_SINK!==`false`&&!process.env.VITEST&&process.env.NODE_ENV!==`test`;function C(){return S?process.env.VITEST||process.env.NODE_ENV===`test`?process.env.KB_LOG_FILE_SINK===`true`:!0:!1}let w;function T(){return w||=h(process.cwd(),v.logs),w}function E(e){let t=e.toISOString().slice(0,10);return m(T(),`${t}.jsonl`)}let D=0;function O(){let e=Date.now();if(!(e-D<36e5)){D=e;try{let t=T(),n=new Date(e-30*864e5).toISOString().slice(0,10);for(let e of d(t))if(e.endsWith(`.jsonl`)&&e.slice(0,10)<n)try{f(m(t,e))}catch{}}catch{}}}function k(e,t){try{l(T(),{recursive:!0}),s(E(t),`${e}\n`),O()}catch{}}function A(e){function t(t,n,r){if(y[t]<y[x])return;let i=new Date,a={ts:i.toISOString(),level:t,component:e,msg:n,...r},o=JSON.stringify(a);console.error(o);for(let i of b)try{i({level:t,component:e,message:n,data:r})}catch{}C()&&(t===`warn`||t===`error`)&&k(o,i)}return{debug:(e,n)=>t(`debug`,e,n),info:(e,n)=>t(`info`,e,n),warn:(e,n)=>t(`warn`,e,n),error:(e,n)=>t(`error`,e,n)}}const j=A(`query-executor`),M=p(_(import.meta.url));function N(){let e=m(M,`..`,`queries`);if(c(e))return e;let t=m(M,`..`,`..`,`src`,`queries`);return c(t)?t:e}const P=N(),F={".ts":`typescript`,".tsx":`typescript`,".mts":`typescript`,".cts":`typescript`,".js":`javascript`,".jsx":`javascript`,".mjs":`javascript`,".cjs":`javascript`,".py":`python`,".go":`go`,".rs":`rust`,".java":`java`};var I=class{queryCache=new Map;scmCache=new Map;execute(e,t,n,r){let i=this.getOrCompile(t,n,r);return i?i.matches(e).map(e=>L(e)):[]}executeCaptures(e,t,n,r){let i=this.getOrCompile(t,n,r);return i?i.captures(e).map(e=>R(e)):[]}executeRaw(e,t,n){return t.query(n).matches(e).map(e=>L(e))}getOrCompile(e,t,n){let r=F[t];if(!r)return null;let i=`${r}:${n}`,a=this.queryCache.get(i);if(a)return a;let o=this.loadScm(r,n);if(!o)return null;try{let t=e.query(o);return this.queryCache.set(i,t),t}catch(e){throw j.warn(`Failed to compile query`,{langDir:r,queryType:n,error:String(e)}),Error(`Failed to compile ${r}/${n}.scm: ${String(e)}`)}}loadScm(e,t){let n=`${e}:${t}`,r=this.scmCache.get(n);if(r!==void 0)return r;let i=m(P,e,`${t}.scm`);try{let e=u(i,`utf-8`);return this.scmCache.set(n,e),e}catch{return j.info(`Query file not found (graceful skip)`,{langDir:e,queryType:t}),null}}dispose(){this.queryCache.clear(),this.scmCache.clear()}static resolveQueryDir(e){return m(P,e)}};function L(e){let t=new Map;for(let n of e.captures)t.set(n.name,R(n));return{pattern:e.pattern,captures:t}}function R(e){let{node:t}=e;return{name:e.name,text:t.text,nodeType:t.type,startLine:t.startPosition.row,endLine:t.endPosition.row,startColumn:t.startPosition.column,endColumn:t.endPosition.column,node:t}}new I,new I,new I,new I,new I,new Set(`.ts,.tsx,.js,.jsx,.mjs,.cjs,.java,.kt,.kts,.scala,.py,.go,.rs,.rb,.php,.swift,.cs,.c,.cpp,.h,.hpp,.sh,.bash,.ps1,.sql,.graphql,.gql,.proto,.json,.yaml,.yml,.toml,.env,.ini,.cfg,.xml,.pom,.gradle,.tf,.hcl,.lock,.mjs`.split(`,`)),`${v.state}`,v.restorePoints,new Set([`node_modules`,`.git`,`dist`,`build`,`coverage`,`.turbo`,`.cache`,`cdk.out`,v.state]),v.state,new Set([`.git`,v.data,v.state,`.turbo`,`.yarn`,`build`,`coverage`,`dist`,`node_modules`]),g(o),`${v.state}`,new Set(`if_statement.for_statement.for_in_statement.while_statement.do_statement.switch_case.catch_clause.ternary_expression.if_statement.for_statement.while_statement.except_clause.list_comprehension.if_statement.for_statement.enhanced_for_statement.while_statement.catch_clause.ternary_expression.if_statement.for_statement.select_statement.if_expression.for_expression.while_expression.match_arm`.split(`.`)),v.state;function z(){return h(process.cwd(),v.state,`replay.jsonl`)}function B(e={}){let t=z(),n;try{n=u(t,`utf-8`)}catch{return[]}let r=n.trim().split(`
3
- `).filter(Boolean),i=[];for(let e of r)try{i.push(JSON.parse(e))}catch{}if(e.tool&&(i=i.filter(t=>t.tool===e.tool)),e.source&&(i=i.filter(t=>t.source===e.source)),e.since){let t=e.since;i=i.filter(e=>e.ts>=t)}let a=e.last??20;return i.slice(-a)}v.state,g(a),v.data,`script,style,noscript,iframe,svg,nav,footer,header,aside,form,button,input,select,textarea,[role="navigation"],[role="banner"],[role="contentinfo"],[aria-hidden="true"],.sidebar,.nav,.menu,.footer,.header,.ad,.advertisement,.cookie-banner,.popup,.modal`.split(`,`),v.state;var V=e(r()),H=i();function U(){let[e,r]=(0,V.useState)([]);return(0,V.useEffect)(()=>{let e=()=>{r(B({last:30}))};e();let t=setInterval(e,2e3);return()=>clearInterval(t)},[]),(0,H.jsxs)(t,{flexDirection:`column`,borderStyle:`round`,paddingX:1,children:[(0,H.jsx)(n,{bold:!0,color:`cyan`,children:`Activity Log`}),(0,H.jsx)(n,{children:` `}),e.length===0&&(0,H.jsx)(n,{color:`gray`,children:`No activity recorded yet`}),e.slice().reverse().map((e,t)=>{let r=e.ts.split(`T`)[1]?.split(`.`)[0]??e.ts,i=e.status===`ok`?`green`:`red`;return(0,H.jsxs)(n,{children:[(0,H.jsx)(n,{color:`gray`,children:r}),` `,(0,H.jsx)(n,{color:i,children:e.status===`ok`?`✓`:`✗`}),` `,(0,H.jsx)(n,{bold:!0,children:e.tool}),` `,(0,H.jsxs)(n,{color:`gray`,children:[`(`,e.durationMs,`ms)`]})]},`${e.ts}-${t}`)}),(0,H.jsx)(n,{children:` `}),(0,H.jsx)(n,{color:`gray`,children:`Refreshes every 2s │ Showing last 30`})]})}export{U as t};
@@ -1,2 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{a as t,i as n,n as r,o as i,s as a,t as o}from"./jsx-runtime-Cof-kwFn.js";var s=e(a(),1);function c({value:e,placeholder:t=``,focus:a=!0,mask:o,highlightPastedText:c=!1,showCursor:l=!0,onChange:u,onSubmit:d}){let[f,p]=(0,s.useState)({cursorOffset:(e||``).length,cursorWidth:0}),{cursorOffset:m,cursorWidth:h}=f;(0,s.useEffect)(()=>{p(t=>{if(!a||!l)return t;let n=e||``;return t.cursorOffset>n.length-1?{cursorOffset:n.length,cursorWidth:0}:t})},[e,a,l]);let g=c?h:0,_=o?o.repeat(e.length):e,v=_,y=t?i.grey(t):void 0;if(l&&a){y=t.length>0?i.inverse(t[0])+i.grey(t.slice(1)):i.inverse(` `),v=_.length>0?``:i.inverse(` `);let e=0;for(let t of _)v+=e>=m-g&&e<=m?i.inverse(t):t,e++;_.length>0&&m===_.length&&(v+=i.inverse(` `))}return r((t,n)=>{if(n.upArrow||n.downArrow||n.ctrl&&t===`c`||n.tab||n.shift&&n.tab)return;if(n.return){d&&d(e);return}let r=m,i=e,a=0;n.leftArrow?l&&r--:n.rightArrow?l&&r++:n.backspace||n.delete?m>0&&(i=e.slice(0,m-1)+e.slice(m,e.length),r--):(i=e.slice(0,m)+t+e.slice(m,e.length),r+=t.length,t.length>1&&(a=t.length)),m<0&&(r=0),m>e.length&&(r=e.length),p({cursorOffset:r,cursorWidth:a}),i!==e&&u(i)},{isActive:a}),s.createElement(n,null,t?_.length>0?v:y:v)}var l=o();function u({store:e,embedder:r}){let[i,a]=(0,s.useState)(``),[o,u]=(0,s.useState)([]),[d,f]=(0,s.useState)(!1);return(0,l.jsxs)(t,{flexDirection:`column`,borderStyle:`round`,paddingX:1,children:[(0,l.jsx)(n,{bold:!0,color:`cyan`,children:`Search`}),(0,l.jsxs)(t,{children:[(0,l.jsx)(n,{color:`green`,children:`> `}),(0,l.jsx)(c,{value:i,onChange:a,onSubmit:async t=>{if(t.trim()){f(!0);try{let n=await r.embed(t);u((await e.search(n,{limit:10})).map(e=>({path:e.record.sourcePath,score:e.score,snippet:e.record.content.slice(0,80)})))}catch{u([])}finally{f(!1)}}}})]}),(0,l.jsx)(n,{children:` `}),d&&(0,l.jsx)(n,{color:`yellow`,children:`Searching…`}),!d&&o.length===0&&i&&(0,l.jsx)(n,{color:`gray`,children:`No results. Press Enter to search.`}),o.map((e,r)=>(0,l.jsxs)(t,{flexDirection:`column`,children:[(0,l.jsxs)(n,{children:[(0,l.jsxs)(n,{color:`green`,children:[(r+1).toString(),`.`]}),` `,(0,l.jsx)(n,{bold:!0,children:e.path}),(0,l.jsxs)(n,{color:`gray`,children:[` (score: `,e.score.toFixed(3),`)`]})]}),(0,l.jsxs)(n,{color:`gray`,children:[` `,e.snippet]})]},`${e.path}-${r}`))]})}export{u as t};
@@ -1,2 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import{r as e}from"./chunk-D6axbAb-.js";import{a as t,i as n,s as r,t as i}from"./jsx-runtime-Cof-kwFn.js";var a=e(r()),o=i();function s({store:e}){let[r,i]=(0,a.useState)(null),[s,c]=(0,a.useState)(null);return(0,a.useEffect)(()=>{let t=!0,n=async()=>{try{let n=await e.getStats(),r=await e.listSourcePaths();t&&(i({totalRecords:n.totalRecords,totalFiles:n.totalFiles??0,sourcePaths:r}),c(null))}catch(e){t&&c(e instanceof Error?e.message:String(e))}};n();let r=setInterval(n,5e3);return()=>{t=!1,clearInterval(r)}},[e]),(0,o.jsxs)(t,{flexDirection:`column`,borderStyle:`round`,paddingX:1,children:[(0,o.jsx)(n,{bold:!0,color:`cyan`,children:`Index Status`}),(0,o.jsx)(n,{children:` `}),s&&(0,o.jsxs)(n,{color:`red`,children:[`Error: `,s]}),r&&(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n,{children:[`Records: `,(0,o.jsx)(n,{bold:!0,children:r.totalRecords.toLocaleString()})]}),(0,o.jsxs)(n,{children:[`Files: `,(0,o.jsx)(n,{bold:!0,children:r.totalFiles.toLocaleString()})]}),(0,o.jsxs)(n,{children:[`Sources: `,(0,o.jsx)(n,{bold:!0,children:r.sourcePaths.length})]}),r.sourcePaths.slice(0,5).map(e=>(0,o.jsxs)(n,{color:`gray`,children:[` `,`• `,e]},e)),r.sourcePaths.length>5&&(0,o.jsxs)(n,{color:`gray`,children:[` `,`… and `,r.sourcePaths.length-5,` more`]})]}),!r&&!s&&(0,o.jsx)(n,{color:`yellow`,children:`Loading…`}),(0,o.jsx)(n,{children:` `}),(0,o.jsx)(n,{color:`gray`,children:`Refreshes every 5s`})]})}export{s as t};
@@ -1,28 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- //#region packages/embeddings/dist/embedder.interface.d.ts
3
- //#region packages/embeddings/src/embedder.interface.d.ts
4
- /**
5
- * Embedding abstraction — allows swapping embedding models.
6
- */
7
- interface IEmbedder {
8
- /** Generate an embedding vector for a single text string (used for documents/passages) */
9
- embed(text: string): Promise<Float32Array>;
10
- /**
11
- * Generate an embedding vector for a search query.
12
- * Some models (e.g., BGE) use a query prefix for asymmetric retrieval.
13
- * Falls back to embed() if the model doesn't need query prefixing.
14
- */
15
- embedQuery(query: string): Promise<Float32Array>;
16
- /** Generate embeddings for multiple text strings (batched, for documents/passages) */
17
- embedBatch(texts: string[], batchSize?: number): Promise<Float32Array[]>;
18
- /** The dimensionality of the embedding vectors */
19
- readonly dimensions: number;
20
- /** The model identifier */
21
- readonly modelId: string;
22
- /** Initialize the model (download if needed, load into memory) */
23
- initialize(): Promise<void>;
24
- /** Release model resources */
25
- shutdown?(): Promise<void>;
26
- } //#endregion
27
- //#endregion
28
- export { IEmbedder as t };
@@ -1,13 +0,0 @@
1
- import { createRequire as __createRequire } from 'node:module'; const require = __createRequire(import.meta.url);
2
- import { n as KBConfig, t as IKnowledgeStore } from "./store.interface-CnY6SPOH.js";
3
- import { t as IEmbedder } from "./embedder.interface-IFCBpOlX.js";
4
-
5
- //#region packages/tui/src/index.d.ts
6
- interface TUIContext {
7
- store: IKnowledgeStore;
8
- embedder: IEmbedder;
9
- config: KBConfig;
10
- }
11
- declare function launch(context: TUIContext): void;
12
- //#endregion
13
- export { launch as n, TUIContext as t };