@aexhq/sdk 0.26.5 → 0.28.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.
@@ -1040,6 +1040,7 @@ export function parseRunSubmissionRequest(input, options = {}) {
1040
1040
  "proxyEndpoints",
1041
1041
  "parentRunId",
1042
1042
  "webhook",
1043
+ "limits",
1043
1044
  SECRETS_KEY
1044
1045
  ]);
1045
1046
  for (const key of Object.keys(value)) {
@@ -1075,6 +1076,7 @@ export function parseRunSubmissionRequest(input, options = {}) {
1075
1076
  // derives it from the parent row (a forged depth must not bypass the cap).
1076
1077
  const parentRunId = optionalString(value.parentRunId, "submission.parentRunId");
1077
1078
  const webhook = parseRunWebhook(value.webhook);
1079
+ const limits = parseRunLimits(value.limits);
1078
1080
  const postHook = parsePostHook(value.postHook, "submission.postHook");
1079
1081
  const proxyEndpoints = parseProxyEndpoints(value.proxyEndpoints);
1080
1082
  const secrets = parseInlineSecrets(value.secrets);
@@ -1132,6 +1134,7 @@ export function parseRunSubmissionRequest(input, options = {}) {
1132
1134
  ...(proxyEndpoints ? { proxyEndpoints } : {}),
1133
1135
  ...(parentRunId !== undefined ? { parentRunId } : {}),
1134
1136
  ...(webhook !== undefined ? { webhook } : {}),
1137
+ ...(limits !== undefined ? { limits } : {}),
1135
1138
  secrets
1136
1139
  };
1137
1140
  }
@@ -1170,6 +1173,41 @@ export function parseRunWebhook(input) {
1170
1173
  }
1171
1174
  return { url };
1172
1175
  }
