@blockrun/franklin 3.15.61 → 3.15.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tools/imagegen.js +8 -1
- package/dist/tools/modal.js +12 -4
- package/dist/tools/videogen.js +8 -1
- package/package.json +1 -1
package/dist/tools/imagegen.js
CHANGED
|
@@ -230,6 +230,12 @@ function buildExecute(deps) {
|
|
|
230
230
|
// minutes; text-to-image keeps the original 60s.
|
|
231
231
|
const timeoutMs = referenceImage ? 180_000 : 60_000;
|
|
232
232
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
233
|
+
// Wall-clock start of the paid call, including 402 retry + (optional)
|
|
234
|
+
// 202 polling. Used by recordUsage below so franklin-stats.json
|
|
235
|
+
// populates avgLatencyMs for image models. Mirrors the agent-loop fix
|
|
236
|
+
// in 3.15.61 — same pattern, same reason: insights couldn't surface
|
|
237
|
+
// "Seedance is slower than grok" while every media call recorded 0.
|
|
238
|
+
const callStartedAt = Date.now();
|
|
233
239
|
try {
|
|
234
240
|
// First request — will get 402
|
|
235
241
|
let response = await fetch(endpoint, {
|
|
@@ -362,11 +368,12 @@ function buildExecute(deps) {
|
|
|
362
368
|
// insights panel under-reported total spend and never surfaced
|
|
363
369
|
// image-generation models in its "top models" list. Fire-and-forget —
|
|
364
370
|
// stats write must not fail a user-visible generation.
|
|
371
|
+
const latencyMs = Date.now() - callStartedAt;
|
|
365
372
|
void (async () => {
|
|
366
373
|
try {
|
|
367
374
|
const m = await findModel(imageModel);
|
|
368
375
|
const estCost = m ? estimateCostUsd(m, { quantity: 1 }) : 0;
|
|
369
|
-
recordUsage(imageModel, 0, 0, estCost,
|
|
376
|
+
recordUsage(imageModel, 0, 0, estCost, latencyMs);
|
|
370
377
|
}
|
|
371
378
|
catch { /* ignore stats errors */ }
|
|
372
379
|
})();
|
package/dist/tools/modal.js
CHANGED
|
@@ -325,7 +325,9 @@ export const modalCreateCapability = {
|
|
|
325
325
|
body.cpu = cpuCoerced;
|
|
326
326
|
if (typeof memoryCoerced === 'number')
|
|
327
327
|
body.memory = memoryCoerced;
|
|
328
|
+
const callStartedAt = Date.now();
|
|
328
329
|
const res = await postWithPayment(modalEndpoint('create'), body, 'Franklin Modal sandbox create', ctx.abortSignal, 90_000);
|
|
330
|
+
const latencyMs = Date.now() - callStartedAt;
|
|
329
331
|
if (!res.ok) {
|
|
330
332
|
const err = res.body.error ? String(res.body.error) : res.raw.slice(0, 300);
|
|
331
333
|
// Surface the per-field validation issues — usually the
|
|
@@ -356,7 +358,7 @@ export const modalCreateCapability = {
|
|
|
356
358
|
});
|
|
357
359
|
// Stats — surface Modal usage in `franklin insights` like other paid tools.
|
|
358
360
|
try {
|
|
359
|
-
recordUsage(`modal/${tier}`, 0, 0, price,
|
|
361
|
+
recordUsage(`modal/${tier}`, 0, 0, price, latencyMs);
|
|
360
362
|
}
|
|
361
363
|
catch { /* ignore */ }
|
|
362
364
|
return {
|
|
@@ -448,7 +450,9 @@ export const modalExecCapability = {
|
|
|
448
450
|
};
|
|
449
451
|
if (coercedTimeout !== undefined)
|
|
450
452
|
body.timeout = coercedTimeout;
|
|
453
|
+
const callStartedAt = Date.now();
|
|
451
454
|
const res = await postWithPayment(modalEndpoint('exec'), body, 'Franklin Modal sandbox exec', ctx.abortSignal, Math.max(30_000, ((coercedTimeout ?? 300) + 30) * 1000));
|
|
455
|
+
const latencyMs = Date.now() - callStartedAt;
|
|
452
456
|
if (!res.ok) {
|
|
453
457
|
// 400 here usually means the agent built the wrong shape (bad
|
|
454
458
|
// sandbox_id, malformed command). Dump the full raw body so the
|
|
@@ -479,7 +483,7 @@ export const modalExecCapability = {
|
|
|
479
483
|
const hasAnyOutput = stdout.length > 0 || stderr.length > 0;
|
|
480
484
|
const exitCode = rawExit !== null ? rawExit : (hasAnyOutput ? 0 : -1);
|
|
481
485
|
try {
|
|
482
|
-
recordUsage('modal/exec', 0, 0, EXEC_PRICE_USD,
|
|
486
|
+
recordUsage('modal/exec', 0, 0, EXEC_PRICE_USD, latencyMs);
|
|
483
487
|
}
|
|
484
488
|
catch { /* ignore */ }
|
|
485
489
|
const summary = `exit ${exitCode}` + (rawExit === null ? ' (inferred — no exit_code field in response)' : '');
|
|
@@ -527,13 +531,15 @@ export const modalStatusCapability = {
|
|
|
527
531
|
}
|
|
528
532
|
catch { /* ignore */ }
|
|
529
533
|
try {
|
|
534
|
+
const callStartedAt = Date.now();
|
|
530
535
|
const res = await postWithPayment(modalEndpoint('status'), { sandbox_id }, 'Franklin Modal sandbox status', ctx.abortSignal, 30_000);
|
|
536
|
+
const latencyMs = Date.now() - callStartedAt;
|
|
531
537
|
if (!res.ok) {
|
|
532
538
|
const err = res.body.error ? String(res.body.error) : res.raw.slice(0, 300);
|
|
533
539
|
return { output: `ModalStatus failed (${res.status}): ${err}`, isError: true };
|
|
534
540
|
}
|
|
535
541
|
try {
|
|
536
|
-
recordUsage('modal/status', 0, 0, STATUS_PRICE_USD,
|
|
542
|
+
recordUsage('modal/status', 0, 0, STATUS_PRICE_USD, latencyMs);
|
|
537
543
|
}
|
|
538
544
|
catch { /* ignore */ }
|
|
539
545
|
const status = res.body.status || 'unknown';
|
|
@@ -573,7 +579,9 @@ export const modalTerminateCapability = {
|
|
|
573
579
|
}
|
|
574
580
|
catch { /* ignore */ }
|
|
575
581
|
try {
|
|
582
|
+
const callStartedAt = Date.now();
|
|
576
583
|
const res = await postWithPayment(modalEndpoint('terminate'), { sandbox_id }, 'Franklin Modal sandbox terminate', ctx.abortSignal, 30_000);
|
|
584
|
+
const latencyMs = Date.now() - callStartedAt;
|
|
577
585
|
// Always remove from tracker — even on failure, retrying is wasteful.
|
|
578
586
|
sessionSandboxTracker.remove(sandbox_id);
|
|
579
587
|
if (!res.ok) {
|
|
@@ -585,7 +593,7 @@ export const modalTerminateCapability = {
|
|
|
585
593
|
};
|
|
586
594
|
}
|
|
587
595
|
try {
|
|
588
|
-
recordUsage('modal/terminate', 0, 0, TERMINATE_PRICE_USD,
|
|
596
|
+
recordUsage('modal/terminate', 0, 0, TERMINATE_PRICE_USD, latencyMs);
|
|
589
597
|
}
|
|
590
598
|
catch { /* ignore */ }
|
|
591
599
|
return { output: `Sandbox \`${sandbox_id}\` terminated.` };
|
package/dist/tools/videogen.js
CHANGED
|
@@ -167,6 +167,12 @@ function buildExecute(deps) {
|
|
|
167
167
|
'Content-Type': 'application/json',
|
|
168
168
|
'User-Agent': `franklin/${VERSION}`,
|
|
169
169
|
};
|
|
170
|
+
// Wall-clock start of the paid call (submit + poll + download). Fed
|
|
171
|
+
// to recordUsage below so franklin-stats.json populates avgLatencyMs
|
|
172
|
+
// for video models. Same fix as 3.15.61 (agent loop) — five
|
|
173
|
+
// recordUsage callsites in this codebase, three of them were
|
|
174
|
+
// hardcoding 0.
|
|
175
|
+
const callStartedAt = Date.now();
|
|
170
176
|
const onAbort = (ctrl) => () => ctrl.abort();
|
|
171
177
|
// Phase 1: submit the job. First POST triggers a 402; we sign and retry.
|
|
172
178
|
// The signed paymentHeaders must be reused on every GET poll — the server
|
|
@@ -300,11 +306,12 @@ function buildExecute(deps) {
|
|
|
300
306
|
// Prefer the live gateway price when the model is in the catalog;
|
|
301
307
|
// fall back to the legacy $0.05/s estimate otherwise. Fire-and-
|
|
302
308
|
// forget — stats write must not fail a user-visible generation.
|
|
309
|
+
const latencyMs = Date.now() - callStartedAt;
|
|
303
310
|
void (async () => {
|
|
304
311
|
try {
|
|
305
312
|
const m = await findModel(videoModel);
|
|
306
313
|
const estCost = m ? estimateCostUsd(m, { duration_seconds: dur }) : estimateVideoCostUsd(dur);
|
|
307
|
-
recordUsage(videoModel, 0, 0, estCost,
|
|
314
|
+
recordUsage(videoModel, 0, 0, estCost, latencyMs);
|
|
308
315
|
}
|
|
309
316
|
catch { /* ignore stats errors */ }
|
|
310
317
|
})();
|
package/package.json
CHANGED