@faapi/agent 5.4.0 → 6.1.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/dist/index.d.ts +74 -36
- package/dist/index.js +132 -91
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -30,10 +30,12 @@ function createOpenAIProvider(config) {
|
|
|
30
30
|
const modelConfig = modelName ? config.models[modelName] : void 0;
|
|
31
31
|
const body = {
|
|
32
32
|
model: modelName,
|
|
33
|
-
messages
|
|
33
|
+
// 规范形即 OpenAI 形状:messages 恒等透传(剥离框架扩展字段 reasoning_content,
|
|
34
|
+
// 推理内容是解析产物不回传——DeepSeek 多轮回传直接 400,OpenAI 等拒绝未知字段)
|
|
35
|
+
messages: stripReasoningFromMessages(request.messages)
|
|
34
36
|
};
|
|
35
37
|
if (request.tools && request.tools.length > 0) {
|
|
36
|
-
body.tools = request.tools
|
|
38
|
+
body.tools = request.tools;
|
|
37
39
|
}
|
|
38
40
|
const mergedConfig = {};
|
|
39
41
|
for (const key of Object.keys(config)) {
|
|
@@ -182,13 +184,13 @@ function createOpenAIProvider(config) {
|
|
|
182
184
|
});
|
|
183
185
|
}
|
|
184
186
|
const content = msg.content ?? "";
|
|
185
|
-
const toolCalls =
|
|
187
|
+
const toolCalls = normalizeToolCalls(msg.tool_calls, bodyText, response.status);
|
|
188
|
+
const message = { role: "assistant", content };
|
|
189
|
+
if (toolCalls) message.tool_calls = toolCalls;
|
|
190
|
+
const reasoning = extractReasoning(msg);
|
|
191
|
+
if (reasoning) message.reasoning_content = reasoning;
|
|
186
192
|
return {
|
|
187
|
-
message
|
|
188
|
-
role: "assistant",
|
|
189
|
-
content,
|
|
190
|
-
toolCalls
|
|
191
|
-
},
|
|
193
|
+
message,
|
|
192
194
|
stopReason: mapStopReason(choice.finish_reason ?? void 0),
|
|
193
195
|
usage: mapUsage(json.usage)
|
|
194
196
|
};
|
|
@@ -243,6 +245,10 @@ function createOpenAIProvider(config) {
|
|
|
243
245
|
}
|
|
244
246
|
const delta = chunk.choices?.[0]?.delta;
|
|
245
247
|
if (delta) {
|
|
248
|
+
const reasoning = extractReasoning(delta);
|
|
249
|
+
if (reasoning) {
|
|
250
|
+
yield { deltaReasoning: reasoning };
|
|
251
|
+
}
|
|
246
252
|
if (typeof delta.content === "string" && delta.content.length > 0) {
|
|
247
253
|
yield { deltaContent: delta.content };
|
|
248
254
|
}
|
|
@@ -271,40 +277,33 @@ function createOpenAIProvider(config) {
|
|
|
271
277
|
}
|
|
272
278
|
return { complete, stream };
|
|
273
279
|
}
|
|
274
|
-
function
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
content: msg.content
|
|
278
|
-
};
|
|
279
|
-
if (msg.toolCallId !== void 0) out.tool_call_id = msg.toolCallId;
|
|
280
|
-
if (msg.toolCalls !== void 0 && msg.toolCalls.length > 0) {
|
|
281
|
-
out.tool_calls = msg.toolCalls.map((tc) => ({
|
|
282
|
-
id: tc.id,
|
|
283
|
-
type: "function",
|
|
284
|
-
function: { name: tc.name, arguments: JSON.stringify(tc.arguments) }
|
|
285
|
-
}));
|
|
280
|
+
function extractReasoning(source) {
|
|
281
|
+
if (typeof source.reasoning_content === "string" && source.reasoning_content.length > 0) {
|
|
282
|
+
return source.reasoning_content;
|
|
286
283
|
}
|
|
287
|
-
|
|
284
|
+
if (typeof source.reasoning === "string" && source.reasoning.length > 0) {
|
|
285
|
+
return source.reasoning;
|
|
286
|
+
}
|
|
287
|
+
return void 0;
|
|
288
288
|
}
|
|
289
|
-
function
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
};
|
|
289
|
+
function stripReasoningFromMessages(messages) {
|
|
290
|
+
if (!messages.some((m) => m.reasoning_content !== void 0)) {
|
|
291
|
+
return messages;
|
|
292
|
+
}
|
|
293
|
+
return messages.map((m) => {
|
|
294
|
+
if (m.reasoning_content === void 0) return m;
|
|
295
|
+
const { reasoning_content: _stripped, ...rest } = m;
|
|
296
|
+
return rest;
|
|
297
|
+
});
|
|
298
298
|
}
|
|
299
|
-
function
|
|
299
|
+
function normalizeToolCalls(toolCalls, bodyText, status) {
|
|
300
300
|
if (!toolCalls || toolCalls.length === 0) return void 0;
|
|
301
301
|
const result = [];
|
|
302
302
|
for (let i = 0; i < toolCalls.length; i++) {
|
|
303
303
|
const tc = toolCalls[i];
|
|
304
304
|
const argsStr = tc?.function?.arguments ?? "{}";
|
|
305
|
-
let args;
|
|
306
305
|
try {
|
|
307
|
-
|
|
306
|
+
JSON.parse(argsStr);
|
|
308
307
|
} catch {
|
|
309
308
|
const excerpt = argsStr.slice(0, 500);
|
|
310
309
|
throw new LLMProviderError(`Invalid tool arguments JSON: ${excerpt}`, {
|
|
@@ -314,8 +313,8 @@ function parseToolCalls(toolCalls, bodyText, status) {
|
|
|
314
313
|
}
|
|
315
314
|
result.push({
|
|
316
315
|
id: tc?.id ?? `call_${i}`,
|
|
317
|
-
|
|
318
|
-
arguments:
|
|
316
|
+
type: "function",
|
|
317
|
+
function: { name: tc?.function?.name ?? "", arguments: argsStr }
|
|
319
318
|
});
|
|
320
319
|
}
|
|
321
320
|
return result;
|
|
@@ -337,9 +336,9 @@ function mapStopReason(fr) {
|
|
|
337
336
|
function mapUsage(u) {
|
|
338
337
|
if (!u) return void 0;
|
|
339
338
|
return {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
339
|
+
prompt_tokens: u.prompt_tokens ?? 0,
|
|
340
|
+
completion_tokens: u.completion_tokens ?? 0,
|
|
341
|
+
total_tokens: u.total_tokens ?? 0
|
|
343
342
|
};
|
|
344
343
|
}
|
|
345
344
|
function extractSSEData(event) {
|
|
@@ -394,19 +393,19 @@ function finalizeStreamChunk(accumulators, finishReason, usage) {
|
|
|
394
393
|
for (const idx of indices) {
|
|
395
394
|
const acc = accumulators.get(idx);
|
|
396
395
|
if (!acc.id || !acc.name) continue;
|
|
397
|
-
|
|
396
|
+
const argsStr = acc.argsString || "{}";
|
|
398
397
|
try {
|
|
399
|
-
|
|
398
|
+
JSON.parse(argsStr);
|
|
400
399
|
} catch {
|
|
401
|
-
const excerpt =
|
|
400
|
+
const excerpt = argsStr.slice(0, 500);
|
|
402
401
|
throw new LLMProviderError(`Invalid tool arguments JSON: ${excerpt}`, {
|
|
403
402
|
body: excerpt
|
|
404
403
|
});
|
|
405
404
|
}
|
|
406
405
|
toolCalls.push({
|
|
407
406
|
id: acc.id,
|
|
408
|
-
|
|
409
|
-
arguments:
|
|
407
|
+
type: "function",
|
|
408
|
+
function: { name: acc.name, arguments: argsStr }
|
|
410
409
|
});
|
|
411
410
|
}
|
|
412
411
|
}
|
|
@@ -464,12 +463,17 @@ function stringifyError(err) {
|
|
|
464
463
|
if (err instanceof Error) return err.message;
|
|
465
464
|
return String(err);
|
|
466
465
|
}
|
|
466
|
+
function stripReasoning(message) {
|
|
467
|
+
if (message.reasoning_content === void 0) return message;
|
|
468
|
+
const { reasoning_content: _stripped, ...rest } = message;
|
|
469
|
+
return rest;
|
|
470
|
+
}
|
|
467
471
|
function accumulateUsage(a, b) {
|
|
468
472
|
if (!a) return { ...b };
|
|
469
473
|
return {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
474
|
+
prompt_tokens: a.prompt_tokens + b.prompt_tokens,
|
|
475
|
+
completion_tokens: a.completion_tokens + b.completion_tokens,
|
|
476
|
+
total_tokens: a.total_tokens + b.total_tokens
|
|
473
477
|
};
|
|
474
478
|
}
|
|
475
479
|
function buildInitialMessages(input, systemPrompt) {
|
|
@@ -480,9 +484,14 @@ function buildInitialMessages(input, systemPrompt) {
|
|
|
480
484
|
messages.push({ role: "user", content: input });
|
|
481
485
|
return messages;
|
|
482
486
|
}
|
|
487
|
+
function parseToolCallArguments(toolCall) {
|
|
488
|
+
const raw = toolCall.function.arguments;
|
|
489
|
+
if (!raw) return {};
|
|
490
|
+
return JSON.parse(raw);
|
|
491
|
+
}
|
|
483
492
|
function initLoopMessages(input, config) {
|
|
484
493
|
if (config.messages?.length) {
|
|
485
|
-
const messages =
|
|
494
|
+
const messages = config.messages.map(stripReasoning);
|
|
486
495
|
if (config.systemPrompt && !messages.some((m) => m.role === "system")) {
|
|
487
496
|
messages.unshift({ role: "system", content: config.systemPrompt });
|
|
488
497
|
}
|
|
@@ -498,11 +507,11 @@ function estimateTokens(chars) {
|
|
|
498
507
|
}
|
|
499
508
|
function estimateMessageTokens(message) {
|
|
500
509
|
let chars = message.content.length;
|
|
501
|
-
if (message.
|
|
502
|
-
chars += JSON.stringify(message.
|
|
510
|
+
if (message.tool_calls) {
|
|
511
|
+
chars += JSON.stringify(message.tool_calls).length;
|
|
503
512
|
}
|
|
504
|
-
if (message.
|
|
505
|
-
chars += message.
|
|
513
|
+
if (message.tool_call_id) {
|
|
514
|
+
chars += message.tool_call_id.length;
|
|
506
515
|
}
|
|
507
516
|
return estimateTokens(chars);
|
|
508
517
|
}
|
|
@@ -555,6 +564,7 @@ async function reactLoop(input, config) {
|
|
|
555
564
|
const maxTurns = config.maxTurns ?? DEFAULT_MAX_TURNS;
|
|
556
565
|
const extras = buildRequestExtras(config);
|
|
557
566
|
let totalUsage;
|
|
567
|
+
let finalReasoning;
|
|
558
568
|
let turns = 0;
|
|
559
569
|
const traceStartedAt = enableTracing ? nowMs() : 0;
|
|
560
570
|
const traceEvents = enableTracing ? [] : void 0;
|
|
@@ -591,15 +601,18 @@ async function reactLoop(input, config) {
|
|
|
591
601
|
durationMs: llmEndedAt - llmStartedAt,
|
|
592
602
|
model: config.model ?? "",
|
|
593
603
|
inputMessages: inputSnapshot,
|
|
604
|
+
// 原始 assistant 消息(含 reasoning_content)——trace 保留完整 LLM 返回,
|
|
605
|
+
// 与历史剥离策略互补(见 trace.md「llm_call.response 与 thinking」)
|
|
594
606
|
response: response.message,
|
|
595
607
|
stopReason: response.stopReason,
|
|
596
608
|
usage: response.usage
|
|
597
609
|
});
|
|
598
610
|
}
|
|
599
|
-
|
|
600
|
-
|
|
611
|
+
finalReasoning = response.message.reasoning_content;
|
|
612
|
+
messages.push(stripReasoning(response.message));
|
|
613
|
+
if (response.stopReason !== "tool_calls" || !response.message.tool_calls) {
|
|
601
614
|
const traceEndedAt = enableTracing ? nowMs() : 0;
|
|
602
|
-
|
|
615
|
+
const result = {
|
|
603
616
|
content: response.message.content,
|
|
604
617
|
messages,
|
|
605
618
|
turns,
|
|
@@ -616,16 +629,23 @@ async function reactLoop(input, config) {
|
|
|
616
629
|
events: traceEvents
|
|
617
630
|
} : void 0
|
|
618
631
|
};
|
|
632
|
+
if (finalReasoning !== void 0) {
|
|
633
|
+
result.reasoning = finalReasoning;
|
|
634
|
+
}
|
|
635
|
+
return result;
|
|
619
636
|
}
|
|
620
637
|
const settled = await Promise.all(
|
|
621
|
-
response.message.
|
|
638
|
+
response.message.tool_calls.map(async (toolCall) => {
|
|
622
639
|
const toolStartedAt = enableTracing ? nowMs() : 0;
|
|
640
|
+
const toolName = toolCall.function.name;
|
|
641
|
+
let args = {};
|
|
623
642
|
let resultStr;
|
|
624
643
|
let rawResult;
|
|
625
644
|
let toolErr;
|
|
626
645
|
let hasError = false;
|
|
627
646
|
try {
|
|
628
|
-
|
|
647
|
+
args = parseToolCallArguments(toolCall);
|
|
648
|
+
rawResult = await config.executeTool(toolName, args);
|
|
629
649
|
if (isTracingToolResult(rawResult)) {
|
|
630
650
|
resultStr = stringifyResult(rawResult.result);
|
|
631
651
|
} else {
|
|
@@ -640,6 +660,8 @@ async function reactLoop(input, config) {
|
|
|
640
660
|
const toolEndedAt = enableTracing ? nowMs() : 0;
|
|
641
661
|
return {
|
|
642
662
|
toolCall,
|
|
663
|
+
toolName,
|
|
664
|
+
args,
|
|
643
665
|
toolStartedAt,
|
|
644
666
|
toolEndedAt,
|
|
645
667
|
resultStr,
|
|
@@ -651,6 +673,8 @@ async function reactLoop(input, config) {
|
|
|
651
673
|
);
|
|
652
674
|
for (const {
|
|
653
675
|
toolCall,
|
|
676
|
+
toolName,
|
|
677
|
+
args,
|
|
654
678
|
toolStartedAt,
|
|
655
679
|
toolEndedAt,
|
|
656
680
|
resultStr,
|
|
@@ -666,8 +690,8 @@ async function reactLoop(input, config) {
|
|
|
666
690
|
startedAt: toolStartedAt,
|
|
667
691
|
durationMs: toolEndedAt - toolStartedAt,
|
|
668
692
|
toolCallId: toolCall.id,
|
|
669
|
-
agentName: extractSubAgentName(
|
|
670
|
-
input: JSON.stringify(
|
|
693
|
+
agentName: extractSubAgentName(toolName),
|
|
694
|
+
input: JSON.stringify(args),
|
|
671
695
|
trace: rawResult.trace,
|
|
672
696
|
result: resultStr
|
|
673
697
|
});
|
|
@@ -678,8 +702,8 @@ async function reactLoop(input, config) {
|
|
|
678
702
|
startedAt: toolStartedAt,
|
|
679
703
|
durationMs: toolEndedAt - toolStartedAt,
|
|
680
704
|
toolCallId: toolCall.id,
|
|
681
|
-
name:
|
|
682
|
-
arguments:
|
|
705
|
+
name: toolName,
|
|
706
|
+
arguments: args,
|
|
683
707
|
result: resultStr,
|
|
684
708
|
error: hasError ? stringifyError(toolErr) : void 0
|
|
685
709
|
});
|
|
@@ -688,7 +712,7 @@ async function reactLoop(input, config) {
|
|
|
688
712
|
messages.push({
|
|
689
713
|
role: "tool",
|
|
690
714
|
content: resultStr,
|
|
691
|
-
|
|
715
|
+
tool_call_id: toolCall.id
|
|
692
716
|
});
|
|
693
717
|
}
|
|
694
718
|
}
|
|
@@ -714,6 +738,7 @@ async function* reactLoopStream(input, config) {
|
|
|
714
738
|
const outgoing = config.maxHistoryTokens ? trimHistory(messages, config.maxHistoryTokens) : messages;
|
|
715
739
|
const inputSnapshot = enableTracing ? [...outgoing] : void 0;
|
|
716
740
|
let turnContent = "";
|
|
741
|
+
let turnReasoning = "";
|
|
717
742
|
let toolCalls;
|
|
718
743
|
let finishReason;
|
|
719
744
|
let turnUsage;
|
|
@@ -723,6 +748,10 @@ async function* reactLoopStream(input, config) {
|
|
|
723
748
|
...extras,
|
|
724
749
|
signal: config.signal
|
|
725
750
|
})) {
|
|
751
|
+
if (typeof chunk.deltaReasoning === "string" && chunk.deltaReasoning.length > 0) {
|
|
752
|
+
turnReasoning += chunk.deltaReasoning;
|
|
753
|
+
yield { deltaReasoning: chunk.deltaReasoning };
|
|
754
|
+
}
|
|
726
755
|
if (typeof chunk.deltaContent === "string" && chunk.deltaContent.length > 0) {
|
|
727
756
|
turnContent += chunk.deltaContent;
|
|
728
757
|
yield { deltaContent: chunk.deltaContent };
|
|
@@ -749,11 +778,12 @@ async function* reactLoopStream(input, config) {
|
|
|
749
778
|
content: turnContent
|
|
750
779
|
};
|
|
751
780
|
if (toolCalls) {
|
|
752
|
-
assistantMessage.
|
|
781
|
+
assistantMessage.tool_calls = toolCalls;
|
|
753
782
|
}
|
|
754
783
|
messages.push(assistantMessage);
|
|
755
784
|
if (enableTracing) {
|
|
756
785
|
const llmEndedAt = nowMs();
|
|
786
|
+
const tracedResponse = turnReasoning ? { ...assistantMessage, reasoning_content: turnReasoning } : assistantMessage;
|
|
757
787
|
yield {
|
|
758
788
|
traceEvent: {
|
|
759
789
|
type: "llm_call",
|
|
@@ -762,32 +792,37 @@ async function* reactLoopStream(input, config) {
|
|
|
762
792
|
durationMs: llmEndedAt - llmStartedAt,
|
|
763
793
|
model: config.model ?? "",
|
|
764
794
|
inputMessages: inputSnapshot,
|
|
765
|
-
response:
|
|
795
|
+
response: tracedResponse,
|
|
766
796
|
stopReason: finishReason ?? "other",
|
|
767
797
|
usage: turnUsage
|
|
768
798
|
}
|
|
769
799
|
};
|
|
770
800
|
}
|
|
771
801
|
if (finishReason !== "tool_calls" || !toolCalls) {
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
usage: totalUsage
|
|
778
|
-
}
|
|
802
|
+
const donePayload = {
|
|
803
|
+
content: turnContent,
|
|
804
|
+
turns,
|
|
805
|
+
stopReason: finishReason ?? "other",
|
|
806
|
+
usage: totalUsage
|
|
779
807
|
};
|
|
808
|
+
if (turnReasoning) {
|
|
809
|
+
donePayload.reasoning = turnReasoning;
|
|
810
|
+
}
|
|
811
|
+
yield { done: donePayload };
|
|
780
812
|
return;
|
|
781
813
|
}
|
|
782
814
|
for (const toolCall of toolCalls) {
|
|
783
|
-
|
|
815
|
+
const toolName = toolCall.function.name;
|
|
784
816
|
const toolStartedAt = enableTracing ? nowMs() : 0;
|
|
817
|
+
let args = {};
|
|
785
818
|
let resultStr;
|
|
786
819
|
let rawResult;
|
|
787
820
|
let toolErr;
|
|
788
821
|
let hasError = false;
|
|
789
822
|
try {
|
|
790
|
-
|
|
823
|
+
args = parseToolCallArguments(toolCall);
|
|
824
|
+
yield { toolCall: { name: toolName, arguments: args } };
|
|
825
|
+
rawResult = await config.executeTool(toolName, args);
|
|
791
826
|
if (isTracingToolResult(rawResult)) {
|
|
792
827
|
resultStr = stringifyResult(rawResult.result);
|
|
793
828
|
} else {
|
|
@@ -799,7 +834,7 @@ async function* reactLoopStream(input, config) {
|
|
|
799
834
|
resultStr = stringifyError(err);
|
|
800
835
|
rawResult = void 0;
|
|
801
836
|
}
|
|
802
|
-
yield { toolResult: { name:
|
|
837
|
+
yield { toolResult: { name: toolName, result: resultStr } };
|
|
803
838
|
if (enableTracing) {
|
|
804
839
|
const toolEndedAt = nowMs();
|
|
805
840
|
if (isTracingToolResult(rawResult)) {
|
|
@@ -810,8 +845,8 @@ async function* reactLoopStream(input, config) {
|
|
|
810
845
|
startedAt: toolStartedAt,
|
|
811
846
|
durationMs: toolEndedAt - toolStartedAt,
|
|
812
847
|
toolCallId: toolCall.id,
|
|
813
|
-
agentName: extractSubAgentName(
|
|
814
|
-
input: JSON.stringify(
|
|
848
|
+
agentName: extractSubAgentName(toolName),
|
|
849
|
+
input: JSON.stringify(args),
|
|
815
850
|
trace: rawResult.trace,
|
|
816
851
|
result: resultStr
|
|
817
852
|
}
|
|
@@ -824,8 +859,8 @@ async function* reactLoopStream(input, config) {
|
|
|
824
859
|
startedAt: toolStartedAt,
|
|
825
860
|
durationMs: toolEndedAt - toolStartedAt,
|
|
826
861
|
toolCallId: toolCall.id,
|
|
827
|
-
name:
|
|
828
|
-
arguments:
|
|
862
|
+
name: toolName,
|
|
863
|
+
arguments: args,
|
|
829
864
|
result: resultStr,
|
|
830
865
|
error: hasError ? stringifyError(toolErr) : void 0
|
|
831
866
|
}
|
|
@@ -835,7 +870,7 @@ async function* reactLoopStream(input, config) {
|
|
|
835
870
|
messages.push({
|
|
836
871
|
role: "tool",
|
|
837
872
|
content: resultStr,
|
|
838
|
-
|
|
873
|
+
tool_call_id: toolCall.id
|
|
839
874
|
});
|
|
840
875
|
}
|
|
841
876
|
}
|
|
@@ -871,10 +906,10 @@ function validateResumeHistory(messages) {
|
|
|
871
906
|
`Invalid resume history at messages[${index}]: unknown role "${String(message.role)}"`
|
|
872
907
|
);
|
|
873
908
|
}
|
|
874
|
-
if (message.role === "assistant" && message.
|
|
875
|
-
const missing = new Set(message.
|
|
909
|
+
if (message.role === "assistant" && message.tool_calls?.length) {
|
|
910
|
+
const missing = new Set(message.tool_calls.map((call) => call.id));
|
|
876
911
|
for (let j = index + 1; j < messages.length && messages[j].role === "tool"; j++) {
|
|
877
|
-
missing.delete(messages[j].
|
|
912
|
+
missing.delete(messages[j].tool_call_id ?? "");
|
|
878
913
|
}
|
|
879
914
|
if (missing.size > 0) {
|
|
880
915
|
throw new AgentError(
|
|
@@ -1166,17 +1201,17 @@ var Agent = class _Agent {
|
|
|
1166
1201
|
);
|
|
1167
1202
|
}
|
|
1168
1203
|
/**
|
|
1169
|
-
* 组装 LLM 可见 tool
|
|
1204
|
+
* 组装 LLM 可见 tool 列表(OpenAI chat completions 规范形)
|
|
1170
1205
|
*
|
|
1171
|
-
* 合并两个来源(按 `name` 去重,先入者保留):
|
|
1206
|
+
* 合并两个来源(按 `function.name` 去重,先入者保留):
|
|
1172
1207
|
* 1. **resolveAgentTools** —— agent 显式声明的 `tools` 引用
|
|
1173
1208
|
* 2. **sub-agent** —— `resolveSubAgents` 每个包装为 `agent.<name>`
|
|
1174
1209
|
*
|
|
1175
|
-
* 每个常规 tool 的 `
|
|
1210
|
+
* 每个常规 tool 的 `function.parameters`:
|
|
1176
1211
|
* - `resolveToolSchema` 提供 → 用其 `jsonSchema`
|
|
1177
1212
|
* - 未提供 / tool 无 `inputTypeName` → 自由 schema `{ type: 'object' }`
|
|
1178
1213
|
*
|
|
1179
|
-
* sub-agent 的 `
|
|
1214
|
+
* sub-agent 的 `function.parameters` 始终为 `{ type: 'object' }`(agent 参数开放)。
|
|
1180
1215
|
*/
|
|
1181
1216
|
async buildToolDefinitions(agentName) {
|
|
1182
1217
|
const definitions = /* @__PURE__ */ new Map();
|
|
@@ -1184,18 +1219,24 @@ var Agent = class _Agent {
|
|
|
1184
1219
|
if (definitions.has(tool.name)) continue;
|
|
1185
1220
|
const schemaRes = await this.getToolSchema(tool);
|
|
1186
1221
|
definitions.set(tool.name, {
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1222
|
+
type: "function",
|
|
1223
|
+
function: {
|
|
1224
|
+
name: tool.name,
|
|
1225
|
+
description: tool.description,
|
|
1226
|
+
parameters: schemaRes?.jsonSchema ?? { type: "object" }
|
|
1227
|
+
}
|
|
1190
1228
|
});
|
|
1191
1229
|
}
|
|
1192
1230
|
for (const subAgent of this.deps.resolveSubAgents(agentName)) {
|
|
1193
1231
|
const name = `agent.${subAgent.name}`;
|
|
1194
1232
|
if (definitions.has(name)) continue;
|
|
1195
1233
|
definitions.set(name, {
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1234
|
+
type: "function",
|
|
1235
|
+
function: {
|
|
1236
|
+
name,
|
|
1237
|
+
description: subAgent.description,
|
|
1238
|
+
parameters: { type: "object" }
|
|
1239
|
+
}
|
|
1199
1240
|
});
|
|
1200
1241
|
}
|
|
1201
1242
|
const defs = Array.from(definitions.values());
|