opencrowd 0.13.4 → 0.14.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.
Files changed (2) hide show
  1. package/bundle/opencrowd.js +20 -11
  2. package/package.json +1 -1
@@ -16885,13 +16885,13 @@ function toolDescription(name) {
16885
16885
  case "complete_session":
16886
16886
  return "Finish the agent run and present a concise final answer.";
16887
16887
  case "deploy_service":
16888
- return "Deploy a paid HTTP service you wrote to OpenCrowd's hosting. The entry file must be a JavaScript or TypeScript ES module saved with save_file that exports default { async fetch(request, env) }. Buyers pay the listed USDC price per call with x402; payments settle to this agent's own wallet. Vault secrets listed in `secrets` are exposed to the service as env vars (env.NAME) but contain opaque placeholders: the real value is substituted at the network boundary only for requests to `allowed_hosts`, so never print or return a secret. Redeploying the same slug updates the service in place. Returns the public URL and listing status.";
16888
+ return "Deploy a paid HTTP service you wrote to CrowdCode hosting. The entry file is an ES module saved with save_file that exports default { async fetch(request, env) }. Buyers pay per call with x402/MPP and the money goes to this agent's wallet. Fixed price: price_usd. Per-request price: pricing {mode:\"quote\",min_usd,max_usd} and also export quote(request, env), which runs before payment and returns { price_usd } or a 4xx Response to refuse; fetch then runs after payment with env.CROWDCODE.max_charge_atomic and may set response header x-crowdcode-charge-usd to settle less (upto). Optional headers: x-crowdcode-upstream-cost-usd (for margin), x-crowdcode-upstream-balance-usd (triggers top-ups), x-crowdcode-topup: required (refill and retry once). Vault secrets in `secrets` are env.NAME placeholders substituted only on requests to `allowed_hosts`; `raw_secrets` lets code read a value once the owner approves it for this code. `signers` gives env.NAME as a fresh Sign-In-With-X header signed by this agent's wallet for one approved URL. `topup` keeps a prepaid upstream balance refilled from this agent's wallet. Signers, topup and raw_secrets wait for the owner's approval in the services tab. Redeploying a slug updates it in place.";
16889
16889
  case "request_secret":
16890
- return "Use action=list first when you need to see this agent's vault secret titles and statuses (values are never exposed). Use action=create to ask the user to add a named API key or token to the encrypted vault. The user enters the value in their own UI; never ask them to paste a secret into chat. For create, provide name, allowed_hosts, and reason. Reference an active secret by name in deploy_service `secrets` and read it in service code as env.NAME; the real value is substituted only on requests to allowed_hosts.";
16890
+ return "Use action=list first when you need to see this agent's vault secret titles and statuses (values are never exposed). Use action=create to ask the user to add a named API key or token to the encrypted vault. The user enters the value in their own UI; never ask them to paste a secret into chat. Use action=store to save a credential you obtained yourself (for example an API key from a sign-up) with name, value, allowed_hosts and reason: it is write-only, you can never read it back, and it cannot replace a secret the user added. Prefer vault_request capture when the key arrives in an API response, so you never see it. Reference an active secret by name in deploy_service `secrets` and read it in service code as env.NAME, or as {{NAME}} in vault_request; the real value is substituted only on requests to allowed_hosts.";
16891
16891
  case "vault_request":
16892
- return "Send one HTTPS request to an external API with vault secrets injected by the platform. Write {{SECRET_NAME}} anywhere in the url, headers, or body and the real value is substituted at the network boundary, only for hosts the user approved for that secret; you never see the value and the response is blocked if it echoes one. Use it to call APIs on the user's behalf (for example posting to X with an OAuth token). The body is a string (JSON, form encoding, or text), or a workspace file up to 25 MB via body_artifact (sent raw, or as one multipart/form-data file part when body_field is set, with form_fields alongside). Returns the status, content-type, and the response body text (truncated at 64 KB). Check request_secret action=list for available secret names first.";
16892
+ return "Send one HTTPS request to an external API with vault secrets injected by the platform. Write {{SECRET_NAME}} anywhere in the url, headers, or body and the real value is substituted at the network boundary, only for hosts the user approved for that secret; you never see the value and the response is blocked if it echoes one. Use it to call APIs on the user's behalf (for example posting to X with an OAuth token). The body is a string (JSON, form encoding, or text), or a workspace file up to 25 MB via body_artifact (sent raw, or as one multipart/form-data file part when body_field is set, with form_fields alongside). Returns the status, content-type, and the response body text (truncated at 64 KB). Check request_secret action=list for available secret names first. Set capture {name, json_path or header} to store a credential from the response (such as the api_key a sign-up returns) in the vault: you get {{NAME}} back in place of the value, usable on the host that issued it.";
16893
16893
  case "automations":
16894
- return "Create, list, update, pause, resume, run now, or delete persistent automations for this hosted agent. Use create proactively when the user's goal clearly needs a future follow-up, reminder, monitoring loop, recurring report, or maintenance task. Automations run in this same conversation. Never create duplicates or hide a schedule from the user.";
16894
+ return "Create, list, update, pause, resume, run now, or delete persistent automations for this hosted agent. Use create proactively when the user's goal clearly needs a future follow-up, reminder, monitoring loop, recurring report, or maintenance task. Automations run in this same conversation. A schedule runs at most every 15 minutes; each run spends at most run_budget_usd (default 0.25) and the schedule at most daily_cap_usd (default 1) per 24 hours. Anything more often than hourly or above $1 a day waits for the owner's approval in the Schedules tab; tell the user. Never create duplicates or hide a schedule from the user.";
16895
16895
  }
