@namzu/sdk 1.2.0 → 1.4.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 +99 -0
- package/dist/compaction/__tests__/verifier-empty-reply.test.d.ts +12 -0
- package/dist/compaction/__tests__/verifier-empty-reply.test.d.ts.map +1 -0
- package/dist/compaction/__tests__/verifier-empty-reply.test.js +73 -0
- package/dist/compaction/__tests__/verifier-empty-reply.test.js.map +1 -0
- package/dist/compaction/verifier.d.ts.map +1 -1
- package/dist/compaction/verifier.js +10 -1
- package/dist/compaction/verifier.js.map +1 -1
- package/dist/config/__tests__/compaction-budget-schema.test.d.ts +18 -0
- package/dist/config/__tests__/compaction-budget-schema.test.d.ts.map +1 -0
- package/dist/config/__tests__/compaction-budget-schema.test.js +96 -0
- package/dist/config/__tests__/compaction-budget-schema.test.js.map +1 -0
- package/dist/config/runtime.d.ts.map +1 -1
- package/dist/config/runtime.js +20 -11
- package/dist/config/runtime.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +2 -1
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +3 -1
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/provider/__tests__/errors.test.d.ts +2 -0
- package/dist/provider/__tests__/errors.test.d.ts.map +1 -0
- package/dist/provider/__tests__/errors.test.js +61 -0
- package/dist/provider/__tests__/errors.test.js.map +1 -0
- package/dist/provider/__tests__/registry.test.d.ts +5 -0
- package/dist/provider/__tests__/registry.test.d.ts.map +1 -1
- package/dist/provider/__tests__/registry.test.js +186 -1
- package/dist/provider/__tests__/registry.test.js.map +1 -1
- package/dist/provider/errors.d.ts +108 -0
- package/dist/provider/errors.d.ts.map +1 -0
- package/dist/provider/errors.js +311 -0
- package/dist/provider/errors.js.map +1 -0
- package/dist/provider/index.d.ts +3 -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/registry.d.ts +81 -1
- package/dist/provider/registry.d.ts.map +1 -1
- package/dist/provider/registry.js +173 -7
- package/dist/provider/registry.js.map +1 -1
- package/dist/public-runtime.d.ts +11 -11
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +11 -11
- package/dist/public-runtime.js.map +1 -1
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +5 -2
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/registry/tool/execute.test.js +11 -0
- package/dist/registry/tool/execute.test.js.map +1 -1
- package/dist/runtime/query/__tests__/stream-recovery.test.js +54 -1
- package/dist/runtime/query/__tests__/stream-recovery.test.js.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction-safe-cut.test.d.ts +32 -0
- package/dist/runtime/query/iteration/phases/compaction-safe-cut.test.d.ts.map +1 -0
- package/dist/runtime/query/iteration/phases/compaction-safe-cut.test.js +152 -0
- package/dist/runtime/query/iteration/phases/compaction-safe-cut.test.js.map +1 -0
- package/dist/runtime/query/iteration/phases/compaction.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/compaction.js +52 -12
- package/dist/runtime/query/iteration/phases/compaction.js.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.d.ts.map +1 -1
- package/dist/runtime/query/iteration/stream-turn.js +11 -5
- package/dist/runtime/query/iteration/stream-turn.js.map +1 -1
- package/dist/runtime/query/result.d.ts.map +1 -1
- package/dist/runtime/query/result.js +11 -1
- package/dist/runtime/query/result.js.map +1 -1
- package/dist/tools/builtins/__tests__/edit.test.js +54 -0
- package/dist/tools/builtins/__tests__/edit.test.js.map +1 -1
- package/dist/tools/builtins/edit.d.ts +1 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +11 -13
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/coordinator/__tests__/task-list.test.js +14 -0
- package/dist/tools/coordinator/__tests__/task-list.test.js.map +1 -1
- package/dist/tools/coordinator/agent.d.ts +6 -8
- package/dist/tools/coordinator/agent.d.ts.map +1 -1
- package/dist/tools/coordinator/agent.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +11 -32
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/defineTool.d.ts +1 -0
- package/dist/tools/defineTool.d.ts.map +1 -1
- package/dist/tools/defineTool.js +1 -0
- package/dist/tools/defineTool.js.map +1 -1
- package/dist/types/provider/config.d.ts +33 -0
- package/dist/types/provider/config.d.ts.map +1 -1
- package/dist/types/provider/error.d.ts +22 -0
- package/dist/types/provider/error.d.ts.map +1 -0
- package/dist/types/provider/error.js +2 -0
- package/dist/types/provider/error.js.map +1 -0
- package/dist/types/provider/index.d.ts +2 -1
- package/dist/types/provider/index.d.ts.map +1 -1
- package/dist/types/run/entity.d.ts +2 -0
- package/dist/types/run/entity.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +2 -0
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/tool/index.d.ts +6 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/compaction/__tests__/verifier-empty-reply.test.ts +96 -0
- package/src/compaction/verifier.ts +10 -1
- package/src/config/__tests__/compaction-budget-schema.test.ts +114 -0
- package/src/config/runtime.ts +20 -11
- package/src/manager/run/persistence.ts +3 -1
- package/src/provider/__tests__/errors.test.ts +85 -0
- package/src/provider/__tests__/registry.test.ts +266 -1
- package/src/provider/errors.ts +344 -0
- package/src/provider/index.ts +22 -1
- package/src/provider/registry.ts +202 -7
- package/src/public-runtime.ts +55 -10
- package/src/registry/tool/execute.test.ts +14 -0
- package/src/registry/tool/execute.ts +5 -2
- package/src/runtime/query/__tests__/stream-recovery.test.ts +64 -1
- package/src/runtime/query/iteration/phases/compaction-safe-cut.test.ts +186 -0
- package/src/runtime/query/iteration/phases/compaction.ts +54 -12
- package/src/runtime/query/iteration/stream-turn.ts +11 -6
- package/src/runtime/query/result.ts +11 -1
- package/src/tools/builtins/__tests__/edit.test.ts +76 -0
- package/src/tools/builtins/edit.ts +12 -12
- package/src/tools/coordinator/__tests__/task-list.test.ts +16 -0
- package/src/tools/coordinator/agent.ts +6 -8
- package/src/tools/coordinator/index.ts +11 -34
- package/src/tools/defineTool.ts +2 -0
- package/src/types/provider/config.ts +36 -0
- package/src/types/provider/error.ts +29 -0
- package/src/types/provider/index.ts +8 -0
- package/src/types/run/entity.ts +2 -0
- package/src/types/run/events.ts +7 -1
- package/src/types/tool/index.ts +6 -0
|
@@ -2,6 +2,8 @@ import { mkdtempSync, readFileSync, writeFileSync } from 'node:fs'
|
|
|
2
2
|
import { tmpdir } from 'node:os'
|
|
3
3
|
import { join } from 'node:path'
|
|
4
4
|
import { describe, expect, it } from 'vitest'
|
|
5
|
+
import { zodToJsonSchema } from 'zod-to-json-schema'
|
|
6
|
+
import { ToolRegistry } from '../../../registry/tool/execute.js'
|
|
5
7
|
import type { ToolContext } from '../../../types/tool/index.js'
|
|
6
8
|
import { EditTool } from '../edit.js'
|
|
7
9
|
|
|
@@ -54,4 +56,78 @@ describe('EditTool', () => {
|
|
|
54
56
|
expect(result.success).toBe(true)
|
|
55
57
|
expect(readFileSync(join(dir, 'doc.md'), 'utf-8')).toBe('alpha\nomega\n')
|
|
56
58
|
})
|
|
59
|
+
|
|
60
|
+
it('publishes only the insertLine values the executor can apply', () => {
|
|
61
|
+
for (const insertLine of ['## Progress', null, '', '1', -1]) {
|
|
62
|
+
const parsed = EditTool.inputSchema.safeParse({
|
|
63
|
+
path: 'doc.md',
|
|
64
|
+
insertLine,
|
|
65
|
+
newStr: 'inserted',
|
|
66
|
+
})
|
|
67
|
+
expect(parsed.success, JSON.stringify(insertLine)).toBe(false)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
for (const insertLine of [0, 1, 'end']) {
|
|
71
|
+
const parsed = EditTool.inputSchema.safeParse({
|
|
72
|
+
path: 'doc.md',
|
|
73
|
+
insertLine,
|
|
74
|
+
newStr: 'inserted',
|
|
75
|
+
})
|
|
76
|
+
expect(parsed.success, JSON.stringify(insertLine)).toBe(true)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const json = zodToJsonSchema(EditTool.inputSchema, {
|
|
80
|
+
target: 'jsonSchema7',
|
|
81
|
+
$refStrategy: 'none',
|
|
82
|
+
}) as {
|
|
83
|
+
properties?: {
|
|
84
|
+
insertLine?: {
|
|
85
|
+
anyOf?: Record<string, unknown>[]
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
expect(json.properties?.insertLine?.anyOf).toEqual([
|
|
90
|
+
{ type: 'integer', minimum: 0 },
|
|
91
|
+
{ type: 'string', const: 'end' },
|
|
92
|
+
])
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('refuses invalid insertLine values even when a caller bypasses the schema', async () => {
|
|
96
|
+
for (const insertLine of ['## Progress', null, '', '1']) {
|
|
97
|
+
const dir = mkdtempSync(join(tmpdir(), 'namzu-edit-'))
|
|
98
|
+
writeFileSync(join(dir, 'doc.md'), 'alpha\nbeta\n')
|
|
99
|
+
|
|
100
|
+
const result = await EditTool.execute(
|
|
101
|
+
{
|
|
102
|
+
path: 'doc.md',
|
|
103
|
+
insertLine,
|
|
104
|
+
newStr: 'inserted',
|
|
105
|
+
replace_all: false,
|
|
106
|
+
} as never,
|
|
107
|
+
makeContext(dir),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
expect(result.success, JSON.stringify(insertLine)).toBe(false)
|
|
111
|
+
expect(result.error).toBe('insertLine must be a non-negative line number or "end".')
|
|
112
|
+
expect(readFileSync(join(dir, 'doc.md'), 'utf-8')).toBe('alpha\nbeta\n')
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
it('returns complete recovery shapes when path is missing and insertLine is invalid', async () => {
|
|
117
|
+
const registry = new ToolRegistry()
|
|
118
|
+
registry.register(EditTool)
|
|
119
|
+
|
|
120
|
+
const result = await registry.execute(
|
|
121
|
+
'edit',
|
|
122
|
+
{ insertLine: '## Progress' },
|
|
123
|
+
makeContext('/tmp'),
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
expect(result.success).toBe(false)
|
|
127
|
+
expect(result.error).toContain('Validation failed for "edit":')
|
|
128
|
+
expect(result.error).toContain('insertLine: Invalid input')
|
|
129
|
+
expect(result.error).toContain('Required: path: string — Path to the file to edit.')
|
|
130
|
+
expect(result.error).toContain('{"path":"file.md","insertLine":"end","new_string":"text"}')
|
|
131
|
+
expect(result.error).toContain('{"path":"file.md","old_string":"old","new_string":"new"}')
|
|
132
|
+
})
|
|
57
133
|
})
|
|
@@ -29,10 +29,10 @@ const inputSchema = z
|
|
|
29
29
|
'Alias for new_string. Also used as inserted content when insertLine is provided. Self-budget this payload under 12000 characters before calling.',
|
|
30
30
|
),
|
|
31
31
|
insertLine: z
|
|
32
|
-
.union([z.
|
|
32
|
+
.union([z.number().int().min(0), z.literal('end')])
|
|
33
33
|
.optional()
|
|
34
34
|
.describe(
|
|
35
|
-
'Optional line insertion target.
|
|
35
|
+
'Optional line insertion target. Pass a JSON integer to insert after that 1-indexed line, 0 to insert before the first line, or the exact string "end" to append. Headings, anchors, numeric strings, null, and empty strings are invalid.',
|
|
36
36
|
),
|
|
37
37
|
replace_all: z
|
|
38
38
|
.boolean()
|
|
@@ -71,6 +71,8 @@ export const EditTool = defineTool({
|
|
|
71
71
|
description:
|
|
72
72
|
'Makes targeted edits to a file using exact string find-and-replace or line insertion. THIS IS THE PREFERRED WAY TO MODIFY AN EXISTING FILE — never reach for `write` to change a file that already exists, because `write` overwrites the whole body and discards earlier work on partial failure. `edit` keeps the rest of the file byte-for-byte intact and is recoverable: if a single edit fails (old_string/oldStr ambiguous, broader restructuring needed), follow up with another `edit` instead of re-emitting the entire file via `write`. The old_string/oldStr must be unique in the file unless replace_all is true. For insertions, pass insertLine plus new_string/newStr; use insertLine: "end" to extend a file at the end. Self-budget new_string/newStr under 12000 characters before emitting the tool call; use repeated bounded edits for long sections. Preserves file formatting and indentation.',
|
|
73
73
|
inputSchema,
|
|
74
|
+
validationErrorHint:
|
|
75
|
+
'Accepted shapes: {"path":"file.md","insertLine":"end","new_string":"text"} or {"path":"file.md","old_string":"old","new_string":"new"}. Always include path; insertLine accepts only a non-negative JSON integer or the exact string "end".',
|
|
74
76
|
category: 'filesystem',
|
|
75
77
|
permissions: ['file_write'],
|
|
76
78
|
readOnly: false,
|
|
@@ -166,18 +168,16 @@ function normalizeEditInput(
|
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
function normalizeInsertLine(
|
|
169
|
-
value:
|
|
171
|
+
value: unknown,
|
|
170
172
|
): { success: true; value: number | 'end' } | { success: false; error: string } {
|
|
171
|
-
if (
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
}
|
|
173
|
+
if (value === 'end') return { success: true, value: 'end' }
|
|
174
|
+
if (typeof value === 'number' && Number.isInteger(value) && value >= 0) {
|
|
175
|
+
return { success: true, value }
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
success: false,
|
|
179
|
+
error: 'insertLine must be a non-negative line number or "end".',
|
|
179
180
|
}
|
|
180
|
-
return { success: true, value }
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
function applyEdit(
|
|
@@ -179,4 +179,20 @@ describe('coordinator agent_task_list tool', () => {
|
|
|
179
179
|
expect(names).toContain('agent_task_list')
|
|
180
180
|
expect(names).not.toContain('task_list')
|
|
181
181
|
})
|
|
182
|
+
|
|
183
|
+
it('does not advertise per-task cancellation on the blocking coordinator surface', () => {
|
|
184
|
+
const coordinatorTools = buildCoordinatorTools({
|
|
185
|
+
gateway: gatewayWith([]),
|
|
186
|
+
workingDirectory: '/tmp/test',
|
|
187
|
+
allowedAgentIds: ['solution-architecture'],
|
|
188
|
+
})
|
|
189
|
+
const names = coordinatorTools.map((tool) => tool.name)
|
|
190
|
+
|
|
191
|
+
// create_task returns only after the worker is terminal, so the
|
|
192
|
+
// supervisor cannot know a live task id in a later model turn.
|
|
193
|
+
// Keeping cancel_task here only manufactured success for missing
|
|
194
|
+
// or terminal ids because every gateway cancellation is a void
|
|
195
|
+
// no-op in those states.
|
|
196
|
+
expect(names).not.toContain('cancel_task')
|
|
197
|
+
})
|
|
182
198
|
})
|
|
@@ -19,14 +19,12 @@ import type { TaskLaunchedCallback } from './index.js'
|
|
|
19
19
|
* subagent tool calls are isolated — only the summary surfaces to
|
|
20
20
|
* the parent.
|
|
21
21
|
*
|
|
22
|
-
* This is **NOT** the same shape as the
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* the legacy coordinator tools only when you genuinely need
|
|
29
|
-
* fire-and-forget multi-task fan-out.
|
|
22
|
+
* This is **NOT** the same shape as the coordinator `create_task`
|
|
23
|
+
* tool that this package ships alongside it. That tool exposes
|
|
24
|
+
* Namzu's task IDs and optional planning integration, while still
|
|
25
|
+
* returning results synchronously. For free agentic alignment,
|
|
26
|
+
* prefer the canonical `Agent` tool; use the coordinator tool when
|
|
27
|
+
* the host needs task tracking.
|
|
30
28
|
*/
|
|
31
29
|
export interface AgentToolOptions {
|
|
32
30
|
gateway: TaskGateway
|
|
@@ -227,28 +227,6 @@ export function buildCoordinatorTools(opts: CoordinatorToolsOptions): ToolDefini
|
|
|
227
227
|
},
|
|
228
228
|
})
|
|
229
229
|
|
|
230
|
-
const cancelTask = defineTool({
|
|
231
|
-
name: 'cancel_task',
|
|
232
|
-
description:
|
|
233
|
-
'Cancel a running agent task. Only use this with a task_id from a previous create_task.',
|
|
234
|
-
inputSchema: z.object({
|
|
235
|
-
task_id: z.string().describe('Agent task ID from a previous create_task'),
|
|
236
|
-
}),
|
|
237
|
-
category: 'custom',
|
|
238
|
-
permissions: [],
|
|
239
|
-
readOnly: false,
|
|
240
|
-
destructive: false,
|
|
241
|
-
concurrencySafe: true,
|
|
242
|
-
async execute({ task_id }) {
|
|
243
|
-
gateway.cancelTask(task_id as TaskId)
|
|
244
|
-
return {
|
|
245
|
-
success: true,
|
|
246
|
-
output: `Task ${task_id} cancelled`,
|
|
247
|
-
data: { task_id },
|
|
248
|
-
}
|
|
249
|
-
},
|
|
250
|
-
})
|
|
251
|
-
|
|
252
230
|
const agentTaskList = defineTool({
|
|
253
231
|
name: 'agent_task_list',
|
|
254
232
|
description:
|
|
@@ -305,19 +283,18 @@ export function buildCoordinatorTools(opts: CoordinatorToolsOptions): ToolDefini
|
|
|
305
283
|
},
|
|
306
284
|
})
|
|
307
285
|
|
|
308
|
-
// `continue_task`
|
|
309
|
-
//
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
//
|
|
315
|
-
//
|
|
316
|
-
//
|
|
317
|
-
//
|
|
318
|
-
// for follow-ups) wants to re-register it.
|
|
286
|
+
// `continue_task` and model-facing per-task cancellation both
|
|
287
|
+
// belonged to the old non-blocking worker protocol. With
|
|
288
|
+
// `create_task` now blocking + tool_result returning the worker's
|
|
289
|
+
// final output, every worker is terminal by the time a later model
|
|
290
|
+
// turn learns its task id. The old cancel tool additionally called
|
|
291
|
+
// a void/no-op gateway method and manufactured "cancelled" even for
|
|
292
|
+
// a missing id. Host-owned run interruption still uses the gateway
|
|
293
|
+
// cancellation contract directly; it does not need a model tool.
|
|
294
|
+
// Keep only the follow-up definition for a future non-default
|
|
295
|
+
// gateway that deliberately preserves live workers between turns.
|
|
319
296
|
void continueTask
|
|
320
|
-
const tools: ToolDefinition[] = [createTask,
|
|
297
|
+
const tools: ToolDefinition[] = [createTask, agentTaskList]
|
|
321
298
|
|
|
322
299
|
if (getPlanManager) {
|
|
323
300
|
const approvePlan = defineTool({
|
package/src/tools/defineTool.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface DefineToolOptions<S extends z.ZodType> {
|
|
|
11
11
|
name: string
|
|
12
12
|
description: string
|
|
13
13
|
inputSchema: S
|
|
14
|
+
validationErrorHint?: string
|
|
14
15
|
category: ToolDefinition['category']
|
|
15
16
|
permissions: ToolPermission[]
|
|
16
17
|
readOnly: boolean
|
|
@@ -29,6 +30,7 @@ export function defineTool<S extends z.ZodType>(
|
|
|
29
30
|
name: options.name,
|
|
30
31
|
description: options.description,
|
|
31
32
|
inputSchema: options.inputSchema,
|
|
33
|
+
validationErrorHint: options.validationErrorHint,
|
|
32
34
|
tier: options.tier,
|
|
33
35
|
category: options.category,
|
|
34
36
|
permissions: options.permissions,
|
|
@@ -70,4 +70,40 @@ export interface RegisterOptions {
|
|
|
70
70
|
replace?: boolean
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* What a lazy loader must resolve to: a factory that constructs the
|
|
75
|
+
* provider, plus (optionally) the provider package's authoritative
|
|
76
|
+
* capability declaration resolved at load time.
|
|
77
|
+
*
|
|
78
|
+
* Designed so a host can map a dynamic import in one line:
|
|
79
|
+
*
|
|
80
|
+
* ```ts
|
|
81
|
+
* ProviderRegistry.registerLazy('anthropic', async () => {
|
|
82
|
+
* const m = await import('@namzu/anthropic')
|
|
83
|
+
* return { create: (c) => new m.AnthropicProvider(c), capabilities: m.ANTHROPIC_CAPABILITIES }
|
|
84
|
+
* })
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
export interface LazyProviderModule<C = unknown> {
|
|
88
|
+
create: (config: C) => LLMProvider
|
|
89
|
+
/**
|
|
90
|
+
* Authoritative type-level capabilities shipped by the loaded module.
|
|
91
|
+
* When present, replaces any registration-time hint in the registry.
|
|
92
|
+
*/
|
|
93
|
+
capabilities?: ProviderCapabilities
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export type LazyProviderLoader<C = unknown> = () => Promise<LazyProviderModule<C>>
|
|
97
|
+
|
|
98
|
+
export interface RegisterLazyOptions extends RegisterOptions {
|
|
99
|
+
/**
|
|
100
|
+
* Pre-load capability HINT so `ProviderRegistry.getCapabilities(type)`
|
|
101
|
+
* can answer without triggering the loader. Precedence (weakest first):
|
|
102
|
+
* this hint → the loaded module's `capabilities` → the constructed
|
|
103
|
+
* instance's own `LLMProvider.capabilities` (what the query runtime
|
|
104
|
+
* resolves via `resolveProviderCapabilities` and actually respects).
|
|
105
|
+
*/
|
|
106
|
+
capabilities?: ProviderCapabilities
|
|
107
|
+
}
|
|
108
|
+
|
|
73
109
|
export type LLMProviderConstructor<C = unknown> = new (config: C) => LLMProvider
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** What went wrong, at the coarsest granularity a caller can act on. */
|
|
2
|
+
export type ProviderErrorKind =
|
|
3
|
+
| 'throttle'
|
|
4
|
+
| 'network'
|
|
5
|
+
| 'auth'
|
|
6
|
+
| 'context_overflow'
|
|
7
|
+
| 'bad_request'
|
|
8
|
+
| 'server'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Serializable provider-failure metadata carried by failed runs and events.
|
|
12
|
+
*
|
|
13
|
+
* No response body, vendor message, URL, or `cause` belongs here.
|
|
14
|
+
*/
|
|
15
|
+
export interface ProviderErrorInfo {
|
|
16
|
+
readonly kind: ProviderErrorKind
|
|
17
|
+
readonly providerId: string
|
|
18
|
+
readonly status?: number
|
|
19
|
+
readonly retryAfterMs?: number
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ProviderRequestErrorInit extends ProviderErrorInfo {
|
|
23
|
+
/**
|
|
24
|
+
* Optional extra clause for the message. MUST be text this codebase
|
|
25
|
+
* authored — never a fragment of a response body, a header, or a vendor
|
|
26
|
+
* error.
|
|
27
|
+
*/
|
|
28
|
+
readonly detail?: string
|
|
29
|
+
}
|
|
@@ -8,6 +8,11 @@ export type {
|
|
|
8
8
|
export type { StreamChunk } from './stream.js'
|
|
9
9
|
export type { ModelInfo } from './model.js'
|
|
10
10
|
export type { LLMProvider } from './interface.js'
|
|
11
|
+
export type {
|
|
12
|
+
ProviderErrorInfo,
|
|
13
|
+
ProviderErrorKind,
|
|
14
|
+
ProviderRequestErrorInit,
|
|
15
|
+
} from './error.js'
|
|
11
16
|
export type {
|
|
12
17
|
ProviderConfigRegistry,
|
|
13
18
|
ProviderType,
|
|
@@ -16,5 +21,8 @@ export type {
|
|
|
16
21
|
ProviderCapabilities,
|
|
17
22
|
ProviderFactoryResult,
|
|
18
23
|
RegisterOptions,
|
|
24
|
+
LazyProviderModule,
|
|
25
|
+
LazyProviderLoader,
|
|
26
|
+
RegisterLazyOptions,
|
|
19
27
|
LLMProviderConstructor,
|
|
20
28
|
} from './config.js'
|
package/src/types/run/entity.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AgentStatus, CostInfo, TokenUsage } from '../common/index.js'
|
|
2
2
|
import type { RunId } from '../ids/index.js'
|
|
3
3
|
import type { Message } from '../message/index.js'
|
|
4
|
+
import type { ProviderErrorInfo } from '../provider/index.js'
|
|
4
5
|
import type { AgentRunConfig } from './config.js'
|
|
5
6
|
import type { ReplayAttribution } from './replay.js'
|
|
6
7
|
import type { StopReason } from './stop-reason.js'
|
|
@@ -37,6 +38,7 @@ export interface Run {
|
|
|
37
38
|
endedAt?: number
|
|
38
39
|
stopReason?: StopReason
|
|
39
40
|
lastError?: string
|
|
41
|
+
lastProviderError?: ProviderErrorInfo
|
|
40
42
|
result?: string
|
|
41
43
|
|
|
42
44
|
parentRunId?: RunId
|
package/src/types/run/events.ts
CHANGED
|
@@ -14,6 +14,7 @@ import type {
|
|
|
14
14
|
} from '../ids/index.js'
|
|
15
15
|
import type { PlanStep } from '../plan/index.js'
|
|
16
16
|
import type { PluginHookEvent, PluginHookResult } from '../plugin/index.js'
|
|
17
|
+
import type { ProviderErrorInfo } from '../provider/index.js'
|
|
17
18
|
import type { TaskStatus } from '../task/index.js'
|
|
18
19
|
import type { Lineage } from './lineage.js'
|
|
19
20
|
import type { MessageStopReason } from './stop-reason.js'
|
|
@@ -98,7 +99,12 @@ type CoreRunEvent =
|
|
|
98
99
|
fromCheckpointId: CheckpointId
|
|
99
100
|
}
|
|
100
101
|
| { type: 'run_completed'; runId: RunId; result: string }
|
|
101
|
-
| {
|
|
102
|
+
| {
|
|
103
|
+
type: 'run_failed'
|
|
104
|
+
runId: RunId
|
|
105
|
+
error: string
|
|
106
|
+
providerError?: ProviderErrorInfo
|
|
107
|
+
}
|
|
102
108
|
// Additive 2026-07 (provider capability negotiation): emitted once per
|
|
103
109
|
// run when the request asks for something the provider DRIVER declared
|
|
104
110
|
// it cannot do — tools registered against a no-tools driver (tool
|
package/src/types/tool/index.ts
CHANGED
|
@@ -64,6 +64,12 @@ export interface ToolDefinition<TInput = unknown> {
|
|
|
64
64
|
name: string
|
|
65
65
|
description: string
|
|
66
66
|
inputSchema: z.ZodType<TInput, z.ZodTypeDef, unknown>
|
|
67
|
+
/**
|
|
68
|
+
* Concise, model-readable recovery guidance appended when inputSchema
|
|
69
|
+
* rejects a call. Use for conditional schemas whose required shapes
|
|
70
|
+
* cannot be reconstructed from JSON Schema's top-level `required` list.
|
|
71
|
+
*/
|
|
72
|
+
validationErrorHint?: string
|
|
67
73
|
execute(input: TInput, context: ToolContext): Promise<ToolResult>
|
|
68
74
|
tier?: string
|
|
69
75
|
permissions?: ToolPermission[]
|