utilitas 1998.2.34 → 1998.2.36
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 +1 -2
- package/dist/utilitas.lite.mjs +1 -1
- package/dist/utilitas.lite.mjs.map +1 -1
- package/lib/alan.mjs +136 -162
- package/lib/manifest.mjs +1 -1
- package/package.json +1 -1
package/lib/alan.mjs
CHANGED
|
@@ -38,8 +38,7 @@ You may be provided with some tools(functions) to help you gather information an
|
|
|
38
38
|
- Use tools when appropriate to enhance efficiency and accuracy, and to gain the contextual knowledge needed to solve problems.
|
|
39
39
|
- Be sure to use tools only when necessary and avoid overuse, you can answer questions based on your own understanding.
|
|
40
40
|
- When the tools are not suitable and you have to answer questions based on your understanding, please do not mention any tool-related information in your response.
|
|
41
|
-
- Unless otherwise specified to require the original result, in most cases, you may reorganize the information obtained after using the tool to solve the problem as needed
|
|
42
|
-
- If the tool fails, do not retry unless requested by the user.`;
|
|
41
|
+
- Unless otherwise specified to require the original result, in most cases, you may reorganize the information obtained after using the tool to solve the problem as needed.`;
|
|
43
42
|
|
|
44
43
|
const _NEED = [
|
|
45
44
|
'@anthropic-ai/sdk', '@anthropic-ai/vertex-sdk', '@google/generative-ai',
|
|
@@ -55,6 +54,7 @@ const [
|
|
|
55
54
|
CLAUDE_35_HAIKU, CLOUD_37_SONNET, AUDIO, WAV, CHATGPT_MINI, ATTACHMENTS,
|
|
56
55
|
CHAT, OPENAI_VOICE, MEDIUM, LOW, HIGH, GPT_REASONING_EFFORT, THINK,
|
|
57
56
|
THINK_STR, THINK_END, AZURE, TOOLS_STR, TOOLS_END, TOOLS, TEXT, THINKING,
|
|
57
|
+
OK,
|
|
58
58
|
] = [
|
|
59
59
|
'OPENAI', 'GEMINI', 'CHATGPT', 'OPENAI_EMBEDDING', 'GEMINI_EMEDDING',
|
|
60
60
|
'OPENAI_TRAINING', 'OLLAMA', 'CLAUDE', 'gpt-4o-mini', 'gpt-4o', 'o1',
|
|
@@ -66,7 +66,7 @@ const [
|
|
|
66
66
|
'claude-3-7-sonnet@20250219', 'audio', 'wav', 'CHATGPT_MINI',
|
|
67
67
|
'[ATTACHMENTS]', 'CHAT', 'OPENAI_VOICE', 'medium', 'low', 'high',
|
|
68
68
|
'medium', 'think', '<think>', '</think>', 'AZURE', '<tools>',
|
|
69
|
-
'</tools>', 'tools', 'text', 'thinking',
|
|
69
|
+
'</tools>', 'tools', 'text', 'thinking', 'OK',
|
|
70
70
|
];
|
|
71
71
|
|
|
72
72
|
const [
|
|
@@ -99,6 +99,7 @@ const [tokenSafeRatio, GPT_QUERY_LIMIT, minsOfDay] = [1.1, 100, 60 * 24];
|
|
|
99
99
|
const tokenSafe = count => Math.ceil(count * tokenSafeRatio);
|
|
100
100
|
const clients = {};
|
|
101
101
|
const size8k = 7680 * 4320;
|
|
102
|
+
const MAX_TOOL_RECURSION = 10;
|
|
102
103
|
const LOG = { log: true };
|
|
103
104
|
const OPENAI_BASE_URL = 'https://api.openai.com/v1';
|
|
104
105
|
const sessionType = `${name.toUpperCase()}-SESSION`;
|
|
@@ -111,6 +112,7 @@ const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
|
|
|
111
112
|
const CONTENT_IS_REQUIRED = 'Content is required.';
|
|
112
113
|
const assertContent = content => assert(content.length, CONTENT_IS_REQUIRED);
|
|
113
114
|
const packThink = thk => thk ? [`${THINK_STR}\n${thk}\n${THINK_END}`] : [];
|
|
115
|
+
const countToolCalls = r => r?.split('\n').filter(x => x === TOOLS_STR).length;
|
|
114
116
|
|
|
115
117
|
const DEFAULT_MODELS = {
|
|
116
118
|
[CHATGPT_MINI]: GPT_4O_MINI,
|
|
@@ -412,6 +414,7 @@ const tools = [
|
|
|
412
414
|
}
|
|
413
415
|
},
|
|
414
416
|
func: async () => new Date().toLocaleString(),
|
|
417
|
+
showRes: true,
|
|
415
418
|
},
|
|
416
419
|
{
|
|
417
420
|
def: {
|
|
@@ -429,6 +432,7 @@ const tools = [
|
|
|
429
432
|
}
|
|
430
433
|
},
|
|
431
434
|
func: async args => (await distill(args?.url))?.summary,
|
|
435
|
+
showReq: true,
|
|
432
436
|
},
|
|
433
437
|
{
|
|
434
438
|
def: {
|
|
@@ -446,6 +450,7 @@ const tools = [
|
|
|
446
450
|
}
|
|
447
451
|
},
|
|
448
452
|
func: async args => await search(args?.keyword),
|
|
453
|
+
showReq: true,
|
|
449
454
|
},
|
|
450
455
|
];
|
|
451
456
|
|
|
@@ -738,14 +743,18 @@ const packResp = async (resp, options) => {
|
|
|
738
743
|
};
|
|
739
744
|
};
|
|
740
745
|
|
|
746
|
+
const streamResp = async (resp, options) => {
|
|
747
|
+
const msg = await packGptResp(resp, { ...options, processing: true });
|
|
748
|
+
return options?.stream && (msg?.text || msg?.audio?.length)
|
|
749
|
+
&& await ignoreErrFunc(async () => await options.stream(msg), LOG);
|
|
750
|
+
};
|
|
751
|
+
|
|
741
752
|
const packGptResp = async (resp, options) => {
|
|
742
753
|
// simple mode is not recommended for streaming responses
|
|
743
|
-
let text = resp
|
|
744
|
-
|| resp?.choices?.[0]?.message?.audio?.transcript // ChatGPT audio mode
|
|
754
|
+
let text = resp.text // ChatGPT / Claude
|
|
745
755
|
|| (Function.isFunction(resp?.text) ? resp.text() : resp?.text) // Gemini
|
|
746
|
-
|| resp?.content?.find(x => x.type === TEXT)?.text // Claude
|
|
747
756
|
|| resp?.message?.content || ''; // Ollama
|
|
748
|
-
const audio = resp?.
|
|
757
|
+
const audio = resp?.message?.audio?.data; // ChatGPT audio mode
|
|
749
758
|
if (options?.raw) { return resp; }
|
|
750
759
|
else if (options?.simple && options?.jsonMode) { return parseJson(text); }
|
|
751
760
|
else if (options?.simple && options?.audioMode) { return audio; }
|
|
@@ -764,30 +773,29 @@ const packGptResp = async (resp, options) => {
|
|
|
764
773
|
};
|
|
765
774
|
|
|
766
775
|
const handleToolsCall = async (msg, options) => {
|
|
767
|
-
let [content, preRes, input, packMsg, toolsResponse] = [
|
|
768
|
-
[], [], [], null,
|
|
769
|
-
options?.currentResponse ? `${options?.currentResponse}\n` : '',
|
|
776
|
+
let [content, preRes, input, packMsg, toolsResponse, responded] = [
|
|
777
|
+
[], [], [], null, options?.result ? options?.result.trim() : '', false
|
|
770
778
|
];
|
|
771
|
-
const resp = async
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
779
|
+
const resp = async m => {
|
|
780
|
+
m = `\n${m}`;
|
|
781
|
+
responded || (m = `\n\n${TOOLS_STR}${m}`);
|
|
782
|
+
responded = true;
|
|
783
|
+
toolsResponse = (toolsResponse + m).trim();
|
|
784
|
+
await streamResp({ text: options?.delta ? m : toolsResponse }, options);
|
|
776
785
|
};
|
|
777
|
-
|
|
778
|
-
|
|
786
|
+
const calls = msg.tool_calls || msg.content || [];
|
|
787
|
+
if (calls.length) {
|
|
779
788
|
switch (options?.flavor) {
|
|
780
|
-
case CLAUDE: preRes.push(
|
|
789
|
+
case CLAUDE: preRes.push(msg); break;
|
|
781
790
|
case GEMINI: preRes.push({ role: MODEL, parts: msg?.tool_calls.map(x => ({ functionCall: x })) }); break;
|
|
782
|
-
case CHATGPT: default: preRes.push(
|
|
791
|
+
case CHATGPT: default: preRes.push(msg); break;
|
|
783
792
|
}
|
|
784
|
-
for (const fn of
|
|
793
|
+
for (const fn of calls) {
|
|
785
794
|
switch (options?.flavor) {
|
|
786
795
|
case CLAUDE:
|
|
787
796
|
input = fn.input = String.isString(fn?.input) ? parseJson(fn.input) : fn?.input;
|
|
788
|
-
packMsg = (
|
|
789
|
-
type: 'tool_result', tool_use_id: fn.id,
|
|
790
|
-
content: JSON.stringify(c), is_error,
|
|
797
|
+
packMsg = (content, is_error) => ({
|
|
798
|
+
type: 'tool_result', tool_use_id: fn.id, content, is_error,
|
|
791
799
|
});
|
|
792
800
|
break;
|
|
793
801
|
case GEMINI:
|
|
@@ -795,8 +803,7 @@ const handleToolsCall = async (msg, options) => {
|
|
|
795
803
|
packMsg = (t, e) => ({
|
|
796
804
|
functionResponse: {
|
|
797
805
|
name: fn.name, response: {
|
|
798
|
-
name: fn.name,
|
|
799
|
-
content: e ? `[Error] ${t}` : JSON.stringify(t),
|
|
806
|
+
name: fn.name, content: e ? `[Error] ${t}` : t,
|
|
800
807
|
}
|
|
801
808
|
}
|
|
802
809
|
});
|
|
@@ -810,34 +817,45 @@ const handleToolsCall = async (msg, options) => {
|
|
|
810
817
|
break;
|
|
811
818
|
}
|
|
812
819
|
const name = fn?.function?.name || fn?.name;
|
|
820
|
+
if (!name) { continue; }
|
|
813
821
|
await resp(`\nName: ${name}`);
|
|
814
822
|
const f = tools.find(x => insensitiveCompare(
|
|
815
823
|
x.def?.function?.name || x?.def?.name, name
|
|
816
824
|
));
|
|
817
825
|
if (!f?.func) {
|
|
818
|
-
|
|
826
|
+
const rt = `Failed: invalid function name \`${name}\``;
|
|
827
|
+
content.push(packMsg(rt, true));
|
|
828
|
+
await resp(rt);
|
|
819
829
|
continue;
|
|
820
830
|
}
|
|
821
831
|
const description = f.def?.function?.description || f.def?.description;
|
|
822
832
|
description && await resp(`Description: ${description}`);
|
|
833
|
+
f.showReq && isSet(input, true) && Object.keys(input).length
|
|
834
|
+
&& await resp(`Input: ${JSON.stringify(input)}`);
|
|
823
835
|
try {
|
|
824
|
-
|
|
825
|
-
|
|
836
|
+
const output = JSON.stringify((await f?.func(input)) ?? OK);
|
|
837
|
+
content.push(packMsg(output));
|
|
838
|
+
await resp(f.showRes ? `Output: ${output}` : `Status: OK`);
|
|
826
839
|
} catch (err) {
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
840
|
+
const rt = `Failed: ${err.message}`;
|
|
841
|
+
content.push(packMsg(rt, true));
|
|
842
|
+
await resp(rt);
|
|
843
|
+
log(rt);
|
|
830
844
|
}
|
|
831
845
|
}
|
|
832
846
|
switch (options?.flavor) {
|
|
833
|
-
case CLAUDE: content = [{ role: user, content }]; break;
|
|
847
|
+
case CLAUDE: content = content.length ? [{ role: user, content }] : []; break;
|
|
834
848
|
case GEMINI: content = [{ role: user, parts: content }]; break;
|
|
835
849
|
}
|
|
836
|
-
await resp(`\n${TOOLS_END}`);
|
|
850
|
+
responded && await resp(`\n${TOOLS_END}`);
|
|
837
851
|
}
|
|
838
|
-
return { toolsResult: [...preRes, ...content], toolsResponse };
|
|
852
|
+
return { toolsResult: [...content.length ? preRes : [], ...content], toolsResponse };
|
|
839
853
|
};
|
|
840
854
|
|
|
855
|
+
const mergeMsgs = (resp, calls) => [resp, ...calls.length ? [
|
|
856
|
+
`⚠️ Tools recursion limit reached: ${MAX_TOOL_RECURSION}`
|
|
857
|
+
] : []].map(x => x.trim()).join('\n\n');
|
|
858
|
+
|
|
841
859
|
const promptChatGPT = async (content, options = {}) => {
|
|
842
860
|
const { client } = await getOpenAIClient(options);
|
|
843
861
|
// https://github.com/openai/openai-node?tab=readme-ov-file#streaming-responses
|
|
@@ -864,81 +882,63 @@ const promptChatGPT = async (content, options = {}) => {
|
|
|
864
882
|
assert(!(
|
|
865
883
|
options?.reasoning && !MODELS[options.model]?.reasoning
|
|
866
884
|
), `This model does not support reasoning: ${options.model}`);
|
|
867
|
-
|
|
868
|
-
[
|
|
869
|
-
= options?.
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
modalities
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
isSet(deltaFunc[x].index, true) && (curFunc.index = deltaFunc[x].index);
|
|
900
|
-
deltaFunc[x].id && (curFunc.id = deltaFunc[x].id);
|
|
901
|
-
deltaFunc[x].type && (curFunc.type = deltaFunc[x].type);
|
|
902
|
-
curFunc.function || (curFunc.function = { name: '', arguments: '' });
|
|
903
|
-
if (deltaFunc[x].function) {
|
|
904
|
-
deltaFunc[x].function.name && (curFunc.function.name += deltaFunc[x].function.name);
|
|
905
|
-
deltaFunc[x].function.arguments && (curFunc.function.arguments += deltaFunc[x].function.arguments);
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
if (deltaText === '' && !deltaAudio.length) { continue; }
|
|
909
|
-
resultText += deltaText;
|
|
910
|
-
resultAudio = Buffer.concat([resultAudio, deltaAudio]);
|
|
911
|
-
const respAudio = options?.delta ? deltaAudio : resultAudio;
|
|
912
|
-
chunk.choices[0].message = {
|
|
913
|
-
content: options?.delta ? deltaText : resultText,
|
|
914
|
-
...respAudio.length ? { audio: { data: respAudio } } : {},
|
|
915
|
-
};
|
|
916
|
-
await ignoreErrFunc(async () => await options?.stream?.(
|
|
917
|
-
await packGptResp(chunk, { ...options || {}, processing: true })
|
|
918
|
-
), LOG);
|
|
885
|
+
[options.audioMimeType, options.suffix] = [pcm16, 'pcm.wav'];
|
|
886
|
+
let [result, resultAudio, event, resultTools, responded]
|
|
887
|
+
= [options?.result ?? '', Buffer.alloc(0), null, [], false];
|
|
888
|
+
const resp = await client.chat.completions.create({
|
|
889
|
+
modalities, audio: options?.audio || (
|
|
890
|
+
modalities?.find?.(x => x === AUDIO)
|
|
891
|
+
&& { voice: DEFAULT_MODELS[OPENAI_VOICE], format: 'pcm16' }
|
|
892
|
+
), ...messages([
|
|
893
|
+
...options?.messages || [], message, ...options?.toolsResult || [],
|
|
894
|
+
]), ...MODELS[options.model]?.tools ? {
|
|
895
|
+
tools: options?.tools ?? tools.map(x => x.def),
|
|
896
|
+
} : {}, ...options?.jsonMode ? {
|
|
897
|
+
response_format: { type: JSON_OBJECT }
|
|
898
|
+
} : {}, model: options.model, stream: true,
|
|
899
|
+
store: true, tool_choice: 'auto',
|
|
900
|
+
});
|
|
901
|
+
for await (event of resp) {
|
|
902
|
+
event = event?.choices?.[0] || {};
|
|
903
|
+
const delta = event.delta || {};
|
|
904
|
+
let deltaText = delta.content || delta.audio?.transcript || '';
|
|
905
|
+
const deltaAudio = delta.audio?.data ? await convert(
|
|
906
|
+
delta.audio.data, { input: BASE64, expected: BUFFER }
|
|
907
|
+
) : Buffer.alloc(0);
|
|
908
|
+
for (const x of delta.tool_calls || []) {
|
|
909
|
+
let curFunc = resultTools.find(y => y.index === x.index);
|
|
910
|
+
curFunc || (resultTools.push(curFunc = {}));
|
|
911
|
+
isSet(x.index, true) && (curFunc.index = x.index);
|
|
912
|
+
x.id && (curFunc.id = x.id);
|
|
913
|
+
x.type && (curFunc.type = x.type);
|
|
914
|
+
curFunc.function || (curFunc.function = { name: '', arguments: '' });
|
|
915
|
+
x?.function?.name && (curFunc.function.name += x.function.name);
|
|
916
|
+
x?.function?.arguments && (curFunc.function.arguments += x.function.arguments);
|
|
919
917
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
918
|
+
deltaText && (responded = responded || (deltaText = `\n\n${deltaText}`));
|
|
919
|
+
result += deltaText;
|
|
920
|
+
resultAudio = Buffer.concat([resultAudio, deltaAudio]);
|
|
921
|
+
const respAudio = options?.delta ? deltaAudio : resultAudio;
|
|
922
|
+
await streamResp({
|
|
923
|
+
text: options?.delta ? deltaText : result,
|
|
924
|
+
...respAudio.length ? { audio: { data: respAudio } } : {},
|
|
925
|
+
}, options);
|
|
926
926
|
}
|
|
927
|
+
event = {
|
|
928
|
+
role: assistant, text: result, tool_calls: resultTools,
|
|
929
|
+
...resultAudio.length ? { audio: { data: resultAudio } } : {},
|
|
930
|
+
};
|
|
927
931
|
const { toolsResult, toolsResponse }
|
|
928
|
-
= await handleToolsCall(
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
);
|
|
934
|
-
return await (toolsResult.length && !options?.toolsResult ? promptChatGPT(
|
|
935
|
-
content, { ...options || {}, toolsResult, toolsResponse }
|
|
936
|
-
) : packGptResp(resp, options));
|
|
932
|
+
= await handleToolsCall(event, { ...options, result });
|
|
933
|
+
if (toolsResult.length && countToolCalls(toolsResponse) < MAX_TOOL_RECURSION) {
|
|
934
|
+
return promptChatGPT(content, { ...options, toolsResult, result: toolsResponse });
|
|
935
|
+
}
|
|
936
|
+
event.text = mergeMsgs(toolsResponse, toolsResult);
|
|
937
|
+
return await packGptResp(event, options);
|
|
937
938
|
};
|
|
938
939
|
|
|
939
|
-
const promptAzure = async (content, options = {}) =>
|
|
940
|
-
content, { ...options, provider: AZURE }
|
|
941
|
-
);
|
|
940
|
+
const promptAzure = async (content, options = {}) =>
|
|
941
|
+
await promptChatGPT(content, { ...options, provider: AZURE });
|
|
942
942
|
|
|
943
943
|
const promptOllama = async (content, options = {}) => {
|
|
944
944
|
const { client, model } = await getOllamaClient(options);
|
|
@@ -966,13 +966,13 @@ const promptOllama = async (content, options = {}) => {
|
|
|
966
966
|
const promptClaude = async (content, options = {}) => {
|
|
967
967
|
const { client } = await getClaudeClient(options);
|
|
968
968
|
options.model = options?.model || DEFAULT_MODELS[CLAUDE];
|
|
969
|
-
const reasoning = options?.reasoning ?? MODELS[options.model]?.reasoning;
|
|
970
969
|
const resp = await client.messages.create({
|
|
971
970
|
model: options.model, max_tokens: MODELS[options.model].maxOutputTokens,
|
|
972
971
|
messages: [
|
|
973
972
|
...options?.messages || [], buildClaudeMessage(content, options),
|
|
974
973
|
...options?.toolsResult || [],
|
|
975
|
-
], stream:
|
|
974
|
+
], stream: true,
|
|
975
|
+
...options?.reasoning ?? MODELS[options.model]?.reasoning ? {
|
|
976
976
|
thinking: options?.thinking || { type: 'enabled', budget_tokens: 1024 },
|
|
977
977
|
} : {}, // https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
|
|
978
978
|
...MODELS[options.model]?.tools ? {
|
|
@@ -980,68 +980,42 @@ const promptClaude = async (content, options = {}) => {
|
|
|
980
980
|
tool_choice: { type: 'auto' },
|
|
981
981
|
} : {},
|
|
982
982
|
});
|
|
983
|
-
let [event,
|
|
984
|
-
= [null, '', '', '', options?.
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
}
|
|
1000
|
-
if (event?.content_block?.type === 'tool_use') {
|
|
1001
|
-
tool_calls.push({ ...event?.content_block, input: '' });
|
|
1002
|
-
} else if (event?.delta?.partial_json) {
|
|
1003
|
-
tool_calls[tool_calls.length - 1].input += event?.delta?.partial_json;
|
|
1004
|
-
}
|
|
1005
|
-
const delta = thkDelta + txtDelta;
|
|
1006
|
-
if (delta === '') { continue; }
|
|
1007
|
-
result += delta;
|
|
1008
|
-
event.content = [{ type: TEXT, text: options?.delta ? delta : result }];
|
|
1009
|
-
await ignoreErrFunc(async () => await options.stream(
|
|
1010
|
-
await packGptResp(event, { ...options, processing: true })
|
|
1011
|
-
), LOG);
|
|
983
|
+
let [event, text, thinking, signature, result, thinkEnd, tool_use]
|
|
984
|
+
= [null, '', '', '', options?.result ?? '', '', []];
|
|
985
|
+
for await (const chunk of resp) {
|
|
986
|
+
event = chunk?.content_block || chunk?.delta || {};
|
|
987
|
+
let [thkDelta, txtDelta] = [event.thinking || '', event.text || ''];
|
|
988
|
+
text += txtDelta;
|
|
989
|
+
thinking += thkDelta;
|
|
990
|
+
signature = signature || event?.signature || '';
|
|
991
|
+
thkDelta && thkDelta === thinking
|
|
992
|
+
&& (thkDelta = `${THINK_STR}\n${thkDelta}`);
|
|
993
|
+
thinking && txtDelta && !thinkEnd
|
|
994
|
+
&& (thinkEnd = thkDelta = `${thkDelta}\n${THINK_END}\n\n`);
|
|
995
|
+
if (event?.type === 'tool_use') {
|
|
996
|
+
tool_use.push({ ...event, input: '' });
|
|
997
|
+
} else if (event.partial_json) {
|
|
998
|
+
tool_use[tool_use.length - 1].input += event.partial_json;
|
|
1012
999
|
}
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
}
|
|
1016
|
-
tool_calls.length && thinking
|
|
1017
|
-
&& event.content.unshift({ type: THINKING, thinking, signature });
|
|
1018
|
-
} else {
|
|
1019
|
-
event = resp;
|
|
1020
|
-
tool_calls = resp?.content?.filter?.(x => x.type === 'tool_use') || [];
|
|
1000
|
+
txtDelta = thkDelta + txtDelta;
|
|
1001
|
+
result += txtDelta;
|
|
1002
|
+
await streamResp({ text: options?.delta ? txtDelta : result }, options);
|
|
1021
1003
|
}
|
|
1004
|
+
event = {
|
|
1005
|
+
role: assistant, content: [
|
|
1006
|
+
...thinking ? [{ type: THINKING, thinking, signature }] : [],
|
|
1007
|
+
...text ? [{ type: TEXT, text }] : [], ...tool_use,
|
|
1008
|
+
]
|
|
1009
|
+
};
|
|
1022
1010
|
const { toolsResult, toolsResponse } = await handleToolsCall(
|
|
1023
|
-
|
|
1011
|
+
event, { ...options, result, flavor: CLAUDE },
|
|
1024
1012
|
);
|
|
1025
|
-
if (
|
|
1026
|
-
toolsResult[0].content.unshift(
|
|
1027
|
-
...event?.content.filter(x => x?.type !== 'tool_use')
|
|
1028
|
-
);
|
|
1013
|
+
if (tool_use.length && countToolCalls(toolsResponse) < MAX_TOOL_RECURSION) {
|
|
1029
1014
|
return await promptClaude(content, {
|
|
1030
|
-
...options, toolsResult, toolsResponse,
|
|
1015
|
+
...options, toolsResult: [...options?.toolsResult || [], ...toolsResult], result: toolsResponse,
|
|
1031
1016
|
});
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
const thinkPart = event.content.find(x => x.type == THINKING);
|
|
1035
|
-
const prvThink = options?.toolsResult?.find(
|
|
1036
|
-
x => x?.content?.find(y => y?.type === THINKING)
|
|
1037
|
-
)?.content?.find(x => x?.type === THINKING);
|
|
1038
|
-
textPart.text = [
|
|
1039
|
-
...packThink(options?.stream ? null : prvThink?.thinking),
|
|
1040
|
-
...packThink(options?.stream ? null : thinkPart?.thinking),
|
|
1041
|
-
...options?.toolsResponse ? [options?.toolsResponse] : [],
|
|
1042
|
-
textPart.text,
|
|
1043
|
-
].join('\n\n');
|
|
1044
|
-
} return packGptResp(event, options);
|
|
1017
|
+
}
|
|
1018
|
+
return packGptResp({ text: mergeMsgs(toolsResponse, tool_use) }, options);
|
|
1045
1019
|
};
|
|
1046
1020
|
|
|
1047
1021
|
const uploadFile = async (input, options) => {
|
package/lib/manifest.mjs
CHANGED