@contractspec/lib.ai-agent 5.0.4 → 6.0.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/README.md +41 -0
- package/dist/agent/agent-factory.d.ts +13 -0
- package/dist/agent/agent-factory.js +290 -63
- package/dist/agent/contract-spec-agent.d.ts +9 -0
- package/dist/agent/contract-spec-agent.js +287 -63
- package/dist/agent/index.js +353 -129
- package/dist/agent/json-runner.js +290 -66
- package/dist/agent/unified-agent.js +350 -126
- package/dist/exporters/claude-agent-exporter.js +12 -1
- package/dist/exporters/index.js +12 -1
- package/dist/exporters/opencode-exporter.js +11 -0
- package/dist/index.js +11 -0
- package/dist/interop/index.js +24 -2
- package/dist/interop/spec-consumer.js +11 -0
- package/dist/interop/tool-consumer.js +13 -2
- package/dist/node/agent/agent-factory.js +290 -63
- package/dist/node/agent/contract-spec-agent.js +287 -63
- package/dist/node/agent/index.js +353 -129
- package/dist/node/agent/json-runner.js +290 -66
- package/dist/node/agent/unified-agent.js +350 -126
- package/dist/node/exporters/claude-agent-exporter.js +12 -1
- package/dist/node/exporters/index.js +12 -1
- package/dist/node/exporters/opencode-exporter.js +11 -0
- package/dist/node/index.js +11 -0
- package/dist/node/interop/index.js +24 -2
- package/dist/node/interop/spec-consumer.js +11 -0
- package/dist/node/interop/tool-consumer.js +13 -2
- package/dist/node/providers/claude-agent-sdk/adapter.js +11 -0
- package/dist/node/providers/claude-agent-sdk/index.js +11 -0
- package/dist/node/providers/index.js +11 -0
- package/dist/node/providers/opencode-sdk/adapter.js +11 -0
- package/dist/node/providers/opencode-sdk/index.js +11 -0
- package/dist/node/spec/index.js +11 -0
- package/dist/node/spec/spec.js +11 -0
- package/dist/node/tools/agent-memory-store.js +24 -0
- package/dist/node/tools/in-memory-agent-memory-store.js +236 -0
- package/dist/node/tools/index.js +463 -42
- package/dist/node/tools/memory-tools.js +45 -0
- package/dist/node/tools/operation-tool-handler.js +35 -0
- package/dist/node/tools/subagent-tool.js +95 -0
- package/dist/node/tools/tool-adapter.js +192 -25
- package/dist/providers/claude-agent-sdk/adapter.js +11 -0
- package/dist/providers/claude-agent-sdk/index.js +11 -0
- package/dist/providers/index.js +11 -0
- package/dist/providers/opencode-sdk/adapter.js +11 -0
- package/dist/providers/opencode-sdk/index.js +11 -0
- package/dist/spec/index.js +11 -0
- package/dist/spec/spec.d.ts +69 -1
- package/dist/spec/spec.js +11 -0
- package/dist/tools/agent-memory-store.d.ts +26 -0
- package/dist/tools/agent-memory-store.js +24 -0
- package/dist/tools/agent-memory-store.test.d.ts +1 -0
- package/dist/tools/in-memory-agent-memory-store.d.ts +18 -0
- package/dist/tools/in-memory-agent-memory-store.js +236 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +463 -42
- package/dist/tools/mcp-client.browser.d.ts +6 -6
- package/dist/tools/memory-tools.d.ts +29 -0
- package/dist/tools/memory-tools.js +45 -0
- package/dist/tools/operation-tool-handler.d.ts +24 -0
- package/dist/tools/operation-tool-handler.js +35 -0
- package/dist/tools/subagent-tool.d.ts +66 -0
- package/dist/tools/subagent-tool.js +95 -0
- package/dist/tools/tool-adapter.d.ts +26 -10
- package/dist/tools/tool-adapter.js +192 -25
- package/dist/types.d.ts +9 -3
- package/package.json +67 -7
package/dist/node/agent/index.js
CHANGED
|
@@ -2156,6 +2156,17 @@ function defineAgent(spec) {
|
|
|
2156
2156
|
}));
|
|
2157
2157
|
}
|
|
2158
2158
|
toolNames.add(tool.name);
|
|
2159
|
+
if (tool.subagentRef && tool.operationRef) {
|
|
2160
|
+
throw new Error(`Agent ${spec.meta.key} tool "${tool.name}" cannot have both subagentRef and operationRef. Use one.`);
|
|
2161
|
+
}
|
|
2162
|
+
const outputRefCount = [
|
|
2163
|
+
tool.outputPresentation,
|
|
2164
|
+
tool.outputForm,
|
|
2165
|
+
tool.outputDataView
|
|
2166
|
+
].filter(Boolean).length;
|
|
2167
|
+
if (outputRefCount > 1) {
|
|
2168
|
+
throw new Error(`Agent ${spec.meta.key} tool "${tool.name}" has multiple output refs (outputPresentation, outputForm, outputDataView). Use at most one.`);
|
|
2169
|
+
}
|
|
2159
2170
|
}
|
|
2160
2171
|
return Object.freeze(spec);
|
|
2161
2172
|
}
|
|
@@ -2299,15 +2310,124 @@ function jsonSchemaToZodSafe(schema) {
|
|
|
2299
2310
|
}
|
|
2300
2311
|
var init_json_schema_to_zod = () => {};
|
|
2301
2312
|
|
|
2313
|
+
// src/tools/operation-tool-handler.ts
|
|
2314
|
+
function toolCtxToHandlerCtx(ctx) {
|
|
2315
|
+
return {
|
|
2316
|
+
traceId: ctx.metadata?.traceId,
|
|
2317
|
+
organizationId: ctx.tenantId ?? null,
|
|
2318
|
+
userId: ctx.actorId ?? null,
|
|
2319
|
+
actor: ctx.actorId ? "user" : "anonymous",
|
|
2320
|
+
channel: "agent",
|
|
2321
|
+
roles: []
|
|
2322
|
+
};
|
|
2323
|
+
}
|
|
2324
|
+
function createOperationToolHandler(registry, operationRef) {
|
|
2325
|
+
return async (input, context) => {
|
|
2326
|
+
const handlerCtx = toolCtxToHandlerCtx(context);
|
|
2327
|
+
const result = await registry.execute(operationRef.key, operationRef.version, input ?? {}, handlerCtx);
|
|
2328
|
+
return result;
|
|
2329
|
+
};
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
// src/tools/subagent-tool.ts
|
|
2333
|
+
import { readUIMessageStream, tool } from "ai";
|
|
2334
|
+
import { z as z2 } from "zod";
|
|
2335
|
+
function toReadableStream(iterable) {
|
|
2336
|
+
if (iterable instanceof ReadableStream) {
|
|
2337
|
+
return iterable;
|
|
2338
|
+
}
|
|
2339
|
+
return new ReadableStream({
|
|
2340
|
+
async start(controller) {
|
|
2341
|
+
try {
|
|
2342
|
+
for await (const chunk of iterable) {
|
|
2343
|
+
controller.enqueue(chunk);
|
|
2344
|
+
}
|
|
2345
|
+
} finally {
|
|
2346
|
+
controller.close();
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2351
|
+
function createSubagentTool(options) {
|
|
2352
|
+
const {
|
|
2353
|
+
subagent,
|
|
2354
|
+
description = "Research a topic or question in depth.",
|
|
2355
|
+
taskParam = "task",
|
|
2356
|
+
toModelSummary = true,
|
|
2357
|
+
passConversationHistory = false
|
|
2358
|
+
} = options;
|
|
2359
|
+
const inputSchema = z2.object({
|
|
2360
|
+
[taskParam]: z2.string().describe("The research task to complete")
|
|
2361
|
+
});
|
|
2362
|
+
const execute = async function* (input, options2) {
|
|
2363
|
+
const task = String(input[taskParam] ?? input.task ?? "");
|
|
2364
|
+
const { abortSignal, messages } = options2 ?? {};
|
|
2365
|
+
if (passConversationHistory && messages && messages.length > 0 && typeof subagent.generate === "function") {
|
|
2366
|
+
const result2 = await subagent.generate({
|
|
2367
|
+
messages: [...messages, { role: "user", content: task }],
|
|
2368
|
+
abortSignal
|
|
2369
|
+
});
|
|
2370
|
+
yield { parts: [{ type: "text", text: result2.text }] };
|
|
2371
|
+
return;
|
|
2372
|
+
}
|
|
2373
|
+
const result = await subagent.stream({
|
|
2374
|
+
prompt: task,
|
|
2375
|
+
abortSignal
|
|
2376
|
+
});
|
|
2377
|
+
const uiStream = result.toUIMessageStream();
|
|
2378
|
+
const stream = toReadableStream(uiStream);
|
|
2379
|
+
for await (const message of readUIMessageStream({
|
|
2380
|
+
stream
|
|
2381
|
+
})) {
|
|
2382
|
+
yield message;
|
|
2383
|
+
}
|
|
2384
|
+
};
|
|
2385
|
+
const toolOptions = {
|
|
2386
|
+
description,
|
|
2387
|
+
inputSchema,
|
|
2388
|
+
execute,
|
|
2389
|
+
...toModelSummary && {
|
|
2390
|
+
toModelOutput: ({
|
|
2391
|
+
output
|
|
2392
|
+
}) => {
|
|
2393
|
+
const parts = output?.parts;
|
|
2394
|
+
if (!Array.isArray(parts)) {
|
|
2395
|
+
return { type: "text", value: "Task completed." };
|
|
2396
|
+
}
|
|
2397
|
+
const lastTextPart = [...parts].reverse().find((p) => p?.type === "text");
|
|
2398
|
+
return {
|
|
2399
|
+
type: "text",
|
|
2400
|
+
value: lastTextPart?.text ?? "Task completed."
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2403
|
+
}
|
|
2404
|
+
};
|
|
2405
|
+
return tool(toolOptions);
|
|
2406
|
+
}
|
|
2407
|
+
var init_subagent_tool = () => {};
|
|
2408
|
+
|
|
2302
2409
|
// src/tools/tool-adapter.ts
|
|
2303
|
-
import { tool } from "ai";
|
|
2304
|
-
function
|
|
2410
|
+
import { tool as tool2 } from "ai";
|
|
2411
|
+
function isAsyncGenerator(value) {
|
|
2412
|
+
return typeof value === "object" && value !== null && typeof value.next === "function" && typeof value[Symbol.asyncIterator] === "function";
|
|
2413
|
+
}
|
|
2414
|
+
function specToolToAISDKTool(specTool, handler, context = {}, effectiveInputSchema, operationSpec) {
|
|
2305
2415
|
let lastInvocationAt;
|
|
2306
|
-
|
|
2416
|
+
const inputSchema = effectiveInputSchema ?? jsonSchemaToZodSafe(specTool.schema);
|
|
2417
|
+
const buildContext = (signal) => ({
|
|
2418
|
+
agentId: context.agentId ?? "unknown",
|
|
2419
|
+
sessionId: context.sessionId ?? "unknown",
|
|
2420
|
+
tenantId: context.tenantId,
|
|
2421
|
+
actorId: context.actorId,
|
|
2422
|
+
locale: context.locale,
|
|
2423
|
+
metadata: context.metadata,
|
|
2424
|
+
signal
|
|
2425
|
+
});
|
|
2426
|
+
return tool2({
|
|
2307
2427
|
description: specTool.description ?? specTool.name,
|
|
2308
|
-
inputSchema
|
|
2428
|
+
inputSchema,
|
|
2309
2429
|
needsApproval: specTool.requiresApproval ?? !specTool.automationSafe,
|
|
2310
|
-
execute: async (input)
|
|
2430
|
+
execute: async function* (input, options) {
|
|
2311
2431
|
const now = Date.now();
|
|
2312
2432
|
const cooldownMs = normalizeDuration(specTool.cooldownMs);
|
|
2313
2433
|
if (cooldownMs && lastInvocationAt !== undefined) {
|
|
@@ -2318,19 +2438,20 @@ function specToolToAISDKTool(specTool, handler, context = {}) {
|
|
|
2318
2438
|
}
|
|
2319
2439
|
}
|
|
2320
2440
|
const timeoutMs = normalizeDuration(specTool.timeoutMs);
|
|
2321
|
-
const
|
|
2441
|
+
const signal = options?.abortSignal ?? context.signal;
|
|
2442
|
+
const { signal: timeoutSignal, dispose } = createTimeoutSignal(signal, timeoutMs);
|
|
2322
2443
|
try {
|
|
2323
|
-
const execution = handler(input,
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2444
|
+
const execution = handler(input, buildContext(timeoutSignal));
|
|
2445
|
+
if (isAsyncGenerator(execution)) {
|
|
2446
|
+
for await (const raw of execution) {
|
|
2447
|
+
const wrapped = wrapToolOutputForRendering(specTool, raw, operationSpec);
|
|
2448
|
+
yield typeof wrapped === "string" ? wrapped : wrapped;
|
|
2449
|
+
}
|
|
2450
|
+
} else {
|
|
2451
|
+
const raw = timeoutMs ? await withTimeout(Promise.resolve(execution), timeoutMs, specTool.name) : await Promise.resolve(execution);
|
|
2452
|
+
const wrapped = wrapToolOutputForRendering(specTool, raw, operationSpec);
|
|
2453
|
+
yield typeof wrapped === "string" ? wrapped : wrapped;
|
|
2454
|
+
}
|
|
2334
2455
|
} finally {
|
|
2335
2456
|
dispose();
|
|
2336
2457
|
lastInvocationAt = Date.now();
|
|
@@ -2338,27 +2459,83 @@ function specToolToAISDKTool(specTool, handler, context = {}) {
|
|
|
2338
2459
|
}
|
|
2339
2460
|
});
|
|
2340
2461
|
}
|
|
2341
|
-
function specToolsToAISDKTools(specTools, handlers, context = {}) {
|
|
2462
|
+
function specToolsToAISDKTools(specTools, handlers, context = {}, options) {
|
|
2342
2463
|
const tools = {};
|
|
2343
2464
|
for (const specTool of specTools) {
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
}
|
|
2465
|
+
if (specTool.subagentRef && options?.subagentRegistry) {
|
|
2466
|
+
const subagent = options.subagentRegistry.get(specTool.subagentRef.agentId);
|
|
2467
|
+
if (!subagent) {
|
|
2468
|
+
throw new Error(`Subagent not found: ${specTool.subagentRef.agentId}. Register it in subagentRegistry.`);
|
|
2469
|
+
}
|
|
2470
|
+
if (specTool.requiresApproval === true || specTool.automationSafe === false) {
|
|
2471
|
+
console.warn(`[ContractSpec] Subagent tool "${specTool.name}" cannot use needsApproval. ` + `requiresApproval and automationSafe are ignored for subagent tools (AI SDK limitation). ` + `See https://ai-sdk.dev/docs/agents/subagents#no-tool-approvals-in-subagents`);
|
|
2472
|
+
}
|
|
2473
|
+
tools[specTool.name] = createSubagentTool({
|
|
2474
|
+
subagent,
|
|
2475
|
+
description: specTool.description ?? specTool.name,
|
|
2476
|
+
toModelSummary: specTool.subagentRef.toModelSummary ?? true,
|
|
2477
|
+
passConversationHistory: specTool.subagentRef.passConversationHistory
|
|
2478
|
+
});
|
|
2479
|
+
continue;
|
|
2349
2480
|
}
|
|
2350
|
-
|
|
2481
|
+
let handler;
|
|
2482
|
+
let effectiveInputSchema;
|
|
2483
|
+
let op;
|
|
2484
|
+
if (specTool.operationRef && options?.operationRegistry) {
|
|
2485
|
+
op = options.operationRegistry.get(specTool.operationRef.key, specTool.operationRef.version);
|
|
2486
|
+
if (!op) {
|
|
2487
|
+
throw new Error(`Operation not found: ${specTool.operationRef.key}${specTool.operationRef.version ? `.v${specTool.operationRef.version}` : ""}`);
|
|
2488
|
+
}
|
|
2489
|
+
handler = createOperationToolHandler(options.operationRegistry, specTool.operationRef);
|
|
2490
|
+
effectiveInputSchema = op.io.input?.getZod?.();
|
|
2491
|
+
} else {
|
|
2492
|
+
const manualHandler = handlers.get(specTool.name);
|
|
2493
|
+
if (!manualHandler) {
|
|
2494
|
+
if (specTool.subagentRef) {
|
|
2495
|
+
throw new Error(`Subagent tool "${specTool.name}" requires subagentRegistry. Pass subagentRegistry in ContractSpecAgentConfig.`);
|
|
2496
|
+
}
|
|
2497
|
+
throw new Error(createAgentI18n(context.locale).t("error.missingToolHandler", {
|
|
2498
|
+
name: specTool.name
|
|
2499
|
+
}));
|
|
2500
|
+
}
|
|
2501
|
+
handler = manualHandler;
|
|
2502
|
+
}
|
|
2503
|
+
tools[specTool.name] = specToolToAISDKTool(specTool, handler, context, effectiveInputSchema, op);
|
|
2351
2504
|
}
|
|
2352
2505
|
return tools;
|
|
2353
2506
|
}
|
|
2354
2507
|
function createToolHandler(handler) {
|
|
2355
|
-
return
|
|
2508
|
+
return (input, context) => {
|
|
2356
2509
|
return handler(input, context);
|
|
2357
2510
|
};
|
|
2358
2511
|
}
|
|
2359
2512
|
function buildToolHandlers(handlersObj) {
|
|
2360
2513
|
return new Map(Object.entries(handlersObj));
|
|
2361
2514
|
}
|
|
2515
|
+
function wrapToolOutputForRendering(specTool, result, operationSpec) {
|
|
2516
|
+
const presentation = specTool.outputPresentation ?? operationSpec?.outputPresentation;
|
|
2517
|
+
const form = specTool.outputForm ?? operationSpec?.outputForm;
|
|
2518
|
+
const dataView = specTool.outputDataView ?? operationSpec?.outputDataView;
|
|
2519
|
+
if (presentation) {
|
|
2520
|
+
return {
|
|
2521
|
+
presentationKey: presentation.key,
|
|
2522
|
+
data: result
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2525
|
+
if (form) {
|
|
2526
|
+
return {
|
|
2527
|
+
formKey: form.key,
|
|
2528
|
+
defaultValues: typeof result === "object" && result !== null ? result : {}
|
|
2529
|
+
};
|
|
2530
|
+
}
|
|
2531
|
+
if (dataView) {
|
|
2532
|
+
return {
|
|
2533
|
+
dataViewKey: dataView.key,
|
|
2534
|
+
items: Array.isArray(result) ? result : result != null ? [result] : []
|
|
2535
|
+
};
|
|
2536
|
+
}
|
|
2537
|
+
return result;
|
|
2538
|
+
}
|
|
2362
2539
|
function normalizeDuration(value) {
|
|
2363
2540
|
if (value === undefined) {
|
|
2364
2541
|
return;
|
|
@@ -2420,11 +2597,12 @@ function createToolExecutionError(message, code, retryAfterMs) {
|
|
|
2420
2597
|
var init_tool_adapter = __esm(() => {
|
|
2421
2598
|
init_json_schema_to_zod();
|
|
2422
2599
|
init_i18n();
|
|
2600
|
+
init_subagent_tool();
|
|
2423
2601
|
});
|
|
2424
2602
|
|
|
2425
2603
|
// src/tools/knowledge-tool.ts
|
|
2426
|
-
import { tool as
|
|
2427
|
-
import * as
|
|
2604
|
+
import { tool as tool3 } from "ai";
|
|
2605
|
+
import * as z3 from "zod";
|
|
2428
2606
|
function createKnowledgeQueryTool(retriever, knowledgeRefs, locale) {
|
|
2429
2607
|
const i18n = createAgentI18n(locale);
|
|
2430
2608
|
const optionalSpaces = knowledgeRefs.filter((k) => !k.required).map((k) => k.key).filter((key) => retriever.supportsSpace(key));
|
|
@@ -2433,15 +2611,15 @@ function createKnowledgeQueryTool(retriever, knowledgeRefs, locale) {
|
|
|
2433
2611
|
}
|
|
2434
2612
|
const spaceDescriptions = knowledgeRefs.filter((k) => !k.required && retriever.supportsSpace(k.key)).map((k) => `- ${k.key}: ${k.instructions ?? i18n.t("tool.knowledge.spaceDefault")}`).join(`
|
|
2435
2613
|
`);
|
|
2436
|
-
return
|
|
2614
|
+
return tool3({
|
|
2437
2615
|
description: `${i18n.t("tool.knowledge.description")}
|
|
2438
2616
|
|
|
2439
2617
|
${i18n.t("tool.knowledge.availableSpaces")}
|
|
2440
2618
|
${spaceDescriptions}`,
|
|
2441
|
-
inputSchema:
|
|
2442
|
-
query:
|
|
2443
|
-
spaceKey:
|
|
2444
|
-
topK:
|
|
2619
|
+
inputSchema: z3.object({
|
|
2620
|
+
query: z3.string().describe(i18n.t("tool.knowledge.param.query")),
|
|
2621
|
+
spaceKey: z3.enum(optionalSpaces).optional().describe(i18n.t("tool.knowledge.param.spaceKey")),
|
|
2622
|
+
topK: z3.number().optional().default(5).describe(i18n.t("tool.knowledge.param.topK"))
|
|
2445
2623
|
}),
|
|
2446
2624
|
execute: async ({ query, spaceKey, topK }) => {
|
|
2447
2625
|
const spacesToSearch = spaceKey ? [spaceKey] : optionalSpaces;
|
|
@@ -2481,6 +2659,33 @@ var init_knowledge_tool = __esm(() => {
|
|
|
2481
2659
|
init_i18n();
|
|
2482
2660
|
});
|
|
2483
2661
|
|
|
2662
|
+
// src/tools/memory-tools.ts
|
|
2663
|
+
import { anthropic } from "@ai-sdk/anthropic";
|
|
2664
|
+
function createAnthropicMemoryTool(store) {
|
|
2665
|
+
const memory = anthropic.tools.memory_20250818({
|
|
2666
|
+
execute: async (action) => {
|
|
2667
|
+
switch (action.command) {
|
|
2668
|
+
case "view":
|
|
2669
|
+
return store.view(action.path ?? "/memories", action.view_range);
|
|
2670
|
+
case "create":
|
|
2671
|
+
return store.create(action.path ?? "/memories/untitled", action.file_text ?? "");
|
|
2672
|
+
case "str_replace":
|
|
2673
|
+
return store.strReplace(action.path ?? "/memories", action.old_str ?? "", action.new_str ?? "");
|
|
2674
|
+
case "insert":
|
|
2675
|
+
return store.insert(action.path ?? "/memories", action.insert_line ?? 0, action.insert_text ?? "");
|
|
2676
|
+
case "delete":
|
|
2677
|
+
return store.delete(action.path ?? "/memories");
|
|
2678
|
+
case "rename":
|
|
2679
|
+
return store.rename(action.old_path ?? "/memories", action.new_path ?? "/memories");
|
|
2680
|
+
default:
|
|
2681
|
+
return `Unknown command: ${action.command}`;
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
});
|
|
2685
|
+
return memory;
|
|
2686
|
+
}
|
|
2687
|
+
var init_memory_tools = () => {};
|
|
2688
|
+
|
|
2484
2689
|
// src/tools/mcp-client-helpers.ts
|
|
2485
2690
|
import {
|
|
2486
2691
|
Experimental_StdioMCPTransport as StdioClientTransport
|
|
@@ -2511,8 +2716,8 @@ function prefixToolNames(config, tools) {
|
|
|
2511
2716
|
return tools;
|
|
2512
2717
|
}
|
|
2513
2718
|
const prefixedTools = {};
|
|
2514
|
-
for (const [toolName,
|
|
2515
|
-
prefixedTools[`${prefix}_${toolName}`] =
|
|
2719
|
+
for (const [toolName, tool4] of Object.entries(tools)) {
|
|
2720
|
+
prefixedTools[`${prefix}_${toolName}`] = tool4;
|
|
2516
2721
|
}
|
|
2517
2722
|
return prefixedTools;
|
|
2518
2723
|
}
|
|
@@ -2618,12 +2823,12 @@ async function createMcpToolsets(configs, options = {}) {
|
|
|
2618
2823
|
for (const [serverName, toolNames] of Object.entries(result.serverToolNames)) {
|
|
2619
2824
|
serverToolNames[serverName] = toolNames;
|
|
2620
2825
|
}
|
|
2621
|
-
for (const [toolName,
|
|
2826
|
+
for (const [toolName, tool4] of Object.entries(result.tools)) {
|
|
2622
2827
|
const hasCollision = combinedTools[toolName] !== undefined;
|
|
2623
2828
|
if (hasCollision && collisionStrategy === "error") {
|
|
2624
2829
|
throw new Error(`Duplicate MCP tool name "${toolName}" detected. Use "toolPrefix" or set onNameCollision to "overwrite".`);
|
|
2625
2830
|
}
|
|
2626
|
-
combinedTools[toolName] =
|
|
2831
|
+
combinedTools[toolName] = tool4;
|
|
2627
2832
|
}
|
|
2628
2833
|
}
|
|
2629
2834
|
} catch (error) {
|
|
@@ -3146,7 +3351,7 @@ import {
|
|
|
3146
3351
|
stepCountIs
|
|
3147
3352
|
} from "ai";
|
|
3148
3353
|
import { randomUUID } from "node:crypto";
|
|
3149
|
-
import * as
|
|
3354
|
+
import * as z4 from "zod";
|
|
3150
3355
|
|
|
3151
3356
|
class ContractSpecAgent {
|
|
3152
3357
|
version = "agent-v1";
|
|
@@ -3175,12 +3380,19 @@ class ContractSpecAgent {
|
|
|
3175
3380
|
}
|
|
3176
3381
|
try {
|
|
3177
3382
|
const instructions = await injectStaticKnowledge(effectiveConfig.spec.instructions, effectiveConfig.spec.knowledge ?? [], effectiveConfig.knowledgeRetriever);
|
|
3178
|
-
const specTools = specToolsToAISDKTools(effectiveConfig.spec.tools, effectiveConfig.toolHandlers, { agentId: agentKey(effectiveConfig.spec.meta) }
|
|
3383
|
+
const specTools = specToolsToAISDKTools(effectiveConfig.spec.tools, effectiveConfig.toolHandlers, { agentId: agentKey(effectiveConfig.spec.meta) }, {
|
|
3384
|
+
operationRegistry: effectiveConfig.operationRegistry,
|
|
3385
|
+
subagentRegistry: effectiveConfig.subagentRegistry
|
|
3386
|
+
});
|
|
3179
3387
|
const knowledgeTool = effectiveConfig.knowledgeRetriever ? createKnowledgeQueryTool(effectiveConfig.knowledgeRetriever, effectiveConfig.spec.knowledge ?? []) : null;
|
|
3388
|
+
const memoryTool = effectiveConfig.spec.memoryTools?.provider === "anthropic" && effectiveConfig.agentMemoryStore ? createAnthropicMemoryTool(effectiveConfig.agentMemoryStore) : null;
|
|
3180
3389
|
const reservedToolNames = new Set(Object.keys(specTools));
|
|
3181
3390
|
if (knowledgeTool) {
|
|
3182
3391
|
reservedToolNames.add("query_knowledge");
|
|
3183
3392
|
}
|
|
3393
|
+
if (memoryTool) {
|
|
3394
|
+
reservedToolNames.add("memory");
|
|
3395
|
+
}
|
|
3184
3396
|
const conflictingMcpTools = Object.keys(mcpToolset?.tools ?? {}).filter((toolName) => reservedToolNames.has(toolName));
|
|
3185
3397
|
if (conflictingMcpTools.length > 0) {
|
|
3186
3398
|
throw new Error(`MCP tools conflict with agent tools: ${conflictingMcpTools.join(", ")}. Configure MCP toolPrefix values to avoid collisions.`);
|
|
@@ -3188,6 +3400,7 @@ class ContractSpecAgent {
|
|
|
3188
3400
|
const tools = {
|
|
3189
3401
|
...specTools,
|
|
3190
3402
|
...knowledgeTool ? { query_knowledge: knowledgeTool } : {},
|
|
3403
|
+
...memoryTool ? { memory: memoryTool } : {},
|
|
3191
3404
|
...mcpToolset?.tools ?? {},
|
|
3192
3405
|
...effectiveConfig.additionalTools ?? {}
|
|
3193
3406
|
};
|
|
@@ -3219,7 +3432,7 @@ class ContractSpecAgent {
|
|
|
3219
3432
|
stepIndex: 0,
|
|
3220
3433
|
stepStartedAt: new Date
|
|
3221
3434
|
});
|
|
3222
|
-
if (this.config.sessionStore) {
|
|
3435
|
+
if (this.config.sessionStore && !params.messages?.length) {
|
|
3223
3436
|
const existing = await this.config.sessionStore.get(sessionId);
|
|
3224
3437
|
if (!existing) {
|
|
3225
3438
|
await this.config.sessionStore.create({
|
|
@@ -3237,14 +3450,9 @@ class ContractSpecAgent {
|
|
|
3237
3450
|
}
|
|
3238
3451
|
await this.config.sessionStore.appendMessage(sessionId, {
|
|
3239
3452
|
role: "user",
|
|
3240
|
-
content: params.prompt
|
|
3453
|
+
content: params.prompt ?? ""
|
|
3241
3454
|
});
|
|
3242
3455
|
}
|
|
3243
|
-
const prompt = params.systemOverride ? `${this.instructions}
|
|
3244
|
-
|
|
3245
|
-
${params.systemOverride}
|
|
3246
|
-
|
|
3247
|
-
${params.prompt}` : params.prompt;
|
|
3248
3456
|
const model = await this.resolveModelForCall({
|
|
3249
3457
|
sessionId,
|
|
3250
3458
|
traceId,
|
|
@@ -3252,18 +3460,33 @@ ${params.prompt}` : params.prompt;
|
|
|
3252
3460
|
});
|
|
3253
3461
|
const effectiveMaxSteps = resolveMaxSteps(params.maxSteps, this.spec.maxSteps);
|
|
3254
3462
|
const inner = this.createInnerAgent(model, effectiveMaxSteps);
|
|
3463
|
+
const generateOptions = {
|
|
3464
|
+
abortSignal: params.signal,
|
|
3465
|
+
options: {
|
|
3466
|
+
tenantId: params.options?.tenantId,
|
|
3467
|
+
actorId: params.options?.actorId,
|
|
3468
|
+
sessionId,
|
|
3469
|
+
metadata: params.options?.metadata
|
|
3470
|
+
}
|
|
3471
|
+
};
|
|
3255
3472
|
let result;
|
|
3256
3473
|
try {
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3474
|
+
if (params.messages && params.messages.length > 0) {
|
|
3475
|
+
result = await inner.generate({
|
|
3476
|
+
messages: params.messages,
|
|
3477
|
+
...generateOptions
|
|
3478
|
+
});
|
|
3479
|
+
} else {
|
|
3480
|
+
const prompt = params.systemOverride && params.prompt ? `${this.instructions}
|
|
3481
|
+
|
|
3482
|
+
${params.systemOverride}
|
|
3483
|
+
|
|
3484
|
+
${params.prompt}` : params.prompt ?? "";
|
|
3485
|
+
result = await inner.generate({
|
|
3486
|
+
prompt,
|
|
3487
|
+
...generateOptions
|
|
3488
|
+
});
|
|
3489
|
+
}
|
|
3267
3490
|
} catch (error) {
|
|
3268
3491
|
if (this.config.sessionStore) {
|
|
3269
3492
|
await this.config.sessionStore.update(sessionId, {
|
|
@@ -3323,11 +3546,11 @@ ${params.prompt}` : params.prompt;
|
|
|
3323
3546
|
stepIndex: 0,
|
|
3324
3547
|
stepStartedAt: new Date
|
|
3325
3548
|
});
|
|
3326
|
-
const prompt = params.systemOverride ? `${this.instructions}
|
|
3549
|
+
const prompt = params.systemOverride && params.prompt ? `${this.instructions}
|
|
3327
3550
|
|
|
3328
3551
|
${params.systemOverride}
|
|
3329
3552
|
|
|
3330
|
-
${params.prompt}` : params.prompt;
|
|
3553
|
+
${params.prompt}` : params.prompt ?? "";
|
|
3331
3554
|
const model = await this.resolveModelForCall({
|
|
3332
3555
|
sessionId,
|
|
3333
3556
|
traceId,
|
|
@@ -3351,7 +3574,7 @@ ${params.prompt}` : params.prompt;
|
|
|
3351
3574
|
}
|
|
3352
3575
|
await this.config.sessionStore.appendMessage(sessionId, {
|
|
3353
3576
|
role: "user",
|
|
3354
|
-
content:
|
|
3577
|
+
content: prompt
|
|
3355
3578
|
});
|
|
3356
3579
|
await this.config.sessionStore.update(sessionId, { status: "running" });
|
|
3357
3580
|
}
|
|
@@ -3482,14 +3705,15 @@ var init_contract_spec_agent = __esm(() => {
|
|
|
3482
3705
|
init_spec();
|
|
3483
3706
|
init_tool_adapter();
|
|
3484
3707
|
init_knowledge_tool();
|
|
3708
|
+
init_memory_tools();
|
|
3485
3709
|
init_mcp_client();
|
|
3486
3710
|
init_injector();
|
|
3487
3711
|
init_adapter();
|
|
3488
|
-
ContractSpecCallOptionsSchema =
|
|
3489
|
-
tenantId:
|
|
3490
|
-
actorId:
|
|
3491
|
-
sessionId:
|
|
3492
|
-
metadata:
|
|
3712
|
+
ContractSpecCallOptionsSchema = z4.object({
|
|
3713
|
+
tenantId: z4.string().optional(),
|
|
3714
|
+
actorId: z4.string().optional(),
|
|
3715
|
+
sessionId: z4.string().optional(),
|
|
3716
|
+
metadata: z4.record(z4.string(), z4.unknown()).optional()
|
|
3493
3717
|
});
|
|
3494
3718
|
});
|
|
3495
3719
|
|
|
@@ -3534,12 +3758,12 @@ var init_types = __esm(() => {
|
|
|
3534
3758
|
});
|
|
3535
3759
|
|
|
3536
3760
|
// src/providers/claude-agent-sdk/tool-bridge.ts
|
|
3537
|
-
function specToolToClaudeAgentTool(
|
|
3761
|
+
function specToolToClaudeAgentTool(tool4, handler, context) {
|
|
3538
3762
|
return {
|
|
3539
|
-
name:
|
|
3540
|
-
description:
|
|
3541
|
-
input_schema: normalizeSchema(
|
|
3542
|
-
requires_confirmation:
|
|
3763
|
+
name: tool4.name,
|
|
3764
|
+
description: tool4.description ?? createAgentI18n().t("tool.fallbackDescription", { name: tool4.name }),
|
|
3765
|
+
input_schema: normalizeSchema(tool4.schema),
|
|
3766
|
+
requires_confirmation: tool4.requiresApproval ?? !tool4.automationSafe,
|
|
3543
3767
|
execute: async (input) => {
|
|
3544
3768
|
const fullContext = {
|
|
3545
3769
|
agentId: context.agentId ?? "unknown",
|
|
@@ -3554,14 +3778,14 @@ function specToolToClaudeAgentTool(tool3, handler, context) {
|
|
|
3554
3778
|
};
|
|
3555
3779
|
}
|
|
3556
3780
|
function specToolsToClaudeAgentTools(tools, handlers, context) {
|
|
3557
|
-
return tools.filter((
|
|
3558
|
-
const handler = handlers.get(
|
|
3781
|
+
return tools.filter((tool4) => handlers.has(tool4.name)).map((tool4) => {
|
|
3782
|
+
const handler = handlers.get(tool4.name);
|
|
3559
3783
|
if (!handler) {
|
|
3560
3784
|
throw new Error(createAgentI18n().t("error.handlerNotFoundForTool", {
|
|
3561
|
-
name:
|
|
3785
|
+
name: tool4.name
|
|
3562
3786
|
}));
|
|
3563
3787
|
}
|
|
3564
|
-
return specToolToClaudeAgentTool(
|
|
3788
|
+
return specToolToClaudeAgentTool(tool4, handler, context);
|
|
3565
3789
|
});
|
|
3566
3790
|
}
|
|
3567
3791
|
function claudeAgentToolToSpecTool(claudeTool, execute) {
|
|
@@ -3587,12 +3811,12 @@ function claudeAgentToolsToSpecTools(claudeTools) {
|
|
|
3587
3811
|
}
|
|
3588
3812
|
return { configs, handlers };
|
|
3589
3813
|
}
|
|
3590
|
-
function specToolToExternalTool(
|
|
3814
|
+
function specToolToExternalTool(tool4, handler, context) {
|
|
3591
3815
|
return {
|
|
3592
|
-
name:
|
|
3593
|
-
description:
|
|
3594
|
-
inputSchema:
|
|
3595
|
-
requiresApproval:
|
|
3816
|
+
name: tool4.name,
|
|
3817
|
+
description: tool4.description ?? createAgentI18n().t("tool.fallbackDescription", { name: tool4.name }),
|
|
3818
|
+
inputSchema: tool4.schema ?? { type: "object" },
|
|
3819
|
+
requiresApproval: tool4.requiresApproval ?? !tool4.automationSafe,
|
|
3596
3820
|
execute: handler ? async (input) => {
|
|
3597
3821
|
const fullContext = {
|
|
3598
3822
|
agentId: context?.agentId ?? "unknown",
|
|
@@ -3793,8 +4017,8 @@ class ClaudeAgentSDKProvider {
|
|
|
3793
4017
|
let mcpToolset = null;
|
|
3794
4018
|
try {
|
|
3795
4019
|
const toolSet = {};
|
|
3796
|
-
for (const
|
|
3797
|
-
toolSet[
|
|
4020
|
+
for (const tool4 of spec.tools) {
|
|
4021
|
+
toolSet[tool4.name] = specToolToExternalTool(tool4);
|
|
3798
4022
|
}
|
|
3799
4023
|
if ((this.config.mcpServers?.length ?? 0) > 0) {
|
|
3800
4024
|
mcpToolset = await createMcpToolsets(this.config.mcpServers ?? [], {
|
|
@@ -4008,20 +4232,20 @@ ${params.systemOverride}` : context.spec.instructions;
|
|
|
4008
4232
|
}
|
|
4009
4233
|
return toolsForSdk;
|
|
4010
4234
|
}
|
|
4011
|
-
mcpToolToExternalTool(toolName,
|
|
4235
|
+
mcpToolToExternalTool(toolName, tool4) {
|
|
4012
4236
|
return {
|
|
4013
4237
|
name: toolName,
|
|
4014
|
-
description:
|
|
4238
|
+
description: tool4.description ?? createAgentI18n(this.config.locale).t("tool.fallbackDescription", {
|
|
4015
4239
|
name: toolName
|
|
4016
4240
|
}),
|
|
4017
|
-
inputSchema: this.normalizeExternalInputSchema(
|
|
4241
|
+
inputSchema: this.normalizeExternalInputSchema(tool4.inputSchema),
|
|
4018
4242
|
execute: async (input) => {
|
|
4019
|
-
if (!
|
|
4243
|
+
if (!tool4.execute) {
|
|
4020
4244
|
throw new Error(createAgentI18n(this.config.locale).t("error.toolNoExecuteHandler", {
|
|
4021
4245
|
name: toolName
|
|
4022
4246
|
}));
|
|
4023
4247
|
}
|
|
4024
|
-
return
|
|
4248
|
+
return tool4.execute(input, {
|
|
4025
4249
|
toolCallId: `mcp-${randomUUID2()}`,
|
|
4026
4250
|
messages: []
|
|
4027
4251
|
});
|
|
@@ -4061,8 +4285,8 @@ ${params.systemOverride}` : context.spec.instructions;
|
|
|
4061
4285
|
return typeof value === "object" && value !== null;
|
|
4062
4286
|
}
|
|
4063
4287
|
async executeTool(toolCall, context, _params) {
|
|
4064
|
-
const
|
|
4065
|
-
if (!
|
|
4288
|
+
const tool4 = context.tools[toolCall.toolName];
|
|
4289
|
+
if (!tool4?.execute) {
|
|
4066
4290
|
return {
|
|
4067
4291
|
toolCallId: toolCall.toolCallId,
|
|
4068
4292
|
toolName: toolCall.toolName,
|
|
@@ -4072,7 +4296,7 @@ ${params.systemOverride}` : context.spec.instructions;
|
|
|
4072
4296
|
};
|
|
4073
4297
|
}
|
|
4074
4298
|
try {
|
|
4075
|
-
const output = await
|
|
4299
|
+
const output = await tool4.execute(toolCall.args);
|
|
4076
4300
|
return {
|
|
4077
4301
|
toolCallId: toolCall.toolCallId,
|
|
4078
4302
|
toolName: toolCall.toolName,
|
|
@@ -4149,22 +4373,22 @@ var init_claude_agent_sdk = __esm(() => {
|
|
|
4149
4373
|
});
|
|
4150
4374
|
|
|
4151
4375
|
// src/providers/opencode-sdk/tool-bridge.ts
|
|
4152
|
-
function specToolToOpenCodeTool(
|
|
4376
|
+
function specToolToOpenCodeTool(tool4) {
|
|
4153
4377
|
return {
|
|
4154
|
-
name:
|
|
4155
|
-
description:
|
|
4156
|
-
parameters: normalizeToOpenCodeParameters(
|
|
4157
|
-
permission: getPermissionLevel(
|
|
4378
|
+
name: tool4.name,
|
|
4379
|
+
description: tool4.description ?? createAgentI18n().t("tool.fallbackDescription", { name: tool4.name }),
|
|
4380
|
+
parameters: normalizeToOpenCodeParameters(tool4.schema),
|
|
4381
|
+
permission: getPermissionLevel(tool4)
|
|
4158
4382
|
};
|
|
4159
4383
|
}
|
|
4160
4384
|
function specToolsToOpenCodeTools(tools) {
|
|
4161
4385
|
return tools.map(specToolToOpenCodeTool);
|
|
4162
4386
|
}
|
|
4163
|
-
function getPermissionLevel(
|
|
4164
|
-
if (
|
|
4387
|
+
function getPermissionLevel(tool4) {
|
|
4388
|
+
if (tool4.requiresApproval) {
|
|
4165
4389
|
return "ask";
|
|
4166
4390
|
}
|
|
4167
|
-
if (
|
|
4391
|
+
if (tool4.automationSafe === false) {
|
|
4168
4392
|
return "ask";
|
|
4169
4393
|
}
|
|
4170
4394
|
return "allow";
|
|
@@ -4181,12 +4405,12 @@ function openCodeToolToSpecTool(openCodeTool) {
|
|
|
4181
4405
|
function openCodeToolsToSpecTools(openCodeTools) {
|
|
4182
4406
|
return openCodeTools.map(openCodeToolToSpecTool);
|
|
4183
4407
|
}
|
|
4184
|
-
function specToolToExternalToolForOpenCode(
|
|
4408
|
+
function specToolToExternalToolForOpenCode(tool4, handler, context) {
|
|
4185
4409
|
return {
|
|
4186
|
-
name:
|
|
4187
|
-
description:
|
|
4188
|
-
inputSchema:
|
|
4189
|
-
requiresApproval:
|
|
4410
|
+
name: tool4.name,
|
|
4411
|
+
description: tool4.description ?? createAgentI18n().t("tool.fallbackDescription", { name: tool4.name }),
|
|
4412
|
+
inputSchema: tool4.schema ?? { type: "object" },
|
|
4413
|
+
requiresApproval: tool4.requiresApproval ?? !tool4.automationSafe,
|
|
4190
4414
|
execute: handler ? async (input) => {
|
|
4191
4415
|
const fullContext = {
|
|
4192
4416
|
agentId: context?.agentId ?? "unknown",
|
|
@@ -4236,9 +4460,9 @@ function convertToOpenCodeParameter(schema) {
|
|
|
4236
4460
|
}
|
|
4237
4461
|
function createToolHandlerMap(tools) {
|
|
4238
4462
|
const handlers = new Map;
|
|
4239
|
-
for (const [name,
|
|
4240
|
-
if (
|
|
4241
|
-
handlers.set(name,
|
|
4463
|
+
for (const [name, tool4] of Object.entries(tools)) {
|
|
4464
|
+
if (tool4.execute) {
|
|
4465
|
+
handlers.set(name, tool4.execute);
|
|
4242
4466
|
}
|
|
4243
4467
|
}
|
|
4244
4468
|
return handlers;
|
|
@@ -4274,7 +4498,7 @@ var init_tool_bridge2 = __esm(() => {
|
|
|
4274
4498
|
|
|
4275
4499
|
// src/providers/opencode-sdk/agent-bridge.ts
|
|
4276
4500
|
function inferAgentType(spec) {
|
|
4277
|
-
const hasCodeTools = spec.tools.some((
|
|
4501
|
+
const hasCodeTools = spec.tools.some((tool4) => [
|
|
4278
4502
|
"write_file",
|
|
4279
4503
|
"edit_file",
|
|
4280
4504
|
"create_file",
|
|
@@ -4283,7 +4507,7 @@ function inferAgentType(spec) {
|
|
|
4283
4507
|
"execute",
|
|
4284
4508
|
"run_command",
|
|
4285
4509
|
"terminal"
|
|
4286
|
-
].includes(
|
|
4510
|
+
].includes(tool4.name.toLowerCase()));
|
|
4287
4511
|
const instructionsLower = spec.instructions.toLowerCase();
|
|
4288
4512
|
const hasPlanningKeywords = /\b(plan|design|architect|strategy|analyze|review|assess|evaluate)\b/.test(instructionsLower);
|
|
4289
4513
|
const hasExplorationKeywords = /\b(search|find|explore|discover|locate|grep|pattern)\b/.test(instructionsLower);
|
|
@@ -4318,13 +4542,13 @@ function specToOpenCodeConfig(spec, options) {
|
|
|
4318
4542
|
}
|
|
4319
4543
|
function buildPermissions(spec) {
|
|
4320
4544
|
const permissions = {};
|
|
4321
|
-
for (const
|
|
4322
|
-
if (
|
|
4323
|
-
permissions[
|
|
4324
|
-
} else if (
|
|
4325
|
-
permissions[
|
|
4545
|
+
for (const tool4 of spec.tools) {
|
|
4546
|
+
if (tool4.requiresApproval) {
|
|
4547
|
+
permissions[tool4.name] = "ask";
|
|
4548
|
+
} else if (tool4.automationSafe === false) {
|
|
4549
|
+
permissions[tool4.name] = "ask";
|
|
4326
4550
|
} else {
|
|
4327
|
-
permissions[
|
|
4551
|
+
permissions[tool4.name] = "allow";
|
|
4328
4552
|
}
|
|
4329
4553
|
}
|
|
4330
4554
|
return permissions;
|
|
@@ -4360,9 +4584,9 @@ function buildMarkdownBody(spec) {
|
|
|
4360
4584
|
if (spec.tools.length > 0) {
|
|
4361
4585
|
lines.push(i18n.t("export.tools"));
|
|
4362
4586
|
lines.push("");
|
|
4363
|
-
for (const
|
|
4364
|
-
const permission =
|
|
4365
|
-
lines.push(`- **${
|
|
4587
|
+
for (const tool4 of spec.tools) {
|
|
4588
|
+
const permission = tool4.requiresApproval ? i18n.t("export.bridge.requiresApproval") : tool4.automationSafe === false ? i18n.t("export.bridge.askMode") : "";
|
|
4589
|
+
lines.push(`- **${tool4.name}**: ${tool4.description ?? i18n.t("export.noDescription")} ${permission}`.trim());
|
|
4366
4590
|
}
|
|
4367
4591
|
lines.push("");
|
|
4368
4592
|
}
|
|
@@ -4397,8 +4621,8 @@ function serializeOpenCodeMarkdown(markdown) {
|
|
|
4397
4621
|
}
|
|
4398
4622
|
if (markdown.frontmatter.tools && markdown.frontmatter.tools.length > 0) {
|
|
4399
4623
|
lines.push(`tools:`);
|
|
4400
|
-
for (const
|
|
4401
|
-
lines.push(` - ${
|
|
4624
|
+
for (const tool4 of markdown.frontmatter.tools) {
|
|
4625
|
+
lines.push(` - ${tool4}`);
|
|
4402
4626
|
}
|
|
4403
4627
|
}
|
|
4404
4628
|
lines.push("---");
|
|
@@ -4419,12 +4643,12 @@ function openCodeConfigToSpec(config) {
|
|
|
4419
4643
|
},
|
|
4420
4644
|
description: config.description,
|
|
4421
4645
|
instructions: config.instructions ?? "",
|
|
4422
|
-
tools: config.tools?.map((
|
|
4423
|
-
name:
|
|
4424
|
-
description:
|
|
4425
|
-
schema:
|
|
4426
|
-
requiresApproval:
|
|
4427
|
-
automationSafe:
|
|
4646
|
+
tools: config.tools?.map((tool4) => ({
|
|
4647
|
+
name: tool4.name,
|
|
4648
|
+
description: tool4.description,
|
|
4649
|
+
schema: tool4.parameters,
|
|
4650
|
+
requiresApproval: tool4.permission === "ask",
|
|
4651
|
+
automationSafe: tool4.permission === "allow"
|
|
4428
4652
|
})) ?? [],
|
|
4429
4653
|
maxSteps: config.config?.max_steps ?? 10
|
|
4430
4654
|
};
|
|
@@ -4481,8 +4705,8 @@ class OpenCodeSDKProvider {
|
|
|
4481
4705
|
model: this.config.model
|
|
4482
4706
|
});
|
|
4483
4707
|
const toolSet = {};
|
|
4484
|
-
for (const
|
|
4485
|
-
toolSet[
|
|
4708
|
+
for (const tool4 of spec.tools) {
|
|
4709
|
+
toolSet[tool4.name] = specToolToExternalToolForOpenCode(tool4);
|
|
4486
4710
|
}
|
|
4487
4711
|
const instructions = await injectStaticKnowledge(spec.instructions, spec.knowledge ?? [], undefined);
|
|
4488
4712
|
const contextId = `opencode-${agentKey(spec.meta)}-${Date.now()}`;
|
|
@@ -4788,10 +5012,10 @@ function buildInstructions(base, locale, system) {
|
|
|
4788
5012
|
`);
|
|
4789
5013
|
}
|
|
4790
5014
|
function ensureToolHandlers(spec, handlers, locale) {
|
|
4791
|
-
for (const
|
|
4792
|
-
if (!handlers.has(
|
|
5015
|
+
for (const tool4 of spec.tools) {
|
|
5016
|
+
if (!handlers.has(tool4.name)) {
|
|
4793
5017
|
throw new Error(createAgentI18n(locale).t("error.missingToolHandler", {
|
|
4794
|
-
name:
|
|
5018
|
+
name: tool4.name
|
|
4795
5019
|
}));
|
|
4796
5020
|
}
|
|
4797
5021
|
}
|
|
@@ -5008,8 +5232,8 @@ class UnifiedAgent {
|
|
|
5008
5232
|
const { createProvider: createProvider2 } = await import("@contractspec/lib.ai-providers/factory");
|
|
5009
5233
|
model = createProvider2(backendConfig.provider).getModel();
|
|
5010
5234
|
} else {
|
|
5011
|
-
const { anthropic } = await import("@ai-sdk/anthropic");
|
|
5012
|
-
model =
|
|
5235
|
+
const { anthropic: anthropic2 } = await import("@ai-sdk/anthropic");
|
|
5236
|
+
model = anthropic2(backendConfig?.model ?? "claude-3-5-sonnet-20240620");
|
|
5013
5237
|
}
|
|
5014
5238
|
return this.applyModelSettings(model, {
|
|
5015
5239
|
temperature: backendConfig?.temperature,
|