vidspotai-shared 1.0.84 → 1.0.86
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/lib/globals/aiModels/providers/runway.d.ts.map +1 -1
- package/lib/globals/aiModels/providers/runway.js +12 -7
- package/lib/globals/types.d.ts +10 -0
- package/lib/globals/types.d.ts.map +1 -1
- package/lib/globals/types.js +11 -0
- package/lib/models/agent.model.d.ts +129 -1
- package/lib/models/agent.model.d.ts.map +1 -1
- package/lib/schemas/agentRunJob.schema.d.ts +21 -0
- package/lib/schemas/agentRunJob.schema.d.ts.map +1 -1
- package/lib/schemas/agentRunJob.schema.js +35 -3
- package/lib/services/agent/executor/core.d.ts.map +1 -1
- package/lib/services/agent/executor/core.js +21 -1
- package/lib/services/agent/executor/types.d.ts +10 -0
- package/lib/services/agent/executor/types.d.ts.map +1 -1
- package/lib/services/agent/index.d.ts +3 -0
- package/lib/services/agent/index.d.ts.map +1 -1
- package/lib/services/agent/index.js +3 -0
- package/lib/services/agent/providerFallback/chains.d.ts +2 -0
- package/lib/services/agent/providerFallback/chains.d.ts.map +1 -1
- package/lib/services/agent/providerFallback/chains.js +1 -0
- package/lib/services/agent/recovery/degradeLadder.d.ts +74 -0
- package/lib/services/agent/recovery/degradeLadder.d.ts.map +1 -0
- package/lib/services/agent/recovery/degradeLadder.js +133 -0
- package/lib/services/agent/repair/engine.d.ts +38 -0
- package/lib/services/agent/repair/engine.d.ts.map +1 -0
- package/lib/services/agent/repair/engine.js +175 -0
- package/lib/services/agent/repair/index.d.ts +20 -0
- package/lib/services/agent/repair/index.d.ts.map +1 -0
- package/lib/services/agent/repair/index.js +49 -0
- package/lib/services/agent/repair/strategies/llmRepair.strategy.d.ts +6 -0
- package/lib/services/agent/repair/strategies/llmRepair.strategy.d.ts.map +1 -0
- package/lib/services/agent/repair/strategies/llmRepair.strategy.js +210 -0
- package/lib/services/agent/repair/strategies/paramRepair.strategy.d.ts +3 -0
- package/lib/services/agent/repair/strategies/paramRepair.strategy.d.ts.map +1 -0
- package/lib/services/agent/repair/strategies/paramRepair.strategy.js +151 -0
- package/lib/services/agent/repair/types.d.ts +92 -0
- package/lib/services/agent/repair/types.d.ts.map +1 -0
- package/lib/services/agent/repair/types.js +2 -0
- package/lib/services/agent/runPlanning.d.ts +96 -0
- package/lib/services/agent/runPlanning.d.ts.map +1 -0
- package/lib/services/agent/runPlanning.js +233 -0
- package/lib/services/aiGen/providers/runway/types.d.ts +14 -0
- package/lib/services/aiGen/providers/runway/types.d.ts.map +1 -1
- package/lib/services/aiGen/providers/runway/types.js +22 -1
- package/lib/services/firestore.service.d.ts +7 -1
- package/lib/services/firestore.service.d.ts.map +1 -1
- package/lib/services/firestore.service.js +8 -0
- package/package.json +1 -1
- package/lib/services/agent/executor.d.ts +0 -141
- package/lib/services/agent/executor.d.ts.map +0 -1
- package/lib/services/agent/executor.js +0 -561
- package/lib/services/agent/llmCallerGateway.d.ts +0 -61
- package/lib/services/agent/llmCallerGateway.d.ts.map +0 -1
- package/lib/services/agent/llmCallerGateway.js +0 -368
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GatewayLlmCaller = void 0;
|
|
4
|
-
const zod_1 = require("zod");
|
|
5
|
-
/**
|
|
6
|
-
* Marks a transient error that should trigger HTTP retry (and, when exhausted,
|
|
7
|
-
* model fallback). Non-transient errors (4xx other than 408/429, schema
|
|
8
|
-
* validation, malformed JSON) are NOT wrapped and propagate immediately.
|
|
9
|
-
*/
|
|
10
|
-
class TransientLlmError extends Error {
|
|
11
|
-
constructor(message, cause) {
|
|
12
|
-
super(message);
|
|
13
|
-
this.cause = cause;
|
|
14
|
-
this.name = "TransientLlmError";
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
const TRANSIENT_HTTP_STATUSES = new Set([408, 425, 429, 500, 502, 503, 504]);
|
|
18
|
-
function isTransientNetworkError(err) {
|
|
19
|
-
if (!err || typeof err !== "object")
|
|
20
|
-
return false;
|
|
21
|
-
const e = err;
|
|
22
|
-
const code = e.code ?? e.cause?.code;
|
|
23
|
-
if (code && /^(ECONNRESET|ECONNREFUSED|ETIMEDOUT|EAI_AGAIN|EPIPE|UND_ERR_.*)$/.test(code)) {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
// Our own per-request timeout (ctrl.abort() in postOnce / structuredStream)
|
|
27
|
-
// surfaces as AbortError "This operation was aborted". Treat as transient so
|
|
28
|
-
// the retry loop (and then the fallback model) gets a chance — otherwise a
|
|
29
|
-
// single slow Gemini Flash vision call sinks the entire critic stage with
|
|
30
|
-
// no recovery.
|
|
31
|
-
if (e.name === "AbortError")
|
|
32
|
-
return true;
|
|
33
|
-
const msg = String(e.message ?? "");
|
|
34
|
-
return /fetch failed|socket hang up|other side closed|network|timeout|operation was aborted/i.test(msg);
|
|
35
|
-
}
|
|
36
|
-
class GatewayLlmCaller {
|
|
37
|
-
constructor(cfg) {
|
|
38
|
-
this.cfg = cfg;
|
|
39
|
-
this.fetchImpl = cfg.fetchImpl ?? fetch;
|
|
40
|
-
this.timeoutMs = cfg.timeoutMs ?? 60000;
|
|
41
|
-
this.maxRetries = cfg.maxRetries ?? 3;
|
|
42
|
-
this.retryBaseMs = cfg.retryBaseMs ?? 250;
|
|
43
|
-
}
|
|
44
|
-
async chat(req) {
|
|
45
|
-
const attempted = [];
|
|
46
|
-
const run = async (model) => {
|
|
47
|
-
attempted.push(model);
|
|
48
|
-
const messages = await Promise.all(req.messages.map((m) => this.encodeMessage(m)));
|
|
49
|
-
const raw = await this.postWithRetry({
|
|
50
|
-
model: this.modelId(model),
|
|
51
|
-
messages,
|
|
52
|
-
temperature: req.temperature,
|
|
53
|
-
max_tokens: req.maxTokens,
|
|
54
|
-
stop: req.stop,
|
|
55
|
-
});
|
|
56
|
-
const text = raw.choices?.[0]?.message?.content ?? "";
|
|
57
|
-
return {
|
|
58
|
-
text: typeof text === "string" ? text : JSON.stringify(text),
|
|
59
|
-
usage: this.usage(raw),
|
|
60
|
-
requestId: raw.id,
|
|
61
|
-
};
|
|
62
|
-
};
|
|
63
|
-
try {
|
|
64
|
-
const out = await run(req.model);
|
|
65
|
-
return { ...out, attemptedModels: attempted, usedFallback: false };
|
|
66
|
-
}
|
|
67
|
-
catch (err) {
|
|
68
|
-
if (req.fallbackModel && err instanceof TransientLlmError) {
|
|
69
|
-
const out = await run(req.fallbackModel);
|
|
70
|
-
return { ...out, attemptedModels: attempted, usedFallback: true };
|
|
71
|
-
}
|
|
72
|
-
throw err;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
async structured(req) {
|
|
76
|
-
const attempted = [];
|
|
77
|
-
const jsonSchema = zod_1.z.toJSONSchema(req.schema, { target: "draft-7" });
|
|
78
|
-
const run = async (model) => {
|
|
79
|
-
attempted.push(model);
|
|
80
|
-
const messages = await Promise.all(req.messages.map((m) => this.encodeMessage(m)));
|
|
81
|
-
const raw = await this.postWithRetry({
|
|
82
|
-
model: this.modelId(model),
|
|
83
|
-
messages,
|
|
84
|
-
temperature: req.temperature,
|
|
85
|
-
max_tokens: req.maxTokens,
|
|
86
|
-
response_format: {
|
|
87
|
-
type: "json_schema",
|
|
88
|
-
json_schema: {
|
|
89
|
-
name: req.schemaName,
|
|
90
|
-
schema: jsonSchema,
|
|
91
|
-
strict: true,
|
|
92
|
-
},
|
|
93
|
-
},
|
|
94
|
-
});
|
|
95
|
-
const txt = raw.choices?.[0]?.message?.content ?? "";
|
|
96
|
-
if (!txt || typeof txt !== "string") {
|
|
97
|
-
// Empty body from the model is not retryable across providers —
|
|
98
|
-
// surface immediately; planner-level retry can re-prompt.
|
|
99
|
-
throw new Error(`GatewayLlmCaller.structured: empty response for schema ${req.schemaName}`);
|
|
100
|
-
}
|
|
101
|
-
let parsed;
|
|
102
|
-
try {
|
|
103
|
-
parsed = JSON.parse(txt);
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
throw new Error(`GatewayLlmCaller.structured: model returned non-JSON for schema ${req.schemaName}: ${txt.slice(0, 200)}`);
|
|
107
|
-
}
|
|
108
|
-
const result = req.schema.safeParse(parsed);
|
|
109
|
-
if (!result.success) {
|
|
110
|
-
throw new Error(`GatewayLlmCaller.structured: schema validation failed for ${req.schemaName}: ${result.error.message}`);
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
data: result.data,
|
|
114
|
-
usage: this.usage(raw),
|
|
115
|
-
requestId: raw.id,
|
|
116
|
-
};
|
|
117
|
-
};
|
|
118
|
-
try {
|
|
119
|
-
const out = await run(req.model);
|
|
120
|
-
return { ...out, attemptedModels: attempted, usedFallback: false };
|
|
121
|
-
}
|
|
122
|
-
catch (err) {
|
|
123
|
-
if (req.fallbackModel && err instanceof TransientLlmError) {
|
|
124
|
-
const out = await run(req.fallbackModel);
|
|
125
|
-
return { ...out, attemptedModels: attempted, usedFallback: true };
|
|
126
|
-
}
|
|
127
|
-
throw err;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
structuredStream(req) {
|
|
131
|
-
// Streaming: fall back is NOT applied mid-stream (would confuse UI
|
|
132
|
-
// chunks). Transport retry IS applied on the initial connect; once
|
|
133
|
-
// bytes start flowing, a mid-stream drop propagates as an error and
|
|
134
|
-
// the caller (planner) handles it via its own retry loop.
|
|
135
|
-
let resolveResult;
|
|
136
|
-
let rejectResult;
|
|
137
|
-
const result = new Promise((resolve, reject) => {
|
|
138
|
-
resolveResult = resolve;
|
|
139
|
-
rejectResult = reject;
|
|
140
|
-
});
|
|
141
|
-
const self = this;
|
|
142
|
-
const tokens = {
|
|
143
|
-
[Symbol.asyncIterator]() {
|
|
144
|
-
return self.createStreamingIterator(req, resolveResult, rejectResult);
|
|
145
|
-
},
|
|
146
|
-
};
|
|
147
|
-
return { tokens, result };
|
|
148
|
-
}
|
|
149
|
-
async *createStreamingIterator(req, resolveResult, rejectResult) {
|
|
150
|
-
const jsonSchema = zod_1.z.toJSONSchema(req.schema, { target: "draft-7" });
|
|
151
|
-
const messages = await Promise.all(req.messages.map((m) => this.encodeMessage(m)));
|
|
152
|
-
const ctrl = new AbortController();
|
|
153
|
-
const t = setTimeout(() => ctrl.abort(), this.timeoutMs);
|
|
154
|
-
let accumulated = "";
|
|
155
|
-
let requestId;
|
|
156
|
-
let usage;
|
|
157
|
-
try {
|
|
158
|
-
// Connect attempt with retry on transient connect failures (pre-stream).
|
|
159
|
-
const res = await this.withRetry(() => this.fetchImpl(`${this.cfg.baseUrl.replace(/\/$/, "")}/chat/completions`, {
|
|
160
|
-
method: "POST",
|
|
161
|
-
headers: {
|
|
162
|
-
"content-type": "application/json",
|
|
163
|
-
authorization: `Bearer ${this.cfg.apiKey}`,
|
|
164
|
-
},
|
|
165
|
-
body: JSON.stringify({
|
|
166
|
-
model: this.modelId(req.model),
|
|
167
|
-
messages,
|
|
168
|
-
temperature: req.temperature,
|
|
169
|
-
max_tokens: req.maxTokens,
|
|
170
|
-
stream: true,
|
|
171
|
-
response_format: {
|
|
172
|
-
type: "json_schema",
|
|
173
|
-
json_schema: {
|
|
174
|
-
name: req.schemaName,
|
|
175
|
-
schema: jsonSchema,
|
|
176
|
-
strict: true,
|
|
177
|
-
},
|
|
178
|
-
},
|
|
179
|
-
}),
|
|
180
|
-
signal: ctrl.signal,
|
|
181
|
-
}).then((r) => {
|
|
182
|
-
if (!r.ok && TRANSIENT_HTTP_STATUSES.has(r.status)) {
|
|
183
|
-
throw new TransientLlmError(`GatewayLlmCaller.structuredStream: ${r.status} ${r.statusText}`);
|
|
184
|
-
}
|
|
185
|
-
return r;
|
|
186
|
-
}));
|
|
187
|
-
if (!res.ok || !res.body) {
|
|
188
|
-
const text = await res.text().catch(() => "");
|
|
189
|
-
const err = new Error(`GatewayLlmCaller.structuredStream: ${res.status} ${res.statusText} — ${text.slice(0, 500)}`);
|
|
190
|
-
rejectResult(err);
|
|
191
|
-
throw err;
|
|
192
|
-
}
|
|
193
|
-
const reader = res.body.getReader();
|
|
194
|
-
const decoder = new TextDecoder();
|
|
195
|
-
let buf = "";
|
|
196
|
-
while (true) {
|
|
197
|
-
const { value, done } = await reader.read();
|
|
198
|
-
if (done)
|
|
199
|
-
break;
|
|
200
|
-
buf += decoder.decode(value, { stream: true });
|
|
201
|
-
let nl;
|
|
202
|
-
while ((nl = buf.indexOf("\n")) !== -1) {
|
|
203
|
-
const line = buf.slice(0, nl).trim();
|
|
204
|
-
buf = buf.slice(nl + 1);
|
|
205
|
-
if (!line || !line.startsWith("data:"))
|
|
206
|
-
continue;
|
|
207
|
-
const payload = line.slice(5).trim();
|
|
208
|
-
if (payload === "[DONE]")
|
|
209
|
-
break;
|
|
210
|
-
try {
|
|
211
|
-
const obj = JSON.parse(payload);
|
|
212
|
-
if (obj.id)
|
|
213
|
-
requestId = obj.id;
|
|
214
|
-
if (obj.usage) {
|
|
215
|
-
usage = {
|
|
216
|
-
promptTokens: obj.usage.prompt_tokens,
|
|
217
|
-
completionTokens: obj.usage.completion_tokens,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
const delta = obj.choices?.[0]?.delta?.content ?? "";
|
|
221
|
-
if (delta) {
|
|
222
|
-
accumulated += delta;
|
|
223
|
-
yield delta;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
catch {
|
|
227
|
-
// skip malformed line
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
// Post-stream failures (bad JSON / schema mismatch) reject the RESULT
|
|
232
|
-
// promise but must NOT throw out of this generator. The tokens already
|
|
233
|
-
// streamed fine; throwing here would propagate into the caller's
|
|
234
|
-
// `for await (...stream.tokens)` loop and abort it before the caller can
|
|
235
|
-
// reach `await stream.result` — which is exactly where the planner's
|
|
236
|
-
// non-streaming retry fallback lives (Planner.planStream). Returning
|
|
237
|
-
// cleanly lets the token loop complete, then the rejected result drives
|
|
238
|
-
// the retry. See plan.controller.ts:planProjectStream.
|
|
239
|
-
let parsed;
|
|
240
|
-
try {
|
|
241
|
-
parsed = JSON.parse(accumulated);
|
|
242
|
-
}
|
|
243
|
-
catch {
|
|
244
|
-
const err = new Error(`GatewayLlmCaller.structuredStream: model returned non-JSON for ${req.schemaName}: ${accumulated.slice(0, 200)}`);
|
|
245
|
-
rejectResult(err);
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
const validated = req.schema.safeParse(parsed);
|
|
249
|
-
if (!validated.success) {
|
|
250
|
-
const err = new Error(`GatewayLlmCaller.structuredStream: schema validation failed for ${req.schemaName}: ${validated.error.message}`);
|
|
251
|
-
rejectResult(err);
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
resolveResult({
|
|
255
|
-
data: validated.data,
|
|
256
|
-
usage,
|
|
257
|
-
requestId,
|
|
258
|
-
attemptedModels: [req.model],
|
|
259
|
-
usedFallback: false,
|
|
260
|
-
});
|
|
261
|
-
}
|
|
262
|
-
catch (e) {
|
|
263
|
-
rejectResult(e);
|
|
264
|
-
throw e;
|
|
265
|
-
}
|
|
266
|
-
finally {
|
|
267
|
-
clearTimeout(t);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
modelId(m) {
|
|
271
|
-
return `${m.provider}/${m.modelId}`;
|
|
272
|
-
}
|
|
273
|
-
async encodeMessage(m) {
|
|
274
|
-
if (!m.imageUrls?.length) {
|
|
275
|
-
return { role: m.role, content: m.content };
|
|
276
|
-
}
|
|
277
|
-
// Fetch + base64-encode each URL into a data URI. The gateway's Anthropic
|
|
278
|
-
// translator rejects raw https URLs ("URL sources are not supported"); data
|
|
279
|
-
// URIs round-trip through every provider's OpenAI-compat shim correctly.
|
|
280
|
-
const dataUris = await Promise.all(m.imageUrls.map((u) => this.toDataUri(u)));
|
|
281
|
-
return {
|
|
282
|
-
role: m.role,
|
|
283
|
-
content: [
|
|
284
|
-
{ type: "text", text: m.content },
|
|
285
|
-
...dataUris.map((url) => ({ type: "image_url", image_url: { url } })),
|
|
286
|
-
],
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
async toDataUri(url) {
|
|
290
|
-
if (url.startsWith("data:"))
|
|
291
|
-
return url;
|
|
292
|
-
const res = await this.fetchImpl(url);
|
|
293
|
-
if (!res.ok) {
|
|
294
|
-
throw new Error(`GatewayLlmCaller.toDataUri: ${res.status} ${res.statusText} fetching ${url}`);
|
|
295
|
-
}
|
|
296
|
-
const contentType = res.headers.get("content-type")?.split(";")[0]?.trim() || "image/jpeg";
|
|
297
|
-
const buf = Buffer.from(await res.arrayBuffer());
|
|
298
|
-
return `data:${contentType};base64,${buf.toString("base64")}`;
|
|
299
|
-
}
|
|
300
|
-
usage(raw) {
|
|
301
|
-
if (!raw.usage)
|
|
302
|
-
return undefined;
|
|
303
|
-
return {
|
|
304
|
-
promptTokens: raw.usage.prompt_tokens,
|
|
305
|
-
completionTokens: raw.usage.completion_tokens,
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* POST /chat/completions with transient-error retry (F1).
|
|
310
|
-
* Throws TransientLlmError after exhausting retries on transient failures —
|
|
311
|
-
* caller catches it to trigger model fallback (F2). Non-transient errors
|
|
312
|
-
* (4xx other than 408/425/429, malformed responses) propagate as plain Error.
|
|
313
|
-
*/
|
|
314
|
-
async postWithRetry(body) {
|
|
315
|
-
return this.withRetry(() => this.postOnce(body));
|
|
316
|
-
}
|
|
317
|
-
async withRetry(fn) {
|
|
318
|
-
let lastErr;
|
|
319
|
-
for (let attempt = 0; attempt < this.maxRetries; attempt++) {
|
|
320
|
-
try {
|
|
321
|
-
return await fn();
|
|
322
|
-
}
|
|
323
|
-
catch (err) {
|
|
324
|
-
lastErr = err;
|
|
325
|
-
const transient = err instanceof TransientLlmError || isTransientNetworkError(err);
|
|
326
|
-
if (!transient || attempt === this.maxRetries - 1) {
|
|
327
|
-
if (transient) {
|
|
328
|
-
// Wrap so the fallback-model path can catch it explicitly.
|
|
329
|
-
throw err instanceof TransientLlmError
|
|
330
|
-
? err
|
|
331
|
-
: new TransientLlmError(`transient LLM error after ${attempt + 1} attempts: ${String(err?.message ?? err)}`, err);
|
|
332
|
-
}
|
|
333
|
-
throw err;
|
|
334
|
-
}
|
|
335
|
-
await new Promise((r) => setTimeout(r, this.retryBaseMs * Math.pow(4, attempt)));
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
throw lastErr;
|
|
339
|
-
}
|
|
340
|
-
async postOnce(body) {
|
|
341
|
-
const ctrl = new AbortController();
|
|
342
|
-
const t = setTimeout(() => ctrl.abort(), this.timeoutMs);
|
|
343
|
-
try {
|
|
344
|
-
const res = await this.fetchImpl(`${this.cfg.baseUrl.replace(/\/$/, "")}/chat/completions`, {
|
|
345
|
-
method: "POST",
|
|
346
|
-
headers: {
|
|
347
|
-
"content-type": "application/json",
|
|
348
|
-
authorization: `Bearer ${this.cfg.apiKey}`,
|
|
349
|
-
},
|
|
350
|
-
body: JSON.stringify(body),
|
|
351
|
-
signal: ctrl.signal,
|
|
352
|
-
});
|
|
353
|
-
if (!res.ok) {
|
|
354
|
-
const text = await res.text().catch(() => "");
|
|
355
|
-
const msg = `GatewayLlmCaller: ${res.status} ${res.statusText} — ${text.slice(0, 500)}`;
|
|
356
|
-
if (TRANSIENT_HTTP_STATUSES.has(res.status)) {
|
|
357
|
-
throw new TransientLlmError(msg);
|
|
358
|
-
}
|
|
359
|
-
throw new Error(msg);
|
|
360
|
-
}
|
|
361
|
-
return (await res.json());
|
|
362
|
-
}
|
|
363
|
-
finally {
|
|
364
|
-
clearTimeout(t);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
exports.GatewayLlmCaller = GatewayLlmCaller;
|