1176
+ /**
1177
+ * Parse the optional per-run `limits` override. Mirrors {@link parseRunWebhook}:
1178
+ * absent ⇒ `undefined`; a non-object or any unknown subfield is rejected so the
1179
+ * strict top-level allow-list extends to the nested object. Each present field
1180
+ * is validated as a positive safe integer via {@link optionalPositiveInt}.
1181
+ *
1182
+ * This is a SHAPE/positivity gate only — it does NOT clamp to the workspace or
1183
+ * platform ceilings (that precedence lives in the resolver, `resolveRunLimits`).
1184
+ * Only the present fields are returned; an all-absent override (e.g. `{}`)
1185
+ * collapses to `undefined` so it carries no signal onto the request.
1186
+ */
1187
+ export function parseRunLimits(input) {
1188
+ if (input === undefined) {
1189
+ return undefined;
1190
+ }
1191
+ const value = requireRecord(input, "limits");
1192
+ const allowed = new Set(["maxConcurrentChildRuns", "maxSubagentDepth"]);
1193
+ for (const key of Object.keys(value)) {
1194
+ if (!allowed.has(key)) {
1195
+ throw new Error(`limits.${key} is not an allowed field; permitted: ${[...allowed].join(", ")}`);
1196
+ }
1197
+ }
1198
+ const maxConcurrentChildRuns = optionalPositiveInt(value.maxConcurrentChildRuns, "limits.maxConcurrentChildRuns");
1199
+ const maxSubagentDepth = optionalPositiveInt(value.maxSubagentDepth, "limits.maxSubagentDepth");
1200
+ // Collapse an all-absent override (e.g. `limits: {}`) to `undefined` so it never
1201
+ // lands an empty object on the request — matches sibling parsers (parseRunWebhook,
1202
+ // parseEnvironment). The resolver supplies platform defaults for absent fields.
1203
+ if (maxConcurrentChildRuns === undefined && maxSubagentDepth === undefined) {
1204
+ return undefined;
1205
+ }
1206
+ return {
1207
+ ...(maxConcurrentChildRuns !== undefined ? { maxConcurrentChildRuns } : {}),
1208
+ ...(maxSubagentDepth !== undefined ? { maxSubagentDepth } : {})
1209
+ };
1210
+ }
1173
1211
  export function parseRunRegion(input) {
1174
1212
  if (input === undefined) {
1175
1213
  return undefined;
@@ -1233,7 +1271,7 @@ export function parseSubmission(input) {
1233
1271
  "securityProfile",
1234
1272
  "metadata",
1235
1273
  "outputs",
1236
- "builtins",
1274
+ "includeBuiltinTools",
1237
1275
  "outputMode",
1238
1276
  "platform"
1239
1277
  ]);
@@ -1246,7 +1284,7 @@ export function parseSubmission(input) {
1246
1284
  const system = optionalString(value.system, "submission.system");
1247
1285
  const prompt = parsePrompt(value.prompt);
1248
1286
  const skills = parseSkills(value.skills);
1249
- const tools = parseTools(value.tools);
1287
+ const { tools, builtinTools } = parseTools(value.tools);
1250
1288
  const agentsMd = parseAgentsMd(value.agentsMd);
1251
1289
  const files = parseFiles(value.files);
1252
1290
  const mcpServers = parseMcpServers(value.mcpServers);
@@ -1255,7 +1293,7 @@ export function parseSubmission(input) {
1255
1293
  const securityProfile = parseRuntimeSecurityProfile(value.securityProfile);
1256
1294
  const metadata = optionalJsonRecord(value.metadata, "submission.metadata");
1257
1295
  const outputs = parseOutputs(value.outputs);
1258
- const builtins = parseBuiltins(value.builtins);
1296
+ const includeBuiltinTools = parseIncludeBuiltinTools(value.includeBuiltinTools);
1259
1297
  const outputMode = parseOutputMode(value.outputMode);
1260
1298
  const platform = parsePlatformConfig(value.platform);
1261
1299
  return {
@@ -1272,7 +1310,8 @@ export function parseSubmission(input) {
1272
1310
  ...(securityProfile ? { securityProfile } : {}),
1273
1311
  ...(metadata ? { metadata } : {}),
1274
1312
  ...(outputs ? { outputs } : {}),
1275
- ...(builtins !== undefined ? { builtins } : {}),
1313
+ ...(includeBuiltinTools !== undefined ? { includeBuiltinTools } : {}),
1314
+ ...(builtinTools.length > 0 ? { builtinTools } : {}),
1276
1315
  ...(outputMode !== undefined ? { outputMode } : {}),
1277
1316
  ...(platform ? { platform } : {})
1278
1317
  };
@@ -1336,108 +1375,105 @@ function parseOutputMode(input) {
1336
1375
  return input;
1337
1376
  }
1338
1377
  /**
1339
- * Managed-runtime builtins the closed set the managed runtime accepts.
1340
- * Closed so an invalid name is a compile error via {@link Builtins}, not a
1341
- * silent runtime no-op.
1378
+ * The CLOSED set of builtin tool NAMES the managed runtime can inject — one per
1379
+ * machine tool the hands implement. This list is the single source of truth for
1380
+ * validating builtin tool references; the platform's `HANDS_TOOLS` (the execute
1381
+ * vocabulary) is pinned EQUAL to it at module load (`platform-runtime-agent`
1382
+ * `assertNamesMatch`), so a rename on either side fails loudly rather than
1383
+ * silently shipping a name the executors do not speak.
1342
1384
  *
1343
- * The first entries are the recommended concrete builtins. The legacy aggregate
1344
- * extension names remain accepted for existing callers, but are not the default.
1385
+ * Order mirrors `HANDS_TOOLS`. A builtin tool reference (a bare string in
1386
+ * `submission.tools`) must be a member of this set.
1345
1387
  */
1346
- export const BUILTINS = [
1347
- "web_search",
1348
- "web_fetch",
1349
- "read",
1350
- "edit",
1351
- "glob",
1352
- "grep",
1353
- "head",
1354
- "tail",
1388
+ export const BUILTIN_TOOL_NAMES = [
1355
1389
  "bash",
1356
- "notebook",
1357
- "developer",
1358
- "computercontroller",
1359
- "memory",
1360
- "autovisualiser",
1361
- "tutorial"
1362
- ];
1363
- /**
1364
- * DX-first managed-runtime defaults. Omitted `builtins` resolves to this list.
1365
- * Notebook support remains opt-in through {@link Builtins.NOTEBOOK}.
1366
- */
1367
- export const DEFAULT_BUILTINS = [
1368
- "web_search",
1369
- "web_fetch",
1370
- "read",
1371
- "edit",
1372
- "glob",
1390
+ "read_file",
1391
+ "write_file",
1392
+ "edit_file",
1373
1393
  "grep",
1394
+ "glob",
1374
1395
  "head",
1375
1396
  "tail",
1376
- "bash"
1397
+ "todo_write",
1398
+ "subagent",
1399
+ "subagent_result",
1400
+ "web_fetch",
1401
+ "web_search",
1402
+ "notebook_edit",
1403
+ "bash_output",
1404
+ "bash_kill",
1405
+ "code_execution",
1406
+ "wait",
1407
+ "git"
1377
1408
  ];
1378
1409
  /**
1379
- * Symbol-style accessors for the closed builtin set, e.g.
1380
- * `Builtins.WEB_SEARCH`.
1410
+ * Typo-safe accessors for the closed builtin tool set: each key maps to the
1411
+ * real tool NAME string. Reference a builtin in `submission.tools` via
1412
+ * `BuiltinTools.notebook_edit` rather than the bare string so a rename is a
1413
+ * compile error, not a runtime 400.
1414
+ *
1415
+ * Keys are the real tool names; a unit test asserts `Object.values(BuiltinTools)`
1416
+ * deep-equals `BUILTIN_TOOL_NAMES` so the two can never drift.
1381
1417
  */
1382
- export const Builtins = {
1383
- /** Managed web search. Included in {@link DEFAULT_BUILTINS}. */
1384
- WEB_SEARCH: "web_search",
1385
- /** Fetch a URL and return readable text. Included in {@link DEFAULT_BUILTINS}. */
1386
- WEB_FETCH: "web_fetch",
1387
- /** Read files. Included in {@link DEFAULT_BUILTINS}. */
1388
- READ: "read",
1389
- /** Create/modify files. Included in {@link DEFAULT_BUILTINS}. */
1390
- EDIT: "edit",
1391
- /** Search paths by glob. Included in {@link DEFAULT_BUILTINS}. */
1392
- GLOB: "glob",
1393
- /** Search file contents. Included in {@link DEFAULT_BUILTINS}. */
1394
- GREP: "grep",
1395
- /** Read the first lines of a file. Included in {@link DEFAULT_BUILTINS}. */
1396
- HEAD: "head",
1397
- /** Read the last lines of a file. Included in {@link DEFAULT_BUILTINS}. */
1398
- TAIL: "tail",
1399
- /** Shell command execution. Included in {@link DEFAULT_BUILTINS}. */
1400
- BASH: "bash",
1401
- /** Jupyter notebook editing. Optional; not in {@link DEFAULT_BUILTINS}. */
1402
- NOTEBOOK: "notebook",
1403
- /** Legacy aggregate: shell/filesystem/navigation/web/notebook tools. */
1404
- DEVELOPER: "developer",
1405
- /** Legacy aggregate alias retained for existing callers. */
1406
- COMPUTER_CONTROLLER: "computercontroller",
1407
- /** Legacy aggregate alias retained for existing callers. */
1408
- MEMORY: "memory",
1409
- /** Legacy aggregate alias retained for existing callers. */
1410
- AUTOVISUALISER: "autovisualiser",
1411
- /** Legacy aggregate alias retained for existing callers. */
1412
- TUTORIAL: "tutorial"
1418
+ export const BuiltinTools = {
1419
+ bash: "bash",
1420
+ read_file: "read_file",
1421
+ write_file: "write_file",
1422
+ edit_file: "edit_file",
1423
+ grep: "grep",
1424
+ glob: "glob",
1425
+ head: "head",
1426
+ tail: "tail",
1427
+ todo_write: "todo_write",
1428
+ subagent: "subagent",
1429
+ subagent_result: "subagent_result",
1430
+ web_fetch: "web_fetch",
1431
+ web_search: "web_search",
1432
+ notebook_edit: "notebook_edit",
1433
+ bash_output: "bash_output",
1434
+ bash_kill: "bash_kill",
1435
+ code_execution: "code_execution",
1436
+ wait: "wait",
1437
+ git: "git"
1413
1438
  };
1414
- const MAX_BUILTINS = 16;
1415
- function parseBuiltins(input) {
1439
+ /**
1440
+ * The default builtin tool set injected when `includeBuiltinTools !== false`:
1441
+ * every builtin tool EXCEPT `notebook_edit` (notebook editing stays opt-in —
1442
+ * add `BuiltinTools.notebook_edit` to `tools` to enable it). Derived by
1443
+ * filtering {@link BUILTIN_TOOL_NAMES} so it can never drift from the closed
1444
+ * set.
1445
+ */
1446
+ export const DEFAULT_BUILTIN_TOOLS = BUILTIN_TOOL_NAMES.filter((name) => name !== "notebook_edit");
1447
+ /**
1448
+ * Resolve the set of builtin tool NAMES a submission injects, deduplicated and
1449
+ * in {@link BUILTIN_TOOL_NAMES} order.
1450
+ *
1451
+ * - `includeBuiltinTools !== false` ⇒ start from {@link DEFAULT_BUILTIN_TOOLS}
1452
+ * (the standard set); `false` ⇒ start from none (pure-MCP / pure-custom).
1453
+ * - union in every builtin-name string the caller listed in `tools` (a
1454
+ * cherry-pick, e.g. `BuiltinTools.notebook_edit` to opt the notebook in).
1455
+ *
1456
+ * Every `toolRefs` string MUST be a member of {@link BUILTIN_TOOL_NAMES}; the
1457
+ * union is validated ⊆ the closed set so an invalid name can never leak through.
1458
+ */
1459
+ export function resolveBuiltinToolNames(includeBuiltinTools, toolRefs) {
1460
+ const enabled = new Set(includeBuiltinTools !== false ? DEFAULT_BUILTIN_TOOLS : []);
1461
+ for (const ref of toolRefs ?? []) {
1462
+ if (!BUILTIN_TOOL_NAMES.includes(ref)) {
1463
+ throw new Error(`${JSON.stringify(ref)} is not a builtin tool; expected one of: ${BUILTIN_TOOL_NAMES.join(", ")}`);
1464
+ }
1465
+ enabled.add(ref);
1466
+ }
1467
+ return BUILTIN_TOOL_NAMES.filter((name) => enabled.has(name));
1468
+ }
1469
+ /** Validate the optional `includeBuiltinTools` flag (default `true`). */
1470
+ function parseIncludeBuiltinTools(input) {
1416
1471
  if (input === undefined || input === null)
1417
1472
  return undefined;
1418
- if (!Array.isArray(input)) {
1419
- throw new Error("submission.builtins must be an array of strings");
1420
- }
1421
- if (input.length > MAX_BUILTINS) {
1422
- throw new Error(`submission.builtins exceeds the max of ${MAX_BUILTINS} entries`);
1423
- }
1424
- const seen = new Set();
1425
- const out = [];
1426
- for (let i = 0; i < input.length; i++) {
1427
- const v = input[i];
1428
- if (typeof v !== "string") {
1429
- throw new Error(`submission.builtins[${i}] must be a string`);
1430
- }
1431
- if (!BUILTINS.includes(v)) {
1432
- throw new Error(`submission.builtins[${i}] (${JSON.stringify(v)}) is not a managed-runtime builtin; ` +
1433
- `expected one of: ${BUILTINS.join(", ")}`);
1434
- }
1435
- if (seen.has(v))
1436
- continue; // dedupe silently
1437
- seen.add(v);
1438
- out.push(v);
1473
+ if (typeof input !== "boolean") {
1474
+ throw new Error("submission.includeBuiltinTools must be a boolean");
1439
1475
  }
1440
- return out;
1476
+ return input;
1441
1477
  }
1442
1478
  /**
1443
1479
  * Maximum number of output capture entries accepted per list.
@@ -1665,17 +1701,35 @@ function parseSkills(input) {
1665
1701
  return ref;
1666
1702
  });
1667
1703
  }
1704
+ /**
1705
+ * Parse the `submission.tools` union: each entry is either a BARE STRING (a
1706
+ * builtin tool reference, validated against {@link BUILTIN_TOOL_NAMES}) or a
1707
+ * custom tool bundle OBJECT ({@link ToolRef}). Returns the two groups split:
1708
+ * `tools` (custom bundles, the existing downstream shape) and `builtinTools`
1709
+ * (the deduped builtin-name references, in {@link BUILTIN_TOOL_NAMES} order).
1710
+ */
1668
1711
  function parseTools(input) {
1669
1712
  if (input === undefined) {
1670
- return [];
1713
+ return { tools: [], builtinTools: [] };
1671
1714
  }
1672
1715
  if (!Array.isArray(input)) {
1673
- throw new Error("submission.tools must be an array of ToolRef objects");
1716
+ throw new Error("submission.tools must be an array of builtin tool names or ToolRef objects");
1674
1717
  }
1675
1718
  const seenNames = new Set();
1676
1719
  const seenAssetIds = new Set();
1677
- return input.map((item, index) => {
1720
+ const seenBuiltins = new Set();
1721
+ const tools = [];
1722
+ input.forEach((item, index) => {
1678
1723
  const path = `submission.tools[${index}]`;
1724
+ // A bare string is a builtin tool reference (e.g. BuiltinTools.notebook_edit).
1725
+ if (typeof item === "string") {
1726
+ if (!BUILTIN_TOOL_NAMES.includes(item)) {
1727
+ throw new Error(`${path} (${JSON.stringify(item)}) is not a builtin tool name; ` +
1728
+ `expected one of: ${BUILTIN_TOOL_NAMES.join(", ")}`);
1729
+ }
1730
+ seenBuiltins.add(item);
1731
+ return;
1732
+ }
1679
1733
  const raw = requireRecord(item, path);
1680
1734
  for (const key of Object.keys(raw)) {
1681
1735
  if (key !== "kind" &&
@@ -1717,15 +1771,17 @@ function parseTools(input) {
1717
1771
  throw new Error(`${path}.input_schema.type must be "object"`);
1718
1772
  }
1719
1773
  const entry = normaliseSkillBundlePath(requireString(raw.entry, `${path}.entry`));
1720
- return {
1774
+ tools.push({
1721
1775
  kind: "asset",
1722
1776
  assetId: fields.assetId,
1723
1777
  name: fields.name,
1724
1778
  description,
1725
1779
  input_schema: inputSchema,
1726
1780
  entry
1727
- };
1781
+ });
1728
1782
  });
1783
+ const builtinTools = BUILTIN_TOOL_NAMES.filter((name) => seenBuiltins.has(name));
1784
+ return { tools, builtinTools };
1729
1785
  }
1730
1786
  function parseAgentsMd(input) {
1731
1787
  if (input === undefined)
package/dist/cli.mjs CHANGED
@@ -798,6 +798,28 @@ function parseRunRegion(input) {
798
798
  }
799
799
  return input;
800
800
  }
801
+ var BUILTIN_TOOL_NAMES = [
802
+ "bash",
803
+ "read_file",
804
+ "write_file",
805
+ "edit_file",
806
+ "grep",
807
+ "glob",
808
+ "head",
809
+ "tail",
810
+ "todo_write",
811
+ "subagent",
812
+ "subagent_result",
813
+ "web_fetch",
814
+ "web_search",
815
+ "notebook_edit",
816
+ "bash_output",
817
+ "bash_kill",
818
+ "code_execution",
819
+ "wait",
820
+ "git"
821
+ ];
822
+ var DEFAULT_BUILTIN_TOOLS = BUILTIN_TOOL_NAMES.filter((name) => name !== "notebook_edit");
801
823
  var MAX_OUTPUT_CAPTURE_TIMEOUT_MS = 6 * 60 * 60 * 1e3;
802
824
 
803
825
  // ../contracts/dist/connection-ticket.js
@@ -1376,6 +1398,8 @@ function extractErrorMessage(body) {
1376
1398
  // ../contracts/dist/operations.js
1377
1399
  var operations_exports = {};
1378
1400
  __export(operations_exports, {
1401
+ READ_OUTPUT_TEXT_DEFAULT_BYTES: () => READ_OUTPUT_TEXT_DEFAULT_BYTES,
1402
+ READ_OUTPUT_TEXT_MAX_BYTES: () => READ_OUTPUT_TEXT_MAX_BYTES,
1379
1403
  cancelRun: () => cancelRun,
1380
1404
  classifyOutput: () => classifyOutput,
1381
1405
  createAgentsMd: () => createAgentsMd,
@@ -1414,10 +1438,12 @@ __export(operations_exports, {
1414
1438
  listFiles: () => listFiles,
1415
1439
  listOutputs: () => listOutputs,
1416
1440
  listRunEvents: () => listRunEvents,
1441
+ listRuns: () => listRuns,
1417
1442
  listSecrets: () => listSecrets,
1418
1443
  listSkills: () => listSkills,
1419
1444
  normalizeOutputLinkExpiresIn: () => normalizeOutputLinkExpiresIn,
1420
1445
  outputLink: () => outputLink,
1446
+ readOutputText: () => readOutputText,
1421
1447
  redeliverRunWebhook: () => redeliverRunWebhook,
1422
1448
  resolveOutputFileSelector: () => resolveOutputFileSelector,
1423
1449
  rotateSecret: () => rotateSecret,
@@ -2151,6 +2177,18 @@ async function getRun(http, runId) {
2151
2177
  async function getRunUnit(http, runId) {
2152
2178
  return http.request(`/api/runs/${encodeURIComponent(runId)}`);
2153
2179
  }
2180
+ async function listRuns(http, query) {
2181
+ const params = {};
2182
+ if (query?.status !== void 0)
2183
+ params.status = query.status;
2184
+ if (query?.since !== void 0)
2185
+ params.since = query.since;
2186
+ if (query?.limit !== void 0)
2187
+ params.limit = String(query.limit);
2188
+ if (query?.cursor !== void 0)
2189
+ params.cursor = query.cursor;
2190
+ return http.request("/api/runs", {}, params);
2191
+ }
2154
2192
  var LIST_EVENTS_PAGE_BUDGET = 1e3;
2155
2193
  async function listRunEvents(http, runId) {
2156
2194
  const path = `/api/runs/${encodeURIComponent(runId)}/events`;
@@ -2249,6 +2287,74 @@ async function downloadOutput(http, runId, selector) {
2249
2287
  const { response } = await http.download(`/api/runs/${encodeURIComponent(runId)}/outputs/${encodeURIComponent(output.id)}/download`);
2250
2288
  return { output, bytes: new Uint8Array(await response.arrayBuffer()) };
2251
2289
  }
2290
+ var READ_OUTPUT_TEXT_MAX_BYTES = 1e7;
2291
+ var READ_OUTPUT_TEXT_DEFAULT_BYTES = 5e4;
2292
+ async function readOutputText(http, runId, selector, options) {
2293
+ const maxBytes = Math.max(1, Math.min(options?.maxBytes ?? READ_OUTPUT_TEXT_DEFAULT_BYTES, READ_OUTPUT_TEXT_MAX_BYTES));
2294
+ const output = isPathSelector(selector) ? resolveOutputFileSelector(await listOutputs(http, runId), selector, runId) : resolveOutputFileSelector([], selector, runId);
2295
+ const { response } = await http.download(`/api/runs/${encodeURIComponent(runId)}/outputs/${encodeURIComponent(output.id)}/download`);
2296
+ const capped = await readCappedText(response, maxBytes);
2297
+ const text = options?.grep === void 0 ? capped.text : grepLines(capped.text, options.grep);
2298
+ return { output, text, truncated: capped.truncated, totalBytes: capped.totalBytes };
2299
+ }
2300
+ async function readCappedText(response, maxBytes) {
2301
+ const declaredRaw = response.headers.get("content-length");
2302
+ const declared = declaredRaw !== null && /^\d+$/.test(declaredRaw) ? Number(declaredRaw) : void 0;
2303
+ const decoder = new TextDecoder("utf-8");
2304
+ const body = response.body;
2305
+ if (!body) {
2306
+ const buf = new Uint8Array(await response.arrayBuffer());
2307
+ const total = declared ?? buf.byteLength;
2308
+ return {
2309
+ text: decoder.decode(buf.subarray(0, maxBytes)),
2310
+ truncated: buf.byteLength > maxBytes,
2311
+ totalBytes: total
2312
+ };
2313
+ }
2314
+ const reader = body.getReader();
2315
+ const chunks = [];
2316
+ let read = 0;
2317
+ let sawMore = false;
2318
+ try {
2319
+ while (read < maxBytes) {
2320
+ const { done, value } = await reader.read();
2321
+ if (done)
2322
+ break;
2323
+ if (value && value.byteLength > 0) {
2324
+ read += value.byteLength;
2325
+ chunks.push(value);
2326
+ }
2327
+ }
2328
+ if (read >= maxBytes) {
2329
+ const next = await reader.read();
2330
+ if (!next.done && next.value && next.value.byteLength > 0)
2331
+ sawMore = true;
2332
+ }
2333
+ } finally {
2334
+ await reader.cancel().catch(() => {
2335
+ });
2336
+ }
2337
+ const merged = concatBytes(chunks).subarray(0, maxBytes);
2338
+ const truncated = declared !== void 0 ? declared > maxBytes : sawMore;
2339
+ const totalBytes = declared ?? read;
2340
+ return { text: decoder.decode(merged), truncated, totalBytes };
2341
+ }
2342
+ function concatBytes(chunks) {
2343
+ if (chunks.length === 1)
2344
+ return chunks[0];
2345
+ const total = chunks.reduce((n, c) => n + c.byteLength, 0);
2346
+ const out = new Uint8Array(total);
2347
+ let offset = 0;
2348
+ for (const c of chunks) {
2349
+ out.set(c, offset);
2350
+ offset += c.byteLength;
2351
+ }
2352
+ return out;
2353
+ }
2354
+ function grepLines(text, pattern) {
2355
+ const test = typeof pattern === "string" ? (line) => line.toLowerCase().includes(pattern.toLowerCase()) : (line) => pattern.test(line);
2356
+ return text.split("\n").filter((line) => test(line)).join("\n");
2357
+ }
2252
2358
  async function cancelRun(http, runId) {
2253
2359
  await http.request(`/api/runs/${encodeURIComponent(runId)}/cancel`, { method: "POST" });
2254
2360
  }
@@ -1 +1 @@
1
- 41301b02d51ef616bfff7b0d282d58e6ccc0ac5792c693f094bcae3c05c105db cli.mjs
1
+ 0386d2625bfa4f8aea426cffc3bf21546c48b33b7134eb7cd4bbfefdc2d69d96 cli.mjs
package/dist/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HttpClient, SecretString, type AexEvent, type AgentsMdRecord, type CredentialMode, type DebugSink, type FetchLike, type FileRecord, type Output, type OutputFileType, type OutputLink, type OutputLinkOptions, type OutputQuery, type OutputMode, type PlatformEnvironmentInput, type PlatformSubmission, type PlatformInlineSecrets, type PlatformProxyEndpoint, type PlatformProxyEndpointAuth, type PlatformPostHookInput, type Run, type RunModel, type RunEvent, type RunWebhookDelivery, type RunProvider, type RunRegion, type SecretRecord, type SecretReveal, type RunUnit, type Builtin, type RuntimeSize, type RuntimeKind, type Skill as SkillRecord, type WhoAmI } from "./_contracts/index.js";
1
+ import { HttpClient, SecretString, type AexEvent, type AgentsMdRecord, type CredentialMode, type DebugSink, type FetchLike, type FileRecord, type Output, type OutputFileType, type OutputLink, type OutputLinkOptions, type OutputQuery, type OutputText, type OutputMode, type ReadOutputTextOptions, type RunListPage, type RunListQuery, type PlatformEnvironmentInput, type PlatformSubmission, type PlatformInlineSecrets, type PlatformProxyEndpoint, type PlatformProxyEndpointAuth, type PlatformPostHookInput, type Run, type RunModel, type RunEvent, type RunLimits, type RunWebhookDelivery, type RunProvider, type RunRegion, type SecretRecord, type SecretReveal, type RunUnit, type BuiltinToolName, type RuntimeSize, type RuntimeKind, type Skill as SkillRecord, type WhoAmI } from "./_contracts/index.js";
2
2
  import { AgentsMd } from "./agents-md.js";
3
3
  import { type UploadedAsset } from "./asset-upload.js";
4
4
  import { File } from "./file.js";
@@ -91,7 +91,18 @@ export interface SubmitOptions {
91
91
  readonly system?: string;
92
92
  readonly prompt: string | readonly string[];
93
93
  readonly skills?: readonly Skill[];
94
- readonly tools?: readonly Tool[];
94
+ /**
95
+ * Tools available to the agent. Each entry is either a custom {@link Tool}
96
+ * bundle, or a BUILTIN tool reference — a bare name string, preferably
97
+ * `BuiltinTools.<name>` (e.g. `BuiltinTools.notebook_edit`) so a typo is a
98
+ * compile error. Builtin references compose with {@link includeBuiltinTools}:
99
+ * use them to cherry-pick a tool the default set omits (notebook editing), or
100
+ * to pick a narrow subset alongside `includeBuiltinTools: false`.
101
+ *
102
+ * Order in the agent's tool list: resolved builtin tools, then custom tools,
103
+ * then MCP tools.
104
+ */
105
+ readonly tools?: readonly (Tool | BuiltinToolName)[];
95
106
  readonly agentsMd?: readonly AgentsMd[];
96
107
  readonly files?: readonly File[];
97
108
  readonly mcpServers?: readonly McpServer[];
@@ -146,22 +157,14 @@ export interface SubmitOptions {
146
157
  readonly maxFiles?: number;
147
158
  };
148
159
  /**
149
- * Override the managed runtime builtins enabled inside the runner.
150
- * Each entry is one of the closed {@link Builtin} set prefer the
151
- * {@link Builtins} symbol const so a typo is a compile error.
160
+ * Whether to inject the standard builtin tool set
161
+ * ({@link DEFAULT_BUILTIN_TOOLS} — every builtin except `notebook_edit`).
152
162
  *
153
- * - Omitted (default): the runner enables `DEFAULT_BUILTINS`
154
- * (`web_search`, `web_fetch`, `read`, `edit`, `glob`, `grep`, `head`,
155
- * `tail`).
156
- * - Empty array: the agent runs with zero builtins — useful for pure-MCP
157
- * setups where every tool comes from a submitted `mcpServers` entry.
158
- * - Custom list: narrows or extends the surface, e.g.
159
- * `[Builtins.WEB_SEARCH, Builtins.NOTEBOOK]`.
160
- *
161
- * Validation: each entry must be a member of {@link Builtins}, max 16
162
- * entries, deduplicated server-side.
163
+ * - Omitted / `true` (default): inject the standard builtins.
164
+ * - `false`: inject NO builtins — useful for a pure-MCP / pure-custom run.
165
+ * Cherry-pick a narrow subset back by listing builtin names in `tools`.
163
166
  */
164
- readonly builtins?: readonly Builtin[];
167
+ readonly includeBuiltinTools?: boolean;
165
168
  /**
166
169
  * Assistant-output granularity. `"buffered"` (default) delivers one event per
167
170
  * assistant message; `"stream"` delivers per-token text deltas for live
@@ -189,6 +192,15 @@ export interface SubmitOptions {
189
192
  readonly webhook?: {
190
193
  readonly url: string;
191
194
  };
195
+ /**
196
+ * Optional per-run override of the lineage limits — the max number of
197
+ * concurrent child runs and the max subagent depth. A sibling of
198
+ * {@link parentRunId}: these are dials the client *requests*; the server
199
+ * resolves each against the per-workspace ceiling and the hard platform
200
+ * ceiling, and an absent field falls back to the platform default. Only
201
+ * shape + positivity are validated client-side.
202
+ */
203
+ readonly limits?: RunLimits;
192
204
  readonly signal?: AbortSignal;
193
205
  }
194
206
  /** @deprecated Renamed to {@link SubmitOptions}. Kept for one release. */
@@ -480,6 +492,17 @@ export declare class AgentExecutor {
480
492
  getRun(runId: string): Promise<Run>;
481
493
  /** Short alias for `getRun`. */
482
494
  get(runId: string): Promise<Run>;
495
+ /**
496
+ * List the runs in this workspace, most-recent first, one page at a time.
497
+ * The workspace is derived server-side from the API token, so this only ever
498
+ * enumerates your own runs. Pass `query.cursor` (from a prior page's
499
+ * `nextCursor`) to page; omit it for the first page. Returns public-safe
500
+ * {@link RunSummary} rows — the full submission stays behind `getRunUnit`.
501
+ *
502
+ * This is the workspace-wide discovery entry point: combine it with
503
+ * `listOutputs` / `readOutputText` to reach any run's deliverables.
504
+ */
505
+ listRuns(query?: RunListQuery): Promise<RunListPage>;
483
506
  /**
484
507
  * Fetch the self-contained `RunUnit`: parsed submission inputs,
485
508
  * attempts, indexed events (inline + cursor for the tail), raw
@@ -530,6 +553,15 @@ export declare class AgentExecutor {
530
553
  outputLink(runId: string, selectorOrQuery: OutputLinkSelector, options?: OutputLinkOptions): Promise<OutputLink>;
531
554
  createOutputLink(runId: string, selectorOrQuery: OutputLinkSelector, options?: OutputLinkOptions): Promise<OutputLink>;
532
555
  fetchOutput(runId: string, selectorOrQuery: OutputLinkSelector, options?: OutputLinkOptions): Promise<Response>;
556
+ /**
557
+ * Read ONE output file as byte-capped, decoded UTF-8 text. Streams the file and
558
+ * STOPS at `options.maxBytes` (default 50 KB, ceiling 10 MB), so a huge
559
+ * deliverable never fully buffers — ideal for handing a run's output to an LLM
560
+ * tool. Check `result.truncated` before treating the text as complete; pass
561
+ * `options.grep` to keep only matching lines. Select by `{ path }` or `{ id }`,
562
+ * same as `downloadOutput`.
563
+ */
564
+ readOutputText(runId: string, selector: OutputFileSelector, options?: ReadOutputTextOptions): Promise<OutputText>;
533
565
  eventArchiveLink(runId: string, options?: OutputLinkOptions): Promise<OutputLink>;
534
566
  /**
535
567
  * Download captured deliverables. Omit `selector` to receive the full