@ziggs-ai/agent-sdk 0.10.2 → 0.10.4
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.
|
@@ -53,6 +53,25 @@ function parametersToZodShape(parameters) {
|
|
|
53
53
|
}
|
|
54
54
|
return shape;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* ZIG-1215 — the Claude brain's args are validated here, before `eff` hands
|
|
58
|
+
* them to the shared executor, so a plain shape means an unknown param is
|
|
59
|
+
* stripped at this layer and ToolManager's own check never sees it. Closing
|
|
60
|
+
* the object is what makes the rejection reach the brain: the call fails with
|
|
61
|
+
* the offending key named, instead of succeeding on a request it silently
|
|
62
|
+
* altered. The published schema also carries `additionalProperties: false`,
|
|
63
|
+
* so the typo is usually caught before the call is made at all.
|
|
64
|
+
*/
|
|
65
|
+
function strictParams(toolName, shape) {
|
|
66
|
+
const accepted = Object.keys(shape).join(', ') || '(none)';
|
|
67
|
+
return z.strictObject(shape, {
|
|
68
|
+
error: (issue) => issue.code === 'unrecognized_keys'
|
|
69
|
+
? `Unknown parameter(s) ${issue.keys.map((k) => `"${k}"`).join(', ')} — ` +
|
|
70
|
+
`${toolName} did not run. Accepted params: ${accepted}. ` +
|
|
71
|
+
`Check for a typo and call again; nothing was changed.`
|
|
72
|
+
: undefined,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
56
75
|
function toCallToolResult(value) {
|
|
57
76
|
const text = typeof value === 'string' ? value : JSON.stringify(value, null, 2);
|
|
58
77
|
return { content: [{ type: 'text', text }] };
|
|
@@ -71,9 +90,10 @@ export function buildSdkToolDefs(toolDefs, getContext) {
|
|
|
71
90
|
const name = String(fn['name'] ?? '');
|
|
72
91
|
const description = String(fn['description'] ?? name);
|
|
73
92
|
const shape = parametersToZodShape(fn['parameters']);
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
// A zero-param tool keeps the `_` envelope the Claude SDK needs, but the
|
|
94
|
+
// envelope itself is closed too — its free-form payload is still checked
|
|
95
|
+
// against the tool's own schema downstream in ToolManager.
|
|
96
|
+
const inputSchema = strictParams(name, Object.keys(shape).length > 0 ? shape : { _: z.record(z.string(), z.unknown()).optional() });
|
|
77
97
|
return {
|
|
78
98
|
name,
|
|
79
99
|
description,
|
|
@@ -9,6 +9,25 @@ function makeError(message, type, extra) {
|
|
|
9
9
|
Object.assign(err, extra);
|
|
10
10
|
return err;
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* ZIG-1215 — Ajv's own wording for a rejected unknown param is "must NOT have
|
|
14
|
+
* additional properties", which names neither the offending key nor the ones
|
|
15
|
+
* that would have worked. An agent reading that has nothing to correct against,
|
|
16
|
+
* so the typo is named alongside the menu it should have come from.
|
|
17
|
+
*/
|
|
18
|
+
function describeErrors(parameters, errors) {
|
|
19
|
+
const unknown = (errors ?? [])
|
|
20
|
+
.map((e) => e)
|
|
21
|
+
.filter((e) => e.keyword === 'additionalProperties')
|
|
22
|
+
.map((e) => e.params?.additionalProperty)
|
|
23
|
+
.filter((k) => typeof k === 'string');
|
|
24
|
+
if (unknown.length === 0)
|
|
25
|
+
return ajv.errorsText(errors);
|
|
26
|
+
const props = parameters.properties ?? {};
|
|
27
|
+
const accepted = Object.keys(props).join(', ') || '(none)';
|
|
28
|
+
return (`unknown parameter(s) ${unknown.map((k) => `"${k}"`).join(', ')} — ` +
|
|
29
|
+
`accepted params: ${accepted}. Check for a typo and call again; nothing was changed.`);
|
|
30
|
+
}
|
|
12
31
|
function stripNullish(args) {
|
|
13
32
|
if (!args || typeof args !== 'object' || Array.isArray(args))
|
|
14
33
|
return args;
|
|
@@ -68,7 +87,7 @@ export class ToolManager extends ToolProvider {
|
|
|
68
87
|
const validate = ajv.compile(parameters);
|
|
69
88
|
if (!validate(args)) {
|
|
70
89
|
const name = tool.schema.function?.['name'];
|
|
71
|
-
throw makeError(`Invalid args for "${name}": ${
|
|
90
|
+
throw makeError(`Invalid args for "${name}": ${describeErrors(parameters, validate.errors)}`, 'validation_error', { data: { errors: validate.errors } });
|
|
72
91
|
}
|
|
73
92
|
}
|
|
74
93
|
}
|
package/dist/tools/defineTool.js
CHANGED
|
@@ -48,7 +48,14 @@ export function defineTool(name, params, handler, options = {}) {
|
|
|
48
48
|
throw new Error('defineTool: name is required');
|
|
49
49
|
if (!handler || typeof handler !== 'function')
|
|
50
50
|
throw new Error('defineTool: handler function is required');
|
|
51
|
-
|
|
51
|
+
// ZIG-1215 — the top level is closed so a misspelled param is rejected by
|
|
52
|
+
// ToolManager's Ajv pass instead of being dropped on the floor. JSON Schema
|
|
53
|
+
// allows unknown keys by default, so without this the validation ran and
|
|
54
|
+
// passed while the handler quietly ignored what the model asked for.
|
|
55
|
+
// Nested objects stay open: the typo class this guards against is at the
|
|
56
|
+
// call surface the model writes, and closing nested payloads (task result,
|
|
57
|
+
// plan) would reject shapes the backend accepts.
|
|
58
|
+
const parameters = { ...convertObject(params || {}), additionalProperties: false };
|
|
52
59
|
const fn = { name, parameters };
|
|
53
60
|
if (options.description)
|
|
54
61
|
fn['description'] = options.description;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/agent-sdk",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.4",
|
|
4
4
|
"description": "Agent framework SDK for building autonomous agents on the Ziggs platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@anthropic-ai/claude-agent-sdk": "^0.3.204",
|
|
27
27
|
"@anthropic-ai/sdk": "^0.110.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
|
-
"@ziggs-ai/api-client": "^0.9.
|
|
29
|
+
"@ziggs-ai/api-client": "^0.9.3",
|
|
30
30
|
"ajv": "^8.17.1",
|
|
31
31
|
"dotenv": "^17.2.3",
|
|
32
32
|
"openai": "^4.0.0",
|