@namzu/sdk 52.0.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.
- package/CHANGELOG.md +29 -0
- package/README.md +1 -1
- package/dist/compaction/verifier.d.ts.map +1 -1
- package/dist/compaction/verifier.js +57 -17
- package/dist/compaction/verifier.js.map +1 -1
- package/dist/connector/tools/adapter.d.ts +2 -2
- package/dist/contracts/a2a.d.ts +94 -94
- package/dist/manager/resident/learning.d.ts +6 -6
- package/dist/manager/resident/store.d.ts +4 -4
- package/dist/pals/activity/subscription-schema.d.ts +48 -48
- package/dist/pals/communication/ingress-schema.d.ts +192 -192
- package/dist/pals/communication/schema.d.ts +18 -18
- package/dist/peers/protocol.d.ts +36 -36
- package/dist/provider/capabilities.d.ts +9 -0
- package/dist/provider/capabilities.d.ts.map +1 -1
- package/dist/provider/capabilities.js +15 -0
- package/dist/provider/capabilities.js.map +1 -1
- package/dist/provider/errors.d.ts.map +1 -1
- package/dist/provider/errors.js +13 -0
- package/dist/provider/errors.js.map +1 -1
- package/dist/provider/fallback.d.ts.map +1 -1
- package/dist/provider/fallback.js +10 -0
- package/dist/provider/fallback.js.map +1 -1
- package/dist/provider/idle-timeout.d.ts.map +1 -1
- package/dist/provider/idle-timeout.js +5 -0
- package/dist/provider/idle-timeout.js.map +1 -1
- package/dist/provider/image-input-refusal.d.ts +9 -0
- package/dist/provider/image-input-refusal.d.ts.map +1 -0
- package/dist/provider/image-input-refusal.js +54 -0
- package/dist/provider/image-input-refusal.js.map +1 -0
- package/dist/provider/index.d.ts +2 -1
- package/dist/provider/index.d.ts.map +1 -1
- package/dist/provider/index.js +2 -1
- package/dist/provider/index.js.map +1 -1
- package/dist/provider/retry.d.ts +7 -2
- package/dist/provider/retry.d.ts.map +1 -1
- package/dist/provider/retry.js +38 -4
- package/dist/provider/retry.js.map +1 -1
- package/dist/public-runtime.d.ts +2 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +1 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +1 -0
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +1 -0
- package/dist/public-tools.js.map +1 -1
- package/dist/runtime/query/deferred-sandbox.d.ts +54 -0
- package/dist/runtime/query/deferred-sandbox.d.ts.map +1 -0
- package/dist/runtime/query/deferred-sandbox.js +75 -0
- package/dist/runtime/query/deferred-sandbox.js.map +1 -0
- package/dist/runtime/query/executor.d.ts +11 -0
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +25 -3
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/index.d.ts +2 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +94 -25
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +26 -0
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +164 -21
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts +10 -7
- package/dist/runtime/query/iteration/phases/compaction-breaker.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction-breaker.js +10 -7
- package/dist/runtime/query/iteration/phases/compaction-breaker.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.d.ts +42 -1
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +119 -21
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/provider-rejected-image.d.ts +21 -1
- package/dist/runtime/query/iteration/provider-rejected-image.d.ts.map +1 -1
- package/dist/runtime/query/iteration/provider-rejected-image.js +53 -7
- package/dist/runtime/query/iteration/provider-rejected-image.js.map +1 -1
- package/dist/runtime/query/iteration/request-repair.d.ts +108 -0
- package/dist/runtime/query/iteration/request-repair.d.ts.map +1 -0
- package/dist/runtime/query/iteration/request-repair.js +593 -0
- package/dist/runtime/query/iteration/request-repair.js.map +1 -0
- package/dist/runtime/query/iteration/stream-turn.d.ts +6 -0
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +2 -2
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/request-rich-content.d.ts +5 -1
- package/dist/runtime/query/request-rich-content.d.ts.map +1 -1
- package/dist/runtime/query/request-rich-content.js +67 -25
- package/dist/runtime/query/request-rich-content.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +1 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +1 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/tools/builtins/browser.d.ts +4 -4
- package/dist/tools/builtins/code-analysis.d.ts +49 -0
- package/dist/tools/builtins/code-analysis.d.ts.map +1 -0
- package/dist/tools/builtins/code-analysis.js +409 -0
- package/dist/tools/builtins/code-analysis.js.map +1 -0
- package/dist/tools/builtins/computer-use.d.ts +25 -25
- package/dist/tools/builtins/computer-use.d.ts.map +1 -1
- package/dist/tools/builtins/computer-use.js +12 -5
- package/dist/tools/builtins/computer-use.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +1 -0
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +1 -0
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/lsp.d.ts +1 -1
- package/dist/tools/builtins/skill.d.ts +2 -2
- package/dist/types/code-analysis/index.d.ts +299 -0
- package/dist/types/code-analysis/index.d.ts.map +1 -0
- package/dist/types/code-analysis/index.js +30 -0
- package/dist/types/code-analysis/index.js.map +1 -0
- package/dist/types/plugin/index.d.ts +6 -6
- package/dist/types/provider/errors.d.ts.map +1 -1
- package/dist/types/provider/errors.js +30 -5
- package/dist/types/provider/errors.js.map +1 -1
- package/dist/types/provider/interface.d.ts +12 -0
- package/dist/types/provider/interface.d.ts.map +1 -1
- package/dist/types/provider/stream.d.ts +1 -1
- package/dist/types/session/config.d.ts +14 -0
- package/dist/types/session/config.d.ts.map +1 -1
- package/dist/types/session/events.d.ts +20 -5
- package/dist/types/session/events.d.ts.map +1 -1
- package/dist/types/session/events.js.map +1 -1
- package/dist/types/session/records.d.ts +127 -127
- package/dist/types/tool/index.d.ts +9 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/package.json +2 -2
- package/src/compaction/verifier.ts +57 -20
- package/src/provider/capabilities.ts +17 -0
- package/src/provider/errors.ts +13 -0
- package/src/provider/fallback.ts +10 -0
- package/src/provider/idle-timeout.ts +5 -0
- package/src/provider/image-input-refusal.ts +54 -0
- package/src/provider/index.ts +2 -0
- package/src/provider/retry.ts +42 -4
- package/src/public-runtime.ts +28 -0
- package/src/public-tools.ts +5 -0
- package/src/runtime/query/deferred-sandbox.ts +110 -0
- package/src/runtime/query/executor.ts +27 -3
- package/src/runtime/query/index.ts +127 -49
- package/src/runtime/query/iteration/index.ts +188 -23
- package/src/runtime/query/iteration/phases/compaction-breaker.ts +10 -8
- package/src/runtime/query/iteration/phases/compaction.ts +151 -35
- package/src/runtime/query/iteration/provider-rejected-image.ts +71 -5
- package/src/runtime/query/iteration/request-repair.ts +743 -0
- package/src/runtime/query/iteration/stream-turn.ts +11 -1
- package/src/runtime/query/request-rich-content.ts +77 -27
- package/src/runtime/query/tooling.ts +2 -0
- package/src/tools/builtins/code-analysis.ts +486 -0
- package/src/tools/builtins/computer-use.ts +13 -4
- package/src/tools/builtins/index.ts +5 -0
- package/src/types/code-analysis/index.ts +325 -0
- package/src/types/provider/errors.ts +33 -5
- package/src/types/provider/interface.ts +13 -0
- package/src/types/provider/stream.ts +1 -1
- package/src/types/session/config.ts +14 -0
- package/src/types/session/events.ts +25 -5
- 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
|
+
}
|
|
@@ -270,6 +270,14 @@ export function readOutputOverflow(err: unknown): OutputOverflowFigures | undefi
|
|
|
270
270
|
return undefined
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
+
/** Undici's `TypeError: terminated` anywhere on the chain: the body stream was cut. */
|
|
274
|
+
function isUndiciTermination(err: unknown): boolean {
|
|
275
|
+
for (const link of causeChain(err)) {
|
|
276
|
+
if ((link as unknown) instanceof TypeError && link.message === 'terminated') return true
|
|
277
|
+
}
|
|
278
|
+
return false
|
|
279
|
+
}
|
|
280
|
+
|
|
273
281
|
/** Node/undici transport failures that mean "never reached the model". */
|
|
274
282
|
const NETWORK_ERRNOS: ReadonlySet<string> = new Set([
|
|
275
283
|
'ECONNRESET',
|
|
@@ -304,12 +312,19 @@ function codeFromStatus(status: number): ProviderErrorCode {
|
|
|
304
312
|
return 'unknown'
|
|
305
313
|
}
|
|
306
314
|
|
|
315
|
+
function overflowWordingAllowed(status: number | undefined): boolean {
|
|
316
|
+
return status === undefined || status === 400 || status === 413
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const CONTEXT_WINDOW_OVERFLOW =
|
|
320
|
+
/(?:exceed\w*|too (?:long|large|big)|larger than|longer than|over the|beyond|maximum|overflow\w*)\b[^.]{0,60}context window|context window[^.]{0,60}\b(?:exceed\w*|too (?:long|large|big)|larger than|longer than|over the|beyond|maximum|overflow\w*)/i
|
|
321
|
+
|
|
307
322
|
/**
|
|
308
323
|
* Message sniffing is the LAST resort, used only when there is no status
|
|
309
324
|
* and no errno. Vendors that tunnel a 400 through a 200 body (several
|
|
310
325
|
* gateways do) are only reachable this way.
|
|
311
326
|
*/
|
|
312
|
-
function codeFromMessage(message: string): ProviderErrorCode | undefined {
|
|
327
|
+
function codeFromMessage(message: string, status?: number): ProviderErrorCode | undefined {
|
|
313
328
|
const m = message.toLowerCase()
|
|
314
329
|
if (
|
|
315
330
|
m.includes('context length') ||
|
|
@@ -322,6 +337,13 @@ function codeFromMessage(message: string): ProviderErrorCode | undefined {
|
|
|
322
337
|
// overflow rescue tests for by exact equality. The turn died holding
|
|
323
338
|
// the remedy.
|
|
324
339
|
m.includes('too long for') ||
|
|
340
|
+
// The reference terminal's own wordings (its `context window` and
|
|
341
|
+
// `input length and max_tokens exceed context limit` matchers).
|
|
342
|
+
// Only where the status cannot say otherwise: a 429, 5xx or 401 that
|
|
343
|
+
// mentions the window is still a rate limit, a server fault or an auth
|
|
344
|
+
// failure, and must keep its retry and fallback behaviour.
|
|
345
|
+
(overflowWordingAllowed(status) &&
|
|
346
|
+
(CONTEXT_WINDOW_OVERFLOW.test(message) || m.includes('exceed context limit'))) ||
|
|
325
347
|
m.includes('maximum length') ||
|
|
326
348
|
m.includes('exceeds the maximum') ||
|
|
327
349
|
m.includes('input is too large') ||
|
|
@@ -498,7 +520,9 @@ export function classifyProviderError(
|
|
|
498
520
|
// usually generic ("request failed") — so matching only the outer text
|
|
499
521
|
// looks at the one string least likely to say anything.
|
|
500
522
|
const messages = chainMessages(err)
|
|
501
|
-
const fromMessage = messages
|
|
523
|
+
const fromMessage = messages
|
|
524
|
+
.map((m) => codeFromMessage(m, status))
|
|
525
|
+
.find((code) => code !== undefined)
|
|
502
526
|
// A first-hand statement from whoever produced the failure, if there
|
|
503
527
|
// is one. It outranks the code's inference, not the code itself: the
|
|
504
528
|
// classification still says WHAT went wrong.
|
|
@@ -522,7 +546,7 @@ export function classifyProviderError(
|
|
|
522
546
|
|
|
523
547
|
// A 400 that is really a window overflow must not be filed as a plain
|
|
524
548
|
// invalid_request: the caller can recover from one and not the other.
|
|
525
|
-
if (messages.some((m) => codeFromMessage(m) === 'context_length_exceeded')) {
|
|
549
|
+
if (messages.some((m) => codeFromMessage(m, status) === 'context_length_exceeded')) {
|
|
526
550
|
return new ProviderError({
|
|
527
551
|
code: 'context_length_exceeded',
|
|
528
552
|
message,
|
|
@@ -566,8 +590,12 @@ export function classifyProviderError(
|
|
|
566
590
|
}
|
|
567
591
|
}
|
|
568
592
|
|
|
569
|
-
// `fetch` rejects with a bare TypeError on transport failure
|
|
570
|
-
|
|
593
|
+
// `fetch` rejects with a bare TypeError on transport failure, and undici
|
|
594
|
+
// ends a response body the peer cut mid-stream with `TypeError:
|
|
595
|
+
// terminated`. Its socket error normally rides along as the cause and the
|
|
596
|
+
// errno walk above catches it, but a vendor SDK that re-wraps the stream
|
|
597
|
+
// error can drop that cause and leave only the bare word.
|
|
598
|
+
if ((err instanceof TypeError && /fetch|network/i.test(message)) || isUndiciTermination(err)) {
|
|
571
599
|
return new ProviderError({
|
|
572
600
|
code: 'network',
|
|
573
601
|
message,
|
|
@@ -22,6 +22,19 @@ export interface LLMProvider {
|
|
|
22
22
|
/** Refine hosted search support for a model and mode. Absent uses the driver-wide declaration. */
|
|
23
23
|
supportsHostedWebSearchFor?(model: string, mode: 'live' | 'cached'): boolean
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Whether `model` reads images. `capabilities.supportsVision` is a statement
|
|
27
|
+
* about the DRIVER (does it map image parts onto the wire); this is about the
|
|
28
|
+
* MODEL behind it, which only the driver's catalogue can know: one driver
|
|
29
|
+
* serves vision and text-only models side by side, and a text-only model
|
|
30
|
+
* refuses the whole request when it finds an image in it.
|
|
31
|
+
*
|
|
32
|
+
* Answer `false` only when the model is known to be text-only. Absent, or
|
|
33
|
+
* `true`, means "send images": the runtime also recovers from a refusal, so a
|
|
34
|
+
* driver with no catalogue loses nothing by omitting this.
|
|
35
|
+
*/
|
|
36
|
+
supportsImageInputFor?(model: string): boolean
|
|
37
|
+
|
|
25
38
|
/**
|
|
26
39
|
* Retry behaviour this DRIVER wants, when the generic default is wrong
|
|
27
40
|
* for the vendor behind it.
|
|
@@ -174,7 +174,7 @@ export interface ProviderRetryNotice {
|
|
|
174
174
|
/** The delay came from the server's own `Retry-After`, not backoff. */
|
|
175
175
|
readonly serverDirected: boolean
|
|
176
176
|
/**
|
|
177
|
-
* The failed attempt had already streamed text or reasoning, and the request
|
|
177
|
+
* The failed attempt had already streamed text or reasoning (reasoning alone is retried without any option), and the request
|
|
178
178
|
* is being sent again from the start. Whatever that attempt produced is void
|
|
179
179
|
* and the consumer must drop it before the next chunk.
|
|
180
180
|
*/
|
|
@@ -88,6 +88,20 @@ export interface TurnConfig {
|
|
|
88
88
|
* behaviour every sandboxed turn had before this existed.
|
|
89
89
|
*/
|
|
90
90
|
workspace?: 'ephemeral' | 'working-directory'
|
|
91
|
+
/**
|
|
92
|
+
* When the turn acquires its sandbox. Absent means `'eager'`: acquired,
|
|
93
|
+
* and waited for, before the input guardrails and the first model
|
|
94
|
+
* request.
|
|
95
|
+
*
|
|
96
|
+
* `'concurrent'` starts at the same point but lets the first model
|
|
97
|
+
* request go out while the provider allocates; the first tool call
|
|
98
|
+
* waits for the handle. `'on-first-use'` does not start until the first
|
|
99
|
+
* tool call. Either way `sandbox_created` is emitted when the handle
|
|
100
|
+
* arrives, and a failure or timeout ends the turn with the stop reason
|
|
101
|
+
* an eager acquisition would have produced, at the first tool call or
|
|
102
|
+
* at turn end, whichever comes first.
|
|
103
|
+
*/
|
|
104
|
+
acquire?: 'eager' | 'concurrent' | 'on-first-use'
|
|
91
105
|
}
|
|
92
106
|
|
|
93
107
|
/**
|
|
@@ -280,8 +280,11 @@ type CoreSessionEvent =
|
|
|
280
280
|
* a provider that rejects the pairing. A reducer bug, and one
|
|
281
281
|
* `findSafeTrimIndex` exists to prevent.
|
|
282
282
|
* - `breaker_open` — only with `compactionConfig.circuitBreaker`:
|
|
283
|
-
* three passes in a row failed, so
|
|
284
|
-
* the rest of the turn
|
|
283
|
+
* three passes in a row failed, so proactive compaction is off for
|
|
284
|
+
* the rest of the turn; a context overflow the provider reports
|
|
285
|
+
* still runs the reactive relief. Sent once, without `error`: it is
|
|
286
|
+
* for a host's records, not a line for the person. `messages` is
|
|
287
|
+
* the live count.
|
|
285
288
|
* - `refilling` — only with `compactionConfig.circuitBreaker`: the
|
|
286
289
|
* context filled back up within three iterations of a compaction,
|
|
287
290
|
* three times in a row, and the turn is stopping. Sent once.
|
|
@@ -289,7 +292,7 @@ type CoreSessionEvent =
|
|
|
289
292
|
cause: 'reducer_threw' | 'shed_nothing' | 'split_tool_pair' | 'breaker_open' | 'refilling'
|
|
290
293
|
/** Unchanged, and stated so a reader need not infer it. */
|
|
291
294
|
messages: number
|
|
292
|
-
/** For `reducer_threw`, the reducer's message; for `
|
|
295
|
+
/** For `reducer_threw`, the reducer's message; for `refilling`, the one line to show. */
|
|
293
296
|
error?: string
|
|
294
297
|
}
|
|
295
298
|
| {
|
|
@@ -714,9 +717,26 @@ type CoreSessionEvent =
|
|
|
714
717
|
sessionId: SessionId
|
|
715
718
|
turnId?: TurnId
|
|
716
719
|
capability: 'tools' | 'vision' | 'documents'
|
|
717
|
-
/**
|
|
718
|
-
|
|
720
|
+
/**
|
|
721
|
+
* Present when the mismatch was not about the user's own message:
|
|
722
|
+
* `'tool-result'` after a tool executed; `'history'` when the model
|
|
723
|
+
* itself turned out not to read images (see `model`) and the images
|
|
724
|
+
* already in the conversation were left out of the request;
|
|
725
|
+
* `'media-removed'` when the provider rejected an image or document
|
|
726
|
+
* and it was left out of the request that then went through;
|
|
727
|
+
* `'media-removed-current'` when that included a file attached to the
|
|
728
|
+
* latest user message; `'media-limit'` when the oldest files were left
|
|
729
|
+
* out only to fit a count the provider accepts.
|
|
730
|
+
*/
|
|
731
|
+
contentSource?:
|
|
732
|
+
| 'tool-result'
|
|
733
|
+
| 'history'
|
|
734
|
+
| 'media-removed'
|
|
735
|
+
| 'media-removed-current'
|
|
736
|
+
| 'media-limit'
|
|
719
737
|
providerId: string
|
|
738
|
+
/** The model that cannot read images, when the warning is about one model rather than the driver. */
|
|
739
|
+
model?: string
|
|
720
740
|
message: string
|
|
721
741
|
}
|
|
722
742
|
/**
|
package/src/types/tool/index.ts
CHANGED
|
@@ -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
|
/**
|