@framers/agentos 0.9.25 → 0.9.27

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.
Files changed (32) hide show
  1. package/dist/api/generateText.d.ts +11 -0
  2. package/dist/api/generateText.d.ts.map +1 -1
  3. package/dist/api/generateText.js +277 -207
  4. package/dist/api/generateText.js.map +1 -1
  5. package/dist/api/runtime/tool-emulation/activation.d.ts +7 -0
  6. package/dist/api/runtime/tool-emulation/activation.d.ts.map +1 -0
  7. package/dist/api/runtime/tool-emulation/activation.js +17 -0
  8. package/dist/api/runtime/tool-emulation/activation.js.map +1 -0
  9. package/dist/api/runtime/tool-emulation/index.d.ts +5 -0
  10. package/dist/api/runtime/tool-emulation/index.d.ts.map +1 -0
  11. package/dist/api/runtime/tool-emulation/index.js +5 -0
  12. package/dist/api/runtime/tool-emulation/index.js.map +1 -0
  13. package/dist/api/runtime/tool-emulation/loop.d.ts +38 -0
  14. package/dist/api/runtime/tool-emulation/loop.d.ts.map +1 -0
  15. package/dist/api/runtime/tool-emulation/loop.js +53 -0
  16. package/dist/api/runtime/tool-emulation/loop.js.map +1 -0
  17. package/dist/api/runtime/tool-emulation/parser.d.ts +23 -0
  18. package/dist/api/runtime/tool-emulation/parser.d.ts.map +1 -0
  19. package/dist/api/runtime/tool-emulation/parser.js +38 -0
  20. package/dist/api/runtime/tool-emulation/parser.js.map +1 -0
  21. package/dist/api/runtime/tool-emulation/renderer.d.ts +8 -0
  22. package/dist/api/runtime/tool-emulation/renderer.d.ts.map +1 -0
  23. package/dist/api/runtime/tool-emulation/renderer.js +26 -0
  24. package/dist/api/runtime/tool-emulation/renderer.js.map +1 -0
  25. package/dist/api/streamText.d.ts.map +1 -1
  26. package/dist/api/streamText.js +324 -256
  27. package/dist/api/streamText.js.map +1 -1
  28. package/dist/index.d.ts +2 -0
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +6 -0
  31. package/dist/index.js.map +1 -1
  32. package/package.json +1 -1
@@ -1,5 +1,6 @@
1
1
  import { type HostLLMPolicy } from './runtime/hostPolicy.js';
2
2
  import { type AdaptableToolInput } from './runtime/toolAdapter.js';
3
+ import { type ToolMode } from './runtime/tool-emulation/index.js';
3
4
  import type { AgentOSUsageLedgerOptions } from './runtime/usageLedger.js';
4
5
  import type { ITool } from '../core/tools/ITool.js';
5
6
  import type { AgentCallRecord, AgencyTraceEvent } from './types.js';
