@vpxa/kb 0.1.12 → 0.1.13

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 (54) hide show
  1. package/README.md +48 -37
  2. package/package.json +1 -1
  3. package/packages/analyzers/dist/entry-point-analyzer.d.ts +18 -0
  4. package/packages/analyzers/dist/entry-point-analyzer.js +6 -5
  5. package/packages/analyzers/dist/pattern-analyzer.js +1 -1
  6. package/packages/analyzers/dist/types.d.ts +1 -1
  7. package/packages/cli/dist/commands/init.d.ts +2 -1
  8. package/packages/cli/dist/commands/init.js +242 -183
  9. package/packages/cli/dist/commands/knowledge.js +1 -1
  10. package/packages/cli/dist/commands/system.js +6 -3
  11. package/packages/cli/dist/helpers.js +5 -3
  12. package/packages/core/dist/content-detector.d.ts +5 -1
  13. package/packages/core/dist/content-detector.js +1 -1
  14. package/packages/core/dist/index.d.ts +1 -1
  15. package/packages/core/dist/index.js +1 -1
  16. package/packages/core/dist/types.d.ts +2 -0
  17. package/packages/server/dist/server.js +1 -1
  18. package/packages/server/dist/tools/analyze.tools.js +3 -1
  19. package/packages/server/dist/tools/audit.tool.d.ts +5 -0
  20. package/packages/server/dist/tools/audit.tool.js +4 -0
  21. package/packages/server/dist/tools/replay.tool.js +4 -4
  22. package/packages/server/dist/tools/search.tool.js +18 -14
  23. package/packages/server/dist/tools/status.tool.js +3 -3
  24. package/packages/server/dist/tools/toolkit.tools.d.ts +1 -1
  25. package/packages/server/dist/tools/toolkit.tools.js +23 -20
  26. package/packages/store/dist/lance-store.js +1 -1
  27. package/packages/store/dist/store.interface.d.ts +2 -0
  28. package/packages/tools/dist/audit.d.ts +66 -0
  29. package/packages/tools/dist/audit.js +7 -0
  30. package/packages/tools/dist/check.d.ts +19 -0
  31. package/packages/tools/dist/check.js +2 -2
  32. package/packages/tools/dist/compact.d.ts +4 -2
  33. package/packages/tools/dist/compact.js +2 -2
  34. package/packages/tools/dist/dead-symbols.d.ts +9 -1
  35. package/packages/tools/dist/dead-symbols.js +2 -2
  36. package/packages/tools/dist/forge-classify.js +1 -1
  37. package/packages/tools/dist/guide.d.ts +23 -0
  38. package/packages/tools/dist/guide.js +1 -0
  39. package/packages/tools/dist/health.js +2 -1
  40. package/packages/tools/dist/index.d.ts +6 -2
  41. package/packages/tools/dist/index.js +1 -1
  42. package/packages/tools/dist/path-resolver.d.ts +12 -0
  43. package/packages/tools/dist/path-resolver.js +1 -0
  44. package/packages/tools/dist/replay.d.ts +1 -1
  45. package/packages/tools/dist/response-envelope.d.ts +41 -0
  46. package/packages/tools/dist/response-envelope.js +1 -0
  47. package/packages/tools/dist/scope-map.d.ts +2 -0
  48. package/packages/tools/dist/scope-map.js +1 -1
  49. package/packages/tools/dist/truncation.d.ts +9 -0
  50. package/packages/tools/dist/truncation.js +8 -8
  51. package/packages/tui/dist/App.js +109 -109
  52. package/packages/tui/dist/index.js +116 -116
  53. package/packages/tui/dist/panels/LogPanel.js +100 -100
  54. package/skills/knowledge-base/SKILL.md +19 -19
package/README.md CHANGED
@@ -23,7 +23,7 @@ This is an **MCP (Model Context Protocol) server** that gives AI agents:
23
23
  8. **Graph auto-population** — during indexing, a lightweight regex extractor builds the knowledge graph automatically from TS/JS source files (functions, classes, interfaces, types, imports)
24
24
  9. **Optimized reindex** — full reindex skips redundant hash checks, batches graph writes (flush every 50 files), and skips per-file graph deletes when bulk-cleared
25
25
 
26
- The KB auto-indexes configured source directories on startup, stores embeddings in a local LanceDB vector store, and exposes everything through 64 MCP tools, 47 CLI commands, and 2 resources.
26
+ The KB auto-indexes configured source directories on startup, stores embeddings in a local LanceDB vector store, and exposes everything through 64 MCP tools, 45 CLI commands, and 2 resources.
27
27
 
28
28
  ---
29
29
 
@@ -54,13 +54,12 @@ npx @vpxa/kb serve
54
54
  | Tool | CLI | Description |
55
55
  |------|-----|-------------|
56
56
  | `kb_search` | `kb search` | Hybrid vector + keyword search |
57
- | `kb_find` | `kb find` | Federated search (vector, FTS, glob, regex) |
57
+ | `kb_find` | `kb find` | Federated search (vector, FTS, glob, regex). Use `mode: 'examples'` to find usage examples. |
58
58
  | `kb_symbol` | `kb symbol` | Resolve symbol definition, imports, references |
59
59
  | `kb_lookup` | `kb lookup` | Look up indexed chunks by file path |
60
60
  | `kb_trace` | `kb trace` | Forward/backward flow tracing |
61
- | `kb_find_examples` | `kb examples` | Find usage examples of a symbol |
62
61
  | `kb_scope_map` | `kb scope-map` | Generate task-scoped reading plan |
63
- | `kb_dead_symbols` | `kb dead-symbols` | Find unused exported symbols |
62
+ | `kb_dead_symbols` | `kb dead-symbols` | Find unused exported symbols (source vs docs) |
64
63
  | `kb_file_summary` | `kb summarize` | Structural file overview |
65
64
 
66
65
  ### Code Analysis
@@ -70,14 +69,14 @@ npx @vpxa/kb serve
70
69
  | `kb_analyze_dependencies` | `kb analyze deps` | Dependency graph |
71
70
  | `kb_analyze_symbols` | `kb analyze symbols` | Symbol extraction |
72
71
  | `kb_analyze_patterns` | `kb analyze patterns` | Code pattern detection |
73
- | `kb_analyze_entry_points` | `kb analyze entry-points` | Entry point discovery |
72
+ | `kb_analyze_entry_points` | `kb analyze entry-points` | Entry point discovery: handlers, CDK constructs, test suites, package exports (walks monorepo workspaces) |
74
73
  | `kb_analyze_diagram` | `kb analyze diagram` | Mermaid diagram generation |
