opencrowd 0.16.3 → 0.16.5
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/bundle/opencrowd.js +688 -211
- package/package.json +1 -1
package/bundle/opencrowd.js
CHANGED
|
@@ -262,7 +262,7 @@ var init_paths = __esm({
|
|
|
262
262
|
});
|
|
263
263
|
|
|
264
264
|
// ../../packages/core/dist/artifacts.js
|
|
265
|
-
import { mkdir as mkdir3, readFile as readFile3 } from "node:fs/promises";
|
|
265
|
+
import { mkdir as mkdir3, readFile as readFile3, readdir, stat } from "node:fs/promises";
|
|
266
266
|
import { dirname as dirname4, join as join3, relative as relative2 } from "node:path";
|
|
267
267
|
async function saveArtifact(state, path3, content, metadata) {
|
|
268
268
|
const target = await safeArtifactPath(state, path3);
|
|
@@ -283,21 +283,75 @@ async function readArtifact(state, path3) {
|
|
|
283
283
|
return readFile3(await safeArtifactPath(state, path3), "utf8");
|
|
284
284
|
}
|
|
285
285
|
async function listArtifacts(state, prefix = "") {
|
|
286
|
-
const { readdir: readdir3 } = await import("node:fs/promises");
|
|
287
286
|
const start = await safeArtifactPath(state, prefix || ".");
|
|
288
287
|
const files = [];
|
|
289
|
-
await
|
|
288
|
+
await walkFiles(start, state.artifactsDir, files);
|
|
290
289
|
return files.sort();
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
290
|
+
}
|
|
291
|
+
async function listOtherChatArtifacts(state) {
|
|
292
|
+
const sessionsDir = dirname4(state.sessionDir);
|
|
293
|
+
let entries;
|
|
294
|
+
try {
|
|
295
|
+
entries = await readdir(sessionsDir, { withFileTypes: true });
|
|
296
|
+
} catch {
|
|
297
|
+
return { chats: [], truncated: false };
|
|
298
|
+
}
|
|
299
|
+
const others = [];
|
|
300
|
+
for (const entry of entries) {
|
|
301
|
+
if (!entry.isDirectory() || entry.name === state.sessionId)
|
|
302
|
+
continue;
|
|
303
|
+
try {
|
|
304
|
+
assertPathId(entry.name);
|
|
305
|
+
} catch {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const dir = join3(sessionsDir, entry.name, "artifacts");
|
|
309
|
+
try {
|
|
310
|
+
const info = await stat(join3(sessionsDir, entry.name));
|
|
311
|
+
others.push({ id: entry.name, dir, mtime: info.mtimeMs });
|
|
312
|
+
} catch {
|
|
299
313
|
}
|
|
300
314
|
}
|
|
315
|
+
others.sort((a, b) => b.mtime - a.mtime);
|
|
316
|
+
const chats = [];
|
|
317
|
+
let remaining = OTHER_CHAT_FILE_LIMIT, truncated = false;
|
|
318
|
+
for (const other of others) {
|
|
319
|
+
if (remaining <= 0) {
|
|
320
|
+
truncated = true;
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
let root;
|
|
324
|
+
try {
|
|
325
|
+
root = await containedPath(sessionsDir, join3(other.id, "artifacts"));
|
|
326
|
+
} catch {
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const files = [];
|
|
330
|
+
try {
|
|
331
|
+
await walkFiles(root, root, files);
|
|
332
|
+
} catch {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (!files.length)
|
|
336
|
+
continue;
|
|
337
|
+
files.sort();
|
|
338
|
+
if (files.length > remaining) {
|
|
339
|
+
truncated = true;
|
|
340
|
+
files.length = remaining;
|
|
341
|
+
}
|
|
342
|
+
remaining -= files.length;
|
|
343
|
+
chats.push({ session_id: other.id, shell_dir: `../${other.id}/artifacts`, files });
|
|
344
|
+
}
|
|
345
|
+
return { chats, truncated };
|
|
346
|
+
}
|
|
347
|
+
async function walkFiles(dir, root, out) {
|
|
348
|
+
for (const entry of await readdir(dir, { withFileTypes: true })) {
|
|
349
|
+
const full = join3(dir, entry.name);
|
|
350
|
+
if (entry.isDirectory())
|
|
351
|
+
await walkFiles(full, root, out);
|
|
352
|
+
else if (entry.isFile())
|
|
353
|
+
out.push(relative2(root, full));
|
|
354
|
+
}
|
|
301
355
|
}
|
|
302
356
|
function safeArtifactPath(state, requestedPath) {
|
|
303
357
|
const normalizedRequest = requestedPath.replace(/^artifacts\//, "");
|
|
@@ -305,11 +359,13 @@ function safeArtifactPath(state, requestedPath) {
|
|
|
305
359
|
throw new Error(`artifact path: ${error53.message}`);
|
|
306
360
|
});
|
|
307
361
|
}
|
|
362
|
+
var OTHER_CHAT_FILE_LIMIT;
|
|
308
363
|
var init_artifacts = __esm({
|
|
309
364
|
"../../packages/core/dist/artifacts.js"() {
|
|
310
365
|
"use strict";
|
|
311
366
|
init_ledger();
|
|
312
367
|
init_paths();
|
|
368
|
+
OTHER_CHAT_FILE_LIMIT = 300;
|
|
313
369
|
}
|
|
314
370
|
});
|
|
315
371
|
|
|
@@ -16176,7 +16232,7 @@ var init_context = __esm({
|
|
|
16176
16232
|
};
|
|
16177
16233
|
CONTEXT_COST_BUDGET_USD = 0.02;
|
|
16178
16234
|
CONTEXT_MIN_HISTORY_TOKENS = 24e3;
|
|
16179
|
-
centsPer1kToUsdPerMillion = (
|
|
16235
|
+
centsPer1kToUsdPerMillion = (cents2) => typeof cents2 === "number" && Number.isFinite(cents2) && cents2 > 0 ? cents2 * 10 : void 0;
|
|
16180
16236
|
}
|
|
16181
16237
|
});
|
|
16182
16238
|
|
|
@@ -16506,7 +16562,7 @@ async function reserveBudget(state, amountCents, action) {
|
|
|
16506
16562
|
assertCents(amountCents, "reservation");
|
|
16507
16563
|
if (state.query) {
|
|
16508
16564
|
const committed = state.spentCents - state.query.startSpentCents + state.reservedCents;
|
|
16509
|
-
const atomic2 = (
|
|
16565
|
+
const atomic2 = (cents2) => String(Math.round(cents2 * 1e4));
|
|
16510
16566
|
const check3 = spendingDecision({
|
|
16511
16567
|
amount: atomic2(amountCents),
|
|
16512
16568
|
perCall: atomic2(state.perCallCents ?? 100),
|
|
@@ -17017,7 +17073,7 @@ function toolDescription(name) {
|
|
|
17017
17073
|
case "read_file":
|
|
17018
17074
|
return "Read a session artifact.";
|
|
17019
17075
|
case "list_files":
|
|
17020
|
-
return
|
|
17076
|
+
return `List this chat's artifacts. Each chat with the owner has its own artifacts/ directory, but the owner's Files view shows every chat's files together: set scope="all" to also list files from your other chats before you say a file the owner mentions does not exist.`;
|
|
17021
17077
|
case "run_shell":
|
|
17022
17078
|
return "Run a gated local shell command only when shell access is enabled for the session.";
|
|
17023
17079
|
case "spawn_subagent":
|
|
@@ -17041,7 +17097,10 @@ function toolParameters(name) {
|
|
|
17041
17097
|
case "get_budget_status":
|
|
17042
17098
|
return objectSchema({});
|
|
17043
17099
|
case "list_files":
|
|
17044
|
-
return objectSchema({
|
|
17100
|
+
return objectSchema({
|
|
17101
|
+
prefix: stringSchema("Optional artifact path prefix (this chat only)."),
|
|
17102
|
+
scope: { type: "string", enum: ["chat", "all"], description: "chat (default): this chat's artifacts. all: also every other chat's files, each with the shell_dir to reach it from run_shell." }
|
|
17103
|
+
});
|
|
17045
17104
|
case "save_file":
|
|
17046
17105
|
return objectSchema({
|
|
17047
17106
|
path: stringSchema("Relative artifact path."),
|
|
@@ -17151,6 +17210,8 @@ function summarizeToolInput(name, args) {
|
|
|
17151
17210
|
return pick3({ url: text(args.url), method: text(args.method), max_cost_cents: text(args.max_cost_cents) });
|
|
17152
17211
|
case "review_paid_service":
|
|
17153
17212
|
return pick3({ purchase_id: text(args.purchase_id), rating: text(args.rating) });
|
|
17213
|
+
case "plan_funding":
|
|
17214
|
+
return pick3({ calls: text(Array.isArray(args.calls) ? args.calls.map((call2) => call2?.url).filter((url3) => typeof url3 === "string").join(" ") : void 0) });
|
|
17154
17215
|
case "bridge_usdc":
|
|
17155
17216
|
return pick3({
|
|
17156
17217
|
from: text(args.from),
|
|
@@ -17237,8 +17298,21 @@ async function executeTool(name, args, context) {
|
|
|
17237
17298
|
return ok(await saveArtifact(context.session, requiredString(args.path, "path"), requiredString(args.content, "content"), objectValue(args.metadata)));
|
|
17238
17299
|
case "read_file":
|
|
17239
17300
|
return ok({ content: await readArtifact(context.session, requiredString(args.path, "path")) });
|
|
17240
|
-
case "list_files":
|
|
17241
|
-
|
|
17301
|
+
case "list_files": {
|
|
17302
|
+
const files = await listArtifacts(context.session, optionalString(args.prefix, "prefix") ?? "");
|
|
17303
|
+
const scope = optionalString(args.scope, "scope") ?? "chat";
|
|
17304
|
+
if (scope !== "chat" && scope !== "all")
|
|
17305
|
+
throw new Error("scope must be chat or all");
|
|
17306
|
+
if (scope === "chat")
|
|
17307
|
+
return ok(files);
|
|
17308
|
+
const other = await listOtherChatArtifacts(context.session);
|
|
17309
|
+
return ok({
|
|
17310
|
+
files,
|
|
17311
|
+
other_chats: other.chats,
|
|
17312
|
+
...other.truncated ? { truncated: true } : {},
|
|
17313
|
+
note: other.chats.length ? "Files from other chats are already the owner's and already in their Files view. Read one with run_shell at <shell_dir>/<file> (run_shell starts in this chat's session directory). To attach or upload one from this chat, copy it into artifacts/ first; never re-buy or regenerate a file you already hold." : "No other chat of this agent has files."
|
|
17314
|
+
});
|
|
17315
|
+
}
|
|
17242
17316
|
case "run_shell": {
|
|
17243
17317
|
context.onProgress?.({ type: "running_shell", message: "Running gated shell command" });
|
|
17244
17318
|
const result = await runShell(context.session, requiredString(args.command, "command"), optionalString(args.cwd, "cwd") ?? context.session.sessionDir, shellTimeoutMs(args.timeout_ms), { signal: context.signal });
|
|
@@ -55927,13 +56001,13 @@ var init_approve = __esm({
|
|
|
55927
56001
|
});
|
|
55928
56002
|
}
|
|
55929
56003
|
approve2.estimateGas = estimateGas2;
|
|
55930
|
-
async function
|
|
56004
|
+
async function simulate2(client, parameters) {
|
|
55931
56005
|
return simulateContract(client, {
|
|
55932
56006
|
...pickWriteParameters(parameters),
|
|
55933
56007
|
...approve2.call(client, parameters)
|
|
55934
56008
|
});
|
|
55935
56009
|
}
|
|
55936
|
-
approve2.simulate =
|
|
56010
|
+
approve2.simulate = simulate2;
|
|
55937
56011
|
function extractEvent(logs) {
|
|
55938
56012
|
const [log] = parseEventLogs({
|
|
55939
56013
|
abi: erc20Abi,
|
|
@@ -56408,13 +56482,13 @@ var init_transfer = __esm({
|
|
|
56408
56482
|
});
|
|
56409
56483
|
}
|
|
56410
56484
|
transfer2.estimateGas = estimateGas2;
|
|
56411
|
-
async function
|
|
56485
|
+
async function simulate2(client, parameters) {
|
|
56412
56486
|
return simulateContract(client, {
|
|
56413
56487
|
...pickWriteParameters(parameters),
|
|
56414
56488
|
...transfer2.call(client, parameters)
|
|
56415
56489
|
});
|
|
56416
56490
|
}
|
|
56417
|
-
transfer2.simulate =
|
|
56491
|
+
transfer2.simulate = simulate2;
|
|
56418
56492
|
function extractEvent(logs) {
|
|
56419
56493
|
const [log] = parseEventLogs({
|
|
56420
56494
|
abi: erc20Abi,
|
|
@@ -57752,7 +57826,8 @@ function classifyOffer(option) {
|
|
|
57752
57826
|
protocol,
|
|
57753
57827
|
rail,
|
|
57754
57828
|
...price_usd !== void 0 ? { price_usd } : {},
|
|
57755
|
-
...typeof option?.payTo === "string" ? { pay_to: option.payTo } : {}
|
|
57829
|
+
...typeof option?.payTo === "string" ? { pay_to: option.payTo } : {},
|
|
57830
|
+
...protocol === "mpp" && rail === "mppx" && price_usd === 0 ? { free: true } : {}
|
|
57756
57831
|
};
|
|
57757
57832
|
}
|
|
57758
57833
|
function selectOffer(offers, selection) {
|
|
@@ -57914,8 +57989,10 @@ var init_discovery = __esm({
|
|
|
57914
57989
|
network: candidate.network_name ?? candidate.network,
|
|
57915
57990
|
protocol: candidate.protocol,
|
|
57916
57991
|
price_usd: candidate.price_usd,
|
|
57917
|
-
payable: payable.includes(candidate)
|
|
57992
|
+
payable: payable.includes(candidate),
|
|
57993
|
+
...candidate.free ? { free: true } : {}
|
|
57918
57994
|
})) } : {},
|
|
57995
|
+
...offer?.free ? { free: true } : {},
|
|
57919
57996
|
input_schema: advisory.inputSchema,
|
|
57920
57997
|
output_schema: advisory.outputSchema,
|
|
57921
57998
|
description: advisory.summary,
|
|
@@ -57935,13 +58012,20 @@ var init_discovery = __esm({
|
|
|
57935
58012
|
}
|
|
57936
58013
|
note(offers, offer) {
|
|
57937
58014
|
const quote = "Inspect with sample_body for the exact quote.";
|
|
58015
|
+
if (offer?.free)
|
|
58016
|
+
return `Free: this endpoint asks only for proof of which wallet is calling (a zero-amount MPP challenge on ${offer.network_name ?? "Tempo"}). Calling it signs that proof; nothing is paid and no balance is needed on ${offer.network_name ?? "that network"} or anywhere else, so never move funds for it. Call it with call_paid_service.`;
|
|
57938
58017
|
if (!offer) {
|
|
57939
58018
|
const offered = [...new Set(offers.map(networkLabel))];
|
|
57940
58019
|
return `${offered.length ? `This service offers ${offered.join(", ")}` : "This service advertises no recognised payment option"}; payable here: ${describeRails(this.rails)}. ${quote}`;
|
|
57941
58020
|
}
|
|
57942
58021
|
if (this.options.negotiated) {
|
|
57943
|
-
const
|
|
57944
|
-
|
|
58022
|
+
const payable = offers.filter((candidate) => candidate.rail !== "unsupported" && this.rails.includes(candidate.rail));
|
|
58023
|
+
const networks = payableNetworks(offers, this.rails).map((name) => {
|
|
58024
|
+
const price = payable.filter((candidate) => candidate.network_name === name).map((candidate) => candidate.price_usd ?? 0).sort((a, b) => a - b)[0];
|
|
58025
|
+
return `${networkLabel({ ...offer, network_name: name, rail: "x402-base" })}${price !== void 0 ? ` ($${price.toFixed(price < 0.01 ? 4 : 2)})` : ""}`;
|
|
58026
|
+
});
|
|
58027
|
+
const one = networks.length > 1 ? " Any one of these networks covering the price is enough: no move is needed while one of them does." : "";
|
|
58028
|
+
return `Payable on ${networks.join(", ")}. The hosted gateway pays the cheapest of them that your spendable balance on that network covers, Base first on a tie; price_usd is the ceiling across them.${one} ${quote}`;
|
|
57945
58029
|
}
|
|
57946
58030
|
const preferred = this.options.paymentNetwork ?? "base";
|
|
57947
58031
|
const reason = payableNetworks(offers, this.rails).includes(preferred) ? `your ${preferred} balance does not cover it` : `${preferred} is not offered`;
|
|
@@ -58013,14 +58097,14 @@ var init_discovery = __esm({
|
|
|
58013
58097
|
*/
|
|
58014
58098
|
async search(query, options = {}) {
|
|
58015
58099
|
const limit = Math.min(20, Math.max(1, options.limit ?? 8));
|
|
58016
|
-
const { rank, ...searchOptions } = options;
|
|
58100
|
+
const { rank: rank2, ...searchOptions } = options;
|
|
58017
58101
|
const [result, balances] = await Promise.all([
|
|
58018
58102
|
bounded(() => this.searchApi(query, { ...searchOptions, limit: Math.min(50, limit * 3) }), CATALOG_DEADLINE_MS, "AgentCash search"),
|
|
58019
|
-
|
|
58103
|
+
rank2 && this.options.balances ? withDeadline(() => this.options.balances(), CATALOG_DEADLINE_MS, "wallet balance read").catch(() => void 0) : Promise.resolve(void 0)
|
|
58020
58104
|
]);
|
|
58021
58105
|
const candidates = result.ok ? searchResults(result.data) : [];
|
|
58022
|
-
if (
|
|
58023
|
-
const ranking = await bounded(() =>
|
|
58106
|
+
if (rank2) {
|
|
58107
|
+
const ranking = await bounded(() => rank2({
|
|
58024
58108
|
query,
|
|
58025
58109
|
networks: this.networks(),
|
|
58026
58110
|
...balances ? { balances } : {},
|
|
@@ -58039,7 +58123,7 @@ var init_discovery = __esm({
|
|
|
58039
58123
|
const verified = await this.verified(candidates, limit);
|
|
58040
58124
|
return { ok: true, data: {
|
|
58041
58125
|
services: verified.services,
|
|
58042
|
-
note: `AgentCash discovery${
|
|
58126
|
+
note: `AgentCash discovery${rank2 ? " (CrowdCode ranking unavailable)" : ""}, verified ${describeRails(this.rails)}. New/unreviewed services are allowed. Inspect the chosen endpoint before paying.${this.partialNote(verified.incomplete)}`
|
|
58043
58127
|
} };
|
|
58044
58128
|
}
|
|
58045
58129
|
async discoverEndpoints(origin) {
|
|
@@ -58477,9 +58561,82 @@ var init_crowdcode = __esm({
|
|
|
58477
58561
|
}
|
|
58478
58562
|
});
|
|
58479
58563
|
|
|
58564
|
+
// ../../packages/economy/dist/follow-ups.js
|
|
58565
|
+
import { readFile as readFile8, writeFile as writeFile4 } from "node:fs/promises";
|
|
58566
|
+
import { join as join10 } from "node:path";
|
|
58567
|
+
function findFollowUpTokens(body) {
|
|
58568
|
+
const found = [];
|
|
58569
|
+
const walk4 = (value, path3, depth) => {
|
|
58570
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || depth > MAX_DEPTH)
|
|
58571
|
+
return;
|
|
58572
|
+
for (const [key, child] of Object.entries(value)) {
|
|
58573
|
+
if (typeof child === "string" && TOKEN_FIELD.test(key) && child.length > 0 && child.length <= MAX_TOKEN_CHARS)
|
|
58574
|
+
found.push({ field: [...path3, key].join("."), value: child });
|
|
58575
|
+
else
|
|
58576
|
+
walk4(child, [...path3, key], depth + 1);
|
|
58577
|
+
}
|
|
58578
|
+
};
|
|
58579
|
+
walk4(body, [], 0);
|
|
58580
|
+
return found;
|
|
58581
|
+
}
|
|
58582
|
+
function matchesTemplate(template, path3) {
|
|
58583
|
+
const pattern = template.split("/").map((part) => /^\{[^}]+\}$/.test(part) ? "[^/]+" : part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("/");
|
|
58584
|
+
return new RegExp(`^${pattern}/?$`).test(path3);
|
|
58585
|
+
}
|
|
58586
|
+
function documentedHeader(openapi, url3, method, field) {
|
|
58587
|
+
const paths2 = openapi?.paths;
|
|
58588
|
+
if (!paths2 || typeof paths2 !== "object")
|
|
58589
|
+
return void 0;
|
|
58590
|
+
const { pathname } = new URL(url3);
|
|
58591
|
+
const leaf = field.split(".").pop().toLowerCase();
|
|
58592
|
+
for (const [template, item] of Object.entries(paths2)) {
|
|
58593
|
+
if (!matchesTemplate(template, pathname))
|
|
58594
|
+
continue;
|
|
58595
|
+
const operation = item?.[method.toLowerCase()] ?? {};
|
|
58596
|
+
const parameters = [...item.parameters ?? [], ...operation.parameters ?? []].filter((p) => !!p && typeof p === "object" && p.in === "header" && typeof p.name === "string");
|
|
58597
|
+
const named = parameters.find((p) => (p.description ?? "").toLowerCase().includes(leaf)) ?? parameters.find((p) => /unlock|re-?read/i.test(p.name));
|
|
58598
|
+
if (named && /^[A-Za-z0-9-]{1,64}$/.test(named.name) && !/^(authorization|cookie|payment-signature|x-payment)$/i.test(named.name))
|
|
58599
|
+
return named.name;
|
|
58600
|
+
}
|
|
58601
|
+
return void 0;
|
|
58602
|
+
}
|
|
58603
|
+
async function loadFollowUps(session) {
|
|
58604
|
+
try {
|
|
58605
|
+
const parsed = JSON.parse(await readFile8(storePath(session), "utf8"));
|
|
58606
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
58607
|
+
} catch {
|
|
58608
|
+
return {};
|
|
58609
|
+
}
|
|
58610
|
+
}
|
|
58611
|
+
async function saveFollowUp(session, key, credential) {
|
|
58612
|
+
const all = await loadFollowUps(session);
|
|
58613
|
+
all[key] = credential;
|
|
58614
|
+
await writeFile4(storePath(session), JSON.stringify(all, null, 2), { mode: 384 });
|
|
58615
|
+
}
|
|
58616
|
+
async function sellerOpenApi(origin, fetchJson) {
|
|
58617
|
+
for (const path3 of OPENAPI_PATHS) {
|
|
58618
|
+
const document = await fetchJson(`${origin}${path3}`).catch(() => void 0);
|
|
58619
|
+
if (document && typeof document === "object" && "paths" in document)
|
|
58620
|
+
return document;
|
|
58621
|
+
}
|
|
58622
|
+
return void 0;
|
|
58623
|
+
}
|
|
58624
|
+
var TOKEN_FIELD, MAX_DEPTH, MAX_TOKEN_CHARS, OPENAPI_PATHS, storePath, followUpKey;
|
|
58625
|
+
var init_follow_ups = __esm({
|
|
58626
|
+
"../../packages/economy/dist/follow-ups.js"() {
|
|
58627
|
+
"use strict";
|
|
58628
|
+
TOKEN_FIELD = /^(unlock|re-?read|access|entitlement)[_-]?token$/i;
|
|
58629
|
+
MAX_DEPTH = 4;
|
|
58630
|
+
MAX_TOKEN_CHARS = 4096;
|
|
58631
|
+
OPENAPI_PATHS = ["/openapi.json", "/.well-known/openapi.json"];
|
|
58632
|
+
storePath = (session) => join10(session.sessionDir, "follow-up-credentials.json");
|
|
58633
|
+
followUpKey = (method, url3) => `${method.toUpperCase()} ${url3}`;
|
|
58634
|
+
}
|
|
58635
|
+
});
|
|
58636
|
+
|
|
58480
58637
|
// ../../packages/economy/dist/crowdcode-preferences.js
|
|
58481
|
-
import { mkdir as mkdir8, readFile as
|
|
58482
|
-
import { dirname as dirname8, join as
|
|
58638
|
+
import { mkdir as mkdir8, readFile as readFile9, rename as rename2, writeFile as writeFile5 } from "node:fs/promises";
|
|
58639
|
+
import { dirname as dirname8, join as join11 } from "node:path";
|
|
58483
58640
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
58484
58641
|
var CrowdCodePreferences;
|
|
58485
58642
|
var init_crowdcode_preferences = __esm({
|
|
@@ -58491,11 +58648,11 @@ var init_crowdcode_preferences = __esm({
|
|
|
58491
58648
|
this.session = session;
|
|
58492
58649
|
}
|
|
58493
58650
|
path(scope) {
|
|
58494
|
-
return
|
|
58651
|
+
return join11(scope === "session" ? this.session.sessionDir : this.session.workspaceRoot, "crowdcode-preferences.json");
|
|
58495
58652
|
}
|
|
58496
58653
|
async read(scope) {
|
|
58497
58654
|
try {
|
|
58498
|
-
const value = JSON.parse(await
|
|
58655
|
+
const value = JSON.parse(await readFile9(this.path(scope), "utf8"));
|
|
58499
58656
|
return typeof value.enabled === "boolean" ? value.enabled : void 0;
|
|
58500
58657
|
} catch (error53) {
|
|
58501
58658
|
if (error53.code === "ENOENT")
|
|
@@ -58511,7 +58668,7 @@ var init_crowdcode_preferences = __esm({
|
|
|
58511
58668
|
async write(scope, enabled) {
|
|
58512
58669
|
const path3 = this.path(scope), temporary = `${path3}.${randomUUID4()}.tmp`;
|
|
58513
58670
|
await mkdir8(dirname8(path3), { recursive: true });
|
|
58514
|
-
await
|
|
58671
|
+
await writeFile5(temporary, JSON.stringify({ enabled }) + "\n", { mode: 384 });
|
|
58515
58672
|
await rename2(temporary, path3);
|
|
58516
58673
|
}
|
|
58517
58674
|
async set(enabled, scope) {
|
|
@@ -58635,11 +58792,11 @@ var init_media = __esm({
|
|
|
58635
58792
|
});
|
|
58636
58793
|
|
|
58637
58794
|
// ../../packages/economy/dist/purchases.js
|
|
58638
|
-
import { appendFile as appendFile3, mkdir as mkdir9, readFile as
|
|
58639
|
-
import { dirname as dirname9, join as
|
|
58795
|
+
import { appendFile as appendFile3, mkdir as mkdir9, readFile as readFile10 } from "node:fs/promises";
|
|
58796
|
+
import { dirname as dirname9, join as join12 } from "node:path";
|
|
58640
58797
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
58641
58798
|
function purchasesPath(session) {
|
|
58642
|
-
return
|
|
58799
|
+
return join12(session.sessionDir, "purchases.jsonl");
|
|
58643
58800
|
}
|
|
58644
58801
|
function newPurchaseId() {
|
|
58645
58802
|
return `pur_${randomUUID5().slice(0, 12)}`;
|
|
@@ -58676,7 +58833,7 @@ async function appendPurchaseEvent(session, event) {
|
|
|
58676
58833
|
async function listPurchases(session) {
|
|
58677
58834
|
let text;
|
|
58678
58835
|
try {
|
|
58679
|
-
text = await
|
|
58836
|
+
text = await readFile10(purchasesPath(session), "utf8");
|
|
58680
58837
|
} catch (error53) {
|
|
58681
58838
|
if (error53.code === "ENOENT") {
|
|
58682
58839
|
return [];
|
|
@@ -58745,8 +58902,8 @@ var init_purchases = __esm({
|
|
|
58745
58902
|
});
|
|
58746
58903
|
|
|
58747
58904
|
// ../../packages/economy/dist/gateway.js
|
|
58748
|
-
import { readFile as
|
|
58749
|
-
import { join as
|
|
58905
|
+
import { readFile as readFile11, writeFile as writeFile6 } from "node:fs/promises";
|
|
58906
|
+
import { join as join13 } from "node:path";
|
|
58750
58907
|
async function boundResponse(session, data) {
|
|
58751
58908
|
return capStrings(await extractMedia(session, data), MAX_EXTERNAL_STRING_CHARS);
|
|
58752
58909
|
}
|
|
@@ -58847,6 +59004,7 @@ var init_gateway = __esm({
|
|
|
58847
59004
|
init_dist();
|
|
58848
59005
|
init_dist2();
|
|
58849
59006
|
init_offers();
|
|
59007
|
+
init_follow_ups();
|
|
58850
59008
|
init_approvals();
|
|
58851
59009
|
init_purchases();
|
|
58852
59010
|
GATEWAY_TOOL_NAMES = [
|
|
@@ -58878,14 +59036,14 @@ var init_gateway = __esm({
|
|
|
58878
59036
|
this.options = options;
|
|
58879
59037
|
}
|
|
58880
59038
|
get inspectionsPath() {
|
|
58881
|
-
return
|
|
59039
|
+
return join13(this.options.session.sessionDir, "inspections.json");
|
|
58882
59040
|
}
|
|
58883
59041
|
async loadInspections() {
|
|
58884
59042
|
if (this.inspections)
|
|
58885
59043
|
return this.inspections;
|
|
58886
59044
|
const map3 = /* @__PURE__ */ new Map();
|
|
58887
59045
|
try {
|
|
58888
|
-
const stored = JSON.parse(await
|
|
59046
|
+
const stored = JSON.parse(await readFile11(this.inspectionsPath, "utf8"));
|
|
58889
59047
|
for (const [key, value] of Object.entries(stored))
|
|
58890
59048
|
map3.set(key, value);
|
|
58891
59049
|
} catch {
|
|
@@ -58896,7 +59054,7 @@ var init_gateway = __esm({
|
|
|
58896
59054
|
async rememberInspection(key, inspection) {
|
|
58897
59055
|
const map3 = await this.loadInspections();
|
|
58898
59056
|
map3.set(key, inspection);
|
|
58899
|
-
await
|
|
59057
|
+
await writeFile6(this.inspectionsPath, JSON.stringify(Object.fromEntries(map3)), "utf8");
|
|
58900
59058
|
}
|
|
58901
59059
|
definitions() {
|
|
58902
59060
|
return GATEWAY_TOOL_DEFINITIONS;
|
|
@@ -58997,8 +59155,8 @@ var init_gateway = __esm({
|
|
|
58997
59155
|
}
|
|
58998
59156
|
if (query) {
|
|
58999
59157
|
const findServices = this.options.crowdcode.findServices?.bind(this.options.crowdcode);
|
|
59000
|
-
const
|
|
59001
|
-
const result = await this.options.agentcash.search(query, { limit: intArg(args.limit), ...
|
|
59158
|
+
const rank2 = findServices && await this.crowdcodeEnabled().catch(() => false) ? findServices : void 0;
|
|
59159
|
+
const result = await this.options.agentcash.search(query, { limit: intArg(args.limit), ...rank2 ? { rank: rank2 } : {} });
|
|
59002
59160
|
return result.ok ? { ok: true, data: result.data } : { ok: false, error: result.error };
|
|
59003
59161
|
}
|
|
59004
59162
|
return { ok: false, error: "find_paid_service requires `origin` (known origin) or `query` (capability search)" };
|
|
@@ -59019,7 +59177,8 @@ var init_gateway = __esm({
|
|
|
59019
59177
|
}
|
|
59020
59178
|
const evidence = await this.serviceEvidence(endpoint);
|
|
59021
59179
|
const rail = railFromSchema(schema.data);
|
|
59022
|
-
const
|
|
59180
|
+
const free = schema.data?.free === true;
|
|
59181
|
+
const priceCeilingCents = free ? 0 : priceCeilingFromSchema(schema.data);
|
|
59023
59182
|
const payTo = schema.data && typeof schema.data === "object" && typeof schema.data.pay_to === "string" ? schema.data.pay_to : void 0;
|
|
59024
59183
|
await this.rememberInspection(inspectionKey(endpoint, method), {
|
|
59025
59184
|
endpoint,
|
|
@@ -59037,6 +59196,8 @@ var init_gateway = __esm({
|
|
|
59037
59196
|
method,
|
|
59038
59197
|
rail,
|
|
59039
59198
|
price_ceiling_cents: priceCeilingCents,
|
|
59199
|
+
// A free, signed call is the one thing never to move funds for; say it first.
|
|
59200
|
+
...free ? { free: true, note: schema.data.note } : {},
|
|
59040
59201
|
schema: schema.data,
|
|
59041
59202
|
reputation: evidence.ok ? {
|
|
59042
59203
|
score: evidence.score,
|
|
@@ -59080,6 +59241,9 @@ var init_gateway = __esm({
|
|
|
59080
59241
|
error: `this endpoint offers no payment rail this agent can pay automatically (payable: ${describeRails(rails)})`
|
|
59081
59242
|
};
|
|
59082
59243
|
}
|
|
59244
|
+
const reread = await this.followUpRead(target, method, body);
|
|
59245
|
+
if (reread)
|
|
59246
|
+
return reread;
|
|
59083
59247
|
const requestedCostCents = intArg(args.max_cost_cents) ?? inspection.priceCeilingCents;
|
|
59084
59248
|
let quotedCostCents = requestedCostCents;
|
|
59085
59249
|
let quoteIdentity;
|
|
@@ -59200,6 +59364,7 @@ var init_gateway = __esm({
|
|
|
59200
59364
|
].join(" ")
|
|
59201
59365
|
};
|
|
59202
59366
|
}
|
|
59367
|
+
const followUp = result.ok && paid ? await this.keepFollowUp(target, method, result.data, purchaseId) : void 0;
|
|
59203
59368
|
return {
|
|
59204
59369
|
ok: result.ok,
|
|
59205
59370
|
data: {
|
|
@@ -59211,12 +59376,84 @@ var init_gateway = __esm({
|
|
|
59211
59376
|
review_required: record3.review_required,
|
|
59212
59377
|
review_available: true,
|
|
59213
59378
|
...result.note ? { note: result.note } : {},
|
|
59379
|
+
...followUp ? { follow_up: followUp } : {},
|
|
59214
59380
|
data: result.data,
|
|
59215
59381
|
...result.ok ? {} : { error: result.error }
|
|
59216
59382
|
},
|
|
59217
59383
|
...result.ok ? {} : { error: result.error }
|
|
59218
59384
|
};
|
|
59219
59385
|
}
|
|
59386
|
+
/**
|
|
59387
|
+
* Keep a follow-up token a paid answer carried, with the request header its
|
|
59388
|
+
* seller documents for it, and tell the model what it is for.
|
|
59389
|
+
*/
|
|
59390
|
+
async keepFollowUp(url3, method, data, purchaseId) {
|
|
59391
|
+
const tokens2 = findFollowUpTokens(data);
|
|
59392
|
+
if (!tokens2.length)
|
|
59393
|
+
return void 0;
|
|
59394
|
+
const fetchFree = this.options.agentcash.fetchFree?.bind(this.options.agentcash);
|
|
59395
|
+
const openapi = fetchFree ? await sellerOpenApi(originOf2(url3), async (address2) => {
|
|
59396
|
+
const response = await fetchFree({ url: address2, method: "GET" });
|
|
59397
|
+
return response.ok ? response.data : void 0;
|
|
59398
|
+
}).catch(() => void 0) : void 0;
|
|
59399
|
+
for (const token of tokens2) {
|
|
59400
|
+
const header = openapi ? documentedHeader(openapi, url3, method, token.field) : void 0;
|
|
59401
|
+
if (!header)
|
|
59402
|
+
continue;
|
|
59403
|
+
await saveFollowUp(this.options.session, followUpKey(method, url3), { header, value: token.value, field: token.field, purchaseId, savedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
59404
|
+
return {
|
|
59405
|
+
header,
|
|
59406
|
+
token_field: token.field,
|
|
59407
|
+
saved: true,
|
|
59408
|
+
note: `The seller issued a follow-up token (${token.field}) and documents the ${header} request header for it. It is saved: calling this same URL again with call_paid_service sends ${header} automatically, and a seller that honours it answers without charging.`
|
|
59409
|
+
};
|
|
59410
|
+
}
|
|
59411
|
+
return {
|
|
59412
|
+
token_field: tokens2[0].field,
|
|
59413
|
+
saved: false,
|
|
59414
|
+
note: `This answer carries a follow-up token (${tokens2[0].field}), but the seller's OpenAPI names no request header for it. Check the seller's documentation before paying for the same request again.`
|
|
59415
|
+
};
|
|
59416
|
+
}
|
|
59417
|
+
/** The same request again with a saved follow-up token, unpaid. */
|
|
59418
|
+
async followUpRead(url3, method, body) {
|
|
59419
|
+
const fetchFree = this.options.agentcash.fetchFree?.bind(this.options.agentcash);
|
|
59420
|
+
if (!fetchFree)
|
|
59421
|
+
return void 0;
|
|
59422
|
+
const credential = (await loadFollowUps(this.options.session))[followUpKey(method, url3)];
|
|
59423
|
+
if (!credential)
|
|
59424
|
+
return void 0;
|
|
59425
|
+
const result = await fetchFree({
|
|
59426
|
+
url: url3,
|
|
59427
|
+
method,
|
|
59428
|
+
body: typeof body === "string" ? body : body === void 0 ? void 0 : JSON.stringify(body),
|
|
59429
|
+
headers: { [credential.header]: credential.value }
|
|
59430
|
+
}).catch(() => void 0);
|
|
59431
|
+
if (!result?.ok || result.status === 402 || result.data === void 0)
|
|
59432
|
+
return void 0;
|
|
59433
|
+
const data = await boundResponse(this.options.session, result.data);
|
|
59434
|
+
const artifact = await saveArtifact(this.options.session, `service-calls/${Date.now()}-${slugUrl(url3)}.json`, JSON.stringify({ status: result.status, body: data }, null, 2), { endpoint: url3, method });
|
|
59435
|
+
await appendLedgerEntry(this.options.session.ledgerPath, {
|
|
59436
|
+
session_id: this.options.session.sessionId,
|
|
59437
|
+
type: "service_call",
|
|
59438
|
+
resource_url: url3,
|
|
59439
|
+
method,
|
|
59440
|
+
quoted_cost_cents: 0,
|
|
59441
|
+
charged_cost_cents: 0,
|
|
59442
|
+
status: "ok",
|
|
59443
|
+
approval_mode: this.options.session.approvalMode,
|
|
59444
|
+
artifact_path: artifact?.path,
|
|
59445
|
+
notes: `free follow-up with ${credential.header} from purchase ${credential.purchaseId ?? "?"}`
|
|
59446
|
+
});
|
|
59447
|
+
return { ok: true, data: {
|
|
59448
|
+
outcome: "free",
|
|
59449
|
+
status: result.status,
|
|
59450
|
+
charged_cost_cents: 0,
|
|
59451
|
+
artifact_path: artifact?.path,
|
|
59452
|
+
review_required: false,
|
|
59453
|
+
note: `Free re-read: sent the ${credential.header} token this seller issued with your earlier purchase${credential.purchaseId ? ` ${credential.purchaseId}` : ""}; nothing was paid. This is the same content that purchase bought.`,
|
|
59454
|
+
data
|
|
59455
|
+
} };
|
|
59456
|
+
}
|
|
59220
59457
|
async resolveApproval(endpoint, method, quotedCostCents, evidence) {
|
|
59221
59458
|
const origin = originOf2(endpoint);
|
|
59222
59459
|
const rules = await loadApprovalRules(this.options.approvalRulesPath);
|
|
@@ -59771,6 +60008,7 @@ var init_dist4 = __esm({
|
|
|
59771
60008
|
init_agentcash2();
|
|
59772
60009
|
init_approvals();
|
|
59773
60010
|
init_crowdcode();
|
|
60011
|
+
init_follow_ups();
|
|
59774
60012
|
init_gateway();
|
|
59775
60013
|
init_mcp();
|
|
59776
60014
|
init_media();
|
|
@@ -59785,7 +60023,7 @@ var init_dist4 = __esm({
|
|
|
59785
60023
|
|
|
59786
60024
|
// ../../packages/agent-runtime/dist/context.js
|
|
59787
60025
|
import { createHash as createHash3 } from "node:crypto";
|
|
59788
|
-
import { relative as relative3, join as
|
|
60026
|
+
import { relative as relative3, join as join14 } from "node:path";
|
|
59789
60027
|
function requestMessages(messages, state) {
|
|
59790
60028
|
if (state.trailingMessage)
|
|
59791
60029
|
return [...messages, state.trailingMessage];
|
|
@@ -59897,14 +60135,14 @@ async function compactContext(session, messages, options) {
|
|
|
59897
60135
|
return { tokensBefore, tokensAfter: tokensBefore };
|
|
59898
60136
|
const raw = messages.map((message) => JSON.stringify(message)).join("\n") + "\n";
|
|
59899
60137
|
const digest = createHash3("sha256").update(raw).digest("hex");
|
|
59900
|
-
const dir = await containedPath(session.sessionDir,
|
|
59901
|
-
const path3 =
|
|
60138
|
+
const dir = await containedPath(session.sessionDir, join14("context", digest));
|
|
60139
|
+
const path3 = join14(dir, "transcript.jsonl");
|
|
59902
60140
|
await atomicWrite(path3, raw);
|
|
59903
60141
|
const archivePath = relative3(session.sessionDir, path3).split("\\").join("/");
|
|
59904
60142
|
const ref = (index2) => `${relative3(session.sessionDir, dir).split("\\").join("/")}/message-${index2 + 1}.txt`;
|
|
59905
60143
|
const saved = /* @__PURE__ */ new Set();
|
|
59906
60144
|
const externalize = async (message, index2) => {
|
|
59907
|
-
await atomicWrite(
|
|
60145
|
+
await atomicWrite(join14(dir, `message-${index2 + 1}.txt`), messages[index2].content);
|
|
59908
60146
|
saved.add(index2);
|
|
59909
60147
|
const preview = message.role === "user" ? ` It began: "${oneLine(messages[index2].content, EXTERNALIZE_PREVIEW_CHARS)}"` : "";
|
|
59910
60148
|
return `[Full ${message.role} message saved verbatim to ${ref(index2)}. Use rg/grep and sed/head/tail to read relevant portions before proceeding; do not load the entire file.${preview}]`;
|
|
@@ -60029,8 +60267,8 @@ var init_context2 = __esm({
|
|
|
60029
60267
|
});
|
|
60030
60268
|
|
|
60031
60269
|
// ../../packages/agent-runtime/dist/knowledge.js
|
|
60032
|
-
import { access, cp, mkdir as mkdir10, readFile as
|
|
60033
|
-
import { dirname as dirname10, join as
|
|
60270
|
+
import { access, cp, mkdir as mkdir10, readFile as readFile12, writeFile as writeFile7 } from "node:fs/promises";
|
|
60271
|
+
import { dirname as dirname10, join as join15, resolve as resolve4 } from "node:path";
|
|
60034
60272
|
import { fileURLToPath } from "node:url";
|
|
60035
60273
|
function bundledKnowledgeDir() {
|
|
60036
60274
|
return resolve4(dirname10(fileURLToPath(import.meta.url)), "..", "knowledge");
|
|
@@ -60049,7 +60287,7 @@ async function resolveKnowledgeDir(options = {}) {
|
|
|
60049
60287
|
}
|
|
60050
60288
|
const bundled = bundledKnowledgeDir();
|
|
60051
60289
|
try {
|
|
60052
|
-
await access(
|
|
60290
|
+
await access(join15(bundled, "L0.md"));
|
|
60053
60291
|
return bundled;
|
|
60054
60292
|
} catch {
|
|
60055
60293
|
return void 0;
|
|
@@ -60062,12 +60300,12 @@ async function loadKnowledgeTree(session, options = {}) {
|
|
|
60062
60300
|
}
|
|
60063
60301
|
let l0;
|
|
60064
60302
|
try {
|
|
60065
|
-
l0 = (await
|
|
60303
|
+
l0 = (await readFile12(join15(dir, "L0.md"), "utf8")).trim();
|
|
60066
60304
|
} catch {
|
|
60067
60305
|
return void 0;
|
|
60068
60306
|
}
|
|
60069
60307
|
const version6 = await readVersion(dir, l0);
|
|
60070
|
-
const target =
|
|
60308
|
+
const target = join15(session.artifactsDir, "knowledge");
|
|
60071
60309
|
if (await currentVersion(target) !== version6) {
|
|
60072
60310
|
await mkdir10(session.artifactsDir, { recursive: true });
|
|
60073
60311
|
await cp(dir, target, {
|
|
@@ -60075,7 +60313,7 @@ async function loadKnowledgeTree(session, options = {}) {
|
|
|
60075
60313
|
force: true,
|
|
60076
60314
|
filter: (source) => !source.endsWith("proposal.raw.txt")
|
|
60077
60315
|
});
|
|
60078
|
-
await
|
|
60316
|
+
await writeFile7(join15(target, VERSION_FILE), `${version6}
|
|
60079
60317
|
`, "utf8");
|
|
60080
60318
|
}
|
|
60081
60319
|
if (session.knowledge?.version !== version6 || session.knowledge?.source !== dir) {
|
|
@@ -60093,7 +60331,7 @@ function renderCapabilityIndex(l0) {
|
|
|
60093
60331
|
}
|
|
60094
60332
|
async function readVersion(dir, l0) {
|
|
60095
60333
|
try {
|
|
60096
|
-
const meta4 = JSON.parse(await
|
|
60334
|
+
const meta4 = JSON.parse(await readFile12(join15(dir, "meta.json"), "utf8"));
|
|
60097
60335
|
if (typeof meta4.content_hash === "string" && meta4.content_hash) {
|
|
60098
60336
|
return meta4.id ? `${meta4.id}@${meta4.content_hash}` : meta4.content_hash;
|
|
60099
60337
|
}
|
|
@@ -60104,7 +60342,7 @@ async function readVersion(dir, l0) {
|
|
|
60104
60342
|
}
|
|
60105
60343
|
async function currentVersion(target) {
|
|
60106
60344
|
try {
|
|
60107
|
-
return (await
|
|
60345
|
+
return (await readFile12(join15(target, VERSION_FILE), "utf8")).trim();
|
|
60108
60346
|
} catch {
|
|
60109
60347
|
return void 0;
|
|
60110
60348
|
}
|
|
@@ -87223,8 +87461,8 @@ var init_economy_tools = __esm({
|
|
|
87223
87461
|
});
|
|
87224
87462
|
|
|
87225
87463
|
// ../../packages/agent-runtime/dist/runtime.js
|
|
87226
|
-
import { readFile as
|
|
87227
|
-
import { join as
|
|
87464
|
+
import { readFile as readFile13, rm as rm2 } from "node:fs/promises";
|
|
87465
|
+
import { join as join20 } from "node:path";
|
|
87228
87466
|
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
87229
87467
|
function createOpenCrowdRuntime(options) {
|
|
87230
87468
|
const storage = options.storage ?? localRuntimeStorage;
|
|
@@ -87257,10 +87495,10 @@ function createOpenCrowdRuntime(options) {
|
|
|
87257
87495
|
};
|
|
87258
87496
|
}
|
|
87259
87497
|
async function execute2(session, task, runOptions = {}) {
|
|
87260
|
-
const path3 =
|
|
87498
|
+
const path3 = join20(session.sessionDir, "query-checkpoint.json");
|
|
87261
87499
|
let persisted;
|
|
87262
87500
|
try {
|
|
87263
|
-
persisted = JSON.parse(await
|
|
87501
|
+
persisted = JSON.parse(await readFile13(path3, "utf8"));
|
|
87264
87502
|
} catch (error53) {
|
|
87265
87503
|
if (error53.code !== "ENOENT")
|
|
87266
87504
|
throw error53;
|
|
@@ -87545,9 +87783,180 @@ var init_hosted_provider = __esm({
|
|
|
87545
87783
|
}
|
|
87546
87784
|
});
|
|
87547
87785
|
|
|
87786
|
+
// ../../packages/agent-runtime/dist/funding-plan.js
|
|
87787
|
+
function spendable(funds) {
|
|
87788
|
+
return Math.max(0, funds.availableUsd - (funds.keepUsd ?? 0));
|
|
87789
|
+
}
|
|
87790
|
+
function simulate(calls, start) {
|
|
87791
|
+
const left = new Map(start);
|
|
87792
|
+
const assigned = [];
|
|
87793
|
+
for (const call2 of calls) {
|
|
87794
|
+
const free = call2.offers.find((offer) => offer.free);
|
|
87795
|
+
if (free) {
|
|
87796
|
+
assigned.push({ url: call2.url, method: call2.method, count: call2.count, network: free.network, priceUsd: 0, totalUsd: 0, free: true });
|
|
87797
|
+
continue;
|
|
87798
|
+
}
|
|
87799
|
+
if (!call2.offers.length) {
|
|
87800
|
+
assigned.push({ url: call2.url, method: call2.method, count: call2.count, totalUsd: 0, unpaid: true, error: call2.error ?? "no payable offer" });
|
|
87801
|
+
continue;
|
|
87802
|
+
}
|
|
87803
|
+
for (let i = 0; i < call2.count; i++) {
|
|
87804
|
+
const offer = [...call2.offers].filter((candidate) => (left.get(candidate.network) ?? 0) + 1e-9 >= candidate.priceUsd).sort((a, b) => a.priceUsd - b.priceUsd || rank(a.network) - rank(b.network))[0];
|
|
87805
|
+
const previous = assigned[assigned.length - 1];
|
|
87806
|
+
const sameAsPrevious = i > 0 && previous && previous.network === offer?.network && !previous.unpaid;
|
|
87807
|
+
if (offer)
|
|
87808
|
+
left.set(offer.network, (left.get(offer.network) ?? 0) - offer.priceUsd);
|
|
87809
|
+
if (sameAsPrevious) {
|
|
87810
|
+
previous.count += 1;
|
|
87811
|
+
previous.totalUsd = cents(previous.totalUsd + offer.priceUsd);
|
|
87812
|
+
continue;
|
|
87813
|
+
}
|
|
87814
|
+
const cheapest = [...call2.offers].sort((a, b) => a.priceUsd - b.priceUsd || rank(a.network) - rank(b.network))[0];
|
|
87815
|
+
assigned.push(offer ? { url: call2.url, method: call2.method, count: 1, network: offer.network, priceUsd: offer.priceUsd, totalUsd: offer.priceUsd } : { url: call2.url, method: call2.method, count: 1, priceUsd: cheapest.priceUsd, totalUsd: cheapest.priceUsd, unpaid: true });
|
|
87816
|
+
}
|
|
87817
|
+
}
|
|
87818
|
+
const merged = [];
|
|
87819
|
+
for (const call2 of assigned) {
|
|
87820
|
+
const last = merged[merged.length - 1];
|
|
87821
|
+
if (last && last.unpaid && call2.unpaid && last.url === call2.url && last.method === call2.method && !last.error && !call2.error) {
|
|
87822
|
+
last.count += call2.count;
|
|
87823
|
+
last.totalUsd = cents(last.totalUsd + call2.totalUsd);
|
|
87824
|
+
} else
|
|
87825
|
+
merged.push({ ...call2 });
|
|
87826
|
+
}
|
|
87827
|
+
return { calls: merged, left, unpaid: merged.some((call2) => call2.unpaid && !call2.error) };
|
|
87828
|
+
}
|
|
87829
|
+
function planTaskFunding(calls, funds) {
|
|
87830
|
+
const start = new Map(funds.map((entry) => [entry.network, headroom(entry)]));
|
|
87831
|
+
const report = (planned, moves, outcome, short) => ({
|
|
87832
|
+
outcome,
|
|
87833
|
+
calls: planned.calls,
|
|
87834
|
+
moves,
|
|
87835
|
+
...short ? { short } : {},
|
|
87836
|
+
networks: funds.map((entry) => {
|
|
87837
|
+
const moved = moves.reduce((sum, move) => sum + (move.to === entry.network ? move.amountUsd - PLAN_FEE_ALLOWANCE_USD : 0) - (move.from === entry.network ? move.amountUsd : 0), 0);
|
|
87838
|
+
const plannedUsd = planned.calls.filter((call2) => call2.network === entry.network && !call2.unpaid).reduce((sum, call2) => sum + call2.totalUsd, 0);
|
|
87839
|
+
return {
|
|
87840
|
+
network: entry.network,
|
|
87841
|
+
availableUsd: cents(entry.availableUsd),
|
|
87842
|
+
hostingOwedUsd: cents(entry.hostingOwedUsd ?? 0),
|
|
87843
|
+
keepUsd: cents(entry.keepUsd ?? 0),
|
|
87844
|
+
spendableUsd: cents(spendable(entry)),
|
|
87845
|
+
plannedUsd: cents(plannedUsd),
|
|
87846
|
+
afterUsd: cents(headroom(entry) + moved - plannedUsd)
|
|
87847
|
+
};
|
|
87848
|
+
})
|
|
87849
|
+
});
|
|
87850
|
+
const now = simulate(calls, start);
|
|
87851
|
+
if (!now.unpaid)
|
|
87852
|
+
return report(now, [], "no_move");
|
|
87853
|
+
const targets = [...new Set(now.calls.filter((call2) => call2.unpaid && !call2.error).flatMap((call2) => calls.find((c) => c.url === call2.url && c.method === call2.method)?.offers.map((offer) => offer.network) ?? []))];
|
|
87854
|
+
let best;
|
|
87855
|
+
let closest;
|
|
87856
|
+
for (const target of targets.sort((a, b) => rank(a) - rank(b))) {
|
|
87857
|
+
const unlimited = simulate(calls, new Map([...start, [target, Number.MAX_SAFE_INTEGER]]));
|
|
87858
|
+
if (unlimited.unpaid)
|
|
87859
|
+
continue;
|
|
87860
|
+
const used = /* @__PURE__ */ new Map();
|
|
87861
|
+
for (const call2 of unlimited.calls)
|
|
87862
|
+
if (call2.network && !call2.unpaid)
|
|
87863
|
+
used.set(call2.network, (used.get(call2.network) ?? 0) + call2.totalUsd);
|
|
87864
|
+
const arrive = Math.max(0, (used.get(target) ?? 0) - (start.get(target) ?? 0));
|
|
87865
|
+
const amountUsd = up(arrive + PLAN_FEE_ALLOWANCE_USD);
|
|
87866
|
+
const sources = funds.filter((entry) => entry.network !== target).map((entry) => ({ network: entry.network, spare: (start.get(entry.network) ?? 0) - (used.get(entry.network) ?? 0) })).sort((a, b) => b.spare - a.spare);
|
|
87867
|
+
const source = sources[0];
|
|
87868
|
+
const gap = source ? amountUsd - source.spare : amountUsd;
|
|
87869
|
+
if (!closest || gap < closest.amountUsd)
|
|
87870
|
+
closest = { network: target, amountUsd: up(Math.max(0, gap)) };
|
|
87871
|
+
if (!source || source.spare + 1e-9 < amountUsd)
|
|
87872
|
+
continue;
|
|
87873
|
+
const move = { from: source.network, to: target, amountUsd };
|
|
87874
|
+
const after = simulate(calls, new Map([...start, [target, (start.get(target) ?? 0) + arrive], [source.network, (start.get(source.network) ?? 0) - amountUsd]]));
|
|
87875
|
+
if (after.unpaid)
|
|
87876
|
+
continue;
|
|
87877
|
+
if (!best || amountUsd < best.move.amountUsd)
|
|
87878
|
+
best = { move, planned: after };
|
|
87879
|
+
}
|
|
87880
|
+
if (best)
|
|
87881
|
+
return report(best.planned, [best.move], "one_move");
|
|
87882
|
+
const direct = targets.map((network) => {
|
|
87883
|
+
const unlimited = simulate(calls, new Map([...start, [network, Number.MAX_SAFE_INTEGER]]));
|
|
87884
|
+
const used = unlimited.calls.filter((call2) => call2.network === network && !call2.unpaid).reduce((sum, call2) => sum + call2.totalUsd, 0);
|
|
87885
|
+
return { network, amountUsd: up(Math.max(0, used - (start.get(network) ?? 0))) };
|
|
87886
|
+
}).sort((a, b) => a.amountUsd - b.amountUsd || rank(a.network) - rank(b.network))[0];
|
|
87887
|
+
return report(now, [], "short", direct ?? closest);
|
|
87888
|
+
}
|
|
87889
|
+
function describePlan(plan) {
|
|
87890
|
+
const money = (usd3) => `$${usd3.toFixed(2)}`;
|
|
87891
|
+
const steps = plan.calls.map((call2) => call2.free ? `${call2.method} ${call2.url}: free (a signed wallet-identity proof on ${call2.network}; nothing moves, no balance needed)` : call2.error ? `${call2.method} ${call2.url}: ${call2.error}` : call2.unpaid ? `${call2.count}\xD7 ${call2.method} ${call2.url}: not payable with these funds (${money(call2.totalUsd)})` : `${call2.count}\xD7 ${call2.method} ${call2.url}: pays ${money(call2.totalUsd)} on ${call2.network}`);
|
|
87892
|
+
const move = plan.moves[0];
|
|
87893
|
+
const instruction = plan.outcome === "no_move" ? "No move is needed: every planned call is payable where the funds already are. Do not call bridge_usdc for this task." : plan.outcome === "one_move" ? `Make exactly this one move, once, before the first purchase: bridge_usdc {"from":"${move.from}","to":"${move.to}","amount_usd":${move.amountUsd}} (about $0.03 of it is the fee). Then make the calls; do not move funds again, and never back the other way, in this run.` : `These funds cannot pay for the whole task with one move. Do the part that is payable without any move if it is worth doing alone, and tell the owner the exact gap: add ${money(plan.short?.amountUsd ?? 0)} on ${plan.short?.network ?? "the network the service is sold on"}. Do not move funds back and forth to make up the difference.`;
|
|
87894
|
+
return {
|
|
87895
|
+
outcome: plan.outcome,
|
|
87896
|
+
steps,
|
|
87897
|
+
moves: plan.moves.map((m) => ({ from: m.from, to: m.to, amount_usd: m.amountUsd })),
|
|
87898
|
+
...plan.short ? { short: { network: plan.short.network, amount_usd: plan.short.amountUsd } } : {},
|
|
87899
|
+
networks: plan.networks.map((n) => ({
|
|
87900
|
+
network: n.network,
|
|
87901
|
+
available_usd: n.availableUsd,
|
|
87902
|
+
hosting_owed_usd: n.hostingOwedUsd,
|
|
87903
|
+
kept_usd: n.keepUsd,
|
|
87904
|
+
spendable_usd: n.spendableUsd,
|
|
87905
|
+
planned_usd: n.plannedUsd,
|
|
87906
|
+
left_after_usd: n.afterUsd
|
|
87907
|
+
})),
|
|
87908
|
+
instruction,
|
|
87909
|
+
note: `spendable = available (balance less payment holds and, on Base, hosting owed) less what is kept: the $${HOSTING_RESERVE_USD.toFixed(2)} hosting reserve, and $${PLAN_INFERENCE_ALLOWANCE_USD.toFixed(2)} on Base for this run's own model calls.`
|
|
87910
|
+
};
|
|
87911
|
+
}
|
|
87912
|
+
var GATEWAY_PREFERENCE, PLAN_FEE_ALLOWANCE_USD, PLAN_INFERENCE_ALLOWANCE_USD, HOSTING_RESERVE_USD, cents, up, rank, headroom, PLAN_FUNDING_TOOL;
|
|
87913
|
+
var init_funding_plan = __esm({
|
|
87914
|
+
"../../packages/agent-runtime/dist/funding-plan.js"() {
|
|
87915
|
+
"use strict";
|
|
87916
|
+
GATEWAY_PREFERENCE = ["base", "solana", "tempo"];
|
|
87917
|
+
PLAN_FEE_ALLOWANCE_USD = 0.05;
|
|
87918
|
+
PLAN_INFERENCE_ALLOWANCE_USD = 0.25;
|
|
87919
|
+
HOSTING_RESERVE_USD = 0.1;
|
|
87920
|
+
cents = (usd3) => Math.round(usd3 * 100) / 100;
|
|
87921
|
+
up = (usd3) => Math.ceil(usd3 * 100 - 1e-9) / 100;
|
|
87922
|
+
rank = (network) => {
|
|
87923
|
+
const index2 = GATEWAY_PREFERENCE.indexOf(network);
|
|
87924
|
+
return index2 < 0 ? GATEWAY_PREFERENCE.length : index2;
|
|
87925
|
+
};
|
|
87926
|
+
headroom = (funds) => funds.availableUsd - (funds.keepUsd ?? 0);
|
|
87927
|
+
PLAN_FUNDING_TOOL = {
|
|
87928
|
+
name: "plan_funding",
|
|
87929
|
+
description: "Plan a task's funding once, before its first purchase, whenever the task will make more than one paid call or a call on a network you hold little on. List every call you intend to make (url, method, how many times). It reads every network and protocol each endpoint accepts \u2014 including free calls that only need a signed wallet-identity proof \u2014 and what each of your networks can really spend (balance less holds, hosting owed, the hosting reserve and an allowance for your own model calls), then says which network will pay each call and the at most one bridge_usdc move the task needs, sized to it. Read-only: nothing is paid or moved.",
|
|
87930
|
+
parameters: {
|
|
87931
|
+
type: "object",
|
|
87932
|
+
properties: {
|
|
87933
|
+
calls: {
|
|
87934
|
+
type: "array",
|
|
87935
|
+
minItems: 1,
|
|
87936
|
+
maxItems: 12,
|
|
87937
|
+
items: {
|
|
87938
|
+
type: "object",
|
|
87939
|
+
properties: {
|
|
87940
|
+
url: { type: "string", description: "Exact endpoint URL, as you will call it" },
|
|
87941
|
+
method: { type: "string", enum: ["GET", "POST"] },
|
|
87942
|
+
count: { type: "integer", minimum: 1, maximum: 20, description: "How many times you will call it (default 1)" },
|
|
87943
|
+
sample_body: { type: "object", description: "For POST: a representative body, for the exact quote" }
|
|
87944
|
+
},
|
|
87945
|
+
required: ["url"],
|
|
87946
|
+
additionalProperties: false
|
|
87947
|
+
}
|
|
87948
|
+
}
|
|
87949
|
+
},
|
|
87950
|
+
required: ["calls"],
|
|
87951
|
+
additionalProperties: false
|
|
87952
|
+
}
|
|
87953
|
+
};
|
|
87954
|
+
}
|
|
87955
|
+
});
|
|
87956
|
+
|
|
87548
87957
|
// ../../packages/agent-runtime/dist/hosted-economy.js
|
|
87549
87958
|
import { randomUUID as randomUUID7, createHash as createHash4 } from "node:crypto";
|
|
87550
|
-
import { join as
|
|
87959
|
+
import { join as join21 } from "node:path";
|
|
87551
87960
|
function describeTransferError(reply) {
|
|
87552
87961
|
return reply.code ? `${reply.error ?? "transfer refused"} (${reply.code})` : reply.error ?? "transfer refused";
|
|
87553
87962
|
}
|
|
@@ -87573,31 +87982,53 @@ function createHostedEconomy(options) {
|
|
|
87573
87982
|
const fetcher = options.fetcher ?? fetch;
|
|
87574
87983
|
const socket = { socketPath: options.socketPath, runId: options.runId, sessionId: options.sessionId };
|
|
87575
87984
|
const directory = new ServiceDirectory(fetcher, (options.crowdcodeBase ?? DEFAULT_CROWDCODE_BASE).replace(/\/+$/, ""));
|
|
87576
|
-
|
|
87985
|
+
const agentcash = new HostedAgentCashAdapter(directory, socket, fetcher, options.reconcileDelayMs, options.transferWait);
|
|
87986
|
+
const gateway = new EconomyGateway({
|
|
87577
87987
|
session: options.session,
|
|
87578
|
-
agentcash
|
|
87988
|
+
agentcash,
|
|
87579
87989
|
crowdcode: new HostedCrowdCodeAdapter(directory, socket),
|
|
87580
87990
|
approvalMode: "auto",
|
|
87581
87991
|
hostedSpending: true,
|
|
87582
87992
|
minServiceScore: 2,
|
|
87583
87993
|
paymentRails: HOSTED_RAILS,
|
|
87584
87994
|
// Hosted rules live with the agent's session, never in a user config dir.
|
|
87585
|
-
approvalRulesPath:
|
|
87995
|
+
approvalRulesPath: join21(options.session.sessionDir, "approval-rules.json")
|
|
87586
87996
|
});
|
|
87997
|
+
return Object.assign(gateway, { planFunding: (args) => agentcash.planFunding(args) });
|
|
87587
87998
|
}
|
|
87588
87999
|
function hostedDynamicTools(economy) {
|
|
87589
88000
|
const tools = economyTools(economy);
|
|
87590
|
-
|
|
88001
|
+
const plan = economy.planFunding;
|
|
88002
|
+
const definitions = tools.definitions.map((tool) => tool.name === "get_wallet_status" ? { ...tool, description: "Read this hosted agent's USDC wallet: the total across networks, each network's balance (Base, Solana, Tempo), what each can spend after payment holds and (on Base) hosting owed, and authoritative current-run inference spending, service spending, transfer fees, payment holds and authorized budget. A payment on a network needs that network's spendable balance. Read-only." } : tool.name === "bridge_usdc" ? HOSTED_BRIDGE_TOOL : tool);
|
|
88003
|
+
return {
|
|
88004
|
+
...tools,
|
|
88005
|
+
definitions: plan ? [...definitions, PLAN_FUNDING_TOOL] : definitions,
|
|
88006
|
+
execute: async (name, args, operationId) => name === "plan_funding" && plan ? plan(args) : tools.execute(name, args, operationId)
|
|
88007
|
+
};
|
|
88008
|
+
}
|
|
88009
|
+
function walletFunds(data) {
|
|
88010
|
+
const wallet = objectValue5(data);
|
|
88011
|
+
const networks = Array.isArray(wallet?.networks) ? wallet.networks : [];
|
|
88012
|
+
const owed = numberValue6(wallet?.hosting_owed_usd) ?? 0;
|
|
88013
|
+
const reserve = numberValue6(wallet?.hosting_reserve_usd) ?? HOSTING_RESERVE_USD;
|
|
88014
|
+
return networks.map(objectValue5).flatMap((row) => {
|
|
88015
|
+
const network = networkName(row?.network) ?? networkName(row?.caip2) ?? stringValue5(row?.network);
|
|
88016
|
+
const available = numberValue6(row?.available_usd ?? row?.balance_usd);
|
|
88017
|
+
if (!network || available === void 0)
|
|
88018
|
+
return [];
|
|
88019
|
+
const base2 = network === "base";
|
|
88020
|
+
return [{ network, availableUsd: available, hostingOwedUsd: base2 ? numberValue6(row?.hosting_owed_usd) ?? owed : 0, keepUsd: base2 ? reserve + PLAN_INFERENCE_ALLOWANCE_USD : 0 }];
|
|
88021
|
+
});
|
|
87591
88022
|
}
|
|
87592
88023
|
function planFundingMove(target, priceUsd, available) {
|
|
87593
|
-
const
|
|
88024
|
+
const cents2 = (usd3) => Math.floor(usd3 * 100) / 100;
|
|
87594
88025
|
const needed = Math.ceil((priceUsd + MOVE_FEE_ALLOWANCE_USD) * 100) / 100;
|
|
87595
88026
|
const source = available.filter((n) => n.network !== target).sort((a, b) => b.usd - a.usd)[0];
|
|
87596
88027
|
if (!source)
|
|
87597
88028
|
return void 0;
|
|
87598
88029
|
const reserve = source.network === "base" ? BASE_WORKING_RESERVE_USD : 0;
|
|
87599
|
-
const spare =
|
|
87600
|
-
const ceiling = Math.min(Math.max(needed, spare),
|
|
88030
|
+
const spare = cents2(Math.max(0, source.usd - reserve));
|
|
88031
|
+
const ceiling = Math.min(Math.max(needed, spare), cents2(source.usd));
|
|
87601
88032
|
const amount = Math.min(Math.max(PREFERRED_MOVE_USD, needed), ceiling);
|
|
87602
88033
|
if (amount < needed)
|
|
87603
88034
|
return void 0;
|
|
@@ -87676,6 +88107,7 @@ var init_hosted_economy = __esm({
|
|
|
87676
88107
|
init_dist4();
|
|
87677
88108
|
init_dist();
|
|
87678
88109
|
init_hosted_provider();
|
|
88110
|
+
init_funding_plan();
|
|
87679
88111
|
init_economy_tools();
|
|
87680
88112
|
DEFAULT_CROWDCODE_BASE = "https://crowdcode-backend.onrender.com";
|
|
87681
88113
|
LIST_CACHE_MS = 6e4;
|
|
@@ -87865,6 +88297,18 @@ var init_hosted_economy = __esm({
|
|
|
87865
88297
|
note: "This is your own service, so CrowdCode ran this call as a free owner test: nothing was paid or earned. Buyers pay the listed price as usual."
|
|
87866
88298
|
};
|
|
87867
88299
|
}
|
|
88300
|
+
if (data.outcome === "free_proof") {
|
|
88301
|
+
const ok4 = status !== void 0 && status < 400;
|
|
88302
|
+
return {
|
|
88303
|
+
ok: ok4,
|
|
88304
|
+
ambiguous: false,
|
|
88305
|
+
status,
|
|
88306
|
+
data: decodeBody(data.body, data.content_type),
|
|
88307
|
+
authMode: "free",
|
|
88308
|
+
error: ok4 ? void 0 : `the service answered HTTP ${status ?? "?"} to a signed identity proof`,
|
|
88309
|
+
note: `Free: the service asked only for proof of which wallet is calling (a zero-amount MPP challenge on ${stringValue5(data.network) ?? "tempo"}). CrowdCode signed it; no USDC moved and no balance was needed on any network, so never move funds for a call like this.`
|
|
88310
|
+
};
|
|
88311
|
+
}
|
|
87868
88312
|
const outcome = data.outcome === "paid_success" ? "paid_success" : "paid_failure";
|
|
87869
88313
|
const paidAtomic = numberValue6(data.amount_atomic);
|
|
87870
88314
|
const network = stringValue5(data.network);
|
|
@@ -87922,6 +88366,10 @@ var init_hosted_economy = __esm({
|
|
|
87922
88366
|
return void 0;
|
|
87923
88367
|
}
|
|
87924
88368
|
}
|
|
88369
|
+
/** An unpaid request with extra headers: a seller's documented follow-up, or its OpenAPI. */
|
|
88370
|
+
fetchFree(request2) {
|
|
88371
|
+
return this.fetchUnpaid(request2.url, request2.method.toUpperCase(), request2.body, request2.headers);
|
|
88372
|
+
}
|
|
87925
88373
|
/** The supervisor found no 402: the endpoint is free, so the worker fetches it itself. */
|
|
87926
88374
|
async fetchUnpaid(url3, method, body, headers) {
|
|
87927
88375
|
try {
|
|
@@ -87953,12 +88401,12 @@ var init_hosted_economy = __esm({
|
|
|
87953
88401
|
*/
|
|
87954
88402
|
async fundingHint(request2) {
|
|
87955
88403
|
const wallet = await this.getBalance().catch(() => void 0);
|
|
87956
|
-
const
|
|
87957
|
-
const available = networks.map((n) => ({ network: stringValue5(n.network) ?? "?", usd: numberValue6(n.available_usd ?? n.balance_usd) })).filter((n) => n.usd !== void 0);
|
|
88404
|
+
const available = walletFunds(wallet?.data).map((n) => ({ network: n.network, usd: n.availableUsd, owed: n.hostingOwedUsd ?? 0 }));
|
|
87958
88405
|
if (!available.length)
|
|
87959
88406
|
return " Check get_wallet_status for where your USDC is.";
|
|
87960
88407
|
const total = available.reduce((sum, n) => sum + n.usd, 0);
|
|
87961
|
-
const
|
|
88408
|
+
const owed = available.filter((n) => n.owed > 0).map((n) => `; ${n.network} is net of $${n.owed.toFixed(2)} owed for hosting`).join("");
|
|
88409
|
+
const line = ` Your spendable USDC: ${available.map((n) => `${n.network} ${n.usd.toFixed(2)}`).join(", ")} (total ${total.toFixed(2)}${owed}). If this task makes more paid calls, call plan_funding with all of them before moving anything: one move sized to the whole task, not one per call.`;
|
|
87962
88410
|
const target = RAIL_NETWORK2[request2.rail];
|
|
87963
88411
|
const funded = available.filter((n) => n.network !== target && n.usd >= request2.maxAmountUsd).map((n) => n.network);
|
|
87964
88412
|
const elsewhere = funded.length ? ` First look for an equivalent service you can already pay: find_paid_service lists every result's networks, and one on ${funded.join(" or ")} costs you no transfer fee.` : "";
|
|
@@ -87970,6 +88418,32 @@ var init_hosted_economy = __esm({
|
|
|
87970
88418
|
return `${line}${elsewhere} Moving funds is the other way, but the most ${move.from} can spare is ${size5}, and a fee of ${cost} is ${Math.round(move.feeShare * 100)}% of that \u2014 too much to spend without asking. If no equivalent service fits, say exactly that to the owner: this service is sold only on ${target}, moving ${size5} there would cost ${cost} in fees, and ask whether to do it.`;
|
|
87971
88419
|
return `${line}${elsewhere} Otherwise move the funds yourself and retry \u2014 a move this size is within the policy and is not something to ask the owner about, any more than paying for the call is: bridge_usdc {"from":"${move.from}","to":"${target}","amount_usd":${move.amount}} (fee ${cost}, counted as spending; the spending guard pauses it for approval by itself if the owner's mode requires that), then retry this call.`;
|
|
87972
88420
|
}
|
|
88421
|
+
/**
|
|
88422
|
+
* plan_funding: probe every planned call for every network it accepts, read
|
|
88423
|
+
* what each network can spend, and plan the task's funding once
|
|
88424
|
+
* (funding-plan.ts). Read-only; the probes are unpaid.
|
|
88425
|
+
*/
|
|
88426
|
+
async planFunding(args) {
|
|
88427
|
+
const raw = Array.isArray(args.calls) ? args.calls.slice(0, 12) : [];
|
|
88428
|
+
const wanted = raw.map(objectValue5).filter((call2) => !!call2 && !!stringValue5(call2.url));
|
|
88429
|
+
if (!wanted.length)
|
|
88430
|
+
return { ok: false, error: "plan_funding needs calls: [{url, method, count}]" };
|
|
88431
|
+
const [calls, wallet] = await Promise.all([
|
|
88432
|
+
Promise.all(wanted.map(async (call2) => {
|
|
88433
|
+
const url3 = stringValue5(call2.url), method = (stringValue5(call2.method) ?? "GET").toUpperCase();
|
|
88434
|
+
const count = Math.min(20, Math.max(1, Math.floor(numberValue6(call2.count) ?? 1)));
|
|
88435
|
+
const probe = await this.discovery.inspect({ url: url3, method, body: objectValue5(call2.sample_body) }).catch((error53) => ({ ok: false, error: error53.message, data: void 0 }));
|
|
88436
|
+
const offers = Array.isArray(probe.data?.offers) ? probe.data.offers : [];
|
|
88437
|
+
const payable = offers.filter((offer) => offer.payable === true && numberValue6(offer.price_usd) !== void 0).map((offer) => ({ network: stringValue5(offer.network) ?? "?", priceUsd: numberValue6(offer.price_usd), ...offer.free === true ? { free: true } : {} }));
|
|
88438
|
+
return { url: url3, method, count, offers: payable, ...probe.ok ? payable.length ? {} : { error: "the endpoint offers nothing this wallet can pay" } : { error: probe.error ?? "the endpoint could not be probed" } };
|
|
88439
|
+
})),
|
|
88440
|
+
this.getBalance().catch(() => void 0)
|
|
88441
|
+
]);
|
|
88442
|
+
const funds = walletFunds(wallet?.data);
|
|
88443
|
+
if (!funds.length)
|
|
88444
|
+
return { ok: false, error: "the wallet's balances could not be read; nothing was planned. Try again shortly." };
|
|
88445
|
+
return { ok: true, data: describePlan(planTaskFunding(calls, funds)) };
|
|
88446
|
+
}
|
|
87973
88447
|
/**
|
|
87974
88448
|
* Moves this agent's own USDC between its networks through the supervisor:
|
|
87975
88449
|
* a quote, or an executed move keyed by the tool call that waits for the
|
|
@@ -88121,7 +88595,7 @@ var init_hosted_economy = __esm({
|
|
|
88121
88595
|
};
|
|
88122
88596
|
HOSTED_BRIDGE_TOOL = {
|
|
88123
88597
|
name: "bridge_usdc",
|
|
88124
|
-
description: "Move your own USDC between your networks (base, solana, tempo); it always arrives at your own address. Use it when the owner asks, or when a paid call failed with funding_required and no equivalent service is sold on a network you already fund. quote_only shows the fee and expected amount without moving. Executing re-quotes, applies the owner's approval policy to the fee (it may pause for approval) and waits for the funds to arrive, usually within a minute. Fees are about $0.02-0.03 and count as spending, so aim for about $1 and one fee funds many calls; when the wallet holds less, move what the call needs plus the fee, as long as the fee stays under about a fifth of what moves (roughly $0.15 and up). A move within that rule needs no permission from the owner: the spending guard applies their approval mode to the fee by itself. Below the rule, quote_only first and ask, rather than spending most of the move on its fee. Pass transfer_id alone to check a pending move.",
|
|
88598
|
+
description: "Move your own USDC between your networks (base, solana, tempo); it always arrives at your own address. Use it when the owner asks, when plan_funding lists a move, or when a paid call failed with funding_required and no equivalent service is sold on a network you already fund. A run moves into each network at most once and never back the other way: plan a multi-call task with plan_funding first, then make its one move. quote_only shows the fee and expected amount without moving. Executing re-quotes, applies the owner's approval policy to the fee (it may pause for approval) and waits for the funds to arrive, usually within a minute. Fees are about $0.02-0.03 and count as spending, so aim for about $1 and one fee funds many calls; when the wallet holds less, move what the call needs plus the fee, as long as the fee stays under about a fifth of what moves (roughly $0.15 and up). A move within that rule needs no permission from the owner: the spending guard applies their approval mode to the fee by itself. Below the rule, quote_only first and ask, rather than spending most of the move on its fee. Pass transfer_id alone to check a pending move.",
|
|
88125
88599
|
parameters: {
|
|
88126
88600
|
type: "object",
|
|
88127
88601
|
properties: {
|
|
@@ -88176,8 +88650,8 @@ var init_tool_deadlines = __esm({
|
|
|
88176
88650
|
});
|
|
88177
88651
|
|
|
88178
88652
|
// ../../packages/agent-runtime/dist/worker.js
|
|
88179
|
-
import { readFile as
|
|
88180
|
-
import { join as
|
|
88653
|
+
import { readFile as readFile14, mkdir as mkdir11 } from "node:fs/promises";
|
|
88654
|
+
import { join as join22 } from "node:path";
|
|
88181
88655
|
import { createHash as createHash5, randomUUID as randomUUID8 } from "node:crypto";
|
|
88182
88656
|
function isWaiting(outcome) {
|
|
88183
88657
|
return ["waiting_for_approval", "waiting_for_funds", "waiting_for_delegation", "payment_unknown"].includes(outcome);
|
|
@@ -88236,13 +88710,13 @@ var init_worker = __esm({
|
|
|
88236
88710
|
constructor(options) {
|
|
88237
88711
|
this.options = options;
|
|
88238
88712
|
this.paths = resolveAgentPaths({ agentHome: options.agentHome });
|
|
88239
|
-
this.statePath =
|
|
88713
|
+
this.statePath = join22(this.paths.metadata, "worker.json");
|
|
88240
88714
|
}
|
|
88241
88715
|
async initialize() {
|
|
88242
88716
|
await containedPath(this.paths.home, "metadata/worker.json");
|
|
88243
88717
|
await mkdir11(this.paths.metadata, { recursive: true });
|
|
88244
88718
|
try {
|
|
88245
|
-
const raw = await
|
|
88719
|
+
const raw = await readFile14(this.statePath, "utf8");
|
|
88246
88720
|
this.state = JSON.parse(raw);
|
|
88247
88721
|
if (this.state.version !== 1 || !Number.isSafeInteger(this.state.seq) || !this.state.commands || !this.state.runs) {
|
|
88248
88722
|
throw new Error("worker checkpoint version or shape is invalid");
|
|
@@ -88417,13 +88891,13 @@ var init_worker = __esm({
|
|
|
88417
88891
|
} catch (error53) {
|
|
88418
88892
|
if (error53.code !== "ENOENT" || run.start.payload.session.kind === "existing")
|
|
88419
88893
|
throw error53;
|
|
88420
|
-
const
|
|
88421
|
-
if (
|
|
88894
|
+
const cents2 = BigInt(run.start.payload.budget.limit) / 10000n;
|
|
88895
|
+
if (cents2 > BigInt(Number.MAX_SAFE_INTEGER))
|
|
88422
88896
|
throw new Error("budget exceeds local accounting range");
|
|
88423
88897
|
session = await createSession({
|
|
88424
88898
|
workspaceRoot: this.paths.workspace,
|
|
88425
88899
|
sessionId: run.sessionId,
|
|
88426
|
-
budgetCents: Number(
|
|
88900
|
+
budgetCents: Number(cents2),
|
|
88427
88901
|
approvalMode: run.start.payload.approvalMode,
|
|
88428
88902
|
shellEnabled: true
|
|
88429
88903
|
});
|
|
@@ -88595,7 +89069,7 @@ var init_worker = __esm({
|
|
|
88595
89069
|
run.checkpoint = checkpoint;
|
|
88596
89070
|
run.checkpointId = randomUUID8();
|
|
88597
89071
|
});
|
|
88598
|
-
await atomicWrite(
|
|
89072
|
+
await atomicWrite(join22(session.sessionDir, "messages.jsonl"), checkpoint.messages.filter((m) => m.role !== "system").map((message) => JSON.stringify({ type: "message", timestamp: (/* @__PURE__ */ new Date()).toISOString(), message }) + "\n").join(""));
|
|
88599
89073
|
},
|
|
88600
89074
|
onMessage: async (message) => {
|
|
88601
89075
|
const content = message.role === "assistant" && !message.housekeeping ? stripReasoning(message.content) : "";
|
|
@@ -88658,7 +89132,7 @@ var init_worker = __esm({
|
|
|
88658
89132
|
}
|
|
88659
89133
|
async history(session) {
|
|
88660
89134
|
try {
|
|
88661
|
-
return (await
|
|
89135
|
+
return (await readFile14(join22(session.sessionDir, "messages.jsonl"), "utf8")).split("\n").filter(Boolean).map((line) => JSON.parse(line).message).filter(Boolean);
|
|
88662
89136
|
} catch (error53) {
|
|
88663
89137
|
if (error53.code === "ENOENT")
|
|
88664
89138
|
return [];
|
|
@@ -88696,7 +89170,7 @@ var init_worker = __esm({
|
|
|
88696
89170
|
});
|
|
88697
89171
|
|
|
88698
89172
|
// ../../packages/agent-runtime/dist/inbox.js
|
|
88699
|
-
import { readFile as
|
|
89173
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
88700
89174
|
var FileSteeringInbox;
|
|
88701
89175
|
var init_inbox = __esm({
|
|
88702
89176
|
"../../packages/agent-runtime/dist/inbox.js"() {
|
|
@@ -88710,7 +89184,7 @@ var init_inbox = __esm({
|
|
|
88710
89184
|
}
|
|
88711
89185
|
async read() {
|
|
88712
89186
|
try {
|
|
88713
|
-
return JSON.parse(await
|
|
89187
|
+
return JSON.parse(await readFile15(this.path, "utf8"));
|
|
88714
89188
|
} catch (e6) {
|
|
88715
89189
|
if (e6.code === "ENOENT")
|
|
88716
89190
|
return [];
|
|
@@ -88755,8 +89229,8 @@ var init_non_answer = __esm({
|
|
|
88755
89229
|
|
|
88756
89230
|
// ../../packages/agent-runtime/dist/index.js
|
|
88757
89231
|
import { createHash as createHash6 } from "node:crypto";
|
|
88758
|
-
import { appendFile as appendFile4, mkdir as mkdir12, readFile as
|
|
88759
|
-
import { join as
|
|
89232
|
+
import { appendFile as appendFile4, mkdir as mkdir12, readFile as readFile16 } from "node:fs/promises";
|
|
89233
|
+
import { join as join23 } from "node:path";
|
|
88760
89234
|
function lastUserMessageIndex(messages) {
|
|
88761
89235
|
for (let index2 = messages.length - 1; index2 >= 0; index2 -= 1) {
|
|
88762
89236
|
if (messages[index2].role === "user") {
|
|
@@ -88779,8 +89253,10 @@ function createMockToolExecutor() {
|
|
|
88779
89253
|
});
|
|
88780
89254
|
case "read_file":
|
|
88781
89255
|
return ok3({ content: `Mock file content for ${stringValue6(args.path) ?? "unknown path"}.` });
|
|
88782
|
-
case "list_files":
|
|
88783
|
-
|
|
89256
|
+
case "list_files": {
|
|
89257
|
+
const files = ["mock-output.txt"].filter((path3) => path3.startsWith(stringValue6(args.prefix) ?? ""));
|
|
89258
|
+
return ok3(args.scope === "all" ? { files, other_chats: [], note: "No other chat of this agent has files." } : files);
|
|
89259
|
+
}
|
|
88784
89260
|
case "run_shell":
|
|
88785
89261
|
context.onProgress?.({ type: "running_shell", message: "Mock running gated shell command" });
|
|
88786
89262
|
return ok3({
|
|
@@ -88890,13 +89366,13 @@ function chargedCostCents(usage, modelId, catalog) {
|
|
|
88890
89366
|
}
|
|
88891
89367
|
const model = catalog?.find((candidate) => candidate.id === modelId);
|
|
88892
89368
|
if (model && (model.inputCostCentsPer1k !== void 0 || model.outputCostCentsPer1k !== void 0) && (usage.inputTokens !== void 0 || usage.outputTokens !== void 0)) {
|
|
88893
|
-
const
|
|
88894
|
-
return Math.max(0, roundCents(
|
|
89369
|
+
const cents2 = (usage.inputTokens ?? 0) / 1e3 * (model.inputCostCentsPer1k ?? 0) + (usage.outputTokens ?? 0) / 1e3 * (model.outputCostCentsPer1k ?? 0);
|
|
89370
|
+
return Math.max(0, roundCents(cents2));
|
|
88895
89371
|
}
|
|
88896
89372
|
return 0;
|
|
88897
89373
|
}
|
|
88898
|
-
function roundCents(
|
|
88899
|
-
return Math.round(
|
|
89374
|
+
function roundCents(cents2) {
|
|
89375
|
+
return Math.round(cents2 * 1e4) / 1e4;
|
|
88900
89376
|
}
|
|
88901
89377
|
function usageMetricsNote(completion) {
|
|
88902
89378
|
const usage = completion.usage;
|
|
@@ -88956,11 +89432,12 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88956
89432
|
if (options.hosted)
|
|
88957
89433
|
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. It arrives as budget_after_tool_call in the latest tool result or, when no tool has just run, as an automatic CrowdCode note at the start of the latest user message; that note is context, not something the user said, so never reply to it or mention it unless the user asks about money. 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. Report the wallet to the owner as one total, mentioning the per-network split only when it matters. 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.");
|
|
88958
89434
|
if (options.hosted)
|
|
88959
|
-
systemPromptParts.push("Files the owner sends you: an attached file is saved in this session under uploads/ before its message reaches you, and the message names each one with its path, size and type. Read a text file with read_file at uploads/<name>, and any file with run_shell at artifacts/uploads/<name> from the session directory. Those files are already the owner's and already in their file list: work from them, and never copy or re-save one under artifacts/ to hand it back. Write your own outputs elsewhere under artifacts/; uploads/ is the owner's directory and nothing you write there is delivered. If a file the message names is missing, say so and ask the owner to send it again rather than guessing at its contents.", "Files you produce: only the artifacts/ directory of this session reaches the owner. save_file writes there; anything you write elsewhere is scratch they never see. The owner sees each file at its path without that prefix, so artifacts/generated/report.pdf is generated/report.pdf to them. Name a produced file in your final message by exactly that path as plain text and nothing else \u2014 the owner's interface turns it into a working download and preview link. Never invent a download URL, a sandbox: link, a /mnt/data path, or any other path the owner cannot open, and never claim a file exists before you have verified it.");
|
|
89435
|
+
systemPromptParts.push("Files the owner sends you: an attached file is saved in this session under uploads/ before its message reaches you, and the message names each one with its path, size and type. Read a text file with read_file at uploads/<name>, and any file with run_shell at artifacts/uploads/<name> from the session directory. Those files are already the owner's and already in their file list: work from them, and never copy or re-save one under artifacts/ to hand it back. Write your own outputs elsewhere under artifacts/; uploads/ is the owner's directory and nothing you write there is delivered. If a file the message names is missing, say so and ask the owner to send it again rather than guessing at its contents.", "Files you produce: only the artifacts/ directory of this session reaches the owner. save_file writes there; anything you write elsewhere is scratch they never see. The owner sees each file at its path without that prefix, so artifacts/generated/report.pdf is generated/report.pdf to them. Name a produced file in your final message by exactly that path as plain text and nothing else \u2014 the owner's interface turns it into a working download and preview link. Never invent a download URL, a sandbox: link, a /mnt/data path, or any other path the owner cannot open, and never claim a file exists before you have verified it.", `Files from your other chats: each chat with the owner is its own session with its own artifacts/, so list_files and read_file see only this one, while the owner's Files view shows every chat's files together. When the owner mentions a file, PDF or report you do not see here, call list_files with scope="all" before you say it does not exist; it lists each other chat's files with the shell_dir that run_shell reaches them at.`);
|
|
88960
89436
|
if (options.dynamicTools) {
|
|
88961
89437
|
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: a call that never reached the seller is never the seller's fault. funding_required means your USDC is on the wrong network, a cap or a declined approval means the owner's policy stopped you, and an unpayable rail means you could not pay at all \u2014 in every one of those the service was never asked, so it gets no review and certainly not a low rating. Fix the cause and call it again instead; the gateway refuses those reviews, and trying anyway wastes a turn. A platform judge, not you, writes the public score and text of a paid review from the platform's record of the call; your rating and notes are evidence it reads, so report accurately and never try to talk it into a rating.", `Choosing a service: find_paid_service with a short capability query (for example "web search" or "object storage", not the task's subject) searches every catalog (AgentCash, Coinbase's x402 catalog, the MPP catalog and CrowdCode's reviews) across Base, Solana and Tempo and returns services you can pay, ranked best first by CrowdCode: quality (score and verified reviews), then effective price on the service's best network, including about $0.03 to move USDC between your own networks when that network's balance is short, then your balance there. Prefer the highest-ranked service that fits the task, whatever its network; a better or cheaper service on Solana or Tempo beats a Base default. Each result also lists \`networks\`, the networks it can be paid on; between services that fit the task equally well, one you can pay from a balance you already hold beats one that needs a transfer first, because a move costs about $0.03. When the chosen service is marked transfer_needed, move USDC between your own networks first if you have a tool for that; otherwise tell the user which network needs funds. When the ranking is unavailable, compare candidates yourself with inspect_paid_service (reputation, price and network) against your per-network balances.`, ...options.hosted ? [
|
|
88962
89438
|
"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.",
|
|
88963
|
-
"funding_required means your USDC is on the wrong network, not that you are out of money, and a wallet with money in it finishes the job. First go back to find_paid_service and look for an equivalent service sold on a network you already hold USDC on \u2014 every result lists its `networks`, and paying from an existing balance costs no transfer fee. If none fits, move funds with bridge_usdc and retry the same call:
|
|
89439
|
+
"funding_required means your USDC is on the wrong network, not that you are out of money, and a wallet with money in it finishes the job. First go back to find_paid_service and look for an equivalent service sold on a network you already hold USDC on \u2014 every result lists its `networks`, and paying from an existing balance costs no transfer fee. If none fits, move funds with bridge_usdc and retry the same call: move what plan_funding says, or, for a single call, about $1 so one fee funds many later calls, and when the wallet holds less than that, move what the call needs plus the fee, as long as the fee stays under about a fifth of what moves (roughly $0.15 and up at a $0.03 fee). A move inside that rule is ordinary work, not a decision for the owner: make it and retry, exactly as you would pay for the call itself. The spending guard applies the owner's approval mode to the fee by itself and pauses the run if it has to, so you never need permission before calling bridge_usdc. Stopping to ask whether you may spend three cents moving the owner's own money to the network a seller wants is the dead end this rule exists to prevent. Only below that threshold is a move not worth making on your own: quote_only it, then ask. When the owner asks you to move funds, quote first, state the fee, then execute and report both transaction ids and the amount received. Moves follow the owner's approval mode like payments; never move funds without a reason.",
|
|
89440
|
+
"Plan a task's funding once, before its first purchase. When a task will make more than one paid call, or call a service sold on a network you hold little on, call plan_funding with every call you intend to make. One seller can need two networks for one task \u2014 articles paid on Base, a free search that only asks a signed wallet proof on Tempo \u2014 and plan_funding reads every network each endpoint accepts against what each of your networks can really spend (balance less holds, hosting owed and what is kept for hosting and your own model calls). Make exactly the moves it lists, at most one into any network, and never move funds back the other way in the same run: a round trip pays two fees for nothing. A call whose offer is free (price 0, marked free) needs no balance on any network; never move funds for it. When a paid answer carries a follow-up token (for example a free re-read), the runtime saves it and sends it on the next call to the same URL, so a repeat costs nothing; never pay twice for content you already bought.",
|
|
88964
89441
|
"When money is what blocks a task, say exactly that and nothing else: which network the service is sold on, what you hold where, and the single thing you need \u2014 permission for a move you have quoted, or USDC added on that network. Never dress a funding problem up as the service being unsuitable or unavailable, never imply your wallet is empty when it is not, and never offer a recorded request_service as though it were the answer the owner asked for."
|
|
88965
89442
|
] : [], 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 (input, output, problem, price_per_call), unless CrowdCode is off. Never invent a purchase or demand.", "Generated media never reaches you as base64 you can read: when a service returns audio, an image, video or a PDF, the runtime has already written the bytes to a file and handed you {artifact_path, bytes, media_type} instead. Work from that path with run_shell \u2014 ffmpeg, python3 and node are installed, so converting a wav to the mp3 the owner asked for is one command \u2014 and leave the deliverable under artifacts/ in the format they asked for. Never pay a second time for a file you already hold.", "Each tool result includes the budget before and after that tool call. Never ask for wallet private keys or secrets.", ...options.promptSections ?? []);
|
|
88966
89443
|
} else {
|
|
@@ -89421,8 +89898,8 @@ async function runSubagentTask(session, args, subagent, index2, parentOptions, o
|
|
|
89421
89898
|
return { ok: false, error: "spawn_subagent requires a task" };
|
|
89422
89899
|
}
|
|
89423
89900
|
const subagentId = `${session.sessionId}#sub${index2}`;
|
|
89424
|
-
const trajectoryDir =
|
|
89425
|
-
const trajectoryPath =
|
|
89901
|
+
const trajectoryDir = join23(session.sessionDir, "subagents", operationKey ?? String(index2));
|
|
89902
|
+
const trajectoryPath = join23(trajectoryDir, "messages.jsonl");
|
|
89426
89903
|
await mkdir12(trajectoryDir, { recursive: true });
|
|
89427
89904
|
const record3 = async (message) => {
|
|
89428
89905
|
await appendFile4(trajectoryPath, `${JSON.stringify({ type: "message", timestamp: (/* @__PURE__ */ new Date()).toISOString(), message })}
|
|
@@ -89453,11 +89930,11 @@ async function runSubagentTask(session, args, subagent, index2, parentOptions, o
|
|
|
89453
89930
|
].filter(Boolean).join("\n\n")
|
|
89454
89931
|
}
|
|
89455
89932
|
];
|
|
89456
|
-
const statePath =
|
|
89933
|
+
const statePath = join23(trajectoryDir, "checkpoint.json");
|
|
89457
89934
|
let saved;
|
|
89458
89935
|
if (operationKey)
|
|
89459
89936
|
try {
|
|
89460
|
-
saved = JSON.parse(await
|
|
89937
|
+
saved = JSON.parse(await readFile16(statePath, "utf8"));
|
|
89461
89938
|
} catch (e6) {
|
|
89462
89939
|
if (e6.code !== "ENOENT")
|
|
89463
89940
|
throw e6;
|
|
@@ -89909,8 +90386,8 @@ function truncateMiddle(value, maxLength) {
|
|
|
89909
90386
|
const tail = Math.floor((maxLength - 1) / 2);
|
|
89910
90387
|
return `${value.slice(0, head)}\u2026${value.slice(value.length - tail)}`;
|
|
89911
90388
|
}
|
|
89912
|
-
function formatCents(
|
|
89913
|
-
return `$${(
|
|
90389
|
+
function formatCents(cents2) {
|
|
90390
|
+
return `$${(cents2 / 100).toFixed(cents2 > 0 && cents2 < 1 ? 4 : 2)}`;
|
|
89914
90391
|
}
|
|
89915
90392
|
function sumCents2(rows) {
|
|
89916
90393
|
const total = rows.reduce((sum, row) => {
|
|
@@ -90188,8 +90665,8 @@ var init_dist6 = __esm({
|
|
|
90188
90665
|
});
|
|
90189
90666
|
|
|
90190
90667
|
// src/shared.ts
|
|
90191
|
-
import { readdir } from "node:fs/promises";
|
|
90192
|
-
import { join as
|
|
90668
|
+
import { readdir as readdir2 } from "node:fs/promises";
|
|
90669
|
+
import { join as join24, resolve as resolve5 } from "node:path";
|
|
90193
90670
|
import { stdout as output } from "node:process";
|
|
90194
90671
|
function renderKeyValues(value) {
|
|
90195
90672
|
return Object.entries(value).filter(([, item]) => item !== void 0).map(([key, item]) => ` ${style(key, "muted").padEnd(24)} ${formatCell(item, 80, key)}`).join("\n");
|
|
@@ -90222,9 +90699,9 @@ function formatCell(value, maxLength, key = "") {
|
|
|
90222
90699
|
return "-";
|
|
90223
90700
|
}
|
|
90224
90701
|
if ((typeof value === "number" || typeof value === "string") && /cost|cents|spend|remaining|budget|max/i.test(key)) {
|
|
90225
|
-
const
|
|
90226
|
-
if (Number.isFinite(
|
|
90227
|
-
return formatCents2(
|
|
90702
|
+
const cents2 = Number(value);
|
|
90703
|
+
if (Number.isFinite(cents2)) {
|
|
90704
|
+
return formatCents2(cents2);
|
|
90228
90705
|
}
|
|
90229
90706
|
}
|
|
90230
90707
|
if (typeof value === "number" && Number.isFinite(value) && /_cents$/.test(key)) {
|
|
@@ -90249,8 +90726,8 @@ function shortUrl(value) {
|
|
|
90249
90726
|
return truncateMiddle2(value, 48);
|
|
90250
90727
|
}
|
|
90251
90728
|
}
|
|
90252
|
-
function formatCents2(
|
|
90253
|
-
return `$${(
|
|
90729
|
+
function formatCents2(cents2) {
|
|
90730
|
+
return `$${(cents2 / 100).toFixed(cents2 > 0 && cents2 < 1 ? 4 : 2)}`;
|
|
90254
90731
|
}
|
|
90255
90732
|
function terminalWidth() {
|
|
90256
90733
|
return Math.max(60, Math.min(140, output.columns ?? 100));
|
|
@@ -90311,9 +90788,9 @@ function isConsumedOption(args, index2, options) {
|
|
|
90311
90788
|
return options.includes(args[index2]) || index2 > 0 && options.includes(args[index2 - 1]);
|
|
90312
90789
|
}
|
|
90313
90790
|
async function latestSessionId(workspaceRoot) {
|
|
90314
|
-
const sessionsDir =
|
|
90791
|
+
const sessionsDir = join24(resolve5(workspaceRoot), "sessions");
|
|
90315
90792
|
try {
|
|
90316
|
-
const entries = await
|
|
90793
|
+
const entries = await readdir2(sessionsDir, { withFileTypes: true });
|
|
90317
90794
|
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort().at(-1);
|
|
90318
90795
|
} catch (error53) {
|
|
90319
90796
|
if (error53.code === "ENOENT") {
|
|
@@ -90481,8 +90958,8 @@ var init_doctor = __esm({
|
|
|
90481
90958
|
});
|
|
90482
90959
|
|
|
90483
90960
|
// ../../packages/evals/dist/gaia.js
|
|
90484
|
-
import { mkdir as mkdir13, readFile as
|
|
90485
|
-
import { dirname as dirname12, join as
|
|
90961
|
+
import { mkdir as mkdir13, readFile as readFile17, writeFile as writeFile8, access as access2 } from "node:fs/promises";
|
|
90962
|
+
import { dirname as dirname12, join as join26 } from "node:path";
|
|
90486
90963
|
import { homedir as homedir7 } from "node:os";
|
|
90487
90964
|
function isUnsupportedModality(fileName) {
|
|
90488
90965
|
if (!fileName) {
|
|
@@ -90492,18 +90969,18 @@ function isUnsupportedModality(fileName) {
|
|
|
90492
90969
|
return UNSUPPORTED_EXTENSIONS.some((extension2) => lower.endsWith(extension2));
|
|
90493
90970
|
}
|
|
90494
90971
|
function defaultGaiaCacheDir() {
|
|
90495
|
-
return process.env.OPENCROWD_GAIA_CACHE_DIR ??
|
|
90972
|
+
return process.env.OPENCROWD_GAIA_CACHE_DIR ?? join26(homedir7(), ".cache", "opencrowd", "gaia", "2023", "validation");
|
|
90496
90973
|
}
|
|
90497
90974
|
async function fetchGaiaValidation(options = {}) {
|
|
90498
90975
|
const cacheDir = options.cacheDir ?? defaultGaiaCacheDir();
|
|
90499
90976
|
await mkdir13(cacheDir, { recursive: true });
|
|
90500
|
-
const metadataPath =
|
|
90977
|
+
const metadataPath = join26(cacheDir, "metadata.jsonl");
|
|
90501
90978
|
let metadataText;
|
|
90502
90979
|
try {
|
|
90503
|
-
metadataText = await
|
|
90980
|
+
metadataText = await readFile17(metadataPath, "utf8");
|
|
90504
90981
|
} catch {
|
|
90505
90982
|
metadataText = await fetchValidationRows(options);
|
|
90506
|
-
await
|
|
90983
|
+
await writeFile8(metadataPath, metadataText, "utf8");
|
|
90507
90984
|
}
|
|
90508
90985
|
return metadataText.split(/\r?\n/).filter(Boolean).map((line) => parseGaiaRecord(JSON.parse(line)));
|
|
90509
90986
|
}
|
|
@@ -90552,7 +91029,7 @@ async function ensureGaiaAttachments(questions, options = {}) {
|
|
|
90552
91029
|
const cacheDir = options.cacheDir ?? defaultGaiaCacheDir();
|
|
90553
91030
|
for (const question of questions) {
|
|
90554
91031
|
if (question.file_name && !isUnsupportedModality(question.file_name)) {
|
|
90555
|
-
const filePath =
|
|
91032
|
+
const filePath = join26(cacheDir, question.file_name);
|
|
90556
91033
|
await cachedDownload(filePath, `${GAIA_BASE_URL}/${encodeURIComponent(question.file_name)}`, options, true);
|
|
90557
91034
|
question.file_path = filePath;
|
|
90558
91035
|
}
|
|
@@ -90582,7 +91059,7 @@ function parseGaiaRecord(record3) {
|
|
|
90582
91059
|
async function cachedDownload(path3, url3, options, binary = false) {
|
|
90583
91060
|
try {
|
|
90584
91061
|
await access2(path3);
|
|
90585
|
-
return binary ? "" : await
|
|
91062
|
+
return binary ? "" : await readFile17(path3, "utf8");
|
|
90586
91063
|
} catch {
|
|
90587
91064
|
}
|
|
90588
91065
|
options.log?.(`fetching ${url3}`);
|
|
@@ -90604,11 +91081,11 @@ async function cachedDownload(path3, url3, options, binary = false) {
|
|
|
90604
91081
|
await mkdir13(dirname12(path3), { recursive: true });
|
|
90605
91082
|
if (binary) {
|
|
90606
91083
|
const buffer2 = Buffer.from(await response.arrayBuffer());
|
|
90607
|
-
await
|
|
91084
|
+
await writeFile8(path3, buffer2);
|
|
90608
91085
|
return "";
|
|
90609
91086
|
}
|
|
90610
91087
|
const text = await response.text();
|
|
90611
|
-
await
|
|
91088
|
+
await writeFile8(path3, text, "utf8");
|
|
90612
91089
|
return text;
|
|
90613
91090
|
}
|
|
90614
91091
|
var GAIA_BASE_URL, GAIA_ROWS_URL, GAIA_TIERS, UNSUPPORTED_EXTENSIONS;
|
|
@@ -90642,9 +91119,9 @@ var init_gaia = __esm({
|
|
|
90642
91119
|
});
|
|
90643
91120
|
|
|
90644
91121
|
// ../../packages/evals/dist/grader.js
|
|
90645
|
-
import { readFile as
|
|
91122
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
90646
91123
|
async function gradeTrajectoryFile(path3) {
|
|
90647
|
-
const text = await
|
|
91124
|
+
const text = await readFile18(path3, "utf8");
|
|
90648
91125
|
const entries = text.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line));
|
|
90649
91126
|
return gradeTrajectory(entries);
|
|
90650
91127
|
}
|
|
@@ -90777,8 +91254,8 @@ var init_grader = __esm({
|
|
|
90777
91254
|
// ../../packages/evals/dist/harnesses.js
|
|
90778
91255
|
import { execFile } from "node:child_process";
|
|
90779
91256
|
import { promisify } from "node:util";
|
|
90780
|
-
import { copyFile, mkdir as mkdir14, readFile as
|
|
90781
|
-
import { basename, join as
|
|
91257
|
+
import { copyFile, mkdir as mkdir14, readFile as readFile19 } from "node:fs/promises";
|
|
91258
|
+
import { basename, join as join27 } from "node:path";
|
|
90782
91259
|
function resolveHarness(name) {
|
|
90783
91260
|
switch (name) {
|
|
90784
91261
|
case "opencrowd":
|
|
@@ -90807,7 +91284,7 @@ function gaiaPrompt(question, attachmentNote) {
|
|
|
90807
91284
|
}
|
|
90808
91285
|
async function countPaidPurchases(path3) {
|
|
90809
91286
|
try {
|
|
90810
|
-
const text = await
|
|
91287
|
+
const text = await readFile19(path3, "utf8");
|
|
90811
91288
|
return text.split(/\r?\n/).filter(Boolean).filter((line) => {
|
|
90812
91289
|
const entry = asRecord3(parseJson4(line));
|
|
90813
91290
|
const outcome = asRecord3(entry.record).outcome ?? entry.outcome;
|
|
@@ -90822,7 +91299,7 @@ async function comparatorPrompt(context) {
|
|
|
90822
91299
|
return context.prompt;
|
|
90823
91300
|
}
|
|
90824
91301
|
const name = basename(context.attachmentPath);
|
|
90825
|
-
await copyFile(context.attachmentPath,
|
|
91302
|
+
await copyFile(context.attachmentPath, join27(context.runDir, name));
|
|
90826
91303
|
return `${context.prompt}
|
|
90827
91304
|
|
|
90828
91305
|
An input file is available in the working directory at ./${name}`;
|
|
@@ -90917,10 +91394,10 @@ var init_harnesses = __esm({
|
|
|
90917
91394
|
if (context.attachmentPath) {
|
|
90918
91395
|
const name = basename(context.attachmentPath);
|
|
90919
91396
|
await mkdir14(session.artifactsDir, { recursive: true });
|
|
90920
|
-
await copyFile(context.attachmentPath,
|
|
91397
|
+
await copyFile(context.attachmentPath, join27(session.artifactsDir, name));
|
|
90921
91398
|
prompt = `${prompt}
|
|
90922
91399
|
|
|
90923
|
-
An input file is available at the session artifact path \`${name}\` (use read_file, or run_shell against ${
|
|
91400
|
+
An input file is available at the session artifact path \`${name}\` (use read_file, or run_shell against ${join27(session.artifactsDir, name)}).`;
|
|
90924
91401
|
}
|
|
90925
91402
|
const llm = context.testMode ? void 0 : await resolveLlmRuntime(session, {
|
|
90926
91403
|
model: context.model,
|
|
@@ -90951,7 +91428,7 @@ An input file is available at the session artifact path \`${name}\` (use read_fi
|
|
|
90951
91428
|
onMessage: (message) => appendConversationMessage(session, message)
|
|
90952
91429
|
});
|
|
90953
91430
|
const budget = asRecord3(result.summary.budget);
|
|
90954
|
-
const trajectoryPath =
|
|
91431
|
+
const trajectoryPath = join27(session.sessionDir, "messages.jsonl");
|
|
90955
91432
|
return {
|
|
90956
91433
|
final_message: String(result.summary.final_message ?? ""),
|
|
90957
91434
|
turns: result.turns,
|
|
@@ -90962,7 +91439,7 @@ An input file is available at the session artifact path \`${name}\` (use read_fi
|
|
|
90962
91439
|
knowledge_version: session.knowledge?.version,
|
|
90963
91440
|
session_dir: session.sessionDir,
|
|
90964
91441
|
artifacts_dir: session.artifactsDir,
|
|
90965
|
-
paid_calls: await countPaidPurchases(
|
|
91442
|
+
paid_calls: await countPaidPurchases(join27(session.sessionDir, "purchases.jsonl")),
|
|
90966
91443
|
model_policy: llm?.models,
|
|
90967
91444
|
compliance: await gradeTrajectoryFile(trajectoryPath).catch(() => void 0)
|
|
90968
91445
|
};
|
|
@@ -91165,8 +91642,8 @@ var init_scorer = __esm({
|
|
|
91165
91642
|
});
|
|
91166
91643
|
|
|
91167
91644
|
// ../../packages/evals/dist/runner.js
|
|
91168
|
-
import { appendFile as appendFile5, mkdir as mkdir15, writeFile as
|
|
91169
|
-
import { join as
|
|
91645
|
+
import { appendFile as appendFile5, mkdir as mkdir15, writeFile as writeFile9 } from "node:fs/promises";
|
|
91646
|
+
import { join as join28, resolve as resolve6 } from "node:path";
|
|
91170
91647
|
async function runGaiaBenchmark(options) {
|
|
91171
91648
|
const log = options.log ?? (() => void 0);
|
|
91172
91649
|
const harnesses = options.harnesses.map(resolveHarness);
|
|
@@ -91193,7 +91670,7 @@ async function runGaiaBenchmark(options) {
|
|
|
91193
91670
|
const runId = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
91194
91671
|
const resultsDir = resolve6(options.workspaceRoot, "evals", "gaia", runId);
|
|
91195
91672
|
await mkdir15(resultsDir, { recursive: true });
|
|
91196
|
-
const resultsPath =
|
|
91673
|
+
const resultsPath = join28(resultsDir, "results.jsonl");
|
|
91197
91674
|
log(`GAIA ${options.tier}: ${runnable.length} questions, ${skipped.length} skipped (unsupported modality), results in ${resultsDir}`);
|
|
91198
91675
|
const parallel = Math.max(1, options.parallel ?? 4);
|
|
91199
91676
|
const rows = [];
|
|
@@ -91219,12 +91696,12 @@ async function runGaiaBenchmark(options) {
|
|
|
91219
91696
|
harnesses: harnesses.map((harness) => summarizeHarness(harness, rows.filter((row) => row.harness === harness.name))),
|
|
91220
91697
|
rows
|
|
91221
91698
|
};
|
|
91222
|
-
await
|
|
91699
|
+
await writeFile9(join28(resultsDir, "report.json"), `${JSON.stringify(report, null, 2)}
|
|
91223
91700
|
`, "utf8");
|
|
91224
91701
|
return report;
|
|
91225
91702
|
}
|
|
91226
91703
|
async function runOneQuestion(harness, question, resultsDir, options) {
|
|
91227
|
-
const runDir =
|
|
91704
|
+
const runDir = join28(resultsDir, harness.name, question.task_id);
|
|
91228
91705
|
await mkdir15(runDir, { recursive: true });
|
|
91229
91706
|
const prompt = gaiaPrompt(question);
|
|
91230
91707
|
const started = Date.now();
|
|
@@ -91356,9 +91833,9 @@ var init_runner = __esm({
|
|
|
91356
91833
|
});
|
|
91357
91834
|
|
|
91358
91835
|
// ../../packages/evals/dist/tasks.js
|
|
91359
|
-
import { readFile as
|
|
91836
|
+
import { readFile as readFile20 } from "node:fs/promises";
|
|
91360
91837
|
import { createHash as createHash7 } from "node:crypto";
|
|
91361
|
-
import { dirname as dirname13, join as
|
|
91838
|
+
import { dirname as dirname13, join as join29 } from "node:path";
|
|
91362
91839
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
91363
91840
|
import { homedir as homedir8 } from "node:os";
|
|
91364
91841
|
async function loadTaskSet(name, options = {}) {
|
|
@@ -91380,10 +91857,10 @@ async function loadTaskSet(name, options = {}) {
|
|
|
91380
91857
|
}
|
|
91381
91858
|
}
|
|
91382
91859
|
function tasksDir() {
|
|
91383
|
-
return
|
|
91860
|
+
return join29(dirname13(fileURLToPath2(import.meta.url)), "..", "tasks");
|
|
91384
91861
|
}
|
|
91385
91862
|
async function loadUsageTasks() {
|
|
91386
|
-
const raw = JSON.parse(await
|
|
91863
|
+
const raw = JSON.parse(await readFile20(join29(tasksDir(), "usage.json"), "utf8"));
|
|
91387
91864
|
return raw.tasks.map((task) => ({
|
|
91388
91865
|
task_id: String(task.id),
|
|
91389
91866
|
suite: "usage",
|
|
@@ -91395,7 +91872,7 @@ async function loadUsageTasks() {
|
|
|
91395
91872
|
capability: typeof task.capability === "string" ? task.capability : void 0,
|
|
91396
91873
|
expect_paid: task.expect_paid,
|
|
91397
91874
|
file_name: typeof task.attachment === "string" ? task.attachment : void 0,
|
|
91398
|
-
file_path: typeof task.attachment === "string" ?
|
|
91875
|
+
file_path: typeof task.attachment === "string" ? join29(tasksDir(), "attachments", task.attachment) : void 0
|
|
91399
91876
|
}));
|
|
91400
91877
|
}
|
|
91401
91878
|
async function loadGaiaHard(options = {}) {
|
|
@@ -91421,13 +91898,13 @@ function gaiaToTask(question) {
|
|
|
91421
91898
|
};
|
|
91422
91899
|
}
|
|
91423
91900
|
function defaultAssistantBenchCachePath() {
|
|
91424
|
-
return process.env.OPENCROWD_ASSISTANTBENCH_CACHE ??
|
|
91901
|
+
return process.env.OPENCROWD_ASSISTANTBENCH_CACHE ?? join29(homedir8(), ".cache", "opencrowd", "assistantbench", "validation.jsonl");
|
|
91425
91902
|
}
|
|
91426
91903
|
async function loadAssistantBench(options = {}) {
|
|
91427
91904
|
const cachePath = defaultAssistantBenchCachePath();
|
|
91428
91905
|
let text;
|
|
91429
91906
|
try {
|
|
91430
|
-
text = await
|
|
91907
|
+
text = await readFile20(cachePath, "utf8");
|
|
91431
91908
|
} catch {
|
|
91432
91909
|
options.log?.(`fetching ${ASSISTANTBENCH_ROWS_URL}`);
|
|
91433
91910
|
const headers = options.hfToken ? { authorization: `Bearer ${options.hfToken}` } : {};
|
|
@@ -91438,9 +91915,9 @@ async function loadAssistantBench(options = {}) {
|
|
|
91438
91915
|
const body = await response.json();
|
|
91439
91916
|
text = `${(body.rows ?? []).map((item) => JSON.stringify(item.row)).join("\n")}
|
|
91440
91917
|
`;
|
|
91441
|
-
const { mkdir: mkdir21, writeFile:
|
|
91918
|
+
const { mkdir: mkdir21, writeFile: writeFile14 } = await import("node:fs/promises");
|
|
91442
91919
|
await mkdir21(dirname13(cachePath), { recursive: true });
|
|
91443
|
-
await
|
|
91920
|
+
await writeFile14(cachePath, text, "utf8");
|
|
91444
91921
|
}
|
|
91445
91922
|
const rows = text.split(/\r?\n/).filter(Boolean).map((line) => JSON.parse(line));
|
|
91446
91923
|
const selected = seededSample(rows, ASSISTANTBENCH_COUNT, `${options.seed ?? DEFAULT_SEED}:assistantbench`, (row) => String(row.id));
|
|
@@ -91496,9 +91973,9 @@ var init_tasks = __esm({
|
|
|
91496
91973
|
});
|
|
91497
91974
|
|
|
91498
91975
|
// ../../packages/evals/dist/scoring.js
|
|
91499
|
-
import { readFile as
|
|
91976
|
+
import { readFile as readFile21, stat as stat2 } from "node:fs/promises";
|
|
91500
91977
|
import { resolve as resolveDns } from "node:dns/promises";
|
|
91501
|
-
import { join as
|
|
91978
|
+
import { join as join30 } from "node:path";
|
|
91502
91979
|
async function scoreTask(task, finalMessage, context = {}) {
|
|
91503
91980
|
const answer = extractAnswerText(finalMessage);
|
|
91504
91981
|
const spec = task.scorer;
|
|
@@ -91543,17 +92020,17 @@ async function scoreTask(task, finalMessage, context = {}) {
|
|
|
91543
92020
|
return { score: 0, correct: false, detail: "no artifacts dir" };
|
|
91544
92021
|
}
|
|
91545
92022
|
for (const name of spec.names) {
|
|
91546
|
-
const path3 =
|
|
92023
|
+
const path3 = join30(context.artifactsDir, name);
|
|
91547
92024
|
let size5;
|
|
91548
92025
|
try {
|
|
91549
|
-
size5 = (await
|
|
92026
|
+
size5 = (await stat2(path3)).size;
|
|
91550
92027
|
} catch {
|
|
91551
92028
|
continue;
|
|
91552
92029
|
}
|
|
91553
92030
|
if (spec.min_bytes !== void 0 && size5 < spec.min_bytes) {
|
|
91554
92031
|
return { score: 0, correct: false, detail: `${name} too small (${size5} bytes)` };
|
|
91555
92032
|
}
|
|
91556
|
-
const buffer2 = await
|
|
92033
|
+
const buffer2 = await readFile21(path3);
|
|
91557
92034
|
if (spec.image && !looksLikeImage(buffer2)) {
|
|
91558
92035
|
return { score: 0, correct: false, detail: `${name} is not a PNG/JPEG/WebP` };
|
|
91559
92036
|
}
|
|
@@ -91740,8 +92217,8 @@ var init_scoring = __esm({
|
|
|
91740
92217
|
});
|
|
91741
92218
|
|
|
91742
92219
|
// ../../packages/evals/dist/suite.js
|
|
91743
|
-
import { appendFile as appendFile6, mkdir as mkdir16, writeFile as
|
|
91744
|
-
import { join as
|
|
92220
|
+
import { appendFile as appendFile6, mkdir as mkdir16, writeFile as writeFile10 } from "node:fs/promises";
|
|
92221
|
+
import { join as join31, resolve as resolve7 } from "node:path";
|
|
91745
92222
|
async function runSuite(options) {
|
|
91746
92223
|
const log = options.log ?? (() => void 0);
|
|
91747
92224
|
const harness = resolveHarness(options.harness ?? "opencrowd");
|
|
@@ -91756,7 +92233,7 @@ async function runSuite(options) {
|
|
|
91756
92233
|
const runId = `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}${options.tag ? `-${slug(options.tag)}` : ""}`;
|
|
91757
92234
|
const resultsDir = resolve7(options.resultsRoot, runId);
|
|
91758
92235
|
await mkdir16(resultsDir, { recursive: true });
|
|
91759
|
-
const resultsPath =
|
|
92236
|
+
const resultsPath = join31(resultsDir, "results.jsonl");
|
|
91760
92237
|
log(`suite ${options.set}${options.tag ? ` [${options.tag}]` : ""}: ${tasks.length} tasks, knowledge=${options.knowledgeDir ?? "none"}, results in ${resultsDir}`);
|
|
91761
92238
|
const limit = createLimiter3(Math.max(1, options.parallel ?? 3));
|
|
91762
92239
|
const rows = await Promise.all(tasks.map((task, index2) => limit(async () => {
|
|
@@ -91780,14 +92257,14 @@ async function runSuite(options) {
|
|
|
91780
92257
|
summary: summarize(rows),
|
|
91781
92258
|
rows
|
|
91782
92259
|
};
|
|
91783
|
-
await
|
|
92260
|
+
await writeFile10(join31(resultsDir, "report.json"), `${JSON.stringify(report, null, 2)}
|
|
91784
92261
|
`, "utf8");
|
|
91785
|
-
await
|
|
92262
|
+
await writeFile10(join31(resultsDir, "report.md"), `${renderSuiteReport(report)}
|
|
91786
92263
|
`, "utf8");
|
|
91787
92264
|
return report;
|
|
91788
92265
|
}
|
|
91789
92266
|
async function runOneTask(harnessName, harness, task, resultsDir, runId, options) {
|
|
91790
|
-
const runDir =
|
|
92267
|
+
const runDir = join31(resultsDir, harnessName, task.task_id);
|
|
91791
92268
|
await mkdir16(runDir, { recursive: true });
|
|
91792
92269
|
const started = Date.now();
|
|
91793
92270
|
let run;
|
|
@@ -91947,13 +92424,13 @@ var init_suite = __esm({
|
|
|
91947
92424
|
});
|
|
91948
92425
|
|
|
91949
92426
|
// ../../packages/evals/dist/evidence.js
|
|
91950
|
-
import { mkdir as mkdir17, readFile as
|
|
92427
|
+
import { mkdir as mkdir17, readFile as readFile22, writeFile as writeFile11 } from "node:fs/promises";
|
|
91951
92428
|
import { dirname as dirname14 } from "node:path";
|
|
91952
92429
|
async function fetchCrowdCodeEvidence(options = {}) {
|
|
91953
92430
|
const cachePath = options.cachePath;
|
|
91954
92431
|
if (cachePath && options.useCache !== false) {
|
|
91955
92432
|
try {
|
|
91956
|
-
return JSON.parse(await
|
|
92433
|
+
return JSON.parse(await readFile22(cachePath, "utf8"));
|
|
91957
92434
|
} catch {
|
|
91958
92435
|
}
|
|
91959
92436
|
}
|
|
@@ -91966,7 +92443,7 @@ async function fetchCrowdCodeEvidence(options = {}) {
|
|
|
91966
92443
|
if (exported) {
|
|
91967
92444
|
if (cachePath) {
|
|
91968
92445
|
await mkdir17(dirname14(cachePath), { recursive: true });
|
|
91969
|
-
await
|
|
92446
|
+
await writeFile11(cachePath, `${JSON.stringify(exported, null, 1)}
|
|
91970
92447
|
`, "utf8");
|
|
91971
92448
|
}
|
|
91972
92449
|
return exported;
|
|
@@ -91997,7 +92474,7 @@ async function fetchCrowdCodeEvidence(options = {}) {
|
|
|
91997
92474
|
};
|
|
91998
92475
|
if (cachePath) {
|
|
91999
92476
|
await mkdir17(dirname14(cachePath), { recursive: true });
|
|
92000
|
-
await
|
|
92477
|
+
await writeFile11(cachePath, `${JSON.stringify(bundle, null, 1)}
|
|
92001
92478
|
`, "utf8");
|
|
92002
92479
|
}
|
|
92003
92480
|
return bundle;
|
|
@@ -92144,8 +92621,8 @@ var init_evidence = __esm({
|
|
|
92144
92621
|
|
|
92145
92622
|
// ../../packages/evals/dist/knowledge.js
|
|
92146
92623
|
import { createHash as createHash8 } from "node:crypto";
|
|
92147
|
-
import { mkdir as mkdir18, readdir as
|
|
92148
|
-
import { dirname as dirname15, join as
|
|
92624
|
+
import { mkdir as mkdir18, readdir as readdir3, readFile as readFile23, writeFile as writeFile12 } from "node:fs/promises";
|
|
92625
|
+
import { dirname as dirname15, join as join32, relative as relative4 } from "node:path";
|
|
92149
92626
|
function approxTokens(text) {
|
|
92150
92627
|
return Math.ceil(text.length / 4);
|
|
92151
92628
|
}
|
|
@@ -92236,30 +92713,30 @@ function validateTree(tree, evidence) {
|
|
|
92236
92713
|
async function writeTree(dir, tree, meta4) {
|
|
92237
92714
|
await mkdir18(dir, { recursive: true });
|
|
92238
92715
|
for (const [name, content] of Object.entries(tree)) {
|
|
92239
|
-
const path3 =
|
|
92716
|
+
const path3 = join32(dir, name);
|
|
92240
92717
|
await mkdir18(dirname15(path3), { recursive: true });
|
|
92241
|
-
await
|
|
92718
|
+
await writeFile12(path3, content.endsWith("\n") ? content : `${content}
|
|
92242
92719
|
`, "utf8");
|
|
92243
92720
|
}
|
|
92244
|
-
await
|
|
92721
|
+
await writeFile12(join32(dir, "meta.json"), `${JSON.stringify(meta4, null, 2)}
|
|
92245
92722
|
`, "utf8");
|
|
92246
92723
|
}
|
|
92247
92724
|
async function readTree(dir) {
|
|
92248
92725
|
const tree = {};
|
|
92249
92726
|
const walk4 = async (current) => {
|
|
92250
|
-
for (const entry of await
|
|
92251
|
-
const path3 =
|
|
92727
|
+
for (const entry of await readdir3(current, { withFileTypes: true })) {
|
|
92728
|
+
const path3 = join32(current, entry.name);
|
|
92252
92729
|
if (entry.isDirectory()) {
|
|
92253
92730
|
await walk4(path3);
|
|
92254
92731
|
} else if (entry.name.endsWith(".md")) {
|
|
92255
|
-
tree[relative4(dir, path3)] = await
|
|
92732
|
+
tree[relative4(dir, path3)] = await readFile23(path3, "utf8");
|
|
92256
92733
|
}
|
|
92257
92734
|
}
|
|
92258
92735
|
};
|
|
92259
92736
|
await walk4(dir);
|
|
92260
92737
|
let meta4;
|
|
92261
92738
|
try {
|
|
92262
|
-
meta4 = JSON.parse(await
|
|
92739
|
+
meta4 = JSON.parse(await readFile23(join32(dir, "meta.json"), "utf8"));
|
|
92263
92740
|
} catch {
|
|
92264
92741
|
meta4 = void 0;
|
|
92265
92742
|
}
|
|
@@ -92267,7 +92744,7 @@ async function readTree(dir) {
|
|
|
92267
92744
|
}
|
|
92268
92745
|
async function updateTreeMeta(dir, patch) {
|
|
92269
92746
|
const { meta: meta4 } = await readTree(dir);
|
|
92270
|
-
await
|
|
92747
|
+
await writeFile12(join32(dir, "meta.json"), `${JSON.stringify({ ...meta4 ?? {}, ...patch }, null, 2)}
|
|
92271
92748
|
`, "utf8");
|
|
92272
92749
|
}
|
|
92273
92750
|
async function proposeTree(options) {
|
|
@@ -92383,23 +92860,23 @@ var init_knowledge2 = __esm({
|
|
|
92383
92860
|
});
|
|
92384
92861
|
|
|
92385
92862
|
// ../../packages/evals/dist/evolve.js
|
|
92386
|
-
import { mkdir as mkdir19, readFile as
|
|
92387
|
-
import { join as
|
|
92863
|
+
import { mkdir as mkdir19, readFile as readFile24, writeFile as writeFile13 } from "node:fs/promises";
|
|
92864
|
+
import { join as join33, resolve as resolve8 } from "node:path";
|
|
92388
92865
|
async function runEvolution(options) {
|
|
92389
92866
|
const log = options.log ?? (() => void 0);
|
|
92390
92867
|
const root = resolve8(options.resultsRoot);
|
|
92391
|
-
const treesDir =
|
|
92392
|
-
const runsDir =
|
|
92868
|
+
const treesDir = join33(root, "trees");
|
|
92869
|
+
const runsDir = join33(root, "runs");
|
|
92393
92870
|
await mkdir19(treesDir, { recursive: true });
|
|
92394
92871
|
await mkdir19(runsDir, { recursive: true });
|
|
92395
|
-
const evidencePath = options.evidencePath ??
|
|
92872
|
+
const evidencePath = options.evidencePath ?? join33(root, "evidence", "crowdcode-evidence.json");
|
|
92396
92873
|
const evidence = await fetchCrowdCodeEvidence({ cachePath: evidencePath, useCache: !options.refreshEvidence, log });
|
|
92397
92874
|
const digest = renderEvidenceDigest(evidence, { detailTop: 90, maxPointsPerService: 9 });
|
|
92398
92875
|
const evidenceHash = hashContent(digest);
|
|
92399
92876
|
log(`evidence: ${evidence.stats.services} services, ${evidence.stats.reviews} reviews, digest ~${Math.round(digest.length / 4)} tokens`);
|
|
92400
92877
|
const heldin = await loadTaskSet("heldin", { hfToken: options.hfToken, log });
|
|
92401
92878
|
const proposer = await buildProposerProviders(root, options.proposerModels);
|
|
92402
|
-
const archivePath =
|
|
92879
|
+
const archivePath = join33(root, "archive.json");
|
|
92403
92880
|
const archive = await readArchive(archivePath) ?? {
|
|
92404
92881
|
started_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
92405
92882
|
agent_model: options.agentModel,
|
|
@@ -92407,9 +92884,9 @@ async function runEvolution(options) {
|
|
|
92407
92884
|
entries: []
|
|
92408
92885
|
};
|
|
92409
92886
|
const save = async () => {
|
|
92410
|
-
await
|
|
92887
|
+
await writeFile13(archivePath, `${JSON.stringify(archive, null, 2)}
|
|
92411
92888
|
`, "utf8");
|
|
92412
|
-
await
|
|
92889
|
+
await writeFile13(join33(root, "frontier.md"), `${renderArchive(archive)}
|
|
92413
92890
|
`, "utf8");
|
|
92414
92891
|
};
|
|
92415
92892
|
const evaluate = async (entry, knowledgeDir) => {
|
|
@@ -92436,7 +92913,7 @@ async function runEvolution(options) {
|
|
|
92436
92913
|
if (!archive.entries.some((entry) => entry.id === "baseline")) {
|
|
92437
92914
|
const baseline = { id: "baseline", generation: 0, children: 0, status: "evaluated" };
|
|
92438
92915
|
if (options.baselineReport) {
|
|
92439
|
-
const report = JSON.parse(await
|
|
92916
|
+
const report = JSON.parse(await readFile24(options.baselineReport, "utf8"));
|
|
92440
92917
|
const rows = report.rows.filter((row) => row.suite === "usage");
|
|
92441
92918
|
baseline.report_dir = report.results_dir;
|
|
92442
92919
|
baseline.metrics = metricsOfRows(rows);
|
|
@@ -92517,7 +92994,7 @@ async function runEvolution(options) {
|
|
|
92517
92994
|
}
|
|
92518
92995
|
const best = bestEntry(archive);
|
|
92519
92996
|
if (best?.dir) {
|
|
92520
|
-
await
|
|
92997
|
+
await writeFile13(join33(root, "BEST"), `${best.dir}
|
|
92521
92998
|
`, "utf8");
|
|
92522
92999
|
}
|
|
92523
93000
|
await save();
|
|
@@ -92550,9 +93027,9 @@ async function proposeCandidate(input2) {
|
|
|
92550
93027
|
log: input2.log
|
|
92551
93028
|
});
|
|
92552
93029
|
const validation = validateTree(proposal.tree, input2.evidence);
|
|
92553
|
-
const dir =
|
|
93030
|
+
const dir = join33(input2.treesDir, id);
|
|
92554
93031
|
await mkdir19(dir, { recursive: true });
|
|
92555
|
-
await
|
|
93032
|
+
await writeFile13(join33(dir, "proposal.raw.txt"), proposal.rawResponse, "utf8");
|
|
92556
93033
|
if (!validation.ok) {
|
|
92557
93034
|
errors = validation.errors;
|
|
92558
93035
|
input2.log(`${id}: invalid (${validation.errors.join("; ")})`);
|
|
@@ -92639,7 +93116,7 @@ function metricsOfRows(rows) {
|
|
|
92639
93116
|
};
|
|
92640
93117
|
}
|
|
92641
93118
|
async function casesFromReport(reportDir) {
|
|
92642
|
-
const report = JSON.parse(await
|
|
93119
|
+
const report = JSON.parse(await readFile24(join33(reportDir, "report.json"), "utf8"));
|
|
92643
93120
|
const cases = [];
|
|
92644
93121
|
for (const row of report.rows) {
|
|
92645
93122
|
cases.push({
|
|
@@ -92660,7 +93137,7 @@ async function casesFromReport(reportDir) {
|
|
|
92660
93137
|
async function summarizeTrajectory(path3) {
|
|
92661
93138
|
let text;
|
|
92662
93139
|
try {
|
|
92663
|
-
text = await
|
|
93140
|
+
text = await readFile24(path3, "utf8");
|
|
92664
93141
|
} catch {
|
|
92665
93142
|
return void 0;
|
|
92666
93143
|
}
|
|
@@ -92692,7 +93169,7 @@ async function summarizeTrajectory(path3) {
|
|
|
92692
93169
|
return steps.length > 0 ? steps.join(" -> ") : void 0;
|
|
92693
93170
|
}
|
|
92694
93171
|
async function buildProposerProviders(root, models) {
|
|
92695
|
-
const session = await createOpenCrowdSession({ workspaceRoot:
|
|
93172
|
+
const session = await createOpenCrowdSession({ workspaceRoot: join33(root, "proposer"), approvalMode: "auto", shellEnabled: false });
|
|
92696
93173
|
const providers = /* @__PURE__ */ new Map();
|
|
92697
93174
|
for (const model of new Set(models)) {
|
|
92698
93175
|
const llm = await resolveLlmRuntime(session, { model, subagentModel: "off", nonInteractive: true });
|
|
@@ -92709,7 +93186,7 @@ async function buildProposerProviders(root, models) {
|
|
|
92709
93186
|
}
|
|
92710
93187
|
async function readArchive(path3) {
|
|
92711
93188
|
try {
|
|
92712
|
-
return JSON.parse(await
|
|
93189
|
+
return JSON.parse(await readFile24(path3, "utf8"));
|
|
92713
93190
|
} catch {
|
|
92714
93191
|
return void 0;
|
|
92715
93192
|
}
|
|
@@ -92854,8 +93331,8 @@ init_dist2();
|
|
|
92854
93331
|
init_dist4();
|
|
92855
93332
|
init_dist6();
|
|
92856
93333
|
init_shared();
|
|
92857
|
-
import { copyFile as copyFile2, mkdir as mkdir20, readFile as
|
|
92858
|
-
import { basename as basename2, join as
|
|
93334
|
+
import { copyFile as copyFile2, mkdir as mkdir20, readFile as readFile25, rm as rm3 } from "node:fs/promises";
|
|
93335
|
+
import { basename as basename2, join as join34 } from "node:path";
|
|
92859
93336
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
92860
93337
|
import { stdin as input, stdout as output2 } from "node:process";
|
|
92861
93338
|
|
|
@@ -93228,14 +93705,14 @@ function parseUsdCents(data) {
|
|
|
93228
93705
|
var BASE_USDC_CONTRACT = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
93229
93706
|
var BASE_CHAIN_ID2 = 8453;
|
|
93230
93707
|
var SUGGESTED_FUND_CENTS = 2e3;
|
|
93231
|
-
function usdcUnits(
|
|
93232
|
-
return BigInt(Math.max(0, Math.round(
|
|
93708
|
+
function usdcUnits(cents2) {
|
|
93709
|
+
return BigInt(Math.max(0, Math.round(cents2))) * 10000n;
|
|
93233
93710
|
}
|
|
93234
|
-
function usdcTransferUri(address2,
|
|
93235
|
-
return `ethereum:${BASE_USDC_CONTRACT}@${BASE_CHAIN_ID2}/transfer?address=${address2}&uint256=${usdcUnits(
|
|
93711
|
+
function usdcTransferUri(address2, cents2) {
|
|
93712
|
+
return `ethereum:${BASE_USDC_CONTRACT}@${BASE_CHAIN_ID2}/transfer?address=${address2}&uint256=${usdcUnits(cents2)}`;
|
|
93236
93713
|
}
|
|
93237
|
-
function metamaskDeepLink(address2,
|
|
93238
|
-
return `https://metamask.app.link/send/${BASE_USDC_CONTRACT}@${BASE_CHAIN_ID2}/transfer?address=${address2}&uint256=${usdcUnits(
|
|
93714
|
+
function metamaskDeepLink(address2, cents2) {
|
|
93715
|
+
return `https://metamask.app.link/send/${BASE_USDC_CONTRACT}@${BASE_CHAIN_ID2}/transfer?address=${address2}&uint256=${usdcUnits(cents2)}`;
|
|
93239
93716
|
}
|
|
93240
93717
|
async function qrTerminal(text) {
|
|
93241
93718
|
const { toString: toString3 } = await import("qrcode");
|
|
@@ -93612,7 +94089,7 @@ function indent(text) {
|
|
|
93612
94089
|
|
|
93613
94090
|
// src/tui/app.tsx
|
|
93614
94091
|
init_dist2();
|
|
93615
|
-
import { join as
|
|
94092
|
+
import { join as join25 } from "node:path";
|
|
93616
94093
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
93617
94094
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
93618
94095
|
import { Box, render, Static, Text, useApp, useInput, usePaste, useStdout } from "ink";
|
|
@@ -93652,7 +94129,7 @@ function App({ session: initialSession, initialTestMode, initialTestSeed, defaul
|
|
|
93652
94129
|
const runningRef = useRef(false);
|
|
93653
94130
|
const inboxPausedRef = useRef(false);
|
|
93654
94131
|
const [inboxRevision, setInboxRevision] = useState(0);
|
|
93655
|
-
const inbox = useMemo(() => new FileSteeringInbox(
|
|
94132
|
+
const inbox = useMemo(() => new FileSteeringInbox(join25(session.sessionDir, "inbox.json")), [session.sessionDir]);
|
|
93656
94133
|
const [activity, setActivity] = useState("");
|
|
93657
94134
|
const [spinnerFrame, setSpinnerFrame] = useState(0);
|
|
93658
94135
|
const [modal, setModal] = useState(null);
|
|
@@ -93729,11 +94206,11 @@ function App({ session: initialSession, initialTestMode, initialTestSeed, defaul
|
|
|
93729
94206
|
const poll2 = async () => {
|
|
93730
94207
|
try {
|
|
93731
94208
|
const summary = await walletSummary();
|
|
93732
|
-
const
|
|
93733
|
-
if (cancelled || !Number.isFinite(
|
|
94209
|
+
const cents2 = summary.totalCents ?? Number.NaN;
|
|
94210
|
+
if (cancelled || !Number.isFinite(cents2)) {
|
|
93734
94211
|
return;
|
|
93735
94212
|
}
|
|
93736
|
-
if (
|
|
94213
|
+
if (cents2 > 0) {
|
|
93737
94214
|
const budgetCents = session.budgetCents;
|
|
93738
94215
|
if (!cancelled) {
|
|
93739
94216
|
setWizard({ step: "done", funded: true, budgetCents });
|
|
@@ -93741,7 +94218,7 @@ function App({ session: initialSession, initialTestMode, initialTestSeed, defaul
|
|
|
93741
94218
|
}
|
|
93742
94219
|
return;
|
|
93743
94220
|
}
|
|
93744
|
-
setWizard((current) => current?.step === "fund" ? { ...current, balanceCents: Math.max(0,
|
|
94221
|
+
setWizard((current) => current?.step === "fund" ? { ...current, balanceCents: Math.max(0, cents2) } : current);
|
|
93745
94222
|
} catch {
|
|
93746
94223
|
}
|
|
93747
94224
|
};
|
|
@@ -94030,9 +94507,9 @@ function App({ session: initialSession, initialTestMode, initialTestSeed, defaul
|
|
|
94030
94507
|
if (modal.budget !== void 0) {
|
|
94031
94508
|
if (isReturn) {
|
|
94032
94509
|
try {
|
|
94033
|
-
const
|
|
94034
|
-
if (
|
|
94035
|
-
modal.resolve({ decision: "approve", queryBudgetCents:
|
|
94510
|
+
const cents2 = parseUsd(modal.budget);
|
|
94511
|
+
if (cents2 <= modal.request.queryLimitCents || cents2 < modal.request.projectedCents) throw new Error("Enter a higher budget covering this call and committed spending.");
|
|
94512
|
+
modal.resolve({ decision: "approve", queryBudgetCents: cents2 });
|
|
94036
94513
|
} catch (e6) {
|
|
94037
94514
|
push({ kind: "error", text: e6.message });
|
|
94038
94515
|
}
|
|
@@ -94511,7 +94988,7 @@ async function main(argv) {
|
|
|
94511
94988
|
case "--version":
|
|
94512
94989
|
case "-v":
|
|
94513
94990
|
case "version": {
|
|
94514
|
-
const pkg2 = JSON.parse(await
|
|
94991
|
+
const pkg2 = JSON.parse(await readFile25(new URL("../package.json", import.meta.url), "utf8"));
|
|
94515
94992
|
console.log(pkg2.version);
|
|
94516
94993
|
return;
|
|
94517
94994
|
}
|
|
@@ -94617,10 +95094,10 @@ async function headlessRunCommand(args) {
|
|
|
94617
95094
|
if (attach) {
|
|
94618
95095
|
const attachmentName = basename2(attach);
|
|
94619
95096
|
await mkdir20(session.artifactsDir, { recursive: true });
|
|
94620
|
-
await copyFile2(attach,
|
|
95097
|
+
await copyFile2(attach, join34(session.artifactsDir, attachmentName));
|
|
94621
95098
|
task = `${prompt}
|
|
94622
95099
|
|
|
94623
|
-
An input file is available at the session artifact path \`${attachmentName}\` (use read_file, or run_shell against ${
|
|
95100
|
+
An input file is available at the session artifact path \`${attachmentName}\` (use read_file, or run_shell against ${join34(session.artifactsDir, attachmentName)}).`;
|
|
94624
95101
|
}
|
|
94625
95102
|
const result = await runPersistentAgentTaskDetailed(session, task, {
|
|
94626
95103
|
model: readOption(args, "--model"),
|
|
@@ -94644,7 +95121,7 @@ An input file is available at the session artifact path \`${attachmentName}\` (u
|
|
|
94644
95121
|
final_message: result.summary.final_message ?? null,
|
|
94645
95122
|
session_id: session.sessionId,
|
|
94646
95123
|
session_dir: session.sessionDir,
|
|
94647
|
-
trajectory_path:
|
|
95124
|
+
trajectory_path: join34(session.sessionDir, "messages.jsonl"),
|
|
94648
95125
|
turns: result.turns,
|
|
94649
95126
|
model_policy: session.models ?? null,
|
|
94650
95127
|
usdc_spent_cents: {
|
|
@@ -94736,7 +95213,7 @@ async function ledgerCommand(args) {
|
|
|
94736
95213
|
if (!sessionId) {
|
|
94737
95214
|
throw new Error("no local sessions found");
|
|
94738
95215
|
}
|
|
94739
|
-
const rows = await readLedger(
|
|
95216
|
+
const rows = await readLedger(join34(process.cwd(), "sessions", sessionId, "ledger.csv"));
|
|
94740
95217
|
printValue("Ledger", rows, {
|
|
94741
95218
|
json: json3,
|
|
94742
95219
|
pretty: renderTable(rows.map(asRecord), [
|
|
@@ -94773,7 +95250,7 @@ async function resumeCommand(args) {
|
|
|
94773
95250
|
} catch (e6) {
|
|
94774
95251
|
if (!(e6 instanceof SpendingDeclined)) throw e6;
|
|
94775
95252
|
}
|
|
94776
|
-
await rm3(
|
|
95253
|
+
await rm3(join34(session.sessionDir, "query-checkpoint.json"), { force: true });
|
|
94777
95254
|
console.log("Query declined. Nothing was paid for the pending call.");
|
|
94778
95255
|
return;
|
|
94779
95256
|
}
|
|
@@ -94925,7 +95402,7 @@ async function evalsSuiteCommand(rest) {
|
|
|
94925
95402
|
const report = await runSuite2({
|
|
94926
95403
|
set: set3,
|
|
94927
95404
|
harness: readOption(rest, "--harness") ?? "opencrowd",
|
|
94928
|
-
resultsRoot: readOption(rest, "--out") ??
|
|
95405
|
+
resultsRoot: readOption(rest, "--out") ?? join34(process.cwd(), "evals", "suite"),
|
|
94929
95406
|
tag: readOption(rest, "--tag"),
|
|
94930
95407
|
knowledgeDir: readOption(rest, "--knowledge"),
|
|
94931
95408
|
hfToken: readOption(rest, "--hf-token") ?? process.env.HF_TOKEN,
|
|
@@ -94944,7 +95421,7 @@ async function evalsSuiteCommand(rest) {
|
|
|
94944
95421
|
async function evalsEvolveCommand(rest) {
|
|
94945
95422
|
const { runEvolution: runEvolution2, renderArchive: renderArchive2 } = await Promise.resolve().then(() => (init_dist7(), dist_exports));
|
|
94946
95423
|
const { archive, best } = await runEvolution2({
|
|
94947
|
-
resultsRoot: readOption(rest, "--out") ??
|
|
95424
|
+
resultsRoot: readOption(rest, "--out") ?? join34(process.cwd(), "evals", "evolve"),
|
|
94948
95425
|
evidencePath: readOption(rest, "--evidence"),
|
|
94949
95426
|
refreshEvidence: rest.includes("--refresh-evidence"),
|
|
94950
95427
|
generations: Number(readOption(rest, "--generations") ?? 2),
|