@tonbo/cli 0.2.0 → 0.3.1

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/dist/bin/tonbo.js +211 -92
  2. package/package.json +7 -7
package/dist/bin/tonbo.js CHANGED
@@ -143,12 +143,12 @@ var TonboApi = class {
143
143
  });
144
144
  if (prepared.status === "upload") {
145
145
  if (!prepared.upload_url) throw new Error("Tonbo did not return a source upload URL.");
146
+ if (!prepared.upload_headers || prepared.upload_headers["if-none-match"] !== "*")
147
+ throw new Error("Missing immutable source upload headers.");
146
148
  const uploaded = await this.fetcher(prepared.upload_url, {
149
+ redirect: "error",
147
150
  method: "PUT",
148
- headers: {
149
- "content-type": prepared.content_type ?? "application/vnd.tonbo.source+tar",
150
- "x-upsert": "false"
151
- },
151
+ headers: prepared.upload_headers,
152
152
  body: new Blob([new Uint8Array(bundle.bytes)])
153
153
  });
154
154
  let uploadError = null;
@@ -323,7 +323,7 @@ var TonboApi = class {
323
323
  import { lstat, readFile } from "node:fs/promises";
324
324
  import path from "node:path";
325
325
 
326
- // ../../packages/agent-source-inspector/src/index.ts
326
+ // ../../packages/agent-source-inspector/dist/src/index.js
327
327
  var AGENTS_INSTRUCTIONS_PATH = "AGENTS.md";
328
328
  var PI_SETTINGS_PATH = ".pi/settings.json";
329
329
  var MAX_HARNESS_CONFIG_BYTES = 256 * 1024;
@@ -339,6 +339,8 @@ var supportedExecutionTargets = [
339
339
  { driver: "command", harness: "pi" }
340
340
  ];
341
341
  var AgentSourceInspectionError = class extends Error {
342
+ code;
343
+ path;
342
344
  constructor(code, path6, message, options) {
343
345
  super(message, options);
344
346
  this.code = code;
@@ -351,28 +353,16 @@ function parsePiPackageCount(contents) {
351
353
  try {
352
354
  settings = JSON.parse(contents);
353
355
  } catch (error) {
354
- throw new AgentSourceInspectionError(
355
- "invalid_pi_settings",
356
- PI_SETTINGS_PATH,
357
- `${PI_SETTINGS_PATH} must contain valid JSON.`,
358
- { cause: error }
359
- );
356
+ throw new AgentSourceInspectionError("invalid_pi_settings", PI_SETTINGS_PATH, `${PI_SETTINGS_PATH} must contain valid JSON.`, { cause: error });
360
357
  }
361
358
  if (!settings || typeof settings !== "object" || Array.isArray(settings)) {
362
- throw new AgentSourceInspectionError(
363
- "invalid_pi_settings",
364
- PI_SETTINGS_PATH,
365
- `${PI_SETTINGS_PATH} must contain a JSON object.`
366
- );
359
+ throw new AgentSourceInspectionError("invalid_pi_settings", PI_SETTINGS_PATH, `${PI_SETTINGS_PATH} must contain a JSON object.`);
367
360
  }
368
- if (!("packages" in settings)) return 0;
361
+ if (!("packages" in settings))
362
+ return 0;
369
363
  const packages = settings.packages;
370
364
  if (!Array.isArray(packages)) {
371
- throw new AgentSourceInspectionError(
372
- "invalid_pi_settings",
373
- PI_SETTINGS_PATH,
374
- `${PI_SETTINGS_PATH} packages must be an array.`
375
- );
365
+ throw new AgentSourceInspectionError("invalid_pi_settings", PI_SETTINGS_PATH, `${PI_SETTINGS_PATH} packages must be an array.`);
376
366
  }
377
367
  return packages.length;
378
368
  }
@@ -773,6 +763,42 @@ async function openBrowser(url) {
773
763
  return void await exec("xdg-open", [url]);
774
764
  }
775
765
 
766
+ // ../../packages/agent-source-bundler/dist/src/generated/contracts.js
767
+ var inferenceDefault = { "model": "claude-sonnet-5" };
768
+ var sourceBundleContract = { "version": 1, "format": "tar-v1", "key_prefix": "agent-source-bundles", "content_type": "application/vnd.tonbo.source+tar", "max_bytes": 67108864 };
769
+ var piSessionContract = { "version": 1, "adapter": "pi-jsonl-v3", "format_version": 3, "durable_completion_timeout_seconds": 30, "session_directory": "/sessions", "path_template": "/sessions/{session_id}.jsonl", "preflight_command": ["/usr/local/bin/artifacts", "runtime", "session-preflight"] };
770
+
771
+ // ../../packages/agent-source-bundler/dist/src/inference-default.js
772
+ var DEFAULT_INFERENCE_MODEL = inferenceDefault.model;
773
+
774
+ // ../../packages/agent-source-bundler/dist/src/deployment-origin.js
775
+ function deploymentOriginLabel(actor) {
776
+ return actor === "onboarding" ? "Setup guide" : "tonbo deploy";
777
+ }
778
+ function githubRepositoryUrl(remote) {
779
+ if (typeof remote !== "string" || !remote || /\s/.test(remote) || [...remote].some((character) => character.charCodeAt(0) < 32))
780
+ return null;
781
+ let path6;
782
+ const ssh = /^git@github\.com:([^?#]+)$/.exec(remote);
783
+ if (ssh)
784
+ path6 = ssh[1];
785
+ else {
786
+ try {
787
+ const url = new URL(remote);
788
+ if (url.hostname !== "github.com" || url.port || !["https:", "ssh:"].includes(url.protocol))
789
+ return null;
790
+ path6 = url.pathname.slice(1);
791
+ } catch {
792
+ return null;
793
+ }
794
+ }
795
+ path6 = path6.replace(/\/$/, "").replace(/\.git$/, "");
796
+ const parts = path6.split("/");
797
+ if (parts.length !== 2 || !/^[a-z\d](?:[a-z\d-]{0,38})$/i.test(parts[0]) || !/^[a-z\d._-]{1,100}$/i.test(parts[1]) || [".", ".."].includes(parts[1]))
798
+ return null;
799
+ return `https://github.com/${parts[0]}/${parts[1]}`;
800
+ }
801
+
776
802
  // src/commands.ts
777
803
  import path4 from "node:path";
778
804
 
@@ -1047,32 +1073,12 @@ var deploymentSchema = {
1047
1073
  }
1048
1074
  }
1049
1075
  };
1050
- var sourceBundleContract = {
1051
- "version": 1,
1052
- "format": "tar-v1",
1053
- "bucket": "agent-source-bundles",
1054
- "content_type": "application/vnd.tonbo.source+tar",
1055
- "max_bytes": 67108864
1056
- };
1057
- var piSessionContract = {
1058
- "version": 1,
1059
- "adapter": "pi-jsonl-v3",
1060
- "format_version": 3,
1061
- "durable_completion_timeout_seconds": 30,
1062
- "session_directory": "/sessions",
1063
- "path_template": "/sessions/{session_id}.jsonl",
1064
- "preflight_command": [
1065
- "/usr/local/bin/artifacts",
1066
- "runtime",
1067
- "session-preflight"
1068
- ]
1069
- };
1070
1076
  var agentNameContract = {
1071
1077
  "$schema": "https://json-schema.org/draft/2020-12/schema",
1072
1078
  "$id": "https://contracts.tonbo.dev/agents/agent-name-v1.json",
1073
1079
  "x-tonbo-version": 1,
1074
1080
  "x-tonbo-public-hostname-apex": "tonbo.sh",
1075
- "x-tonbo-public-hostname-template": "<agent>-<organization>.tonbo.sh",
1081
+ "x-tonbo-public-hostname-template": "<agent>-<organization>-<word>-<word>.tonbo.sh",
1076
1082
  "$defs": {
1077
1083
  "name": {
1078
1084
  "type": "string",
@@ -1111,6 +1117,116 @@ var agentNameContract = {
1111
1117
  "www.tonbo.sh"
1112
1118
  ]
1113
1119
  }
1120
+ },
1121
+ "hostnameWord": {
1122
+ "type": "string",
1123
+ "enum": [
1124
+ "arch",
1125
+ "bark",
1126
+ "beam",
1127
+ "bell",
1128
+ "bird",
1129
+ "blue",
1130
+ "boat",
1131
+ "bold",
1132
+ "book",
1133
+ "calm",
1134
+ "cave",
1135
+ "clay",
1136
+ "coal",
1137
+ "cool",
1138
+ "cove",
1139
+ "dawn",
1140
+ "deer",
1141
+ "dove",
1142
+ "dune",
1143
+ "dusk",
1144
+ "echo",
1145
+ "fern",
1146
+ "fire",
1147
+ "flax",
1148
+ "flow",
1149
+ "foam",
1150
+ "fawn",
1151
+ "frog",
1152
+ "gate",
1153
+ "glow",
1154
+ "gold",
1155
+ "gray",
1156
+ "gulf",
1157
+ "hail",
1158
+ "halo",
1159
+ "hare",
1160
+ "hawk",
1161
+ "hill",
1162
+ "iris",
1163
+ "jade",
1164
+ "kite",
1165
+ "lake",
1166
+ "lamb",
1167
+ "leaf",
1168
+ "lime",
1169
+ "lion",
1170
+ "lobe",
1171
+ "loft",
1172
+ "loom",
1173
+ "luma",
1174
+ "lynx",
1175
+ "mint",
1176
+ "mist",
1177
+ "moon",
1178
+ "moss",
1179
+ "navy",
1180
+ "nest",
1181
+ "nova",
1182
+ "oak",
1183
+ "ocean",
1184
+ "onyx",
1185
+ "opal",
1186
+ "otter",
1187
+ "palm",
1188
+ "peak",
1189
+ "pine",
1190
+ "pond",
1191
+ "pool",
1192
+ "rain",
1193
+ "reed",
1194
+ "reef",
1195
+ "rice",
1196
+ "ring",
1197
+ "rise",
1198
+ "road",
1199
+ "rock",
1200
+ "rose",
1201
+ "ruby",
1202
+ "sage",
1203
+ "sand",
1204
+ "seal",
1205
+ "seed",
1206
+ "silk",
1207
+ "sky",
1208
+ "snow",
1209
+ "soft",
1210
+ "star",
1211
+ "stem",
1212
+ "stone",
1213
+ "surf",
1214
+ "swan",
1215
+ "teal",
1216
+ "tide",
1217
+ "tree",
1218
+ "vale",
1219
+ "vine",
1220
+ "wave",
1221
+ "west",
1222
+ "wind",
1223
+ "wing",
1224
+ "wolf",
1225
+ "wood",
1226
+ "wren",
1227
+ "yarn",
1228
+ "zest"
1229
+ ]
1114
1230
  }
1115
1231
  }
1116
1232
  };
@@ -1144,26 +1260,35 @@ function assertManagedDeploymentSpec(value) {
1144
1260
  }
1145
1261
  }
1146
1262
 
1263
+ // ../../packages/agent-source-bundler/dist/src/native-pi.js
1264
+ import { stringify } from "smol-toml";
1265
+ function nativePiDeclaration(model) {
1266
+ return {
1267
+ version: 2,
1268
+ harness: { runtime: "pi", driver: { kind: "native" } },
1269
+ inference: { model }
1270
+ };
1271
+ }
1272
+
1147
1273
  // src/declaration.ts
1148
1274
  import { randomUUID as randomUUID2 } from "node:crypto";
1149
1275
  import { lstat as lstat2, open, readFile as readFile2, rename, rm } from "node:fs/promises";
1150
1276
  import path2 from "node:path";
1151
- import { parse, stringify } from "smol-toml";
1277
+ import { parse, stringify as stringify2 } from "smol-toml";
1152
1278
  var DECLARATION_FILENAME = ".tonbo";
1153
- var DEFAULT_INFERENCE_MODEL = "claude-sonnet-4-5";
1154
1279
  function createDeclaration(model = DEFAULT_INFERENCE_MODEL, driver = { kind: "native" }, buildCommand, agentHostname) {
1280
+ const base = nativePiDeclaration(model.trim());
1155
1281
  return parseDeclaration({
1156
- version: 2,
1282
+ ...base,
1157
1283
  ...agentHostname ? { agent: agentHostname } : {},
1158
- harness: { runtime: "pi", driver },
1159
- inference: { model: model.trim() },
1284
+ harness: { ...base.harness, driver },
1160
1285
  ...buildCommand ? { build: { command: buildCommand } } : {}
1161
1286
  });
1162
1287
  }
1163
1288
  function renderDeclaration(declaration) {
1164
1289
  return `# Tonbo Agent configuration.
1165
1290
  # Edit this file directly or run \`tonbo init\` to reconfigure.
1166
- ${stringify(declaration)}`;
1291
+ ${stringify2(declaration)}`;
1167
1292
  }
1168
1293
  async function bindDeclarationAgent(root, agentHostname) {
1169
1294
  const declaration = await loadDeclaration(root);
@@ -1246,7 +1371,7 @@ function buildDeploymentSpec(declaration, source) {
1246
1371
  return spec;
1247
1372
  }
1248
1373
 
1249
- // src/source.ts
1374
+ // ../../packages/agent-source-bundler/dist/src/index.js
1250
1375
  import { createHash as createHash2 } from "node:crypto";
1251
1376
  import { lstat as lstat3, readFile as readFile3, readdir } from "node:fs/promises";
1252
1377
  import path3 from "node:path";
@@ -1269,7 +1394,8 @@ var DEFAULT_IGNORES = [
1269
1394
  var EXACT_NPM_VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
1270
1395
  var GIT_COMMIT = /^[0-9a-f]{40}$/i;
1271
1396
  function packageSource(value, index) {
1272
- if (typeof value === "string") return value;
1397
+ if (typeof value === "string")
1398
+ return value;
1273
1399
  if (value && typeof value === "object" && "source" in value && typeof value.source === "string")
1274
1400
  return value.source;
1275
1401
  throw new Error(`.pi/settings.json packages[${index}] must be a source string or object.`);
@@ -1279,9 +1405,7 @@ async function validatePackageSource(root, source) {
1279
1405
  const specifier = source.slice(4);
1280
1406
  const separator = specifier.lastIndexOf("@");
1281
1407
  if (separator <= 0 || !EXACT_NPM_VERSION.test(specifier.slice(separator + 1))) {
1282
- throw new Error(
1283
- `PI package ${source} must pin an exact npm version, for example npm:my-agent@1.2.3.`
1284
- );
1408
+ throw new Error(`PI package ${source} must pin an exact npm version, for example npm:my-agent@1.2.3.`);
1285
1409
  }
1286
1410
  return;
1287
1411
  }
@@ -1313,9 +1437,7 @@ async function validatePackageSource(root, source) {
1313
1437
  }
1314
1438
  return;
1315
1439
  }
1316
- throw new Error(
1317
- `PI package ${source} must use an exact npm version, a full Git commit, or a agent-local path.`
1318
- );
1440
+ throw new Error(`PI package ${source} must use an exact npm version, a full Git commit, or a agent-local path.`);
1319
1441
  }
1320
1442
  async function validatePiPackages(root) {
1321
1443
  const filename = path3.join(root, ".pi", "settings.json");
@@ -1323,23 +1445,26 @@ async function validatePiPackages(root) {
1323
1445
  try {
1324
1446
  settings = JSON.parse(await readFile3(filename, "utf8"));
1325
1447
  } catch (error) {
1326
- if (error.code === "ENOENT") return;
1448
+ if (error.code === "ENOENT")
1449
+ return;
1327
1450
  throw new Error(`Could not read ${filename} as JSON.`, { cause: error });
1328
1451
  }
1329
- if (!settings || typeof settings !== "object" || !("packages" in settings)) return;
1452
+ if (!settings || typeof settings !== "object" || !("packages" in settings))
1453
+ return;
1330
1454
  const packages = settings.packages;
1331
- if (!Array.isArray(packages)) throw new Error(`${filename} packages must be an array.`);
1332
- await Promise.all(
1333
- packages.map((value, index) => validatePackageSource(root, packageSource(value, index)))
1334
- );
1455
+ if (!Array.isArray(packages))
1456
+ throw new Error(`${filename} packages must be an array.`);
1457
+ await Promise.all(packages.map((value, index) => validatePackageSource(root, packageSource(value, index))));
1335
1458
  }
1336
1459
  async function findDeclarationRoot(start) {
1337
1460
  let candidate = path3.resolve(start);
1338
1461
  for (; ; ) {
1339
1462
  try {
1340
- if ((await lstat3(path3.join(candidate, ".tonbo"))).isFile()) return candidate;
1463
+ if ((await lstat3(path3.join(candidate, ".tonbo"))).isFile())
1464
+ return candidate;
1341
1465
  } catch (error) {
1342
- if (error.code !== "ENOENT") throw error;
1466
+ if (error.code !== "ENOENT")
1467
+ throw error;
1343
1468
  }
1344
1469
  const parent = path3.dirname(candidate);
1345
1470
  if (parent === candidate) {
@@ -1353,7 +1478,8 @@ async function sourceIgnore(root) {
1353
1478
  try {
1354
1479
  matcher.add(await readFile3(path3.join(root, ".tonboignore"), "utf8"));
1355
1480
  } catch (error) {
1356
- if (error.code !== "ENOENT") throw error;
1481
+ if (error.code !== "ENOENT")
1482
+ throw error;
1357
1483
  }
1358
1484
  return matcher;
1359
1485
  }
@@ -1366,11 +1492,10 @@ async function collectFiles(root) {
1366
1492
  for (const entry of entries) {
1367
1493
  const relative = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
1368
1494
  const ignored = matcher.ignores(relative + (entry.isDirectory() ? "/" : ""));
1369
- if (ignored) continue;
1495
+ if (ignored)
1496
+ continue;
1370
1497
  if (relative === SESSION_SOURCE_DIRECTORY || relative.startsWith(`${SESSION_SOURCE_DIRECTORY}/`)) {
1371
- throw new Error(
1372
- `Source path ${SESSION_SOURCE_DIRECTORY}/ is reserved for durable PI history. Rename it or exclude it with .tonboignore.`
1373
- );
1498
+ throw new Error(`Source path ${SESSION_SOURCE_DIRECTORY}/ is reserved for durable PI history. Rename it or exclude it with .tonboignore.`);
1374
1499
  }
1375
1500
  const absolute = path3.join(directory, entry.name);
1376
1501
  if (entry.isDirectory()) {
@@ -1379,9 +1504,7 @@ async function collectFiles(root) {
1379
1504
  }
1380
1505
  const metadata = await lstat3(absolute);
1381
1506
  if (!metadata.isFile()) {
1382
- throw new Error(
1383
- `Source path ${relative} is not a regular file. V1 does not follow symlinks or special files.`
1384
- );
1507
+ throw new Error(`Source path ${relative} is not a regular file. V1 does not follow symlinks or special files.`);
1385
1508
  }
1386
1509
  files.push({
1387
1510
  absolute,
@@ -1399,19 +1522,15 @@ async function collectFiles(root) {
1399
1522
  }
1400
1523
  function addEntry(pack, file, contents) {
1401
1524
  return new Promise((resolve, reject) => {
1402
- pack.entry(
1403
- {
1404
- gid: 0,
1405
- mode: file.mode,
1406
- mtime: /* @__PURE__ */ new Date(0),
1407
- name: file.relative,
1408
- size: contents.length,
1409
- type: "file",
1410
- uid: 0
1411
- },
1412
- contents,
1413
- (error) => error ? reject(error) : resolve()
1414
- );
1525
+ pack.entry({
1526
+ gid: 0,
1527
+ mode: file.mode,
1528
+ mtime: /* @__PURE__ */ new Date(0),
1529
+ name: file.relative,
1530
+ size: contents.length,
1531
+ type: "file",
1532
+ uid: 0
1533
+ }, contents, (error) => error ? reject(error) : resolve());
1415
1534
  });
1416
1535
  }
1417
1536
  async function buildSourceBundle(root) {
@@ -1428,9 +1547,7 @@ async function buildSourceBundle(root) {
1428
1547
  pack.on("data", (chunk) => {
1429
1548
  size += chunk.length;
1430
1549
  if (size > MAX_BUNDLE_BYTES) {
1431
- pack.destroy(
1432
- new Error(`Source bundle exceeds ${MAX_BUNDLE_BYTES} bytes after ignore rules.`)
1433
- );
1550
+ pack.destroy(new Error(`Source bundle exceeds ${MAX_BUNDLE_BYTES} bytes after ignore rules.`));
1434
1551
  return;
1435
1552
  }
1436
1553
  chunks.push(chunk);
@@ -2066,7 +2183,7 @@ function deploymentName(deployment) {
2066
2183
  }
2067
2184
  function deploymentSourceLabel(deployment) {
2068
2185
  const git = deployment.origin.git;
2069
- if (!git) return "tonbo deploy";
2186
+ if (!git) return deploymentOriginLabel(deployment.origin.actor);
2070
2187
  const sha = git.commit_sha.slice(0, 7);
2071
2188
  return git.ref ? `${sha} \xB7 ${git.ref}` : sha;
2072
2189
  }
@@ -2369,15 +2486,17 @@ var AUTHOR_MAX_LENGTH = 255;
2369
2486
  async function collectGitProvenance(root, run = defaultGitRunner) {
2370
2487
  const commitSha = await read(run, ["rev-parse", "HEAD"], root);
2371
2488
  if (!commitSha || !COMMIT_SHA.test(commitSha)) return null;
2372
- const [ref, subject, author, status] = await Promise.all([
2489
+ const [ref, subject, author, status, remote] = await Promise.all([
2373
2490
  read(run, ["rev-parse", "--abbrev-ref", "HEAD"], root),
2374
2491
  read(run, ["log", "-1", "--format=%s"], root),
2375
2492
  read(run, ["log", "-1", "--format=%an"], root),
2376
2493
  // Only the deployed tree matters: changes elsewhere in the repository do
2377
2494
  // not alter the uploaded bundle.
2378
- read(run, ["status", "--porcelain", "--", "."], root)
2495
+ read(run, ["status", "--porcelain", "--", "."], root),
2496
+ read(run, ["remote", "get-url", "origin"], root)
2379
2497
  ]);
2380
2498
  return {
2499
+ ...githubRepositoryUrl(remote) ? { repository_url: githubRepositoryUrl(remote) } : {},
2381
2500
  commit_sha: commitSha,
2382
2501
  ref: ref === "HEAD" ? null : clamp(ref, REF_MAX_LENGTH),
2383
2502
  subject: clamp(subject, SUBJECT_MAX_LENGTH),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tonbo/cli",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Deploy persistent Agents and manage their Machines from the command line.",
5
5
  "homepage": "https://tonbo.dev",
6
6
  "bugs": {
@@ -22,12 +22,12 @@
22
22
  "access": "public"
23
23
  },
24
24
  "scripts": {
25
- "build": "pnpm run build:source-inspector && node scripts/generate-contracts.mjs --check && tsc -p tsconfig.json && node scripts/bundle.mjs",
26
- "build:source-inspector": "pnpm --filter @tonbo/agent-source-inspector build",
25
+ "build": "pnpm run build:source-tools && node scripts/generate-contracts.mjs --check && tsc -p tsconfig.json && node scripts/bundle.mjs",
26
+ "build:source-tools": "pnpm --filter @tonbo/agent-source-inspector --filter @tonbo/agent-source-bundler build",
27
27
  "generate:contracts": "node scripts/generate-contracts.mjs",
28
- "lint": "pnpm run build:source-inspector && eslint . --max-warnings=0",
28
+ "lint": "pnpm run build:source-tools && eslint . --max-warnings=0",
29
29
  "test": "pnpm build && node --test dist/test/*.test.js",
30
- "typecheck": "pnpm run build:source-inspector && node scripts/generate-contracts.mjs --check && tsc -p tsconfig.json --noEmit"
30
+ "typecheck": "pnpm run build:source-tools && node scripts/generate-contracts.mjs --check && tsc -p tsconfig.json --noEmit"
31
31
  },
32
32
  "dependencies": {
33
33
  "@inquirer/select": "4.4.2",
@@ -40,9 +40,9 @@
40
40
  "devDependencies": {
41
41
  "@tonbo/agent-source-inspector": "workspace:*",
42
42
  "@types/node": "^20.19.37",
43
- "@types/tar-stream": "^3.1.4",
44
43
  "esbuild": "0.25.4",
45
- "typescript": "catalog:"
44
+ "typescript": "catalog:",
45
+ "@tonbo/agent-source-bundler": "workspace:*"
46
46
  },
47
47
  "engines": {
48
48
  "node": ">=22"