75
74
  | `kb_blast_radius` | `kb analyze blast-radius` | Change impact analysis |
76
75
 
77
76
  ### Context Management
78
77
  | Tool | CLI | Description |
79
78
  |------|-----|-------------|
80
- | `kb_compact` | `kb compact` | Compress text to relevant sections |
79
+ | `kb_compact` | `kb compact` | Compress text/file to relevant sections (accepts `path`) |
81
80
  | `kb_workset` | `kb workset` | Named file set management |
82
81
  | `kb_stash` | `kb stash` | Named key-value store |
83
82
  | `kb_checkpoint` | `kb checkpoint` | Session checkpoint save/restore |
@@ -104,9 +103,10 @@ npx @vpxa/kb serve
104
103
  | Tool | CLI | Description |
105
104
  |------|-----|-------------|
106
105
  | `kb_eval` | `kb eval` | Sandboxed JavaScript/TypeScript execution |
107
- | `kb_check` | `kb check` | Incremental typecheck + lint |
106
+ | `kb_check` | `kb check` | Incremental typecheck + lint (`detail`: summary/errors/full) |
108
107
  | `kb_test_run` | `kb test` | Run tests with structured results |
109
108
  | `kb_batch` | `kb batch` | Parallel operation execution |
109
+ | `kb_audit` | `kb audit` | Unified project audit: runs structure, deps, patterns, health, dead symbols, check, entry points in one call. Returns score, recommendations, and next steps. |
110
110
 
111
111
  ### Knowledge Management
112
112
  | Tool | CLI | Description |
@@ -158,14 +158,14 @@ npx @vpxa/kb serve
158
158
  ### System
159
159
  | Tool | CLI | Description |
160
160
  |------|-----|-------------|
161
- | `kb_status` | `kb status` | Index statistics |
161
+ | `kb_status` | `kb status` | Index statistics + tree-sitter availability |
162
162
  | `kb_reindex` | `kb reindex` | Rebuild index |
163
- | `kb_health` | `kb health` | Project health checks (package.json, tsconfig, lockfile, etc.) |
163
+ | `kb_health` | `kb health` | Project health checks (package.json, tsconfig, lockfile, circular deps) |
164
+ | `kb_guide` | `kb guide` | Tool discovery — given a goal, recommends tools and workflow order |
164
165
  | `kb_queue` | `kb queue` | Task queue for sequential agent operations |
165
166
  | `kb_graph` | `kb graph` | Query and manage the knowledge graph (8 actions: find_nodes, find_edges, neighbors, traverse, stats, add, delete, clear) |
166
167
  | `kb_onboard` | `kb onboard` | First-time codebase onboarding — runs all analysis tools in one command, auto-persists results |
167
- | `kb_replay_list` | `kb replay` | View audit trail of tool invocations |
168
- | `kb_replay_clear` | `kb replay-clear` | Clear the replay audit trail |
168
+ | `kb_replay` | `kb replay` | View or clear the audit trail of tool invocations (action: list/clear) |
169
169
 
170
170
  ### TUI Dashboard
171
171
 
@@ -211,7 +211,7 @@ kb analyze <type> <path>
211
211
  kb lookup <path>
212
212
 
213
213
  # Context
214
- kb compact <query> [--max-chars N]
214
+ kb compact <query> [--path <file>] [--max-chars N]
215
215
  kb workset <action> [name] [--files f1,f2]
216
216
  kb stash <action> [key] [value]
217
217
  kb checkpoint <action> [label]
@@ -226,7 +226,7 @@ kb transform <expression>
226
226
  # Execution
227
227
  kb eval <code> [--lang js|ts] [--timeout N]
228
228
  kb test [files...] [--grep pattern]
229
- kb check [--skip-types] [--skip-lint]
229
+ kb check [--skip-types] [--skip-lint] [--detail summary|errors|full]
230
230
  kb batch
231
231
 
232
232
  # Knowledge
@@ -296,7 +296,7 @@ kb init [--force]
296
296
  │ ├── chunker/ — tree-sitter + regex code chunking
297
297
  │ ├── indexer/ — incremental file indexer
298
298
  │ ├── analyzers/ — blast-radius, deps, symbols, patterns, diagrams
299
- │ ├── tools/ — 49 tool modules (64 MCP tools)
299
+ │ ├── tools/ — 52 tool modules (64 MCP tools)
300
300
  │ ├── server/ — MCP protocol server
301
301
  │ └── cli/ — command-line interface
302
302
  ├── bin/kb.mjs — CLI entry point
