@blockrun/franklin 3.8.33 → 3.8.34

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.
@@ -84,7 +84,7 @@ export function classifyAgentError(message) {
84
84
  'dns resolution',
85
85
  ])) {
86
86
  return {
87
- category: 'network', label: 'Network', isTransient: true,
87
+ category: 'network', label: 'Network', isTransient: true, maxRetries: 1,
88
88
  suggestion: 'Check your network connection. Use /retry to try again.',
89
89
  };
90
90
  }
package/dist/agent/llm.js CHANGED
@@ -7,10 +7,20 @@ import { getOrCreateWallet, getOrCreateSolanaWallet, createPaymentPayload, creat
7
7
  import { USER_AGENT } from '../config.js';
8
8
  import { routeRequest, parseRoutingProfile } from '../router/index.js';
9
9
  import { ThinkTagStripper } from './think-tag-stripper.js';
10
- function getModelIdleTimeoutMs() {
11
- const raw = process.env.FRANKLIN_MODEL_IDLE_TIMEOUT_MS;
10
+ function parseTimeoutEnv(name) {
11
+ const raw = process.env[name];
12
12
  const parsed = raw ? Number.parseInt(raw, 10) : NaN;
13
- return Number.isFinite(parsed) && parsed >= 0 ? parsed : 25_000;
13
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : null;
14
+ }
15
+ function getModelRequestTimeoutMs() {
16
+ return (parseTimeoutEnv('FRANKLIN_MODEL_REQUEST_TIMEOUT_MS') ??
17
+ parseTimeoutEnv('FRANKLIN_MODEL_IDLE_TIMEOUT_MS') ??
18
+ 8_000);
19
+ }
20
+ function getModelStreamIdleTimeoutMs() {
21
+ return (parseTimeoutEnv('FRANKLIN_MODEL_STREAM_IDLE_TIMEOUT_MS') ??
22
+ parseTimeoutEnv('FRANKLIN_MODEL_IDLE_TIMEOUT_MS') ??
23
+ 25_000);
14
24
  }
15
25
  function linkAbortSignal(parent, child) {
16
26
  if (!parent)
@@ -329,7 +339,8 @@ export class ModelClient {
329
339
  if (this.debug) {
330
340
  console.error(`[franklin] POST ${endpoint} model=${request.model}`);
331
341
  }
332
- const timeoutMs = getModelIdleTimeoutMs();
342
+ const requestTimeoutMs = getModelRequestTimeoutMs();
343
+ const streamTimeoutMs = getModelStreamIdleTimeoutMs();
333
344
  const requestController = new AbortController();
334
345
  const unlinkAbort = linkAbortSignal(signal, requestController);
335
346
  try {
@@ -338,7 +349,7 @@ export class ModelClient {
338
349
  headers,
339
350
  body,
340
351
  signal: requestController.signal,
341
- }), requestController, createModelTimeoutError('request', request.model, timeoutMs), timeoutMs);
352
+ }), requestController, createModelTimeoutError('request', request.model, requestTimeoutMs), requestTimeoutMs);
342
353
  // Handle x402 payment
343
354
  if (response.status === 402) {
344
355
  if (this.debug)
@@ -353,7 +364,7 @@ export class ModelClient {
353
364
  headers: { ...headers, ...paymentHeader },
354
365
  body,
355
366
  signal: requestController.signal,
356
- }), requestController, createModelTimeoutError('request', request.model, timeoutMs), timeoutMs);
367
+ }), requestController, createModelTimeoutError('request', request.model, requestTimeoutMs), requestTimeoutMs);
357
368
  }
358
369
  if (!response.ok) {
359
370
  const errorBody = await response.text().catch(() => 'unknown error');
@@ -365,7 +376,7 @@ export class ModelClient {
365
376
  return;
366
377
  }
367
378
  // Parse SSE stream
368
- yield* this.parseSSEStream(response, requestController, timeoutMs, request.model);
379
+ yield* this.parseSSEStream(response, requestController, streamTimeoutMs, request.model);
369
380
  }
370
381
  finally {
371
382
  unlinkAbort();
@@ -31,6 +31,14 @@ const INSTALL_ID_FILE = path.join(BLOCKRUN_DIR, 'telemetry-install-id.txt');
31
31
  function ensureDir() {
32
32
  fs.mkdirSync(BLOCKRUN_DIR, { recursive: true });
33
33
  }
34
+ function canonicalDir(dir) {
35
+ try {
36
+ return fs.realpathSync(path.resolve(dir));
37
+ }
38
+ catch {
39
+ return path.resolve(dir);
40
+ }
41
+ }
34
42
  /** Enabled-state check. Default: false. */
35
43
  export function isTelemetryEnabled() {
36
44
  try {
@@ -121,8 +129,9 @@ export function recordSession(meta, chain) {
121
129
  export function recordLatestSessionIfEnabled(workingDir, chain) {
122
130
  if (!isTelemetryEnabled())
123
131
  return;
132
+ const targetDir = canonicalDir(workingDir);
124
133
  const sessions = listSessions();
125
- const match = sessions.find(s => s.workDir === workingDir);
134
+ const match = sessions.find(s => canonicalDir(s.workDir) === targetDir);
126
135
  if (!match)
127
136
  return;
128
137
  recordSession(match, chain);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blockrun/franklin",
3
- "version": "3.8.33",
3
+ "version": "3.8.34",
4
4
  "description": "Franklin — The AI agent with a wallet. Spends USDC autonomously to get real work done. Pay per action, no subscriptions.",
5
5
  "type": "module",
6
6
  "exports": {