@autohq/cli 0.1.104 → 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.
@@ -21848,6 +21848,14 @@ var ProjectApplyAssetsSchema = external_exports.record(
21848
21848
  }),
21849
21849
  ProjectApplyAssetSchema
21850
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
+ });
21851
21859
  var ProjectApplyRequestSchema = external_exports.object({
21852
21860
  delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
21853
21861
  dryRun: external_exports.boolean().default(false),
@@ -26183,7 +26191,7 @@ Object.assign(lookup, {
26183
26191
  // package.json
26184
26192
  var package_default = {
26185
26193
  name: "@autohq/cli",
26186
- version: "0.1.104",
26194
+ version: "0.1.105",
26187
26195
  license: "SEE LICENSE IN README.md",
26188
26196
  publishConfig: {
26189
26197
  access: "public"
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),
@@ -18489,7 +18497,7 @@ var init_package = __esm({
18489
18497
  "package.json"() {
18490
18498
  package_default = {
18491
18499
  name: "@autohq/cli",
18492
- version: "0.1.104",
18500
+ version: "0.1.105",
18493
18501
  license: "SEE LICENSE IN README.md",
18494
18502
  publishConfig: {
18495
18503
  access: "public"
@@ -18920,6 +18928,8 @@ function createResourceApi(context) {
18920
18928
  });
18921
18929
  return {
18922
18930
  applyEnvironmentResource: environments.apply,
18931
+ hasAvatarAsset: (request, options) => hasAvatarAsset(context, request, options ?? {}),
18932
+ uploadAvatarAsset: (request, options) => uploadAvatarAsset(context, request, options ?? {}),
18923
18933
  applyProjectResources: (request, options) => applyProjectResources(
18924
18934
  context,
18925
18935
  request,
@@ -18945,6 +18955,58 @@ function createResourceApi(context) {
18945
18955
  updateProjectServiceAccount: (request, options) => updateProjectServiceAccount(context, request, options ?? {})
18946
18956
  };
18947
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
+ }
18948
19010
  async function listProjectServiceAccounts(context, options) {
18949
19011
  const project = await context.activeProject();
18950
19012
  const response = await context.authenticatedFetch(
@@ -19249,13 +19311,15 @@ async function listProjectResources(context, endpoint, options) {
19249
19311
  }
19250
19312
  return await response.json();
19251
19313
  }
19252
- var SlackConfigTokenRequiredError;
19314
+ var AvatarAssetUploadUnsupportedError, SlackConfigTokenRequiredError;
19253
19315
  var init_resources2 = __esm({
19254
19316
  "src/lib/api/resources.ts"() {
19255
19317
  "use strict";
19256
19318
  init_src();
19257
19319
  init_errors3();
19258
19320
  init_paths();
19321
+ AvatarAssetUploadUnsupportedError = class extends Error {
19322
+ };
19259
19323
  SlackConfigTokenRequiredError = class extends Error {
19260
19324
  workspace;
19261
19325
  constructor(message, workspace) {
@@ -20935,6 +20999,98 @@ var init_connect = __esm({
20935
20999
  }
20936
21000
  });
20937
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
+
20938
21094
  // src/commands/apply/files.ts
20939
21095
  import { createHash as createHash2 } from "crypto";
20940
21096
  import {
@@ -21279,16 +21435,27 @@ async function applyResource(input) {
21279
21435
  }
21280
21436
  async function applyProjectInput(input) {
21281
21437
  const style = input.style ?? plainStyle;
21282
- const response = await input.client.applyProjectResources(
21283
- {
21284
- ...input.request.delete.length > 0 ? { delete: input.request.delete } : {},
21285
- dryRun: input.commandOptions.dryRun ?? input.request.dryRun,
21286
- prune: input.commandOptions.prune ?? input.request.prune,
21287
- resources: input.request.resources,
21288
- ...Object.keys(input.request.assets).length > 0 ? { assets: input.request.assets } : {}
21289
- },
21290
- { apiBaseUrl: input.commandOptions.apiBaseUrl }
21291
- );
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
+ });
21292
21459
  const resources = response.resources.map((resource, index) => ({
21293
21460
  kind: appliedResourceKind(input.request, response, index),
21294
21461
  resource
@@ -21391,6 +21558,7 @@ var init_actions = __esm({
21391
21558
  "use strict";
21392
21559
  init_style();
21393
21560
  init_connect();
21561
+ init_assets();
21394
21562
  init_files();
21395
21563
  }
21396
21564
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.104",
3
+ "version": "0.1.105",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"