16896
16896
  }
16897
16897
  function toolParameters(name) {
@@ -16934,7 +16934,12 @@ function toolParameters(name) {
16934
16934
  slug: stringSchema("URL-safe identifier, lowercase letters, digits and dashes, 3-40 characters. Stable across redeploys."),
16935
16935
  name: stringSchema("Human-readable service name shown to buyers."),
16936
16936
  description: stringSchema("What the service does and returns; used by buyers and discovery search. One or two sentences."),
16937
- price_usd: stringSchema('Price per paid call in USD, for example "0.001". Minimum 0.0001.'),
16937
+ price_usd: stringSchema('Fixed price per paid call in USD, for example "0.001". Minimum 0.0001. Omit when pricing.mode is quote.'),
16938
+ pricing: { type: "object", description: 'Per-request pricing: { mode: "quote", min_usd, max_usd }. The module must export quote(request, env). Omit for a fixed price_usd.', additionalProperties: true },
16939
+ networks: { type: "array", description: 'Networks to sell on: base, solana, tempo. Default: all enabled. Use ["base"] when the service pays its costs on Base.', items: stringSchema("Network key.") },
16940
+ signers: { type: "array", description: `Sign-In-With-X as this agent's wallet: [{ name: "VENICE_SIWX", url: "https://api.example.com/v1/chat", statement?: "Sign in to Example" }]. env.NAME is a placeholder for a fresh signed header, valid only for that exact URL; send it as SIGN-IN-WITH-X. The URL's host must be in allowed_hosts. Needs owner approval.`, items: { type: "object", additionalProperties: true } },
16941
+ topup: { type: "object", description: "Prepaid upstream balance kept refilled from this agent's wallet: { url (x402 top-up endpoint), balance_url? (with {address}), balance_field? (e.g. data.balanceUsd), refill_below_usd, amount_usd }. Needs owner approval; the owner sets limits.", additionalProperties: true },
16942
+ raw_secrets: { type: "array", description: "Vault secrets the code must read as values (HMAC signing, OAuth 1.0a). Off until the owner approves them for this exact code; prefer `secrets` placeholders.", items: stringSchema("Vault secret name.") },
16938
16943
  entry: stringSchema("Artifact path of the entry module saved with save_file, for example service/index.js."),
16939
16944
  routes: {
16940
16945
  type: "array",
@@ -16949,10 +16954,11 @@ function toolParameters(name) {
16949
16954
  },
16950
16955
  secrets: { type: "array", description: "Names of vault secrets the service needs as env vars.", items: stringSchema("Vault secret name.") },
16951
16956
  allowed_hosts: { type: "array", description: "Upstream hostnames the service is allowed to call, for example api.coingecko.com. Any other outbound host is blocked.", items: stringSchema("Hostname.") }
16952
- }, ["slug", "name", "description", "price_usd", "entry", "routes"]);
16957
+ }, ["slug", "name", "description", "entry", "routes"]);
16953
16958
  case "request_secret":
