@pentoshi/clai 4.10.2 → 4.11.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 +40 -7
- package/dist/agent/runner.js +114 -25
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/task-evidence.js +0 -63
- package/dist/agent/task-evidence.js.map +1 -1
- package/dist/app/adapters/current-store-adapter.js +8 -2
- package/dist/app/adapters/current-store-adapter.js.map +1 -1
- package/dist/app/commands/catalog.js +19 -2
- package/dist/app/commands/catalog.js.map +1 -1
- package/dist/app/controllers/session-controller.d.ts +4 -2
- package/dist/app/controllers/session-controller.js +26 -38
- package/dist/app/controllers/session-controller.js.map +1 -1
- package/dist/app/controllers/session-loop-recovery.d.ts +13 -0
- package/dist/app/controllers/session-loop-recovery.js +43 -0
- package/dist/app/controllers/session-loop-recovery.js.map +1 -0
- package/dist/app/ports/persistence-port.d.ts +3 -1
- package/dist/classic/bootstrap/start-classic.d.ts +1 -0
- package/dist/classic/bootstrap/start-classic.js +12 -4
- package/dist/classic/bootstrap/start-classic.js.map +1 -1
- package/dist/commands/providers.js +2 -0
- package/dist/commands/providers.js.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/llm/capabilities.js +13 -0
- package/dist/llm/capabilities.js.map +1 -1
- package/dist/llm/free-default-model.d.ts +6 -0
- package/dist/llm/free-default-model.js +32 -0
- package/dist/llm/free-default-model.js.map +1 -0
- package/dist/llm/free.js +39 -0
- package/dist/llm/free.js.map +1 -1
- package/dist/llm/merge-gateway.d.ts +6 -0
- package/dist/llm/merge-gateway.js +157 -0
- package/dist/llm/merge-gateway.js.map +1 -0
- package/dist/llm/meta.d.ts +1 -2
- package/dist/llm/meta.js +31 -1140
- package/dist/llm/meta.js.map +1 -1
- package/dist/llm/provider-model-layers.js +6 -0
- package/dist/llm/provider-model-layers.js.map +1 -1
- package/dist/llm/provider-profile-layers.js +21 -0
- package/dist/llm/provider-profile-layers.js.map +1 -1
- package/dist/llm/provider.js +68 -0
- package/dist/llm/provider.js.map +1 -1
- package/dist/llm/reasoning-capability.js +8 -0
- package/dist/llm/reasoning-capability.js.map +1 -1
- package/dist/llm/responses-complete.d.ts +4 -0
- package/dist/llm/responses-complete.js +28 -0
- package/dist/llm/responses-complete.js.map +1 -0
- package/dist/llm/responses-config.d.ts +22 -0
- package/dist/llm/responses-config.js +19 -0
- package/dist/llm/responses-config.js.map +1 -0
- package/dist/llm/responses-dialect.d.ts +6 -0
- package/dist/llm/responses-dialect.js +6 -0
- package/dist/llm/responses-dialect.js.map +1 -0
- package/dist/llm/responses-http.d.ts +13 -0
- package/dist/llm/responses-http.js +88 -0
- package/dist/llm/responses-http.js.map +1 -0
- package/dist/llm/responses-parse.d.ts +42 -0
- package/dist/llm/responses-parse.js +242 -0
- package/dist/llm/responses-parse.js.map +1 -0
- package/dist/llm/responses-request.d.ts +15 -0
- package/dist/llm/responses-request.js +209 -0
- package/dist/llm/responses-request.js.map +1 -0
- package/dist/llm/responses-stream-accumulator.d.ts +38 -0
- package/dist/llm/responses-stream-accumulator.js +102 -0
- package/dist/llm/responses-stream-accumulator.js.map +1 -0
- package/dist/llm/responses-stream-events.d.ts +6 -0
- package/dist/llm/responses-stream-events.js +398 -0
- package/dist/llm/responses-stream-events.js.map +1 -0
- package/dist/llm/responses-stream-watchdog.d.ts +14 -0
- package/dist/llm/responses-stream-watchdog.js +64 -0
- package/dist/llm/responses-stream-watchdog.js.map +1 -0
- package/dist/llm/responses-stream.d.ts +4 -0
- package/dist/llm/responses-stream.js +264 -0
- package/dist/llm/responses-stream.js.map +1 -0
- package/dist/llm/router.js +3 -0
- package/dist/llm/router.js.map +1 -1
- package/dist/llm/tool-protocol.js +35 -3
- package/dist/llm/tool-protocol.js.map +1 -1
- package/dist/mcp/auth/host-credentials.d.ts +11 -0
- package/dist/mcp/auth/host-credentials.js +54 -0
- package/dist/mcp/auth/host-credentials.js.map +1 -0
- package/dist/mcp/auth/loopback.d.ts +16 -0
- package/dist/mcp/auth/loopback.js +126 -0
- package/dist/mcp/auth/loopback.js.map +1 -0
- package/dist/mcp/auth/metadata.d.ts +9 -0
- package/dist/mcp/auth/metadata.js +102 -0
- package/dist/mcp/auth/metadata.js.map +1 -0
- package/dist/mcp/auth/pkce.d.ts +3 -0
- package/dist/mcp/auth/pkce.js +17 -0
- package/dist/mcp/auth/pkce.js.map +1 -0
- package/dist/mcp/auth/provider.d.ts +24 -0
- package/dist/mcp/auth/provider.js +372 -0
- package/dist/mcp/auth/provider.js.map +1 -0
- package/dist/mcp/auth/registration.d.ts +12 -0
- package/dist/mcp/auth/registration.js +38 -0
- package/dist/mcp/auth/registration.js.map +1 -0
- package/dist/mcp/auth/security.d.ts +2 -0
- package/dist/mcp/auth/security.js +29 -0
- package/dist/mcp/auth/security.js.map +1 -0
- package/dist/mcp/auth/token-exchange.d.ts +24 -0
- package/dist/mcp/auth/token-exchange.js +66 -0
- package/dist/mcp/auth/token-exchange.js.map +1 -0
- package/dist/mcp/auth/token-store.d.ts +3 -0
- package/dist/mcp/auth/token-store.js +170 -0
- package/dist/mcp/auth/token-store.js.map +1 -0
- package/dist/mcp/auth/types.d.ts +62 -0
- package/dist/mcp/auth/types.js +2 -0
- package/dist/mcp/auth/types.js.map +1 -0
- package/dist/mcp/auth/www-authenticate.d.ts +2 -0
- package/dist/mcp/auth/www-authenticate.js +42 -0
- package/dist/mcp/auth/www-authenticate.js.map +1 -0
- package/dist/mcp/discovery.js +48 -1
- package/dist/mcp/discovery.js.map +1 -1
- package/dist/mcp/manager.d.ts +19 -0
- package/dist/mcp/manager.js +102 -10
- package/dist/mcp/manager.js.map +1 -1
- package/dist/mcp/mentions.js +2 -2
- package/dist/mcp/mentions.js.map +1 -1
- package/dist/mcp/runtime.d.ts +12 -0
- package/dist/mcp/runtime.js +146 -8
- package/dist/mcp/runtime.js.map +1 -1
- package/dist/mcp/transport-http.d.ts +12 -1
- package/dist/mcp/transport-http.js +160 -45
- package/dist/mcp/transport-http.js.map +1 -1
- package/dist/mcp/types.d.ts +18 -0
- package/dist/mcp/types.js.map +1 -1
- package/dist/mcp/validation.d.ts +10 -1
- package/dist/mcp/validation.js +111 -1
- package/dist/mcp/validation.js.map +1 -1
- package/dist/noninteractive/cancellation.d.ts +15 -0
- package/dist/noninteractive/cancellation.js +49 -0
- package/dist/noninteractive/cancellation.js.map +1 -0
- package/dist/noninteractive/readline-prompts.d.ts +1 -0
- package/dist/noninteractive/readline-prompts.js +14 -0
- package/dist/noninteractive/readline-prompts.js.map +1 -1
- package/dist/noninteractive/start-noninteractive.js +11 -10
- package/dist/noninteractive/start-noninteractive.js.map +1 -1
- package/dist/os/screen-sequences.d.ts +4 -0
- package/dist/os/screen-sequences.js +9 -0
- package/dist/os/screen-sequences.js.map +1 -1
- package/dist/os/terminal-rescue.js +2 -2
- package/dist/os/terminal-rescue.js.map +1 -1
- package/dist/os/terminal-write.d.ts +5 -0
- package/dist/os/terminal-write.js +45 -0
- package/dist/os/terminal-write.js.map +1 -0
- package/dist/safety/classifier.js +7 -2
- package/dist/safety/classifier.js.map +1 -1
- package/dist/session-runtime/alt-screen.js +2 -1
- package/dist/session-runtime/alt-screen.js.map +1 -1
- package/dist/session-runtime/child-bridge.d.ts +1 -1
- package/dist/session-runtime/child-bridge.js +7 -2
- package/dist/session-runtime/child-bridge.js.map +1 -1
- package/dist/session-runtime/client.js +13 -5
- package/dist/session-runtime/client.js.map +1 -1
- package/dist/session-runtime/host.d.ts +2 -0
- package/dist/session-runtime/host.js +19 -2
- package/dist/session-runtime/host.js.map +1 -1
- package/dist/session-runtime/reaper.d.ts +4 -0
- package/dist/session-runtime/reaper.js +64 -0
- package/dist/session-runtime/reaper.js.map +1 -0
- package/dist/session-runtime/terminal-modes.d.ts +8 -0
- package/dist/session-runtime/terminal-modes.js +51 -0
- package/dist/session-runtime/terminal-modes.js.map +1 -0
- package/dist/session-runtime/types.d.ts +2 -0
- package/dist/store/config.js +1 -0
- package/dist/store/config.js.map +1 -1
- package/dist/store/history.d.ts +9 -3
- package/dist/store/history.js +39 -8
- package/dist/store/history.js.map +1 -1
- package/dist/store/session-model.d.ts +28 -0
- package/dist/store/session-model.js +212 -0
- package/dist/store/session-model.js.map +1 -0
- package/dist/tools/definitions.d.ts +2 -0
- package/dist/tools/definitions.js +54 -0
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tui-v2/bootstrap/renderer-handle.d.ts +2 -1
- package/dist/tui-v2/bootstrap/renderer-handle.js +2 -1
- package/dist/tui-v2/bootstrap/renderer-handle.js.map +1 -1
- package/dist/tui-v2/bootstrap/resize-repaint.d.ts +3 -1
- package/dist/tui-v2/bootstrap/resize-repaint.js +18 -2
- package/dist/tui-v2/bootstrap/resize-repaint.js.map +1 -1
- package/dist/tui-v2/bootstrap/start-tui-v2.d.ts +1 -0
- package/dist/tui-v2/bootstrap/start-tui-v2.js +20 -17
- package/dist/tui-v2/bootstrap/start-tui-v2.js.map +1 -1
- package/dist/tui-v2/components/transcript/intro-card.js +2 -2
- package/dist/tui-v2/components/transcript/intro-card.js.map +1 -1
- package/dist/tui-v2/composer/composer-editor.js +4 -2
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -1
- package/dist/ui-core/bootstrap/composition-root.d.ts +2 -2
- package/dist/ui-core/bootstrap/composition-root.js +3 -1
- package/dist/ui-core/bootstrap/composition-root.js.map +1 -1
- package/dist/ui-core/bootstrap/exit-epilogue.d.ts +2 -2
- package/dist/ui-core/bootstrap/exit-epilogue.js +1 -1
- package/dist/ui-core/bootstrap/exit-epilogue.js.map +1 -1
- package/dist/ui-core/bootstrap/session-resume.js +10 -0
- package/dist/ui-core/bootstrap/session-resume.js.map +1 -1
- package/dist/ui-core/commands/mcp-commands.js +182 -70
- package/dist/ui-core/commands/mcp-commands.js.map +1 -1
- package/dist/ui-core/commands/picker-commands.js +10 -8
- package/dist/ui-core/commands/picker-commands.js.map +1 -1
- package/dist/ui-core/commands/session-commands.js +41 -8
- package/dist/ui-core/commands/session-commands.js.map +1 -1
- package/dist/version.generated.d.ts +2 -2
- package/dist/version.generated.js +2 -2
- package/package.json +1 -1
package/dist/llm/meta.js
CHANGED
|
@@ -1,397 +1,45 @@
|
|
|
1
1
|
import { defaultModels } from "./provider.js";
|
|
2
2
|
import { cacheAffinityKey } from "./cache-affinity.js";
|
|
3
|
-
import { readJson, ingestOpenAiModelCatalog
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import { createReasoningArtifact, createReasoningArtifactProvenance, reasoningArtifactItems, reasoningArtifactsForMessage, selectReasoningArtifactsForReplay, } from "./reasoning-artifacts.js";
|
|
9
|
-
import { compileRequestPlan } from "./request-plan.js";
|
|
10
|
-
import { emitStreamReasoningArtifacts, emitStreamReasoningDelta, } from "./stream-events.js";
|
|
11
|
-
import { META_STREAM_TERMINAL, requireTerminalProof, } from "./stream-terminal.js";
|
|
3
|
+
import { readJson, ingestOpenAiModelCatalog } from "./http.js";
|
|
4
|
+
import { runGenerationAttempt } from "./operation-usage.js";
|
|
5
|
+
import { META_STREAM_TERMINAL } from "./stream-terminal.js";
|
|
6
|
+
import { mapResponsesEffort, responsesComplete, responsesReasoningSummary, responsesStream, } from "./responses-dialect.js";
|
|
7
|
+
export { parseResponsesUsage as parseMetaUsage } from "./responses-dialect.js";
|
|
12
8
|
const baseUrl = "https://api.meta.ai/v1";
|
|
13
9
|
const modelCache = new Map();
|
|
14
10
|
const CACHE_TTL_MS = 60 * 60 * 1000;
|
|
15
|
-
function mapMetaEffort(e) {
|
|
16
|
-
if (e === "none" || e === "minimal")
|
|
17
|
-
return "minimal";
|
|
18
|
-
if (e === "max" || e === "xhigh")
|
|
19
|
-
return "xhigh";
|
|
20
|
-
if (e === "low")
|
|
21
|
-
return "low";
|
|
22
|
-
if (e === "high")
|
|
23
|
-
return "high";
|
|
24
|
-
return "medium";
|
|
25
|
-
}
|
|
26
11
|
function metaReasoningPayload(reasoning) {
|
|
27
12
|
const enabled = Boolean(reasoning?.enabled);
|
|
28
|
-
const
|
|
29
|
-
const eff = mapMetaEffort(effort);
|
|
13
|
+
const eff = mapResponsesEffort(reasoning?.effort ?? "medium");
|
|
30
14
|
if (!enabled)
|
|
31
15
|
return { effort: "minimal" };
|
|
32
|
-
|
|
33
|
-
if (eff === "xhigh" || eff === "high")
|
|
34
|
-
summary = "detailed";
|
|
35
|
-
else if (eff === "medium")
|
|
36
|
-
summary = "concise";
|
|
37
|
-
else
|
|
38
|
-
summary = "auto";
|
|
39
|
-
return { effort: eff, summary };
|
|
16
|
+
return { effort: eff, summary: responsesReasoningSummary(eff) };
|
|
40
17
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
.filter((artifact) => artifact.kind === "encrypted")
|
|
49
|
-
.sort((left, right) => left.position.sequence - right.position.sequence)
|
|
50
|
-
.map((artifact) => {
|
|
51
|
-
const byId = artifact.position.toolCallId
|
|
52
|
-
? message.toolCalls?.findIndex((toolCall) => toolCall.id === artifact.position.toolCallId)
|
|
53
|
-
: undefined;
|
|
54
|
-
const toolCallIndex = artifact.position.toolCallIndex ??
|
|
55
|
-
(byId !== undefined && byId >= 0 ? byId : undefined);
|
|
18
|
+
const META_RESPONSES_CONFIG = {
|
|
19
|
+
baseUrl,
|
|
20
|
+
providerId: "meta",
|
|
21
|
+
displayName: "Meta Model API",
|
|
22
|
+
artifactDialect: "meta-responses",
|
|
23
|
+
terminalPolicy: META_STREAM_TERMINAL,
|
|
24
|
+
buildHeaders(auth, accept) {
|
|
56
25
|
return {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
function appendMetaReplayItems(input, entries) {
|
|
63
|
-
for (const entry of entries)
|
|
64
|
-
input.push(...entry.items);
|
|
65
|
-
}
|
|
66
|
-
function toResponsesInput(messages, supportsVision, replay) {
|
|
67
|
-
const input = [];
|
|
68
|
-
for (const m of messages) {
|
|
69
|
-
if (m.role === "system") {
|
|
70
|
-
input.push({
|
|
71
|
-
type: "message",
|
|
72
|
-
role: "system",
|
|
73
|
-
content: [{ type: "input_text", text: m.content }],
|
|
74
|
-
});
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
if (m.role === "user") {
|
|
78
|
-
const blocks = [];
|
|
79
|
-
if (m.content)
|
|
80
|
-
blocks.push({ type: "input_text", text: m.content });
|
|
81
|
-
if (supportsVision && m.images && m.images.length > 0) {
|
|
82
|
-
for (const img of m.images) {
|
|
83
|
-
const mt = (img.mediaType || "").toLowerCase();
|
|
84
|
-
const dataUrl = `data:${img.mediaType};base64,${img.dataBase64}`;
|
|
85
|
-
if (mt === "application/pdf") {
|
|
86
|
-
const filename = img.path ? img.path.split("/").pop() || "document.pdf" : "document.pdf";
|
|
87
|
-
blocks.push({ type: "input_file", filename, file_data: dataUrl });
|
|
88
|
-
}
|
|
89
|
-
else if (mt.startsWith("video/")) {
|
|
90
|
-
blocks.push({ type: "input_video", video_url: dataUrl });
|
|
91
|
-
}
|
|
92
|
-
else if (mt.startsWith("audio/")) {
|
|
93
|
-
blocks.push({ type: "input_audio", input_audio: { data: img.dataBase64, format: mt.includes("wav") ? "wav" : "mp3" } });
|
|
94
|
-
}
|
|
95
|
-
else {
|
|
96
|
-
blocks.push({ type: "input_image", image_url: dataUrl, detail: "high" });
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (blocks.length === 0)
|
|
101
|
-
blocks.push({ type: "input_text", text: "" });
|
|
102
|
-
input.push({ type: "message", role: "user", content: blocks });
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
if (m.role === "assistant") {
|
|
106
|
-
const replayArtifacts = metaReplayArtifacts(m, replay);
|
|
107
|
-
const leadingArtifacts = replayArtifacts.filter((artifact) => artifact.toolCallIndex === undefined);
|
|
108
|
-
const artifactsByTool = new Map();
|
|
109
|
-
for (const artifact of replayArtifacts) {
|
|
110
|
-
if (artifact.toolCallIndex === undefined)
|
|
111
|
-
continue;
|
|
112
|
-
const current = artifactsByTool.get(artifact.toolCallIndex) ?? [];
|
|
113
|
-
current.push(artifact);
|
|
114
|
-
artifactsByTool.set(artifact.toolCallIndex, current);
|
|
115
|
-
}
|
|
116
|
-
const hasTools = m.toolCalls && m.toolCalls.length > 0;
|
|
117
|
-
if (hasTools) {
|
|
118
|
-
appendMetaReplayItems(input, leadingArtifacts);
|
|
119
|
-
if (m.content && m.content.trim()) {
|
|
120
|
-
input.push({
|
|
121
|
-
type: "message",
|
|
122
|
-
role: "assistant",
|
|
123
|
-
phase: "commentary",
|
|
124
|
-
content: [{ type: "output_text", text: m.content }],
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
for (const [toolCallIndex, tc] of m.toolCalls.entries()) {
|
|
128
|
-
appendMetaReplayItems(input, artifactsByTool.get(toolCallIndex) ?? []);
|
|
129
|
-
const wire = toWireName(tc.name);
|
|
130
|
-
input.push({
|
|
131
|
-
type: "function_call",
|
|
132
|
-
call_id: tc.id,
|
|
133
|
-
name: wire,
|
|
134
|
-
arguments: tc.rawArguments ?? JSON.stringify(tc.args ?? {}),
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
continue;
|
|
138
|
-
}
|
|
139
|
-
appendMetaReplayItems(input, replayArtifacts);
|
|
140
|
-
if (m.content !== undefined && m.content !== null) {
|
|
141
|
-
input.push({
|
|
142
|
-
type: "message",
|
|
143
|
-
role: "assistant",
|
|
144
|
-
content: [{ type: "output_text", text: m.content }],
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
if (m.role === "tool") {
|
|
150
|
-
input.push({
|
|
151
|
-
type: "function_call_output",
|
|
152
|
-
call_id: m.toolCallId ?? `call_${Date.now()}`,
|
|
153
|
-
output: m.content,
|
|
154
|
-
});
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
return input;
|
|
159
|
-
}
|
|
160
|
-
function toResponsesTools(tools) {
|
|
161
|
-
if (!tools || tools.length === 0)
|
|
162
|
-
return undefined;
|
|
163
|
-
return tools.map((t) => ({
|
|
164
|
-
type: "function",
|
|
165
|
-
name: t.wireName,
|
|
166
|
-
description: t.description,
|
|
167
|
-
parameters: t.parameters,
|
|
168
|
-
}));
|
|
169
|
-
}
|
|
170
|
-
export function parseMetaUsage(raw) {
|
|
171
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
172
|
-
return undefined;
|
|
173
|
-
const u = raw;
|
|
174
|
-
const inputTokens = u.input_tokens ??
|
|
175
|
-
u.prompt_tokens ??
|
|
176
|
-
u.inputTokens;
|
|
177
|
-
const outputTokens = u.output_tokens ??
|
|
178
|
-
u.completion_tokens ??
|
|
179
|
-
u.outputTokens;
|
|
180
|
-
const totalTokens = u.total_tokens ??
|
|
181
|
-
u.totalTokens;
|
|
182
|
-
const inputDetails = u.input_tokens_details;
|
|
183
|
-
const promptDetails = u.prompt_tokens_details;
|
|
184
|
-
const outputDetails = u.output_tokens_details;
|
|
185
|
-
const completionDetails = u.completion_tokens_details;
|
|
186
|
-
const cached = inputDetails?.cached_tokens ?? promptDetails?.cached_tokens;
|
|
187
|
-
const cacheCreation = inputDetails?.cache_creation_tokens ??
|
|
188
|
-
promptDetails?.cache_creation_tokens ??
|
|
189
|
-
u.cache_creation_input_tokens;
|
|
190
|
-
const uncached = inputDetails?.uncached_tokens ??
|
|
191
|
-
promptDetails?.uncached_tokens ??
|
|
192
|
-
u.prompt_cache_miss_tokens;
|
|
193
|
-
const reasoning = outputDetails?.reasoning_tokens ?? completionDetails?.reasoning_tokens;
|
|
194
|
-
return normalizeTokenUsage({
|
|
195
|
-
promptTokens: inputTokens,
|
|
196
|
-
completionTokens: outputTokens,
|
|
197
|
-
totalTokens,
|
|
198
|
-
cachedPromptTokens: typeof cached === "number" ? cached : undefined,
|
|
199
|
-
cacheCreationTokens: typeof cacheCreation === "number" ? cacheCreation : undefined,
|
|
200
|
-
uncachedPromptTokens: typeof uncached === "number" ? uncached : undefined,
|
|
201
|
-
reasoningTokens: typeof reasoning === "number" ? reasoning : undefined,
|
|
202
|
-
exact: true,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
function extractReasoningSummary(item) {
|
|
206
|
-
if (!item || typeof item !== "object")
|
|
207
|
-
return "";
|
|
208
|
-
const obj = item;
|
|
209
|
-
const summary = obj.summary;
|
|
210
|
-
if (!Array.isArray(summary))
|
|
211
|
-
return "";
|
|
212
|
-
let out = "";
|
|
213
|
-
for (const s of summary) {
|
|
214
|
-
if (s && typeof s === "object" && typeof s.text === "string") {
|
|
215
|
-
out += s.text;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return out;
|
|
219
|
-
}
|
|
220
|
-
function buildResponsesBody(options) {
|
|
221
|
-
const plan = compileRequestPlan({
|
|
222
|
-
provider: "meta",
|
|
223
|
-
model: options.model,
|
|
224
|
-
messages: options.messages,
|
|
225
|
-
stream: options.stream,
|
|
226
|
-
endpoint: baseUrl,
|
|
227
|
-
reasoning: options.reasoning,
|
|
228
|
-
tools: options.tools,
|
|
229
|
-
parallelToolCalls: options.parallelToolCalls,
|
|
230
|
-
temperature: options.temperature,
|
|
231
|
-
maxTokens: options.maxTokens,
|
|
232
|
-
});
|
|
233
|
-
const reasoning = metaReasoningPayload(plan.controls.reasoning);
|
|
234
|
-
const input = toResponsesInput([...plan.timeline.messages], plan.images.visionAccepted, {
|
|
235
|
-
target: plan.replay.target,
|
|
236
|
-
observe: options.reasoningArtifactReplayObserver,
|
|
237
|
-
});
|
|
238
|
-
const tools = toResponsesTools(plan.tools.definitions.length ? [...plan.tools.definitions] : undefined);
|
|
239
|
-
const reasoningOn = Boolean(plan.controls.reasoning?.enabled);
|
|
240
|
-
const defaultMax = reasoningOn ? 8192 : 4096;
|
|
241
|
-
const requestedMax = Math.max(16, plan.controls.requestedMaxTokens ?? defaultMax);
|
|
242
|
-
const effectiveMax = plan.policy.limits.outputTokens === undefined
|
|
243
|
-
? requestedMax
|
|
244
|
-
: Math.min(requestedMax, plan.policy.limits.outputTokens);
|
|
245
|
-
const body = {
|
|
246
|
-
model: options.model,
|
|
247
|
-
input,
|
|
248
|
-
store: false,
|
|
249
|
-
prompt_cache_key: `${options.purpose === "auxiliary" ? "aux-" : ""}${cacheAffinityKey("meta", options.model, options.messages)}`,
|
|
250
|
-
prompt_cache_retention: "24h",
|
|
251
|
-
include: ["reasoning.encrypted_content"],
|
|
252
|
-
max_output_tokens: effectiveMax,
|
|
253
|
-
temperature: plan.controls.temperature,
|
|
254
|
-
};
|
|
255
|
-
if (plan.controls.topP !== undefined)
|
|
256
|
-
body.top_p = plan.controls.topP;
|
|
257
|
-
if (reasoning)
|
|
258
|
-
body.reasoning = reasoning;
|
|
259
|
-
if (options.stream)
|
|
260
|
-
body.stream = true;
|
|
261
|
-
if (tools) {
|
|
262
|
-
body.tools = tools;
|
|
263
|
-
body.tool_choice = "auto";
|
|
264
|
-
body.parallel_tool_calls = options.parallelToolCalls === false ? false : true;
|
|
265
|
-
}
|
|
266
|
-
return JSON.stringify(body);
|
|
267
|
-
}
|
|
268
|
-
function parseResponsesOutput(data) {
|
|
269
|
-
const output = Array.isArray(data.output) ? data.output : [];
|
|
270
|
-
let text = "";
|
|
271
|
-
let reasoningSummary = "";
|
|
272
|
-
const toolCalls = [];
|
|
273
|
-
const reasoningItems = [];
|
|
274
|
-
const reasoningItemSequences = [];
|
|
275
|
-
const toolCallSequences = [];
|
|
276
|
-
for (const [sequence, item] of output.entries()) {
|
|
277
|
-
if (!item || typeof item !== "object")
|
|
278
|
-
continue;
|
|
279
|
-
const obj = item;
|
|
280
|
-
if (obj.type === "message" && obj.role === "assistant") {
|
|
281
|
-
const content = obj.content;
|
|
282
|
-
if (Array.isArray(content)) {
|
|
283
|
-
for (const block of content) {
|
|
284
|
-
if (block && typeof block === "object" && block.type === "output_text" && typeof block.text === "string") {
|
|
285
|
-
text += block.text;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
else if (obj.type === "reasoning") {
|
|
291
|
-
const s = extractReasoningSummary(obj);
|
|
292
|
-
if (s)
|
|
293
|
-
reasoningSummary += s;
|
|
294
|
-
if (typeof obj.encrypted_content === "string" && obj.encrypted_content) {
|
|
295
|
-
reasoningItems.push({ ...obj });
|
|
296
|
-
reasoningItemSequences.push(sequence);
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
else if (obj.type === "function_call") {
|
|
300
|
-
const callId = typeof obj.call_id === "string" ? obj.call_id : typeof obj.id === "string" ? obj.id : `call_${toolCalls.length}`;
|
|
301
|
-
const nameWire = typeof obj.name === "string" ? obj.name : "";
|
|
302
|
-
const canonical = fromWireName(nameWire) ?? nameWire;
|
|
303
|
-
const rawArgs = typeof obj.arguments === "string" ? obj.arguments : JSON.stringify(obj.arguments ?? {});
|
|
304
|
-
let args;
|
|
305
|
-
try {
|
|
306
|
-
const parsed = JSON.parse(rawArgs);
|
|
307
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
308
|
-
args = parsed;
|
|
309
|
-
else
|
|
310
|
-
args = {};
|
|
311
|
-
}
|
|
312
|
-
catch {
|
|
313
|
-
args = parseToolArguments(rawArgs);
|
|
314
|
-
}
|
|
315
|
-
const toolCallIndex = toolCalls.length;
|
|
316
|
-
toolCalls.push({ id: callId, name: canonical, args, rawArguments: rawArgs });
|
|
317
|
-
toolCallSequences.push({ sequence, toolCallIndex });
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
const reasoningItemPositions = reasoningItemSequences.map((sequence) => {
|
|
321
|
-
const followingTool = toolCallSequences.find((toolCall) => toolCall.sequence > sequence);
|
|
322
|
-
return followingTool
|
|
323
|
-
? { sequence, toolCallIndex: followingTool.toolCallIndex }
|
|
324
|
-
: { sequence };
|
|
325
|
-
});
|
|
326
|
-
const usage = parseMetaUsage(data.usage);
|
|
327
|
-
return {
|
|
328
|
-
text,
|
|
329
|
-
toolCalls,
|
|
330
|
-
usage,
|
|
331
|
-
reasoningSummary,
|
|
332
|
-
reasoningItems,
|
|
333
|
-
reasoningItemPositions,
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
function metaReasoningArtifacts(model, items, positions) {
|
|
337
|
-
const provenance = createReasoningArtifactProvenance({
|
|
338
|
-
provider: "meta",
|
|
339
|
-
model,
|
|
340
|
-
dialect: "meta-responses",
|
|
341
|
-
endpoint: baseUrl,
|
|
342
|
-
});
|
|
343
|
-
const artifacts = items.map((item, index) => {
|
|
344
|
-
const position = positions[index] ?? { sequence: index };
|
|
345
|
-
const replayable = position.toolCallIndex !== undefined;
|
|
346
|
-
return createReasoningArtifact({
|
|
347
|
-
kind: "encrypted",
|
|
348
|
-
raw: item,
|
|
349
|
-
provenance,
|
|
350
|
-
replay: replayable
|
|
351
|
-
? { scope: "tool-turn", persistence: "tool-turn" }
|
|
352
|
-
: { scope: "none", persistence: "never" },
|
|
353
|
-
position: {
|
|
354
|
-
sequence: position.sequence,
|
|
355
|
-
placement: replayable ? "before-tool-call" : "assistant",
|
|
356
|
-
...(replayable ? { toolCallIndex: position.toolCallIndex } : {}),
|
|
357
|
-
},
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
return artifacts.length ? artifacts : undefined;
|
|
361
|
-
}
|
|
362
|
-
function readWithAbort(reader, signal) {
|
|
363
|
-
if (signal.aborted) {
|
|
364
|
-
return Promise.reject(signal.reason ?? new Error("Stream aborted"));
|
|
365
|
-
}
|
|
366
|
-
return new Promise((resolve, reject) => {
|
|
367
|
-
let settled = false;
|
|
368
|
-
const cleanup = () => signal.removeEventListener("abort", abort);
|
|
369
|
-
const succeed = (value) => {
|
|
370
|
-
if (settled)
|
|
371
|
-
return;
|
|
372
|
-
settled = true;
|
|
373
|
-
cleanup();
|
|
374
|
-
resolve(value);
|
|
26
|
+
"content-type": "application/json",
|
|
27
|
+
accept,
|
|
28
|
+
authorization: `Bearer ${auth.apiKey}`,
|
|
375
29
|
};
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
30
|
+
},
|
|
31
|
+
reasoningPayload(reasoning) {
|
|
32
|
+
return metaReasoningPayload(reasoning);
|
|
33
|
+
},
|
|
34
|
+
bodyExtras(context) {
|
|
35
|
+
return {
|
|
36
|
+
store: false,
|
|
37
|
+
prompt_cache_key: `${context.purpose === "auxiliary" ? "aux-" : ""}${cacheAffinityKey("meta", context.model, context.messages)}`,
|
|
38
|
+
prompt_cache_retention: "24h",
|
|
39
|
+
include: ["reasoning.encrypted_content"],
|
|
385
40
|
};
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
void reader.read().then(succeed, fail);
|
|
389
|
-
}
|
|
390
|
-
catch (error) {
|
|
391
|
-
fail(error);
|
|
392
|
-
}
|
|
393
|
-
});
|
|
394
|
-
}
|
|
41
|
+
},
|
|
42
|
+
};
|
|
395
43
|
export const metaProvider = {
|
|
396
44
|
id: "meta",
|
|
397
45
|
reasoningStyle: "meta",
|
|
@@ -439,84 +87,7 @@ export const metaProvider = {
|
|
|
439
87
|
model,
|
|
440
88
|
mode: "complete",
|
|
441
89
|
reason: request.attemptReason ?? "initial",
|
|
442
|
-
},
|
|
443
|
-
const body = buildResponsesBody({
|
|
444
|
-
model,
|
|
445
|
-
messages: request.messages,
|
|
446
|
-
maxTokens: request.maxTokens,
|
|
447
|
-
temperature: request.temperature,
|
|
448
|
-
stream: false,
|
|
449
|
-
reasoning: request.thinking,
|
|
450
|
-
tools: request.tools,
|
|
451
|
-
parallelToolCalls: request.parallelToolCalls,
|
|
452
|
-
purpose: request.purpose,
|
|
453
|
-
reasoningArtifactReplayObserver: request.onReasoningArtifactReplayDecision,
|
|
454
|
-
});
|
|
455
|
-
let response;
|
|
456
|
-
try {
|
|
457
|
-
response = await generationFetch(`${baseUrl}/responses`, {
|
|
458
|
-
method: "POST",
|
|
459
|
-
signal: request.signal ?? null,
|
|
460
|
-
headers: {
|
|
461
|
-
"content-type": "application/json",
|
|
462
|
-
accept: "application/json",
|
|
463
|
-
authorization: `Bearer ${auth.apiKey}`,
|
|
464
|
-
},
|
|
465
|
-
body,
|
|
466
|
-
verbose: process.env.CLAI_VERBOSE === "true",
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
catch (error) {
|
|
470
|
-
if (error instanceof Error && error.name === "AbortError")
|
|
471
|
-
throw error;
|
|
472
|
-
if (isOperationPolicyError(error))
|
|
473
|
-
throw error;
|
|
474
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
475
|
-
throw new ProviderError(`Meta Model API request could not be sent (${msg}). Check connectivity to ${baseUrl}.`);
|
|
476
|
-
}
|
|
477
|
-
let data;
|
|
478
|
-
try {
|
|
479
|
-
data = await readJson(response);
|
|
480
|
-
}
|
|
481
|
-
catch (error) {
|
|
482
|
-
if (error instanceof ProviderError) {
|
|
483
|
-
throw new ProviderError(`Meta Model API (model=${model}): ${error.message}`, error.status, error.body, error.retryAfterSeconds);
|
|
484
|
-
}
|
|
485
|
-
throw error;
|
|
486
|
-
}
|
|
487
|
-
const parsed = parseResponsesOutput(data);
|
|
488
|
-
const reasoningArtifacts = metaReasoningArtifacts(model, parsed.reasoningItems, parsed.reasoningItemPositions);
|
|
489
|
-
const usage = withReasoningObservation(parsed.usage ?? parseMetaUsage(data.usage), Boolean(parsed.reasoningSummary.trim()));
|
|
490
|
-
const responseStatus = data.status;
|
|
491
|
-
const incompleteDetails = data
|
|
492
|
-
.incomplete_details;
|
|
493
|
-
const outputBudgetIncomplete = responseStatus === "incomplete" &&
|
|
494
|
-
incompleteDetails?.reason === "max_output_tokens";
|
|
495
|
-
if (!outputBudgetIncomplete &&
|
|
496
|
-
!parsed.text.trim() &&
|
|
497
|
-
parsed.toolCalls.length === 0 &&
|
|
498
|
-
!parsed.reasoningSummary.trim()) {
|
|
499
|
-
throw new ProviderError(`Meta Model API returned no completion text (model=${model}). The response was empty — try /effort off, raise max_tokens, or pick another model with /model.`);
|
|
500
|
-
}
|
|
501
|
-
return {
|
|
502
|
-
text: parsed.text,
|
|
503
|
-
provider: "meta",
|
|
504
|
-
model,
|
|
505
|
-
...(parsed.toolCalls.length ? { toolCalls: parsed.toolCalls } : {}),
|
|
506
|
-
...(parsed.toolCalls.length
|
|
507
|
-
? { finishReason: "tool_calls" }
|
|
508
|
-
: outputBudgetIncomplete
|
|
509
|
-
? { finishReason: "length" }
|
|
510
|
-
: { finishReason: "stop" }),
|
|
511
|
-
...(usage ? { usage } : {}),
|
|
512
|
-
...(parsed.reasoningItems.length
|
|
513
|
-
? { reasoningBlock: { text: parsed.reasoningSummary, items: parsed.reasoningItems } }
|
|
514
|
-
: parsed.reasoningSummary
|
|
515
|
-
? { reasoningBlock: { text: parsed.reasoningSummary } }
|
|
516
|
-
: {}),
|
|
517
|
-
...(reasoningArtifacts ? { reasoningArtifacts } : {}),
|
|
518
|
-
};
|
|
519
|
-
});
|
|
90
|
+
}, () => responsesComplete(META_RESPONSES_CONFIG, request, auth, model));
|
|
520
91
|
},
|
|
521
92
|
async stream(request, auth, onToken) {
|
|
522
93
|
if (!auth.apiKey)
|
|
@@ -527,687 +98,7 @@ export const metaProvider = {
|
|
|
527
98
|
model,
|
|
528
99
|
mode: "stream",
|
|
529
100
|
reason: request.attemptReason ?? "initial",
|
|
530
|
-
},
|
|
531
|
-
const idleTimeoutMs = THINKING_STREAM_IDLE_TIMEOUT_MS;
|
|
532
|
-
const initialIdleTimeoutMs = THINKING_STREAM_INITIAL_IDLE_TIMEOUT_MS;
|
|
533
|
-
const outputIdleTimeoutMs = Math.round(Math.max(idleTimeoutMs, initialIdleTimeoutMs) * 1.5);
|
|
534
|
-
const idleController = new AbortController();
|
|
535
|
-
let transportTimer;
|
|
536
|
-
let outputTimer;
|
|
537
|
-
let idleFired = false;
|
|
538
|
-
let firedWatchdog;
|
|
539
|
-
let firedBudgetMs = initialIdleTimeoutMs;
|
|
540
|
-
let sawTransportActivity = false;
|
|
541
|
-
let sawStreamProgress = false;
|
|
542
|
-
const fireStall = (watchdog, budgetMs) => {
|
|
543
|
-
if (idleFired)
|
|
544
|
-
return;
|
|
545
|
-
idleFired = true;
|
|
546
|
-
firedWatchdog = watchdog;
|
|
547
|
-
firedBudgetMs = budgetMs;
|
|
548
|
-
idleController.abort();
|
|
549
|
-
};
|
|
550
|
-
const armTransportTimer = (budgetMs) => {
|
|
551
|
-
if (transportTimer)
|
|
552
|
-
clearTimeout(transportTimer);
|
|
553
|
-
transportTimer = setTimeout(() => fireStall("transport", budgetMs), budgetMs);
|
|
554
|
-
};
|
|
555
|
-
const noteTransportActivity = () => {
|
|
556
|
-
sawTransportActivity = true;
|
|
557
|
-
armTransportTimer(idleTimeoutMs);
|
|
558
|
-
};
|
|
559
|
-
const resetIdleTimer = () => {
|
|
560
|
-
sawStreamProgress = true;
|
|
561
|
-
noteTransportActivity();
|
|
562
|
-
if (outputTimer)
|
|
563
|
-
clearTimeout(outputTimer);
|
|
564
|
-
outputTimer = setTimeout(() => fireStall("output", outputIdleTimeoutMs), outputIdleTimeoutMs);
|
|
565
|
-
};
|
|
566
|
-
armTransportTimer(initialIdleTimeoutMs);
|
|
567
|
-
outputTimer = setTimeout(() => fireStall("output", outputIdleTimeoutMs), outputIdleTimeoutMs);
|
|
568
|
-
const clearIdleTimers = () => {
|
|
569
|
-
if (transportTimer)
|
|
570
|
-
clearTimeout(transportTimer);
|
|
571
|
-
if (outputTimer)
|
|
572
|
-
clearTimeout(outputTimer);
|
|
573
|
-
transportTimer = undefined;
|
|
574
|
-
outputTimer = undefined;
|
|
575
|
-
};
|
|
576
|
-
const onCallerAbort = () => idleController.abort(request.signal?.reason);
|
|
577
|
-
request.signal?.addEventListener("abort", onCallerAbort, { once: true });
|
|
578
|
-
const body = buildResponsesBody({
|
|
579
|
-
model,
|
|
580
|
-
messages: request.messages,
|
|
581
|
-
maxTokens: request.maxTokens,
|
|
582
|
-
temperature: request.temperature,
|
|
583
|
-
stream: true,
|
|
584
|
-
reasoning: request.thinking,
|
|
585
|
-
tools: request.tools,
|
|
586
|
-
parallelToolCalls: request.parallelToolCalls,
|
|
587
|
-
purpose: request.purpose,
|
|
588
|
-
reasoningArtifactReplayObserver: request.onReasoningArtifactReplayDecision,
|
|
589
|
-
});
|
|
590
|
-
let response;
|
|
591
|
-
let lastFetchError;
|
|
592
|
-
for (let fetchAttempt = 0; fetchAttempt < 2; fetchAttempt++) {
|
|
593
|
-
if (fetchAttempt > 0) {
|
|
594
|
-
await new Promise((r) => setTimeout(r, 1000));
|
|
595
|
-
if (request.signal?.aborted)
|
|
596
|
-
throw request.signal.reason;
|
|
597
|
-
if (idleFired)
|
|
598
|
-
break;
|
|
599
|
-
armTransportTimer(initialIdleTimeoutMs);
|
|
600
|
-
if (outputTimer) {
|
|
601
|
-
clearTimeout(outputTimer);
|
|
602
|
-
outputTimer = setTimeout(() => fireStall("output", outputIdleTimeoutMs), outputIdleTimeoutMs);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
try {
|
|
606
|
-
response = await generationFetch(`${baseUrl}/responses`, {
|
|
607
|
-
method: "POST",
|
|
608
|
-
signal: idleController.signal,
|
|
609
|
-
headers: {
|
|
610
|
-
"content-type": "application/json",
|
|
611
|
-
accept: "text/event-stream",
|
|
612
|
-
authorization: `Bearer ${auth.apiKey}`,
|
|
613
|
-
},
|
|
614
|
-
body,
|
|
615
|
-
verbose: process.env.CLAI_VERBOSE === "true",
|
|
616
|
-
});
|
|
617
|
-
lastFetchError = undefined;
|
|
618
|
-
break;
|
|
619
|
-
}
|
|
620
|
-
catch (error) {
|
|
621
|
-
lastFetchError = error;
|
|
622
|
-
if (idleFired) {
|
|
623
|
-
clearIdleTimers();
|
|
624
|
-
request.signal?.removeEventListener("abort", onCallerAbort);
|
|
625
|
-
throw new ProviderError(`Meta Model API request timed out before any response (${Math.round(firedBudgetMs / 1000)}s) — no data arrived on the connection.`);
|
|
626
|
-
}
|
|
627
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
628
|
-
const transient = /fetch failed|network error|etimedout|enotfound|econnreset|premature close|socket.*closed|aborted without reason/i.test(msg);
|
|
629
|
-
if (!transient || sawStreamProgress)
|
|
630
|
-
throw error;
|
|
631
|
-
continue;
|
|
632
|
-
}
|
|
633
|
-
}
|
|
634
|
-
if (!response) {
|
|
635
|
-
clearIdleTimers();
|
|
636
|
-
request.signal?.removeEventListener("abort", onCallerAbort);
|
|
637
|
-
if (lastFetchError)
|
|
638
|
-
throw lastFetchError;
|
|
639
|
-
throw new ProviderError(`Meta Model API request failed before a response was received.`);
|
|
640
|
-
}
|
|
641
|
-
if (!response.ok) {
|
|
642
|
-
clearIdleTimers();
|
|
643
|
-
request.signal?.removeEventListener("abort", onCallerAbort);
|
|
644
|
-
try {
|
|
645
|
-
await readJson(response);
|
|
646
|
-
}
|
|
647
|
-
catch (error) {
|
|
648
|
-
if (error instanceof ProviderError) {
|
|
649
|
-
throw new ProviderError(`Meta Model API (model=${model}): ${error.message}`, error.status, error.body, error.retryAfterSeconds);
|
|
650
|
-
}
|
|
651
|
-
throw error;
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
if (!response.body) {
|
|
655
|
-
clearIdleTimers();
|
|
656
|
-
request.signal?.removeEventListener("abort", onCallerAbort);
|
|
657
|
-
throw new ProviderError(`Meta Model API returned no stream body`);
|
|
658
|
-
}
|
|
659
|
-
const contentType = response.headers.get("content-type") ?? "";
|
|
660
|
-
if (response.status === 202 || /\bapplication\/json\b/i.test(contentType)) {
|
|
661
|
-
try {
|
|
662
|
-
const data = await readJson(response, idleController.signal);
|
|
663
|
-
if (response.status === 202) {
|
|
664
|
-
const requestId = data.requestId ?? data.id;
|
|
665
|
-
throw new ProviderError(`Meta Model API returned a pending async response${requestId ? ` (${requestId})` : ""}; streaming did not start.`, response.status, JSON.stringify(data).slice(0, 1_000));
|
|
666
|
-
}
|
|
667
|
-
const parsed = parseResponsesOutput(data);
|
|
668
|
-
const reasoningArtifacts = metaReasoningArtifacts(model, parsed.reasoningItems, parsed.reasoningItemPositions);
|
|
669
|
-
const usageTmp = parsed.usage ?? parseMetaUsage(data.usage);
|
|
670
|
-
const jsonStatus = data.status;
|
|
671
|
-
const jsonDetails = data
|
|
672
|
-
.incomplete_details;
|
|
673
|
-
const outputBudgetIncomplete = jsonStatus === "incomplete" &&
|
|
674
|
-
jsonDetails?.reason === "max_output_tokens";
|
|
675
|
-
if (outputBudgetIncomplete ||
|
|
676
|
-
parsed.text.trim() ||
|
|
677
|
-
parsed.toolCalls.length > 0 ||
|
|
678
|
-
parsed.reasoningSummary.trim()) {
|
|
679
|
-
emitStreamReasoningArtifacts(request.onStreamEvent, reasoningArtifacts);
|
|
680
|
-
if (parsed.reasoningSummary) {
|
|
681
|
-
emitStreamReasoningDelta(request.onStreamEvent, parsed.reasoningSummary);
|
|
682
|
-
}
|
|
683
|
-
if (parsed.text)
|
|
684
|
-
onToken(parsed.text);
|
|
685
|
-
return {
|
|
686
|
-
text: parsed.text,
|
|
687
|
-
provider: "meta",
|
|
688
|
-
model,
|
|
689
|
-
...(parsed.toolCalls.length ? { toolCalls: parsed.toolCalls } : {}),
|
|
690
|
-
...(parsed.toolCalls.length
|
|
691
|
-
? { finishReason: "tool_calls" }
|
|
692
|
-
: outputBudgetIncomplete
|
|
693
|
-
? { finishReason: "length" }
|
|
694
|
-
: { finishReason: "stop" }),
|
|
695
|
-
...(usageTmp ? { usage: usageTmp } : {}),
|
|
696
|
-
...(parsed.reasoningItems.length
|
|
697
|
-
? { reasoningBlock: { text: parsed.reasoningSummary, items: parsed.reasoningItems } }
|
|
698
|
-
: parsed.reasoningSummary
|
|
699
|
-
? { reasoningBlock: { text: parsed.reasoningSummary } }
|
|
700
|
-
: {}),
|
|
701
|
-
...(reasoningArtifacts ? { reasoningArtifacts } : {}),
|
|
702
|
-
};
|
|
703
|
-
}
|
|
704
|
-
throw new ProviderError(`Meta Model API returned JSON instead of an SSE stream, but no completion text was present.`, response.status, JSON.stringify(data).slice(0, 1_000));
|
|
705
|
-
}
|
|
706
|
-
catch (error) {
|
|
707
|
-
if (idleFired) {
|
|
708
|
-
const seconds = Math.round(firedBudgetMs / 1000);
|
|
709
|
-
if (firedWatchdog === "transport" || !sawTransportActivity) {
|
|
710
|
-
if (!sawTransportActivity) {
|
|
711
|
-
throw new ProviderError(`Meta Model API request timed out before any response (${seconds}s) — no data arrived on the connection.`);
|
|
712
|
-
}
|
|
713
|
-
throw new ProviderError(`Meta Model API stream transport timeout (${seconds}s) — no data arrived on the connection after it had started.`);
|
|
714
|
-
}
|
|
715
|
-
throw new ProviderError(`Meta Model API stream stalled — ${STREAM_STALL_MARKER} for ${seconds}s`);
|
|
716
|
-
}
|
|
717
|
-
throw error;
|
|
718
|
-
}
|
|
719
|
-
finally {
|
|
720
|
-
clearIdleTimers();
|
|
721
|
-
request.signal?.removeEventListener("abort", onCallerAbort);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
const decoder = new TextDecoder();
|
|
725
|
-
const reader = response.body.getReader();
|
|
726
|
-
let buffer = "";
|
|
727
|
-
let full = "";
|
|
728
|
-
let visible = "";
|
|
729
|
-
let reasoningSeen = "";
|
|
730
|
-
let finishReason;
|
|
731
|
-
let sawTerminalProof;
|
|
732
|
-
let streamUsage;
|
|
733
|
-
const toolCallState = new Map();
|
|
734
|
-
const outputIndexToItemId = new Map();
|
|
735
|
-
const outputIndexToToolCallIndex = new Map();
|
|
736
|
-
let responseId;
|
|
737
|
-
const reasoningItems = [];
|
|
738
|
-
const reasoningItemSequences = [];
|
|
739
|
-
const reasoningItemToolCallIndices = [];
|
|
740
|
-
const reasoningItemIndexes = new Map();
|
|
741
|
-
const noteReasoningItem = (item, sequence, toolCallIndex) => {
|
|
742
|
-
const encrypted = typeof item.encrypted_content === "string" ? item.encrypted_content : "";
|
|
743
|
-
if (!encrypted)
|
|
744
|
-
return;
|
|
745
|
-
const id = typeof item.id === "string" ? item.id : undefined;
|
|
746
|
-
const key = id ?? encrypted.slice(0, 64);
|
|
747
|
-
const existingIndex = reasoningItemIndexes.get(key);
|
|
748
|
-
if (existingIndex !== undefined) {
|
|
749
|
-
reasoningItems[existingIndex] = { ...item };
|
|
750
|
-
if (sequence !== undefined)
|
|
751
|
-
reasoningItemSequences[existingIndex] = sequence;
|
|
752
|
-
if (toolCallIndex !== undefined) {
|
|
753
|
-
reasoningItemToolCallIndices[existingIndex] = toolCallIndex;
|
|
754
|
-
}
|
|
755
|
-
return;
|
|
756
|
-
}
|
|
757
|
-
reasoningItemIndexes.set(key, reasoningItems.length);
|
|
758
|
-
reasoningItems.push({ ...item });
|
|
759
|
-
reasoningItemSequences.push(sequence ?? Number.MAX_SAFE_INTEGER);
|
|
760
|
-
reasoningItemToolCallIndices.push(toolCallIndex);
|
|
761
|
-
};
|
|
762
|
-
const reasoningReplay = () => {
|
|
763
|
-
if (!reasoningItems.length) {
|
|
764
|
-
return reasoningSeen ? { reasoningBlock: { text: reasoningSeen } } : {};
|
|
765
|
-
}
|
|
766
|
-
const toolCallSequences = [...outputIndexToToolCallIndex.entries()]
|
|
767
|
-
.map(([sequence, toolCallIndex]) => ({ sequence, toolCallIndex }))
|
|
768
|
-
.sort((left, right) => left.sequence - right.sequence);
|
|
769
|
-
const positions = reasoningItemSequences.map((sequence, index) => {
|
|
770
|
-
const storedToolCallIndex = reasoningItemToolCallIndices[index];
|
|
771
|
-
if (storedToolCallIndex !== undefined) {
|
|
772
|
-
return { sequence, toolCallIndex: storedToolCallIndex };
|
|
773
|
-
}
|
|
774
|
-
const followingTool = toolCallSequences.find((toolCall) => toolCall.sequence > sequence);
|
|
775
|
-
return followingTool
|
|
776
|
-
? { sequence, toolCallIndex: followingTool.toolCallIndex }
|
|
777
|
-
: { sequence };
|
|
778
|
-
});
|
|
779
|
-
const reasoningArtifacts = metaReasoningArtifacts(model, reasoningItems, positions);
|
|
780
|
-
emitStreamReasoningArtifacts(request.onStreamEvent, reasoningArtifacts);
|
|
781
|
-
return {
|
|
782
|
-
reasoningBlock: { text: reasoningSeen, items: reasoningItems },
|
|
783
|
-
...(reasoningArtifacts ? { reasoningArtifacts } : {}),
|
|
784
|
-
};
|
|
785
|
-
};
|
|
786
|
-
const usageResult = () => {
|
|
787
|
-
const usage = withReasoningObservation(streamUsage, Boolean(reasoningSeen.trim()));
|
|
788
|
-
return usage ? { usage } : {};
|
|
789
|
-
};
|
|
790
|
-
const emitVisible = (text) => {
|
|
791
|
-
if (!text)
|
|
792
|
-
return;
|
|
793
|
-
visible += text;
|
|
794
|
-
full += text;
|
|
795
|
-
onToken(text);
|
|
796
|
-
};
|
|
797
|
-
const emitReasoningDelta = (text) => {
|
|
798
|
-
if (!text)
|
|
799
|
-
return;
|
|
800
|
-
reasoningSeen += text;
|
|
801
|
-
emitStreamReasoningDelta(request.onStreamEvent, text);
|
|
802
|
-
};
|
|
803
|
-
const cleanup = () => {
|
|
804
|
-
clearIdleTimers();
|
|
805
|
-
request.signal?.removeEventListener("abort", onCallerAbort);
|
|
806
|
-
idleController.signal.removeEventListener("abort", cancelReaderOnAbort);
|
|
807
|
-
};
|
|
808
|
-
const cancelReaderOnAbort = () => {
|
|
809
|
-
reader.cancel().catch(() => undefined);
|
|
810
|
-
};
|
|
811
|
-
idleController.signal.addEventListener("abort", cancelReaderOnAbort, { once: true });
|
|
812
|
-
const sseFrames = createSseFrameAssembler();
|
|
813
|
-
try {
|
|
814
|
-
while (true) {
|
|
815
|
-
request.signal?.throwIfAborted();
|
|
816
|
-
if (idleController.signal.aborted)
|
|
817
|
-
throw new Error("Stream aborted");
|
|
818
|
-
const { done, value } = await readWithAbort(reader, idleController.signal);
|
|
819
|
-
request.signal?.throwIfAborted();
|
|
820
|
-
if (idleController.signal.aborted)
|
|
821
|
-
throw new Error("Stream aborted");
|
|
822
|
-
if (done)
|
|
823
|
-
break;
|
|
824
|
-
if (value && value.byteLength > 0)
|
|
825
|
-
noteTransportActivity();
|
|
826
|
-
buffer += decoder.decode(value, { stream: true });
|
|
827
|
-
const lines = buffer.split("\n");
|
|
828
|
-
buffer = lines.pop() ?? "";
|
|
829
|
-
for (const line of lines) {
|
|
830
|
-
const payload = sseFrames.pushLine(line);
|
|
831
|
-
if (payload === undefined)
|
|
832
|
-
continue;
|
|
833
|
-
if (payload === "[DONE]") {
|
|
834
|
-
if (!reasoningSeen.trim() && streamUsage?.reasoningTokens && streamUsage.reasoningTokens > 0 && (visible.trim() || toolCallState.size > 0)) {
|
|
835
|
-
const effort = metaReasoningPayload(request.thinking)?.effort;
|
|
836
|
-
const effortText = effort ? ` at ${effort} effort` : "";
|
|
837
|
-
const note = `Reasoning is private on Meta Model API: the model reasoned${effortText} and used ${streamUsage.reasoningTokens.toLocaleString("en-US")} reasoning tokens, but the API returns no reasoning text to display.`;
|
|
838
|
-
emitReasoningDelta(note);
|
|
839
|
-
}
|
|
840
|
-
cleanup();
|
|
841
|
-
const toolCalls = [];
|
|
842
|
-
for (const [, state] of toolCallState) {
|
|
843
|
-
if (!state.name)
|
|
844
|
-
continue;
|
|
845
|
-
const canonical = state.name ? fromWireName(state.name) ?? state.name : state.name ?? "";
|
|
846
|
-
const raw = state.arguments;
|
|
847
|
-
let args;
|
|
848
|
-
try {
|
|
849
|
-
const parsed = JSON.parse(raw);
|
|
850
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
851
|
-
args = parsed;
|
|
852
|
-
else
|
|
853
|
-
args = {};
|
|
854
|
-
}
|
|
855
|
-
catch {
|
|
856
|
-
args = parseToolArguments(raw);
|
|
857
|
-
}
|
|
858
|
-
toolCalls.push({ id: state.callId ?? state.id ?? `call_${toolCalls.length}`, name: canonical, args, rawArguments: raw });
|
|
859
|
-
}
|
|
860
|
-
if (!visible.trim() && toolCalls.length === 0) {
|
|
861
|
-
if (reasoningSeen.trim() || finishReason === "length") {
|
|
862
|
-
return { text: full, provider: "meta", model, finishReason: finishReason ?? "stop", ...usageResult(), ...reasoningReplay() };
|
|
863
|
-
}
|
|
864
|
-
throw new ProviderError(`Meta Model API completed without a visible answer.`);
|
|
865
|
-
}
|
|
866
|
-
return {
|
|
867
|
-
text: full,
|
|
868
|
-
provider: "meta",
|
|
869
|
-
model,
|
|
870
|
-
...(toolCalls.length ? { toolCalls } : {}),
|
|
871
|
-
...(finishReason ? { finishReason } : toolCalls.length ? { finishReason: "tool_calls" } : {}),
|
|
872
|
-
...usageResult(),
|
|
873
|
-
...reasoningReplay(),
|
|
874
|
-
};
|
|
875
|
-
}
|
|
876
|
-
let parsed;
|
|
877
|
-
try {
|
|
878
|
-
parsed = JSON.parse(payload);
|
|
879
|
-
}
|
|
880
|
-
catch {
|
|
881
|
-
continue;
|
|
882
|
-
}
|
|
883
|
-
if (parsed.error) {
|
|
884
|
-
const rawDetail = typeof parsed.error === "string"
|
|
885
|
-
? parsed.error
|
|
886
|
-
: parsed.error.message ?? parsed.error.type ?? "unknown error";
|
|
887
|
-
const detail = rawDetail.trim().length <= 2 ? `${rawDetail} — ${payload.slice(0, 300)}` : rawDetail;
|
|
888
|
-
throw new ProviderError(`Meta Model API stream error: ${detail}`, undefined, payload.slice(0, 1000));
|
|
889
|
-
}
|
|
890
|
-
const type = parsed.type;
|
|
891
|
-
if (type === "response.created" || type === "response.in_progress") {
|
|
892
|
-
const resp = (parsed.response ?? parsed);
|
|
893
|
-
if (typeof resp.id === "string")
|
|
894
|
-
responseId = resp.id;
|
|
895
|
-
continue;
|
|
896
|
-
}
|
|
897
|
-
if (type === "response.output_item.added") {
|
|
898
|
-
const item = parsed.item;
|
|
899
|
-
if (!item)
|
|
900
|
-
continue;
|
|
901
|
-
const outputIndex = typeof parsed.output_index === "number" ? parsed.output_index : undefined;
|
|
902
|
-
const itemId = typeof item.id === "string" ? item.id : typeof parsed.item_id === "string" ? parsed.item_id : undefined;
|
|
903
|
-
if (outputIndex !== undefined && itemId)
|
|
904
|
-
outputIndexToItemId.set(outputIndex, itemId);
|
|
905
|
-
if (item.type === "function_call") {
|
|
906
|
-
const id = typeof item.id === "string" ? item.id : typeof item.call_id === "string" ? item.call_id : itemId ?? `call_${toolCallState.size}`;
|
|
907
|
-
const callId = typeof item.call_id === "string" ? item.call_id : id;
|
|
908
|
-
const name = typeof item.name === "string" ? item.name : "";
|
|
909
|
-
const args = typeof item.arguments === "string" ? item.arguments : "";
|
|
910
|
-
const toolCallIndex = toolCallState.size;
|
|
911
|
-
toolCallState.set(id, { id, callId, name, arguments: args });
|
|
912
|
-
if (outputIndex !== undefined) {
|
|
913
|
-
outputIndexToToolCallIndex.set(outputIndex, toolCallIndex);
|
|
914
|
-
}
|
|
915
|
-
resetIdleTimer();
|
|
916
|
-
if (request.onToolCallDelta) {
|
|
917
|
-
const canonical = name ? fromWireName(name) ?? name : undefined;
|
|
918
|
-
request.onToolCallDelta({ index: toolCallState.size - 1, ...(callId ? { id: callId } : {}), ...(canonical ? { name: canonical } : {}), argumentsBytes: args.length });
|
|
919
|
-
}
|
|
920
|
-
}
|
|
921
|
-
else if (item.type === "reasoning") {
|
|
922
|
-
noteReasoningItem(item, outputIndex);
|
|
923
|
-
const s = extractReasoningSummary(item);
|
|
924
|
-
if (s) {
|
|
925
|
-
resetIdleTimer();
|
|
926
|
-
emitReasoningDelta(s);
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
else if (item.type === "message") {
|
|
930
|
-
resetIdleTimer();
|
|
931
|
-
}
|
|
932
|
-
continue;
|
|
933
|
-
}
|
|
934
|
-
if (type === "response.output_item.done") {
|
|
935
|
-
const item = parsed.item;
|
|
936
|
-
if (item?.type === "reasoning") {
|
|
937
|
-
noteReasoningItem(item, typeof parsed.output_index === "number"
|
|
938
|
-
? parsed.output_index
|
|
939
|
-
: undefined);
|
|
940
|
-
}
|
|
941
|
-
if (item?.type === "function_call") {
|
|
942
|
-
const id = typeof item.id === "string" ? item.id : typeof parsed.item_id === "string" ? parsed.item_id : undefined;
|
|
943
|
-
if (id && toolCallState.has(id)) {
|
|
944
|
-
const state = toolCallState.get(id);
|
|
945
|
-
if (typeof item.arguments === "string" && item.arguments.length > state.arguments.length)
|
|
946
|
-
state.arguments = item.arguments;
|
|
947
|
-
if (typeof item.name === "string" && !state.name)
|
|
948
|
-
state.name = item.name;
|
|
949
|
-
if (typeof item.call_id === "string" && !state.callId)
|
|
950
|
-
state.callId = item.call_id;
|
|
951
|
-
}
|
|
952
|
-
resetIdleTimer();
|
|
953
|
-
}
|
|
954
|
-
if (item && typeof item.status === "string")
|
|
955
|
-
finishReason = item.status;
|
|
956
|
-
continue;
|
|
957
|
-
}
|
|
958
|
-
if (type === "response.content_part.added" || type === "response.content_part.done") {
|
|
959
|
-
continue;
|
|
960
|
-
}
|
|
961
|
-
if (type === "response.output_text.delta") {
|
|
962
|
-
const delta = typeof parsed.delta === "string" ? parsed.delta : "";
|
|
963
|
-
if (delta) {
|
|
964
|
-
resetIdleTimer();
|
|
965
|
-
emitVisible(delta);
|
|
966
|
-
}
|
|
967
|
-
continue;
|
|
968
|
-
}
|
|
969
|
-
if (type === "response.reasoning_summary_text.delta") {
|
|
970
|
-
const delta = typeof parsed.delta === "string" ? parsed.delta : "";
|
|
971
|
-
if (delta) {
|
|
972
|
-
resetIdleTimer();
|
|
973
|
-
emitReasoningDelta(delta);
|
|
974
|
-
}
|
|
975
|
-
continue;
|
|
976
|
-
}
|
|
977
|
-
if (type === "response.reasoning_summary_text.done") {
|
|
978
|
-
const textVal = typeof parsed.text === "string" ? parsed.text : "";
|
|
979
|
-
if (textVal && !reasoningSeen.includes(textVal)) {
|
|
980
|
-
const remaining = textVal.slice(reasoningSeen.length);
|
|
981
|
-
if (remaining) {
|
|
982
|
-
resetIdleTimer();
|
|
983
|
-
emitReasoningDelta(remaining);
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
continue;
|
|
987
|
-
}
|
|
988
|
-
if (type === "response.function_call_arguments.delta") {
|
|
989
|
-
const delta = typeof parsed.delta === "string" ? parsed.delta : "";
|
|
990
|
-
const itemId = typeof parsed.item_id === "string" ? parsed.item_id : typeof parsed.itemId === "string" ? parsed.itemId : undefined;
|
|
991
|
-
let targetId = itemId;
|
|
992
|
-
if (!targetId && typeof parsed.output_index === "number")
|
|
993
|
-
targetId = outputIndexToItemId.get(parsed.output_index);
|
|
994
|
-
if (targetId) {
|
|
995
|
-
const state = toolCallState.get(targetId);
|
|
996
|
-
if (state) {
|
|
997
|
-
state.arguments += delta;
|
|
998
|
-
resetIdleTimer();
|
|
999
|
-
if (request.onToolCallDelta) {
|
|
1000
|
-
const canonical = state.name ? fromWireName(state.name) ?? state.name : undefined;
|
|
1001
|
-
request.onToolCallDelta({ index: Array.from(toolCallState.keys()).indexOf(targetId), ...(state.callId ? { id: state.callId } : {}), ...(canonical ? { name: canonical } : {}), argumentsBytes: state.arguments.length });
|
|
1002
|
-
}
|
|
1003
|
-
}
|
|
1004
|
-
else {
|
|
1005
|
-
toolCallState.set(targetId, { id: targetId, callId: targetId, name: "", arguments: delta });
|
|
1006
|
-
resetIdleTimer();
|
|
1007
|
-
}
|
|
1008
|
-
}
|
|
1009
|
-
else if (delta) {
|
|
1010
|
-
const anyKey = Array.from(toolCallState.keys()).pop();
|
|
1011
|
-
if (anyKey) {
|
|
1012
|
-
const state = toolCallState.get(anyKey);
|
|
1013
|
-
state.arguments += delta;
|
|
1014
|
-
resetIdleTimer();
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
continue;
|
|
1018
|
-
}
|
|
1019
|
-
if (type === "response.function_call_arguments.done") {
|
|
1020
|
-
const args = typeof parsed.arguments === "string" ? parsed.arguments : typeof parsed.argument === "string" ? parsed.argument : "";
|
|
1021
|
-
const itemId = typeof parsed.item_id === "string" ? parsed.item_id : undefined;
|
|
1022
|
-
let targetId = itemId;
|
|
1023
|
-
if (!targetId && typeof parsed.output_index === "number")
|
|
1024
|
-
targetId = outputIndexToItemId.get(parsed.output_index);
|
|
1025
|
-
if (targetId && toolCallState.has(targetId) && args) {
|
|
1026
|
-
toolCallState.get(targetId).arguments = args;
|
|
1027
|
-
}
|
|
1028
|
-
else if (args && toolCallState.size > 0) {
|
|
1029
|
-
const lastKey = Array.from(toolCallState.keys()).pop();
|
|
1030
|
-
if (!toolCallState.get(lastKey).arguments)
|
|
1031
|
-
toolCallState.get(lastKey).arguments = args;
|
|
1032
|
-
}
|
|
1033
|
-
resetIdleTimer();
|
|
1034
|
-
continue;
|
|
1035
|
-
}
|
|
1036
|
-
if (type === "response.completed") {
|
|
1037
|
-
sawTerminalProof = "response-completed";
|
|
1038
|
-
const resp = (parsed.response ?? parsed);
|
|
1039
|
-
if (resp.usage) {
|
|
1040
|
-
const u = parseMetaUsage(resp.usage);
|
|
1041
|
-
if (u)
|
|
1042
|
-
streamUsage = u;
|
|
1043
|
-
}
|
|
1044
|
-
if (typeof resp.status === "string")
|
|
1045
|
-
finishReason = resp.status;
|
|
1046
|
-
if (Array.isArray(resp.output)) {
|
|
1047
|
-
const out = parseResponsesOutput(resp);
|
|
1048
|
-
for (const [index, item] of out.reasoningItems.entries()) {
|
|
1049
|
-
const position = out.reasoningItemPositions[index];
|
|
1050
|
-
noteReasoningItem(item, position?.sequence, position?.toolCallIndex);
|
|
1051
|
-
}
|
|
1052
|
-
if (out.reasoningSummary && !reasoningSeen.trim()) {
|
|
1053
|
-
emitReasoningDelta(out.reasoningSummary);
|
|
1054
|
-
}
|
|
1055
|
-
if (out.text && !visible.trim()) {
|
|
1056
|
-
emitVisible(out.text);
|
|
1057
|
-
}
|
|
1058
|
-
for (const tc of out.toolCalls) {
|
|
1059
|
-
const exists = Array.from(toolCallState.values()).some((s) => s.callId === tc.id);
|
|
1060
|
-
if (!exists) {
|
|
1061
|
-
const id = tc.id;
|
|
1062
|
-
toolCallState.set(id, { id, callId: tc.id, name: toWireName(tc.name), arguments: tc.rawArguments ?? JSON.stringify(tc.args) });
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
}
|
|
1066
|
-
continue;
|
|
1067
|
-
}
|
|
1068
|
-
if (type === "response.failed" || type === "response.incomplete") {
|
|
1069
|
-
const resp = (parsed.response ?? parsed);
|
|
1070
|
-
if (type === "response.incomplete") {
|
|
1071
|
-
const details = resp.incomplete_details;
|
|
1072
|
-
const reason = typeof details?.reason === "string" ? details.reason : "";
|
|
1073
|
-
if (resp.usage) {
|
|
1074
|
-
const u = parseMetaUsage(resp.usage);
|
|
1075
|
-
if (u)
|
|
1076
|
-
streamUsage = u;
|
|
1077
|
-
}
|
|
1078
|
-
if (Array.isArray(resp.output)) {
|
|
1079
|
-
const out = parseResponsesOutput(resp);
|
|
1080
|
-
for (const [index, item] of out.reasoningItems.entries()) {
|
|
1081
|
-
const position = out.reasoningItemPositions[index];
|
|
1082
|
-
noteReasoningItem(item, position?.sequence, position?.toolCallIndex);
|
|
1083
|
-
}
|
|
1084
|
-
if (out.reasoningSummary && !reasoningSeen.trim()) {
|
|
1085
|
-
emitReasoningDelta(out.reasoningSummary);
|
|
1086
|
-
}
|
|
1087
|
-
if (out.text && !visible.trim())
|
|
1088
|
-
emitVisible(out.text);
|
|
1089
|
-
for (const tc of out.toolCalls) {
|
|
1090
|
-
const exists = Array.from(toolCallState.values()).some((state) => state.callId === tc.id);
|
|
1091
|
-
if (!exists) {
|
|
1092
|
-
toolCallState.set(tc.id, {
|
|
1093
|
-
id: tc.id,
|
|
1094
|
-
callId: tc.id,
|
|
1095
|
-
name: toWireName(tc.name),
|
|
1096
|
-
arguments: tc.rawArguments ?? JSON.stringify(tc.args),
|
|
1097
|
-
});
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
finishReason =
|
|
1102
|
-
reason === "max_output_tokens" ? "length" : "incomplete";
|
|
1103
|
-
sawTerminalProof = "response-incomplete";
|
|
1104
|
-
continue;
|
|
1105
|
-
}
|
|
1106
|
-
const err = resp.error;
|
|
1107
|
-
const rawDetail = err?.message ?? err?.code ?? type;
|
|
1108
|
-
const rawStr = String(rawDetail);
|
|
1109
|
-
const detail = rawStr.trim().length <= 2 ? `${rawStr} — ${payload.slice(0, 300)}` : rawStr;
|
|
1110
|
-
throw new ProviderError(`Meta Model API stream error: ${detail}`, undefined, payload.slice(0, 1000));
|
|
1111
|
-
}
|
|
1112
|
-
const usageField = parsed.usage;
|
|
1113
|
-
if (usageField) {
|
|
1114
|
-
const u = parseMetaUsage(usageField);
|
|
1115
|
-
if (u) {
|
|
1116
|
-
streamUsage = u;
|
|
1117
|
-
resetIdleTimer();
|
|
1118
|
-
}
|
|
1119
|
-
}
|
|
1120
|
-
const choice = parsed.choices;
|
|
1121
|
-
if (choice) {
|
|
1122
|
-
const chunkUsage = parseMetaUsage(parsed.usage);
|
|
1123
|
-
if (chunkUsage)
|
|
1124
|
-
streamUsage = chunkUsage;
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
if (!reasoningSeen.trim() && streamUsage?.reasoningTokens && streamUsage.reasoningTokens > 0 && (visible.trim() || toolCallState.size > 0)) {
|
|
1129
|
-
const effort = metaReasoningPayload(request.thinking)?.effort;
|
|
1130
|
-
const effortText = effort ? ` at ${effort} effort` : "";
|
|
1131
|
-
const note = `Reasoning is private on Meta Model API: the model reasoned${effortText} and used ${streamUsage.reasoningTokens.toLocaleString("en-US")} reasoning tokens, but the API returns no reasoning text to display.`;
|
|
1132
|
-
reasoningSeen += note;
|
|
1133
|
-
emitStreamReasoningDelta(request.onStreamEvent, note);
|
|
1134
|
-
}
|
|
1135
|
-
cleanup();
|
|
1136
|
-
let metaToolArgumentBytes = 0;
|
|
1137
|
-
for (const state of toolCallState.values()) {
|
|
1138
|
-
metaToolArgumentBytes += state.arguments.length;
|
|
1139
|
-
}
|
|
1140
|
-
requireTerminalProof({
|
|
1141
|
-
provider: "Meta Model API",
|
|
1142
|
-
policy: META_STREAM_TERMINAL,
|
|
1143
|
-
signal: sawTerminalProof,
|
|
1144
|
-
answerBytes: full.length,
|
|
1145
|
-
reasoningBytes: reasoningSeen.length,
|
|
1146
|
-
toolArgumentBytes: metaToolArgumentBytes,
|
|
1147
|
-
});
|
|
1148
|
-
const toolCalls = [];
|
|
1149
|
-
for (const [, state] of toolCallState) {
|
|
1150
|
-
if (!state.name && !state.arguments)
|
|
1151
|
-
continue;
|
|
1152
|
-
const name = state.name || "";
|
|
1153
|
-
const canonical = name ? fromWireName(name) ?? name : "";
|
|
1154
|
-
if (!canonical)
|
|
1155
|
-
continue;
|
|
1156
|
-
const raw = state.arguments;
|
|
1157
|
-
let args;
|
|
1158
|
-
try {
|
|
1159
|
-
const parsed = JSON.parse(raw || "{}");
|
|
1160
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
1161
|
-
args = parsed;
|
|
1162
|
-
else
|
|
1163
|
-
args = {};
|
|
1164
|
-
}
|
|
1165
|
-
catch {
|
|
1166
|
-
args = parseToolArguments(raw);
|
|
1167
|
-
}
|
|
1168
|
-
toolCalls.push({ id: state.callId ?? state.id ?? `call_${toolCalls.length}`, name: canonical, args, rawArguments: raw });
|
|
1169
|
-
}
|
|
1170
|
-
if (!visible.trim() && toolCalls.length === 0) {
|
|
1171
|
-
if (reasoningSeen.trim() || finishReason === "length") {
|
|
1172
|
-
return { text: full, provider: "meta", model, finishReason: finishReason ?? "stop", ...usageResult(), ...reasoningReplay() };
|
|
1173
|
-
}
|
|
1174
|
-
throw new ProviderError(`Meta Model API completed without a visible answer.`);
|
|
1175
|
-
}
|
|
1176
|
-
return {
|
|
1177
|
-
text: full,
|
|
1178
|
-
provider: "meta",
|
|
1179
|
-
model,
|
|
1180
|
-
...(toolCalls.length ? { toolCalls } : {}),
|
|
1181
|
-
...(finishReason ? { finishReason } : toolCalls.length ? { finishReason: "tool_calls" } : {}),
|
|
1182
|
-
...usageResult(),
|
|
1183
|
-
...reasoningReplay(),
|
|
1184
|
-
};
|
|
1185
|
-
}
|
|
1186
|
-
catch (error) {
|
|
1187
|
-
if (idleFired) {
|
|
1188
|
-
const seconds = Math.round(firedBudgetMs / 1000);
|
|
1189
|
-
if (firedWatchdog === "transport" || !sawTransportActivity) {
|
|
1190
|
-
if (!sawTransportActivity) {
|
|
1191
|
-
throw new ProviderError(`Meta Model API request timed out before any response (${seconds}s) — no data arrived on the connection.`);
|
|
1192
|
-
}
|
|
1193
|
-
throw new ProviderError(`Meta Model API stream transport timeout (${seconds}s) — no data arrived on the connection after it had started.`);
|
|
1194
|
-
}
|
|
1195
|
-
throw new ProviderError(`Meta Model API stream stalled — ${STREAM_STALL_MARKER} for ${seconds}s` +
|
|
1196
|
-
(sawStreamProgress
|
|
1197
|
-
? " after it had already started producing output. The connection stayed open, so the model was most likely buffering one very large tool call. Split large writes into smaller sequential calls, or try a smaller model / disable thinking with /effort off."
|
|
1198
|
-
: " — the connection stayed open but the model never produced anything. Try another model, or disable thinking with /effort off."));
|
|
1199
|
-
}
|
|
1200
|
-
throw error;
|
|
1201
|
-
}
|
|
1202
|
-
finally {
|
|
1203
|
-
cleanup();
|
|
1204
|
-
void reader.cancel().catch(() => undefined);
|
|
1205
|
-
try {
|
|
1206
|
-
reader.releaseLock();
|
|
1207
|
-
}
|
|
1208
|
-
catch { }
|
|
1209
|
-
}
|
|
1210
|
-
});
|
|
101
|
+
}, () => responsesStream(META_RESPONSES_CONFIG, request, auth, onToken, model));
|
|
1211
102
|
},
|
|
1212
103
|
};
|
|
1213
104
|
//# sourceMappingURL=meta.js.map
|