@@ -466,7 +466,9 @@ Dependency results include a **confidence** level per import: `high` (ES static
466
466
  |-----------|------|----------|-------------|
467
467
  | `path` | string | **yes** | Root path |
468
468
 
469
- #### `kb_analyze_entry_points` — Find Lambda handlers, CLI bins, server starts
469
+ #### `kb_analyze_entry_points` — Find Lambda handlers, CDK constructs, test suites, package exports
470
+
471
+ Walks monorepo workspace packages (pnpm-workspace.yaml / package.json#workspaces), parses `exports` fields, detects CDK constructs and test suites.
470
472
 
471
473
  | Parameter | Type | Required | Description |
472
474
  |-----------|------|----------|-------------|
@@ -485,12 +487,13 @@ Dependency results include a **confidence** level per import: `high` (ES static
485
487
 
486
488
  | Parameter | Type | Required | Default | Description |
487
489
  |-----------|------|----------|---------|-------------|
488
- | `text` | string | **yes** | — | The text to compress |
490
+ | `text` | string | no* | — | The text to compress (provide `text` or `path`) |
491
+ | `path` | string | no* | — | File path to read server-side (avoids read_file round-trip) |
489
492
  | `query` | string | **yes** | — | Focus query — what are you trying to understand? |
490
493
  | `max_chars` | number (100–50000) | no | `3000` | Target output size in characters |
491
494
  | `segmentation` | enum | no | `paragraph` | How to split: `paragraph`, `sentence`, `line` |
492
495
 
493
- Uses embedding similarity (no LLM needed) to keep only the segments most relevant to the query. Returns compression stats (originalcompressed chars, ratio, segments kept/total) and the compressed text.
496
+ \* At least one of `text` or `path` must be provided. Using `path` is preferred it eliminates the `read_file``compact` two-call chain and prevents token doubling.
494
497
 
495
498
  #### `kb_workset` — Manage named file sets
496
499
 
@@ -641,16 +644,6 @@ Returns a ranked file list with estimated token counts, relevance %, focus line
641
644
 
642
645
  Follows imports, call sites, and references to build a relationship graph from a starting symbol or file location.
643
646
 
644
- #### `kb_find_examples` — Find real usage examples
645
-
646
- | Parameter | Type | Required | Default | Description |
647
- |-----------|------|----------|---------|-------------|
648
- | `query` | string | **yes** | — | Symbol or pattern to find examples of |
649
- | `limit` | number (1–20) | no | `5` | Maximum examples to return |
650
- | `content_type` | string | no | — | Filter by content type |
651
-
652
- Returns usage examples with file paths and code snippets from the indexed codebase.
653
-
654
647
  #### `kb_dead_symbols` — Find unused exported symbols
655
648
 
656
649
  | Parameter | Type | Required | Default | Description |
@@ -748,6 +741,18 @@ Returns structured pass/fail summary. `isError` set if any tests failed.
748
741
 
749
742
  Returns per-operation outcomes (success/failure with results or errors).
750
743
 
744
+ #### `kb_audit` — Unified project audit
745
+
746
+ Runs multiple analysis checks in a single call and returns a synthesized report with a composite score (0–100), per-check summaries, and prioritized recommendations.
747
+
748
+ | Parameter | Type | Required | Default | Description |
749
+ |-----------|------|----------|---------|-------------|
750
+ | `path` | string | no | `.` | Root path to audit |
751
+ | `checks` | string[] | no | all | Subset of checks: `structure`, `dependencies`, `patterns`, `health`, `dead_symbols`, `check`, `entry_points` |
752
+ | `detail` | enum | no | `summary` | `summary` (markdown overview) or `full` (structured JSON data) |
753
+
754
+ Returns `KBResponse<AuditData>` with `next[]` hints for follow-up actions.
755
+
751
756
  ### Git & Environment
752
757
 
753
758
  #### `kb_git_context` — Summarize Git repository state
@@ -931,13 +936,22 @@ Isolated file copies for parallel exploration. Create a lane, make changes, diff
931
936
 
932
937
  ### System
933
938
 
939
+ #### `kb_guide` — Tool discovery
940
+
941
+ | Parameter | Type | Required | Default | Description |
942
+ |-----------|------|----------|---------|-------------|
943
+ | `goal` | string | **yes** | — | What you want to accomplish |
944
+ | `max_recommendations` | number | no | 5 | Max tools to recommend (1-10) |
945
+
946
+ 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.
947
+
934
948
  #### `kb_health` — Run project health checks
935
949
 
936
950
  | Parameter | Type | Required | Default | Description |
937
951
  |-----------|------|----------|---------|-------------|
938
952
  | `path` | string | no | cwd | Root directory to check |
939
953
 
940
- Verifies package.json, tsconfig, scripts, lockfile, README, LICENSE, .gitignore.
954
+ Verifies package.json, tsconfig, scripts, lockfile, README, LICENSE, .gitignore, circular dependencies.
941
955
 
942
956
  #### `kb_queue` — Manage task queues
943
957
 
@@ -952,21 +966,18 @@ Verifies package.json, tsconfig, scripts, lockfile, README, LICENSE, .gitignore.
952
966
 
953
967
  Sequential task queues for agent operations.
954
968
 
955
- #### `kb_replay_list` — View audit trail
969
+ #### `kb_replay` — View or clear audit trail
956
970
 
957
971
  | Parameter | Type | Required | Default | Description |
958
972
  |-----------|------|----------|---------|-------------|
959
- | `last` | number | no | 20 | Number of entries to return |
960
- | `tool` | string | no | | Filter by tool name (e.g., `kb_search`) |
961
- | `source` | enum | no | — | Filter by source: `mcp` or `cli` |
962
- | `since` | string | no | — | ISO timestamp only show entries after this time |
973
+ | `action` | enum | no | `list` | `list` to view entries, `clear` to wipe the log |
974
+ | `last` | number | no | 20 | Number of entries to return (list only) |
975
+ | `tool` | string | no | — | Filter by tool name (list only) |
976
+ | `source` | enum | no | — | Filter by source: `mcp` or `cli` (list only) |
977
+ | `since` | string | no | — | ISO timestamp — only show entries after this time (list only) |
963
978
 
964
979
  Shows the audit trail of recent tool invocations. Each entry includes tool name, duration, input/output summaries, and status. Useful for debugging agent behavior.
965
980
 
966
- #### `kb_replay_clear` — Clear audit trail
967
-
968
- No parameters. Clears the entire replay log.
969
-
970
981
  ---
971
982
 
972
983
  ## MCP Resources
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vpxa/kb",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "type": "module",
5
5
  "description": "Local-first AI developer toolkit — knowledge base, code analysis, context management, and developer tools for LLM agents",
6
6
  "license": "MIT",
@@ -3,7 +3,25 @@ export declare class EntryPointAnalyzer implements IAnalyzer<AnalyzerOptions> {
3
3
  readonly name = "entry-points";
4
4
  analyze(rootPath: string, _options?: AnalyzerOptions): Promise<AnalysisResult>;
5
5
  private fromPackageJson;
6
+ /** Parse package.json `exports` field into entry points. */
7
+ private parseExportsField;
8
+ /** Resolve export value through condition maps (import > default > first string). */
9
+ private resolveExportValue;
10
+ /**
11
+ * Find all workspace package directories in a monorepo.
12
+ * Supports pnpm-workspace.yaml and package.json#workspaces.
13
+ */
14
+ private findWorkspacePackages;
15
+ /** Simple YAML parser for pnpm-workspace.yaml — extracts packages list. */
16
+ private parsePnpmWorkspaceYaml;
17
+ /**
18
+ * Expand a workspace glob like "packages/*" into actual directories
19
+ * that contain package.json files.
20
+ */
21
+ private expandWorkspaceGlob;
6
22
  private fromHandlerExports;
23
+ /** Check if a file is a test suite. */
24
+ private isTestFile;
7
25
  /** Extract a meaningful name from the file path for non-JS entry points */
8
26
  private inferNameFromFile;
9
27
  /**
@@ -1,5 +1,6 @@
1
- import{access as f,readdir as m,readFile as g}from"node:fs/promises";import{extname as d,join as l,relative as h}from"node:path";const y=new Set(["node_modules",".git","dist","build","coverage",".turbo",".cache","cdk.out","__pycache__",".venv","target","bin","obj",".gradle","venv","env"]),S=new Set(["test","tests","__tests__","spec","specs","test-utils"]),E=[/export\s+const\s+(handler|main)\s*(?::[^=]*)?\s*=/,/export\s+(?:async\s+)?function\s+(handler|main)\s*\(/,/export\s+const\s+(\w+Handler)\s*(?::[^=]*)?\s*=/,/export\s+default\s+app/,/^app\s*=\s*(?:Flask|FastAPI)\s*\(/m,/^urlpatterns\s*=\s*\[/m,/^if\s+__name__\s*==\s*['"]__main__['"]:/m,/public\s+static\s+void\s+main\s*\(\s*String/,/@SpringBootApplication/,/^func\s+main\s*\(\s*\)/m],v=[{regex:/SqsEventSource|SQSEvent|sqs/i,trigger:"SQS"},{regex:/SnsEventSource|SNSEvent|sns/i,trigger:"SNS"},{regex:/ApiGateway|APIGatewayEvent|httpApi|restApi/i,trigger:"API Gateway"},{regex:/ScheduleExpression|EventBridgeRule|schedule/i,trigger:"EventBridge Schedule"},{regex:/S3EventSource|S3Event|s3/i,trigger:"S3"},{regex:/DynamoEventSource|DynamoDBStream/i,trigger:"DynamoDB Stream"},{regex:/@RequestMapping|@GetMapping|@PostMapping/i,trigger:"HTTP Endpoint"},{regex:/http\.ListenAndServe|gin\.Default|echo\.New/i,trigger:"HTTP Server"},{regex:/app\.route\(|@app\.get|@app\.post|@router\./i,trigger:"HTTP Route"}];class A{name="entry-points";async analyze(n,e={}){const r=Date.now(),t=[],s=await this.fromPackageJson(n);t.push(...s);const i=await this.fromHandlerExports(n);return t.push(...i),{output:this.formatMarkdown(t,n),data:{entryPoints:t,total:t.length},meta:{analyzedAt:new Date().toISOString(),scope:n,fileCount:t.length,durationMs:Date.now()-r}}}async fromPackageJson(n){const e=[];try{const r=l(n,"package.json");await f(r);const t=JSON.parse(await g(r,"utf-8"));if(t.main&&e.push({name:"main",type:"main",filePath:t.main}),t.bin){const s=typeof t.bin=="string"?{[t.name??"cli"]:t.bin}:t.bin;for(const[i,c]of Object.entries(s))e.push({name:i,type:"cli",filePath:c})}t.scripts?.start&&e.push({name:"start",type:"server",filePath:t.scripts.start,trigger:"npm start"})}catch{}return e}async fromHandlerExports(n){const e=[],r=await this.collectFiles(n);for(const t of r)try{const s=await g(t,"utf-8"),i=h(n,t).replace(/\\/g,"/");if(i.split("/").some(a=>S.has(a)))continue;for(const a of E){const o=s.match(a);if(o){let p=o[1]??this.inferNameFromFile(i);(p==="handler"||p==="main")&&(p=this.deriveContextualName(i)??p);const u=/@SpringBootApplication/.test(s)?"HTTP Server":this.detectTrigger(s);e.push({name:p,type:this.inferEntryType(o[1]??p,i),filePath:i,trigger:u});break}}}catch{}return e}inferNameFromFile(n){return(n.split(/[/\\]/).pop()??"default").replace(/\.\w+$/,"")}deriveContextualName(n){const e=n.split("/").filter(s=>s!=="src"&&s!=="lib");if(e.pop(),e.length===0)return;const r=e.filter(s=>!["services","functions","lambdas","handlers","packages","apps"].includes(s));if(r.length===0)return;const t=r.slice(-2);return t.length===2&&t[1].startsWith(t[0])?t[1]:t.join("-")}inferEntryType(n,e){return n==="handler"||n==="main"||e.includes("handler")||/functions[/]/.test(e)||n.endsWith("Handler")?"lambda-handler":(e.endsWith(".py")||e.endsWith(".go")||e.endsWith(".java"),"main")}detectTrigger(n){for(const e of v)if(e.regex.test(n))return e.trigger}async collectFiles(n){const e=[],r=new Set([".ts",".tsx",".js",".jsx",".java",".py",".go",".cs",".kt",".rb",".rs",".php",".swift"]),t=async(s,i)=>{if(i>10)return;const c=await m(s,{withFileTypes:!0});for(const a of c){if(y.has(a.name)||a.name.startsWith("."))continue;const o=l(s,a.name);a.isDirectory()?await t(o,i+1):r.has(d(a.name))&&e.push(o)}};return await t(n,0),e}formatMarkdown(n,e){const r=[];if(r.push(`## Entry Points: ${e}
2
- `),r.push(`**${n.length} entry ${n.length===1?"point":"points"}** found
3
- `),n.length===0)return r.push("No entry points detected."),r.join(`
4
- `);r.push("| Name | Type | File | Trigger |"),r.push("|------|------|------|---------|");for(const t of n)r.push(`| ${t.name} | ${t.type} | ${t.filePath} | ${t.trigger??"\u2014"} |`);return r.join(`
5
- `)}}export{A as EntryPointAnalyzer};
1
+ import{access as f,readdir as h,readFile as u}from"node:fs/promises";import{extname as S,join as p,relative as d,resolve as y}from"node:path";const k=new Set(["node_modules",".git","dist","build","coverage",".turbo",".cache","cdk.out","__pycache__",".venv","target","bin","obj",".gradle","venv","env"]),w=new Set(["test","tests","__tests__","spec","specs","test-utils"]),v=[/export\s+const\s+(handler|main)\s*(?::[^=]*)?\s*=/,/export\s+(?:async\s+)?function\s+(handler|main)\s*\(/,/export\s+const\s+(\w+Handler)\s*(?::[^=]*)?\s*=/,/export\s+default\s+app/,/^app\s*=\s*(?:Flask|FastAPI)\s*\(/m,/^urlpatterns\s*=\s*\[/m,/^if\s+__name__\s*==\s*['"]__main__['"]:/m,/public\s+static\s+void\s+main\s*\(\s*String/,/@SpringBootApplication/,/^func\s+main\s*\(\s*\)/m],P=/export\s+(?:default\s+)?class\s+(\w+)\s+extends\s+(?:Construct|Stack|NestedStack|Stage)/,x=[/from\s+['"]vitest['"]/,/from\s+['"]jest['"]/,/from\s+['"]mocha['"]/,/import\s+.*['"]@jest\/globals['"]/,/require\s*\(\s*['"](?:vitest|jest|mocha)['"]\s*\)/],T=[{regex:/SqsEventSource|SQSEvent|sqs/i,trigger:"SQS"},{regex:/SnsEventSource|SNSEvent|sns/i,trigger:"SNS"},{regex:/ApiGateway|APIGatewayEvent|httpApi|restApi/i,trigger:"API Gateway"},{regex:/ScheduleExpression|EventBridgeRule|schedule/i,trigger:"EventBridge Schedule"},{regex:/S3EventSource|S3Event|s3/i,trigger:"S3"},{regex:/DynamoEventSource|DynamoDBStream/i,trigger:"DynamoDB Stream"},{regex:/@RequestMapping|@GetMapping|@PostMapping/i,trigger:"HTTP Endpoint"},{regex:/http\.ListenAndServe|gin\.Default|echo\.New/i,trigger:"HTTP Server"},{regex:/app\.route\(|@app\.get|@app\.post|@router\./i,trigger:"HTTP Route"}];class ${name="entry-points";async analyze(t,e={}){const s=Date.now(),n=[],i=await this.findWorkspacePackages(t);if(i.length>0)for(const a of i){const c=await this.fromPackageJson(a,t);n.push(...c)}else{const a=await this.fromPackageJson(t,t);n.push(...a)}const r=await this.fromHandlerExports(t);return n.push(...r),{output:this.formatMarkdown(n,t),data:{entryPoints:n,total:n.length},meta:{analyzedAt:new Date().toISOString(),scope:t,fileCount:n.length,durationMs:Date.now()-s}}}async fromPackageJson(t,e){const s=[],n=d(e,t).replace(/\\/g,"/")||".";try{const i=p(t,"package.json");await f(i);const r=JSON.parse(await u(i,"utf-8")),o=n==="."?"":`${n}/`;if(r.main&&s.push({name:r.name?`${r.name}:main`:"main",type:"main",filePath:`${o}${r.main}`}),r.bin){const a=typeof r.bin=="string"?{[r.name??"cli"]:r.bin}:r.bin;for(const[c,g]of Object.entries(a))s.push({name:c,type:"cli",filePath:`${o}${g}`})}if(r.exports){const a=this.parseExportsField(r.exports,r.name??n,o);s.push(...a)}r.scripts?.start&&s.push({name:r.name?`${r.name}:start`:"start",type:"server",filePath:r.scripts.start,trigger:"npm start"})}catch{}return s}parseExportsField(t,e,s){const n=[];if(typeof t=="string")return n.push({name:e,type:"main",filePath:`${s}${t}`}),n;if(typeof t!="object"||t===null)return n;for(const[i,r]of Object.entries(t)){if(!i.startsWith("."))continue;const o=i==="."?e:`${e}/${i.slice(2)}`,a=this.resolveExportValue(r);a&&n.push({name:o,type:"main",filePath:`${s}${a}`})}return n}resolveExportValue(t){if(typeof t=="string")return t;if(typeof t!="object"||t===null)return;const e=t;for(const s of["import","default","require"])if(typeof e[s]=="string")return e[s];for(const s of Object.values(e))if(typeof s=="string")return s}async findWorkspacePackages(t){const e=[];try{const s=p(t,"pnpm-workspace.yaml");await f(s);const n=await u(s,"utf-8"),i=this.parsePnpmWorkspaceYaml(n);for(const r of i){const o=await this.expandWorkspaceGlob(t,r);e.push(...o)}if(e.length>0)return e}catch{}try{const s=p(t,"package.json"),n=JSON.parse(await u(s,"utf-8")),i=Array.isArray(n.workspaces)?n.workspaces:n.workspaces?.packages??[];for(const r of i){const o=await this.expandWorkspaceGlob(t,r);e.push(...o)}}catch{}return e}parsePnpmWorkspaceYaml(t){const e=[];let s=!1;for(const n of t.split(`
2
+ `)){const i=n.trim();if(i==="packages:"){s=!0;continue}if(s){if(i.startsWith("- "))e.push(i.slice(2).replace(/^['"]|['"]$/g,""));else if(i&&!i.startsWith("#"))break}}return e}async expandWorkspaceGlob(t,e){const s=[],n=e.indexOf("*");if(n===-1){const r=y(t,e);try{await f(p(r,"package.json")),s.push(r)}catch{}return s}const i=y(t,e.slice(0,n));try{const r=await h(i,{withFileTypes:!0});for(const o of r){if(!o.isDirectory()||k.has(o.name))continue;const a=p(i,o.name);try{await f(p(a,"package.json")),s.push(a)}catch{}}}catch{}return s}async fromHandlerExports(t){const e=[],s=await this.collectFiles(t);for(const n of s)try{const i=await u(n,"utf-8"),r=d(t,n).replace(/\\/g,"/");if(!r.split("/").some(c=>w.has(c))){let c=!1;for(const g of v){const m=i.match(g);if(m){let l=m[1]??this.inferNameFromFile(r);(l==="handler"||l==="main")&&(l=this.deriveContextualName(r)??l);const E=/@SpringBootApplication/.test(i)?"HTTP Server":this.detectTrigger(i);e.push({name:l,type:this.inferEntryType(m[1]??l,r),filePath:r,trigger:E}),c=!0;break}}if(!c){const g=i.match(P);g&&e.push({name:g[1],type:"cdk-construct",filePath:r,trigger:"CDK Construct"})}}this.isTestFile(r,i)&&e.push({name:this.inferNameFromFile(r),type:"test",filePath:r,trigger:"Test Suite"})}catch{}return e}isTestFile(t,e){return/\.(test|spec)\.[jt]sx?$/.test(t)?x.some(s=>s.test(e)):!1}inferNameFromFile(t){return(t.split(/[/\\]/).pop()??"default").replace(/\.\w+$/,"")}deriveContextualName(t){const e=t.split("/").filter(i=>i!=="src"&&i!=="lib");if(e.pop(),e.length===0)return;const s=e.filter(i=>!["services","functions","lambdas","handlers","packages","apps"].includes(i));if(s.length===0)return;const n=s.slice(-2);return n.length===2&&n[1].startsWith(n[0])?n[1]:n.join("-")}inferEntryType(t,e){return t==="handler"||t==="main"||e.includes("handler")||/functions[/]/.test(e)||t.endsWith("Handler")?"lambda-handler":(e.endsWith(".py")||e.endsWith(".go")||e.endsWith(".java"),"main")}detectTrigger(t){for(const e of T)if(e.regex.test(t))return e.trigger}async collectFiles(t){const e=[],s=new Set([".ts",".tsx",".js",".jsx",".java",".py",".go",".cs",".kt",".rb",".rs",".php",".swift"]),n=async(i,r)=>{if(r>10)return;const o=await h(i,{withFileTypes:!0});for(const a of o){if(k.has(a.name)||a.name.startsWith("."))continue;const c=p(i,a.name);a.isDirectory()?await n(c,r+1):s.has(S(a.name))&&e.push(c)}};return await n(t,0),e}formatMarkdown(t,e){const s=[];if(s.push(`## Entry Points: ${e}
3
+ `),s.push(`**${t.length} entry ${t.length===1?"point":"points"}** found
4
+ `),t.length===0)return s.push("No entry points detected."),s.join(`
5
+ `);const n=new Map;for(const o of t){const a=n.get(o.type)??[];a.push(o),n.set(o.type,a)}const i=["lambda-handler","main","server","cli","bin","cdk-construct","test"],r=[...n.entries()].sort((o,a)=>i.indexOf(o[0])-i.indexOf(a[0]));s.push("| Name | Type | File | Trigger |"),s.push("|------|------|------|---------|");for(const[,o]of r)for(const a of o)s.push(`| ${a.name} | ${a.type} | ${a.filePath} | ${a.trigger??"\u2014"} |`);return s.join(`
6
+ `)}}export{$ as EntryPointAnalyzer};
@@ -1,4 +1,4 @@
1
- import{access as P,readdir as h,readFile as C}from"node:fs/promises";import{extname as m,join as u,relative as S}from"node:path";const y=new Set(["node_modules",".git","dist","build","coverage",".turbo",".cache","cdk.out","__pycache__",".venv","target","bin","obj",".gradle","venv","env"]),v=[{dirs:["adapters","ports"],pattern:"Hexagonal Architecture",description:"Ports & adapters (hexagonal) separation"},{dirs:["domain","infrastructure","application"],pattern:"Clean Architecture",description:"Layered with domain/infrastructure separation"},{dirs:["controllers","models"],pattern:"MVC Pattern",description:"Model-View-Controller structure"},{dirs:["repositories"],pattern:"Repository Pattern",description:"Data access abstraction via repositories"},{dirs:["factories"],pattern:"Factory Pattern",description:"Object creation via factories"},{dirs:["handlers"],pattern:"Handler Pattern",description:"Event/request handler separation"},{dirs:["middleware"],pattern:"Middleware Pattern",description:"Request pipeline middleware"},{dirs:["hooks"],pattern:"React Hooks",description:"Custom React hooks for logic reuse"},{dirs:["components"],pattern:"Component Architecture",description:"UI component-based structure"},{dirs:["stacks","constructs"],pattern:"CDK IaC",description:"AWS CDK infrastructure as code"},{dirs:["lambdas","functions"],pattern:"Serverless",description:"Serverless function architecture"}];function A(g){if(g.length<=3)return g;const r=new Map;for(const e of g){const t=e.split("/"),n=t.length>1?t.slice(0,-1).join("/"):".",a=r.get(n);a?a.push(e):r.set(n,[e])}const o=[];for(const[e,t]of r)t.length>=3?o.push(`${e}/ (${t.length} files)`):o.push(...t);return o.slice(0,5)}const w=[{regex:/container\.register|@injectable|@inject/i,pattern:"Dependency Injection",description:"IoC container or DI decorators"},{regex:/\.pipe\(|Observable|BehaviorSubject/i,pattern:"Reactive (RxJS)",description:"Reactive programming with observables",lang:"js"},{regex:/createContext|useContext/i,pattern:"React Context",description:"React Context API for state sharing",lang:"js"},{regex:/createSlice|configureStore/i,pattern:"Redux Toolkit",description:"Redux state management",lang:"js"},{regex:/defineStore|usePinia/i,pattern:"Pinia Store",description:"Vue Pinia state management",lang:"js"},{regex:/\.(test|spec)\.[jt]sx?|describe\s*\(|\bit\s*\([\s'"]/i,pattern:"Test Suite",description:"Unit/integration test files"},{regex:/@SpringBootApplication|@EnableAutoConfiguration/,pattern:"Spring Boot",description:"Spring Boot application framework",lang:"java",definitive:!0},{regex:/@Autowired|@Component|@Service|@Repository|@Controller/,pattern:"Spring DI",description:"Spring dependency injection",lang:"java"},{regex:/@RestController|@RequestMapping|@GetMapping|@PostMapping/,pattern:"Spring REST",description:"Spring REST API controllers",lang:"java"},{regex:/app\s*=\s*Flask\s*\(|@app\.route/,pattern:"Flask",description:"Flask web framework",lang:"python"},{regex:/app\s*=\s*FastAPI\s*\(|@app\.get|@app\.post/,pattern:"FastAPI",description:"FastAPI web framework",lang:"python"},{regex:/func\s+main\s*\(\s*\)|http\.ListenAndServe/,pattern:"Go Application",description:"Go main application",lang:"go"}];class D{name="patterns";async analyze(r,o={}){const e=Date.now(),t=await this.collectDirectories(r),n=this.detectDirectoryPatterns(t,r),a=await this.collectCodeFiles(r),i=await this.detectCodePatterns(a,r),s=[...n,...i],c=await this.detectConfigPatterns(r),p=c.find(l=>l.pattern==="Maven"||l.pattern==="Gradle"||l.pattern==="Gradle (Kotlin DSL)"||l.pattern==="Node.js Project"||l.pattern==="Go Module"||l.pattern==="Rust (Cargo)"),f=new Set(["Ruby (Bundler)","PHP (Composer)","Swift Package","SBT"]);for(const l of c)p&&f.has(l.pattern)||s.push(l);return{output:this.formatMarkdown(s,r),data:{patterns:s,total:s.length},meta:{analyzedAt:new Date().toISOString(),scope:r,fileCount:a.length,durationMs:Date.now()-e}}}async collectDirectories(r){const o=[],e=async(t,n)=>{if(n>5)return;const a=await h(t,{withFileTypes:!0});for(const i of a){if(!i.isDirectory()||y.has(i.name)||i.name.startsWith("."))continue;const s=u(t,i.name);o.push(i.name),await e(s,n+1)}};return await e(r,0),o}async collectCodeFiles(r){const o=[],e=new Set([".ts",".tsx",".js",".jsx",".java",".py",".go",".cs",".kt",".scala",".rb",".rs",".php",".swift"]),t=async n=>{const a=await h(n,{withFileTypes:!0});for(const i of a){if(y.has(i.name)||i.name.startsWith("."))continue;const s=u(n,i.name);i.isDirectory()?await t(s):e.has(m(i.name))&&o.push(s)}};return await t(r),o}detectDirectoryPatterns(r,o){const e=new Set(r.map(n=>n.toLowerCase())),t=[];for(const n of v){const a=n.dirs.filter(i=>e.has(i));a.length!==0&&(n.dirs.length>1&&a.length<2||t.push({pattern:n.pattern,description:n.description,locations:a.map(i=>`${i}/`),confidence:a.length===n.dirs.length?"high":"medium"}))}return t}async detectCodePatterns(r,o){const e=[],t={},n=r.filter(s=>/Application\.\w+$|Main\.\w+$|app\.\w+$|main\.\w+$/i.test(s)||/Controller|Service|Handler|Router/i.test(s)),a=r.filter(s=>!n.includes(s)),i=[...n.slice(0,50),...a.slice(0,150)];for(const s of i)try{const c=await C(s,"utf-8"),p=m(s).toLowerCase(),f=p===".java"||p===".kt"||p===".scala"?"java":p===".py"?"python":p===".go"?"go":"js";for(const d of w)d.lang&&d.lang!==f||d.regex.test(c)&&(t[d.pattern]||(t[d.pattern]=new Set),t[d.pattern].add(S(o,s).replace(/\\/g,"/")))}catch{}for(const s of w){const c=t[s.pattern];if(c&&c.size>0){const p=A([...c]);e.push({pattern:s.pattern,description:s.description,locations:p,confidence:s.definitive||c.size>=3?"high":c.size>=2?"medium":"low"})}}return e}async detectConfigPatterns(r){const o=[],e=[{file:"Dockerfile",pattern:"Docker",description:"Containerized application"},{file:"docker-compose.yml",pattern:"Docker Compose",description:"Container orchestration"},{file:"cdk.json",pattern:"AWS CDK",description:"AWS CDK infrastructure as code"},{file:"terraform.tf",pattern:"Terraform",description:"Terraform IaC"},{file:"main.tf",pattern:"Terraform",description:"Terraform IaC"}];for(const t of e)try{await P(u(r,t.file)),o.push({pattern:t.pattern,description:t.description,locations:[t.file],confidence:"high"})}catch{}return o}formatMarkdown(r,o){const e=[];e.push(`## Patterns Detected: ${o}
1
+ import{access as P,readdir as h,readFile as C}from"node:fs/promises";import{extname as m,join as f,relative as S}from"node:path";const w=new Set(["node_modules",".git","dist","build","coverage",".turbo",".cache","cdk.out","__pycache__",".venv","target","bin","obj",".gradle","venv","env"]),v=[{dirs:["adapters","ports"],pattern:"Hexagonal Architecture",description:"Ports & adapters (hexagonal) separation"},{dirs:["domain","infrastructure","application"],pattern:"Clean Architecture",description:"Layered with domain/infrastructure separation"},{dirs:["controllers","models"],pattern:"MVC Pattern",description:"Model-View-Controller structure"},{dirs:["repositories"],pattern:"Repository Pattern",description:"Data access abstraction via repositories"},{dirs:["factories"],pattern:"Factory Pattern",description:"Object creation via factories"},{dirs:["handlers"],pattern:"Handler Pattern",description:"Event/request handler separation"},{dirs:["middleware"],pattern:"Middleware Pattern",description:"Request pipeline middleware"},{dirs:["hooks"],pattern:"React Hooks",description:"Custom React hooks for logic reuse"},{dirs:["components"],pattern:"Component Architecture",description:"UI component-based structure"},{dirs:["stacks","constructs"],pattern:"CDK IaC",description:"AWS CDK infrastructure as code"},{dirs:["lambdas","functions"],pattern:"Serverless",description:"Serverless function architecture"}];function x(g){if(g.length<=3)return g;const r=new Map;for(const e of g){const t=e.split("/"),n=t.length>1?t.slice(0,-1).join("/"):".",a=r.get(n);a?a.push(e):r.set(n,[e])}const o=[];for(const[e,t]of r)t.length>=3?o.push(`${e}/ (${t.length} files)`):o.push(...t);return o.slice(0,5)}const y=[{regex:/container\.register|@injectable|@inject/i,pattern:"Dependency Injection",description:"IoC container or DI decorators"},{regex:/\.pipe\(|Observable|BehaviorSubject/i,pattern:"Reactive (RxJS)",description:"Reactive programming with observables",lang:"js"},{regex:/createContext|useContext/i,pattern:"React Context",description:"React Context API for state sharing",lang:"js"},{regex:/createSlice|configureStore/i,pattern:"Redux Toolkit",description:"Redux state management",lang:"js"},{regex:/defineStore|usePinia/i,pattern:"Pinia Store",description:"Vue Pinia state management",lang:"js"},{regex:/\.(test|spec)\.[jt]sx?|describe\s*\(|\bit\s*\([\s'"]/i,pattern:"Test Suite",description:"Unit/integration test files"},{regex:/@SpringBootApplication|@EnableAutoConfiguration/,pattern:"Spring Boot",description:"Spring Boot application framework",lang:"java",definitive:!0},{regex:/@Autowired|@Component|@Service|@Repository|@Controller/,pattern:"Spring DI",description:"Spring dependency injection",lang:"java"},{regex:/@RestController|@RequestMapping|@GetMapping|@PostMapping/,pattern:"Spring REST",description:"Spring REST API controllers",lang:"java"},{regex:/app\s*=\s*Flask\s*\(|@app\.route/,pattern:"Flask",description:"Flask web framework",lang:"python"},{regex:/app\s*=\s*FastAPI\s*\(|@app\.get|@app\.post/,pattern:"FastAPI",description:"FastAPI web framework",lang:"python"},{regex:/func\s+main\s*\(\s*\)|http\.ListenAndServe/,pattern:"Go Application",description:"Go main application",lang:"go"},{regex:/export\s+(?:async\s+)?function\s+create[A-Z]\w+/,pattern:"Factory",description:"Object creation via create*() functions",lang:"js"},{regex:/(?:export\s+)?function\s+wrap[A-Z]\w+/,pattern:"Wrapper/Decorator",description:"Higher-order function wrapping",lang:"js"},{regex:/(?:const|let)\s+\w+\s*=\s*new\s+(?:Map|WeakMap)\s*[<(]/,pattern:"Singleton Cache",description:"Module-level cache with lazy initialization",lang:"js"},{regex:/Record<string,\s*(?:\w+)?Handler>|\.(?:get|post|put|delete)\s*\(/,pattern:"Router/Dispatcher",description:"Request routing/dispatch table",lang:"js"},{regex:/export\s+(?:default\s+)?class\s+\w+\s+extends\s+(?:Construct|Stack|NestedStack|Stage)/,pattern:"CDK Construct",description:"AWS CDK infrastructure construct",lang:"js",definitive:!0}];class D{name="patterns";async analyze(r,o={}){const e=Date.now(),t=await this.collectDirectories(r),n=this.detectDirectoryPatterns(t,r),a=await this.collectCodeFiles(r),i=await this.detectCodePatterns(a,r),s=[...n,...i],c=await this.detectConfigPatterns(r),p=c.find(l=>l.pattern==="Maven"||l.pattern==="Gradle"||l.pattern==="Gradle (Kotlin DSL)"||l.pattern==="Node.js Project"||l.pattern==="Go Module"||l.pattern==="Rust (Cargo)"),u=new Set(["Ruby (Bundler)","PHP (Composer)","Swift Package","SBT"]);for(const l of c)p&&u.has(l.pattern)||s.push(l);return{output:this.formatMarkdown(s,r),data:{patterns:s,total:s.length},meta:{analyzedAt:new Date().toISOString(),scope:r,fileCount:a.length,durationMs:Date.now()-e}}}async collectDirectories(r){const o=[],e=async(t,n)=>{if(n>5)return;const a=await h(t,{withFileTypes:!0});for(const i of a){if(!i.isDirectory()||w.has(i.name)||i.name.startsWith("."))continue;const s=f(t,i.name);o.push(i.name),await e(s,n+1)}};return await e(r,0),o}async collectCodeFiles(r){const o=[],e=new Set([".ts",".tsx",".js",".jsx",".java",".py",".go",".cs",".kt",".scala",".rb",".rs",".php",".swift"]),t=async n=>{const a=await h(n,{withFileTypes:!0});for(const i of a){if(w.has(i.name)||i.name.startsWith("."))continue;const s=f(n,i.name);i.isDirectory()?await t(s):e.has(m(i.name))&&o.push(s)}};return await t(r),o}detectDirectoryPatterns(r,o){const e=new Set(r.map(n=>n.toLowerCase())),t=[];for(const n of v){const a=n.dirs.filter(i=>e.has(i));a.length!==0&&(n.dirs.length>1&&a.length<2||t.push({pattern:n.pattern,description:n.description,locations:a.map(i=>`${i}/`),confidence:a.length===n.dirs.length?"high":"medium"}))}return t}async detectCodePatterns(r,o){const e=[],t={},n=r.filter(s=>/Application\.\w+$|Main\.\w+$|app\.\w+$|main\.\w+$/i.test(s)||/Controller|Service|Handler|Router/i.test(s)),a=r.filter(s=>!n.includes(s)),i=[...n.slice(0,50),...a.slice(0,150)];for(const s of i)try{const c=await C(s,"utf-8"),p=m(s).toLowerCase(),u=p===".java"||p===".kt"||p===".scala"?"java":p===".py"?"python":p===".go"?"go":"js";for(const d of y)d.lang&&d.lang!==u||d.regex.test(c)&&(t[d.pattern]||(t[d.pattern]=new Set),t[d.pattern].add(S(o,s).replace(/\\/g,"/")))}catch{}for(const s of y){const c=t[s.pattern];if(c&&c.size>0){const p=x([...c]);e.push({pattern:s.pattern,description:s.description,locations:p,confidence:s.definitive||c.size>=3?"high":c.size>=2?"medium":"low"})}}return e}async detectConfigPatterns(r){const o=[],e=[{file:"Dockerfile",pattern:"Docker",description:"Containerized application"},{file:"docker-compose.yml",pattern:"Docker Compose",description:"Container orchestration"},{file:"cdk.json",pattern:"AWS CDK",description:"AWS CDK infrastructure as code"},{file:"terraform.tf",pattern:"Terraform",description:"Terraform IaC"},{file:"main.tf",pattern:"Terraform",description:"Terraform IaC"}];for(const t of e)try{await P(f(r,t.file)),o.push({pattern:t.pattern,description:t.description,locations:[t.file],confidence:"high"})}catch{}return o}formatMarkdown(r,o){const e=[];e.push(`## Patterns Detected: ${o}
2
2
  `),e.push(`**${r.length} patterns** found
3
3
  `);const t={high:[],medium:[],low:[]};for(const n of r)t[n.confidence].push(n);for(const[n,a]of Object.entries(t))if(a.length!==0){e.push(`### ${n.charAt(0).toUpperCase()+n.slice(1)} Confidence
4
4
  `);for(const i of a)e.push(`- **${i.pattern}**: ${i.description}`),e.push(` Locations: ${i.locations.slice(0,5).join(", ")}`);e.push("")}return e.join(`
@@ -78,7 +78,7 @@ export interface PatternMatch {
78
78
  }
79
79
  export interface EntryPoint {
80
80
  name: string;
81
- type: 'lambda-handler' | 'main' | 'bin' | 'server' | 'cli';
81
+ type: 'lambda-handler' | 'main' | 'bin' | 'server' | 'cli' | 'test' | 'cdk-construct';
82
82
  filePath: string;
83
83
  trigger?: string;
84
84
  }
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * `kb init` — scaffold a knowledge base in the current directory.
3
3
  * Creates kb.config.json, .gitignore entry, optional IDE config,
4
- * and agent instruction files (.github/copilot-instructions.md, AGENTS.md).
4
+ * agent instruction files (.github/copilot-instructions.md, AGENTS.md),
5
+ * and skills/knowledge-base/SKILL.md.
5
6
  */
6
7
  export declare function initProject(options: {
7
8
  force: boolean;