@camelai/camelrun 0.11.2 → 0.13.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/dist/api.js CHANGED
@@ -1,8 +1,13 @@
1
- /** A refused call: the runtime's `error` message, with the HTTP status and its `code` when it gave one. */
1
+ /**
2
+ * A refused call: the runtime's `error` message, with the HTTP status and its `code` when it gave one. The message
3
+ * suits every surface; `cliHint` is what to do about it with the CLI, which only the CLI shows (an MCP client's model
4
+ * would try to run it).
5
+ */
2
6
  export class ApiError extends Error {
3
7
  status;
4
8
  code;
5
- constructor(status, message, code) { super(message); this.status = status; this.code = code; }
9
+ cliHint;
10
+ constructor(status, message, code, cliHint) { super(message); this.status = status; this.code = code; this.cliHint = cliHint; }
6
11
  }
7
12
  /** SHA-256 as hex, with Web Crypto: the same in Node and browsers. */
8
13
  async function sha256(text) {
@@ -39,7 +44,7 @@ export class Api {
39
44
  }
40
45
  if (!response.ok) {
41
46
  const message = json?.error ?? json?.message ?? (text.slice(0, 300) || response.statusText);
42
- throw new ApiError(response.status, response.status === 401 ? `${message} (check your API key: camelrun login)` : message, json?.code);
47
+ throw new ApiError(response.status, message, json?.code, response.status === 401 ? "check your API key: camelrun login" : undefined);
43
48
  }
44
49
  return json;
45
50
  }
@@ -66,7 +71,7 @@ export class Api {
66
71
  const agents = await this.get("/v1/agents");
67
72
  const found = agents.find(agent => agent.key === keyOrId);
68
73
  if (!found)
69
- throw new ApiError(404, `No agent with key ${JSON.stringify(keyOrId)} (camelrun agents list shows them)`);
74
+ throw new ApiError(404, `No agent with key ${JSON.stringify(keyOrId)} in this account`, undefined, "camelrun agents list shows them");
70
75
  return found.id;
71
76
  }
72
77
  }
package/dist/cli.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { existsSync, writeFileSync } from "node:fs";
2
2
  import { createInterface } from "node:readline/promises";
3
3
  import { parseArgs } from "node:util";
4
- import { Api, enc } from "./api.js";
4
+ import { Api, ApiError, enc } from "./api.js";
5
5
  import { DEFAULT_URL, forget, resolve, save } from "./config.js";
6
6
  import { DEFAULT_FILES, template } from "./manifest.js";
7
7
  import { findManifest, loadManifests } from "./manifest-files.js";
@@ -51,7 +51,7 @@ MCP
51
51
 
52
52
  Options
53
53
  --json Print JSON (the default when stdout is not a terminal)
54
- --api-key <key>, --url <url> Instead of CAMELAI_API_KEY / CAMELAI_URL / the saved login
54
+ --api-key <key>, --url <url> Instead of CAMELAI_API_KEY / CAMELAI_BASE_URL / the saved login
55
55
 
56
56
  Docs: https://run.camelai.com/llms.txt`;
