@blockrun/franklin 3.15.63 → 3.15.65
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/context.js +49 -13
- package/package.json +1 -1
package/dist/agent/context.js
CHANGED
|
@@ -6,6 +6,8 @@ import fs from 'node:fs';
|
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { execSync } from 'node:child_process';
|
|
8
8
|
import { getWalletAddress as getBaseWalletAddress } from '@blockrun/llm';
|
|
9
|
+
import { Keypair } from '@solana/web3.js';
|
|
10
|
+
import bs58 from 'bs58';
|
|
9
11
|
import { loadLearnings, decayLearnings, saveLearnings, formatForPrompt, loadSkills, formatSkillsForPrompt } from '../learnings/store.js';
|
|
10
12
|
// ─── System Instructions Assembly ──────────────────────────────────────────
|
|
11
13
|
// Composable prompt sections — each independently maintainable and conditionally includable.
|
|
@@ -164,10 +166,16 @@ Franklin stores wallet keys in ~/.blockrun/. When the user asks about wallet loc
|
|
|
164
166
|
Format: 66-char hex string starting with 0x (file name intentionally looks like a session token for obscurity)
|
|
165
167
|
Address: derivable from the key; also available via getWalletAddress() from @blockrun/llm
|
|
166
168
|
- Solana wallet:
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
-
|
|
169
|
+
Private key file: ~/.blockrun/.solana-session
|
|
170
|
+
Format: bare base58 secret key (file name mirrors the Base wallet's obscurity convention; mode 600)
|
|
171
|
+
Address: derivable; available via getOrCreateSolanaWallet() from @blockrun/llm
|
|
172
|
+
- Chain selection: ~/.blockrun/payment-chain ("base" or "solana"). Legacy file ~/.blockrun/.chain may also exist on installs that haven't migrated; canonical is payment-chain.
|
|
173
|
+
- Spending data:
|
|
174
|
+
- ~/.blockrun/franklin-stats.json — rolling totals + per-model breakdown (what \`franklin stats\` reads).
|
|
175
|
+
- ~/.blockrun/franklin-audit.jsonl — append-only forensic ledger of every LLM call.
|
|
176
|
+
- ~/.blockrun/cost_log.jsonl — append-only ledger of every settled x402 payment (written by @blockrun/llm SDK).
|
|
177
|
+
- Use \`franklin stats\` / \`franklin content list\` instead of parsing files when the user asks "how much did I spend".
|
|
178
|
+
- Programmatic access: import { getWalletAddress, getOrCreateWallet, getOrCreateSolanaWallet } from '@blockrun/llm'
|
|
171
179
|
|
|
172
180
|
When the user asks about "my wallet" without qualifier, default to Base (it's the primary chain shown at launch). Only mention Solana if the chain file says solana or the user explicitly asks.`;
|
|
173
181
|
}
|
|
@@ -184,7 +192,7 @@ You run on the BlockRun AI Gateway. When the user asks you to "test the BlockRun
|
|
|
184
192
|
- \`GET /.well-known/x402\` — x402 resource list with prices
|
|
185
193
|
|
|
186
194
|
**LLM (POST, x402-paid)**
|
|
187
|
-
- \`POST /v1/chat/completions\` — OpenAI-compatible. Body: \`{ model, messages, stream?, tools?, max_tokens?, temperature? }\`. \`model\` MUST come from \`GET /v1/models\` (
|
|
195
|
+
- \`POST /v1/chat/completions\` — OpenAI-compatible. Body: \`{ model, messages, stream?, tools?, max_tokens?, temperature? }\`. \`model\` MUST come from \`GET /v1/models\` (real frontier examples on the gateway as of 2026-05: \`anthropic/claude-sonnet-4.6\`, \`anthropic/claude-opus-4.7\`, \`deepseek/deepseek-v4-pro\`, \`zai/glm-5.1\`, \`nvidia/qwen3-coder-480b\`, \`openai/gpt-5-nano\`). Do NOT invent versions like \`openai/gpt-5.1\` or \`xai/grok-5\` — those don't exist; the gateway 400s with the valid list in the error body, so when in doubt fetch \`GET /v1/models\` first.
|
|
188
196
|
- \`POST /v1/messages\` — Anthropic-compatible. Body: \`{ model, messages, max_tokens, system?, tools? }\`.
|
|
189
197
|
|
|
190
198
|
**Media (POST, x402-paid; GET to poll async jobs)**
|
|
@@ -604,7 +612,7 @@ function buildEnvironmentSection(workingDir) {
|
|
|
604
612
|
if (wallet.base)
|
|
605
613
|
lines.push(`- Base wallet address: ${wallet.base} (private key at ~/.blockrun/.session)`);
|
|
606
614
|
if (wallet.solana)
|
|
607
|
-
lines.push(`- Solana wallet address: ${wallet.solana} (private key at ~/.blockrun
|
|
615
|
+
lines.push(`- Solana wallet address: ${wallet.solana} (private key at ~/.blockrun/.solana-session)`);
|
|
608
616
|
}
|
|
609
617
|
return lines.join('\n');
|
|
610
618
|
}
|
|
@@ -644,14 +652,42 @@ function readRuntimeWallet() {
|
|
|
644
652
|
out.base = addr;
|
|
645
653
|
}
|
|
646
654
|
catch { /* SDK may not be available in all contexts — skip silently */ }
|
|
647
|
-
// Solana address:
|
|
655
|
+
// Solana address: prefer the canonical SDK file `.solana-session`
|
|
656
|
+
// (raw base58 secret key, mode 600 — what the SDK actually writes
|
|
657
|
+
// and reads via getOrCreateSolanaWallet). Fall back to the legacy
|
|
658
|
+
// `solana-wallet.json` shape (JSON with {address, privateKey}) for
|
|
659
|
+
// unmigrated installs. Verified 2026-05-05: user's machine had
|
|
660
|
+
// both files present — `.solana-session` (88 bytes) was canonical
|
|
661
|
+
// and `solana-wallet.json` (123 bytes) was a leftover from an
|
|
662
|
+
// earlier SDK version. The pre-fix code only read the legacy file,
|
|
663
|
+
// so once a user `rm`s it after migration, the runtime-wallet
|
|
664
|
+
// section silently stops showing the Solana address.
|
|
648
665
|
try {
|
|
649
|
-
const
|
|
650
|
-
if (fs.existsSync(
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
666
|
+
const canonical = path.join(blockrunDir, '.solana-session');
|
|
667
|
+
if (fs.existsSync(canonical)) {
|
|
668
|
+
const key = fs.readFileSync(canonical, 'utf-8').trim();
|
|
669
|
+
if (key) {
|
|
670
|
+
// Derive the public address from the secret key. Same primitives
|
|
671
|
+
// jupiter.ts:229 uses for transaction signing — keeps this
|
|
672
|
+
// sync-with-SDK without depending on async `getOrCreateSolanaWallet`
|
|
673
|
+
// (which would create a wallet on first read, an unwanted side
|
|
674
|
+
// effect for a context-builder).
|
|
675
|
+
try {
|
|
676
|
+
const bytes = bs58.decode(key);
|
|
677
|
+
const kp = Keypair.fromSecretKey(bytes);
|
|
678
|
+
out.solana = kp.publicKey.toBase58();
|
|
679
|
+
}
|
|
680
|
+
catch { /* derivation failed — fall through to legacy probe */ }
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (!out.solana) {
|
|
684
|
+
const legacy = path.join(blockrunDir, 'solana-wallet.json');
|
|
685
|
+
if (fs.existsSync(legacy)) {
|
|
686
|
+
const data = JSON.parse(fs.readFileSync(legacy, 'utf-8'));
|
|
687
|
+
const addr = data.address || data.publicKey;
|
|
688
|
+
if (addr && typeof addr === 'string')
|
|
689
|
+
out.solana = addr;
|
|
690
|
+
}
|
|
655
691
|
}
|
|
656
692
|
}
|
|
657
693
|
catch { /* ignore */ }
|
package/package.json
CHANGED