@botbotgo/agent-harness 0.0.400 → 0.0.402
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/README.md +17 -0
- package/README.zh.md +17 -0
- package/dist/contracts/runtime-observability.d.ts +25 -0
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/runtime/adapter/flow/stream-runtime.js +16 -1
- package/dist/runtime/adapter/local-tool-invocation.js +242 -14
- package/dist/runtime/adapter/middleware-assembly.js +1 -1
- package/dist/runtime/adapter/model/invocation-request.js +1 -1
- package/dist/runtime/adapter/model/model-providers.js +178 -119
- package/dist/runtime/adapter/stream-event-projection.js +70 -5
- package/dist/runtime/adapter/tool/tool-hitl.js +49 -6
- package/dist/runtime/agent-runtime-adapter.d.ts +2 -0
- package/dist/runtime/agent-runtime-adapter.js +329 -36
- package/dist/runtime/harness/bindings.js +2 -0
- package/dist/runtime/harness/tool-gateway/index.d.ts +2 -0
- package/dist/runtime/harness/tool-gateway/index.js +2 -0
- package/dist/runtime/harness/tool-gateway/policy.d.ts +2 -0
- package/dist/runtime/harness/tool-gateway/policy.js +45 -0
- package/dist/runtime/harness/tool-gateway/validation.d.ts +33 -0
- package/dist/runtime/harness/tool-gateway/validation.js +176 -0
- package/dist/runtime/parsing/output-recovery.js +1 -4
- package/package.json +15 -15
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
function isRecord(value) {
|
|
2
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
|
+
}
|
|
4
|
+
function readJsonSchemaType(schema) {
|
|
5
|
+
if (!isRecord(schema)) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const type = schema.type;
|
|
9
|
+
if (typeof type === "string") {
|
|
10
|
+
return [type];
|
|
11
|
+
}
|
|
12
|
+
return Array.isArray(type) ? type.filter((entry) => typeof entry === "string") : [];
|
|
13
|
+
}
|
|
14
|
+
function typeMatches(value, allowedTypes) {
|
|
15
|
+
if (allowedTypes.length === 0) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (value === null) {
|
|
19
|
+
return allowedTypes.includes("null");
|
|
20
|
+
}
|
|
21
|
+
return allowedTypes.some((type) => {
|
|
22
|
+
if (type === "integer") {
|
|
23
|
+
return Number.isInteger(value);
|
|
24
|
+
}
|
|
25
|
+
if (type === "array") {
|
|
26
|
+
return Array.isArray(value);
|
|
27
|
+
}
|
|
28
|
+
if (type === "object") {
|
|
29
|
+
return isRecord(value);
|
|
30
|
+
}
|
|
31
|
+
return typeof value === type;
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function toPath(path) {
|
|
35
|
+
if (path.length === 0) {
|
|
36
|
+
return "$";
|
|
37
|
+
}
|
|
38
|
+
let rendered = "$";
|
|
39
|
+
for (const part of path) {
|
|
40
|
+
rendered = typeof part === "number" ? `${rendered}[${part}]` : `${rendered}.${part}`;
|
|
41
|
+
}
|
|
42
|
+
return rendered;
|
|
43
|
+
}
|
|
44
|
+
function zodIssues(error) {
|
|
45
|
+
const issues = isRecord(error) && Array.isArray(error.issues) ? error.issues : [];
|
|
46
|
+
return issues
|
|
47
|
+
.map((issue) => {
|
|
48
|
+
if (!isRecord(issue)) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
const path = Array.isArray(issue.path) ? issue.path.filter((part) => typeof part === "string" || typeof part === "number") : [];
|
|
52
|
+
const message = typeof issue.message === "string" ? issue.message : "Invalid value";
|
|
53
|
+
return {
|
|
54
|
+
path: toPath(path),
|
|
55
|
+
message,
|
|
56
|
+
...(typeof issue.expected === "string" ? { expected: issue.expected } : {}),
|
|
57
|
+
...(typeof issue.received === "string" ? { received: issue.received } : {}),
|
|
58
|
+
};
|
|
59
|
+
})
|
|
60
|
+
.filter((issue) => issue !== null);
|
|
61
|
+
}
|
|
62
|
+
function validateJsonSchemaObject(schema, input) {
|
|
63
|
+
const issues = [];
|
|
64
|
+
const rootTypes = readJsonSchemaType(schema);
|
|
65
|
+
if (!typeMatches(input, rootTypes.length > 0 ? rootTypes : ["object"])) {
|
|
66
|
+
return [{
|
|
67
|
+
path: "$",
|
|
68
|
+
message: "Tool input must match the declared schema root type.",
|
|
69
|
+
expected: rootTypes.join("|") || "object",
|
|
70
|
+
received: Array.isArray(input) ? "array" : input === null ? "null" : typeof input,
|
|
71
|
+
}];
|
|
72
|
+
}
|
|
73
|
+
if (!isRecord(input)) {
|
|
74
|
+
return issues;
|
|
75
|
+
}
|
|
76
|
+
const properties = isRecord(schema.properties) ? schema.properties : {};
|
|
77
|
+
const required = Array.isArray(schema.required)
|
|
78
|
+
? schema.required.filter((entry) => typeof entry === "string")
|
|
79
|
+
: [];
|
|
80
|
+
for (const key of required) {
|
|
81
|
+
if (!(key in input)) {
|
|
82
|
+
issues.push({
|
|
83
|
+
path: `$.${key}`,
|
|
84
|
+
message: "Required tool argument is missing.",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
for (const [key, value] of Object.entries(input)) {
|
|
89
|
+
const fieldSchema = properties[key];
|
|
90
|
+
if (!fieldSchema) {
|
|
91
|
+
if (schema.additionalProperties === false) {
|
|
92
|
+
issues.push({
|
|
93
|
+
path: `$.${key}`,
|
|
94
|
+
message: "Unexpected tool argument.",
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const fieldTypes = readJsonSchemaType(fieldSchema);
|
|
100
|
+
if (!typeMatches(value, fieldTypes)) {
|
|
101
|
+
issues.push({
|
|
102
|
+
path: `$.${key}`,
|
|
103
|
+
message: "Tool argument has the wrong type.",
|
|
104
|
+
...(fieldTypes.length > 0 ? { expected: fieldTypes.join("|") } : {}),
|
|
105
|
+
received: Array.isArray(value) ? "array" : value === null ? "null" : typeof value,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
if (isRecord(fieldSchema) && Array.isArray(fieldSchema.enum) && !fieldSchema.enum.includes(value)) {
|
|
109
|
+
issues.push({
|
|
110
|
+
path: `$.${key}`,
|
|
111
|
+
message: "Tool argument must be one of the declared enum values.",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return issues;
|
|
116
|
+
}
|
|
117
|
+
export function createInvalidToolArgumentsResult(input) {
|
|
118
|
+
return {
|
|
119
|
+
isError: true,
|
|
120
|
+
code: "INVALID_ARGUMENTS",
|
|
121
|
+
toolName: input.toolName,
|
|
122
|
+
message: `Tool ${input.toolName} received invalid arguments. Correct the arguments to match the declared schema before retrying.`,
|
|
123
|
+
retryable: !input.requiresApproval,
|
|
124
|
+
requiresApproval: input.requiresApproval,
|
|
125
|
+
validationErrors: input.issues.length > 0
|
|
126
|
+
? input.issues
|
|
127
|
+
: [{ path: "$", message: "Tool input failed schema validation." }],
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export function validateToolGatewayInput(input) {
|
|
131
|
+
const schema = input.schema;
|
|
132
|
+
const requiresApproval = input.requiresApproval === true;
|
|
133
|
+
if (schema && typeof schema.safeParse === "function") {
|
|
134
|
+
const parsed = schema.safeParse(input.args);
|
|
135
|
+
if (parsed.success) {
|
|
136
|
+
return { ok: true, input: parsed.data };
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
ok: false,
|
|
140
|
+
error: createInvalidToolArgumentsResult({
|
|
141
|
+
toolName: input.toolName,
|
|
142
|
+
requiresApproval,
|
|
143
|
+
issues: zodIssues(parsed.error),
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (schema && typeof schema.parse === "function") {
|
|
148
|
+
try {
|
|
149
|
+
return { ok: true, input: schema.parse(input.args) };
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
return {
|
|
153
|
+
ok: false,
|
|
154
|
+
error: createInvalidToolArgumentsResult({
|
|
155
|
+
toolName: input.toolName,
|
|
156
|
+
requiresApproval,
|
|
157
|
+
issues: zodIssues(error),
|
|
158
|
+
}),
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (isRecord(input.schema) && (input.schema.type === "object" || isRecord(input.schema.properties))) {
|
|
163
|
+
const issues = validateJsonSchemaObject(input.schema, input.args);
|
|
164
|
+
if (issues.length > 0) {
|
|
165
|
+
return {
|
|
166
|
+
ok: false,
|
|
167
|
+
error: createInvalidToolArgumentsResult({
|
|
168
|
+
toolName: input.toolName,
|
|
169
|
+
requiresApproval,
|
|
170
|
+
issues,
|
|
171
|
+
}),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return { ok: true, input: input.args };
|
|
176
|
+
}
|
|
@@ -118,10 +118,7 @@ export function resolveMissingPlanRecoveryInstruction(params) {
|
|
|
118
118
|
if (params.requiresPlan !== true || hasPlanEvidence) {
|
|
119
119
|
return null;
|
|
120
120
|
}
|
|
121
|
-
|
|
122
|
-
return WRITE_TODOS_REQUIRED_PLAN_INSTRUCTION;
|
|
123
|
-
}
|
|
124
|
-
return null;
|
|
121
|
+
return WRITE_TODOS_REQUIRED_PLAN_INSTRUCTION;
|
|
125
122
|
}
|
|
126
123
|
export function resolveExecutionWithoutToolEvidenceInstruction(request, result) {
|
|
127
124
|
const assistantText = readTextContent(result).trim();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botbotgo/agent-harness",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.402",
|
|
4
4
|
"description": "Workspace runtime for multi-agent applications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -47,21 +47,21 @@
|
|
|
47
47
|
}
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@langchain/anthropic": "^1.3.
|
|
51
|
-
"@langchain/core": "^1.1.
|
|
52
|
-
"@langchain/google": "^0.1.
|
|
50
|
+
"@langchain/anthropic": "^1.3.28",
|
|
51
|
+
"@langchain/core": "^1.1.43",
|
|
52
|
+
"@langchain/google": "^0.1.11",
|
|
53
53
|
"@langchain/langgraph": "^1.2.9",
|
|
54
|
-
"@langchain/ollama": "^1.2.
|
|
55
|
-
"@langchain/openai": "^1.4.
|
|
56
|
-
"@libsql/client": "^0.17.
|
|
57
|
-
"@llamaindex/ollama": "^0.1.
|
|
58
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
54
|
+
"@langchain/ollama": "^1.2.7",
|
|
55
|
+
"@langchain/openai": "^1.4.5",
|
|
56
|
+
"@libsql/client": "^0.17.3",
|
|
57
|
+
"@llamaindex/ollama": "^0.1.24",
|
|
58
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
59
59
|
"@qdrant/js-client-rest": "1.17.0",
|
|
60
60
|
"deepagents": "^1.9.0",
|
|
61
|
-
"langchain": "^1.3.
|
|
61
|
+
"langchain": "^1.3.5",
|
|
62
62
|
"llamaindex": "^0.12.1",
|
|
63
63
|
"mustache": "^4.2.0",
|
|
64
|
-
"yaml": "^2.8.
|
|
64
|
+
"yaml": "^2.8.3",
|
|
65
65
|
"zod": "^3.25.76"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
@@ -88,10 +88,10 @@
|
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@langchain/community": "^1.1.27",
|
|
91
|
-
"@types/node": "^25.
|
|
91
|
+
"@types/node": "^25.6.0",
|
|
92
92
|
"typescript": "^6.0.2",
|
|
93
|
-
"vite": "^
|
|
94
|
-
"vitest": "^4.1.
|
|
93
|
+
"vite": "^8.0.10",
|
|
94
|
+
"vitest": "^4.1.5"
|
|
95
95
|
},
|
|
96
96
|
"overrides": {
|
|
97
97
|
"axios": "^1.15.0",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"uuid": "^14.0.0",
|
|
103
103
|
"undici": "^6.24.0",
|
|
104
104
|
"@qdrant/js-client-rest": "1.17.0",
|
|
105
|
-
"vite": "^
|
|
105
|
+
"vite": "^8.0.10",
|
|
106
106
|
"openai": "6.33.0",
|
|
107
107
|
"protobufjs": "^7.5.5"
|
|
108
108
|
}
|