opencrowd 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/opencrowd.js +46 -16
- package/package.json +1 -1
package/bundle/opencrowd.js
CHANGED
|
@@ -16717,12 +16717,19 @@ var init_session_defaults = __esm({
|
|
|
16717
16717
|
// ../../packages/core/dist/shell.js
|
|
16718
16718
|
import { spawn } from "node:child_process";
|
|
16719
16719
|
import { isAbsolute as isAbsolute2, join as join7, resolve as resolve3 } from "node:path";
|
|
16720
|
+
function maxShellTimeoutMs(env = process.env) {
|
|
16721
|
+
const requested = Number(env.OPENCROWD_MAX_SHELL_TIMEOUT_MS);
|
|
16722
|
+
if (!Number.isInteger(requested) || requested <= DEFAULT_MAX_SHELL_TIMEOUT_MS) {
|
|
16723
|
+
return DEFAULT_MAX_SHELL_TIMEOUT_MS;
|
|
16724
|
+
}
|
|
16725
|
+
return Math.min(SHELL_TIMEOUT_CEILING_MS, requested);
|
|
16726
|
+
}
|
|
16720
16727
|
async function runShell(state, command, cwd = state.workspaceRoot, timeoutMs = 1e4, options = {}) {
|
|
16721
16728
|
if (!state.shellEnabled) {
|
|
16722
16729
|
throw new Error("shell tool is disabled for this session");
|
|
16723
16730
|
}
|
|
16724
16731
|
options.signal?.throwIfAborted();
|
|
16725
|
-
const maxTimeout = options.maxTimeoutMs ??
|
|
16732
|
+
const maxTimeout = options.maxTimeoutMs ?? maxShellTimeoutMs();
|
|
16726
16733
|
if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > maxTimeout) {
|
|
16727
16734
|
throw new Error(`timeout_ms must be between 1 and ${maxTimeout}`);
|
|
16728
16735
|
}
|
|
@@ -16853,10 +16860,13 @@ function capOutput(output3, maxBytes) {
|
|
|
16853
16860
|
}
|
|
16854
16861
|
return output3.slice(0, maxBytes) + "\n[output truncated]\n";
|
|
16855
16862
|
}
|
|
16863
|
+
var DEFAULT_MAX_SHELL_TIMEOUT_MS, SHELL_TIMEOUT_CEILING_MS;
|
|
16856
16864
|
var init_shell = __esm({
|
|
16857
16865
|
"../../packages/core/dist/shell.js"() {
|
|
16858
16866
|
"use strict";
|
|
16859
16867
|
init_ledger();
|
|
16868
|
+
DEFAULT_MAX_SHELL_TIMEOUT_MS = 3e5;
|
|
16869
|
+
SHELL_TIMEOUT_CEILING_MS = 27e5;
|
|
16860
16870
|
}
|
|
16861
16871
|
});
|
|
16862
16872
|
|
|
@@ -16907,7 +16917,7 @@ function toolParameters(name) {
|
|
|
16907
16917
|
return objectSchema({
|
|
16908
16918
|
command: stringSchema("Shell command."),
|
|
16909
16919
|
cwd: stringSchema("Working directory inside the workspace. Use artifacts/<dir> to run where save_file writes (cd inside the command does not reach it)."),
|
|
16910
|
-
timeout_ms: integerSchema(
|
|
16920
|
+
timeout_ms: integerSchema(`Timeout in milliseconds (default 10000, maximum ${maxShellTimeoutMs()}). Pass the real time a long build or download needs; the command is killed at the timeout.`)
|
|
16911
16921
|
}, ["command"]);
|
|
16912
16922
|
case "spawn_subagent":
|
|
16913
16923
|
return objectSchema({
|
|
@@ -17039,6 +17049,7 @@ var TOOL_NAMES, HOSTED_ONLY_TOOL_NAMES, SUBAGENT_TOOL_NAMES, OPEN_CROWD_TOOLS;
|
|
|
17039
17049
|
var init_tool_definitions = __esm({
|
|
17040
17050
|
"../../packages/core/dist/tool-definitions.js"() {
|
|
17041
17051
|
"use strict";
|
|
17052
|
+
init_shell();
|
|
17042
17053
|
TOOL_NAMES = [
|
|
17043
17054
|
"get_budget_status",
|
|
17044
17055
|
"save_file",
|
|
@@ -17167,7 +17178,7 @@ function shellTimeoutMs(value) {
|
|
|
17167
17178
|
if (typeof value !== "number" || !Number.isInteger(value)) {
|
|
17168
17179
|
return DEFAULT_SHELL_TIMEOUT_MS;
|
|
17169
17180
|
}
|
|
17170
|
-
return Math.min(
|
|
17181
|
+
return Math.min(maxShellTimeoutMs(), Math.max(1, value));
|
|
17171
17182
|
}
|
|
17172
17183
|
function objectValue(value) {
|
|
17173
17184
|
if (value === void 0 || value === null) {
|
|
@@ -17184,7 +17195,7 @@ function sumCents(rows) {
|
|
|
17184
17195
|
return total + (Number.isFinite(value) ? Math.round(value) : 0);
|
|
17185
17196
|
}, 0);
|
|
17186
17197
|
}
|
|
17187
|
-
var DEFAULT_SHELL_TIMEOUT_MS
|
|
17198
|
+
var DEFAULT_SHELL_TIMEOUT_MS;
|
|
17188
17199
|
var init_tools = __esm({
|
|
17189
17200
|
"../../packages/core/dist/tools.js"() {
|
|
17190
17201
|
"use strict";
|
|
@@ -17193,7 +17204,6 @@ var init_tools = __esm({
|
|
|
17193
17204
|
init_ledger();
|
|
17194
17205
|
init_shell();
|
|
17195
17206
|
DEFAULT_SHELL_TIMEOUT_MS = 1e4;
|
|
17196
|
-
MAX_SHELL_TIMEOUT_MS = 3e5;
|
|
17197
17207
|
}
|
|
17198
17208
|
});
|
|
17199
17209
|
|
|
@@ -80894,7 +80904,7 @@ function economyTools(economy, options = {}) {
|
|
|
80894
80904
|
const status = await economy.execute("crowdcode_status", {});
|
|
80895
80905
|
if (!status.ok || !status.data?.enabled)
|
|
80896
80906
|
return review || void 0;
|
|
80897
|
-
return [review, "Before
|
|
80907
|
+
return [review, "Before this run ends, reflect once: What concrete services would have been worth paying for to solve this task? For each observed failure, poor result, excessive cost or avoidable detour with a reusable paid remedy, call request_service. Specify exact inputs, the paid deliverable, acceptance criteria, the actual use case and why paying would help. A prior purchase or spending permission is not required. Do not invent budgets. Skip generic local computation, ordinary agent mistakes without a sellable remedy, and services such as web search that already worked well. If everything worked well and cheaply, submit nothing. Then call complete_session again to finish."].filter(Boolean).join(" ");
|
|
80898
80908
|
}
|
|
80899
80909
|
};
|
|
80900
80910
|
}
|
|
@@ -82475,6 +82485,8 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
82475
82485
|
];
|
|
82476
82486
|
if (options.hosted)
|
|
82477
82487
|
systemPromptParts.push("You operate this service for its owner. Inference and paid tools debit its USDC wallet. When authorized to build or sell a service, take concrete steps within the owner's configured scope and budget. Ask only for missing information or permissions that materially block progress. Report actual costs and outcomes. Financial sustainability is the owner's business objective; respect their stop controls.", "You are a continuous autonomous agent, not a turn-based assistant. Maintain unfinished goals, promised follow-ups, recurring work, and conditions worth monitoring. When future work would clearly help, proactively create a persistent automation instead of waiting for the owner to say schedule. Use a one-time automation for a future reminder or follow-up and a cron automation for monitoring, recurring reports, or maintenance. It runs in this same conversation. Never create duplicates or noisy schedules, and always tell the owner exactly what you created, its timezone, and next run.", "Before finishing a substantive task, consider whether a follow-up, reminder, monitoring loop, recurring report, or maintenance check would materially advance the owner's goal; create one when the need is clear, but do not schedule ordinary one-off work.", "Financial state: the current hosted financial snapshot is authoritative; historical local session budget figures are not wallet balances and may omit inference spending. Wallet balance, pending payment holds, settled inference spend, settled service spend, and remaining run budget are separate. When the snapshot lists wallet networks, each network's balance is separate: a payment on a network needs that network's available balance. 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.");
|
|
82488
|
+
if (options.hosted)
|
|
82489
|
+
systemPromptParts.push("Files you produce: every file in this session's workspace, whether written with save_file or by a shell command, is published to the owner as a downloadable, previewable file. To point at one in your final message, write its exact workspace-relative path as plain text, for example generated/report.pdf \u2014 the owner's interface turns that path 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.");
|
|
82478
82490
|
if (options.dynamicTools) {
|
|
82479
82491
|
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.", `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. 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 ? [
|
|
82480
82492
|
"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.",
|
|
@@ -82494,7 +82506,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
82494
82506
|
systemPromptParts.push("Using secrets from chat: call vault_request to send one HTTPS request with a vault secret injected, writing {{SECRET_NAME}} where the value belongs (for example an authorization header). The platform substitutes the real value only for hosts the user approved for that secret, refreshes OAuth tokens automatically, and never returns the value to you. If it reports that a host needs approval, tell the user to allow it in the Vault tab and stop; never look for paid third-party services to do what an approved secret already lets you do. To upload a file (an image or video you rendered with run_shell, where ffmpeg is installed), pass body_artifact with its path under artifacts/ and, for multipart APIs, body_field plus form_fields; files over an API's chunk limit can be split with run_shell first.");
|
|
82495
82507
|
}
|
|
82496
82508
|
if (options.hosted && hostedTools.includes("run_shell")) {
|
|
82497
|
-
systemPromptParts.push("Tooling: ffmpeg, python3 with pip and venv, node and npm are installed; the system image is read-only, but `pip install --user <package>` and `npm install` persist on this machine's volume between runs, so install once and reuse.", "Resource recovery: before installing large ML dependencies, check available memory, disk space and Python version. A killed install or OOM is a failed approach, not the end of the task. Inspect partial installs and preserve user files, then choose a materially lighter backend or an external service within the user's budget. Verify package metadata: optional extras add dependencies and do not remove default ones; never invent an extra such as basic-pitch[tflite]. For audio-to-MIDI, prefer a verified TFLite or ONNX inference setup in an isolated venv over full TensorFlow; test on a short audio segment before processing the whole file. If no viable path remains, report the concrete blocker and useful artifacts. Do not claim success until the output has been checked.");
|
|
82509
|
+
systemPromptParts.push("Tooling: ffmpeg, python3 with pip and venv, node and npm are installed; the system image is read-only, but `pip install --user <package>` and `npm install` persist on this machine's volume between runs, so install once and reuse.", "Heavy toolchains: this machine's CPU, memory and disk come from the agent's compute tier, and a multi-gigabyte toolchain needs the heavy tier. Measure before installing one (`df -h \"$HOME\"`, `free -m`, `nproc`) and compare the numbers with what it needs. Install it under `$HOME`: that is the persistent volume and is excluded from the per-run workspace backup, while the session workspace is archived after every run with a 25 MB cap. Give a long download or compile the time it really needs through run_shell `timeout_ms` instead of accepting the 10 s default, redirect build logs to a file under `$HOME` and tail it rather than printing everything, and re-check free space between steps. `No space left on device` or an OOM kill twice means the tier is too small, not that the command was wrong: stop retrying, and tell the owner exactly which limit you hit, how much you need, and that they can switch this agent to the heavy compute tier from Machine in the agent menu (which also raises the shell timeout).", 'Lean 4 and Mathlib, when a task asks for machine-checked proofs: install elan into `$HOME` (`ELAN_HOME="$HOME/.elan" curl -fsSL https://elan.lean-lang.org/elan-init.sh | sh -s -- -y --default-toolchain none`, then source `$HOME/.elan/env`), create or clone the project under `$HOME` so `lake-manifest.json` pins the toolchain, and always run `lake exe cache get` to fetch prebuilt `.olean` files before `lake build` \u2014 compiling Mathlib from source is not viable here. Expect roughly 2 GB for the toolchain, 10 GB for the Mathlib cache, several minutes for `cache get`, and a few GB of memory to elaborate one file that imports Mathlib. Report the compiler\'s real output; a file containing `sorry` is not a proof.', "Resource recovery: before installing large ML dependencies, check available memory, disk space and Python version. A killed install or OOM is a failed approach, not the end of the task. Inspect partial installs and preserve user files, then choose a materially lighter backend or an external service within the user's budget. Verify package metadata: optional extras add dependencies and do not remove default ones; never invent an extra such as basic-pitch[tflite]. For audio-to-MIDI, prefer a verified TFLite or ONNX inference setup in an isolated venv over full TensorFlow; test on a short audio segment before processing the whole file. If no viable path remains, report the concrete blocker and useful artifacts. Do not claim success until the output has been checked.");
|
|
82498
82510
|
}
|
|
82499
82511
|
systemPromptParts.push("End by calling complete_session with a concise final message.");
|
|
82500
82512
|
if (options.subagent) {
|
|
@@ -82523,6 +82535,8 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
82523
82535
|
const repeatedFailures = new Map(options.resume?.repeatedFailures);
|
|
82524
82536
|
let completionNudges = options.resume?.completionNudges ?? 0;
|
|
82525
82537
|
let pendingFinalMessage = options.resume?.pendingFinalMessage;
|
|
82538
|
+
let finalAnswerHeld = options.resume?.finalAnswerHeld ?? false;
|
|
82539
|
+
let supersededFinalMessage;
|
|
82526
82540
|
let outputContinuationNudges = options.resume?.outputContinuationNudges ?? 0;
|
|
82527
82541
|
let outputContinuationPrefix = options.resume?.outputContinuationPrefix ?? "";
|
|
82528
82542
|
let serviceCallFailures = options.resume?.serviceCallFailures ?? 0;
|
|
@@ -82537,6 +82551,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
82537
82551
|
deliveredMessageIds: [...deliveredMessageIds],
|
|
82538
82552
|
completionNudges,
|
|
82539
82553
|
pendingFinalMessage,
|
|
82554
|
+
finalAnswerHeld,
|
|
82540
82555
|
outputContinuationNudges,
|
|
82541
82556
|
outputContinuationPrefix,
|
|
82542
82557
|
serviceCallFailures,
|
|
@@ -82552,6 +82567,8 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
82552
82567
|
}
|
|
82553
82568
|
if (fresh.length) {
|
|
82554
82569
|
pendingFinalMessage = void 0;
|
|
82570
|
+
finalAnswerHeld = false;
|
|
82571
|
+
supersededFinalMessage = void 0;
|
|
82555
82572
|
outputContinuationPrefix = "";
|
|
82556
82573
|
await checkpoint(turn);
|
|
82557
82574
|
}
|
|
@@ -82561,6 +82578,16 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
82561
82578
|
await options.inbox?.delivered(pending.map((m) => m.id));
|
|
82562
82579
|
return fresh.length > 0;
|
|
82563
82580
|
};
|
|
82581
|
+
const recordFinalMessage = (text) => {
|
|
82582
|
+
if (!text?.trim())
|
|
82583
|
+
return;
|
|
82584
|
+
if (!finalAnswerHeld)
|
|
82585
|
+
pendingFinalMessage = text;
|
|
82586
|
+
else if (text.trim() !== pendingFinalMessage?.trim())
|
|
82587
|
+
supersededFinalMessage = text;
|
|
82588
|
+
};
|
|
82589
|
+
const gateNudge = (blocker) => finalAnswerHeld ? `Your final answer is already saved and will be delivered to the user exactly as written; nothing you write now can replace it. Before this run ends: ${blocker} Then call complete_session again to finish; a one-line acknowledgement is enough, and do not restate the answer.` : `You cannot finish yet: ${blocker}`;
|
|
82590
|
+
const withReflection = (summary2) => supersededFinalMessage ? { ...summary2, reflection_note: supersededFinalMessage } : summary2;
|
|
82564
82591
|
let subagentCount = 0;
|
|
82565
82592
|
const backgroundSubagents = /* @__PURE__ */ new Map();
|
|
82566
82593
|
const subagentLimiter = createLimiter(options.subagent?.maxParallel ?? 4);
|
|
@@ -82642,8 +82669,7 @@ ${outputContinuationPrefix}`);
|
|
|
82642
82669
|
if (await injectMessages(turn + 1))
|
|
82643
82670
|
continue;
|
|
82644
82671
|
const finalMessage = response.content.trim() ? outputContinuationPrefix + response.content : pendingFinalMessage ?? outputContinuationPrefix;
|
|
82645
|
-
|
|
82646
|
-
pendingFinalMessage = finalMessage;
|
|
82672
|
+
recordFinalMessage(finalMessage);
|
|
82647
82673
|
const blocker = await options.completionGate?.(completionNudges > 0);
|
|
82648
82674
|
if (blocker) {
|
|
82649
82675
|
if (completionNudges >= 1) {
|
|
@@ -82651,7 +82677,9 @@ ${outputContinuationPrefix}`);
|
|
|
82651
82677
|
return { outcome: "stopped", summary: summary3, turns: turn + 1 };
|
|
82652
82678
|
}
|
|
82653
82679
|
completionNudges += 1;
|
|
82654
|
-
|
|
82680
|
+
if (pendingFinalMessage?.trim())
|
|
82681
|
+
finalAnswerHeld = true;
|
|
82682
|
+
const nudge = { role: "user", content: gateNudge(blocker) };
|
|
82655
82683
|
messages.push(nudge);
|
|
82656
82684
|
await options.onMessage?.(nudge);
|
|
82657
82685
|
await checkpoint(turn + 1);
|
|
@@ -82659,7 +82687,7 @@ ${outputContinuationPrefix}`);
|
|
|
82659
82687
|
}
|
|
82660
82688
|
if (!pendingFinalMessage?.trim())
|
|
82661
82689
|
throw new Error("The model ended without an answer.");
|
|
82662
|
-
const summary2 = await completeSession(session, pendingFinalMessage);
|
|
82690
|
+
const summary2 = withReflection(await completeSession(session, pendingFinalMessage));
|
|
82663
82691
|
return { outcome: "completed", summary: summary2, turns: turn + 1 };
|
|
82664
82692
|
}
|
|
82665
82693
|
const spawnedThisTurn = /* @__PURE__ */ new Map();
|
|
@@ -82795,8 +82823,8 @@ ${outputContinuationPrefix}`);
|
|
|
82795
82823
|
if (!result.ok)
|
|
82796
82824
|
continue;
|
|
82797
82825
|
const finalMessage = result.data && typeof result.data === "object" ? result.data.final_message : void 0;
|
|
82798
|
-
if (typeof finalMessage === "string"
|
|
82799
|
-
|
|
82826
|
+
if (typeof finalMessage === "string")
|
|
82827
|
+
recordFinalMessage(finalMessage);
|
|
82800
82828
|
const blocker = await options.completionGate?.(completionNudges > 0);
|
|
82801
82829
|
if (blocker) {
|
|
82802
82830
|
if (completionNudges >= 1) {
|
|
@@ -82804,9 +82832,11 @@ ${outputContinuationPrefix}`);
|
|
|
82804
82832
|
return { outcome: "stopped", summary: summary3, turns: turn + 1 };
|
|
82805
82833
|
}
|
|
82806
82834
|
completionNudges += 1;
|
|
82835
|
+
if (pendingFinalMessage?.trim())
|
|
82836
|
+
finalAnswerHeld = true;
|
|
82807
82837
|
const gateMessage = {
|
|
82808
82838
|
role: "user",
|
|
82809
|
-
content:
|
|
82839
|
+
content: gateNudge(blocker)
|
|
82810
82840
|
};
|
|
82811
82841
|
messages.push(gateMessage);
|
|
82812
82842
|
await options.onMessage?.(gateMessage);
|
|
@@ -82817,13 +82847,13 @@ ${outputContinuationPrefix}`);
|
|
|
82817
82847
|
throw new Error("The model ended without an answer.");
|
|
82818
82848
|
const backgroundResults = backgroundSubagents.size > 0 ? await drainBackground() : void 0;
|
|
82819
82849
|
if (result.data && typeof result.data === "object") {
|
|
82820
|
-
const summary3 = { ...result.data, final_message: pendingFinalMessage };
|
|
82850
|
+
const summary3 = withReflection({ ...result.data, final_message: pendingFinalMessage });
|
|
82821
82851
|
if (backgroundResults) {
|
|
82822
82852
|
summary3.background_subagents = backgroundResults;
|
|
82823
82853
|
}
|
|
82824
82854
|
return { outcome: "completed", summary: summary3, turns: turn + 1 };
|
|
82825
82855
|
}
|
|
82826
|
-
const summary2 = await completeSession(session, pendingFinalMessage);
|
|
82856
|
+
const summary2 = withReflection(await completeSession(session, pendingFinalMessage));
|
|
82827
82857
|
if (backgroundResults) {
|
|
82828
82858
|
summary2.background_subagents = backgroundResults;
|
|
82829
82859
|
}
|
package/package.json
CHANGED