opencrowd 0.15.3 → 0.15.4

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.
Files changed (2) hide show
  1. package/bundle/opencrowd.js +45 -13
  2. package/package.json +1 -1
@@ -15432,6 +15432,13 @@ var init_primitives = __esm({
15432
15432
  });
15433
15433
 
15434
15434
  // ../../packages/protocol/dist/outcomes.js
15435
+ function upstreamRefusalSummary(error53) {
15436
+ const refusal = error53;
15437
+ if (!refusal || typeof refusal !== "object" || refusal.name !== "HostedRequestError" || refusal.code !== "upstream_refused")
15438
+ return void 0;
15439
+ const detail = typeof refusal.message === "string" ? refusal.message.trim() : "";
15440
+ return `The model provider refused this request before any payment, so nothing was charged${detail ? `: ${detail}` : "."} You can retry or send another message.`;
15441
+ }
15435
15442
  var RUN_FAILURE_MESSAGE, RUN_OUTCOMES, RunOutcomeSchema, RESUME_CAUSES, ResumeCauseSchema, RunStateSchema;
15436
15443
  var init_outcomes = __esm({
15437
15444
  "../../packages/protocol/dist/outcomes.js"() {
@@ -16101,6 +16108,18 @@ function estimateContextTokens(value) {
16101
16108
  function estimateModelInput(messages, tools) {
16102
16109
  return messages.reduce((total, message) => total + estimateContextTokens(message), estimateContextTokens(tools) + 32);
16103
16110
  }
16111
+ function isRequestTooLargeError(value, status) {
16112
+ if (status === 413)
16113
+ return true;
16114
+ const error53 = value;
16115
+ if (!error53 || typeof error53 !== "object")
16116
+ return false;
16117
+ if (["request_too_large", "payload_too_large", "request_entity_too_large", "body_too_large"].includes(String(error53.code)))
16118
+ return true;
16119
+ if (typeof error53.message === "string" && /request (?:body|entity|payload) (?:is )?too large|payload too large|request too large|body must be at most/i.test(error53.message))
16120
+ return true;
16121
+ return error53.error !== value && !!error53.error && isRequestTooLargeError(typeof error53.error === "string" ? { message: error53.error } : error53.error);
16122
+ }
16104
16123
  function isContextWindowError(value) {
16105
16124
  const error53 = value;
16106
16125
  if (!error53 || typeof error53 !== "object")
@@ -16111,11 +16130,12 @@ function isContextWindowError(value) {
16111
16130
  return true;
16112
16131
  return error53.error !== value && !!error53.error && isContextWindowError(typeof error53.error === "string" ? { message: error53.error } : error53.error);
16113
16132
  }
16114
- var MODEL_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;
16133
+ 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;
16115
16134
  var init_context = __esm({
16116
16135
  "../../packages/protocol/dist/context.js"() {
16117
16136
  "use strict";
16118
16137
  MODEL_REQUEST_MAX_BYTES = 16 * 1024 * 1024;
16138
+ MODEL_SELLER_REQUEST_MAX_BYTES = 5 * 1024 * 1024;
16119
16139
  MODEL_MAX_MESSAGES = 1e3;
16120
16140
  MODEL_GATEWAY_TIMEOUT_MS = 42e4;
16121
16141
  MODEL_BRIDGE_TIMEOUT_MS = 2 * MODEL_GATEWAY_TIMEOUT_MS + 3e4;
@@ -59738,7 +59758,7 @@ async function completeWithContext(session, messages, options) {
59738
59758
  options.state.retry = 0;
59739
59759
  return response;
59740
59760
  } catch (error53) {
59741
- const overflow = error53 instanceof ContextWindowExceeded || !options.hosted && isContextWindowError(error53);
59761
+ const overflow = error53 instanceof ContextWindowExceeded || !options.hosted && (isContextWindowError(error53) || isRequestTooLargeError(error53));
59742
59762
  if (!overflow || (options.state.retry ?? 0) >= 2)
59743
59763
  throw error53;
59744
59764
  options.state.retry = (options.state.retry ?? 0) + 1;
@@ -59764,10 +59784,12 @@ async function compactContext(session, messages, options) {
59764
59784
  const count = (list2) => Math.ceil(list2.reduce((total, m) => total + measure(m).tokens, toolTokens) * scale);
59765
59785
  const tokensBefore = count(messages);
59766
59786
  const retry = options.state.retry ?? 0;
59767
- const trigger = Math.floor(limits.trigger * 0.5 ** retry);
59768
- const target = Math.min(limits.target, Math.floor(trigger * 0.5));
59769
59787
  const bytes = (list2) => list2.reduce((total, m) => total + measure(m).bytes, toolBytes);
59770
- const transportLimit = MODEL_REQUEST_MAX_BYTES - 64 * 1024;
59788
+ const budget = options.maxRequestBytes ?? (options.hosted ? MODEL_SELLER_REQUEST_MAX_BYTES : MODEL_REQUEST_MAX_BYTES);
59789
+ const byteCeiling = budget - 64 * 1024;
59790
+ const trigger = retry ? Math.min(Math.floor(limits.trigger * 0.5 ** retry), Math.floor(tokensBefore * 0.5)) : limits.trigger;
59791
+ const target = Math.min(limits.target, Math.floor(trigger * 0.5));
59792
+ const transportLimit = retry ? Math.floor(Math.min(byteCeiling, bytes(messages) * 0.5)) : byteCeiling;
59771
59793
  if (tokensBefore <= trigger && bytes(messages) <= transportLimit && messages.length <= MODEL_MAX_MESSAGES && !retry)
59772
59794
  return { tokensBefore, tokensAfter: tokensBefore };
59773
59795
  const raw = messages.map((message) => JSON.stringify(message)).join("\n") + "\n";
@@ -59826,7 +59848,7 @@ async function compactContext(session, messages, options) {
59826
59848
  entry.message.content = await externalize(entry.message, entry.index);
59827
59849
  }
59828
59850
  const tokensAfter = count(current());
59829
- if (tokensAfter > trigger || bytes(current()) > transportLimit || list.length > MODEL_MAX_MESSAGES)
59851
+ if (tokensAfter > Math.max(trigger, limits.trigger) || bytes(current()) > byteCeiling || list.length > MODEL_MAX_MESSAGES)
59830
59852
  throw new Error(`Context cannot fit after compaction: system instructions, tools and required references exceed the input budget. Original context: ${archivePath}`);
59831
59853
  messages.splice(0, messages.length, ...current());
59832
59854
  return { tokensBefore, tokensAfter, archivePath };
@@ -87133,8 +87155,8 @@ function createHostedProvider(options) {
87133
87155
  if (!operationId?.startsWith(`${options.runId}:llm:`))
87134
87156
  throw new Error("Hosted model operation scope is missing");
87135
87157
  const body = JSON.stringify({ runId: options.runId, sessionId: options.sessionId, operationId, messages: messages.map(({ contextArchive: _archive, ...message }) => message), tools });
87136
- if (Buffer.byteLength(body) > MODEL_REQUEST_MAX_BYTES)
87137
- throw new Error("Hosted request exceeds the transport byte limit");
87158
+ if (Buffer.byteLength(body) > MODEL_SELLER_REQUEST_MAX_BYTES)
87159
+ throw new ContextWindowExceeded(`Hosted request is ${Buffer.byteLength(body)} bytes, above the ${MODEL_SELLER_REQUEST_MAX_BYTES} a seller accepts`);
87138
87160
  const result = await new Promise((resolve9, reject) => {
87139
87161
  const req = request({
87140
87162
  socketPath: options.socketPath,
@@ -87201,10 +87223,14 @@ function rejectedRequest(status, text) {
87201
87223
  return new HostedRequestError("model_failed", status, String(body.message ?? "The model response failed after payment settled. Its receipt is saved."));
87202
87224
  if (body.paid !== false)
87203
87225
  return void 0;
87204
- if (isContextWindowError({ code: body.error, message: body.message }))
87226
+ const upstream = body.upstream && typeof body.upstream === "object" && typeof body.upstream.code === "string" ? { status: Number(body.upstream.status) || status, code: body.upstream.code } : void 0;
87227
+ const refusal = { code: upstream?.code ?? body.error, message: body.message };
87228
+ if (isContextWindowError(refusal))
87205
87229
  return new ContextWindowExceeded(String(body.message ?? "Provider context window exceeded"));
87230
+ if (isRequestTooLargeError(refusal, upstream?.status ?? status))
87231
+ return new ContextWindowExceeded(String(body.message ?? "The model provider refused this request as too large"));
87206
87232
  const code = typeof body.error === "string" && body.error ? body.error : `http_${status}`;
87207
- return new HostedRequestError(code, status, typeof body.message === "string" && body.message ? body.message : `The model request was rejected (${code})`);
87233
+ return new HostedRequestError(code, status, typeof body.message === "string" && body.message ? body.message : `The model request was rejected (${code})`, upstream);
87208
87234
  } catch {
87209
87235
  return void 0;
87210
87236
  }
@@ -87308,12 +87334,18 @@ var init_hosted_provider = __esm({
87308
87334
  HostedRequestError = class extends Error {
87309
87335
  code;
87310
87336
  status;
87311
- constructor(code, status, message) {
87337
+ upstream;
87338
+ constructor(code, status, message, upstream) {
87312
87339
  super(message);
87313
87340
  this.code = code;
87314
87341
  this.status = status;
87342
+ this.upstream = upstream;
87315
87343
  this.name = "HostedRequestError";
87316
87344
  }
87345
+ /** What the owner reads as the run's summary; undefined keeps the generic copy. */
87346
+ get summary() {
87347
+ return upstreamRefusalSummary(this);
87348
+ }
87317
87349
  };
87318
87350
  HOSTED_TOOL_REQUEST_BYTES = 1024 * 1024;
87319
87351
  HostedToolTimeout = class extends Error {
@@ -87660,7 +87692,7 @@ var init_hosted_economy = __esm({
87660
87692
  throw new SpendingDeclined();
87661
87693
  if (reply.code === "approval_required")
87662
87694
  throw new RuntimePause("waiting_for_approval", purchaseId, "Spending approval required. Review the quoted amount to continue.");
87663
- if (reply.code === "expected_payment_required") {
87695
+ if (reply.code === "expected_payment_required" || reply.code === "upstream_refused") {
87664
87696
  return this.fetchUnpaid(request2.url, method, body, request2.headers);
87665
87697
  }
87666
87698
  if (reply.code === "funding_required") {
@@ -88392,7 +88424,7 @@ var init_worker = __esm({
88392
88424
  } else if (error53 instanceof SpendingDeclined)
88393
88425
  await this.finish(runId, run, "user_stopped", error53.message);
88394
88426
  else
88395
- await this.finish(runId, run, "failed", RUN_FAILURE_MESSAGE);
88427
+ await this.finish(runId, run, "failed", upstreamRefusalSummary(error53) ?? RUN_FAILURE_MESSAGE);
88396
88428
  }
88397
88429
  }
88398
88430
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencrowd",
3
- "version": "0.15.3",
3
+ "version": "0.15.4",
4
4
  "description": "A CLI agent with its own wallet — discovers x402 services, pays in USDC, and completes tasks under a local budget",
5
5
  "type": "module",
6
6
  "license": "MIT",