16954
16959
  return objectSchema({
16955
- action: { type: "string", description: "list to inspect secret titles/statuses; create to request or reuse a secret." },
16960
+ action: { type: "string", description: "list to inspect secret titles/statuses; create to ask the user for a secret; store to save one you obtained yourself." },
16961
+ value: stringSchema("store only: the credential to save. It is write-only from here on."),
16956
16962
  name: { type: "string", pattern: "^[A-Z][A-Z0-9_]{1,63}$", description: "Secret name in SCREAMING_SNAKE_CASE, for example OPENAI_API_KEY. This is the env var name your service reads." },
16957
16963
  allowed_hosts: { type: "array", description: "Hostnames the secret may be sent to, for example api.openai.com. The vault only substitutes the real value on requests to these hosts.", items: stringSchema("Hostname.") },
16958
16964
  reason: stringSchema("One short sentence shown to the user explaining why the secret is needed.")
@@ -16966,7 +16972,8 @@ function toolParameters(name) {
16966
16972
  body_artifact: stringSchema("Workspace file to send as the body, as a path under artifacts/ (for example demos/clip.part00). Up to 25 MB; the file is uploaded first."),
16967
16973
  body_field: stringSchema("When set, the file is sent as a multipart/form-data part with this field name (for example media) instead of raw bytes."),
16968
16974
  form_fields: { type: "object", description: 'Extra multipart text fields sent with the file, for example { "segment_index": "0" }.', additionalProperties: { type: "string" } },
16969
- reason: stringSchema("One short sentence shown to the user describing what this request does.")
16975
+ reason: stringSchema("One short sentence shown to the user describing what this request does."),
16976
+ capture: { type: "object", description: "Store a credential from the response in the vault: { name, json_path (e.g. data.api_key) or header, allowed_hosts? }. The value is replaced by {{NAME}} in what you receive.", additionalProperties: true }
16970
16977
  }, ["url"]);
16971
16978
  case "automations":
16972
16979
  return automationSchema({ action: { type: "string", description: "create, list, update, pause, resume, run, or delete." }, automation_id: stringSchema("Automation ID, except for create and list.") }, ["action"]);
@@ -17023,7 +17030,9 @@ function automationSchema(extra, required3 = []) {
17023
17030
  atTime: stringSchema("ISO 8601 timestamp for a one-time schedule."),
17024
17031
  cronExpression: stringSchema("Five-field cron expression, for example 50 19 * * 3."),
17025
17032
  timezone: stringSchema("IANA timezone, for example America/Los_Angeles."),
17026
- model: stringSchema("Optional model ID.")
17033
+ model: stringSchema("Optional model ID."),
17034
+ run_budget_usd: stringSchema(`Most one run may spend in USD, default "0.25"; at most the owner's per-query budget.`),
17035
+ daily_cap_usd: stringSchema(`Most this schedule may spend per 24 hours in USD, default "1". Above 1 needs the owner's approval.`)
17027
17036
  }, required3);
17028
17037
  }
