opencrowd 0.16.0 → 0.16.2
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 +204 -73
- package/package.json +1 -1
package/bundle/opencrowd.js
CHANGED
|
@@ -15448,12 +15448,13 @@ function upstreamRefusalSummary(error53) {
|
|
|
15448
15448
|
const detail = typeof refusal.message === "string" ? refusal.message.trim() : "";
|
|
15449
15449
|
return `The model provider refused this request before any payment, so nothing was charged${detail ? `: ${detail}` : "."} You can retry or send another message.`;
|
|
15450
15450
|
}
|
|
15451
|
-
var RUN_FAILURE_MESSAGE, RUN_OUTCOMES, RunOutcomeSchema, RESUME_CAUSES, ResumeCauseSchema, RunStateSchema;
|
|
15451
|
+
var RUN_FAILURE_MESSAGE, PAYMENT_RECONCILING_MESSAGE, RUN_OUTCOMES, RunOutcomeSchema, RESUME_CAUSES, ResumeCauseSchema, RunStateSchema;
|
|
15452
15452
|
var init_outcomes = __esm({
|
|
15453
15453
|
"../../packages/protocol/dist/outcomes.js"() {
|
|
15454
15454
|
"use strict";
|
|
15455
15455
|
init_zod();
|
|
15456
15456
|
RUN_FAILURE_MESSAGE = "Something went wrong. You can retry or send another message.";
|
|
15457
|
+
PAYMENT_RECONCILING_MESSAGE = "The model call was interrupted while its payment was in flight. CrowdCode is confirming that payment and will continue this run automatically; nothing is charged twice. You can also send a new message.";
|
|
15457
15458
|
RUN_OUTCOMES = [
|
|
15458
15459
|
"completed",
|
|
15459
15460
|
"idle",
|
|
@@ -16151,15 +16152,19 @@ function isContextWindowError(value) {
|
|
|
16151
16152
|
return true;
|
|
16152
16153
|
return error53.error !== value && !!error53.error && isContextWindowError(typeof error53.error === "string" ? { message: error53.error } : error53.error);
|
|
16153
16154
|
}
|
|
16154
|
-
var MODEL_REQUEST_MAX_BYTES, MODEL_SELLER_REQUEST_MAX_BYTES, MODEL_MAX_MESSAGES, MODEL_GATEWAY_TIMEOUT_MS, MODEL_BRIDGE_TIMEOUT_MS, SERVICE_GATEWAY_TIMEOUT_MS, SERVICE_BRIDGE_TIMEOUT_MS, HOSTED_TOOL_BRIDGE_TIMEOUT_MS, HOSTED_CONTROL_TOOL_TIMEOUT_MS, SERVICE_RESPONSE_MAX_BYTES, DEFAULT_CONTEXT_WINDOW, ContextWindowExceeded, CONTEXT_COST_BUDGET_USD, CONTEXT_MIN_HISTORY_TOKENS, centsPer1kToUsdPerMillion;
|
|
16155
|
+
var MODEL_REQUEST_MAX_BYTES, MODEL_SELLER_REQUEST_MAX_BYTES, MODEL_MAX_MESSAGES, MODEL_PROVIDER_MAX_TIMEOUT_MS, MODEL_QUOTE_MAX_TIMEOUT_MS, MIB, MODEL_GATEWAY_TIMEOUT_MS, MODEL_GATEWAY_RETRY_BUDGET_MS, MODEL_BRIDGE_TIMEOUT_MS, SERVICE_GATEWAY_TIMEOUT_MS, SERVICE_BRIDGE_TIMEOUT_MS, HOSTED_TOOL_BRIDGE_TIMEOUT_MS, HOSTED_CONTROL_TOOL_TIMEOUT_MS, SERVICE_RESPONSE_MAX_BYTES, DEFAULT_CONTEXT_WINDOW, ContextWindowExceeded, CONTEXT_COST_BUDGET_USD, CONTEXT_MIN_HISTORY_TOKENS, centsPer1kToUsdPerMillion;
|
|
16155
16156
|
var init_context = __esm({
|
|
16156
16157
|
"../../packages/protocol/dist/context.js"() {
|
|
16157
16158
|
"use strict";
|
|
16158
16159
|
MODEL_REQUEST_MAX_BYTES = 16 * 1024 * 1024;
|
|
16159
16160
|
MODEL_SELLER_REQUEST_MAX_BYTES = 5 * 1024 * 1024;
|
|
16160
16161
|
MODEL_MAX_MESSAGES = 1e3;
|
|
16161
|
-
|
|
16162
|
-
|
|
16162
|
+
MODEL_PROVIDER_MAX_TIMEOUT_MS = 48e4;
|
|
16163
|
+
MODEL_QUOTE_MAX_TIMEOUT_MS = 45e3;
|
|
16164
|
+
MIB = 1024 * 1024;
|
|
16165
|
+
MODEL_GATEWAY_TIMEOUT_MS = MODEL_QUOTE_MAX_TIMEOUT_MS + MODEL_PROVIDER_MAX_TIMEOUT_MS + 75e3;
|
|
16166
|
+
MODEL_GATEWAY_RETRY_BUDGET_MS = 33e4;
|
|
16167
|
+
MODEL_BRIDGE_TIMEOUT_MS = 2 * MODEL_GATEWAY_TIMEOUT_MS + MODEL_GATEWAY_RETRY_BUDGET_MS + 3e4;
|
|
16163
16168
|
SERVICE_GATEWAY_TIMEOUT_MS = 33e4;
|
|
16164
16169
|
SERVICE_BRIDGE_TIMEOUT_MS = MODEL_GATEWAY_TIMEOUT_MS + SERVICE_GATEWAY_TIMEOUT_MS + 3e4;
|
|
16165
16170
|
HOSTED_TOOL_BRIDGE_TIMEOUT_MS = 9e4;
|
|
@@ -16311,6 +16316,26 @@ var init_financial_state = __esm({
|
|
|
16311
16316
|
}
|
|
16312
16317
|
});
|
|
16313
16318
|
|
|
16319
|
+
// ../../packages/protocol/dist/reasoning.js
|
|
16320
|
+
function stripReasoning(text) {
|
|
16321
|
+
let rest = text;
|
|
16322
|
+
for (; ; ) {
|
|
16323
|
+
const lead = /^\s*<think>[\s\S]*?<\/think>/.exec(rest);
|
|
16324
|
+
if (!lead)
|
|
16325
|
+
break;
|
|
16326
|
+
rest = rest.slice(lead[0].length);
|
|
16327
|
+
}
|
|
16328
|
+
const close = rest.indexOf("</think>");
|
|
16329
|
+
if (close !== -1 && !rest.slice(0, close).includes("<think>"))
|
|
16330
|
+
rest = rest.slice(close + "</think>".length);
|
|
16331
|
+
return rest === text ? text : rest.trim();
|
|
16332
|
+
}
|
|
16333
|
+
var init_reasoning = __esm({
|
|
16334
|
+
"../../packages/protocol/dist/reasoning.js"() {
|
|
16335
|
+
"use strict";
|
|
16336
|
+
}
|
|
16337
|
+
});
|
|
16338
|
+
|
|
16314
16339
|
// ../../packages/protocol/dist/index.js
|
|
16315
16340
|
var init_dist = __esm({
|
|
16316
16341
|
"../../packages/protocol/dist/index.js"() {
|
|
@@ -16329,6 +16354,7 @@ var init_dist = __esm({
|
|
|
16329
16354
|
init_deadlines();
|
|
16330
16355
|
init_spending();
|
|
16331
16356
|
init_financial_state();
|
|
16357
|
+
init_reasoning();
|
|
16332
16358
|
}
|
|
16333
16359
|
});
|
|
16334
16360
|
|
|
@@ -59184,6 +59210,7 @@ var init_gateway = __esm({
|
|
|
59184
59210
|
artifact_path: artifact?.path,
|
|
59185
59211
|
review_required: record3.review_required,
|
|
59186
59212
|
review_available: true,
|
|
59213
|
+
...result.note ? { note: result.note } : {},
|
|
59187
59214
|
data: result.data,
|
|
59188
59215
|
...result.ok ? {} : { error: result.error }
|
|
59189
59216
|
},
|
|
@@ -59759,6 +59786,16 @@ var init_dist4 = __esm({
|
|
|
59759
59786
|
// ../../packages/agent-runtime/dist/context.js
|
|
59760
59787
|
import { createHash as createHash3 } from "node:crypto";
|
|
59761
59788
|
import { relative as relative3, join as join13 } from "node:path";
|
|
59789
|
+
function requestMessages(messages, state) {
|
|
59790
|
+
if (state.trailingMessage)
|
|
59791
|
+
return [...messages, state.trailingMessage];
|
|
59792
|
+
const last = messages.at(-1);
|
|
59793
|
+
if (!state.note || last?.role !== "user")
|
|
59794
|
+
return messages;
|
|
59795
|
+
return [...messages.slice(0, -1), { ...last, content: `${state.note}
|
|
59796
|
+
|
|
59797
|
+
${last.content}` }];
|
|
59798
|
+
}
|
|
59762
59799
|
async function completeWithContext(session, messages, options) {
|
|
59763
59800
|
for (; ; ) {
|
|
59764
59801
|
options.signal?.throwIfAborted();
|
|
@@ -59771,8 +59808,7 @@ async function completeWithContext(session, messages, options) {
|
|
|
59771
59808
|
await options.checkpoint?.();
|
|
59772
59809
|
try {
|
|
59773
59810
|
const retry = options.state.retry ?? 0;
|
|
59774
|
-
const
|
|
59775
|
-
const request2 = trailing ? [...messages, trailing] : messages;
|
|
59811
|
+
const request2 = requestMessages(messages, options.state);
|
|
59776
59812
|
const response = await options.provider.complete(request2, {
|
|
59777
59813
|
signal: options.signal,
|
|
59778
59814
|
operationId: options.operationId && `${options.operationId}${retry ? `:context:${retry}` : ""}`
|
|
@@ -59784,6 +59820,7 @@ async function completeWithContext(session, messages, options) {
|
|
|
59784
59820
|
options.state.cachedFraction = typeof cached3 === "number" && Number.isFinite(cached3) && cached3 >= 0 ? Math.min(1, cached3 / used) : 0;
|
|
59785
59821
|
}
|
|
59786
59822
|
options.state.prepared = false;
|
|
59823
|
+
options.state.note = void 0;
|
|
59787
59824
|
options.state.trailingMessage = void 0;
|
|
59788
59825
|
options.state.retry = 0;
|
|
59789
59826
|
return response;
|
|
@@ -59842,9 +59879,9 @@ async function compactContext(session, messages, options) {
|
|
|
59842
59879
|
}
|
|
59843
59880
|
return saved;
|
|
59844
59881
|
};
|
|
59845
|
-
const
|
|
59846
|
-
const toolTokens = estimateContextTokens(options.tools) + 32 + (
|
|
59847
|
-
const toolBytes = Buffer.byteLength(JSON.stringify(options.tools)) + 32 + (
|
|
59882
|
+
const extra = options.state.trailingMessage ?? options.state.note;
|
|
59883
|
+
const toolTokens = estimateContextTokens(options.tools) + 32 + (extra ? estimateContextTokens(extra) : 0);
|
|
59884
|
+
const toolBytes = Buffer.byteLength(JSON.stringify(options.tools)) + 32 + (extra ? Buffer.byteLength(JSON.stringify(extra)) + 1 : 0);
|
|
59848
59885
|
const count = (list2) => Math.ceil(list2.reduce((total, m) => total + measure(m).tokens, toolTokens) * scale);
|
|
59849
59886
|
const tokensBefore = count(messages);
|
|
59850
59887
|
const retry = options.state.retry ?? 0;
|
|
@@ -60150,16 +60187,11 @@ async function readSseCompletion(response, onTextDelta, startedAtMs, onActivity)
|
|
|
60150
60187
|
throw new Error("LLM stream terminated before a finish reason or [DONE] marker (unexpected EOF)");
|
|
60151
60188
|
}
|
|
60152
60189
|
const toolCalls = [...toolCallsByIndex.entries()].sort(([left], [right]) => left - right).map(([index2, entry]) => {
|
|
60153
|
-
|
|
60154
|
-
try {
|
|
60155
|
-
parsedArguments = entry.argumentsText ? JSON.parse(entry.argumentsText) : {};
|
|
60156
|
-
} catch {
|
|
60157
|
-
parsedArguments = {};
|
|
60158
|
-
}
|
|
60190
|
+
const parsed = parseToolArguments(entry.argumentsText);
|
|
60159
60191
|
return {
|
|
60160
60192
|
id: entry.id ?? `call-${index2}`,
|
|
60161
60193
|
name: entry.name ?? "",
|
|
60162
|
-
|
|
60194
|
+
...parsed
|
|
60163
60195
|
};
|
|
60164
60196
|
}).filter((toolCall) => toolCall.name !== "");
|
|
60165
60197
|
return { content, toolCalls, usage, finishReason, firstTokenMs };
|
|
@@ -60340,20 +60372,24 @@ function toParsedToolCall(value) {
|
|
|
60340
60372
|
if (!name) {
|
|
60341
60373
|
return null;
|
|
60342
60374
|
}
|
|
60343
|
-
|
|
60344
|
-
if (typeof fn.arguments === "string") {
|
|
60345
|
-
try {
|
|
60346
|
-
parsedArguments = JSON.parse(fn.arguments);
|
|
60347
|
-
} catch {
|
|
60348
|
-
parsedArguments = {};
|
|
60349
|
-
}
|
|
60350
|
-
}
|
|
60375
|
+
const parsed = typeof fn.arguments === "string" ? parseToolArguments(fn.arguments) : { arguments: objectValue4(fn.arguments) ?? {} };
|
|
60351
60376
|
return {
|
|
60352
60377
|
id: stringValue3(object3.id) ?? `call-${Date.now()}`,
|
|
60353
60378
|
name,
|
|
60354
|
-
|
|
60379
|
+
...parsed
|
|
60355
60380
|
};
|
|
60356
60381
|
}
|
|
60382
|
+
function parseToolArguments(text) {
|
|
60383
|
+
if (!text?.trim())
|
|
60384
|
+
return { arguments: {} };
|
|
60385
|
+
try {
|
|
60386
|
+
const parsed = JSON.parse(text);
|
|
60387
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
|
|
60388
|
+
return { arguments: parsed };
|
|
60389
|
+
} catch {
|
|
60390
|
+
}
|
|
60391
|
+
return { arguments: {}, invalidArguments: text.slice(0, 2e3) };
|
|
60392
|
+
}
|
|
60357
60393
|
function messageContent(value) {
|
|
60358
60394
|
if (typeof value === "string") {
|
|
60359
60395
|
return value;
|
|
@@ -69543,7 +69579,7 @@ var init_crowdcode_venice = __esm({
|
|
|
69543
69579
|
init_http3();
|
|
69544
69580
|
init_dist2();
|
|
69545
69581
|
init_providers();
|
|
69546
|
-
CROWDCODE_VENICE_URL = "https://crowdcode.app/s/venice-
|
|
69582
|
+
CROWDCODE_VENICE_URL = "https://crowdcode.app/s/venice-proxy/chat/completions";
|
|
69547
69583
|
CROWDCODE_VENICE_PAYEE = "0xeEc135BDe3C69e48Ce6Cf5b9e4520d65baf90FC3";
|
|
69548
69584
|
VENICE_MODELS_URL = "https://api.venice.ai/api/v1/models?type=text";
|
|
69549
69585
|
BASE_USDC2 = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913";
|
|
@@ -87313,6 +87349,8 @@ function createHostedProvider(options) {
|
|
|
87313
87349
|
for (const call2 of result.response.toolCalls) {
|
|
87314
87350
|
if (typeof call2.id !== "string" || !call2.id || typeof call2.name !== "string" || !call2.arguments || typeof call2.arguments !== "object" || Array.isArray(call2.arguments))
|
|
87315
87351
|
throw new Error("Invalid hosted tool call");
|
|
87352
|
+
if (call2.invalidArguments !== void 0 && typeof call2.invalidArguments !== "string")
|
|
87353
|
+
delete call2.invalidArguments;
|
|
87316
87354
|
}
|
|
87317
87355
|
return result.response;
|
|
87318
87356
|
}
|
|
@@ -87772,6 +87810,18 @@ var init_hosted_economy = __esm({
|
|
|
87772
87810
|
if (reply.ok) {
|
|
87773
87811
|
const data = objectValue5(reply.data) ?? {};
|
|
87774
87812
|
const status = numberValue6(data.status);
|
|
87813
|
+
if (data.outcome === "owner_test") {
|
|
87814
|
+
const ok4 = status !== void 0 && status < 400;
|
|
87815
|
+
return {
|
|
87816
|
+
ok: ok4,
|
|
87817
|
+
ambiguous: false,
|
|
87818
|
+
status,
|
|
87819
|
+
data: decodeBody(data.body, data.content_type),
|
|
87820
|
+
authMode: "free",
|
|
87821
|
+
error: ok4 ? void 0 : `your service answered HTTP ${status ?? "?"}`,
|
|
87822
|
+
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."
|
|
87823
|
+
};
|
|
87824
|
+
}
|
|
87775
87825
|
const outcome = data.outcome === "paid_success" ? "paid_success" : "paid_failure";
|
|
87776
87826
|
const paidAtomic = numberValue6(data.amount_atomic);
|
|
87777
87827
|
const network = stringValue5(data.network);
|
|
@@ -88505,10 +88555,11 @@ var init_worker = __esm({
|
|
|
88505
88555
|
await atomicWrite(join21(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(""));
|
|
88506
88556
|
},
|
|
88507
88557
|
onMessage: async (message) => {
|
|
88508
|
-
|
|
88558
|
+
const content = message.role === "assistant" && !message.housekeeping ? stripReasoning(message.content) : "";
|
|
88559
|
+
if (content.trim())
|
|
88509
88560
|
await this.emit("assistant.message", {
|
|
88510
88561
|
messageId: randomUUID8(),
|
|
88511
|
-
content
|
|
88562
|
+
content
|
|
88512
88563
|
}, runId, run.commandId);
|
|
88513
88564
|
},
|
|
88514
88565
|
toolExecutor: (name, args, context) => record3(name, args, () => hosted && HOSTED_ONLY_TOOL_NAMES.includes(name) ? hosted(name, args, context) : local(name, args, context))
|
|
@@ -88528,7 +88579,7 @@ var init_worker = __esm({
|
|
|
88528
88579
|
await this.mutate(() => {
|
|
88529
88580
|
run.pendingOperationId = error53.operationId;
|
|
88530
88581
|
});
|
|
88531
|
-
await this.finish(runId, run, error53.outcome
|
|
88582
|
+
await this.finish(runId, run, error53.outcome, error53.outcome === "payment_unknown" ? PAYMENT_RECONCILING_MESSAGE : error53.message);
|
|
88532
88583
|
} else if (error53 instanceof SpendingDeclined)
|
|
88533
88584
|
await this.finish(runId, run, "user_stopped", error53.message);
|
|
88534
88585
|
else
|
|
@@ -88642,6 +88693,23 @@ var init_inbox = __esm({
|
|
|
88642
88693
|
}
|
|
88643
88694
|
});
|
|
88644
88695
|
|
|
88696
|
+
// ../../packages/agent-runtime/dist/non-answer.js
|
|
88697
|
+
function isNonAnswer(text) {
|
|
88698
|
+
const trimmed = text.trim();
|
|
88699
|
+
if (!trimmed || trimmed.length > 160 || /https?:\/\/|\n\s*\n/.test(trimmed))
|
|
88700
|
+
return false;
|
|
88701
|
+
return ACKNOWLEDGEMENT.test(trimmed) || PROMISE.test(trimmed);
|
|
88702
|
+
}
|
|
88703
|
+
var ACKNOWLEDGEMENT, ME, PROMISE;
|
|
88704
|
+
var init_non_answer = __esm({
|
|
88705
|
+
"../../packages/agent-runtime/dist/non-answer.js"() {
|
|
88706
|
+
"use strict";
|
|
88707
|
+
ACKNOWLEDGEMENT = /^(?:ok(?:ay)?|acknowledged|noted|understood|done|got it|sure|will do|on it|roger(?: that)?|thanks?(?: you)?|all done|complete(?:d)?|finished)(?:[.!]|\s*(?:—|-|,)\s*(?:thanks?(?: you)?|done))*$/i;
|
|
88708
|
+
ME = String.raw`(?:i(?:['’]?m| am)|i(?:['’]ll| will)(?: now)?|we(?:['’]re| are)|we(?:['’]ll| will)(?: now)?|now i(?:['’]ll| will)|next,? i(?:['’]ll| will)|let me(?: now)?|now,? let me|next,? let me)`;
|
|
88709
|
+
PROMISE = new RegExp(String.raw`^(?:${ME}\s+(?:now\s+|just\s+|going to\s+|about to\s+|currently\s+)*(?:prepar|compil|put(?:ting)?\b|writ|draft|gather|finali[sz]|summari[sz]|pull|assembl|format|work(?:ing)? on|get(?:ting)? (?:the|your|that|this)|provid|present|shar|send|deliver|giv)|(?:one moment|stand by|please wait|hang on|working on it|preparing|compiling|drafting|finali[sz]ing)\b)`, "i");
|
|
88710
|
+
}
|
|
88711
|
+
});
|
|
88712
|
+
|
|
88645
88713
|
// ../../packages/agent-runtime/dist/index.js
|
|
88646
88714
|
import { createHash as createHash6 } from "node:crypto";
|
|
88647
88715
|
import { appendFile as appendFile4, mkdir as mkdir12, readFile as readFile15 } from "node:fs/promises";
|
|
@@ -88843,7 +88911,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88843
88911
|
"Before repeatedly fighting the local environment, decide whether the task needs external capability such as hosting, persistent infrastructure, remote compute, specialized APIs, live data, or access the user's device does not have."
|
|
88844
88912
|
];
|
|
88845
88913
|
if (options.hosted)
|
|
88846
|
-
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;
|
|
88914
|
+
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.");
|
|
88847
88915
|
if (options.hosted)
|
|
88848
88916
|
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.");
|
|
88849
88917
|
if (options.dynamicTools) {
|
|
@@ -88889,6 +88957,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88889
88957
|
};
|
|
88890
88958
|
const currentBudget = () => options.financialState ? financial : budgetStatus(session);
|
|
88891
88959
|
const financialPrefix = "Current hosted financial snapshot: ";
|
|
88960
|
+
const financialNote = "[Automatic note from CrowdCode, not written by the user; do not reply to it. ";
|
|
88892
88961
|
if (!options.resume)
|
|
88893
88962
|
await options.onMessage?.({ role: "user", content: task });
|
|
88894
88963
|
const maxTurns = options.maxTurns ?? 100;
|
|
@@ -88896,6 +88965,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88896
88965
|
let completionNudges = options.resume?.completionNudges ?? 0;
|
|
88897
88966
|
let pendingFinalMessage = options.resume?.pendingFinalMessage;
|
|
88898
88967
|
let finalAnswerHeld = options.resume?.finalAnswerHeld ?? false;
|
|
88968
|
+
let answerNudges = options.resume?.answerNudges ?? 0;
|
|
88899
88969
|
let supersededFinalMessage;
|
|
88900
88970
|
let outputContinuationNudges = options.resume?.outputContinuationNudges ?? 0;
|
|
88901
88971
|
let outputContinuationPrefix = options.resume?.outputContinuationPrefix ?? "";
|
|
@@ -88912,6 +88982,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88912
88982
|
completionNudges,
|
|
88913
88983
|
pendingFinalMessage,
|
|
88914
88984
|
finalAnswerHeld,
|
|
88985
|
+
answerNudges,
|
|
88915
88986
|
outputContinuationNudges,
|
|
88916
88987
|
outputContinuationPrefix,
|
|
88917
88988
|
serviceCallFailures,
|
|
@@ -88938,7 +89009,8 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88938
89009
|
await options.inbox?.delivered(pending.map((m) => m.id));
|
|
88939
89010
|
return fresh.length > 0;
|
|
88940
89011
|
};
|
|
88941
|
-
const recordFinalMessage = (
|
|
89012
|
+
const recordFinalMessage = (raw) => {
|
|
89013
|
+
const text = raw === void 0 ? void 0 : stripReasoning(raw);
|
|
88942
89014
|
if (!text?.trim())
|
|
88943
89015
|
return;
|
|
88944
89016
|
if (!finalAnswerHeld)
|
|
@@ -88946,8 +89018,23 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88946
89018
|
else if (text.trim() !== pendingFinalMessage?.trim())
|
|
88947
89019
|
supersededFinalMessage = text;
|
|
88948
89020
|
};
|
|
88949
|
-
const
|
|
89021
|
+
const placeholder = () => !finalAnswerHeld && !!pendingFinalMessage && isNonAnswer(pendingFinalMessage) && messages.some((m) => m.role === "assistant" && m.toolCalls?.some((call2) => call2.name !== "complete_session"));
|
|
89022
|
+
const notAnAnswer = () => `Your final message so far ("${pendingFinalMessage.trim()}") is not an answer, and the user sees only your final message, never your tool results.`;
|
|
89023
|
+
const hold = () => {
|
|
89024
|
+
if (pendingFinalMessage?.trim() && !placeholder())
|
|
89025
|
+
finalAnswerHeld = true;
|
|
89026
|
+
};
|
|
89027
|
+
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.` : placeholder() ? `You cannot finish yet: ${blocker} ${notAnAnswer()} When you call complete_session again, put the complete answer to the user's request in it.` : `You cannot finish yet: ${blocker}`;
|
|
89028
|
+
const answerNudge = () => `${notAnAnswer()} Call complete_session again with the complete answer to the user's request: what you found or did, with the URLs, figures or identifiers they need.`;
|
|
88950
89029
|
const withReflection = (summary2) => supersededFinalMessage ? { ...summary2, reflection_note: supersededFinalMessage } : summary2;
|
|
89030
|
+
const holding = () => finalAnswerHeld && !!pendingFinalMessage?.trim() && !options.signal?.aborted;
|
|
89031
|
+
const deliverHeld = async (turn, problem) => {
|
|
89032
|
+
options.onProgress?.({ type: "complete", message: `Delivered the saved answer; housekeeping did not finish: ${problem}` });
|
|
89033
|
+
const summary2 = { ...withReflection(await completeSession(session, pendingFinalMessage)), housekeeping_error: problem };
|
|
89034
|
+
if (backgroundSubagents.size > 0)
|
|
89035
|
+
summary2.background_subagents = await drainBackground();
|
|
89036
|
+
return { outcome: "completed", summary: summary2, turns: turn + 1 };
|
|
89037
|
+
};
|
|
88951
89038
|
let subagentCount = 0;
|
|
88952
89039
|
const backgroundSubagents = /* @__PURE__ */ new Map();
|
|
88953
89040
|
const subagentLimiter = createLimiter(options.subagent?.maxParallel ?? 4);
|
|
@@ -88974,7 +89061,7 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88974
89061
|
const legacy = messages.findIndex((m) => m.role === "system" && m.content.startsWith(financialPrefix));
|
|
88975
89062
|
if (legacy !== -1)
|
|
88976
89063
|
messages.splice(legacy, 1);
|
|
88977
|
-
contextState.
|
|
89064
|
+
contextState.note = `${financialNote}${financialPrefix}${JSON.stringify(financial)}]`;
|
|
88978
89065
|
}
|
|
88979
89066
|
response = restored?.response ?? await completeWithContext(session, messages, {
|
|
88980
89067
|
provider: provider instanceof MockLlmProvider ? { complete: (input2) => completeMockLlmCall(session, provider, input2, turn + 1) } : provider,
|
|
@@ -88995,6 +89082,8 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
88995
89082
|
options.signal?.throwIfAborted();
|
|
88996
89083
|
await refreshFinancialState();
|
|
88997
89084
|
} catch (error53) {
|
|
89085
|
+
if (holding())
|
|
89086
|
+
return deliverHeld(turn, `the housekeeping model call failed: ${error53.message}`);
|
|
88998
89087
|
if (error53 instanceof BudgetExhaustedError) {
|
|
88999
89088
|
const summary2 = await completeSession(session, `Stopped: the session budget is exhausted (${error53.message}).`);
|
|
89000
89089
|
return { outcome: options.hosted ? "budget_exhausted" : "stopped", summary: summary2, turns: turn + 1 };
|
|
@@ -89004,12 +89093,14 @@ async function runAgentTaskDetailed(session, task, options = {}) {
|
|
|
89004
89093
|
if (!restored?.response && (response.content || response.toolCalls.length > 0)) {
|
|
89005
89094
|
const assistantMessage = assistantMessageFromResponse(isOutputLimitFinishReason(response.finishReason) ? { ...response, toolCalls: [] } : response);
|
|
89006
89095
|
messages.push(assistantMessage);
|
|
89007
|
-
await options.onMessage?.(assistantMessage);
|
|
89096
|
+
await options.onMessage?.(finalAnswerHeld ? { ...assistantMessage, housekeeping: true } : assistantMessage);
|
|
89008
89097
|
}
|
|
89009
89098
|
await checkpoint(turn, response, completedTools);
|
|
89010
89099
|
if (isOutputLimitFinishReason(response.finishReason)) {
|
|
89011
89100
|
outputContinuationPrefix += response.content;
|
|
89012
89101
|
if (outputContinuationNudges >= 1) {
|
|
89102
|
+
if (holding())
|
|
89103
|
+
return deliverHeld(turn, "the housekeeping turn hit the output limit twice");
|
|
89013
89104
|
const summary2 = await completeSession(session, `Stopped: the LLM hit its output limit twice. Partial response:
|
|
89014
89105
|
|
|
89015
89106
|
${outputContinuationPrefix}`);
|
|
@@ -89030,15 +89121,23 @@ ${outputContinuationPrefix}`);
|
|
|
89030
89121
|
const finalMessage = response.content.trim() ? outputContinuationPrefix + response.content : pendingFinalMessage ?? outputContinuationPrefix;
|
|
89031
89122
|
recordFinalMessage(finalMessage);
|
|
89032
89123
|
const blocker = await options.completionGate?.(completionNudges > 0);
|
|
89124
|
+
const unanswered = answerNudges < 1 && placeholder();
|
|
89033
89125
|
if (blocker) {
|
|
89034
89126
|
if (completionNudges >= 1) {
|
|
89127
|
+
hold();
|
|
89128
|
+
if (holding())
|
|
89129
|
+
return deliverHeld(turn, `the completion gate still blocks: ${blocker}`);
|
|
89035
89130
|
const summary3 = await completeSession(session, `Stopped: ${blocker}`);
|
|
89036
89131
|
return { outcome: "stopped", summary: summary3, turns: turn + 1 };
|
|
89037
89132
|
}
|
|
89038
89133
|
completionNudges += 1;
|
|
89039
|
-
|
|
89040
|
-
|
|
89041
|
-
|
|
89134
|
+
}
|
|
89135
|
+
if (blocker || unanswered) {
|
|
89136
|
+
if (unanswered)
|
|
89137
|
+
answerNudges += 1;
|
|
89138
|
+
hold();
|
|
89139
|
+
const content = blocker ? gateNudge(blocker) : answerNudge();
|
|
89140
|
+
const nudge = { role: "user", content };
|
|
89042
89141
|
messages.push(nudge);
|
|
89043
89142
|
await options.onMessage?.(nudge);
|
|
89044
89143
|
await checkpoint(turn + 1);
|
|
@@ -89090,42 +89189,52 @@ ${outputContinuationPrefix}`);
|
|
|
89090
89189
|
data: { tool: call2.name, arguments: call2.arguments }
|
|
89091
89190
|
});
|
|
89092
89191
|
const budgetBeforeToolCall = currentBudget();
|
|
89192
|
+
const salvaged = call2.invalidArguments === void 0 || call2.name !== "complete_session" ? void 0 : response.content.trim() ? response.content : holding() ? pendingFinalMessage : void 0;
|
|
89193
|
+
const baseArguments = salvaged === void 0 ? call2.arguments : { final_message: salvaged };
|
|
89093
89194
|
const callArguments = call2.name === "complete_session" && outputContinuationPrefix ? {
|
|
89094
|
-
...
|
|
89095
|
-
final_message: outputContinuationPrefix + (typeof
|
|
89096
|
-
} :
|
|
89195
|
+
...baseArguments,
|
|
89196
|
+
final_message: outputContinuationPrefix + (typeof baseArguments.final_message === "string" ? baseArguments.final_message : "")
|
|
89197
|
+
} : baseArguments;
|
|
89097
89198
|
let result;
|
|
89098
|
-
|
|
89099
|
-
|
|
89100
|
-
|
|
89101
|
-
|
|
89102
|
-
result =
|
|
89103
|
-
}
|
|
89104
|
-
|
|
89105
|
-
|
|
89106
|
-
|
|
89107
|
-
|
|
89108
|
-
|
|
89109
|
-
|
|
89199
|
+
try {
|
|
89200
|
+
if (completedTools[call2.id]) {
|
|
89201
|
+
result = completedTools[call2.id];
|
|
89202
|
+
} else if (call2.invalidArguments !== void 0 && salvaged === void 0) {
|
|
89203
|
+
result = { ok: false, error: invalidArgumentsError(call2.name, call2.invalidArguments) };
|
|
89204
|
+
} else if (call2.name === "spawn_subagent") {
|
|
89205
|
+
try {
|
|
89206
|
+
result = options.subagent ? await (spawnedThisTurn.get(call2.id) ?? Promise.resolve({ ok: false, error: "subagent launch failed" })) : { ok: false, error: "subagents are not enabled for this session" };
|
|
89207
|
+
} catch (error53) {
|
|
89208
|
+
await Promise.allSettled(spawnedThisTurn.values());
|
|
89209
|
+
throw error53;
|
|
89210
|
+
}
|
|
89211
|
+
} else if (call2.name === "check_subagents") {
|
|
89212
|
+
if (call2.arguments.wait === true) {
|
|
89213
|
+
result = { ok: true, data: { subagents: await drainBackground() } };
|
|
89214
|
+
} else {
|
|
89215
|
+
result = {
|
|
89216
|
+
ok: true,
|
|
89217
|
+
data: {
|
|
89218
|
+
subagents: [...backgroundSubagents.values()].map((entry) => ({
|
|
89219
|
+
subagent_index: entry.index,
|
|
89220
|
+
task: entry.task,
|
|
89221
|
+
status: entry.status,
|
|
89222
|
+
...entry.status === "finished" && entry.result?.ok && entry.result.data && typeof entry.result.data === "object" ? entry.result.data : entry.status === "finished" ? { outcome: "error", error: entry.result?.error } : {}
|
|
89223
|
+
}))
|
|
89224
|
+
}
|
|
89225
|
+
};
|
|
89226
|
+
}
|
|
89227
|
+
} else if (TOOL_NAMES.includes(call2.name)) {
|
|
89228
|
+
result = await toolExecutor(call2.name, callArguments, { session, onProgress: options.onProgress, signal: options.signal });
|
|
89229
|
+
} else if (options.dynamicTools) {
|
|
89230
|
+
result = await options.dynamicTools.execute(call2.name, callArguments);
|
|
89110
89231
|
} else {
|
|
89111
|
-
result = {
|
|
89112
|
-
ok: true,
|
|
89113
|
-
data: {
|
|
89114
|
-
subagents: [...backgroundSubagents.values()].map((entry) => ({
|
|
89115
|
-
subagent_index: entry.index,
|
|
89116
|
-
task: entry.task,
|
|
89117
|
-
status: entry.status,
|
|
89118
|
-
...entry.status === "finished" && entry.result?.ok && entry.result.data && typeof entry.result.data === "object" ? entry.result.data : entry.status === "finished" ? { outcome: "error", error: entry.result?.error } : {}
|
|
89119
|
-
}))
|
|
89120
|
-
}
|
|
89121
|
-
};
|
|
89232
|
+
result = { ok: false, error: `unknown tool: ${call2.name}` };
|
|
89122
89233
|
}
|
|
89123
|
-
}
|
|
89124
|
-
|
|
89125
|
-
|
|
89126
|
-
|
|
89127
|
-
} else {
|
|
89128
|
-
result = { ok: false, error: `unknown tool: ${call2.name}` };
|
|
89234
|
+
} catch (error53) {
|
|
89235
|
+
if (holding())
|
|
89236
|
+
return deliverHeld(turn, `the housekeeping tool ${call2.name} failed: ${error53.message}`);
|
|
89237
|
+
throw error53;
|
|
89129
89238
|
}
|
|
89130
89239
|
result = capToolResult(result);
|
|
89131
89240
|
await refreshFinancialState();
|
|
@@ -89161,6 +89270,8 @@ ${outputContinuationPrefix}`);
|
|
|
89161
89270
|
if (call2.name === "call_paid_service") {
|
|
89162
89271
|
serviceCallFailures += 1;
|
|
89163
89272
|
if (serviceCallFailures >= 3) {
|
|
89273
|
+
if (holding())
|
|
89274
|
+
return deliverHeld(turn, `paid service calls failed ${serviceCallFailures} times: ${result.error}`);
|
|
89164
89275
|
const summary2 = await completeSession(session, `Stopped after ${serviceCallFailures} service call failures. Last error: ${result.error}`);
|
|
89165
89276
|
return { outcome: "stopped", summary: summary2, turns: turn + 1 };
|
|
89166
89277
|
}
|
|
@@ -89169,6 +89280,8 @@ ${outputContinuationPrefix}`);
|
|
|
89169
89280
|
const count = (repeatedFailures.get(key) ?? 0) + 1;
|
|
89170
89281
|
repeatedFailures.set(key, count);
|
|
89171
89282
|
if (count >= 2) {
|
|
89283
|
+
if (holding())
|
|
89284
|
+
return deliverHeld(turn, `${call2.name} failed repeatedly: ${result.error}`);
|
|
89172
89285
|
const summary2 = await completeSession(session, `Stopped because ${call2.name} failed repeatedly: ${result.error}`);
|
|
89173
89286
|
return { outcome: "stopped", summary: summary2, turns: turn + 1 };
|
|
89174
89287
|
}
|
|
@@ -89186,17 +89299,25 @@ ${outputContinuationPrefix}`);
|
|
|
89186
89299
|
if (typeof finalMessage === "string")
|
|
89187
89300
|
recordFinalMessage(finalMessage);
|
|
89188
89301
|
const blocker = await options.completionGate?.(completionNudges > 0);
|
|
89302
|
+
const unanswered = answerNudges < 1 && placeholder();
|
|
89189
89303
|
if (blocker) {
|
|
89190
89304
|
if (completionNudges >= 1) {
|
|
89305
|
+
hold();
|
|
89306
|
+
if (holding())
|
|
89307
|
+
return deliverHeld(turn, `the completion gate still blocks: ${blocker}`);
|
|
89191
89308
|
const summary3 = await completeSession(session, `Stopped: ${blocker}`);
|
|
89192
89309
|
return { outcome: "stopped", summary: summary3, turns: turn + 1 };
|
|
89193
89310
|
}
|
|
89194
89311
|
completionNudges += 1;
|
|
89195
|
-
|
|
89196
|
-
|
|
89312
|
+
}
|
|
89313
|
+
if (blocker || unanswered) {
|
|
89314
|
+
if (unanswered)
|
|
89315
|
+
answerNudges += 1;
|
|
89316
|
+
hold();
|
|
89317
|
+
const content = blocker ? gateNudge(blocker) : answerNudge();
|
|
89197
89318
|
const gateMessage = {
|
|
89198
89319
|
role: "user",
|
|
89199
|
-
content
|
|
89320
|
+
content
|
|
89200
89321
|
};
|
|
89201
89322
|
messages.push(gateMessage);
|
|
89202
89323
|
await options.onMessage?.(gateMessage);
|
|
@@ -89220,6 +89341,8 @@ ${outputContinuationPrefix}`);
|
|
|
89220
89341
|
return { outcome: "completed", summary: summary2, turns: turn + 1 };
|
|
89221
89342
|
}
|
|
89222
89343
|
}
|
|
89344
|
+
if (holding())
|
|
89345
|
+
return deliverHeld(maxTurns - 1, "the run reached its maximum turns during housekeeping");
|
|
89223
89346
|
if (backgroundSubagents.size > 0) {
|
|
89224
89347
|
await drainBackground();
|
|
89225
89348
|
}
|
|
@@ -89453,9 +89576,15 @@ function assistantMessageFromResponse(response) {
|
|
|
89453
89576
|
return {
|
|
89454
89577
|
role: "assistant",
|
|
89455
89578
|
content: response.content,
|
|
89456
|
-
|
|
89579
|
+
// The raw text of a malformed call is for this runtime's error, not a
|
|
89580
|
+
// field a provider request may carry.
|
|
89581
|
+
toolCalls: response.toolCalls.map(({ invalidArguments: _invalid, ...call2 }) => call2)
|
|
89457
89582
|
};
|
|
89458
89583
|
}
|
|
89584
|
+
function invalidArgumentsError(name, raw) {
|
|
89585
|
+
const shown = raw.length > 300 ? `${raw.slice(0, 300)}\u2026` : raw;
|
|
89586
|
+
return `Your ${name} call was not run: its arguments were not a valid JSON object (${JSON.stringify(shown)}). Call ${name} again with valid JSON arguments.`;
|
|
89587
|
+
}
|
|
89459
89588
|
async function completeMockLlmCall(session, provider, messages, turn) {
|
|
89460
89589
|
const costCents = 1;
|
|
89461
89590
|
const reservation = await reserveBudget(session, costCents);
|
|
@@ -89765,6 +89894,8 @@ var init_dist6 = __esm({
|
|
|
89765
89894
|
init_knowledge();
|
|
89766
89895
|
init_context2();
|
|
89767
89896
|
init_tool_deadlines();
|
|
89897
|
+
init_non_answer();
|
|
89898
|
+
init_non_answer();
|
|
89768
89899
|
MockLlmProvider = class {
|
|
89769
89900
|
random;
|
|
89770
89901
|
endProbability;
|
package/package.json
CHANGED