@automatalabs/acp-agents 0.20.2 → 0.20.3
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/dist/backends/claude.d.ts.map +1 -1
- package/dist/backends/claude.js +6 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/schema-strict.d.ts +12 -1
- package/dist/schema-strict.d.ts.map +1 -1
- package/dist/schema-strict.js +135 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/backends/claude.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAM5E,qBAAa,aAAc,YAAW,OAAO;IAC3C,QAAQ,CAAC,EAAE,EAAG,QAAQ,CAAU;IAEhC,WAAW,IAAI,WAAW;IAgB1B,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/backends/claude.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAM5E,qBAAa,aAAc,YAAW,OAAO;IAC3C,QAAQ,CAAC,EAAE,EAAG,QAAQ,CAAU;IAEhC,WAAW,IAAI,WAAW;IAgB1B,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAmB7E,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS;IAKjD,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO;CAGpD"}
|
package/dist/backends/claude.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// `_claude/sdkMessage` extension notification (the runner's ACP client captures it).
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { splitArgs } from "../backend.js";
|
|
9
|
-
import {
|
|
9
|
+
import { toAnthropicJsonSchema } from "../schema-strict.js";
|
|
10
10
|
const require = createRequire(import.meta.url);
|
|
11
11
|
export class ClaudeBackend {
|
|
12
12
|
id = "claude";
|
|
@@ -31,10 +31,14 @@ export class ClaudeBackend {
|
|
|
31
31
|
// optional SessionMetaInputs (the seam still accepts them via the Backend interface).
|
|
32
32
|
if (!schema)
|
|
33
33
|
return undefined;
|
|
34
|
+
// Anthropic structured outputs accept only a JSON-Schema subset (additionalProperties:false
|
|
35
|
+
// required on every object; numeric/string/array constraints rejected). Normalize the wire
|
|
36
|
+
// copy so the native constraint always engages — an incompatible schema would fail the SDK
|
|
37
|
+
// constraint and silently degrade the run to unconstrained text + the repair ladder.
|
|
34
38
|
const meta = {
|
|
35
39
|
claudeCode: {
|
|
36
40
|
options: {
|
|
37
|
-
outputFormat: { type: "json_schema", schema:
|
|
41
|
+
outputFormat: { type: "json_schema", schema: toAnthropicJsonSchema(schema) },
|
|
38
42
|
},
|
|
39
43
|
emitRawSDKMessages: true,
|
|
40
44
|
},
|
package/dist/index.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export { decidePermission } from "./permissions.js";
|
|
|
27
27
|
export type { ElicitationResolver, PermissionResolver, ToolPolicy } from "./permissions.js";
|
|
28
28
|
export { UsageAccumulator } from "./usage.js";
|
|
29
29
|
export type { McpAcpServerConfig, McpServerConfig } from "@automatalabs/shared-types";
|
|
30
|
-
export { toJsonSchema, toStrictJsonSchema } from "./schema-strict.js";
|
|
30
|
+
export { toAnthropicJsonSchema, toJsonSchema, toStrictJsonSchema } from "./schema-strict.js";
|
|
31
31
|
export { extractValidated, findJsonBlock, parseFinalJson, resolveStructuredOutput, validateValue, } from "./structured-output.js";
|
|
32
32
|
export type { ResolveOptions, StructuredSession } from "./structured-output.js";
|
|
33
33
|
export { ACP_AUTH_REQUIRED_ERROR_CODE, errorText, mapThrownError } from "./errors-map.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,6 @@ export { OpenCodeBackend } from "./backends/opencode.js";
|
|
|
26
26
|
export { CustomAcpBackend } from "./backends/custom.js";
|
|
27
27
|
export { decidePermission } from "./permissions.js";
|
|
28
28
|
export { UsageAccumulator } from "./usage.js";
|
|
29
|
-
export { toJsonSchema, toStrictJsonSchema } from "./schema-strict.js";
|
|
29
|
+
export { toAnthropicJsonSchema, toJsonSchema, toStrictJsonSchema } from "./schema-strict.js";
|
|
30
30
|
export { extractValidated, findJsonBlock, parseFinalJson, resolveStructuredOutput, validateValue, } from "./structured-output.js";
|
|
31
31
|
export { ACP_AUTH_REQUIRED_ERROR_CODE, errorText, mapThrownError } from "./errors-map.js";
|
package/dist/schema-strict.d.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import type { TSchema } from "typebox";
|
|
2
|
-
/** Deep-clone a typebox schema into a plain JSON Schema object (
|
|
2
|
+
/** Deep-clone a typebox schema into a plain JSON Schema object (prompt embedding / MCP tool
|
|
3
|
+
* inputSchema — surfaces with no provider-side keyword restrictions). */
|
|
3
4
|
export declare function toJsonSchema(schema: TSchema): Record<string, unknown>;
|
|
5
|
+
/**
|
|
6
|
+
* Deep-clone a typebox schema and normalize it to the subset Anthropic structured outputs
|
|
7
|
+
* accepts (Claude `outputFormat.schema`): additionalProperties:false on every object,
|
|
8
|
+
* unsupported validation keywords / formats / regex features stripped, oneOf -> anyOf.
|
|
9
|
+
* Authored `required` is preserved (optional properties stay optional). Without this, an
|
|
10
|
+
* Anthropic-incompatible schema makes the SDK's native constraint fail and the run silently
|
|
11
|
+
* degrades to unconstrained text + the repair ladder. Operates on the clone only — the schema
|
|
12
|
+
* that feeds hashAgentCall is never mutated.
|
|
13
|
+
*/
|
|
14
|
+
export declare function toAnthropicJsonSchema(schema: TSchema): Record<string, unknown>;
|
|
4
15
|
/**
|
|
5
16
|
* Deep-clone a typebox schema and normalize it to OpenAI STRICT rules (Codex
|
|
6
17
|
* `turn/start.outputSchema`): every property required, additionalProperties:false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-strict.d.ts","sourceRoot":"","sources":["../src/schema-strict.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC
|
|
1
|
+
{"version":3,"file":"schema-strict.d.ts","sourceRoot":"","sources":["../src/schema-strict.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAEvC;0EAC0E;AAC1E,wBAAgB,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAErE;AAqHD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG9E;AAmMD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAG3E"}
|
package/dist/schema-strict.js
CHANGED
|
@@ -1,7 +1,135 @@
|
|
|
1
|
-
/** Deep-clone a typebox schema into a plain JSON Schema object (
|
|
1
|
+
/** Deep-clone a typebox schema into a plain JSON Schema object (prompt embedding / MCP tool
|
|
2
|
+
* inputSchema — surfaces with no provider-side keyword restrictions). */
|
|
2
3
|
export function toJsonSchema(schema) {
|
|
3
4
|
return JSON.parse(JSON.stringify(schema));
|
|
4
5
|
}
|
|
6
|
+
// JSON-Schema keywords Anthropic structured outputs REJECTS with a 400 (numeric/string/array
|
|
7
|
+
// constraints, composition/annotation keywords outside its supported subset). Stripped on the
|
|
8
|
+
// COPY sent as Claude's `outputFormat.schema`; the ORIGINAL schema still backs the client-side
|
|
9
|
+
// typebox validation, so a stripped constraint is enforced there instead of on the wire.
|
|
10
|
+
const ANTHROPIC_UNSUPPORTED_KEYWORDS = new Set([
|
|
11
|
+
"$schema",
|
|
12
|
+
"$id",
|
|
13
|
+
"title",
|
|
14
|
+
"examples",
|
|
15
|
+
"minLength",
|
|
16
|
+
"maxLength",
|
|
17
|
+
"minimum",
|
|
18
|
+
"maximum",
|
|
19
|
+
"exclusiveMinimum",
|
|
20
|
+
"exclusiveMaximum",
|
|
21
|
+
"multipleOf",
|
|
22
|
+
"maxItems",
|
|
23
|
+
"uniqueItems",
|
|
24
|
+
"contains",
|
|
25
|
+
"minContains",
|
|
26
|
+
"maxContains",
|
|
27
|
+
"minProperties",
|
|
28
|
+
"maxProperties",
|
|
29
|
+
"contentEncoding",
|
|
30
|
+
"contentMediaType",
|
|
31
|
+
"patternProperties",
|
|
32
|
+
"additionalItems",
|
|
33
|
+
"unevaluatedProperties",
|
|
34
|
+
"unevaluatedItems",
|
|
35
|
+
"dependencies",
|
|
36
|
+
"dependentRequired",
|
|
37
|
+
"dependentSchemas",
|
|
38
|
+
"propertyNames",
|
|
39
|
+
"if",
|
|
40
|
+
"then",
|
|
41
|
+
"else",
|
|
42
|
+
"not",
|
|
43
|
+
"readOnly",
|
|
44
|
+
"writeOnly",
|
|
45
|
+
"deprecated",
|
|
46
|
+
]);
|
|
47
|
+
// The only `format` values Anthropic structured outputs accepts; any other value is a 400.
|
|
48
|
+
const ANTHROPIC_SUPPORTED_FORMATS = new Set([
|
|
49
|
+
"date-time",
|
|
50
|
+
"time",
|
|
51
|
+
"date",
|
|
52
|
+
"duration",
|
|
53
|
+
"email",
|
|
54
|
+
"hostname",
|
|
55
|
+
"uri",
|
|
56
|
+
"ipv4",
|
|
57
|
+
"ipv6",
|
|
58
|
+
"uuid",
|
|
59
|
+
]);
|
|
60
|
+
// Regex features Anthropic's `pattern` support excludes: backreferences, lookaround, word
|
|
61
|
+
// boundaries. A pattern using any of these is dropped from the wire copy (typebox still
|
|
62
|
+
// enforces it client-side) rather than risking a 400 that silently disables the constraint.
|
|
63
|
+
const ANTHROPIC_UNSUPPORTED_REGEX = /\\[1-9]|\(\?<?[=!]|\\[bB]/;
|
|
64
|
+
/** Keys whose value is a NAME -> subschema map: the names are data, not JSON-Schema keywords,
|
|
65
|
+
* so keyword filtering must not apply to them (a property literally named "format" survives). */
|
|
66
|
+
const SCHEMA_MAP_KEYS = new Set(["properties", "$defs", "definitions"]);
|
|
67
|
+
function normalizeSchemaMap(value, normalize) {
|
|
68
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
69
|
+
return value;
|
|
70
|
+
const out = {};
|
|
71
|
+
for (const [name, sub] of Object.entries(value)) {
|
|
72
|
+
out[name] = normalize(sub);
|
|
73
|
+
}
|
|
74
|
+
return out;
|
|
75
|
+
}
|
|
76
|
+
function normalizeAnthropicNode(node) {
|
|
77
|
+
if (Array.isArray(node))
|
|
78
|
+
return node.map(normalizeAnthropicNode);
|
|
79
|
+
if (node === null || typeof node !== "object")
|
|
80
|
+
return node;
|
|
81
|
+
const input = node;
|
|
82
|
+
const out = {};
|
|
83
|
+
for (const [key, value] of Object.entries(input)) {
|
|
84
|
+
if (SCHEMA_MAP_KEYS.has(key)) {
|
|
85
|
+
out[key] = normalizeSchemaMap(value, normalizeAnthropicNode);
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (ANTHROPIC_UNSUPPORTED_KEYWORDS.has(key))
|
|
89
|
+
continue;
|
|
90
|
+
if (key === "minItems") {
|
|
91
|
+
// Supported only for the values 0 and 1; anything larger is a 400.
|
|
92
|
+
if (value === 0 || value === 1)
|
|
93
|
+
out[key] = value;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (key === "format") {
|
|
97
|
+
if (typeof value === "string" && ANTHROPIC_SUPPORTED_FORMATS.has(value))
|
|
98
|
+
out[key] = value;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (key === "pattern") {
|
|
102
|
+
if (typeof value === "string" && !ANTHROPIC_UNSUPPORTED_REGEX.test(value))
|
|
103
|
+
out[key] = value;
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
// `oneOf` is not in Anthropic's supported subset; its branches are an exclusive subset of
|
|
107
|
+
// anyOf, so mapping over only widens acceptance — typebox re-narrows client-side.
|
|
108
|
+
const targetKey = key === "oneOf" ? "anyOf" : key;
|
|
109
|
+
out[targetKey] = normalizeAnthropicNode(value);
|
|
110
|
+
}
|
|
111
|
+
// Anthropic REQUIRES additionalProperties:false on EVERY object (true / a subschema / absent
|
|
112
|
+
// are all 400s). Unlike OpenAI strict, `required` is left as authored — Anthropic allows
|
|
113
|
+
// optional properties, so no all-required forcing and no null-widening here.
|
|
114
|
+
const properties = out["properties"];
|
|
115
|
+
const isObjectSchema = out["type"] === "object" || (out["type"] === undefined && properties !== undefined);
|
|
116
|
+
if (isObjectSchema)
|
|
117
|
+
out["additionalProperties"] = false;
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Deep-clone a typebox schema and normalize it to the subset Anthropic structured outputs
|
|
122
|
+
* accepts (Claude `outputFormat.schema`): additionalProperties:false on every object,
|
|
123
|
+
* unsupported validation keywords / formats / regex features stripped, oneOf -> anyOf.
|
|
124
|
+
* Authored `required` is preserved (optional properties stay optional). Without this, an
|
|
125
|
+
* Anthropic-incompatible schema makes the SDK's native constraint fail and the run silently
|
|
126
|
+
* degrades to unconstrained text + the repair ladder. Operates on the clone only — the schema
|
|
127
|
+
* that feeds hashAgentCall is never mutated.
|
|
128
|
+
*/
|
|
129
|
+
export function toAnthropicJsonSchema(schema) {
|
|
130
|
+
const clone = JSON.parse(JSON.stringify(schema));
|
|
131
|
+
return normalizeAnthropicNode(clone);
|
|
132
|
+
}
|
|
5
133
|
// JSON-Schema keywords OpenAI strict structured output does NOT accept. Stripped on the
|
|
6
134
|
// COPY before sending to Codex (turn/start.outputSchema is sent in strict mode). Structural
|
|
7
135
|
// keywords (type/properties/items/enum/anyOf/oneOf/allOf/$ref/$defs/definitions/const/
|
|
@@ -57,6 +185,12 @@ function normalizeStrictNode(node) {
|
|
|
57
185
|
}
|
|
58
186
|
const out = {};
|
|
59
187
|
for (const [key, value] of Object.entries(input)) {
|
|
188
|
+
if (SCHEMA_MAP_KEYS.has(key)) {
|
|
189
|
+
// name -> subschema maps: the names are data, never keyword-filtered (a property
|
|
190
|
+
// literally named "format" or "title" must survive).
|
|
191
|
+
out[key] = normalizeSchemaMap(value, normalizeStrictNode);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
60
194
|
if (STRICT_UNSUPPORTED_KEYWORDS.has(key))
|
|
61
195
|
continue;
|
|
62
196
|
// OpenAI strict accepts `anyOf` but not `oneOf` — map it over (its branches are an
|