@autohq/cli 0.1.103 → 0.1.105

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.
@@ -19558,7 +19558,17 @@ var RuntimeBridgeBootstrapEnvelopeSchema = external_exports.object({
19558
19558
  var RuntimeBridgeBootstrapAckSchema = external_exports.object({
19559
19559
  status: external_exports.enum(["ready", "failed"]),
19560
19560
  error: external_exports.string().trim().min(1).optional(),
19561
- at: external_exports.string().datetime()
19561
+ at: external_exports.string().datetime(),
19562
+ // The sandbox-baked CLI's own release version (e.g. "0.1.95"), so the
19563
+ // bridge can tag bootstrap observability with the runtime version that is
19564
+ // actually live. Optional because runtimes older than the field predate
19565
+ // reporting it; the bridge logs those as "unknown" instead of failing.
19566
+ cliVersion: external_exports.string().trim().min(1).optional(),
19567
+ // Top-level bootstrap plaintext fields the runtime's tolerant parse
19568
+ // stripped because its schema does not know them yet (worker-ahead skew).
19569
+ // Reported so the bridge can log the degradation instead of it staying
19570
+ // silent.
19571
+ ignoredBootstrapKeys: external_exports.array(external_exports.string().trim().min(1)).optional()
19562
19572
  });
19563
19573
  var RuntimeBridgeConnectedPayloadSchema = external_exports.object({
19564
19574
  runId: SessionRunIdSchema,
@@ -21838,6 +21848,14 @@ var ProjectApplyAssetsSchema = external_exports.record(
21838
21848
  }),
21839
21849
  ProjectApplyAssetSchema
21840
21850
  );
21851
+ var AvatarAssetUploadRequestSchema = ProjectApplyAssetSchema.omit({
21852
+ sha256: true
21853
+ });
21854
+ var AvatarAssetUploadResponseSchema = external_exports.object({
21855
+ sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
21856
+ contentType: external_exports.enum(AVATAR_ASSET_CONTENT_TYPES),
21857
+ sizeBytes: external_exports.number().int().positive()
21858
+ });
21841
21859
  var ProjectApplyRequestSchema = external_exports.object({
21842
21860
  delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
21843
21861
  dryRun: external_exports.boolean().default(false),
@@ -22584,7 +22602,16 @@ function decryptRuntimeBridgeBootstrap(input) {
22584
22602
  decipher.update(Buffer.from(envelope.bootstrap.ciphertext, "base64")),
22585
22603
  decipher.final()
22586
22604
  ]).toString("utf8");
22587
- return RuntimeBridgeBootstrapPlaintextSchema.parse(JSON.parse(plaintext));
22605
+ const raw = JSON.parse(plaintext);
22606
+ const bootstrap = RuntimeBridgeBootstrapPlaintextSchema.parse(raw);
22607
+ return { bootstrap, ignoredKeys: ignoredPlaintextKeys(raw) };
22608
+ }
22609
+ function ignoredPlaintextKeys(raw) {
22610
+ const record2 = external_exports.record(external_exports.string(), external_exports.unknown()).parse(raw);
22611
+ const knownKeys = new Set(
22612
+ Object.keys(RuntimeBridgeBootstrapPlaintextSchema.shape)
22613
+ );
22614
+ return Object.keys(record2).filter((key) => !knownKeys.has(key));
22588
22615
  }
22589
22616
  function deriveBootstrapKey(accessToken, salt) {
22590
22617
  return Buffer.from(
@@ -26161,6 +26188,61 @@ Object.assign(lookup, {
26161
26188
  connect: lookup
26162
26189
  });
26163
26190
 
26191
+ // package.json
26192
+ var package_default = {
26193
+ name: "@autohq/cli",
26194
+ version: "0.1.105",
26195
+ license: "SEE LICENSE IN README.md",
26196
+ publishConfig: {
26197
+ access: "public"
26198
+ },
26199
+ repository: {
26200
+ type: "git",
26201
+ url: "git+https://github.com/fractal-works/auto.git",
26202
+ directory: "apps/cli"
26203
+ },
26204
+ engines: {
26205
+ node: ">=20"
26206
+ },
26207
+ type: "module",
26208
+ bin: {
26209
+ auto: "./dist/index.js"
26210
+ },
26211
+ files: ["dist"],
26212
+ scripts: {
26213
+ build: "tsup",
26214
+ dev: "tsx src/main.ts",
26215
+ "dev:tui": "node ../../scripts/cli-tui-dev-watch.mjs",
26216
+ "skill:generate": "tsx scripts/generate-skill-content.ts",
26217
+ test: "npm run test:unit",
26218
+ "test:unit": 'tsx --test "test/**/*.unit.test.ts"',
26219
+ typecheck: "tsc --noEmit"
26220
+ },
26221
+ dependencies: {
26222
+ "@anthropic-ai/claude-agent-sdk": "^0.3.153",
26223
+ "@inkjs/ui": "^2.0.0",
26224
+ "@tanstack/react-query": "^5.100.14",
26225
+ chalk: "^5.3.0",
26226
+ commander: "^14.0.2",
26227
+ ink: "^7",
26228
+ "ink-text-input": "^6.0.0",
26229
+ jose: "^5.9.6",
26230
+ marked: "^15.0.12",
26231
+ react: "^19",
26232
+ "socket.io-client": "^4.8.3",
26233
+ yaml: "^2.9.0"
26234
+ },
26235
+ devDependencies: {
26236
+ "@auto/protocol": "*",
26237
+ "@auto/schemas": "*",
26238
+ "@types/react": "^19",
26239
+ tsup: "^8.5.1"
26240
+ }
26241
+ };
26242
+
26243
+ // src/cli/version.ts
26244
+ var cliVersion = package_default.version;
26245
+
26164
26246
  // src/commands/agent-bridge/socket.ts
26165
26247
  async function runAgentBridgeSocket(options) {
26166
26248
  const socket = lookup(`${options.bridgeUrl}${RUNTIME_BRIDGE_NAMESPACE}`, {
@@ -26296,13 +26378,18 @@ function createRuntimeBridgeBootstrapListener(input) {
26296
26378
  bridgeLeaseId: envelope.bridgeLeaseId
26297
26379
  });
26298
26380
  const decryptStartedAt = Date.now();
26299
- const bootstrap = decryptRuntimeBridgeBootstrap({
26381
+ const { bootstrap, ignoredKeys } = decryptRuntimeBridgeBootstrap({
26300
26382
  accessToken: input.token,
26301
26383
  envelope
26302
26384
  });
26303
26385
  input.writeOutput?.(
26304
26386
  `agent_bridge_bootstrap_decrypted duration_ms=${Date.now() - decryptStartedAt}`
26305
26387
  );
26388
+ if (ignoredKeys.length > 0) {
26389
+ input.writeOutput?.(
26390
+ `agent_bridge_bootstrap_ignored_keys cli_version=${cliVersion} keys=${ignoredKeys.join(",")}`
26391
+ );
26392
+ }
26306
26393
  await input.onBootstrap?.(bootstrap);
26307
26394
  let handler = input.getHandler();
26308
26395
  if (!handler) {
@@ -26318,7 +26405,9 @@ function createRuntimeBridgeBootstrapListener(input) {
26318
26405
  ack?.(
26319
26406
  RuntimeBridgeBootstrapAckSchema.parse({
26320
26407
  status: "ready",
26321
- at: (/* @__PURE__ */ new Date()).toISOString()
26408
+ at: (/* @__PURE__ */ new Date()).toISOString(),
26409
+ cliVersion,
26410
+ ignoredBootstrapKeys: ignoredKeys.length > 0 ? ignoredKeys : void 0
26322
26411
  })
26323
26412
  );
26324
26413
  prepare?.then(
@@ -26344,7 +26433,10 @@ function createRuntimeBridgeBootstrapListener(input) {
26344
26433
  RuntimeBridgeBootstrapAckSchema.parse({
26345
26434
  status: "failed",
26346
26435
  error: message,
26347
- at: (/* @__PURE__ */ new Date()).toISOString()
26436
+ at: (/* @__PURE__ */ new Date()).toISOString(),
26437
+ // Version skew is a leading cause of bootstrap failure, so failed
26438
+ // acks carry the version that could not bootstrap.
26439
+ cliVersion
26348
26440
  })
26349
26441
  );
26350
26442
  input.onBootstrapError(error51);
package/dist/index.js CHANGED
@@ -17628,7 +17628,7 @@ var init_sessions = __esm({
17628
17628
  });
17629
17629
 
17630
17630
  // ../../packages/schemas/src/project-resources.ts
17631
- var EnvironmentApplyDocumentSchema, ProfileApplyDocumentSchema, ToolApplyDocumentSchema, SessionApplyDocumentSchema, ProjectApplyResourceSchema, PROJECT_RESOURCE_KINDS, ProjectDeleteResourceSchema, AVATAR_ASSET_CONTENT_TYPES, MAX_AVATAR_ASSET_BASE64_LENGTH, ProjectApplyAssetSchema, ProjectApplyAssetsSchema, ProjectApplyRequestSchema, ProjectApplySystemConfigSchema, ProjectAppliedResourceSchema, ProjectApplyDiagnosticSchema, ProjectApplyResponseSchema;
17631
+ var EnvironmentApplyDocumentSchema, ProfileApplyDocumentSchema, ToolApplyDocumentSchema, SessionApplyDocumentSchema, ProjectApplyResourceSchema, PROJECT_RESOURCE_KINDS, ProjectDeleteResourceSchema, AVATAR_ASSET_CONTENT_TYPES, MAX_AVATAR_ASSET_BASE64_LENGTH, ProjectApplyAssetSchema, ProjectApplyAssetsSchema, AvatarAssetUploadRequestSchema, AvatarAssetUploadResponseSchema, ProjectApplyRequestSchema, ProjectApplySystemConfigSchema, ProjectAppliedResourceSchema, ProjectApplyDiagnosticSchema, ProjectApplyResponseSchema;
17632
17632
  var init_project_resources = __esm({
17633
17633
  "../../packages/schemas/src/project-resources.ts"() {
17634
17634
  "use strict";
@@ -17678,6 +17678,14 @@ var init_project_resources = __esm({
17678
17678
  }),
17679
17679
  ProjectApplyAssetSchema
17680
17680
  );
17681
+ AvatarAssetUploadRequestSchema = ProjectApplyAssetSchema.omit({
17682
+ sha256: true
17683
+ });
17684
+ AvatarAssetUploadResponseSchema = external_exports.object({
17685
+ sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
17686
+ contentType: external_exports.enum(AVATAR_ASSET_CONTENT_TYPES),
17687
+ sizeBytes: external_exports.number().int().positive()
17688
+ });
17681
17689
  ProjectApplyRequestSchema = external_exports.object({
17682
17690
  delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
17683
17691
  dryRun: external_exports.boolean().default(false),
@@ -18483,6 +18491,73 @@ var init_src = __esm({
18483
18491
  }
18484
18492
  });
18485
18493
 
18494
+ // package.json
18495
+ var package_default;
18496
+ var init_package = __esm({
18497
+ "package.json"() {
18498
+ package_default = {
18499
+ name: "@autohq/cli",
18500
+ version: "0.1.105",
18501
+ license: "SEE LICENSE IN README.md",
18502
+ publishConfig: {
18503
+ access: "public"
18504
+ },
18505
+ repository: {
18506
+ type: "git",
18507
+ url: "git+https://github.com/fractal-works/auto.git",
18508
+ directory: "apps/cli"
18509
+ },
18510
+ engines: {
18511
+ node: ">=20"
18512
+ },
18513
+ type: "module",
18514
+ bin: {
18515
+ auto: "./dist/index.js"
18516
+ },
18517
+ files: ["dist"],
18518
+ scripts: {
18519
+ build: "tsup",
18520
+ dev: "tsx src/main.ts",
18521
+ "dev:tui": "node ../../scripts/cli-tui-dev-watch.mjs",
18522
+ "skill:generate": "tsx scripts/generate-skill-content.ts",
18523
+ test: "npm run test:unit",
18524
+ "test:unit": 'tsx --test "test/**/*.unit.test.ts"',
18525
+ typecheck: "tsc --noEmit"
18526
+ },
18527
+ dependencies: {
18528
+ "@anthropic-ai/claude-agent-sdk": "^0.3.153",
18529
+ "@inkjs/ui": "^2.0.0",
18530
+ "@tanstack/react-query": "^5.100.14",
18531
+ chalk: "^5.3.0",
18532
+ commander: "^14.0.2",
18533
+ ink: "^7",
18534
+ "ink-text-input": "^6.0.0",
18535
+ jose: "^5.9.6",
18536
+ marked: "^15.0.12",
18537
+ react: "^19",
18538
+ "socket.io-client": "^4.8.3",
18539
+ yaml: "^2.9.0"
18540
+ },
18541
+ devDependencies: {
18542
+ "@auto/protocol": "*",
18543
+ "@auto/schemas": "*",
18544
+ "@types/react": "^19",
18545
+ tsup: "^8.5.1"
18546
+ }
18547
+ };
18548
+ }
18549
+ });
18550
+
18551
+ // src/cli/version.ts
18552
+ var cliVersion;
18553
+ var init_version = __esm({
18554
+ "src/cli/version.ts"() {
18555
+ "use strict";
18556
+ init_package();
18557
+ cliVersion = package_default.version;
18558
+ }
18559
+ });
18560
+
18486
18561
  // src/lib/auth/tokens.ts
18487
18562
  function accessTokenExpiresAt(token2) {
18488
18563
  if (!token2.access_token) {
@@ -18853,6 +18928,8 @@ function createResourceApi(context) {
18853
18928
  });
18854
18929
  return {
18855
18930
  applyEnvironmentResource: environments.apply,
18931
+ hasAvatarAsset: (request, options) => hasAvatarAsset(context, request, options ?? {}),
18932
+ uploadAvatarAsset: (request, options) => uploadAvatarAsset(context, request, options ?? {}),
18856
18933
  applyProjectResources: (request, options) => applyProjectResources(
18857
18934
  context,
18858
18935
  request,
@@ -18878,6 +18955,58 @@ function createResourceApi(context) {
18878
18955
  updateProjectServiceAccount: (request, options) => updateProjectServiceAccount(context, request, options ?? {})
18879
18956
  };
18880
18957
  }
18958
+ async function hasAvatarAsset(context, request, options) {
18959
+ const response = await context.authenticatedFetch(
18960
+ context.apiUrl(
18961
+ apiPath(`/avatars/${encodeURIComponent(request.sha256)}`),
18962
+ options.apiBaseUrl
18963
+ ),
18964
+ { method: "HEAD" },
18965
+ options.apiBaseUrl
18966
+ );
18967
+ if (response.ok) {
18968
+ return true;
18969
+ }
18970
+ if (response.status === 404) {
18971
+ return false;
18972
+ }
18973
+ throw new Error(await responseErrorMessage(response));
18974
+ }
18975
+ async function uploadAvatarAsset(context, request, options) {
18976
+ const path2 = await avatarAssetUploadPath(context, request.sha256);
18977
+ const response = await context.authenticatedFetch(
18978
+ context.apiUrl(path2, options.apiBaseUrl),
18979
+ {
18980
+ method: "PUT",
18981
+ headers: { "content-type": "application/json" },
18982
+ body: JSON.stringify({
18983
+ contentType: request.contentType,
18984
+ dataBase64: request.dataBase64
18985
+ })
18986
+ },
18987
+ options.apiBaseUrl
18988
+ );
18989
+ if (response.status === 404) {
18990
+ throw new AvatarAssetUploadUnsupportedError(
18991
+ await responseErrorMessage(response)
18992
+ );
18993
+ }
18994
+ if (!response.ok) {
18995
+ throw new Error(await responseErrorMessage(response));
18996
+ }
18997
+ return AvatarAssetUploadResponseSchema.parse(await response.json());
18998
+ }
18999
+ async function avatarAssetUploadPath(context, sha256) {
19000
+ const subpath = `/avatar-assets/${encodeURIComponent(sha256)}`;
19001
+ try {
19002
+ return projectApiPath(await context.activeProject(), subpath);
19003
+ } catch (error51) {
19004
+ if (context.shouldTryProjectInferredAuth()) {
19005
+ return apiPath(`/project${subpath}`);
19006
+ }
19007
+ throw error51;
19008
+ }
19009
+ }
18881
19010
  async function listProjectServiceAccounts(context, options) {
18882
19011
  const project = await context.activeProject();
18883
19012
  const response = await context.authenticatedFetch(
@@ -19182,13 +19311,15 @@ async function listProjectResources(context, endpoint, options) {
19182
19311
  }
19183
19312
  return await response.json();
19184
19313
  }
19185
- var SlackConfigTokenRequiredError;
19314
+ var AvatarAssetUploadUnsupportedError, SlackConfigTokenRequiredError;
19186
19315
  var init_resources2 = __esm({
19187
19316
  "src/lib/api/resources.ts"() {
19188
19317
  "use strict";
19189
19318
  init_src();
19190
19319
  init_errors3();
19191
19320
  init_paths();
19321
+ AvatarAssetUploadUnsupportedError = class extends Error {
19322
+ };
19192
19323
  SlackConfigTokenRequiredError = class extends Error {
19193
19324
  workspace;
19194
19325
  constructor(message, workspace) {
@@ -20868,6 +20999,98 @@ var init_connect = __esm({
20868
20999
  }
20869
21000
  });
20870
21001
 
21002
+ // src/commands/apply/assets.ts
21003
+ async function resolveApplyAssets(input) {
21004
+ const entries = Object.entries(input.request.assets);
21005
+ if (entries.length === 0) {
21006
+ return { resources: input.request.resources, assets: {} };
21007
+ }
21008
+ const probes = await Promise.all(
21009
+ entries.map(async ([path2, asset]) => ({
21010
+ path: path2,
21011
+ asset,
21012
+ stored: await input.client.hasAvatarAsset(
21013
+ { sha256: asset.sha256 },
21014
+ { apiBaseUrl: input.apiBaseUrl }
21015
+ )
21016
+ }))
21017
+ );
21018
+ const inline2 = {};
21019
+ for (const probe of probes) {
21020
+ if (probe.stored) {
21021
+ continue;
21022
+ }
21023
+ if (input.dryRun) {
21024
+ inline2[probe.path] = probe.asset;
21025
+ continue;
21026
+ }
21027
+ if (!await uploadAvatarAsset2(input.client, probe.asset, input.apiBaseUrl)) {
21028
+ inline2[probe.path] = probe.asset;
21029
+ }
21030
+ }
21031
+ const resources = input.request.resources.map(
21032
+ (resource) => stampAvatarSha256(resource, input.request.assets)
21033
+ );
21034
+ return { resources, assets: inline2 };
21035
+ }
21036
+ function assertApplyRequestBodySize(input) {
21037
+ const bytes = Buffer.byteLength(input.body, "utf8");
21038
+ if (bytes <= MAX_APPLY_REQUEST_BODY_BYTES) {
21039
+ return;
21040
+ }
21041
+ const paths = Object.keys(input.assets);
21042
+ const assetDetail = paths.length > 0 ? ` ${paths.length} avatar asset(s) are not yet stored on the server, so their bytes must ride this request: ${paths.join(", ")}. Apply the sessions referencing them in smaller batches (auto apply -f <file> --no-prune) or shrink the image files.` : "";
21043
+ throw new Error(
21044
+ `Apply request body is ${formatMegabytes(bytes)}MB, over the ~4.5MB server request limit.${assetDetail}`
21045
+ );
21046
+ }
21047
+ async function uploadAvatarAsset2(client, asset, apiBaseUrl) {
21048
+ try {
21049
+ await client.uploadAvatarAsset(asset, { apiBaseUrl });
21050
+ return true;
21051
+ } catch (error51) {
21052
+ if (error51 instanceof AvatarAssetUploadUnsupportedError) {
21053
+ return false;
21054
+ }
21055
+ throw error51;
21056
+ }
21057
+ }
21058
+ function stampAvatarSha256(resource, assets) {
21059
+ if (resource.kind !== "session") {
21060
+ return resource;
21061
+ }
21062
+ const identity2 = resource.spec.identity;
21063
+ const avatar = identity2?.avatar;
21064
+ if (!identity2 || !avatar) {
21065
+ return resource;
21066
+ }
21067
+ const asset = assets[avatar.asset];
21068
+ if (!asset) {
21069
+ return resource;
21070
+ }
21071
+ return {
21072
+ ...resource,
21073
+ spec: {
21074
+ ...resource.spec,
21075
+ identity: {
21076
+ ...identity2,
21077
+ avatar: { asset: avatar.asset, sha256: asset.sha256 }
21078
+ }
21079
+ }
21080
+ };
21081
+ }
21082
+ function formatMegabytes(bytes) {
21083
+ return (bytes / (1024 * 1024)).toFixed(1);
21084
+ }
21085
+ var MAX_APPLY_REQUEST_BODY_BYTES;
21086
+ var init_assets = __esm({
21087
+ "src/commands/apply/assets.ts"() {
21088
+ "use strict";
21089
+ init_resources2();
21090
+ MAX_APPLY_REQUEST_BODY_BYTES = 4 * 1024 * 1024;
21091
+ }
21092
+ });
21093
+
20871
21094
  // src/commands/apply/files.ts
20872
21095
  import { createHash as createHash2 } from "crypto";
20873
21096
  import {
@@ -21212,16 +21435,27 @@ async function applyResource(input) {
21212
21435
  }
21213
21436
  async function applyProjectInput(input) {
21214
21437
  const style = input.style ?? plainStyle;
21215
- const response = await input.client.applyProjectResources(
21216
- {
21217
- ...input.request.delete.length > 0 ? { delete: input.request.delete } : {},
21218
- dryRun: input.commandOptions.dryRun ?? input.request.dryRun,
21219
- prune: input.commandOptions.prune ?? input.request.prune,
21220
- resources: input.request.resources,
21221
- ...Object.keys(input.request.assets).length > 0 ? { assets: input.request.assets } : {}
21222
- },
21223
- { apiBaseUrl: input.commandOptions.apiBaseUrl }
21224
- );
21438
+ const dryRun = input.commandOptions.dryRun ?? input.request.dryRun;
21439
+ const resolved = await resolveApplyAssets({
21440
+ client: input.client,
21441
+ request: input.request,
21442
+ apiBaseUrl: input.commandOptions.apiBaseUrl,
21443
+ dryRun
21444
+ });
21445
+ const request = {
21446
+ ...input.request.delete.length > 0 ? { delete: input.request.delete } : {},
21447
+ dryRun,
21448
+ prune: input.commandOptions.prune ?? input.request.prune,
21449
+ resources: resolved.resources,
21450
+ ...Object.keys(resolved.assets).length > 0 ? { assets: resolved.assets } : {}
21451
+ };
21452
+ assertApplyRequestBodySize({
21453
+ body: JSON.stringify(request),
21454
+ assets: resolved.assets
21455
+ });
21456
+ const response = await input.client.applyProjectResources(request, {
21457
+ apiBaseUrl: input.commandOptions.apiBaseUrl
21458
+ });
21225
21459
  const resources = response.resources.map((resource, index) => ({
21226
21460
  kind: appliedResourceKind(input.request, response, index),
21227
21461
  resource
@@ -21324,6 +21558,7 @@ var init_actions = __esm({
21324
21558
  "use strict";
21325
21559
  init_style();
21326
21560
  init_connect();
21561
+ init_assets();
21327
21562
  init_files();
21328
21563
  }
21329
21564
  });
@@ -21852,73 +22087,6 @@ var init_conversation2 = __esm({
21852
22087
  }
21853
22088
  });
21854
22089
 
21855
- // package.json
21856
- var package_default;
21857
- var init_package = __esm({
21858
- "package.json"() {
21859
- package_default = {
21860
- name: "@autohq/cli",
21861
- version: "0.1.103",
21862
- license: "SEE LICENSE IN README.md",
21863
- publishConfig: {
21864
- access: "public"
21865
- },
21866
- repository: {
21867
- type: "git",
21868
- url: "git+https://github.com/fractal-works/auto.git",
21869
- directory: "apps/cli"
21870
- },
21871
- engines: {
21872
- node: ">=20"
21873
- },
21874
- type: "module",
21875
- bin: {
21876
- auto: "./dist/index.js"
21877
- },
21878
- files: ["dist"],
21879
- scripts: {
21880
- build: "tsup",
21881
- dev: "tsx src/main.ts",
21882
- "dev:tui": "node ../../scripts/cli-tui-dev-watch.mjs",
21883
- "skill:generate": "tsx scripts/generate-skill-content.ts",
21884
- test: "npm run test:unit",
21885
- "test:unit": 'tsx --test "test/**/*.unit.test.ts"',
21886
- typecheck: "tsc --noEmit"
21887
- },
21888
- dependencies: {
21889
- "@anthropic-ai/claude-agent-sdk": "^0.3.153",
21890
- "@inkjs/ui": "^2.0.0",
21891
- "@tanstack/react-query": "^5.100.14",
21892
- chalk: "^5.3.0",
21893
- commander: "^14.0.2",
21894
- ink: "^7",
21895
- "ink-text-input": "^6.0.0",
21896
- jose: "^5.9.6",
21897
- marked: "^15.0.12",
21898
- react: "^19",
21899
- "socket.io-client": "^4.8.3",
21900
- yaml: "^2.9.0"
21901
- },
21902
- devDependencies: {
21903
- "@auto/protocol": "*",
21904
- "@auto/schemas": "*",
21905
- "@types/react": "^19",
21906
- tsup: "^8.5.1"
21907
- }
21908
- };
21909
- }
21910
- });
21911
-
21912
- // src/cli/version.ts
21913
- var cliVersion;
21914
- var init_version = __esm({
21915
- "src/cli/version.ts"() {
21916
- "use strict";
21917
- init_package();
21918
- cliVersion = package_default.version;
21919
- }
21920
- });
21921
-
21922
22090
  // src/tui/ApiClientContext.ts
21923
22091
  import { createContext, useContext } from "react";
21924
22092
  function useApiClient() {
@@ -27267,7 +27435,17 @@ var RuntimeBridgeBootstrapEnvelopeSchema = external_exports.object({
27267
27435
  var RuntimeBridgeBootstrapAckSchema = external_exports.object({
27268
27436
  status: external_exports.enum(["ready", "failed"]),
27269
27437
  error: external_exports.string().trim().min(1).optional(),
27270
- at: external_exports.string().datetime()
27438
+ at: external_exports.string().datetime(),
27439
+ // The sandbox-baked CLI's own release version (e.g. "0.1.95"), so the
27440
+ // bridge can tag bootstrap observability with the runtime version that is
27441
+ // actually live. Optional because runtimes older than the field predate
27442
+ // reporting it; the bridge logs those as "unknown" instead of failing.
27443
+ cliVersion: external_exports.string().trim().min(1).optional(),
27444
+ // Top-level bootstrap plaintext fields the runtime's tolerant parse
27445
+ // stripped because its schema does not know them yet (worker-ahead skew).
27446
+ // Reported so the bridge can log the degradation instead of it staying
27447
+ // silent.
27448
+ ignoredBootstrapKeys: external_exports.array(external_exports.string().trim().min(1)).optional()
27271
27449
  });
27272
27450
  var RuntimeBridgeConnectedPayloadSchema = external_exports.object({
27273
27451
  runId: SessionRunIdSchema,
@@ -27383,6 +27561,7 @@ function now() {
27383
27561
  }
27384
27562
 
27385
27563
  // ../../packages/protocol/src/bootstrap-crypto.ts
27564
+ init_zod();
27386
27565
  import {
27387
27566
  createCipheriv,
27388
27567
  createDecipheriv,
@@ -27412,7 +27591,16 @@ function decryptRuntimeBridgeBootstrap(input) {
27412
27591
  decipher.update(Buffer.from(envelope.bootstrap.ciphertext, "base64")),
27413
27592
  decipher.final()
27414
27593
  ]).toString("utf8");
27415
- return RuntimeBridgeBootstrapPlaintextSchema.parse(JSON.parse(plaintext));
27594
+ const raw = JSON.parse(plaintext);
27595
+ const bootstrap = RuntimeBridgeBootstrapPlaintextSchema.parse(raw);
27596
+ return { bootstrap, ignoredKeys: ignoredPlaintextKeys(raw) };
27597
+ }
27598
+ function ignoredPlaintextKeys(raw) {
27599
+ const record2 = external_exports.record(external_exports.string(), external_exports.unknown()).parse(raw);
27600
+ const knownKeys = new Set(
27601
+ Object.keys(RuntimeBridgeBootstrapPlaintextSchema.shape)
27602
+ );
27603
+ return Object.keys(record2).filter((key) => !knownKeys.has(key));
27416
27604
  }
27417
27605
  function deriveBootstrapKey(accessToken, salt) {
27418
27606
  return Buffer.from(
@@ -27433,6 +27621,7 @@ function bootstrapAdditionalData(input) {
27433
27621
  }
27434
27622
 
27435
27623
  // src/commands/agent-bridge/socket.ts
27624
+ init_version();
27436
27625
  import { io } from "socket.io-client";
27437
27626
  async function runAgentBridgeSocket(options) {
27438
27627
  const socket = io(`${options.bridgeUrl}${RUNTIME_BRIDGE_NAMESPACE}`, {
@@ -27568,13 +27757,18 @@ function createRuntimeBridgeBootstrapListener(input) {
27568
27757
  bridgeLeaseId: envelope.bridgeLeaseId
27569
27758
  });
27570
27759
  const decryptStartedAt = Date.now();
27571
- const bootstrap = decryptRuntimeBridgeBootstrap({
27760
+ const { bootstrap, ignoredKeys } = decryptRuntimeBridgeBootstrap({
27572
27761
  accessToken: input.token,
27573
27762
  envelope
27574
27763
  });
27575
27764
  input.writeOutput?.(
27576
27765
  `agent_bridge_bootstrap_decrypted duration_ms=${Date.now() - decryptStartedAt}`
27577
27766
  );
27767
+ if (ignoredKeys.length > 0) {
27768
+ input.writeOutput?.(
27769
+ `agent_bridge_bootstrap_ignored_keys cli_version=${cliVersion} keys=${ignoredKeys.join(",")}`
27770
+ );
27771
+ }
27578
27772
  await input.onBootstrap?.(bootstrap);
27579
27773
  let handler = input.getHandler();
27580
27774
  if (!handler) {
@@ -27590,7 +27784,9 @@ function createRuntimeBridgeBootstrapListener(input) {
27590
27784
  ack?.(
27591
27785
  RuntimeBridgeBootstrapAckSchema.parse({
27592
27786
  status: "ready",
27593
- at: (/* @__PURE__ */ new Date()).toISOString()
27787
+ at: (/* @__PURE__ */ new Date()).toISOString(),
27788
+ cliVersion,
27789
+ ignoredBootstrapKeys: ignoredKeys.length > 0 ? ignoredKeys : void 0
27594
27790
  })
27595
27791
  );
27596
27792
  prepare?.then(
@@ -27616,7 +27812,10 @@ function createRuntimeBridgeBootstrapListener(input) {
27616
27812
  RuntimeBridgeBootstrapAckSchema.parse({
27617
27813
  status: "failed",
27618
27814
  error: message,
27619
- at: (/* @__PURE__ */ new Date()).toISOString()
27815
+ at: (/* @__PURE__ */ new Date()).toISOString(),
27816
+ // Version skew is a leading cause of bootstrap failure, so failed
27817
+ // acks carry the version that could not bootstrap.
27818
+ cliVersion
27620
27819
  })
27621
27820
  );
27622
27821
  input.onBootstrapError(error51);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.103",
3
+ "version": "0.1.105",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"