57
57
  const OPTIONS = {
@@ -189,7 +189,8 @@ export async function main(argv, io = { out: text => process.stdout.write(text +
189
189
  }
190
190
  }
191
191
  catch (error) {
192
- io.err(json && !(error instanceof UsageError) ? JSON.stringify({ error: error.message, ...("status" in error ? { status: error.status, code: error.code } : {}) }) : `Error: ${error.message}`);
192
+ const message = error.message + (error instanceof ApiError && error.cliHint ? ` (${error.cliHint})` : "");
193
+ io.err(json && !(error instanceof UsageError) ? JSON.stringify({ error: message, ...("status" in error ? { status: error.status, code: error.code } : {}) }) : `Error: ${message}`);
193
194
  return 1;
194
195
  }
195
196
  }
@@ -202,7 +203,7 @@ async function login(flags, io, print) {
202
203
  apiKey = (await prompt.question("API key (create one at https://run.camelai.com/console/tokens): ")).trim();
203
204
  prompt.close();
204
205
  }
205
- const url = flags.url || io.env.CAMELAI_URL || DEFAULT_URL;
206
+ const url = flags.url || io.env.CAMELAI_BASE_URL || io.env.CAMELAI_URL || DEFAULT_URL;
206
207
  const me = await new Api({ apiKey, url }).me();
207
208
  const path = save({ apiKey, url }, io.env);
208
209
  print({ tenant: me.tenant, url, saved: path }, () => `Logged in as ${me.login ?? me.tenant} on ${url} (key saved to ${path})`);
package/dist/config.js CHANGED
@@ -32,11 +32,11 @@ export function forget(env = process.env) {
32
32
  rmSync(path, { force: true });
33
33
  return had ? path : undefined;
34
34
  }
35
- /** Flags first, then CAMELAI_API_KEY / CAMELAI_URL, then what `camelrun login` saved. */
35
+ /** Flags first, then CAMELAI_API_KEY / CAMELAI_BASE_URL (as the SDKs read it; CAMELAI_URL too), then what `camelrun login` saved. */
36
36
  export function resolve(flags, env = process.env) {
37
37
  const saved = readSaved(env);
38
38
  const apiKey = flags.apiKey || env.CAMELAI_API_KEY || saved.apiKey;
39
39
  if (!apiKey)
40
40
  throw new Error("No API key: run `camelrun login`, or set CAMELAI_API_KEY. Create one at https://run.camelai.com/console/tokens. Coding agents: read https://run.camelai.com/SKILL.md");
41
- return { apiKey, url: flags.url || env.CAMELAI_URL || saved.url || DEFAULT_URL };
41
+ return { apiKey, url: flags.url || env.CAMELAI_BASE_URL || env.CAMELAI_URL || saved.url || DEFAULT_URL };
42
42
  }
package/dist/ops.js CHANGED
@@ -51,7 +51,8 @@ export function summarize(agent, record) {
51
51
  const result = outcome.result ?? {};
52
52
  const failure = outcome.error ? { code: outcome.uncertain ? "uncertain" : "runtime_error", message: outcome.error }
53
53
  : result.error ? { code: result.code ?? "model_error", message: result.error }
54
- : result.stopped === "spend_limit" ? { code: "spend_limit", message: "The agent reached its spend limit; raise it to go on" } : undefined;
54
+ : result.stopped === "spend_limit" ? { code: "spend_limit", message: "The agent reached its spend limit; raise it to go on" }
55
+ : result.stopped === "turn_limit" ? { code: "turn_limit", message: "The run reached its limit of model responses or time; send another message to continue" } : undefined;
55
56
  const status = failure ? "failed" : result.stopped === "input_required" ? "input_required" : "completed";
56
57
  return {
57
58
  ...base, status,
package/dist/tools.js CHANGED
@@ -68,7 +68,10 @@ export function tools(api, options = {}) {
68
68
  const client = api();
69
69
  return client.call("DELETE", `/v1/definitions/${await client.definitionId(definition)}`);
70
70
  }, destructive);
71
- tool("list_agents", "List agents", "The account's agents: key, id, model, and whether each is running. Changes nothing.", {}, () => api().get("/v1/agents"), read);
71
+ tool("list_agents", "List agents", "The account's agents: key, id, name and model. `loaded` is whether the agent is in a runtime's memory now, idle or not; it says nothing about whether a run is going (run_agent and get_run do). `toolsConnected` is whether an application serving its attached tools is connected. Changes nothing.", {}, async () => {
72
+ const list = await api().get("/v1/agents");
73
+ return list.map(({ id, key, name, model, running, connected, expiresAt }) => ({ key, id, name, model, loaded: running, toolsConnected: connected, expiresAt }));
74
+ }, read);
72
75
  tool("get_agent", "Get agent", "An agent's configuration, the definition revision it has, and every source of its tools with what each offers. Changes nothing.", { agent }, async ({ agent }) => {
73
76
  const client = api();
74
77
  return client.get(`/v1/agents/${enc(await client.agentId(agent))}`);
@@ -129,7 +132,7 @@ export function tools(api, options = {}) {
129
132
  }, async ({ agent, ...schedule }) => {
130
133
  const client = api();
131
134
  return client.call("POST", `/v1/agents/${enc(await client.agentId(agent))}/schedules`, schedule);
132
- }, add);
135
+ }, { ...add, openWorldHint: true });
133
136
  tool("delete_schedule", "Delete schedule", "Cancel a scheduled wake-up; this cannot be undone.", { agent, scheduleId: z.string() }, async ({ agent, scheduleId }) => {
134
137
  const client = api();
135
138
  return client.call("DELETE", `/v1/agents/${enc(await client.agentId(agent))}/schedules/${enc(scheduleId)}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camelai/camelrun",
3
- "version": "0.11.2",
3
+ "version": "0.13.0",
4
4
  "description": "camelRun CLI: deploy and manage agents on camelRun from a terminal, or from a coding agent over MCP (camelrun mcp).",
5
5
  "type": "module",
6
6
  "license": "MIT",