@blockrun/franklin 3.15.95 → 3.15.97
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/agent/streaming-executor.js +13 -1
- package/dist/commands/doctor.js +19 -5
- package/dist/logger.js +16 -1
- package/package.json +1 -1
|
@@ -219,7 +219,19 @@ export class StreamingExecutor {
|
|
|
219
219
|
const execElapsed = Date.now() - execStart;
|
|
220
220
|
if (execElapsed >= 30_000) {
|
|
221
221
|
const status = result.isError ? 'error' : 'ok';
|
|
222
|
-
|
|
222
|
+
// Single-line the preview before logging. Bash invocations like
|
|
223
|
+
// `python3 -c "<heredoc>"` carry embedded newlines that, sliced
|
|
224
|
+
// raw, break the one-line-per-entry contract of
|
|
225
|
+
// franklin-debug.log and shred any parser that splits on
|
|
226
|
+
// `^\[timestamp\]`. Verified 2026-05-04 (and reviewed again
|
|
227
|
+
// 2026-05-12): a real entry produced
|
|
228
|
+
// `Slow tool: Bash ok after 438.4s — cd ... python3 -c "`
|
|
229
|
+
// `import subprocess`
|
|
230
|
+
// `[2026-05-04T19:25:10] [ERROR] Signature-loop hard stop ...`
|
|
231
|
+
// where "import subprocess" sat on its own line, untimestamped,
|
|
232
|
+
// because the preview's first 80 chars contained the heredoc
|
|
233
|
+
// opener.
|
|
234
|
+
const preview = (this.inputPreview(invocation) || '').replace(/[\r\n]+/g, ' ');
|
|
223
235
|
logger.info(`[franklin] Slow tool: ${invocation.name} ${status} after ${(execElapsed / 1000).toFixed(1)}s${preview ? ` — ${preview.slice(0, 80)}` : ''}`);
|
|
224
236
|
}
|
|
225
237
|
// Persist large results to disk with preview.
|
package/dist/commands/doctor.js
CHANGED
|
@@ -108,13 +108,27 @@ async function runChecks() {
|
|
|
108
108
|
status: 'ok',
|
|
109
109
|
detail: `${walletAddress.slice(0, 10)}…${walletAddress.slice(-6)}`,
|
|
110
110
|
});
|
|
111
|
+
// Tiered balance status. Binary `> 0` was misleading — verified
|
|
112
|
+
// 2026-05-11 from a real run: doctor printed `✓ USDC balance
|
|
113
|
+
// $0.37` (green) on a wallet that couldn't fund a single Opus
|
|
114
|
+
// call ($0.50+ each). Threshold of $1.00 covers ~10 cheap-model
|
|
115
|
+
// calls or ~2 mid-tier calls — anything below that is
|
|
116
|
+
// operationally empty for paid workflows. Free models still work.
|
|
117
|
+
const LOW_BALANCE_THRESHOLD = 1.00;
|
|
118
|
+
const balanceStatus = walletBalance >= LOW_BALANCE_THRESHOLD ? 'ok' : 'warn';
|
|
119
|
+
const balanceDetail = walletBalance === 0
|
|
120
|
+
? '$0.00 — free-tier models only (no paid calls possible)'
|
|
121
|
+
: walletBalance < LOW_BALANCE_THRESHOLD
|
|
122
|
+
? `$${walletBalance.toFixed(2)} — low; paid calls likely to fail mid-stream`
|
|
123
|
+
: `$${walletBalance.toFixed(2)}`;
|
|
124
|
+
const balanceRemedy = walletBalance < LOW_BALANCE_THRESHOLD
|
|
125
|
+
? `Send USDC on ${chain} to ${walletAddress} (or open http://localhost:3100/#wallet)`
|
|
126
|
+
: undefined;
|
|
111
127
|
out.push({
|
|
112
128
|
name: 'USDC balance',
|
|
113
|
-
status:
|
|
114
|
-
detail:
|
|
115
|
-
remedy:
|
|
116
|
-
? `Send USDC on ${chain} to ${walletAddress} to unlock paid models`
|
|
117
|
-
: undefined,
|
|
129
|
+
status: balanceStatus,
|
|
130
|
+
detail: balanceDetail,
|
|
131
|
+
remedy: balanceRemedy,
|
|
118
132
|
});
|
|
119
133
|
}
|
|
120
134
|
catch (err) {
|
package/dist/logger.js
CHANGED
|
@@ -86,7 +86,22 @@ function writeFile(level, msg) {
|
|
|
86
86
|
writesSinceRotateProbe = 0;
|
|
87
87
|
maybeRotate();
|
|
88
88
|
}
|
|
89
|
-
|
|
89
|
+
// Two-step sanitize, in this order:
|
|
90
|
+
// 1. Collapse embedded newlines (\n / \r / \r\n) to a literal
|
|
91
|
+
// " ↵ " marker so a single logger call always produces one
|
|
92
|
+
// physical log line.
|
|
93
|
+
// 2. Strip ANSI escape sequences.
|
|
94
|
+
//
|
|
95
|
+
// Order matters: ANSI_RE strips bare \r (used by progress bars), so
|
|
96
|
+
// running it first would erase \r-only line breaks and let
|
|
97
|
+
// "first\rsecond" appear as "firstsecond" in the log. Verified
|
|
98
|
+
// 2026-05-12 from franklin-debug.log: a `Slow tool: Bash ok ...
|
|
99
|
+
// python3 -c "` preview leaked `import subprocess` onto its own
|
|
100
|
+
// untimestamped line because the embedded \n in the bash command
|
|
101
|
+
// survived the preview slice and broke any parser that splits on
|
|
102
|
+
// ^\[timestamp\]. Cheaper to enforce one-line-per-entry here than
|
|
103
|
+
// to police every callsite.
|
|
104
|
+
const clean = msg.replace(/\r\n|\r|\n/g, ' ↵ ').replace(ANSI_RE, '');
|
|
90
105
|
fs.appendFileSync(LOG_FILE, `[${new Date().toISOString()}] [${level.toUpperCase()}] ${clean}\n`);
|
|
91
106
|
}
|
|
92
107
|
catch { /* best-effort — never break the agent on log failure */ }
|
package/package.json
CHANGED