opencrowd 0.7.0 → 0.8.0
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/README.md +13 -0
- package/bundle/opencrowd.js +421 -118
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,6 +84,18 @@ There is one wallet: AgentCash's. OpenCrowd shows public addresses,
|
|
|
84
84
|
balances, and funding links (`/wallet`, `/fund`) and never manages, copies,
|
|
85
85
|
or exports keys. See [SECURITY.md](SECURITY.md) for the enforcement model.
|
|
86
86
|
|
|
87
|
+
Paid services settle in USDC on the network you prefer when they offer it:
|
|
88
|
+
x402 on Base (the default) or Solana, MPP on Tempo, and x402 on Monad when
|
|
89
|
+
you choose it. Solana uses AgentCash's separate Solana address
|
|
90
|
+
(`~/.agentcash/solana-wallet.json`); `opencrowd wallet accounts` lists every
|
|
91
|
+
network's address and balance. When a service does not offer your preferred
|
|
92
|
+
network, the first of Base, Solana and Tempo whose balance covers the price is
|
|
93
|
+
used.
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
opencrowd config set payment-network solana # or --payment-network solana per run
|
|
97
|
+
```
|
|
98
|
+
|
|
87
99
|
## Spending limits
|
|
88
100
|
|
|
89
101
|
By default, each model or paid tool call can spend up to **$1** automatically,
|
|
@@ -137,6 +149,7 @@ opencrowd run --budget 1.00 "Find a service and summarize options"
|
|
|
137
149
|
opencrowd run --session <session-id> "Follow up on the previous result"
|
|
138
150
|
opencrowd config show
|
|
139
151
|
opencrowd wallet balance
|
|
152
|
+
opencrowd wallet accounts
|
|
140
153
|
opencrowd doctor
|
|
141
154
|
opencrowd evals gaia --tier smoke --harness opencrowd,claude,codex
|
|
142
155
|
opencrowd evals suite --set all --tag baseline --model openai/gpt-5.6-luna --subagent-model off
|
package/bundle/opencrowd.js
CHANGED
|
@@ -50,7 +50,7 @@ var __toESM = (mod4, isNodeMode, target) => (target = mod4 != null ? __create(__
|
|
|
50
50
|
|
|
51
51
|
// ../../packages/core/dist/agentcash.js
|
|
52
52
|
import { readFile } from "node:fs/promises";
|
|
53
|
-
import { join } from "node:path";
|
|
53
|
+
import { dirname, join } from "node:path";
|
|
54
54
|
import { homedir } from "node:os";
|
|
55
55
|
function agentCashWalletPath() {
|
|
56
56
|
return process.env.AGENTCASH_WALLET_PATH ?? join(homedir(), ".agentcash", "wallet.json");
|
|
@@ -65,6 +65,14 @@ async function readAgentCashWallet() {
|
|
|
65
65
|
return void 0;
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
|
+
async function readAgentCashSolanaAddress() {
|
|
69
|
+
try {
|
|
70
|
+
const parsed = JSON.parse(await readFile(join(dirname(agentCashWalletPath()), "solana-wallet.json"), "utf8"));
|
|
71
|
+
return typeof parsed.address === "string" && /^[1-9A-HJ-NP-Za-km-z]{32,44}$/.test(parsed.address) ? parsed.address : void 0;
|
|
72
|
+
} catch {
|
|
73
|
+
return void 0;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
68
76
|
async function requireAgentCashWallet() {
|
|
69
77
|
const wallet = await readAgentCashWallet();
|
|
70
78
|
if (!wallet) {
|
|
@@ -80,9 +88,9 @@ var init_agentcash = __esm({
|
|
|
80
88
|
|
|
81
89
|
// ../../packages/core/dist/ledger.js
|
|
82
90
|
import { appendFile, mkdir, readFile as readFile2, writeFile } from "node:fs/promises";
|
|
83
|
-
import { dirname } from "node:path";
|
|
91
|
+
import { dirname as dirname2 } from "node:path";
|
|
84
92
|
async function ensureLedger(path3) {
|
|
85
|
-
await mkdir(
|
|
93
|
+
await mkdir(dirname2(path3), { recursive: true });
|
|
86
94
|
try {
|
|
87
95
|
await readFile2(path3, "utf8");
|
|
88
96
|
} catch (error53) {
|
|
@@ -182,7 +190,7 @@ var init_ledger = __esm({
|
|
|
182
190
|
// ../../packages/core/dist/paths.js
|
|
183
191
|
import { lstat, mkdir as mkdir2, open, rename, rm } from "node:fs/promises";
|
|
184
192
|
import { homedir as homedir2 } from "node:os";
|
|
185
|
-
import { dirname as
|
|
193
|
+
import { dirname as dirname3, isAbsolute, join as join2, relative, resolve, sep } from "node:path";
|
|
186
194
|
import { randomUUID } from "node:crypto";
|
|
187
195
|
function resolveAgentPaths(options = {}) {
|
|
188
196
|
if (options.agentHome) {
|
|
@@ -218,7 +226,7 @@ async function containedPath(root, requested) {
|
|
|
218
226
|
if (error53.code !== "ENOENT")
|
|
219
227
|
throw error53;
|
|
220
228
|
}
|
|
221
|
-
const parent =
|
|
229
|
+
const parent = dirname3(current);
|
|
222
230
|
if (parent === current)
|
|
223
231
|
break;
|
|
224
232
|
current = parent;
|
|
@@ -226,7 +234,7 @@ async function containedPath(root, requested) {
|
|
|
226
234
|
return target;
|
|
227
235
|
}
|
|
228
236
|
async function atomicWrite(path3, content) {
|
|
229
|
-
await mkdir2(
|
|
237
|
+
await mkdir2(dirname3(path3), { recursive: true });
|
|
230
238
|
const temp = `${path3}.${randomUUID()}.tmp`;
|
|
231
239
|
const handle = await open(temp, "wx", 384);
|
|
232
240
|
try {
|
|
@@ -237,7 +245,7 @@ async function atomicWrite(path3, content) {
|
|
|
237
245
|
}
|
|
238
246
|
try {
|
|
239
247
|
await rename(temp, path3);
|
|
240
|
-
const dir = await open(
|
|
248
|
+
const dir = await open(dirname3(path3), "r");
|
|
241
249
|
try {
|
|
242
250
|
await dir.sync();
|
|
243
251
|
} finally {
|
|
@@ -255,10 +263,10 @@ var init_paths = __esm({
|
|
|
255
263
|
|
|
256
264
|
// ../../packages/core/dist/artifacts.js
|
|
257
265
|
import { mkdir as mkdir3, readFile as readFile3 } from "node:fs/promises";
|
|
258
|
-
import { dirname as
|
|
266
|
+
import { dirname as dirname4, join as join3, relative as relative2 } from "node:path";
|
|
259
267
|
async function saveArtifact(state, path3, content, metadata) {
|
|
260
268
|
const target = await safeArtifactPath(state, path3);
|
|
261
|
-
await mkdir3(
|
|
269
|
+
await mkdir3(dirname4(target), { recursive: true });
|
|
262
270
|
await atomicWrite(target, content);
|
|
263
271
|
const rel = relative2(state.sessionDir, target);
|
|
264
272
|
await appendLedgerEntry(state.ledgerPath, {
|
|
@@ -16115,12 +16123,49 @@ var init_spending = __esm({
|
|
|
16115
16123
|
});
|
|
16116
16124
|
|
|
16117
16125
|
// ../../packages/protocol/dist/financial-state.js
|
|
16118
|
-
|
|
16126
|
+
function atomicUsdc(value) {
|
|
16127
|
+
const amount = BigInt(value);
|
|
16128
|
+
return `${amount / 1000000n}.${(amount % 1000000n).toString().padStart(6, "0")}`;
|
|
16129
|
+
}
|
|
16130
|
+
function parseNetworkBalances(raw) {
|
|
16131
|
+
if (!Array.isArray(raw))
|
|
16132
|
+
return void 0;
|
|
16133
|
+
const rows = raw.flatMap((entry) => {
|
|
16134
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
16135
|
+
return [];
|
|
16136
|
+
const row = entry;
|
|
16137
|
+
const balance = decimal(row.balance_usdc) ?? atomic(row.balance_atomic ?? row.balanceAtomic);
|
|
16138
|
+
const reserved = decimal(row.reserved_usdc) ?? atomic(row.reserved_atomic ?? row.reservedAtomic);
|
|
16139
|
+
const available = decimal(row.available_usdc) ?? atomic(row.available_atomic ?? row.availableAtomic);
|
|
16140
|
+
const status = row.balance_status ?? row.status;
|
|
16141
|
+
const parsed = NetworkBalanceSchema.safeParse({
|
|
16142
|
+
network: row.network,
|
|
16143
|
+
...typeof row.caip2 === "string" ? { caip2: row.caip2 } : {},
|
|
16144
|
+
...typeof row.address === "string" || row.address === null ? { address: row.address } : {},
|
|
16145
|
+
balance_status: status === "available" || status === "unavailable" || status === "no_address" ? status : balance ? "available" : "unavailable",
|
|
16146
|
+
balance_usdc: balance ?? null,
|
|
16147
|
+
...reserved ? { reserved_usdc: reserved } : {},
|
|
16148
|
+
...available ? { available_usdc: available } : {}
|
|
16149
|
+
});
|
|
16150
|
+
return parsed.success ? [parsed.data] : [];
|
|
16151
|
+
});
|
|
16152
|
+
return rows.length ? rows : void 0;
|
|
16153
|
+
}
|
|
16154
|
+
var usdc, NetworkBalanceSchema, FinancialStateSchema, atomic, decimal;
|
|
16119
16155
|
var init_financial_state = __esm({
|
|
16120
16156
|
"../../packages/protocol/dist/financial-state.js"() {
|
|
16121
16157
|
"use strict";
|
|
16122
16158
|
init_zod();
|
|
16123
16159
|
usdc = external_exports.string().regex(/^\d+\.\d{6}$/);
|
|
16160
|
+
NetworkBalanceSchema = external_exports.object({
|
|
16161
|
+
network: external_exports.string().min(1).max(40),
|
|
16162
|
+
caip2: external_exports.string().max(100).optional(),
|
|
16163
|
+
address: external_exports.string().max(100).nullable().optional(),
|
|
16164
|
+
balance_status: external_exports.enum(["available", "unavailable", "no_address"]),
|
|
16165
|
+
balance_usdc: usdc.nullable(),
|
|
16166
|
+
reserved_usdc: usdc.optional(),
|
|
16167
|
+
available_usdc: usdc.nullable().optional()
|
|
16168
|
+
});
|
|
16124
16169
|
FinancialStateSchema = external_exports.discriminatedUnion("status", [
|
|
16125
16170
|
external_exports.object({
|
|
16126
16171
|
status: external_exports.literal("available"),
|
|
@@ -16131,7 +16176,8 @@ var init_financial_state = __esm({
|
|
|
16131
16176
|
balance_status: external_exports.enum(["available", "unavailable"]),
|
|
16132
16177
|
balance_usdc: usdc.nullable(),
|
|
16133
16178
|
reserved_usdc: usdc,
|
|
16134
|
-
available_usdc: usdc.nullable()
|
|
16179
|
+
available_usdc: usdc.nullable(),
|
|
16180
|
+
networks: external_exports.array(NetworkBalanceSchema).max(16).optional()
|
|
16135
16181
|
}),
|
|
16136
16182
|
current_run: external_exports.object({
|
|
16137
16183
|
inference_spent_usdc: usdc,
|
|
@@ -16146,6 +16192,8 @@ var init_financial_state = __esm({
|
|
|
16146
16192
|
}),
|
|
16147
16193
|
external_exports.object({ status: external_exports.literal("unavailable"), reason: external_exports.string() })
|
|
16148
16194
|
]);
|
|
16195
|
+
atomic = (value) => typeof value === "string" && /^\d+$/.test(value) ? atomicUsdc(value) : typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? atomicUsdc(BigInt(value)) : void 0;
|
|
16196
|
+
decimal = (value) => typeof value === "string" && /^\d+\.\d{6}$/.test(value) ? value : void 0;
|
|
16149
16197
|
}
|
|
16150
16198
|
});
|
|
16151
16199
|
|
|
@@ -16316,12 +16364,12 @@ async function reserveBudget(state, amountCents, action) {
|
|
|
16316
16364
|
assertCents(amountCents, "reservation");
|
|
16317
16365
|
if (state.query) {
|
|
16318
16366
|
const committed = state.spentCents - state.query.startSpentCents + state.reservedCents;
|
|
16319
|
-
const
|
|
16367
|
+
const atomic2 = (cents) => String(Math.round(cents * 1e4));
|
|
16320
16368
|
const check3 = spendingDecision({
|
|
16321
|
-
amount:
|
|
16322
|
-
perCall:
|
|
16323
|
-
queryLimit:
|
|
16324
|
-
queryCommitted:
|
|
16369
|
+
amount: atomic2(amountCents),
|
|
16370
|
+
perCall: atomic2(state.perCallCents ?? 100),
|
|
16371
|
+
queryLimit: atomic2(state.query.limitCents),
|
|
16372
|
+
queryCommitted: atomic2(committed)
|
|
16325
16373
|
});
|
|
16326
16374
|
const id = createHash("sha256").update(JSON.stringify([state.query.id, action?.identity ?? "call", amountCents])).digest("hex");
|
|
16327
16375
|
const approved = state.query.approved?.[id] !== void 0 && state.query.approved[id] >= amountCents;
|
|
@@ -16412,7 +16460,7 @@ var init_budget = __esm({
|
|
|
16412
16460
|
|
|
16413
16461
|
// ../../packages/core/dist/config.js
|
|
16414
16462
|
import { mkdir as mkdir5, readFile as readFile5 } from "node:fs/promises";
|
|
16415
|
-
import { dirname as
|
|
16463
|
+
import { dirname as dirname5, join as join5 } from "node:path";
|
|
16416
16464
|
function configDir(paths2) {
|
|
16417
16465
|
return (paths2 ?? resolveAgentPaths()).config;
|
|
16418
16466
|
}
|
|
@@ -16431,7 +16479,7 @@ async function loadConfig(paths2) {
|
|
|
16431
16479
|
}
|
|
16432
16480
|
}
|
|
16433
16481
|
async function saveConfig(config4, paths2) {
|
|
16434
|
-
await mkdir5(
|
|
16482
|
+
await mkdir5(dirname5(configPath(paths2)), { recursive: true });
|
|
16435
16483
|
await atomicWrite(configPath(paths2), `${JSON.stringify(config4, null, 2)}
|
|
16436
16484
|
`);
|
|
16437
16485
|
}
|
|
@@ -16447,7 +16495,7 @@ function normalizeConfig(value) {
|
|
|
16447
16495
|
const proxyDefaults = providerDefaults(raw["openrouter-x402-proxy"] ?? raw.x402, DEFAULT_CONFIG["openrouter-x402-proxy"]);
|
|
16448
16496
|
const mcpServers = recordValue(raw.mcpServers);
|
|
16449
16497
|
const servers = { ...DEFAULT_CONFIG.mcpServers, ...mcpServers };
|
|
16450
|
-
if (servers.crowdcode?.command === "npx" && ["0.5", "0.5.2", "0.5.3", "0.6.0"].some((version6) => JSON.stringify(servers.crowdcode.args) === JSON.stringify(["--yes", `crowdcode-mcp@${version6}`]))) {
|
|
16498
|
+
if (servers.crowdcode?.command === "npx" && ["0.5", "0.5.2", "0.5.3", "0.6.0", "0.7.0"].some((version6) => JSON.stringify(servers.crowdcode.args) === JSON.stringify(["--yes", `crowdcode-mcp@${version6}`]))) {
|
|
16451
16499
|
servers.crowdcode = { ...servers.crowdcode, args: [...DEFAULT_CONFIG.mcpServers.crowdcode.args] };
|
|
16452
16500
|
}
|
|
16453
16501
|
return {
|
|
@@ -16471,6 +16519,8 @@ function parsePaymentNetwork(value) {
|
|
|
16471
16519
|
const normalized = typeof value === "string" ? value.trim().toLowerCase() : void 0;
|
|
16472
16520
|
if (normalized === "monad" || normalized === "eip155:143")
|
|
16473
16521
|
return "monad";
|
|
16522
|
+
if (normalized === "solana" || normalized === "solana:5eykt4usfv8p8njdtrepy1vzqkqzkvdp")
|
|
16523
|
+
return "solana";
|
|
16474
16524
|
if (normalized === "base" || normalized === "eip155:8453")
|
|
16475
16525
|
return "base";
|
|
16476
16526
|
return void 0;
|
|
@@ -16480,7 +16530,7 @@ function resolvePaymentNetwork(config4) {
|
|
|
16480
16530
|
if (env !== void 0 && env.trim() !== "") {
|
|
16481
16531
|
const parsed = parsePaymentNetwork(env);
|
|
16482
16532
|
if (!parsed)
|
|
16483
|
-
throw new Error(
|
|
16533
|
+
throw new Error(`OPENCROWD_PAYMENT_NETWORK must be ${PAYMENT_NETWORKS.join(", ")}`);
|
|
16484
16534
|
return parsed;
|
|
16485
16535
|
}
|
|
16486
16536
|
return config4?.paymentNetwork ?? DEFAULT_CONFIG.paymentNetwork;
|
|
@@ -16506,17 +16556,18 @@ function stringValue(value) {
|
|
|
16506
16556
|
function numberValue(value) {
|
|
16507
16557
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
16508
16558
|
}
|
|
16509
|
-
var DEFAULT_CONFIG;
|
|
16559
|
+
var PAYMENT_NETWORKS, DEFAULT_CONFIG;
|
|
16510
16560
|
var init_config = __esm({
|
|
16511
16561
|
"../../packages/core/dist/config.js"() {
|
|
16512
16562
|
"use strict";
|
|
16513
16563
|
init_dist();
|
|
16514
16564
|
init_paths();
|
|
16565
|
+
PAYMENT_NETWORKS = ["base", "solana", "monad"];
|
|
16515
16566
|
DEFAULT_CONFIG = {
|
|
16516
16567
|
configVersion: 3,
|
|
16517
16568
|
mcpServers: {
|
|
16518
16569
|
agentcash: { command: "npx", args: ["--yes", "agentcash@0.17"] },
|
|
16519
|
-
crowdcode: { command: "npx", args: ["--yes", "crowdcode-mcp@0.
|
|
16570
|
+
crowdcode: { command: "npx", args: ["--yes", "crowdcode-mcp@0.8.0"] }
|
|
16520
16571
|
},
|
|
16521
16572
|
// GAIA provider benchmark (2026-08-25): same-model BlockRun matched the
|
|
16522
16573
|
// current route's accuracy and completed the sample 6.7x faster. The
|
|
@@ -16544,7 +16595,7 @@ var init_config = __esm({
|
|
|
16544
16595
|
|
|
16545
16596
|
// ../../packages/core/dist/conversation.js
|
|
16546
16597
|
import { appendFile as appendFile2, mkdir as mkdir6, readFile as readFile6, writeFile as writeFile2 } from "node:fs/promises";
|
|
16547
|
-
import { dirname as
|
|
16598
|
+
import { dirname as dirname6, join as join6 } from "node:path";
|
|
16548
16599
|
function conversationPath(session) {
|
|
16549
16600
|
return join6(session.sessionDir, CONVERSATION_FILE);
|
|
16550
16601
|
}
|
|
@@ -16557,7 +16608,7 @@ async function appendConversationMessage(session, message) {
|
|
|
16557
16608
|
}
|
|
16558
16609
|
async function appendConversationEntry(session, entry) {
|
|
16559
16610
|
const path3 = conversationPath(session);
|
|
16560
|
-
await mkdir6(
|
|
16611
|
+
await mkdir6(dirname6(path3), { recursive: true });
|
|
16561
16612
|
await appendFile2(path3, `${JSON.stringify(entry)}
|
|
16562
16613
|
`, "utf8");
|
|
16563
16614
|
}
|
|
@@ -16600,7 +16651,7 @@ async function clearConversation(session) {
|
|
|
16600
16651
|
}
|
|
16601
16652
|
const archivePath = join6("context", `cleared-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}.jsonl`);
|
|
16602
16653
|
const absoluteArchivePath = join6(session.sessionDir, archivePath);
|
|
16603
|
-
await mkdir6(
|
|
16654
|
+
await mkdir6(dirname6(absoluteArchivePath), { recursive: true });
|
|
16604
16655
|
await writeFile2(absoluteArchivePath, messages.map((message) => `${JSON.stringify({ timestamp: (/* @__PURE__ */ new Date()).toISOString(), message })}
|
|
16605
16656
|
`).join(""), "utf8");
|
|
16606
16657
|
await writeFile2(conversationPath(session), `${JSON.stringify({ type: "clear", timestamp: (/* @__PURE__ */ new Date()).toISOString(), archive_path: archivePath })}
|
|
@@ -17021,9 +17072,17 @@ async function executeTool(name, args, context) {
|
|
|
17021
17072
|
return ok({ content: await readArtifact(context.session, requiredString(args.path, "path")) });
|
|
17022
17073
|
case "list_files":
|
|
17023
17074
|
return ok(await listArtifacts(context.session, optionalString(args.prefix, "prefix") ?? ""));
|
|
17024
|
-
case "run_shell":
|
|
17075
|
+
case "run_shell": {
|
|
17025
17076
|
context.onProgress?.({ type: "running_shell", message: "Running gated shell command" });
|
|
17026
|
-
|
|
17077
|
+
const result = await runShell(context.session, requiredString(args.command, "command"), optionalString(args.cwd, "cwd") ?? context.session.workspaceRoot, shellTimeoutMs(args.timeout_ms), { signal: context.signal });
|
|
17078
|
+
if (result.timed_out || result.exit_code !== 0)
|
|
17079
|
+
return {
|
|
17080
|
+
ok: false,
|
|
17081
|
+
error: result.timed_out ? "Shell command timed out; inspect partial output before retrying." : result.exit_code === null ? "Shell command was terminated; inspect stderr and resource limits before retrying." : `Shell command exited with code ${result.exit_code}; inspect stderr and partial output before choosing the next approach.`,
|
|
17082
|
+
data: result
|
|
17083
|
+
};
|
|
17084
|
+
return ok(result);
|
|
17085
|
+
}
|
|
17027
17086
|
case "spawn_subagent":
|
|
17028
17087
|
case "check_subagents":
|
|
17029
17088
|
return {
|
|
@@ -46189,7 +46248,7 @@ async function getCallsStatus(client, parameters) {
|
|
|
46189
46248
|
params: [id]
|
|
46190
46249
|
});
|
|
46191
46250
|
}
|
|
46192
|
-
const { atomic = false, chainId, receipts, version: version6 = "2.0.0", ...response } = await getStatus(parameters.id);
|
|
46251
|
+
const { atomic: atomic2 = false, chainId, receipts, version: version6 = "2.0.0", ...response } = await getStatus(parameters.id);
|
|
46193
46252
|
const [status, statusCode] = (() => {
|
|
46194
46253
|
const statusCode2 = response.status;
|
|
46195
46254
|
if (statusCode2 >= 100 && statusCode2 < 200)
|
|
@@ -46206,7 +46265,7 @@ async function getCallsStatus(client, parameters) {
|
|
|
46206
46265
|
})();
|
|
46207
46266
|
return {
|
|
46208
46267
|
...response,
|
|
46209
|
-
atomic,
|
|
46268
|
+
atomic: atomic2,
|
|
46210
46269
|
// @ts-expect-error: for backwards compatibility
|
|
46211
46270
|
chainId: chainId ? hexToNumber(chainId) : void 0,
|
|
46212
46271
|
receipts: receipts?.map((receipt) => ({
|
|
@@ -56964,23 +57023,123 @@ var init_monad = __esm({
|
|
|
56964
57023
|
}
|
|
56965
57024
|
});
|
|
56966
57025
|
|
|
57026
|
+
// ../../packages/economy/dist/offers.js
|
|
57027
|
+
function localRails(preferred = "base") {
|
|
57028
|
+
return preferred === "monad" ? ["x402-base", "x402-solana", "mppx", "x402-monad"] : ["x402-base", "x402-solana", "mppx"];
|
|
57029
|
+
}
|
|
57030
|
+
function describeRails(rails) {
|
|
57031
|
+
const labels = rails.filter((rail) => rail !== "unsupported").map((rail) => NETWORK_LABEL[RAIL_NETWORK[rail]]);
|
|
57032
|
+
return labels.length > 1 ? `${labels.slice(0, -1).join(", ")} or ${labels.at(-1)}` : labels[0] ?? "nothing";
|
|
57033
|
+
}
|
|
57034
|
+
function networkLabel(offer) {
|
|
57035
|
+
if (!offer.network_name)
|
|
57036
|
+
return `${offer.protocol} on ${offer.network || "an unknown network"}`;
|
|
57037
|
+
return offer.rail === "unsupported" ? `${offer.protocol} on ${offer.network_name} (unsupported token or scheme)` : NETWORK_LABEL[offer.network_name];
|
|
57038
|
+
}
|
|
57039
|
+
function networkName(value) {
|
|
57040
|
+
const network = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
57041
|
+
if (network === BASE_NETWORK || network === "base")
|
|
57042
|
+
return "base";
|
|
57043
|
+
if (network === SOLANA_NETWORK.toLowerCase() || network === "solana" || network === "solana:mainnet")
|
|
57044
|
+
return "solana";
|
|
57045
|
+
if (network === TEMPO_NETWORK || network === "tempo" || network === "tempo:4217" || network === "tempo:mainnet")
|
|
57046
|
+
return "tempo";
|
|
57047
|
+
if (network === MONAD_NETWORK || network === "monad")
|
|
57048
|
+
return "monad";
|
|
57049
|
+
return void 0;
|
|
57050
|
+
}
|
|
57051
|
+
function railForNetwork(value) {
|
|
57052
|
+
const name = networkName(value);
|
|
57053
|
+
return name ? NETWORK_RAIL[name] : void 0;
|
|
57054
|
+
}
|
|
57055
|
+
function classifyOffer(option) {
|
|
57056
|
+
const protocol = option?.protocol === "mpp" ? "mpp" : "x402";
|
|
57057
|
+
const network = String(option?.network ?? "");
|
|
57058
|
+
const name = networkName(network);
|
|
57059
|
+
const asset = String(option?.asset ?? "");
|
|
57060
|
+
const atomic2 = Number(option?.amount ?? option?.maxAmountRequired);
|
|
57061
|
+
const decimals = typeof option?.decimals === "number" ? option.decimals : 6;
|
|
57062
|
+
const price_usd = Number.isFinite(atomic2) && atomic2 >= 0 ? atomic2 / 10 ** decimals : void 0;
|
|
57063
|
+
const scheme = option?.scheme;
|
|
57064
|
+
let rail = "unsupported";
|
|
57065
|
+
if (protocol === "x402" && name === "base" && asset.toLowerCase() === BASE_USDC)
|
|
57066
|
+
rail = "x402-base";
|
|
57067
|
+
else if (protocol === "x402" && name === "solana" && asset === SOLANA_USDC && (scheme === void 0 || scheme === "exact"))
|
|
57068
|
+
rail = "x402-solana";
|
|
57069
|
+
else if (protocol === "x402" && name === "monad" && asset.toLowerCase() === MONAD_USDC.toLowerCase() && (scheme === void 0 || scheme === "exact"))
|
|
57070
|
+
rail = "x402-monad";
|
|
57071
|
+
else if (protocol === "mpp" && name === "tempo" && asset.toLowerCase() === TEMPO_USDC && (option.paymentMethod === void 0 || option.paymentMethod === "tempo") && (option.intent === void 0 || option.intent === "charge"))
|
|
57072
|
+
rail = "mppx";
|
|
57073
|
+
return {
|
|
57074
|
+
network,
|
|
57075
|
+
...name ? { network_name: name } : {},
|
|
57076
|
+
protocol,
|
|
57077
|
+
rail,
|
|
57078
|
+
...price_usd !== void 0 ? { price_usd } : {},
|
|
57079
|
+
...typeof option?.payTo === "string" ? { pay_to: option.payTo } : {}
|
|
57080
|
+
};
|
|
57081
|
+
}
|
|
57082
|
+
function selectOffer(offers, selection) {
|
|
57083
|
+
const preferred = selection.preferred ?? "base";
|
|
57084
|
+
const payable = offers.filter((offer) => offer.rail !== "unsupported" && selection.rails.includes(offer.rail));
|
|
57085
|
+
const cheapest = (name) => payable.filter((offer) => offer.network_name === name).sort((a, b) => (a.price_usd ?? Infinity) - (b.price_usd ?? Infinity))[0];
|
|
57086
|
+
const order = [preferred, ...FALLBACK_ORDER.filter((name) => name !== preferred)];
|
|
57087
|
+
const first = cheapest(preferred);
|
|
57088
|
+
if (first)
|
|
57089
|
+
return first;
|
|
57090
|
+
const candidates = order.map(cheapest).filter((offer) => offer !== void 0);
|
|
57091
|
+
const balances = selection.balances;
|
|
57092
|
+
return balances && candidates.find((offer) => (balances[offer.network_name] ?? 0) >= (offer.price_usd ?? 0)) || candidates[0];
|
|
57093
|
+
}
|
|
57094
|
+
function payableNetworks(offers, rails) {
|
|
57095
|
+
return [...new Set(offers.filter((offer) => offer.rail !== "unsupported" && rails.includes(offer.rail)).map((offer) => offer.network_name))];
|
|
57096
|
+
}
|
|
57097
|
+
var BASE_NETWORK, BASE_USDC, SOLANA_NETWORK, SOLANA_USDC, TEMPO_NETWORK, TEMPO_USDC, RAIL_NETWORK, NETWORK_CAIP2, NETWORK_RAIL, NETWORK_LABEL, FALLBACK_ORDER, HOSTED_RAILS;
|
|
57098
|
+
var init_offers = __esm({
|
|
57099
|
+
"../../packages/economy/dist/offers.js"() {
|
|
57100
|
+
"use strict";
|
|
57101
|
+
init_monad();
|
|
57102
|
+
BASE_NETWORK = "eip155:8453";
|
|
57103
|
+
BASE_USDC = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
57104
|
+
SOLANA_NETWORK = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
|
|
57105
|
+
SOLANA_USDC = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
|
|
57106
|
+
TEMPO_NETWORK = "eip155:4217";
|
|
57107
|
+
TEMPO_USDC = "0x20c000000000000000000000b9537d11c60e8b50";
|
|
57108
|
+
RAIL_NETWORK = {
|
|
57109
|
+
"x402-base": "base",
|
|
57110
|
+
"x402-solana": "solana",
|
|
57111
|
+
"x402-monad": "monad",
|
|
57112
|
+
mppx: "tempo"
|
|
57113
|
+
};
|
|
57114
|
+
NETWORK_CAIP2 = { base: BASE_NETWORK, solana: SOLANA_NETWORK, tempo: TEMPO_NETWORK, monad: MONAD_NETWORK };
|
|
57115
|
+
NETWORK_RAIL = { base: "x402-base", solana: "x402-solana", monad: "x402-monad", tempo: "mppx" };
|
|
57116
|
+
NETWORK_LABEL = {
|
|
57117
|
+
base: "x402 USDC on Base",
|
|
57118
|
+
solana: "x402 USDC on Solana",
|
|
57119
|
+
tempo: "MPP USDC.e on Tempo",
|
|
57120
|
+
monad: "x402 USDC on Monad"
|
|
57121
|
+
};
|
|
57122
|
+
FALLBACK_ORDER = ["base", "solana", "tempo", "monad"];
|
|
57123
|
+
HOSTED_RAILS = ["x402-base", "x402-solana", "mppx"];
|
|
57124
|
+
}
|
|
57125
|
+
});
|
|
57126
|
+
|
|
56967
57127
|
// ../../packages/economy/dist/discovery.js
|
|
56968
|
-
var
|
|
57128
|
+
var BaseServiceDiscovery;
|
|
56969
57129
|
var init_discovery = __esm({
|
|
56970
57130
|
"../../packages/economy/dist/discovery.js"() {
|
|
56971
57131
|
"use strict";
|
|
56972
57132
|
init_dist3();
|
|
56973
|
-
|
|
56974
|
-
BASE_USDC = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
56975
|
-
BASE_NETWORK = "eip155:8453";
|
|
56976
|
-
isBaseOffer = (offer) => offer?.protocol === "x402" && [BASE_NETWORK, "base"].includes(offer.network) && String(offer.asset).toLowerCase() === BASE_USDC;
|
|
57133
|
+
init_offers();
|
|
56977
57134
|
BaseServiceDiscovery = class {
|
|
56978
57135
|
searchApi;
|
|
56979
57136
|
options;
|
|
56980
57137
|
cache = /* @__PURE__ */ new Map();
|
|
57138
|
+
rails;
|
|
56981
57139
|
constructor(searchApi, options = {}) {
|
|
56982
57140
|
this.searchApi = searchApi;
|
|
56983
57141
|
this.options = options;
|
|
57142
|
+
this.rails = options.rails ?? localRails(options.paymentNetwork);
|
|
56984
57143
|
}
|
|
56985
57144
|
async inspect(input2) {
|
|
56986
57145
|
const key = `${input2.method ?? "POST"} ${input2.url}`;
|
|
@@ -56998,26 +57157,55 @@ var init_discovery = __esm({
|
|
|
56998
57157
|
const advisory = result.advisories.find((a) => a.method === (input2.method ?? "POST").toUpperCase());
|
|
56999
57158
|
if (!advisory)
|
|
57000
57159
|
return { ok: false, error: "The endpoint does not advertise this method" };
|
|
57001
|
-
const
|
|
57002
|
-
const offer =
|
|
57160
|
+
const offers = (advisory.paymentOptions ?? []).map((option) => classifyOffer(option));
|
|
57161
|
+
const offer = await this.select(offers);
|
|
57162
|
+
const payable = offers.filter((candidate) => candidate.rail !== "unsupported" && this.rails.includes(candidate.rail));
|
|
57163
|
+
const ceiling = this.options.negotiated && offer ? Math.max(...payable.map((candidate) => candidate.price_usd ?? 0)) : offer?.price_usd;
|
|
57003
57164
|
const read = ["siwx", "unprotected"].includes(advisory.authMode ?? "");
|
|
57004
57165
|
const data = {
|
|
57005
57166
|
endpoint: input2.url,
|
|
57006
57167
|
method: advisory.method,
|
|
57007
|
-
rail:
|
|
57168
|
+
rail: offer ? offer.rail : read ? "x402-base" : "unsupported",
|
|
57008
57169
|
payable: !!offer,
|
|
57009
57170
|
authMode: advisory.authMode,
|
|
57010
|
-
network:
|
|
57011
|
-
price_usd: offer ?
|
|
57171
|
+
network: offer?.network_name ? NETWORK_CAIP2[offer.network_name] : void 0,
|
|
57172
|
+
price_usd: offer ? ceiling ?? 0 : read ? 0 : void 0,
|
|
57173
|
+
...offers.length ? { offers: offers.map((candidate) => ({
|
|
57174
|
+
network: candidate.network_name ?? candidate.network,
|
|
57175
|
+
protocol: candidate.protocol,
|
|
57176
|
+
price_usd: candidate.price_usd,
|
|
57177
|
+
payable: payable.includes(candidate)
|
|
57178
|
+
})) } : {},
|
|
57012
57179
|
input_schema: advisory.inputSchema,
|
|
57013
57180
|
output_schema: advisory.outputSchema,
|
|
57014
57181
|
description: advisory.summary,
|
|
57015
|
-
note: read ? "Read with read_service; wallet authentication is automatic. Never resubmit a pending generation job." :
|
|
57182
|
+
note: read ? "Read with read_service; wallet authentication is automatic. Never resubmit a pending generation job." : this.note(offers, offer)
|
|
57016
57183
|
};
|
|
57017
57184
|
if (input2.body === void 0)
|
|
57018
57185
|
this.cache.set(key, { until: Date.now() + 6e4, data });
|
|
57019
57186
|
return { ok: true, data };
|
|
57020
57187
|
}
|
|
57188
|
+
/** Balances are read only when they can change the choice: the preferred network is absent and several are payable. */
|
|
57189
|
+
async select(offers) {
|
|
57190
|
+
const selection = { preferred: this.options.paymentNetwork, rails: this.rails };
|
|
57191
|
+
const networks = payableNetworks(offers, this.rails);
|
|
57192
|
+
const needsBalances = !this.options.negotiated && this.options.balances && networks.length > 1 && !networks.includes(this.options.paymentNetwork ?? "base");
|
|
57193
|
+
const balances = needsBalances ? await this.options.balances().catch(() => void 0) : void 0;
|
|
57194
|
+
return selectOffer(offers, { ...selection, balances });
|
|
57195
|
+
}
|
|
57196
|
+
note(offers, offer) {
|
|
57197
|
+
const quote = "Inspect with sample_body for the exact quote.";
|
|
57198
|
+
if (!offer) {
|
|
57199
|
+
const offered = [...new Set(offers.map(networkLabel))];
|
|
57200
|
+
return `${offered.length ? `This service offers ${offered.join(", ")}` : "This service advertises no recognised payment option"}; payable here: ${describeRails(this.rails)}. ${quote}`;
|
|
57201
|
+
}
|
|
57202
|
+
if (this.options.negotiated) {
|
|
57203
|
+
const networks = payableNetworks(offers, this.rails).map((name) => networkLabel({ ...offer, network_name: name, rail: "x402-base" }));
|
|
57204
|
+
return `The hosted gateway pays the cheapest of ${networks.join(", ")} that your balance on that network covers; price_usd is the ceiling across them. ${quote}`;
|
|
57205
|
+
}
|
|
57206
|
+
const preferred = this.options.paymentNetwork ?? "base";
|
|
57207
|
+
return `Pays ${networkLabel(offer)}${offer.network_name === preferred ? "" : ` (${preferred} is not offered)`}. ${quote}`;
|
|
57208
|
+
}
|
|
57021
57209
|
async verified(candidates, limit) {
|
|
57022
57210
|
const services = [];
|
|
57023
57211
|
for (let i = 0; i < candidates.length && services.length < limit; i += 4) {
|
|
@@ -57031,7 +57219,7 @@ var init_discovery = __esm({
|
|
|
57031
57219
|
method: c.method ?? "POST",
|
|
57032
57220
|
name: c.summary ?? c.name,
|
|
57033
57221
|
price_usd: schema.price_usd,
|
|
57034
|
-
payment_provider: "x402",
|
|
57222
|
+
payment_provider: schema.rail === "mppx" ? "mppx" : "x402",
|
|
57035
57223
|
network: schema.network ?? BASE_NETWORK,
|
|
57036
57224
|
payable: true
|
|
57037
57225
|
} : void 0;
|
|
@@ -57053,14 +57241,14 @@ var init_discovery = __esm({
|
|
|
57053
57241
|
const candidates = Array.isArray(body?.results) ? body.results : Array.isArray(body?.services) ? body.services : [];
|
|
57054
57242
|
return { ok: true, data: {
|
|
57055
57243
|
services: await this.verified(candidates, limit),
|
|
57056
|
-
note: `AgentCash discovery, verified
|
|
57244
|
+
note: `AgentCash discovery, verified ${describeRails(this.rails)}. New/unreviewed services are allowed. Inspect the chosen endpoint before paying.`
|
|
57057
57245
|
} };
|
|
57058
57246
|
}
|
|
57059
57247
|
async discoverEndpoints(origin) {
|
|
57060
57248
|
const result = await discoverOriginSchema({ target: origin, signal: AbortSignal.timeout(1e4) });
|
|
57061
57249
|
if (!result.found)
|
|
57062
57250
|
return { ok: false, error: result.message ?? "Provider discovery failed" };
|
|
57063
|
-
const candidates = result.endpoints.filter((e6) => e6.protocols?.
|
|
57251
|
+
const candidates = result.endpoints.filter((e6) => e6.protocols?.some((protocol) => protocol === "x402" || protocol === "mpp")).map((e6) => ({ ...e6, origin: result.origin }));
|
|
57064
57252
|
return { ok: true, data: {
|
|
57065
57253
|
services: await this.verified(candidates, 50),
|
|
57066
57254
|
guidance: result.guidance,
|
|
@@ -57154,15 +57342,32 @@ function parsePaymentEvidence(record3, requestedRail) {
|
|
|
57154
57342
|
}
|
|
57155
57343
|
const network = stringValue2(payment?.network ?? record3.network ?? receipt?.network)?.toLowerCase();
|
|
57156
57344
|
const protocol = stringValue2(payment?.protocol ?? record3.protocol ?? record3.paymentProtocol)?.toLowerCase();
|
|
57157
|
-
const
|
|
57345
|
+
const named = networkName(network);
|
|
57346
|
+
const rail = named === "tempo" || protocol === "mpp" || protocol === "mppx" ? "mppx" : named === "solana" ? "x402-solana" : named === "base" || network === void 0 && protocol === "x402" ? requestedRail === "x402-solana" && named === void 0 ? "x402-solana" : "x402-base" : network === void 0 && protocol === void 0 ? requestedRail : "unsupported";
|
|
57347
|
+
if (rail === "x402-solana" && !reference.startsWith("x402:"))
|
|
57348
|
+
reference = `x402:solana:${reference}`;
|
|
57158
57349
|
return {
|
|
57159
57350
|
paidUsd,
|
|
57160
57351
|
rail,
|
|
57161
57352
|
reference,
|
|
57353
|
+
payer: stringValue2(payment?.payer ?? receipt?.payer),
|
|
57162
57354
|
proof,
|
|
57163
57355
|
payTo: stringValue2(payment?.payTo ?? payment?.pay_to ?? payment?.recipient ?? receipt?.payTo ?? receipt?.pay_to ?? receipt?.recipient ?? receipt?.payee)
|
|
57164
57356
|
};
|
|
57165
57357
|
}
|
|
57358
|
+
function parseWalletAccounts(data) {
|
|
57359
|
+
const record3 = objectValue3(data);
|
|
57360
|
+
const rows = Array.isArray(data) ? data : Array.isArray(record3?.accounts) ? record3.accounts : [];
|
|
57361
|
+
return rows.map(objectValue3).filter((row) => row !== void 0 && stringValue2(row.network) !== void 0).map((row) => {
|
|
57362
|
+
const usdc2 = numberValue2(row.balance ?? row.usdc ?? row.balanceUsd);
|
|
57363
|
+
return {
|
|
57364
|
+
network: stringValue2(row.network),
|
|
57365
|
+
...stringValue2(row.address) ? { address: stringValue2(row.address) } : {},
|
|
57366
|
+
...usdc2 !== void 0 ? { usdc: usdc2 } : {},
|
|
57367
|
+
...stringValue2(row.depositLink) ? { depositLink: stringValue2(row.depositLink) } : {}
|
|
57368
|
+
};
|
|
57369
|
+
});
|
|
57370
|
+
}
|
|
57166
57371
|
function normalizedHeaders(value) {
|
|
57167
57372
|
const headers = objectValue3(value) ?? {};
|
|
57168
57373
|
return Object.fromEntries(Object.entries(headers).map(([key, child]) => [key.toLowerCase(), child]));
|
|
@@ -57207,34 +57412,71 @@ function moneyValue(value) {
|
|
|
57207
57412
|
const cleaned = value.replace(/[$,\s]|usd(c?)/gi, "");
|
|
57208
57413
|
return cleaned === "" ? void 0 : numberValue2(cleaned);
|
|
57209
57414
|
}
|
|
57210
|
-
var McpAgentCashAdapter;
|
|
57415
|
+
var ACCOUNTS_TTL_MS, McpAgentCashAdapter;
|
|
57211
57416
|
var init_agentcash2 = __esm({
|
|
57212
57417
|
"../../packages/economy/dist/agentcash.js"() {
|
|
57213
57418
|
"use strict";
|
|
57214
57419
|
init_discovery();
|
|
57215
57420
|
init_dist2();
|
|
57216
57421
|
init_monad();
|
|
57422
|
+
init_offers();
|
|
57423
|
+
ACCOUNTS_TTL_MS = 3e4;
|
|
57217
57424
|
McpAgentCashAdapter = class {
|
|
57218
57425
|
connection;
|
|
57219
57426
|
options;
|
|
57220
57427
|
discovery;
|
|
57221
57428
|
monad;
|
|
57429
|
+
accountsCache;
|
|
57222
57430
|
constructor(connection, options = {}) {
|
|
57223
57431
|
this.connection = connection;
|
|
57224
57432
|
this.options = options;
|
|
57225
|
-
this.discovery = new BaseServiceDiscovery((query, options2) => this.connection.call("search", { query, ...options2 }), { paymentNetwork: options.paymentNetwork });
|
|
57433
|
+
this.discovery = new BaseServiceDiscovery((query, options2) => this.connection.call("search", { query, ...options2 }), { paymentNetwork: options.paymentNetwork, balances: () => this.networkBalances() });
|
|
57226
57434
|
this.monad = options.monad ?? new MonadX402Payer();
|
|
57227
57435
|
}
|
|
57228
57436
|
read(url3) {
|
|
57229
57437
|
return this.connection.call("fetch", { url: url3, method: "GET", maxAmount: 1e-9, paymentNetwork: "base", paymentProtocol: "x402" });
|
|
57230
57438
|
}
|
|
57231
57439
|
async getBalance() {
|
|
57232
|
-
const [result, monad] = await Promise.all([
|
|
57440
|
+
const [result, monad, accounts] = await Promise.all([
|
|
57441
|
+
this.connection.call("get_balance", {}),
|
|
57442
|
+
this.monadBalance(),
|
|
57443
|
+
this.accounts(true).catch(() => void 0)
|
|
57444
|
+
]);
|
|
57233
57445
|
if (!result.ok)
|
|
57234
57446
|
return { ok: false, data: result.data, error: result.error };
|
|
57235
|
-
const data = result.data && typeof result.data === "object" && !Array.isArray(result.data) ? { ...result.data, monad } : { agentcash: result.data, monad };
|
|
57447
|
+
const data = result.data && typeof result.data === "object" && !Array.isArray(result.data) ? { ...result.data, ...accounts ? { accounts } : {}, monad } : { agentcash: result.data, ...accounts ? { accounts } : {}, monad };
|
|
57236
57448
|
return { ok: true, data };
|
|
57237
57449
|
}
|
|
57450
|
+
/** AgentCash's per-network accounts (`list_accounts`), briefly cached for offer selection. */
|
|
57451
|
+
accounts(refresh = false) {
|
|
57452
|
+
if (!refresh && this.accountsCache && this.accountsCache.until > Date.now())
|
|
57453
|
+
return this.accountsCache.accounts;
|
|
57454
|
+
const accounts = this.connection.call("list_accounts", {}).then((result) => {
|
|
57455
|
+
if (!result.ok)
|
|
57456
|
+
throw new Error(result.error ?? "list_accounts failed");
|
|
57457
|
+
return parseWalletAccounts(result.data);
|
|
57458
|
+
});
|
|
57459
|
+
this.accountsCache = { until: Date.now() + ACCOUNTS_TTL_MS, accounts };
|
|
57460
|
+
accounts.catch(() => {
|
|
57461
|
+
this.accountsCache = void 0;
|
|
57462
|
+
});
|
|
57463
|
+
return accounts;
|
|
57464
|
+
}
|
|
57465
|
+
/** Spendable USDC per network, for choosing among a service's offers. */
|
|
57466
|
+
async networkBalances() {
|
|
57467
|
+
const balances = {};
|
|
57468
|
+
for (const account of await this.accounts()) {
|
|
57469
|
+
const name = networkName(account.network);
|
|
57470
|
+
if (name && account.usdc !== void 0)
|
|
57471
|
+
balances[name] = (balances[name] ?? 0) + account.usdc;
|
|
57472
|
+
}
|
|
57473
|
+
if (this.options.paymentNetwork === "monad") {
|
|
57474
|
+
const monad = await this.monadBalance();
|
|
57475
|
+
if (typeof monad.usdc === "number")
|
|
57476
|
+
balances.monad = monad.usdc;
|
|
57477
|
+
}
|
|
57478
|
+
return balances;
|
|
57479
|
+
}
|
|
57238
57480
|
async monadBalance() {
|
|
57239
57481
|
const preferred = this.options.paymentNetwork === "monad";
|
|
57240
57482
|
try {
|
|
@@ -57259,7 +57501,7 @@ var init_agentcash2 = __esm({
|
|
|
57259
57501
|
async fetch(request2) {
|
|
57260
57502
|
if (request2.rail === "x402-monad")
|
|
57261
57503
|
return this.monad.fetch(request2);
|
|
57262
|
-
const railParams = request2.rail === "mppx" ? { paymentNetwork: "tempo", paymentProtocol: "mpp" } : { paymentNetwork: "base", paymentProtocol: "x402" };
|
|
57504
|
+
const railParams = request2.rail === "mppx" ? { paymentNetwork: "tempo", paymentProtocol: "mpp" } : request2.rail === "x402-solana" ? { paymentNetwork: "solana", paymentProtocol: "x402" } : { paymentNetwork: "base", paymentProtocol: "x402" };
|
|
57263
57505
|
const result = await this.connection.call("fetch", {
|
|
57264
57506
|
url: request2.url,
|
|
57265
57507
|
method: request2.method,
|
|
@@ -57289,7 +57531,7 @@ var init_agentcash2 = __esm({
|
|
|
57289
57531
|
|
|
57290
57532
|
// ../../packages/economy/dist/approvals.js
|
|
57291
57533
|
import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile3 } from "node:fs/promises";
|
|
57292
|
-
import { dirname as
|
|
57534
|
+
import { dirname as dirname7, join as join9 } from "node:path";
|
|
57293
57535
|
function isApprovalMode(value) {
|
|
57294
57536
|
return value === "ask" || value === "auto" || value === "off";
|
|
57295
57537
|
}
|
|
@@ -57308,7 +57550,7 @@ async function loadApprovalRules(path3 = approvalRulesPath()) {
|
|
|
57308
57550
|
}
|
|
57309
57551
|
}
|
|
57310
57552
|
async function saveApprovalRules(rules, path3 = approvalRulesPath()) {
|
|
57311
|
-
await mkdir7(
|
|
57553
|
+
await mkdir7(dirname7(path3), { recursive: true });
|
|
57312
57554
|
await writeFile3(path3, `${JSON.stringify({ services: rules }, null, 2)}
|
|
57313
57555
|
`, "utf8");
|
|
57314
57556
|
}
|
|
@@ -57421,6 +57663,8 @@ var init_crowdcode = __esm({
|
|
|
57421
57663
|
...review.paymentProvider ? { payment_provider: review.paymentProvider } : {},
|
|
57422
57664
|
...review.paymentProof ? { payment_proof: review.paymentProof } : {},
|
|
57423
57665
|
...review.paymentTargetRef ? { payment_target_ref: review.paymentTargetRef } : {},
|
|
57666
|
+
...review.payer ? { payer: review.payer } : {},
|
|
57667
|
+
...review.payerSignature ? { payer_signature: review.payerSignature } : {},
|
|
57424
57668
|
...review.taskContext ? { task_context: review.taskContext } : {}
|
|
57425
57669
|
});
|
|
57426
57670
|
const payload = result.data && typeof result.data === "object" ? result.data : {};
|
|
@@ -57433,7 +57677,7 @@ var init_crowdcode = __esm({
|
|
|
57433
57677
|
|
|
57434
57678
|
// ../../packages/economy/dist/crowdcode-preferences.js
|
|
57435
57679
|
import { mkdir as mkdir8, readFile as readFile8, rename as rename2, writeFile as writeFile4 } from "node:fs/promises";
|
|
57436
|
-
import { dirname as
|
|
57680
|
+
import { dirname as dirname8, join as join10 } from "node:path";
|
|
57437
57681
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
57438
57682
|
var CrowdCodePreferences;
|
|
57439
57683
|
var init_crowdcode_preferences = __esm({
|
|
@@ -57464,7 +57708,7 @@ var init_crowdcode_preferences = __esm({
|
|
|
57464
57708
|
}
|
|
57465
57709
|
async write(scope, enabled) {
|
|
57466
57710
|
const path3 = this.path(scope), temporary = `${path3}.${randomUUID4()}.tmp`;
|
|
57467
|
-
await mkdir8(
|
|
57711
|
+
await mkdir8(dirname8(path3), { recursive: true });
|
|
57468
57712
|
await writeFile4(temporary, JSON.stringify({ enabled }) + "\n", { mode: 384 });
|
|
57469
57713
|
await rename2(temporary, path3);
|
|
57470
57714
|
}
|
|
@@ -57510,7 +57754,7 @@ var init_media = __esm({
|
|
|
57510
57754
|
|
|
57511
57755
|
// ../../packages/economy/dist/purchases.js
|
|
57512
57756
|
import { appendFile as appendFile3, mkdir as mkdir9, readFile as readFile9 } from "node:fs/promises";
|
|
57513
|
-
import { dirname as
|
|
57757
|
+
import { dirname as dirname9, join as join11 } from "node:path";
|
|
57514
57758
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
57515
57759
|
function purchasesPath(session) {
|
|
57516
57760
|
return join11(session.sessionDir, "purchases.jsonl");
|
|
@@ -57538,7 +57782,7 @@ async function skipPendingReviews(session) {
|
|
|
57538
57782
|
}
|
|
57539
57783
|
async function appendPurchaseEvent(session, event) {
|
|
57540
57784
|
const path3 = purchasesPath(session);
|
|
57541
|
-
await mkdir9(
|
|
57785
|
+
await mkdir9(dirname9(path3), { recursive: true });
|
|
57542
57786
|
await appendFile3(path3, `${JSON.stringify(event)}
|
|
57543
57787
|
`, "utf8");
|
|
57544
57788
|
}
|
|
@@ -57672,13 +57916,14 @@ function numberArg(value) {
|
|
|
57672
57916
|
function slugUrl(url3) {
|
|
57673
57917
|
return url3.replace(/[^a-z0-9]+/gi, "-").replace(/^-|-$/g, "").slice(0, 80) || "service";
|
|
57674
57918
|
}
|
|
57675
|
-
var GATEWAY_TOOL_NAMES, EconomyGateway, GATEWAY_TOOL_DEFINITIONS;
|
|
57919
|
+
var GATEWAY_TOOL_NAMES, VERIFIED_RAILS, EconomyGateway, GATEWAY_TOOL_DEFINITIONS;
|
|
57676
57920
|
var init_gateway = __esm({
|
|
57677
57921
|
"../../packages/economy/dist/gateway.js"() {
|
|
57678
57922
|
"use strict";
|
|
57679
57923
|
init_crowdcode_preferences();
|
|
57680
57924
|
init_media();
|
|
57681
57925
|
init_dist2();
|
|
57926
|
+
init_offers();
|
|
57682
57927
|
init_approvals();
|
|
57683
57928
|
init_purchases();
|
|
57684
57929
|
GATEWAY_TOOL_NAMES = [
|
|
@@ -57695,6 +57940,7 @@ var init_gateway = __esm({
|
|
|
57695
57940
|
"review_paid_service",
|
|
57696
57941
|
"bridge_usdc"
|
|
57697
57942
|
];
|
|
57943
|
+
VERIFIED_RAILS = ["x402-base", "x402-solana", "x402-monad", "mppx"];
|
|
57698
57944
|
EconomyGateway = class {
|
|
57699
57945
|
options;
|
|
57700
57946
|
/**
|
|
@@ -57888,10 +58134,11 @@ var init_gateway = __esm({
|
|
|
57888
58134
|
if (!inspection) {
|
|
57889
58135
|
return { ok: false, error: `inspect_paid_service must run for ${method} ${endpoint} before call_paid_service` };
|
|
57890
58136
|
}
|
|
57891
|
-
|
|
58137
|
+
const rails = this.options.paymentRails ?? VERIFIED_RAILS;
|
|
58138
|
+
if (!rails.includes(inspection.rail)) {
|
|
57892
58139
|
return {
|
|
57893
58140
|
ok: false,
|
|
57894
|
-
error:
|
|
58141
|
+
error: `this endpoint offers no payment rail this agent can pay automatically (payable: ${describeRails(rails)})`
|
|
57895
58142
|
};
|
|
57896
58143
|
}
|
|
57897
58144
|
const requestedCostCents = intArg(args.max_cost_cents) ?? inspection.priceCeilingCents;
|
|
@@ -57955,7 +58202,7 @@ var init_gateway = __esm({
|
|
|
57955
58202
|
const artifact = result.ambiguityReason === "transport" ? void 0 : await saveArtifact(session, `service-calls/${Date.now()}-${slugUrl(endpoint)}.json`, JSON.stringify({ status: result.status, body: result.data }, null, 2), { endpoint, method });
|
|
57956
58203
|
const purchaseId = newPurchaseId();
|
|
57957
58204
|
const railUsed = result.payment?.rail ?? inspection.rail;
|
|
57958
|
-
const supportedRail = railUsed
|
|
58205
|
+
const supportedRail = VERIFIED_RAILS.includes(railUsed);
|
|
57959
58206
|
const record3 = {
|
|
57960
58207
|
purchase_id: purchaseId,
|
|
57961
58208
|
session_id: session.sessionId,
|
|
@@ -58119,6 +58366,8 @@ var init_gateway = __esm({
|
|
|
58119
58366
|
paymentProvider: evidence?.reference ? state.record.rail === "mppx" ? "mppx" : "x402" : void 0,
|
|
58120
58367
|
paymentProof: evidence?.proof,
|
|
58121
58368
|
paymentTargetRef: evidence?.reference ? evidence.payTo : void 0,
|
|
58369
|
+
// Solana pays from a different address than the EVM reviewer key.
|
|
58370
|
+
...state.record.rail === "x402-solana" && evidence?.payer ? { payer: evidence.payer } : {},
|
|
58122
58371
|
taskContext: stringArg(args.task_context)
|
|
58123
58372
|
});
|
|
58124
58373
|
if (!result.ok) {
|
|
@@ -58528,6 +58777,7 @@ var init_dist4 = __esm({
|
|
|
58528
58777
|
init_purchases();
|
|
58529
58778
|
init_runtime();
|
|
58530
58779
|
init_discovery();
|
|
58780
|
+
init_offers();
|
|
58531
58781
|
}
|
|
58532
58782
|
});
|
|
58533
58783
|
|
|
@@ -58660,10 +58910,10 @@ var init_context2 = __esm({
|
|
|
58660
58910
|
|
|
58661
58911
|
// ../../packages/agent-runtime/dist/knowledge.js
|
|
58662
58912
|
import { access, cp, mkdir as mkdir10, readFile as readFile11, writeFile as writeFile6 } from "node:fs/promises";
|
|
58663
|
-
import { dirname as
|
|
58913
|
+
import { dirname as dirname10, join as join14, resolve as resolve4 } from "node:path";
|
|
58664
58914
|
import { fileURLToPath } from "node:url";
|
|
58665
58915
|
function bundledKnowledgeDir() {
|
|
58666
|
-
return resolve4(
|
|
58916
|
+
return resolve4(dirname10(fileURLToPath(import.meta.url)), "..", "knowledge");
|
|
58667
58917
|
}
|
|
58668
58918
|
function knowledgeDisabledByEnv() {
|
|
58669
58919
|
const value = process.env.OPENCROWD_KNOWLEDGE_DIR?.trim().toLowerCase();
|
|
@@ -80681,9 +80931,12 @@ function rejectedRequest(status, text) {
|
|
|
80681
80931
|
async function readHostedFinancialState(options) {
|
|
80682
80932
|
try {
|
|
80683
80933
|
const reply = await postHostedTool(options, "economy.balance", {}, { timeoutMs: 1e4 });
|
|
80684
|
-
const
|
|
80685
|
-
|
|
80686
|
-
|
|
80934
|
+
const data = reply.data;
|
|
80935
|
+
const parsed = FinancialStateSchema.safeParse(data?.financial_state);
|
|
80936
|
+
if (reply.ok && parsed.success && parsed.data.status === "available" && parsed.data.run_id === options.runId) {
|
|
80937
|
+
const networks = parsed.data.wallet.networks ?? parseNetworkBalances(data?.networks);
|
|
80938
|
+
return networks ? { ...parsed.data, wallet: { ...parsed.data.wallet, networks } } : parsed.data;
|
|
80939
|
+
}
|
|
80687
80940
|
} catch {
|
|
80688
80941
|
}
|
|
80689
80942
|
return { status: "unavailable", reason: "Hosted financial state could not be read. Do not infer balance or spending from the local session budget." };
|
|
@@ -80801,13 +81054,14 @@ function createHostedEconomy(options) {
|
|
|
80801
81054
|
approvalMode: "auto",
|
|
80802
81055
|
hostedSpending: true,
|
|
80803
81056
|
minServiceScore: 2,
|
|
81057
|
+
paymentRails: HOSTED_RAILS,
|
|
80804
81058
|
// Hosted rules live with the agent's session, never in a user config dir.
|
|
80805
81059
|
approvalRulesPath: join20(options.session.sessionDir, "approval-rules.json")
|
|
80806
81060
|
});
|
|
80807
81061
|
}
|
|
80808
81062
|
function hostedDynamicTools(economy) {
|
|
80809
81063
|
const tools = economyTools(economy, { hidden: HIDDEN_HOSTED_TOOLS });
|
|
80810
|
-
return { ...tools, definitions: tools.definitions.map((tool) => tool.name === "get_wallet_status" ? { ...tool, description: "Read this hosted agent's USDC wallet
|
|
81064
|
+
return { ...tools, definitions: tools.definitions.map((tool) => tool.name === "get_wallet_status" ? { ...tool, description: "Read this hosted agent's USDC wallet balances (per network when reported: Base, Solana, Tempo) and authoritative current-run inference spending, service spending, payment holds and authorized budget. A payment on a network needs that network's balance. Read-only." } : tool) };
|
|
80811
81065
|
}
|
|
80812
81066
|
function parseListedService(raw) {
|
|
80813
81067
|
const row = objectValue5(raw);
|
|
@@ -80937,8 +81191,6 @@ var init_hosted_economy = __esm({
|
|
|
80937
81191
|
socket;
|
|
80938
81192
|
fetcher;
|
|
80939
81193
|
reconcileDelayMs;
|
|
80940
|
-
/** Rails observed by inspection; `fetch` refuses anything but Base x402 regardless of the caller's rail. */
|
|
80941
|
-
inspectedRails = /* @__PURE__ */ new Map();
|
|
80942
81194
|
constructor(directory, socket, fetcher, reconcileDelayMs = RECONCILE_DELAY_MS) {
|
|
80943
81195
|
this.directory = directory;
|
|
80944
81196
|
this.socket = socket;
|
|
@@ -80954,7 +81206,7 @@ var init_hosted_economy = __esm({
|
|
|
80954
81206
|
if (!reply.ok || result?.status !== 200)
|
|
80955
81207
|
return { ok: false, error: reply.error ?? "AgentCash search unavailable" };
|
|
80956
81208
|
return { ok: true, data: JSON.parse(result.body) };
|
|
80957
|
-
});
|
|
81209
|
+
}, { rails: HOSTED_RAILS, negotiated: true });
|
|
80958
81210
|
}
|
|
80959
81211
|
discovery;
|
|
80960
81212
|
async read(url3) {
|
|
@@ -80987,15 +81239,8 @@ var init_hosted_economy = __esm({
|
|
|
80987
81239
|
}
|
|
80988
81240
|
async fetch(request2) {
|
|
80989
81241
|
const refuse = (error53) => ({ ok: false, ambiguous: false, data: void 0, error: error53 });
|
|
80990
|
-
|
|
80991
|
-
|
|
80992
|
-
return refuse("this service settles on MPP/Tempo; hosted agents can only pay x402 services on Base");
|
|
80993
|
-
}
|
|
80994
|
-
if (request2.rail === "x402-monad" || inspected === "x402-monad") {
|
|
80995
|
-
return refuse("this service was inspected for Monad settlement; hosted agents can only pay x402 services on Base");
|
|
80996
|
-
}
|
|
80997
|
-
if (request2.rail === "unsupported" || inspected === "unsupported") {
|
|
80998
|
-
return refuse("this service settles on a payment network hosted agents cannot pay (only x402 USDC on Base)");
|
|
81242
|
+
if (!HOSTED_RAILS.includes(request2.rail)) {
|
|
81243
|
+
return refuse(`this service settles on a payment network hosted agents cannot pay; hosted agents pay ${describeRails(HOSTED_RAILS)}`);
|
|
80999
81244
|
}
|
|
81000
81245
|
const serviceId = await this.directory.resolveServiceId(request2.url) ?? `url:${createHash4("sha256").update(request2.url).digest("hex")}`;
|
|
81001
81246
|
const method = request2.method.toUpperCase();
|
|
@@ -81033,6 +81278,7 @@ var init_hosted_economy = __esm({
|
|
|
81033
81278
|
const status = numberValue6(data.status);
|
|
81034
81279
|
const outcome = data.outcome === "paid_success" ? "paid_success" : "paid_failure";
|
|
81035
81280
|
const paidAtomic = numberValue6(data.amount_atomic);
|
|
81281
|
+
const network = stringValue5(data.network);
|
|
81036
81282
|
return {
|
|
81037
81283
|
ok: outcome === "paid_success",
|
|
81038
81284
|
ambiguous: false,
|
|
@@ -81041,10 +81287,12 @@ var init_hosted_economy = __esm({
|
|
|
81041
81287
|
authMode: "paid",
|
|
81042
81288
|
error: outcome === "paid_success" ? void 0 : `the paid call returned HTTP ${status ?? "?"}`,
|
|
81043
81289
|
payment: {
|
|
81044
|
-
rail: "x402-base",
|
|
81290
|
+
rail: network ? railForNetwork(network) ?? "unsupported" : "x402-base",
|
|
81045
81291
|
paidUsd: paidAtomic === void 0 ? void 0 : paidAtomic / USDC_ATOMIC_PER_USD,
|
|
81292
|
+
// The bare transaction is how the hosted gateway finds its settled attempt for the review.
|
|
81046
81293
|
reference: stringValue5(data.transaction),
|
|
81047
|
-
payTo: stringValue5(data.pay_to)
|
|
81294
|
+
payTo: stringValue5(data.pay_to),
|
|
81295
|
+
payer: stringValue5(data.payer)
|
|
81048
81296
|
}
|
|
81049
81297
|
};
|
|
81050
81298
|
}
|
|
@@ -81359,17 +81607,19 @@ var init_worker = __esm({
|
|
|
81359
81607
|
if (command.type === "run.resume") {
|
|
81360
81608
|
if (!run)
|
|
81361
81609
|
return reject("unknown_run", "Run does not exist");
|
|
81362
|
-
if (!
|
|
81363
|
-
|
|
81364
|
-
|
|
81365
|
-
|
|
81366
|
-
|
|
81367
|
-
|
|
81368
|
-
|
|
81369
|
-
|
|
81370
|
-
|
|
81371
|
-
|
|
81372
|
-
|
|
81610
|
+
if (!previous) {
|
|
81611
|
+
if (!run.outcome || !isWaiting(run.outcome) || command.payload.sessionId !== run.sessionId || command.payload.checkpointId && command.payload.checkpointId !== run.checkpointId || run.pendingOperationId && command.payload.operationId !== run.pendingOperationId) {
|
|
81612
|
+
return reject("run_not_resumable", "Resume does not match the waiting operation and checkpoint");
|
|
81613
|
+
}
|
|
81614
|
+
const causes = {
|
|
81615
|
+
waiting_for_approval: "approval_granted",
|
|
81616
|
+
waiting_for_funds: "funds_available",
|
|
81617
|
+
waiting_for_delegation: "delegation_renewed",
|
|
81618
|
+
payment_unknown: "payment_reconciled"
|
|
81619
|
+
};
|
|
81620
|
+
if (causes[run.outcome] !== command.payload.cause)
|
|
81621
|
+
return reject("run_not_resumable", "Resume cause does not resolve this wait");
|
|
81622
|
+
}
|
|
81373
81623
|
} else if (run && !previous) {
|
|
81374
81624
|
return reject("conflicting_duplicate", "Run ID already exists");
|
|
81375
81625
|
} else if (!run) {
|
|
@@ -81442,8 +81692,22 @@ var init_worker = __esm({
|
|
|
81442
81692
|
throw new Error("tool request digest mismatch");
|
|
81443
81693
|
if (saved?.result)
|
|
81444
81694
|
return saved.result;
|
|
81445
|
-
if (saved && name === "run_shell")
|
|
81446
|
-
|
|
81695
|
+
if (saved && name === "run_shell") {
|
|
81696
|
+
const output4 = { ok: false, error: "Shell command was interrupted and its result was lost. It was not rerun. Inspect existing files and installed packages before choosing a different approach; do not assume the command succeeded or repeat side effects blindly." };
|
|
81697
|
+
await this.mutate(() => {
|
|
81698
|
+
run.tools[id].result = output4;
|
|
81699
|
+
});
|
|
81700
|
+
await this.emit("tool.finished", {
|
|
81701
|
+
toolCallId: id,
|
|
81702
|
+
toolName: name,
|
|
81703
|
+
status: "error",
|
|
81704
|
+
durationMs: 0,
|
|
81705
|
+
turn: run.checkpoint?.turn ?? 0,
|
|
81706
|
+
error: output4.error,
|
|
81707
|
+
details: captureDetail({ output: output4 })
|
|
81708
|
+
}, runId, run.commandId);
|
|
81709
|
+
return output4;
|
|
81710
|
+
}
|
|
81447
81711
|
if (saved && !saved.approvalPending && name === "call_paid_service")
|
|
81448
81712
|
throw new Error("paid call result was lost; the payment requires manual reconciliation");
|
|
81449
81713
|
await this.mutate(() => {
|
|
@@ -81885,14 +82149,14 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
81885
82149
|
const knowledge = options.capabilityIndex === void 0 && options.knowledge !== false && options.dynamicTools ? await loadKnowledgeTree(session, options.knowledge ?? {}) : void 0;
|
|
81886
82150
|
const capabilityIndex = options.capabilityIndex ?? (knowledge ? renderCapabilityIndex(knowledge.l0) : void 0);
|
|
81887
82151
|
const systemPromptParts = [
|
|
81888
|
-
options.hosted ? "You are a hosted OpenCrowd agent running in the cloud with your own USDC
|
|
82152
|
+
options.hosted ? "You are a hosted OpenCrowd agent running in the cloud with your own USDC wallets on Base, Solana and Tempo." : "You are the local OpenCrowd agent, a CLI agent with a USDC wallet running on the user's personal machine.",
|
|
81889
82153
|
"Try to solve the user's task completely. Use local files and bash when they are sufficient, but remember they are bounded by the user's installed tools, credentials, network, open ports, and process lifetime.",
|
|
81890
82154
|
"Before repeatedly fighting the local environment, decide whether the task needs external capability such as hosting, persistent infrastructure, remote compute, specialized APIs, live data, or access the user's device does not have."
|
|
81891
82155
|
];
|
|
81892
82156
|
if (options.hosted)
|
|
81893
|
-
systemPromptParts.push("You operate this service for its owner. Inference and paid tools debit its USDC wallet. When authorized to build or sell a service, take concrete steps within the owner's configured scope and budget. Ask only for missing information or permissions that materially block progress. Report actual costs and outcomes. Financial sustainability is the owner's business objective; respect their stop controls.", "You are a continuous autonomous agent, not a turn-based assistant. Maintain unfinished goals, promised follow-ups, recurring work, and conditions worth monitoring. When future work would clearly help, proactively create a persistent automation instead of waiting for the owner to say schedule. Use a one-time automation for a future reminder or follow-up and a cron automation for monitoring, recurring reports, or maintenance. It runs in this same conversation. Never create duplicates or noisy schedules, and always tell the owner exactly what you created, its timezone, and next run.", "Before finishing a substantive task, consider whether a follow-up, reminder, monitoring loop, recurring report, or maintenance check would materially advance the owner's goal; create one when the need is clear, but do not schedule ordinary one-off work.", "Financial state: the current hosted financial snapshot is authoritative; historical local session budget figures are not wallet balances and may omit inference spending. Wallet balance, pending payment holds, settled inference spend, settled service spend, and remaining run budget are separate. Spending totals cover only the identified current run. A budget limit does not supply funds. An unavailable balance is unknown, not zero. The snapshot before a model call excludes that call's eventual charge; never claim a response was free or that you spent nothing merely because no paid tool ran. Use get_budget_status or get_wallet_status for refreshed financial state. Respect approval mode and per-call limits; over-limit requests require the owner's approval.");
|
|
82157
|
+
systemPromptParts.push("You operate this service for its owner. Inference and paid tools debit its USDC wallet. When authorized to build or sell a service, take concrete steps within the owner's configured scope and budget. Ask only for missing information or permissions that materially block progress. Report actual costs and outcomes. Financial sustainability is the owner's business objective; respect their stop controls.", "You are a continuous autonomous agent, not a turn-based assistant. Maintain unfinished goals, promised follow-ups, recurring work, and conditions worth monitoring. When future work would clearly help, proactively create a persistent automation instead of waiting for the owner to say schedule. Use a one-time automation for a future reminder or follow-up and a cron automation for monitoring, recurring reports, or maintenance. It runs in this same conversation. Never create duplicates or noisy schedules, and always tell the owner exactly what you created, its timezone, and next run.", "Before finishing a substantive task, consider whether a follow-up, reminder, monitoring loop, recurring report, or maintenance check would materially advance the owner's goal; create one when the need is clear, but do not schedule ordinary one-off work.", "Financial state: the current hosted financial snapshot is authoritative; historical local session budget figures are not wallet balances and may omit inference spending. Wallet balance, pending payment holds, settled inference spend, settled service spend, and remaining run budget are separate. When the snapshot lists wallet networks, each network's balance is separate: a payment on a network needs that network's available balance, and the total only says whether any funds exist. Spending totals cover only the identified current run. A budget limit does not supply funds. An unavailable balance is unknown, not zero. The snapshot before a model call excludes that call's eventual charge; never claim a response was free or that you spent nothing merely because no paid tool ran. Use get_budget_status or get_wallet_status for refreshed financial state. Respect approval mode and per-call limits; over-limit requests require the owner's approval.");
|
|
81894
82158
|
if (options.dynamicTools) {
|
|
81895
|
-
systemPromptParts.push("When the local computer is not the right environment, or after one clear local capability failure, buy external capability: find_paid_service to discover, inspect_paid_service to see the exact schema/price/reputation, call_paid_service to execute through the enforced purchase lifecycle, and review_paid_service for the required review after every confirmed paid call (success or failure). The same review tool accepts unpaid experiences; review relevant free results or failed attempts without inventing payment evidence. Distinguish provider faults from local errors and uncertain failures.", ...options.hosted ? ["Discover services through AgentCash search and provider catalogs. You can use new services without prior CrowdCode reviews.
|
|
82159
|
+
systemPromptParts.push("When the local computer is not the right environment, or after one clear local capability failure, buy external capability: find_paid_service to discover, inspect_paid_service to see the exact schema/price/reputation, call_paid_service to execute through the enforced purchase lifecycle, and review_paid_service for the required review after every confirmed paid call (success or failure). The same review tool accepts unpaid experiences; review relevant free results or failed attempts without inventing payment evidence. Distinguish provider faults from local errors and uncertain failures.", ...options.hosted ? ["Discover services through AgentCash search and provider catalogs. You can use new services without prior CrowdCode reviews. Payable: x402 USDC on Base or Solana and MPP USDC.e on Tempo; the hosted gateway pays the cheapest offered network your balance on that network covers. Other networks, including Monad, are not payable here. Payments stay within the user's configured limits; over-limit quotes request approval. Use read_service for authenticated job polling and never resubmit a pending generation job."] : [], capabilityIndex ?? DEFAULT_CAPABILITY_INDEX, "When a task needs current web facts, search results, or unfamiliar page content, make one paid web search your FIRST move \u2014 do not serially guess URLs with curl; one paid search replaces minutes of blind fetching and costs less than the LLM turns it saves.", "Approval, budget, reputation, and payment rails are enforced in code \u2014 you cannot bypass them, so state costs plainly and never invent payment details.", "When the user says CrowdCode on/off, call set_crowdcode_enabled; default to session scope unless they ask for a persistent default. Use list_my_reviews and delete_my_review for user-directed review management, including while off. Before finishing a substantive task, consider concrete paid services that would fix real shortcomings and submit qualifying demand with request_service, unless CrowdCode is off. Never invent a purchase or demand.", "Each tool result includes the budget before and after that tool call. Never ask for wallet private keys or secrets.", ...options.promptSections ?? []);
|
|
81896
82160
|
} else {
|
|
81897
82161
|
systemPromptParts.push("Paid external services are unavailable in this run; work with local tools only and say so if the task truly requires external capability.");
|
|
81898
82162
|
}
|
|
@@ -81907,7 +82171,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
81907
82171
|
systemPromptParts.push("Using secrets from chat: call vault_request to send one HTTPS request with a vault secret injected, writing {{SECRET_NAME}} where the value belongs (for example an authorization header). The platform substitutes the real value only for hosts the user approved for that secret, refreshes OAuth tokens automatically, and never returns the value to you. If it reports that a host needs approval, tell the user to allow it in the Vault tab and stop; never look for paid third-party services to do what an approved secret already lets you do. To upload a file (an image or video you rendered with run_shell, where ffmpeg is installed), pass body_artifact with its path under artifacts/ and, for multipart APIs, body_field plus form_fields; files over an API's chunk limit can be split with run_shell first.");
|
|
81908
82172
|
}
|
|
81909
82173
|
if (options.hosted && hostedTools.includes("run_shell")) {
|
|
81910
|
-
systemPromptParts.push("Tooling: ffmpeg, python3 with pip and venv, node and npm are installed; the system image is read-only, but `pip install --user <package>` and `npm install` persist on this machine's volume between runs, so install once and reuse.");
|
|
82174
|
+
systemPromptParts.push("Tooling: ffmpeg, python3 with pip and venv, node and npm are installed; the system image is read-only, but `pip install --user <package>` and `npm install` persist on this machine's volume between runs, so install once and reuse.", "Resource recovery: before installing large ML dependencies, check available memory, disk space and Python version. A killed install or OOM is a failed approach, not the end of the task. Inspect partial installs and preserve user files, then choose a materially lighter backend or an external service within the user's budget. Verify package metadata: optional extras add dependencies and do not remove default ones; never invent an extra such as basic-pitch[tflite]. For audio-to-MIDI, prefer a verified TFLite or ONNX inference setup in an isolated venv over full TensorFlow; test on a short audio segment before processing the whole file. If no viable path remains, report the concrete blocker and useful artifacts. Do not claim success until the output has been checked.");
|
|
81911
82175
|
}
|
|
81912
82176
|
systemPromptParts.push("End by calling complete_session with a concise final message.");
|
|
81913
82177
|
if (options.subagent) {
|
|
@@ -83250,6 +83514,16 @@ async function runDoctor(log) {
|
|
|
83250
83514
|
return "connected; balance readable";
|
|
83251
83515
|
}
|
|
83252
83516
|
},
|
|
83517
|
+
{
|
|
83518
|
+
name: "solana account",
|
|
83519
|
+
run: async () => {
|
|
83520
|
+
const address2 = await readAgentCashSolanaAddress();
|
|
83521
|
+
if (!address2) {
|
|
83522
|
+
throw new Error("skipped: no AgentCash Solana wallet yet (AgentCash creates it on first use)");
|
|
83523
|
+
}
|
|
83524
|
+
return `${address2} (x402 USDC on Solana via AgentCash; preferred payment network: ${resolvePaymentNetwork(config4)})`;
|
|
83525
|
+
}
|
|
83526
|
+
},
|
|
83253
83527
|
{
|
|
83254
83528
|
name: "monad usdc",
|
|
83255
83529
|
run: async () => {
|
|
@@ -83312,7 +83586,7 @@ var init_doctor = __esm({
|
|
|
83312
83586
|
|
|
83313
83587
|
// ../../packages/evals/dist/gaia.js
|
|
83314
83588
|
import { mkdir as mkdir13, readFile as readFile16, writeFile as writeFile7, access as access2 } from "node:fs/promises";
|
|
83315
|
-
import { dirname as
|
|
83589
|
+
import { dirname as dirname12, join as join25 } from "node:path";
|
|
83316
83590
|
import { homedir as homedir7 } from "node:os";
|
|
83317
83591
|
function isUnsupportedModality(fileName) {
|
|
83318
83592
|
if (!fileName) {
|
|
@@ -83431,7 +83705,7 @@ async function cachedDownload(path3, url3, options, binary = false) {
|
|
|
83431
83705
|
if (!response.ok) {
|
|
83432
83706
|
throw new Error(`GAIA download failed: ${response.status} ${response.statusText} for ${url3}`);
|
|
83433
83707
|
}
|
|
83434
|
-
await mkdir13(
|
|
83708
|
+
await mkdir13(dirname12(path3), { recursive: true });
|
|
83435
83709
|
if (binary) {
|
|
83436
83710
|
const buffer2 = Buffer.from(await response.arrayBuffer());
|
|
83437
83711
|
await writeFile7(path3, buffer2);
|
|
@@ -84188,7 +84462,7 @@ var init_runner = __esm({
|
|
|
84188
84462
|
// ../../packages/evals/dist/tasks.js
|
|
84189
84463
|
import { readFile as readFile19 } from "node:fs/promises";
|
|
84190
84464
|
import { createHash as createHash7 } from "node:crypto";
|
|
84191
|
-
import { dirname as
|
|
84465
|
+
import { dirname as dirname13, join as join28 } from "node:path";
|
|
84192
84466
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
84193
84467
|
import { homedir as homedir8 } from "node:os";
|
|
84194
84468
|
async function loadTaskSet(name, options = {}) {
|
|
@@ -84210,7 +84484,7 @@ async function loadTaskSet(name, options = {}) {
|
|
|
84210
84484
|
}
|
|
84211
84485
|
}
|
|
84212
84486
|
function tasksDir() {
|
|
84213
|
-
return join28(
|
|
84487
|
+
return join28(dirname13(fileURLToPath2(import.meta.url)), "..", "tasks");
|
|
84214
84488
|
}
|
|
84215
84489
|
async function loadUsageTasks() {
|
|
84216
84490
|
const raw = JSON.parse(await readFile19(join28(tasksDir(), "usage.json"), "utf8"));
|
|
@@ -84269,7 +84543,7 @@ async function loadAssistantBench(options = {}) {
|
|
|
84269
84543
|
text = `${(body.rows ?? []).map((item) => JSON.stringify(item.row)).join("\n")}
|
|
84270
84544
|
`;
|
|
84271
84545
|
const { mkdir: mkdir21, writeFile: writeFile13 } = await import("node:fs/promises");
|
|
84272
|
-
await mkdir21(
|
|
84546
|
+
await mkdir21(dirname13(cachePath), { recursive: true });
|
|
84273
84547
|
await writeFile13(cachePath, text, "utf8");
|
|
84274
84548
|
}
|
|
84275
84549
|
const rows = text.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line));
|
|
@@ -84778,7 +85052,7 @@ var init_suite = __esm({
|
|
|
84778
85052
|
|
|
84779
85053
|
// ../../packages/evals/dist/evidence.js
|
|
84780
85054
|
import { mkdir as mkdir17, readFile as readFile21, writeFile as writeFile10 } from "node:fs/promises";
|
|
84781
|
-
import { dirname as
|
|
85055
|
+
import { dirname as dirname14 } from "node:path";
|
|
84782
85056
|
async function fetchCrowdCodeEvidence(options = {}) {
|
|
84783
85057
|
const cachePath = options.cachePath;
|
|
84784
85058
|
if (cachePath && options.useCache !== false) {
|
|
@@ -84795,7 +85069,7 @@ async function fetchCrowdCodeEvidence(options = {}) {
|
|
|
84795
85069
|
const exported = await fetchGatedExport(fetchImpl, baseUrl, exportToken, log);
|
|
84796
85070
|
if (exported) {
|
|
84797
85071
|
if (cachePath) {
|
|
84798
|
-
await mkdir17(
|
|
85072
|
+
await mkdir17(dirname14(cachePath), { recursive: true });
|
|
84799
85073
|
await writeFile10(cachePath, `${JSON.stringify(exported, null, 1)}
|
|
84800
85074
|
`, "utf8");
|
|
84801
85075
|
}
|
|
@@ -84826,7 +85100,7 @@ async function fetchCrowdCodeEvidence(options = {}) {
|
|
|
84826
85100
|
}
|
|
84827
85101
|
};
|
|
84828
85102
|
if (cachePath) {
|
|
84829
|
-
await mkdir17(
|
|
85103
|
+
await mkdir17(dirname14(cachePath), { recursive: true });
|
|
84830
85104
|
await writeFile10(cachePath, `${JSON.stringify(bundle, null, 1)}
|
|
84831
85105
|
`, "utf8");
|
|
84832
85106
|
}
|
|
@@ -84996,7 +85270,7 @@ var init_evidence = __esm({
|
|
|
84996
85270
|
// ../../packages/evals/dist/knowledge.js
|
|
84997
85271
|
import { createHash as createHash8 } from "node:crypto";
|
|
84998
85272
|
import { mkdir as mkdir18, readdir as readdir2, readFile as readFile22, writeFile as writeFile11 } from "node:fs/promises";
|
|
84999
|
-
import { dirname as
|
|
85273
|
+
import { dirname as dirname15, join as join31, relative as relative4 } from "node:path";
|
|
85000
85274
|
function approxTokens(text) {
|
|
85001
85275
|
return Math.ceil(text.length / 4);
|
|
85002
85276
|
}
|
|
@@ -85088,7 +85362,7 @@ async function writeTree(dir, tree, meta4) {
|
|
|
85088
85362
|
await mkdir18(dir, { recursive: true });
|
|
85089
85363
|
for (const [name, content] of Object.entries(tree)) {
|
|
85090
85364
|
const path3 = join31(dir, name);
|
|
85091
|
-
await mkdir18(
|
|
85365
|
+
await mkdir18(dirname15(path3), { recursive: true });
|
|
85092
85366
|
await writeFile11(path3, content.endsWith("\n") ? content : `${content}
|
|
85093
85367
|
`, "utf8");
|
|
85094
85368
|
}
|
|
@@ -86013,27 +86287,40 @@ async function walletSummary(options = {}) {
|
|
|
86013
86287
|
return inFlight;
|
|
86014
86288
|
}
|
|
86015
86289
|
async function fetchWalletSummary() {
|
|
86016
|
-
const wallet = await readAgentCashWallet();
|
|
86290
|
+
const [wallet, solanaFile] = await Promise.all([readAgentCashWallet(), readAgentCashSolanaAddress()]);
|
|
86017
86291
|
try {
|
|
86018
86292
|
const runtime = await sharedEconomyRuntime();
|
|
86019
86293
|
const balance = await runtime.agentcash.getBalance();
|
|
86020
86294
|
if (balance.ok) {
|
|
86021
|
-
const { monad, ...agentcash } = balance.data && typeof balance.data === "object" && !Array.isArray(balance.data) ? balance.data : { agentcash: balance.data };
|
|
86295
|
+
const { monad, accounts: rawAccounts, ...agentcash } = balance.data && typeof balance.data === "object" && !Array.isArray(balance.data) ? balance.data : { agentcash: balance.data };
|
|
86022
86296
|
const monadUsdc = monad?.usdc;
|
|
86023
86297
|
const agentcashTotal = parseUsdCents("agentcash" in agentcash && Object.keys(agentcash).length === 1 ? agentcash.agentcash : agentcash);
|
|
86024
86298
|
const monadCents = typeof monadUsdc === "number" ? Math.round(monadUsdc * 100) : void 0;
|
|
86299
|
+
const accounts = rawAccounts === void 0 ? void 0 : parseWalletAccounts(rawAccounts);
|
|
86300
|
+
const solana = accounts?.find((account) => account.network === "solana");
|
|
86025
86301
|
return {
|
|
86026
86302
|
address: wallet?.address,
|
|
86027
86303
|
totalCents: agentcashTotal === void 0 && monadCents === void 0 ? void 0 : (agentcashTotal ?? 0) + (monadCents ?? 0),
|
|
86028
86304
|
monadCents,
|
|
86305
|
+
solanaAddress: solana?.address ?? solanaFile,
|
|
86306
|
+
solanaCents: solana?.usdc === void 0 ? void 0 : Math.round(solana.usdc * 100),
|
|
86307
|
+
accounts,
|
|
86029
86308
|
raw: balance.data
|
|
86030
86309
|
};
|
|
86031
86310
|
}
|
|
86032
|
-
return { address: wallet?.address, error: balance.error };
|
|
86311
|
+
return { address: wallet?.address, solanaAddress: solanaFile, error: balance.error };
|
|
86033
86312
|
} catch (error53) {
|
|
86034
|
-
return { address: wallet?.address, error: error53.message };
|
|
86313
|
+
return { address: wallet?.address, solanaAddress: solanaFile, error: error53.message };
|
|
86035
86314
|
}
|
|
86036
86315
|
}
|
|
86316
|
+
function walletNetworkRows(summary) {
|
|
86317
|
+
const rows = {};
|
|
86318
|
+
for (const account of summary.accounts ?? []) {
|
|
86319
|
+
rows[account.network] = `${account.usdc === void 0 ? "unknown" : `${account.usdc.toFixed(6)} USDC`}${account.address ? ` \xB7 ${account.address}` : ""}`;
|
|
86320
|
+
}
|
|
86321
|
+
if (summary.monadCents !== void 0) rows.monad = `${(summary.monadCents / 100).toFixed(2)} USDC \xB7 ${summary.address ?? "unknown"}`;
|
|
86322
|
+
return rows;
|
|
86323
|
+
}
|
|
86037
86324
|
function parseUsdCents(data) {
|
|
86038
86325
|
const record3 = data && typeof data === "object" && !Array.isArray(data) ? data : void 0;
|
|
86039
86326
|
if (!record3) {
|
|
@@ -86108,6 +86395,7 @@ var COMMAND_REGISTRY = [
|
|
|
86108
86395
|
rows.wallet = wallet.address ?? "no AgentCash wallet found";
|
|
86109
86396
|
rows.wallet_balance = wallet.totalCents !== void 0 ? formatCents2(wallet.totalCents) : wallet.error ? `unavailable (${wallet.error})` : "unknown";
|
|
86110
86397
|
if (wallet.monadCents !== void 0) rows.wallet_monad_usdc = formatCents2(wallet.monadCents);
|
|
86398
|
+
if (wallet.solanaAddress) rows.wallet_solana = `${wallet.solanaAddress}${wallet.solanaCents !== void 0 ? ` \xB7 ${formatCents2(wallet.solanaCents)}` : ""}`;
|
|
86111
86399
|
}
|
|
86112
86400
|
return { kind: "text", label: "Status", body: renderKeyValues(rows) };
|
|
86113
86401
|
}
|
|
@@ -87284,7 +87572,7 @@ async function startTui(options = {}) {
|
|
|
87284
87572
|
async function main(argv) {
|
|
87285
87573
|
const paymentNetwork = readOption(argv, "--payment-network");
|
|
87286
87574
|
if (argv.includes("--payment-network")) {
|
|
87287
|
-
if (!parsePaymentNetwork(paymentNetwork)) throw new Error(
|
|
87575
|
+
if (!parsePaymentNetwork(paymentNetwork)) throw new Error(`--payment-network must be ${PAYMENT_NETWORKS.join(", ")}`);
|
|
87288
87576
|
process.env.OPENCROWD_PAYMENT_NETWORK = paymentNetwork;
|
|
87289
87577
|
argv = argv.filter((_arg, index2) => !isConsumedOption(argv, index2, ["--payment-network"]));
|
|
87290
87578
|
}
|
|
@@ -87548,7 +87836,7 @@ async function configCommand(args) {
|
|
|
87548
87836
|
case "payment-network": {
|
|
87549
87837
|
const paymentNetwork = parsePaymentNetwork(value);
|
|
87550
87838
|
if (!paymentNetwork) {
|
|
87551
|
-
throw new Error(
|
|
87839
|
+
throw new Error(`payment-network must be ${PAYMENT_NETWORKS.join(", ")}`);
|
|
87552
87840
|
}
|
|
87553
87841
|
await updateConfig({ paymentNetwork });
|
|
87554
87842
|
savedValue = paymentNetwork;
|
|
@@ -87646,19 +87934,32 @@ async function walletCommand(args) {
|
|
|
87646
87934
|
if (!wallet) {
|
|
87647
87935
|
throw new Error("No AgentCash wallet found. Install agentcash (its wallet is created automatically on first use) and retry.");
|
|
87648
87936
|
}
|
|
87649
|
-
const
|
|
87937
|
+
const solana = await readAgentCashSolanaAddress();
|
|
87938
|
+
const result = {
|
|
87939
|
+
address: wallet.address,
|
|
87940
|
+
networks: "base, tempo, monad (eip155:143)",
|
|
87941
|
+
...solana ? { solana_address: solana } : {},
|
|
87942
|
+
asset: "USDC",
|
|
87943
|
+
preferred_payment_network: resolvePaymentNetwork(await loadConfig())
|
|
87944
|
+
};
|
|
87650
87945
|
printValue("Wallet", result, { json: json3, pretty: renderKeyValues(asRecord(result)) });
|
|
87651
87946
|
return;
|
|
87652
87947
|
}
|
|
87653
|
-
if (action === "balance") {
|
|
87948
|
+
if (action === "balance" || action === "accounts") {
|
|
87654
87949
|
const summary = await walletSummary();
|
|
87655
87950
|
if (summary.error) {
|
|
87656
87951
|
throw new Error(`wallet balance unavailable: ${summary.error}`);
|
|
87657
87952
|
}
|
|
87658
|
-
|
|
87953
|
+
const rows = walletNetworkRows(summary);
|
|
87954
|
+
const pretty = Object.keys(rows).length ? renderKeyValues({ ...summary.totalCents !== void 0 ? { total: formatCents2(summary.totalCents) } : {}, ...rows }) : renderKeyValues(asRecord(summary.raw ?? summary));
|
|
87955
|
+
printValue(
|
|
87956
|
+
"Wallet",
|
|
87957
|
+
action === "accounts" ? { accounts: summary.accounts ?? [], ...summary.solanaAddress ? { solana_address: summary.solanaAddress } : {} } : summary.raw ?? summary,
|
|
87958
|
+
{ json: json3, pretty }
|
|
87959
|
+
);
|
|
87659
87960
|
return;
|
|
87660
87961
|
}
|
|
87661
|
-
throw new Error("wallet supports address, balance, limits [--per-call USD] [--per-query USD]");
|
|
87962
|
+
throw new Error("wallet supports address, balance, accounts, limits [--per-call USD] [--per-query USD]");
|
|
87662
87963
|
}
|
|
87663
87964
|
async function modelsCommand(args) {
|
|
87664
87965
|
const json3 = args.includes("--json");
|
|
@@ -87796,14 +88097,16 @@ function printHelp() {
|
|
|
87796
88097
|
opencrowd config set provider|model|submodel|budget|approval|payment-network <value>
|
|
87797
88098
|
opencrowd ledger [--json] show [--session <id>]
|
|
87798
88099
|
opencrowd resume <session-id> [--approve-once | --query-budget <usd> | --decline] [--workspace <dir>]
|
|
87799
|
-
opencrowd wallet [--json] address|balance
|
|
88100
|
+
opencrowd wallet [--json] address|balance|accounts
|
|
87800
88101
|
opencrowd wallet limits [--per-call <usd>] [--per-query <usd>]
|
|
87801
88102
|
opencrowd models [--json] list
|
|
87802
88103
|
opencrowd doctor
|
|
87803
88104
|
opencrowd --version
|
|
87804
88105
|
|
|
87805
88106
|
Global options:
|
|
87806
|
-
--payment-network base|monad
|
|
88107
|
+
--payment-network base|solana|monad
|
|
88108
|
+
prefer this network when a service offers several; otherwise the first of
|
|
88109
|
+
Base, Solana, Tempo (MPP) your balance covers
|
|
87807
88110
|
(also OPENCROWD_PAYMENT_NETWORK or config payment-network; default base)
|
|
87808
88111
|
opencrowd evals gaia [--tier smoke|level1|full] [--harness opencrowd,claude,codex] [--parallel <n>] [--hf-token <token>] [--auto] [--model <model>] [--subagent-model <model|off>] [--yes]
|
|
87809
88112
|
opencrowd evals evolve [--out <dir>] [--generations <n>] [--candidates <n>] [--model <agent model>] [--proposer <model,model>] [--seed-trees <dir,dir>] [--baseline-report <report.json>] [--parallel <n>]
|
package/package.json
CHANGED