@namzu/sdk 52.1.0 → 52.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +1 -1
  3. package/dist/connector/tools/adapter.d.ts +2 -2
  4. package/dist/contracts/a2a.d.ts +92 -92
  5. package/dist/manager/resident/learning.d.ts +6 -6
  6. package/dist/manager/resident/store.d.ts +4 -4
  7. package/dist/pals/activity/subscription-schema.d.ts +48 -48
  8. package/dist/pals/communication/ingress-schema.d.ts +192 -192
  9. package/dist/pals/communication/schema.d.ts +18 -18
  10. package/dist/peers/protocol.d.ts +36 -36
  11. package/dist/public-runtime.d.ts +1 -0
  12. package/dist/public-runtime.d.ts.map +1 -1
  13. package/dist/public-runtime.js.map +1 -1
  14. package/dist/public-tools.d.ts +1 -0
  15. package/dist/public-tools.d.ts.map +1 -1
  16. package/dist/public-tools.js +1 -0
  17. package/dist/public-tools.js.map +1 -1
  18. package/dist/runtime/query/executor.d.ts +1 -0
  19. package/dist/runtime/query/executor.d.ts.map +1 -1
  20. package/dist/runtime/query/executor.js +1 -0
  21. package/dist/runtime/query/executor.js.map +1 -1
  22. package/dist/runtime/query/index.d.ts +2 -0
  23. package/dist/runtime/query/index.d.ts.map +1 -1
  24. package/dist/runtime/query/index.js +1 -0
  25. package/dist/runtime/query/index.js.map +1 -1
  26. package/dist/runtime/query/tooling.d.ts +1 -0
  27. package/dist/runtime/query/tooling.d.ts.map +1 -1
  28. package/dist/runtime/query/tooling.js +1 -0
  29. package/dist/runtime/query/tooling.js.map +1 -1
  30. package/dist/tools/builtins/browser.d.ts +4 -4
  31. package/dist/tools/builtins/code-analysis.d.ts +49 -0
  32. package/dist/tools/builtins/code-analysis.d.ts.map +1 -0
  33. package/dist/tools/builtins/code-analysis.js +409 -0
  34. package/dist/tools/builtins/code-analysis.js.map +1 -0
  35. package/dist/tools/builtins/computer-use.d.ts +24 -24
  36. package/dist/tools/builtins/index.d.ts +1 -0
  37. package/dist/tools/builtins/index.d.ts.map +1 -1
  38. package/dist/tools/builtins/index.js +1 -0
  39. package/dist/tools/builtins/index.js.map +1 -1
  40. package/dist/tools/builtins/lsp.d.ts +1 -1
  41. package/dist/tools/builtins/skill.d.ts +2 -2
  42. package/dist/types/code-analysis/index.d.ts +299 -0
  43. package/dist/types/code-analysis/index.d.ts.map +1 -0
  44. package/dist/types/code-analysis/index.js +30 -0
  45. package/dist/types/code-analysis/index.js.map +1 -0
  46. package/dist/types/plugin/index.d.ts +6 -6
  47. package/dist/types/session/records.d.ts +127 -127
  48. package/dist/types/tool/index.d.ts +9 -0
  49. package/dist/types/tool/index.d.ts.map +1 -1
  50. package/dist/types/tool/index.js.map +1 -1
  51. package/package.json +2 -2
  52. package/src/public-runtime.ts +25 -0
  53. package/src/public-tools.ts +5 -0
  54. package/src/runtime/query/executor.ts +2 -0
  55. package/src/runtime/query/index.ts +3 -0
  56. package/src/runtime/query/tooling.ts +2 -0
  57. package/src/tools/builtins/code-analysis.ts +486 -0
  58. package/src/tools/builtins/index.ts +5 -0
  59. package/src/types/code-analysis/index.ts +325 -0
  60. package/src/types/tool/index.ts +9 -0