@@ -180,6 +181,16 @@ export interface GenerateTextOptions {
180
181
  * Each tool-call round trip counts as one step. Defaults to `1`.
181
182
  */
182
183
  maxSteps?: number;
184
+ /**
185
+ * Tool-calling strategy. `'auto'` (default) uses native provider tool-calling,
186
+ * and on a tool-unsupported provider error falls back to a prompt-based shim
187
+ * (tool schemas rendered into the prompt, `<tool_call>` blocks parsed from the
188
+ * model's text). `'native'` forces native only. `'prompt'` forces the shim.
189
+ * The shim makes AgentOS tools work on models without native tool-use (e.g.
190
+ * the uncensored OpenRouter catalog). Shim roundtrips are capped by `maxSteps`
191
+ * (default 5 when unset on the shim path).
192
+ */
193
+ toolMode?: ToolMode;
183
194
  /** Sampling temperature forwarded to the provider (0-2 for most providers). */
184
195
  temperature?: number;
185
196
  /** Hard cap on output tokens. Provider-dependent default applies when omitted. */
@@ -1 +1 @@
1
- {"version":3,"file":"generateText.d.ts","sourceRoot":"","sources":["../../src/api/generateText.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"generateText.d.ts","sourceRoot":"","sources":["../../src/api/generateText.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ import { attachUsageAttributes, toTurnMetricUsage } from './observability.js';
17
17
  import { fireLlmUsageObserver } from './observers.js';
18
18
  import { hostPolicyToRouteParams, mergeRequiredCapabilities, } from './runtime/hostPolicy.js';
19
19
  import { adaptTools } from './runtime/toolAdapter.js';
20
+ import { runEmulatedToolLoop } from './runtime/tool-emulation/index.js';
20
21
  import { resolveDynamicToolCalls } from './runtime/dynamicToolCalling.js';
21
22
  import { recordAgentOSTurnMetrics, withAgentOSSpan } from '../safety/evaluation/observability/otel.js';
22
23
  import { createLogger } from '../core/logging/loggerFactory.js';
@@ -633,119 +634,290 @@ export async function generateText(opts) {
633
634
  span?.setAttribute('agentos.api.plan_steps', resolvedPlan.steps.length);
634
635
  }
635
636
  }
636
- for (let step = 0; step < maxSteps; step++) {
637
- // --- onBeforeGeneration hook ---
638
- let effectiveMessages = messages;
639
- if (opts.onBeforeGeneration) {
640
- try {
641
- const hookCtx = {
642
- messages: [...messages],
643
- system: opts.system,
644
- tools: Array.from(toolMap.values()),
645
- model: resolved.modelId,
646
- provider: resolved.providerId,
647
- step,
648
- prompt: opts.prompt,
637
+ // --- Prompt-based tool-calling shim (toolMode) ---
638
+ // For models without native tool-use, render tool schemas into the
639
+ // prompt and parse <tool_call> blocks out of the model's text. 'prompt'
640
+ // forces it up front; 'auto' tries native first and falls back on the
641
+ // provider's tool-unsupported error (see the catch after the loop).
642
+ const toolMode = opts.toolMode ?? 'auto';
643
+ const shimMaxRoundtrips = opts.maxSteps ?? 5;
644
+ const runShim = async () => {
645
+ const loopResult = await runEmulatedToolLoop({
646
+ tools: Array.from(toolMap.values()),
647
+ messages: messages.map((m) => ({
648
+ role: String(m.role),
649
+ content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content ?? ''),
650
+ })),
651
+ maxRoundtrips: shimMaxRoundtrips,
652
+ callModel: async (msgs) => {
653
+ const r = await provider.generateCompletion(resolved.modelId, msgs, {
654
+ temperature: opts.temperature,
655
+ maxTokens: opts.maxTokens,
656
+ });
657
+ const cc = r.choices?.[0]?.message?.content;
658
+ return {
659
+ text: typeof cc === 'string' ? cc : (cc?.text ?? ''),
660
+ usage: { totalTokens: r.usage?.totalTokens ?? 0 },
649
661
  };
650
- const modified = await opts.onBeforeGeneration(hookCtx);
651
- if (modified) {
652
- effectiveMessages = modified.messages;
662
+ },
663
+ });
664
+ const shimUsage = {
665
+ ...totalUsage,
666
+ totalTokens: (totalUsage.totalTokens ?? 0) + loopResult.totalTokens,
667
+ };
668
+ metricUsage = shimUsage;
669
+ fireLlmUsageObserver({
670
+ provider: resolved.providerId,
671
+ model: resolved.modelId,
672
+ usage: shimUsage,
673
+ source: opts.source,
674
+ finishReason: loopResult.finishReason,
675
+ surface: 'generateText',
676
+ });
677
+ return {
678
+ provider: resolved.providerId,
679
+ model: resolved.modelId,
680
+ text: loopResult.text,
681
+ usage: shimUsage,
682
+ toolCalls: loopResult.toolCalls.map((c) => ({
683
+ name: c.name,
684
+ args: c.args,
685
+ ...(c.error ? { error: c.error } : {}),
686
+ })),
687
+ finishReason: loopResult.finishReason,
688
+ plan: resolvedPlan,
689
+ };
690
+ };
691
+ const toolUnsupportedErr = (e) => e instanceof Error &&
692
+ /support tool use|does not support (tools|function)|no endpoints found that support/i.test(e.message);
693
+ if (tools.length > 0 && toolMode === 'prompt') {
694
+ return await runShim();
695
+ }
696
+ try {
697
+ for (let step = 0; step < maxSteps; step++) {
698
+ // --- onBeforeGeneration hook ---
699
+ let effectiveMessages = messages;
700
+ if (opts.onBeforeGeneration) {
701
+ try {
702
+ const hookCtx = {
703
+ messages: [...messages],
704
+ system: opts.system,
705
+ tools: Array.from(toolMap.values()),
706
+ model: resolved.modelId,
707
+ provider: resolved.providerId,
708
+ step,
709
+ prompt: opts.prompt,
710
+ };
711
+ const modified = await opts.onBeforeGeneration(hookCtx);
712
+ if (modified) {
713
+ effectiveMessages = modified.messages;
714
+ }
715
+ }
716
+ catch (hookErr) {
717
+ console.warn('[agentos] onBeforeGeneration hook error:', hookErr);
653
718
  }
654
719
  }
655
- catch (hookErr) {
656
- console.warn('[agentos] onBeforeGeneration hook error:', hookErr);
657
- }
658
- }
659
- const response = await withAgentOSSpan('agentos.api.generate_text.step', async (stepSpan) => {
660
- stepSpan?.setAttribute('llm.provider', resolved.providerId);
661
- stepSpan?.setAttribute('llm.model', resolved.modelId);
662
- stepSpan?.setAttribute('agentos.api.step', step + 1);
663
- stepSpan?.setAttribute('agentos.api.tool_count', tools.length);
664
- const stepResponse = await provider.generateCompletion(resolved.modelId, effectiveMessages, {
665
- tools: toolSchemas,
666
- temperature: opts.temperature,
667
- maxTokens: opts.maxTokens,
668
- ...(opts._responseFormat ? { responseFormat: opts._responseFormat } : {}),
720
+ const response = await withAgentOSSpan('agentos.api.generate_text.step', async (stepSpan) => {
721
+ stepSpan?.setAttribute('llm.provider', resolved.providerId);
722
+ stepSpan?.setAttribute('llm.model', resolved.modelId);
723
+ stepSpan?.setAttribute('agentos.api.step', step + 1);
724
+ stepSpan?.setAttribute('agentos.api.tool_count', tools.length);
725
+ const stepResponse = await provider.generateCompletion(resolved.modelId, effectiveMessages, {
726
+ tools: toolSchemas,
727
+ temperature: opts.temperature,
728
+ maxTokens: opts.maxTokens,
729
+ ...(opts._responseFormat ? { responseFormat: opts._responseFormat } : {}),
730
+ });
731
+ attachUsageAttributes(stepSpan, {
732
+ promptTokens: stepResponse.usage?.promptTokens,
733
+ completionTokens: stepResponse.usage?.completionTokens,
734
+ totalTokens: stepResponse.usage?.totalTokens,
735
+ costUSD: stepResponse.usage?.costUSD,
736
+ });
737
+ return stepResponse;
669
738
  });
670
- attachUsageAttributes(stepSpan, {
671
- promptTokens: stepResponse.usage?.promptTokens,
672
- completionTokens: stepResponse.usage?.completionTokens,
673
- totalTokens: stepResponse.usage?.totalTokens,
674
- costUSD: stepResponse.usage?.costUSD,
675
- });
676
- return stepResponse;
677
- });
678
- if (response.usage) {
679
- totalUsage.promptTokens += response.usage.promptTokens ?? 0;
680
- totalUsage.completionTokens += response.usage.completionTokens ?? 0;
681
- totalUsage.totalTokens += response.usage.totalTokens ?? 0;
682
- if (typeof response.usage.costUSD === 'number') {
683
- totalUsage.costUSD = (totalUsage.costUSD ?? 0) + response.usage.costUSD;
684
- }
685
- // Plumb prompt-cache metrics through so generateText() callers
686
- // can measure cache hit rate. Provider-layer ModelUsage carries
687
- // these fields; TokenUsage was dropping them.
688
- const cacheRead = response.usage.cacheReadInputTokens;
689
- const cacheCreate = response.usage.cacheCreationInputTokens;
690
- if (typeof cacheRead === 'number' && cacheRead > 0) {
691
- totalUsage.cacheReadTokens = (totalUsage.cacheReadTokens ?? 0) + cacheRead;
739
+ if (response.usage) {
740
+ totalUsage.promptTokens += response.usage.promptTokens ?? 0;
741
+ totalUsage.completionTokens += response.usage.completionTokens ?? 0;
742
+ totalUsage.totalTokens += response.usage.totalTokens ?? 0;
743
+ if (typeof response.usage.costUSD === 'number') {
744
+ totalUsage.costUSD = (totalUsage.costUSD ?? 0) + response.usage.costUSD;
745
+ }
746
+ // Plumb prompt-cache metrics through so generateText() callers
747
+ // can measure cache hit rate. Provider-layer ModelUsage carries
748
+ // these fields; TokenUsage was dropping them.
749
+ const cacheRead = response.usage.cacheReadInputTokens;
750
+ const cacheCreate = response.usage.cacheCreationInputTokens;
751
+ if (typeof cacheRead === 'number' && cacheRead > 0) {
752
+ totalUsage.cacheReadTokens = (totalUsage.cacheReadTokens ?? 0) + cacheRead;
753
+ }
754
+ if (typeof cacheCreate === 'number' && cacheCreate > 0) {
755
+ totalUsage.cacheCreationTokens = (totalUsage.cacheCreationTokens ?? 0) + cacheCreate;
756
+ }
692
757
  }
693
- if (typeof cacheCreate === 'number' && cacheCreate > 0) {
694
- totalUsage.cacheCreationTokens = (totalUsage.cacheCreationTokens ?? 0) + cacheCreate;
758
+ const choice = response.choices?.[0];
759
+ if (!choice)
760
+ break;
761
+ const content = choice.message?.content;
762
+ let textContent = typeof content === 'string' ? content : (content?.text ?? '');
763
+ let toolCallsInChoice = resolveDynamicToolCalls(choice.message?.tool_calls, {
764
+ text: textContent,
765
+ step,
766
+ toolsAvailable: tools.length > 0,
767
+ });
768
+ // --- onAfterGeneration hook ---
769
+ if (opts.onAfterGeneration) {
770
+ try {
771
+ const stepUsage = {
772
+ promptTokens: response.usage?.promptTokens ?? 0,
773
+ completionTokens: response.usage?.completionTokens ?? 0,
774
+ totalTokens: response.usage?.totalTokens ?? 0,
775
+ costUSD: response.usage?.costUSD,
776
+ cacheReadTokens: response.usage?.cacheReadInputTokens,
777
+ cacheCreationTokens: response.usage?.cacheCreationInputTokens,
778
+ };
779
+ const toolCallRecords = toolCallsInChoice.map((tc) => ({
780
+ name: tc.function?.name ?? tc.name ?? '',
781
+ args: tc.function?.arguments ?? '{}',
782
+ }));
783
+ const hookResult = {
784
+ text: textContent,
785
+ toolCalls: toolCallRecords,
786
+ usage: stepUsage,
787
+ step,
788
+ };
789
+ const modified = await opts.onAfterGeneration(hookResult);
790
+ if (modified) {
791
+ textContent = modified.text;
792
+ if (modified.toolCalls.length === 0 && toolCallsInChoice.length > 0) {
793
+ toolCallsInChoice = [];
794
+ }
795
+ }
796
+ }
797
+ catch (hookErr) {
798
+ console.warn('[agentos] onAfterGeneration hook error:', hookErr);
799
+ }
695
800
  }
696
- }
697
- const choice = response.choices?.[0];
698
- if (!choice)
699
- break;
700
- const content = choice.message?.content;
701
- let textContent = typeof content === 'string' ? content : (content?.text ?? '');
702
- let toolCallsInChoice = resolveDynamicToolCalls(choice.message?.tool_calls, {
703
- text: textContent,
704
- step,
705
- toolsAvailable: tools.length > 0,
706
- });
707
- // --- onAfterGeneration hook ---
708
- if (opts.onAfterGeneration) {
709
- try {
710
- const stepUsage = {
711
- promptTokens: response.usage?.promptTokens ?? 0,
712
- completionTokens: response.usage?.completionTokens ?? 0,
713
- totalTokens: response.usage?.totalTokens ?? 0,
714
- costUSD: response.usage?.costUSD,
715
- cacheReadTokens: response.usage?.cacheReadInputTokens,
716
- cacheCreationTokens: response.usage?.cacheCreationInputTokens,
717
- };
718
- const toolCallRecords = toolCallsInChoice.map((tc) => ({
719
- name: tc.function?.name ?? tc.name ?? '',
720
- args: tc.function?.arguments ?? '{}',
721
- }));
722
- const hookResult = {
801
+ if (textContent && toolCallsInChoice.length === 0) {
802
+ metricUsage = totalUsage;
803
+ span?.setAttribute('agentos.api.finish_reason', choice.finishReason ?? 'stop');
804
+ span?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
805
+ attachUsageAttributes(span, totalUsage);
806
+ // 2026-05-29 fire the global LLM usage observer so hosts
807
+ // (wilds-ai foundation_usage_events, billing dashboards) get
808
+ // the resolved provider + model + cost without wrapping every
809
+ // callsite. No-op when no observer is registered.
810
+ fireLlmUsageObserver({
811
+ provider: resolved.providerId,
812
+ model: resolved.modelId,
813
+ usage: totalUsage,
814
+ source: opts.source,
815
+ finishReason: choice.finishReason ?? 'stop',
816
+ surface: 'generateText',
817
+ });
818
+ return {
819
+ provider: resolved.providerId,
820
+ model: resolved.modelId,
723
821
  text: textContent,
724
- toolCalls: toolCallRecords,
725
- usage: stepUsage,
726
- step,
822
+ usage: totalUsage,
823
+ toolCalls: allToolCalls,
824
+ finishReason: (choice.finishReason ?? 'stop'),
825
+ plan: resolvedPlan,
727
826
  };
728
- const modified = await opts.onAfterGeneration(hookResult);
729
- if (modified) {
730
- textContent = modified.text;
731
- if (modified.toolCalls.length === 0 && toolCallsInChoice.length > 0) {
732
- toolCallsInChoice = [];
827
+ }
828
+ if (toolCallsInChoice.length > 0) {
829
+ messages.push({
830
+ role: 'assistant',
831
+ content: textContent || null,
832
+ tool_calls: toolCallsInChoice,
833
+ });
834
+ for (const tc of toolCallsInChoice) {
835
+ const fnName = tc.function?.name ?? tc.name ?? '';
836
+ const fnArgs = tc.function?.arguments ?? '{}';
837
+ const tcId = tc.id ?? '';
838
+ const tool = toolMap.get(fnName);
839
+ const record = {
840
+ name: fnName,
841
+ args: fnArgs,
842
+ };
843
+ let parsedArgs;
844
+ try {
845
+ parsedArgs =
846
+ typeof fnArgs === 'string' ? JSON.parse(fnArgs) : fnArgs;
847
+ record.args = parsedArgs;
848
+ }
849
+ catch {
850
+ record.error = `Tool "${fnName}" arguments were not valid JSON.`;
851
+ messages.push({
852
+ role: 'tool',
853
+ tool_call_id: tcId,
854
+ content: JSON.stringify({ error: record.error }),
855
+ });
856
+ allToolCalls.push(record);
857
+ continue;
858
+ }
859
+ // --- onBeforeToolExecution hook ---
860
+ if (opts.onBeforeToolExecution) {
861
+ try {
862
+ const hookInfo = {
863
+ name: fnName,
864
+ args: parsedArgs,
865
+ id: tcId || '',
866
+ step,
867
+ };
868
+ const hookResult = await opts.onBeforeToolExecution(hookInfo);
869
+ if (hookResult === null) {
870
+ record.error = 'Skipped by onBeforeToolExecution hook';
871
+ messages.push({
872
+ role: 'tool',
873
+ tool_call_id: tcId,
874
+ content: JSON.stringify({ skipped: true }),
875
+ });
876
+ allToolCalls.push(record);
877
+ continue;
878
+ }
879
+ parsedArgs = hookResult.args;
880
+ }
881
+ catch (hookErr) {
882
+ console.warn('[agentos] onBeforeToolExecution hook error:', hookErr);
883
+ }
733
884
  }
885
+ if (tool) {
886
+ try {
887
+ const result = await tool.execute(parsedArgs, buildHelperToolExecutionContext('generateText', helperToolRunId, step, tcId || undefined));
888
+ record.result = result.output;
889
+ record.error = result.success ? undefined : result.error;
890
+ messages.push({
891
+ role: 'tool',
892
+ tool_call_id: tcId,
893
+ content: JSON.stringify(result.output ?? result.error ?? ''),
894
+ });
895
+ }
896
+ catch (err) {
897
+ record.error = err?.message;
898
+ messages.push({
899
+ role: 'tool',
900
+ tool_call_id: tcId,
901
+ content: JSON.stringify({ error: err?.message }),
902
+ });
903
+ }
904
+ }
905
+ else {
906
+ record.error = `Tool "${fnName}" not found.`;
907
+ messages.push({
908
+ role: 'tool',
909
+ tool_call_id: tcId,
910
+ content: JSON.stringify({ error: record.error }),
911
+ });
912
+ }
913
+ allToolCalls.push(record);
734
914
  }
915
+ continue;
735
916
  }
736
- catch (hookErr) {
737
- console.warn('[agentos] onAfterGeneration hook error:', hookErr);
738
- }
739
- }
740
- if (textContent && toolCallsInChoice.length === 0) {
741
917
  metricUsage = totalUsage;
742
918
  span?.setAttribute('agentos.api.finish_reason', choice.finishReason ?? 'stop');
743
919
  span?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
744
920
  attachUsageAttributes(span, totalUsage);
745
- // 2026-05-29 — fire the global LLM usage observer so hosts
746
- // (wilds-ai foundation_usage_events, billing dashboards) get
747
- // the resolved provider + model + cost without wrapping every
748
- // callsite. No-op when no observer is registered.
749
921
  fireLlmUsageObserver({
750
922
  provider: resolved.providerId,
751
923
  model: resolved.modelId,
@@ -764,116 +936,14 @@ export async function generateText(opts) {
764
936
  plan: resolvedPlan,
765
937
  };
766
938
  }
767
- if (toolCallsInChoice.length > 0) {
768
- messages.push({
769
- role: 'assistant',
770
- content: textContent || null,
771
- tool_calls: toolCallsInChoice,
772
- });
773
- for (const tc of toolCallsInChoice) {
774
- const fnName = tc.function?.name ?? tc.name ?? '';
775
- const fnArgs = tc.function?.arguments ?? '{}';
776
- const tcId = tc.id ?? '';
777
- const tool = toolMap.get(fnName);
778
- const record = {
779
- name: fnName,
780
- args: fnArgs,
781
- };
782
- let parsedArgs;
783
- try {
784
- parsedArgs =
785
- typeof fnArgs === 'string' ? JSON.parse(fnArgs) : fnArgs;
786
- record.args = parsedArgs;
787
- }
788
- catch {
789
- record.error = `Tool "${fnName}" arguments were not valid JSON.`;
790
- messages.push({
791
- role: 'tool',
792
- tool_call_id: tcId,
793
- content: JSON.stringify({ error: record.error }),
794
- });
795
- allToolCalls.push(record);
796
- continue;
797
- }
798
- // --- onBeforeToolExecution hook ---
799
- if (opts.onBeforeToolExecution) {
800
- try {
801
- const hookInfo = {
802
- name: fnName,
803
- args: parsedArgs,
804
- id: tcId || '',
805
- step,
806
- };
807
- const hookResult = await opts.onBeforeToolExecution(hookInfo);
808
- if (hookResult === null) {
809
- record.error = 'Skipped by onBeforeToolExecution hook';
810
- messages.push({
811
- role: 'tool',
812
- tool_call_id: tcId,
813
- content: JSON.stringify({ skipped: true }),
814
- });
815
- allToolCalls.push(record);
816
- continue;
817
- }
818
- parsedArgs = hookResult.args;
819
- }
820
- catch (hookErr) {
821
- console.warn('[agentos] onBeforeToolExecution hook error:', hookErr);
822
- }
823
- }
824
- if (tool) {
825
- try {
826
- const result = await tool.execute(parsedArgs, buildHelperToolExecutionContext('generateText', helperToolRunId, step, tcId || undefined));
827
- record.result = result.output;
828
- record.error = result.success ? undefined : result.error;
829
- messages.push({
830
- role: 'tool',
831
- tool_call_id: tcId,
832
- content: JSON.stringify(result.output ?? result.error ?? ''),
833
- });
834
- }
835
- catch (err) {
836
- record.error = err?.message;
837
- messages.push({
838
- role: 'tool',
839
- tool_call_id: tcId,
840
- content: JSON.stringify({ error: err?.message }),
841
- });
842
- }
843
- }
844
- else {
845
- record.error = `Tool "${fnName}" not found.`;
846
- messages.push({
847
- role: 'tool',
848
- tool_call_id: tcId,
849
- content: JSON.stringify({ error: record.error }),
850
- });
851
- }
852
- allToolCalls.push(record);
853
- }
854
- continue;
939
+ }
940
+ catch (loopErr) {
941
+ // 'auto' reactive fallback: when the provider rejects native tool-use,
942
+ // re-run the turn through the prompt-based shim.
943
+ if (tools.length > 0 && toolMode === 'auto' && toolUnsupportedErr(loopErr)) {
944
+ return await runShim();
855
945
  }
856
- metricUsage = totalUsage;
857
- span?.setAttribute('agentos.api.finish_reason', choice.finishReason ?? 'stop');
858
- span?.setAttribute('agentos.api.tool_calls', allToolCalls.length);
859
- attachUsageAttributes(span, totalUsage);
860
- fireLlmUsageObserver({
861
- provider: resolved.providerId,
862
- model: resolved.modelId,
863
- usage: totalUsage,
864
- source: opts.source,
865
- finishReason: choice.finishReason ?? 'stop',
866
- surface: 'generateText',
867
- });
868
- return {
869
- provider: resolved.providerId,
870
- model: resolved.modelId,
871
- text: textContent,
872
- usage: totalUsage,
873
- toolCalls: allToolCalls,
874
- finishReason: (choice.finishReason ?? 'stop'),
875
- plan: resolvedPlan,
876
- };
946
+ throw loopErr;
877
947
  }
878
948
  const lastAssistant = messages.filter((m) => m.role === 'assistant').pop();
879
949
  metricUsage = totalUsage;