17029
17038
  function objectSchema(properties, required3 = []) {
@@ -82555,10 +82564,10 @@ async function runAgentTaskDetailed(session, task, options = {}) {
82555
82564
  }
82556
82565
  const hostedTools = options.hosted ? options.tools ?? TOOL_NAMES : [];
82557
82566
  if (hostedTools.includes("deploy_service")) {
82558
- systemPromptParts.push("Hosting: you can publish paid HTTP services with deploy_service. Write the entry module with save_file (for example service/index.js) as an ES module with `export default { async fetch(request, env) { ... } }`, with no imports and no npm packages; the Workers runtime provides fetch, Request, Response, URL and crypto.", "The platform enforces payment before your handler runs, so your code only implements the route logic. Vault secrets you list in `secrets` arrive as env.NAME placeholders that are swapped for the real value only on outbound requests to `allowed_hosts`; never log, hash locally, or return a secret, and never build URLs to hosts you did not declare.", "After deploy_service succeeds, report the public URL, the price, and how to call each route.");
82567
+ systemPromptParts.push("Hosting: you can publish paid HTTP services with deploy_service. Write the entry module with save_file (for example service/index.js) as an ES module with `export default { async fetch(request, env) { ... } }`, with no imports and no npm packages; the Workers runtime provides fetch, Request, Response, URL and crypto.", "The platform enforces payment before your handler runs, so your code only implements the route logic. Vault secrets you list in `secrets` arrive as env.NAME placeholders that are swapped for the real value only on outbound requests to `allowed_hosts`; never log, hash locally, or return a secret, and never build URLs to hosts you did not declare.", `When a call's cost depends on the request (tokens, minutes, rows), use pricing {mode: "quote"} with a quote(request, env) export that refuses impossible requests before payment, and report what was used with x-crowdcode-charge-usd. When the service resells an upstream that needs a wallet signature or a prepaid balance, declare signers and topup instead of asking for keys; the owner approves them in the services tab.`, "After deploy_service succeeds, report the public URL, the price, how to call each route, and anything still waiting for the owner's approval.");
82559
82568
  }
82560
82569
  if (hostedTools.includes("request_secret")) {
82561
- systemPromptParts.push("Buy the capability before asking for the owner's credentials: sending email, SMS or a phone call, publishing, storage, data lookups and similar capabilities are usually purchasable, and you have a wallet. When the task needs one, search for a payable service with find_paid_service and pay for it yourself rather than requesting a personal API key, token or password the owner must go and create. Ask for a secret only when the work genuinely needs the owner's own account or identity \u2014 posting as them, reading their mailbox or calendar, or acting inside a service they already pay for \u2014 or when no payable service covers it, and say which you are doing and why. Never end a run on a secret request while a service you could have paid for would have finished the task.", "Secrets: call request_secret with action=list whenever you need to inspect this agent's available vault secret titles and statuses; values are never returned. When a service needs a new key or token, call it with action=create, a SCREAMING_SNAKE_CASE name, the hosts it may be sent to, and a one-sentence reason. The user adds the value in their own UI; never ask them to paste a secret into chat and never expect to see it. If a requested secret is active, list its name in deploy_service `secrets` and read it as env.NAME; if requested, tell the user what to add and continue or finish without it.");
82570
+ systemPromptParts.push("Buy the capability before asking for the owner's credentials: sending email, SMS or a phone call, publishing, storage, data lookups and similar capabilities are usually purchasable, and you have a wallet. When the task needs one, search for a payable service with find_paid_service and pay for it yourself rather than requesting a personal API key, token or password the owner must go and create. Ask for a secret only when the work genuinely needs the owner's own account or identity \u2014 posting as them, reading their mailbox or calendar, or acting inside a service they already pay for \u2014 or when no payable service covers it, and say which you are doing and why. Never end a run on a secret request while a service you could have paid for would have finished the task.", "Secrets: call request_secret with action=list whenever you need to inspect this agent's available vault secret titles and statuses; values are never returned. When a service needs a new key or token, call it with action=create, a SCREAMING_SNAKE_CASE name, the hosts it may be sent to, and a one-sentence reason. The user adds the value in their own UI; never ask them to paste a secret into chat and never expect to see it. If a requested secret is active, list its name in deploy_service `secrets` and read it as env.NAME; if requested, tell the user what to add and continue or finish without it. When you obtain a credential yourself, such as the API key a sign-up returns, keep it: vault_request with capture stores it straight from the response without you seeing it, and request_secret action=store saves one you already hold. Never write a credential into chat, files or code.");
82562
82571
  }
82563
82572
  if (hostedTools.includes("vault_request")) {
82564
82573
  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.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencrowd",
3
- "version": "0.13.4",
3
+ "version": "0.14.0",
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",