@@ -0,0 +1,325 @@
1
+ /**
2
+ * The seam a semantic code index arrives on.
3
+ *
4
+ * Declared in the SDK and implemented in `@namzu/analysis`, the same split
5
+ * `CodeNavigationProvider` uses with `@namzu/lsp`: the kernel owns the shape a
6
+ * tool programs against, the optional package owns the parser and the store
7
+ * that answer. A host constructs one and puts it on the tool context — there
8
+ * is no discovery step.
9
+ *
10
+ * Kept here rather than imported from `@namzu/analysis` because the
11
+ * dependency direction forbids it: `sdk ← analysis`, never the other way.
12
+ *
13
+ * ## What this answers that `grep` and a language server do not
14
+ *
15
+ * `grep` finds a string and says nothing of the function around it. A
16
+ * language server resolves a symbol the project's own types can see, and has
17
+ * nothing to say about a 40 MB bundle with no types and a hundred
18
+ * single-letter names. This index is for the second case: *which function
19
+ * contains this literal, what is its exact source, and who calls it by name*,
20
+ * over code nobody wrote for you to read.
21
+ *
22
+ * ## Positions
23
+ *
24
+ * Lines and columns are ONE-based, and columns count UTF-16 code units, which
25
+ * is what a JavaScript string index is. A character outside the Basic
26
+ * Multilingual Plane therefore takes two columns. `start` / `end` are the
27
+ * same UTF-16 offsets into the file's text, half-open. A line ends at `\n`.
28
+ */
29
+
30
+ /**
31
+ * How much of the question the answer covers.
32
+ *
33
+ * Two cases, and the second carries its reasons. `partial` is not a failure —
34
+ * the answer is true as far as it goes — but a caller deciding "nothing
35
+ * calls this" from a partial answer is guessing, and the reasons say what is
36
+ * missing (a file that did not parse, a file that changed since it was
37
+ * indexed, a page cut off by `limit`).
38
+ */
39
+ export type AnalysisCoverage =
40
+ | { readonly status: 'complete' }
41
+ | { readonly status: 'partial'; readonly reasons: readonly string[] }
42
+
43
+ /**
44
+ * The evidence behind an answer, in three parts.
45
+ *
46
+ * - `observed`: what the index read out of the files, stated as fact.
47
+ * - `inferred`: what was concluded rather than read. A callee matched by
48
+ * its TEXT is an inference — the index does no scope analysis, so two
49
+ * unrelated functions called `run` are the same callee to it.
50
+ * - `coverage`: whether the answer is the whole answer.
51
+ *
52
+ * Every successful result carries one. An answer without it reads as
53
+ * certain, and the cases this package exists for are the ones where it is
54
+ * not.
55
+ */
56
+ export interface AnalysisEvidence {
57
+ readonly observed: readonly string[]
58
+ readonly inferred: readonly string[]
59
+ readonly coverage: AnalysisCoverage
60
+ }
61
+
62
+ /**
63
+ * What a query answers. Three cases, closed, as with `CodeNavigationResult`:
64
+ * `unsupported` is "this index does not do that", `failed` is "something
65
+ * broke", and neither is an empty page. An empty page means "I looked and
66
+ * there are none", the answer a deletion depends on.
67
+ */
68
+ export type CodeAnalysisResult<T> =
69
+ | { readonly kind: 'ok'; readonly value: T; readonly evidence: AnalysisEvidence }
70
+ | { readonly kind: 'unsupported'; readonly reason: string }
71
+ | { readonly kind: 'failed'; readonly error: string }
72
+
73
+ /**
74
+ * One page of a larger answer. `total` is the count across ALL pages, so a
75
+ * caller can tell a complete list from the first slice of a long one;
76
+ * `nextCursor` is absent on the last page and is opaque — pass it back
77
+ * unchanged.
78
+ */
79
+ export interface AnalysisPage<T> {
80
+ readonly items: readonly T[]
81
+ readonly total: number
82
+ readonly nextCursor?: string
83
+ }
84
+
85
+ /**
86
+ * What every request may carry beyond its own fields.
87
+ *
88
+ * `signal` stops the call: an index run in progress is abandoned (what it had
89
+ * already committed stays, so the next call continues from there), and a call
90
+ * still queued behind another never starts. Without it nothing a user does,
91
+ * Esc included, can stop a multi-second index of a large tree.
92
+ */
93
+ export interface AnalysisCallOptions {
94
+ readonly signal?: AbortSignal
95
+ }
96
+
97
+ /** The paging arguments every list-returning request takes. */
98
+ export interface AnalysisPaging extends AnalysisCallOptions {
99
+ /** Items per page. The provider clamps it to its own maximum. */
100
+ readonly limit?: number
101
+ /** The previous page's `nextCursor`. */
102
+ readonly cursor?: string
103
+ }
104
+
105
+ export type AnalysisFunctionKind =
106
+ | 'declaration'
107
+ | 'expression'
108
+ | 'arrow'
109
+ | 'method'
110
+ | 'getter'
111
+ | 'setter'
112
+ | 'constructor'
113
+
114
+ /**
115
+ * A function, located. `id` is valid until its file changes and is then
116
+ * re-issued: do not keep one across an `index` that re-read the file.
117
+ */
118
+ export interface AnalysisFunction {
119
+ readonly id: number
120
+ /** `null` for an anonymous function with nothing to infer a name from. */
121
+ readonly name: string | null
122
+ readonly kind: AnalysisFunctionKind
123
+ /** Absolute path. */
124
+ readonly path: string
125
+ readonly line: number
126
+ readonly column: number
127
+ readonly endLine: number
128
+ readonly start: number
129
+ readonly end: number
130
+ }
131
+
132
+ /** A piece of a file's source, with the honesty about a cut. */
133
+ export interface AnalysisSourceSlice {
134
+ readonly text: string
135
+ /** The full length in UTF-16 units, whether or not all of it is in `text`. */
136
+ readonly chars: number
137
+ /** `true` when `text` is shorter than `chars` because of the size cap. */
138
+ readonly truncated: boolean
139
+ }
140
+
141
+ export interface IndexRequest extends AnalysisCallOptions {
142
+ /** Absolute directory the index belongs to. */
143
+ readonly root: string
144
+ /**
145
+ * Index only this file or directory under `root`, instead of all of it.
146
+ *
147
+ * The way to make progress on a root too big to index whole (a home
148
+ * directory): a call that stops at its limits says so, and the next step is
149
+ * a narrower `scope`. Work from earlier calls is kept.
150
+ */
151
+ readonly scope?: string
152
+ /** Re-read every file, ignoring size / mtime / hash. */
153
+ readonly force?: boolean
154
+ }
155
+
156
+ export interface IndexSummary {
157
+ readonly root: string
158
+ /** Whether the index lives on disk; `false` for an in-memory fallback. */
159
+ readonly persisted: boolean
160
+ readonly files: {
161
+ readonly indexed: number
162
+ /** Parsed this call (new or changed). */
163
+ readonly parsed: number
164
+ /** Seen and left alone: same size and mtime, or same content hash. */
165
+ readonly unchanged: number
166
+ readonly removed: number
167
+ readonly skipped: number
168
+ readonly withParseErrors: number
169
+ }
170
+ /** Why files were skipped, as reason → count. */
171
+ readonly skippedReasons: Readonly<Record<string, number>>
172
+ readonly functions: number
173
+ readonly strings: number
174
+ readonly calls: number
175
+ readonly durationMs: number
176
+ /**
177
+ * Why this call stopped before covering `scope`, when it did: a time or
178
+ * directory limit. Present means the index is partial; the text names the
179
+ * next step.
180
+ */
181
+ readonly truncated?: string
182
+ }
183
+
184
+ export interface FindLiteralRequest extends AnalysisPaging {
185
+ readonly root: string
186
+ /** The substring to look for inside string and template literals. */
187
+ readonly text: string
188
+ /** Absolute file or directory to restrict the search to. */
189
+ readonly path?: string
190
+ /** Default `true`. */
191
+ readonly caseSensitive?: boolean
192
+ }
193
+
194
+ export interface AnalysisLiteralHit {
195
+ readonly path: string
196
+ readonly line: number
197
+ readonly column: number
198
+ readonly start: number
199
+ readonly end: number
200
+ readonly kind: 'string' | 'template' | 'key'
201
+ /** The literal's value, cut to a preview. */
202
+ readonly value: string
203
+ readonly valueTruncated: boolean
204
+ /** The innermost function around it; absent at the top level of a file. */
205
+ readonly function?: AnalysisFunction
206
+ /**
207
+ * Present when the file this came from no longer matches the index: the
208
+ * position may be off (`changed`) or the file may be gone (`deleted`).
209
+ */
210
+ readonly stale?: 'changed' | 'deleted'
211
+ }
212
+
213
+ export interface EnclosingFunctionRequest extends AnalysisCallOptions {
214
+ readonly root: string
215
+ readonly path: string
216
+ readonly line: number
217
+ readonly column?: number
218
+ /** Cap on the source slice, in UTF-16 units. */
219
+ readonly maxChars?: number
220
+ }
221
+
222
+ export interface AnalysisEnclosingFunction {
223
+ /** `null` when the position is not inside any function — a real answer. */
224
+ readonly function: AnalysisFunction | null
225
+ /** The function's parents, innermost first. */
226
+ readonly parents: readonly AnalysisFunction[]
227
+ readonly source?: AnalysisSourceSlice
228
+ }
229
+
230
+ export interface FunctionSourceRequest extends AnalysisPaging {
231
+ readonly root: string
232
+ /** A function id from an earlier answer. */
233
+ readonly id?: number
234
+ /** Alternatively, a file and a name; several functions can share one. */
235
+ readonly path?: string
236
+ readonly name?: string
237
+ readonly maxChars?: number
238
+ }
239
+
240
+ export interface AnalysisFunctionSource {
241
+ readonly function: AnalysisFunction
242
+ readonly parents: readonly AnalysisFunction[]
243
+ readonly source: AnalysisSourceSlice
244
+ }
245
+
246
+ export interface CallersOfRequest extends AnalysisPaging {
247
+ readonly root: string
248
+ /** The callee text: `foo`, `obj.foo`, `this.foo`. */
249
+ readonly name: string
250
+ /**
251
+ * `file` looks in `path` only and is the default, because a callee matched
252
+ * by text is far more likely to be the one you mean inside one file than
253
+ * across a bundle of unrelated modules that reuse short names.
254
+ */
255
+ readonly scope?: 'file' | 'workspace'
256
+ readonly path?: string
257
+ /**
258
+ * `exact` matches the callee text as written. `member` also matches any
259
+ * `<expression>.name`, which finds method calls whose receiver is unknown.
260
+ */
261
+ readonly match?: 'exact' | 'member'
262
+ }
263
+
264
+ export interface AnalysisCallSite {
265
+ readonly path: string
266
+ readonly line: number
267
+ readonly column: number
268
+ readonly callee: string
269
+ readonly kind: 'call' | 'new'
270
+ readonly argumentCount: number
271
+ /** The function the call sits in; absent at the top level of a file. */
272
+ readonly caller?: AnalysisFunction
273
+ /** See {@link AnalysisLiteralHit.stale}. */
274
+ readonly stale?: 'changed' | 'deleted'
275
+ }
276
+
277
+ export interface ImportsRequest extends AnalysisPaging {
278
+ readonly root: string
279
+ readonly path: string
280
+ }
281
+
282
+ export type AnalysisModuleEdge =
283
+ | {
284
+ readonly direction: 'import'
285
+ readonly kind: 'static' | 'type' | 'require' | 'dynamic'
286
+ readonly source: string
287
+ readonly names: readonly string[]
288
+ readonly line: number
289
+ readonly column: number
290
+ }
291
+ | {
292
+ readonly direction: 'export'
293
+ readonly kind: 'named' | 'default' | 'reexport' | 'star'
294
+ readonly name: string
295
+ readonly source?: string
296
+ readonly line: number
297
+ readonly column: number
298
+ }
299
+
300
+ export interface CodeAnalysisProvider {
301
+ /**
302
+ * Build or refresh the index for a directory. Incremental: a file whose
303
+ * size and mtime are unchanged is not read, and one whose content hash is
304
+ * unchanged is not parsed.
305
+ */
306
+ index(request: IndexRequest): Promise<CodeAnalysisResult<IndexSummary>>
307
+ /** Where a string appears, and the function around each hit. */
308
+ findLiteral(
309
+ request: FindLiteralRequest,
310
+ ): Promise<CodeAnalysisResult<AnalysisPage<AnalysisLiteralHit>>>
311
+ /** The function containing a position, with its source and parent chain. */
312
+ enclosingFunction(
313
+ request: EnclosingFunctionRequest,
314
+ ): Promise<CodeAnalysisResult<AnalysisEnclosingFunction>>
315
+ /** A function's exact source, by id or by file and name. */
316
+ functionSource(
317
+ request: FunctionSourceRequest,
318
+ ): Promise<CodeAnalysisResult<AnalysisPage<AnalysisFunctionSource>>>
319
+ /** Call sites of a name. Matched by text, not by scope; see the evidence. */
320
+ callersOf(request: CallersOfRequest): Promise<CodeAnalysisResult<AnalysisPage<AnalysisCallSite>>>
321
+ /** One file's imports and exports. */
322
+ imports(request: ImportsRequest): Promise<CodeAnalysisResult<AnalysisPage<AnalysisModuleEdge>>>
323
+ /** Close whatever backs it. Not optional: an open database is a held file. */
324
+ dispose(): Promise<void>
325
+ }
@@ -1,5 +1,6 @@
1
1
  import type { ChildProcess } from 'node:child_process'
2
2
  import type { z } from 'zod'
3
+ import type { CodeAnalysisProvider } from '../code-analysis/index.js'
3
4
  import type { CodeNavigationProvider } from '../code-navigation/index.js'
4
5
  // Type-only, and circular by design: a tool-result guardrail is described in
5
6
  // terms of the tool that produced the result, and the registry that holds
@@ -465,6 +466,14 @@ export interface ToolContext {
465
466
  * always says "unavailable" is worse than one that is not there.
466
467
  */
467
468
  codeNavigation?: CodeNavigationProvider
469
+ /**
470
+ * A semantic index of JavaScript/TypeScript, for the `code_analysis` tool.
471
+ *
472
+ * Same rule as `codeNavigation`: absent means the tool is not registered,
473
+ * so a tool that is always present and always says "unavailable" never
474
+ * exists. See `tools/builtins/code-analysis.ts`.
475
+ */
476
+ codeAnalysis?: CodeAnalysisProvider
468
477
  fileReadTracker?: FileReadTracker
469
478
 
470
479
  /**