@ai-sdk/harness-opencode 1.0.135 → 1.0.137
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 +22 -0
- package/dist/bridge/host-tool-mcp.mjs +76 -93
- package/dist/bridge/host-tool-mcp.mjs.map +1 -1
- package/dist/bridge/index.mjs +2713 -2952
- package/dist/bridge/index.mjs.map +1 -1
- package/dist/index.d.ts +857 -855
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1596 -2004
- package/dist/index.js.map +1 -1
- package/package.json +8 -7
- package/src/bridge/host-tool-mcp.ts +2 -2
- package/src/bridge/index.ts +66 -12
- package/src/index.ts +1 -0
- package/src/opencode-harness.ts +41 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @ai-sdk/harness-opencode
|
|
2
2
|
|
|
3
|
+
## 1.0.137
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 82b6142: fix(harness-opencode): stop aborted OpenCode turns before starting the next turn
|
|
8
|
+
- Updated dependencies [8c65988]
|
|
9
|
+
- Updated dependencies [8182916]
|
|
10
|
+
- Updated dependencies [527a163]
|
|
11
|
+
- @ai-sdk/provider@4.0.21
|
|
12
|
+
- @ai-sdk/provider-utils@5.0.53
|
|
13
|
+
- @ai-sdk/harness@1.0.135
|
|
14
|
+
|
|
15
|
+
## 1.0.136
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- ede5b89: chore: migrate package builds from tsup to tsdown
|
|
20
|
+
- Updated dependencies [ede5b89]
|
|
21
|
+
- @ai-sdk/harness@1.0.134
|
|
22
|
+
- @ai-sdk/provider@4.0.20
|
|
23
|
+
- @ai-sdk/provider-utils@5.0.52
|
|
24
|
+
|
|
3
25
|
## 1.0.135
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
|
@@ -1,117 +1,100 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/bridge/host-tool-mcp.ts
|
|
4
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
5
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
6
|
-
|
|
7
|
-
// src/bridge/json-schema-to-zod.ts
|
|
8
4
|
import { z } from "zod/v4";
|
|
5
|
+
//#region src/bridge/json-schema-to-zod.ts
|
|
9
6
|
function jsonSchemaToZodShape(input) {
|
|
10
|
-
|
|
11
|
-
return toZodShape(schema);
|
|
7
|
+
return toZodShape(isJsonSchemaObject(input) ? input : {});
|
|
12
8
|
}
|
|
13
9
|
function toZodShape(schema) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
10
|
+
if (!schema?.properties) return {};
|
|
11
|
+
const required = new Set(schema.required);
|
|
12
|
+
const shape = {};
|
|
13
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
14
|
+
const propType = toZodType(propSchema);
|
|
15
|
+
shape[key] = required.has(key) ? propType : propType.optional();
|
|
16
|
+
}
|
|
17
|
+
return shape;
|
|
22
18
|
}
|
|
23
19
|
function toZodType(schema) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
20
|
+
if (!schema) return z.any();
|
|
21
|
+
let zType = zodForEnum(schema) ?? zodForType(schema);
|
|
22
|
+
if (schema.description) zType = zType.describe(schema.description);
|
|
23
|
+
if (schema.nullable) zType = zType.nullable();
|
|
24
|
+
if ("default" in schema) zType = zType.meta({ default: schema.default });
|
|
25
|
+
return zType;
|
|
30
26
|
}
|
|
31
27
|
function zodForEnum(schema) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
return z.literal(schema.enum);
|
|
28
|
+
if (!Array.isArray(schema.enum) || schema.enum.length === 0 || !schema.enum.every(isJsonLiteral)) return;
|
|
29
|
+
return z.literal(schema.enum);
|
|
36
30
|
}
|
|
37
31
|
function zodForType(schema) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
case "array":
|
|
49
|
-
return z.array(toZodType(schema.items));
|
|
50
|
-
case "object":
|
|
51
|
-
return z.object(toZodShape(schema));
|
|
52
|
-
case "null":
|
|
53
|
-
return z.null();
|
|
54
|
-
default:
|
|
55
|
-
return z.any();
|
|
56
|
-
}
|
|
32
|
+
switch ((Array.isArray(schema.type) ? schema.type.filter((t) => t !== "null") : [schema.type].filter(Boolean))[0]) {
|
|
33
|
+
case "string": return z.string();
|
|
34
|
+
case "number": return z.number();
|
|
35
|
+
case "integer": return z.number().int();
|
|
36
|
+
case "boolean": return z.boolean();
|
|
37
|
+
case "array": return z.array(toZodType(schema.items));
|
|
38
|
+
case "object": return z.object(toZodShape(schema));
|
|
39
|
+
case "null": return z.null();
|
|
40
|
+
default: return z.any();
|
|
41
|
+
}
|
|
57
42
|
}
|
|
58
43
|
function isJsonSchemaObject(input) {
|
|
59
|
-
|
|
44
|
+
return input != null && typeof input === "object" && !Array.isArray(input);
|
|
60
45
|
}
|
|
61
46
|
function isJsonLiteral(value) {
|
|
62
|
-
|
|
47
|
+
return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
|
|
63
48
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/bridge/host-tool-mcp.ts
|
|
51
|
+
const schemas = JSON.parse(process.env.TOOL_SCHEMAS || "[]");
|
|
52
|
+
const relayUrl = process.env.TOOL_RELAY_URL || "";
|
|
68
53
|
if (!schemas.length || !relayUrl) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
);
|
|
72
|
-
process.exit(0);
|
|
54
|
+
process.stderr.write("[host-tool-mcp] Missing TOOL_SCHEMAS or TOOL_RELAY_URL; exiting\n");
|
|
55
|
+
process.exit(0);
|
|
73
56
|
}
|
|
74
|
-
|
|
57
|
+
const server = new McpServer({
|
|
58
|
+
name: "harness-tools",
|
|
59
|
+
version: "1.0.0"
|
|
60
|
+
});
|
|
75
61
|
for (const schema of schemas) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
content: [{ type: "text", text: `Error: ${String(err)}` }],
|
|
109
|
-
isError: true
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
);
|
|
62
|
+
const shape = jsonSchemaToZodShape(schema.inputSchema);
|
|
63
|
+
server.tool(schema.name, schema.description ?? "", shape, async (input) => {
|
|
64
|
+
const requestId = crypto.randomUUID();
|
|
65
|
+
try {
|
|
66
|
+
const res = await fetch(relayUrl, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: { "Content-Type": "application/json" },
|
|
69
|
+
body: JSON.stringify({
|
|
70
|
+
requestId,
|
|
71
|
+
toolName: schema.name,
|
|
72
|
+
input
|
|
73
|
+
})
|
|
74
|
+
});
|
|
75
|
+
if (!res.ok) {
|
|
76
|
+
const body = await res.text();
|
|
77
|
+
throw new Error(`Tool relay ${schema.name} failed with ${res.status}: ${body.slice(0, 500)}`);
|
|
78
|
+
}
|
|
79
|
+
const data = await res.json();
|
|
80
|
+
return { content: [{
|
|
81
|
+
type: "text",
|
|
82
|
+
text: JSON.stringify(data.result ?? null)
|
|
83
|
+
}] };
|
|
84
|
+
} catch (err) {
|
|
85
|
+
return {
|
|
86
|
+
content: [{
|
|
87
|
+
type: "text",
|
|
88
|
+
text: `Error: ${String(err)}`
|
|
89
|
+
}],
|
|
90
|
+
isError: true
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
114
94
|
}
|
|
115
|
-
|
|
95
|
+
const transport = new StdioServerTransport();
|
|
116
96
|
await server.connect(transport);
|
|
97
|
+
//#endregion
|
|
98
|
+
export {};
|
|
99
|
+
|
|
117
100
|
//# sourceMappingURL=host-tool-mcp.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"host-tool-mcp.mjs","names":[],"sources":["../../src/bridge/json-schema-to-zod.ts","../../src/bridge/host-tool-mcp.ts"],"sourcesContent":["import { z } from 'zod/v4';\n\ntype JsonLiteral = string | number | boolean | null;\n\ntype JsonSchemaObject = {\n type?: string | string[];\n description?: string;\n properties?: Record<string, JsonSchemaObject>;\n required?: string[];\n items?: JsonSchemaObject;\n enum?: unknown[];\n default?: unknown;\n nullable?: boolean;\n};\n\ntype ZodShape = Record<string, z.ZodTypeAny>;\n\nexport function jsonSchemaToZodShape(input: unknown): ZodShape {\n const schema = isJsonSchemaObject(input) ? input : {};\n return toZodShape(schema);\n}\n\nfunction toZodShape(schema: JsonSchemaObject | undefined): ZodShape {\n if (!schema?.properties) return {};\n const required = new Set(schema.required);\n const shape: ZodShape = {};\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n const propType = toZodType(propSchema);\n shape[key] = required.has(key) ? propType : propType.optional();\n }\n return shape;\n}\n\nfunction toZodType(schema: JsonSchemaObject | undefined): z.ZodTypeAny {\n if (!schema) return z.any();\n\n let zType = zodForEnum(schema) ?? zodForType(schema);\n if (schema.description) zType = zType.describe(schema.description);\n if (schema.nullable) zType = zType.nullable();\n if ('default' in schema) zType = zType.meta({ default: schema.default });\n return zType;\n}\n\nfunction zodForEnum(schema: JsonSchemaObject): z.ZodTypeAny | undefined {\n if (\n !Array.isArray(schema.enum) ||\n schema.enum.length === 0 ||\n !schema.enum.every(isJsonLiteral)\n ) {\n return undefined;\n }\n return z.literal(schema.enum);\n}\n\nfunction zodForType(schema: JsonSchemaObject): z.ZodTypeAny {\n const types = Array.isArray(schema.type)\n ? schema.type.filter((t): t is string => t !== 'null')\n : ([schema.type].filter(Boolean) as string[]);\n\n switch (types[0]) {\n case 'string':\n return z.string();\n case 'number':\n return z.number();\n case 'integer':\n return z.number().int();\n case 'boolean':\n return z.boolean();\n case 'array':\n return z.array(toZodType(schema.items));\n case 'object':\n return z.object(toZodShape(schema));\n case 'null':\n return z.null();\n default:\n return z.any();\n }\n}\n\nfunction isJsonSchemaObject(input: unknown): input is JsonSchemaObject {\n return input != null && typeof input === 'object' && !Array.isArray(input);\n}\n\nfunction isJsonLiteral(value: unknown): value is JsonLiteral {\n return (\n value === null ||\n typeof value === 'string' ||\n typeof value === 'boolean' ||\n (typeof value === 'number' && Number.isFinite(value))\n );\n}\n","#!/usr/bin/env node\n/*\n * These bridge imports are externalized by tsdown and resolved inside the\n * sandbox from src/bridge/package.json and its lockfile. Keep this file,\n * tsdown.config.ts, and the bridge package dependency list in sync.\n */\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { jsonSchemaToZodShape } from './json-schema-to-zod';\n\ntype ToolSchema = {\n name: string;\n description?: string;\n inputSchema?: unknown;\n};\n\nconst schemas: ToolSchema[] = JSON.parse(process.env.TOOL_SCHEMAS || '[]');\nconst relayUrl = process.env.TOOL_RELAY_URL || '';\n\nif (!schemas.length || !relayUrl) {\n process.stderr.write(\n '[host-tool-mcp] Missing TOOL_SCHEMAS or TOOL_RELAY_URL; exiting\\n',\n );\n process.exit(0);\n}\n\nconst server = new McpServer({ name: 'harness-tools', version: '1.0.0' });\n\nfor (const schema of schemas) {\n const shape = jsonSchemaToZodShape(schema.inputSchema);\n server.tool(\n schema.name,\n schema.description ?? '',\n shape,\n async (input: Record<string, unknown>) => {\n const requestId = crypto.randomUUID();\n try {\n const res = await fetch(relayUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ requestId, toolName: schema.name, input }),\n });\n if (!res.ok) {\n const body = await res.text();\n throw new Error(\n `Tool relay ${schema.name} failed with ${res.status}: ${body.slice(0, 500)}`,\n );\n }\n const data = (await res.json()) as { result?: unknown };\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(data.result ?? null),\n },\n ],\n };\n } catch (err) {\n return {\n content: [{ type: 'text' as const, text: `Error: ${String(err)}` }],\n isError: true,\n };\n }\n },\n );\n}\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n"],"mappings":"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"}
|