@autohq/cli 0.1.165 → 0.1.167

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.
@@ -22067,6 +22067,12 @@ var PROJECT_APPLY_RESOURCE_KINDS = [
22067
22067
  RESOURCE_KIND_ENVIRONMENT,
22068
22068
  RESOURCE_KIND_AGENT
22069
22069
  ];
22070
+ var PROJECT_APPLY_BUNDLE_VERSION = 1;
22071
+ var MAX_PROJECT_APPLY_BUNDLE_BYTES = 64 * 1024 * 1024;
22072
+ var PROJECT_APPLY_BUNDLE_CONTENT_TYPE = "application/vnd.auto.project-apply-bundle+json";
22073
+ function projectApplyBundleStorageKey(sha256) {
22074
+ return `project-apply-bundles/${sha256}.json`;
22075
+ }
22070
22076
  var ProjectDeleteResourceBaseSchema = external_exports.object({
22071
22077
  name: external_exports.string().trim().min(1)
22072
22078
  });
@@ -22086,14 +22092,72 @@ var ProjectApplyAssetsSchema = external_exports.record(
22086
22092
  }),
22087
22093
  ProjectApplyAssetSchema
22088
22094
  );
22089
- var AvatarAssetUploadRequestSchema = ProjectApplyAssetSchema.omit({
22090
- sha256: true
22091
- });
22092
22095
  var AvatarAssetUploadResponseSchema = external_exports.object({
22093
22096
  sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
22094
22097
  contentType: external_exports.enum(AVATAR_ASSET_CONTENT_TYPES),
22095
22098
  sizeBytes: external_exports.number().int().positive()
22096
22099
  });
22100
+ var ApplyBundlePathSchema = external_exports.string().trim().min(1).max(4096).refine((path2) => !path2.startsWith("/") && !path2.includes("\0"), {
22101
+ message: "apply bundle paths must be relative paths"
22102
+ });
22103
+ var ProjectApplyBundleFileSchema = external_exports.object({
22104
+ path: ApplyBundlePathSchema,
22105
+ contentBase64: external_exports.string().regex(/^[A-Za-z0-9+/]*={0,2}$/)
22106
+ });
22107
+ var ProjectApplyBundleSchema = external_exports.object({
22108
+ version: external_exports.literal(PROJECT_APPLY_BUNDLE_VERSION),
22109
+ files: external_exports.array(ProjectApplyBundleFileSchema).max(2e4)
22110
+ });
22111
+ var ProjectApplyBundleRefSchema = external_exports.object({
22112
+ kind: external_exports.literal("vercel_blob"),
22113
+ storageKey: external_exports.string().trim().min(1).max(1024),
22114
+ sha256: external_exports.string().regex(SHA256_HEX_PATTERN),
22115
+ sizeBytes: external_exports.number().int().positive().max(MAX_PROJECT_APPLY_BUNDLE_BYTES)
22116
+ }).superRefine((ref, context) => {
22117
+ const expectedStorageKey = projectApplyBundleStorageKey(ref.sha256);
22118
+ if (ref.storageKey === expectedStorageKey) {
22119
+ return;
22120
+ }
22121
+ context.addIssue({
22122
+ code: "custom",
22123
+ path: ["storageKey"],
22124
+ message: "apply bundle storage key must match its sha256"
22125
+ });
22126
+ });
22127
+ var ProjectApplyBundleUploadRequestSchema = external_exports.object({
22128
+ sha256: external_exports.string().regex(SHA256_HEX_PATTERN),
22129
+ sizeBytes: external_exports.number().int().positive().max(MAX_PROJECT_APPLY_BUNDLE_BYTES)
22130
+ });
22131
+ var ProjectApplyBundleUploadResponseSchema = external_exports.object({
22132
+ method: external_exports.literal("PUT"),
22133
+ uploadUrl: external_exports.string().url(),
22134
+ contentType: external_exports.literal(PROJECT_APPLY_BUNDLE_CONTENT_TYPE),
22135
+ source: ProjectApplyBundleRefSchema
22136
+ });
22137
+ var ProjectApplyBundleDirectoryEntrypointSchema = external_exports.object({
22138
+ kind: external_exports.literal("directory"),
22139
+ resourceRoot: ApplyBundlePathSchema.default(".auto"),
22140
+ displayResourceRoot: external_exports.string().trim().min(1).max(4096).optional()
22141
+ });
22142
+ var ProjectApplyBundleFileEntrypointSchema = external_exports.object({
22143
+ kind: external_exports.literal("file"),
22144
+ filePath: ApplyBundlePathSchema
22145
+ });
22146
+ var ProjectApplyBundleEntrypointSchema = external_exports.discriminatedUnion("kind", [
22147
+ ProjectApplyBundleDirectoryEntrypointSchema,
22148
+ ProjectApplyBundleFileEntrypointSchema
22149
+ ]);
22150
+ var ProjectApplySourceSchema = external_exports.object({
22151
+ kind: external_exports.literal("bundle"),
22152
+ bundle: ProjectApplyBundleRefSchema,
22153
+ entrypoint: ProjectApplyBundleEntrypointSchema
22154
+ });
22155
+ var ProjectApplySourceRequestSchema = external_exports.object({
22156
+ source: ProjectApplySourceSchema,
22157
+ delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
22158
+ dryRun: external_exports.boolean().default(false),
22159
+ prune: external_exports.boolean().default(true)
22160
+ });
22097
22161
  var ProjectApplyRequestSchema = external_exports.object({
22098
22162
  delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
22099
22163
  dryRun: external_exports.boolean().default(false),
@@ -22177,11 +22241,20 @@ var ProjectResourceApplyWorkflowErrorSchema = external_exports.object({
22177
22241
  });
22178
22242
  var ProjectResourceApplyWorkflowInputSchema = external_exports.object({
22179
22243
  operationId: ProjectResourceApplyOperationIdSchema,
22180
- request: ProjectApplyRequestSchema,
22244
+ request: ProjectApplyRequestSchema.optional(),
22245
+ sourceRequest: ProjectApplySourceRequestSchema.optional(),
22181
22246
  organizationId: OrganizationIdSchema,
22182
22247
  projectId: ProjectIdSchema.nullable().optional(),
22183
22248
  actor: AuthActorSchema,
22184
22249
  auditAction: ProjectResourceApplyAuditActionSchema
22250
+ }).superRefine((input, context) => {
22251
+ if ((input.request ? 1 : 0) + (input.sourceRequest ? 1 : 0) !== 1) {
22252
+ context.addIssue({
22253
+ code: "custom",
22254
+ path: ["request"],
22255
+ message: "exactly one of request or sourceRequest is required"
22256
+ });
22257
+ }
22185
22258
  });
22186
22259
  var ProjectResourceApplyWorkflowResultSchema = external_exports.discriminatedUnion(
22187
22260
  "status",
@@ -22806,6 +22879,21 @@ var SetupOnboardingPullRequestSchema = external_exports.object({
22806
22879
  var SetupOnboardingPullRequestCreateResponseSchema = external_exports.object({
22807
22880
  pullRequest: SetupOnboardingPullRequestSchema
22808
22881
  });
22882
+ var SetupOnboardingPullRequestStatusRequestSchema = external_exports.object({
22883
+ githubConnection: external_exports.string().trim().min(1).optional(),
22884
+ repo: GithubSyncRepositoryFullNameSchema,
22885
+ pullRequestNumber: external_exports.coerce.number().int().positive()
22886
+ });
22887
+ var SetupOnboardingPullRequestStatusResponseSchema = external_exports.object({
22888
+ pullRequest: external_exports.object({
22889
+ merged: external_exports.boolean(),
22890
+ state: external_exports.string().trim().min(1)
22891
+ }),
22892
+ apply: external_exports.object({
22893
+ applied: external_exports.boolean()
22894
+ }),
22895
+ ready: external_exports.boolean()
22896
+ });
22809
22897
 
22810
22898
  // ../../packages/schemas/src/runtimes.ts
22811
22899
  var RuntimeRecordSchema = external_exports.object({
@@ -26467,7 +26555,7 @@ Object.assign(lookup, {
26467
26555
  // package.json
26468
26556
  var package_default = {
26469
26557
  name: "@autohq/cli",
26470
- version: "0.1.165",
26558
+ version: "0.1.167",
26471
26559
  license: "SEE LICENSE IN README.md",
26472
26560
  publishConfig: {
26473
26561
  access: "public"
package/dist/index.js CHANGED
@@ -18762,7 +18762,10 @@ var init_project_service_accounts = __esm({
18762
18762
  });
18763
18763
 
18764
18764
  // ../../packages/schemas/src/project-resources.ts
18765
- var EnvironmentApplyDocumentSchema, IdentityApplyDocumentSchema, AgentApplyDocumentSchema, ProjectApplyResourceSchema, PROJECT_RESOURCE_APPLY_ORDER, PROJECT_RESOURCE_KINDS, PROJECT_APPLY_RESOURCE_KINDS, ProjectDeleteResourceBaseSchema, ProjectDeleteResourceSchema, AVATAR_ASSET_CONTENT_TYPES, MAX_AVATAR_ASSET_BASE64_LENGTH, ProjectApplyAssetSchema, ProjectApplyAssetsSchema, AvatarAssetUploadRequestSchema, AvatarAssetUploadResponseSchema, ProjectApplyRequestSchema, ProjectApplySystemConfigSchema, ProjectAppliedResourceSchema, ProjectApplyDiagnosticSchema, ProjectApplyResponsePrunedSchema, ProjectApplyPlanDiffSchema, ProjectApplyResponseSchema, ProjectResourceApplyResultSchema, ProjectResourceApplyAuditActionSchema, ProjectResourceApplyOperationIdSchema, ProjectResourceApplyWorkflowErrorSchema, ProjectResourceApplyWorkflowInputSchema, ProjectResourceApplyWorkflowResultSchema;
18765
+ function projectApplyBundleStorageKey(sha256) {
18766
+ return `project-apply-bundles/${sha256}.json`;
18767
+ }
18768
+ var EnvironmentApplyDocumentSchema, IdentityApplyDocumentSchema, AgentApplyDocumentSchema, ProjectApplyResourceSchema, PROJECT_RESOURCE_APPLY_ORDER, PROJECT_RESOURCE_KINDS, PROJECT_APPLY_RESOURCE_KINDS, PROJECT_APPLY_BUNDLE_VERSION, MAX_PROJECT_APPLY_BUNDLE_BYTES, PROJECT_APPLY_BUNDLE_CONTENT_TYPE, ProjectDeleteResourceBaseSchema, ProjectDeleteResourceSchema, AVATAR_ASSET_CONTENT_TYPES, MAX_AVATAR_ASSET_BASE64_LENGTH, ProjectApplyAssetSchema, ProjectApplyAssetsSchema, AvatarAssetUploadResponseSchema, ApplyBundlePathSchema, ProjectApplyBundleFileSchema, ProjectApplyBundleSchema, ProjectApplyBundleRefSchema, ProjectApplyBundleUploadRequestSchema, ProjectApplyBundleUploadResponseSchema, ProjectApplyBundleDirectoryEntrypointSchema, ProjectApplyBundleFileEntrypointSchema, ProjectApplyBundleEntrypointSchema, ProjectApplySourceSchema, ProjectApplySourceRequestSchema, ProjectApplyRequestSchema, ProjectApplySystemConfigSchema, ProjectAppliedResourceSchema, ProjectApplyDiagnosticSchema, ProjectApplyResponsePrunedSchema, ProjectApplyPlanDiffSchema, ProjectApplyResponseSchema, ProjectResourceApplyResultSchema, ProjectResourceApplyAuditActionSchema, ProjectResourceApplyOperationIdSchema, ProjectResourceApplyWorkflowErrorSchema, ProjectResourceApplyWorkflowInputSchema, ProjectResourceApplyWorkflowResultSchema;
18766
18769
  var init_project_resources = __esm({
18767
18770
  "../../packages/schemas/src/project-resources.ts"() {
18768
18771
  "use strict";
@@ -18804,6 +18807,9 @@ var init_project_resources = __esm({
18804
18807
  RESOURCE_KIND_ENVIRONMENT,
18805
18808
  RESOURCE_KIND_AGENT
18806
18809
  ];
18810
+ PROJECT_APPLY_BUNDLE_VERSION = 1;
18811
+ MAX_PROJECT_APPLY_BUNDLE_BYTES = 64 * 1024 * 1024;
18812
+ PROJECT_APPLY_BUNDLE_CONTENT_TYPE = "application/vnd.auto.project-apply-bundle+json";
18807
18813
  ProjectDeleteResourceBaseSchema = external_exports.object({
18808
18814
  name: external_exports.string().trim().min(1)
18809
18815
  });
@@ -18823,14 +18829,72 @@ var init_project_resources = __esm({
18823
18829
  }),
18824
18830
  ProjectApplyAssetSchema
18825
18831
  );
18826
- AvatarAssetUploadRequestSchema = ProjectApplyAssetSchema.omit({
18827
- sha256: true
18828
- });
18829
18832
  AvatarAssetUploadResponseSchema = external_exports.object({
18830
18833
  sha256: external_exports.string().regex(/^[a-f0-9]{64}$/),
18831
18834
  contentType: external_exports.enum(AVATAR_ASSET_CONTENT_TYPES),
18832
18835
  sizeBytes: external_exports.number().int().positive()
18833
18836
  });
18837
+ ApplyBundlePathSchema = external_exports.string().trim().min(1).max(4096).refine((path2) => !path2.startsWith("/") && !path2.includes("\0"), {
18838
+ message: "apply bundle paths must be relative paths"
18839
+ });
18840
+ ProjectApplyBundleFileSchema = external_exports.object({
18841
+ path: ApplyBundlePathSchema,
18842
+ contentBase64: external_exports.string().regex(/^[A-Za-z0-9+/]*={0,2}$/)
18843
+ });
18844
+ ProjectApplyBundleSchema = external_exports.object({
18845
+ version: external_exports.literal(PROJECT_APPLY_BUNDLE_VERSION),
18846
+ files: external_exports.array(ProjectApplyBundleFileSchema).max(2e4)
18847
+ });
18848
+ ProjectApplyBundleRefSchema = external_exports.object({
18849
+ kind: external_exports.literal("vercel_blob"),
18850
+ storageKey: external_exports.string().trim().min(1).max(1024),
18851
+ sha256: external_exports.string().regex(SHA256_HEX_PATTERN),
18852
+ sizeBytes: external_exports.number().int().positive().max(MAX_PROJECT_APPLY_BUNDLE_BYTES)
18853
+ }).superRefine((ref, context) => {
18854
+ const expectedStorageKey = projectApplyBundleStorageKey(ref.sha256);
18855
+ if (ref.storageKey === expectedStorageKey) {
18856
+ return;
18857
+ }
18858
+ context.addIssue({
18859
+ code: "custom",
18860
+ path: ["storageKey"],
18861
+ message: "apply bundle storage key must match its sha256"
18862
+ });
18863
+ });
18864
+ ProjectApplyBundleUploadRequestSchema = external_exports.object({
18865
+ sha256: external_exports.string().regex(SHA256_HEX_PATTERN),
18866
+ sizeBytes: external_exports.number().int().positive().max(MAX_PROJECT_APPLY_BUNDLE_BYTES)
18867
+ });
18868
+ ProjectApplyBundleUploadResponseSchema = external_exports.object({
18869
+ method: external_exports.literal("PUT"),
18870
+ uploadUrl: external_exports.string().url(),
18871
+ contentType: external_exports.literal(PROJECT_APPLY_BUNDLE_CONTENT_TYPE),
18872
+ source: ProjectApplyBundleRefSchema
18873
+ });
18874
+ ProjectApplyBundleDirectoryEntrypointSchema = external_exports.object({
18875
+ kind: external_exports.literal("directory"),
18876
+ resourceRoot: ApplyBundlePathSchema.default(".auto"),
18877
+ displayResourceRoot: external_exports.string().trim().min(1).max(4096).optional()
18878
+ });
18879
+ ProjectApplyBundleFileEntrypointSchema = external_exports.object({
18880
+ kind: external_exports.literal("file"),
18881
+ filePath: ApplyBundlePathSchema
18882
+ });
18883
+ ProjectApplyBundleEntrypointSchema = external_exports.discriminatedUnion("kind", [
18884
+ ProjectApplyBundleDirectoryEntrypointSchema,
18885
+ ProjectApplyBundleFileEntrypointSchema
18886
+ ]);
18887
+ ProjectApplySourceSchema = external_exports.object({
18888
+ kind: external_exports.literal("bundle"),
18889
+ bundle: ProjectApplyBundleRefSchema,
18890
+ entrypoint: ProjectApplyBundleEntrypointSchema
18891
+ });
18892
+ ProjectApplySourceRequestSchema = external_exports.object({
18893
+ source: ProjectApplySourceSchema,
18894
+ delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
18895
+ dryRun: external_exports.boolean().default(false),
18896
+ prune: external_exports.boolean().default(true)
18897
+ });
18834
18898
  ProjectApplyRequestSchema = external_exports.object({
18835
18899
  delete: external_exports.array(ProjectDeleteResourceSchema).default([]),
18836
18900
  dryRun: external_exports.boolean().default(false),
@@ -18914,11 +18978,20 @@ var init_project_resources = __esm({
18914
18978
  });
18915
18979
  ProjectResourceApplyWorkflowInputSchema = external_exports.object({
18916
18980
  operationId: ProjectResourceApplyOperationIdSchema,
18917
- request: ProjectApplyRequestSchema,
18981
+ request: ProjectApplyRequestSchema.optional(),
18982
+ sourceRequest: ProjectApplySourceRequestSchema.optional(),
18918
18983
  organizationId: OrganizationIdSchema,
18919
18984
  projectId: ProjectIdSchema.nullable().optional(),
18920
18985
  actor: AuthActorSchema,
18921
18986
  auditAction: ProjectResourceApplyAuditActionSchema
18987
+ }).superRefine((input, context) => {
18988
+ if ((input.request ? 1 : 0) + (input.sourceRequest ? 1 : 0) !== 1) {
18989
+ context.addIssue({
18990
+ code: "custom",
18991
+ path: ["request"],
18992
+ message: "exactly one of request or sourceRequest is required"
18993
+ });
18994
+ }
18922
18995
  });
18923
18996
  ProjectResourceApplyWorkflowResultSchema = external_exports.discriminatedUnion(
18924
18997
  "status",
@@ -19589,7 +19662,7 @@ var init_session_commands = __esm({
19589
19662
  });
19590
19663
 
19591
19664
  // ../../packages/schemas/src/setup.ts
19592
- var SetupOnboardingPullRequestCreateRequestSchema, SetupOnboardingPullRequestSchema, SetupOnboardingPullRequestCreateResponseSchema;
19665
+ var SetupOnboardingPullRequestCreateRequestSchema, SetupOnboardingPullRequestSchema, SetupOnboardingPullRequestCreateResponseSchema, SetupOnboardingPullRequestStatusRequestSchema, SetupOnboardingPullRequestStatusResponseSchema;
19593
19666
  var init_setup = __esm({
19594
19667
  "../../packages/schemas/src/setup.ts"() {
19595
19668
  "use strict";
@@ -19611,6 +19684,21 @@ var init_setup = __esm({
19611
19684
  SetupOnboardingPullRequestCreateResponseSchema = external_exports.object({
19612
19685
  pullRequest: SetupOnboardingPullRequestSchema
19613
19686
  });
19687
+ SetupOnboardingPullRequestStatusRequestSchema = external_exports.object({
19688
+ githubConnection: external_exports.string().trim().min(1).optional(),
19689
+ repo: GithubSyncRepositoryFullNameSchema,
19690
+ pullRequestNumber: external_exports.coerce.number().int().positive()
19691
+ });
19692
+ SetupOnboardingPullRequestStatusResponseSchema = external_exports.object({
19693
+ pullRequest: external_exports.object({
19694
+ merged: external_exports.boolean(),
19695
+ state: external_exports.string().trim().min(1)
19696
+ }),
19697
+ apply: external_exports.object({
19698
+ applied: external_exports.boolean()
19699
+ }),
19700
+ ready: external_exports.boolean()
19701
+ });
19614
19702
  }
19615
19703
  });
19616
19704
 
@@ -19871,6 +19959,7 @@ var init_paths = __esm({
19871
19959
  });
19872
19960
 
19873
19961
  // src/lib/api/resources.ts
19962
+ import { createHash as createHash3 } from "crypto";
19874
19963
  function createResourceApi(context) {
19875
19964
  const environments = projectResource(context, {
19876
19965
  path: "/environments",
@@ -19889,8 +19978,8 @@ function createResourceApi(context) {
19889
19978
  );
19890
19979
  return {
19891
19980
  applyEnvironmentResource: environments.apply,
19892
- hasAvatarAsset: (request, options) => hasAvatarAsset(context, request, options ?? {}),
19893
- uploadAvatarAsset: (request, options) => uploadAvatarAsset(context, request, options ?? {}),
19981
+ prepareProjectApplyBundleUpload: (request, options) => prepareProjectApplyBundleUpload(context, request, options ?? {}),
19982
+ uploadProjectApplyBundle: (request) => uploadProjectApplyBundle(context, request),
19894
19983
  applyProjectResources: (request, options) => applyProjectResources(
19895
19984
  context,
19896
19985
  request,
@@ -19913,54 +20002,59 @@ function createResourceApi(context) {
19913
20002
  updateProjectServiceAccount: (request, options) => updateProjectServiceAccount(context, request, options ?? {})
19914
20003
  };
19915
20004
  }
19916
- async function hasAvatarAsset(context, request, options) {
19917
- const response = await context.authenticatedFetch(
19918
- context.apiUrl(
19919
- apiPath(`/avatars/${encodeURIComponent(request.sha256)}`),
19920
- options.apiBaseUrl
19921
- ),
19922
- { method: "HEAD" },
19923
- options.apiBaseUrl
19924
- );
19925
- if (response.ok) {
19926
- return true;
19927
- }
19928
- if (response.status === 404) {
19929
- return false;
19930
- }
19931
- throw new Error(await responseErrorMessage(response));
19932
- }
19933
- async function uploadAvatarAsset(context, request, options) {
19934
- const path2 = await avatarAssetUploadPath(context, request.sha256);
20005
+ async function prepareProjectApplyBundleUpload(context, request, options) {
20006
+ const path2 = await projectApplyBundleUploadPath(context);
19935
20007
  const response = await context.authenticatedFetch(
19936
20008
  context.apiUrl(path2, options.apiBaseUrl),
19937
20009
  {
19938
- method: "PUT",
20010
+ method: "POST",
19939
20011
  headers: { "content-type": "application/json" },
19940
- body: JSON.stringify({
19941
- contentType: request.contentType,
19942
- dataBase64: request.dataBase64
19943
- })
20012
+ body: JSON.stringify(request)
19944
20013
  },
19945
20014
  options.apiBaseUrl
19946
20015
  );
19947
- if (response.status === 404) {
19948
- throw new AvatarAssetUploadUnsupportedError(
19949
- await responseErrorMessage(response)
19950
- );
19951
- }
19952
20016
  if (!response.ok) {
19953
20017
  throw new Error(await responseErrorMessage(response));
19954
20018
  }
19955
- return AvatarAssetUploadResponseSchema.parse(await response.json());
20019
+ return ProjectApplyBundleUploadResponseSchema.parse(await response.json());
20020
+ }
20021
+ async function stageEmptyApplyBundle(context, options) {
20022
+ const body = JSON.stringify({
20023
+ version: PROJECT_APPLY_BUNDLE_VERSION,
20024
+ files: []
20025
+ });
20026
+ const sizeBytes = Buffer.byteLength(body, "utf8");
20027
+ const upload = await prepareProjectApplyBundleUpload(
20028
+ context,
20029
+ { sha256: createHash3("sha256").update(body).digest("hex"), sizeBytes },
20030
+ options
20031
+ );
20032
+ await uploadProjectApplyBundle(context, {
20033
+ uploadUrl: upload.uploadUrl,
20034
+ method: upload.method,
20035
+ contentType: upload.contentType,
20036
+ body
20037
+ });
20038
+ return upload.source;
20039
+ }
20040
+ async function uploadProjectApplyBundle(context, request) {
20041
+ const response = await context.fetch(request.uploadUrl, {
20042
+ method: request.method,
20043
+ headers: { "content-type": request.contentType },
20044
+ body: request.body
20045
+ });
20046
+ if (!response.ok) {
20047
+ throw new Error(
20048
+ `Project apply bundle upload failed with ${response.status}: ${await response.text()}`
20049
+ );
20050
+ }
19956
20051
  }
19957
- async function avatarAssetUploadPath(context, sha256) {
19958
- const subpath = `/avatar-assets/${encodeURIComponent(sha256)}`;
20052
+ async function projectApplyBundleUploadPath(context) {
19959
20053
  try {
19960
- return projectApiPath(await context.activeProject(), subpath);
20054
+ return projectApiPath(await context.activeProject(), "/apply-bundles");
19961
20055
  } catch (error51) {
19962
20056
  if (context.shouldTryProjectInferredAuth()) {
19963
- return apiPath(`/project${subpath}`);
20057
+ return apiPath("/project/apply-bundles");
19964
20058
  }
19965
20059
  throw error51;
19966
20060
  }
@@ -20181,12 +20275,18 @@ async function removeProjectServiceAccount(context, request, options) {
20181
20275
  return ProjectServiceAccountRemoveResponseSchema.parse(await response.json());
20182
20276
  }
20183
20277
  async function deleteProjectResource(context, request, options) {
20278
+ const bundle = await stageEmptyApplyBundle(context, options);
20184
20279
  const response = await applyProjectResources(
20185
20280
  context,
20186
20281
  {
20282
+ source: {
20283
+ kind: "bundle",
20284
+ bundle,
20285
+ entrypoint: { kind: "directory", resourceRoot: ".auto" }
20286
+ },
20187
20287
  delete: [request],
20188
- prune: false,
20189
- resources: []
20288
+ dryRun: false,
20289
+ prune: false
20190
20290
  },
20191
20291
  options
20192
20292
  );
@@ -20269,15 +20369,13 @@ async function listProjectResources(context, endpoint, options) {
20269
20369
  }
20270
20370
  return await response.json();
20271
20371
  }
20272
- var AvatarAssetUploadUnsupportedError, SlackConfigTokenRequiredError;
20372
+ var SlackConfigTokenRequiredError;
20273
20373
  var init_resources2 = __esm({
20274
20374
  "src/lib/api/resources.ts"() {
20275
20375
  "use strict";
20276
20376
  init_src();
20277
20377
  init_errors3();
20278
20378
  init_paths();
20279
- AvatarAssetUploadUnsupportedError = class extends Error {
20280
- };
20281
20379
  SlackConfigTokenRequiredError = class extends Error {
20282
20380
  workspace;
20283
20381
  constructor(message, workspace) {
@@ -21005,10 +21103,28 @@ function createApiClient(input) {
21005
21103
  }
21006
21104
  );
21007
21105
  },
21106
+ async getSetupOnboardingPullRequestStatus(request, options = {}) {
21107
+ const project = await activeProject();
21108
+ const searchParams = [
21109
+ ["repo", request.repo],
21110
+ ["pullRequestNumber", String(request.pullRequestNumber)]
21111
+ ];
21112
+ if (request.githubConnection) {
21113
+ searchParams.push(["githubConnection", request.githubConnection]);
21114
+ }
21115
+ return requestJson(
21116
+ projectApiPath(project, "/setup/onboarding-pr"),
21117
+ {
21118
+ apiBaseUrl: options.apiBaseUrl,
21119
+ searchParams
21120
+ }
21121
+ );
21122
+ },
21008
21123
  ...createResourceApi({
21009
21124
  activeProject,
21010
21125
  apiUrl,
21011
21126
  authenticatedFetch,
21127
+ fetch: input.fetch,
21012
21128
  shouldTryProjectInferredAuth
21013
21129
  }),
21014
21130
  async setSecret(name, request, options = {}) {
@@ -21549,7 +21665,7 @@ var init_package = __esm({
21549
21665
  "package.json"() {
21550
21666
  package_default = {
21551
21667
  name: "@autohq/cli",
21552
- version: "0.1.165",
21668
+ version: "0.1.167",
21553
21669
  license: "SEE LICENSE IN README.md",
21554
21670
  publishConfig: {
21555
21671
  access: "public"
@@ -22393,106 +22509,6 @@ var init_agent_tool_connect = __esm({
22393
22509
  }
22394
22510
  });
22395
22511
 
22396
- // src/commands/apply/assets.ts
22397
- async function resolveApplyAssets(input) {
22398
- const entries = Object.entries(input.request.assets);
22399
- if (entries.length === 0) {
22400
- return { resources: input.request.resources, assets: {} };
22401
- }
22402
- const probes = await Promise.all(
22403
- entries.map(async ([path2, asset]) => ({
22404
- path: path2,
22405
- asset,
22406
- stored: await input.client.hasAvatarAsset(
22407
- { sha256: asset.sha256 },
22408
- { apiBaseUrl: input.apiBaseUrl }
22409
- )
22410
- }))
22411
- );
22412
- const inline2 = {};
22413
- for (const probe of probes) {
22414
- if (probe.stored) {
22415
- continue;
22416
- }
22417
- if (!await uploadAvatarAsset2(input.client, probe.asset, input.apiBaseUrl)) {
22418
- inline2[probe.path] = probe.asset;
22419
- }
22420
- }
22421
- const resources = input.request.resources.map(
22422
- (resource) => stampAvatarSha256(resource, input.request.assets)
22423
- );
22424
- return { resources, assets: inline2 };
22425
- }
22426
- function assertApplyRequestBodySize(input) {
22427
- const bytes = Buffer.byteLength(input.body, "utf8");
22428
- if (bytes <= MAX_APPLY_REQUEST_BODY_BYTES) {
22429
- return;
22430
- }
22431
- const paths = Object.keys(input.assets);
22432
- 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 agents referencing them in smaller batches (auto apply -f <file> --no-prune) or shrink the image files.` : "";
22433
- throw new Error(
22434
- `Apply request body is ${formatMegabytes(bytes)}MB, over the ~4.5MB server request limit.${assetDetail}`
22435
- );
22436
- }
22437
- async function uploadAvatarAsset2(client, asset, apiBaseUrl) {
22438
- try {
22439
- await client.uploadAvatarAsset(asset, { apiBaseUrl });
22440
- return true;
22441
- } catch (error51) {
22442
- if (error51 instanceof AvatarAssetUploadUnsupportedError) {
22443
- return false;
22444
- }
22445
- throw error51;
22446
- }
22447
- }
22448
- function stampAvatarSha256(resource, assets) {
22449
- if (resource.kind === "identity") {
22450
- const avatar = resource.spec.avatar;
22451
- const asset = avatar ? assets[avatar.asset] : void 0;
22452
- if (!avatar || !asset) {
22453
- return resource;
22454
- }
22455
- return {
22456
- ...resource,
22457
- spec: {
22458
- ...resource.spec,
22459
- avatar: { asset: avatar.asset, sha256: asset.sha256 }
22460
- }
22461
- };
22462
- }
22463
- if (resource.kind === RESOURCE_KIND_AGENT && typeof resource.spec.identity === "object" && resource.spec.identity !== null && !Array.isArray(resource.spec.identity)) {
22464
- const identity2 = resource.spec.identity;
22465
- const avatar = identity2.avatar;
22466
- const asset = avatar ? assets[avatar.asset] : void 0;
22467
- if (!avatar || !asset) {
22468
- return resource;
22469
- }
22470
- return {
22471
- ...resource,
22472
- spec: {
22473
- ...resource.spec,
22474
- identity: {
22475
- ...identity2,
22476
- avatar: { asset: avatar.asset, sha256: asset.sha256 }
22477
- }
22478
- }
22479
- };
22480
- }
22481
- return resource;
22482
- }
22483
- function formatMegabytes(bytes) {
22484
- return (bytes / (1024 * 1024)).toFixed(1);
22485
- }
22486
- var MAX_APPLY_REQUEST_BODY_BYTES;
22487
- var init_assets = __esm({
22488
- "src/commands/apply/assets.ts"() {
22489
- "use strict";
22490
- init_src();
22491
- init_resources2();
22492
- MAX_APPLY_REQUEST_BODY_BYTES = 4 * 1024 * 1024;
22493
- }
22494
- });
22495
-
22496
22512
  // ../../packages/schemas/src/project-apply-files/source.ts
22497
22513
  import { parseAllDocuments as parseYamlDocuments2 } from "yaml";
22498
22514
  function readDocumentsFromSource(file2) {
@@ -23334,7 +23350,7 @@ var init_apply_result = __esm({
23334
23350
  });
23335
23351
 
23336
23352
  // ../../packages/schemas/src/project-apply-files/assets.ts
23337
- import { createHash as createHash3 } from "crypto";
23353
+ import { createHash as createHash4 } from "crypto";
23338
23354
  import { extname as extname2 } from "path";
23339
23355
  function readApplyAssets(resources, readAsset) {
23340
23356
  const assets = {};
@@ -23381,7 +23397,7 @@ function projectApplyAssetFromSource(input) {
23381
23397
  );
23382
23398
  }
23383
23399
  return {
23384
- sha256: createHash3("sha256").update(bytes).digest("hex"),
23400
+ sha256: createHash4("sha256").update(bytes).digest("hex"),
23385
23401
  contentType: extension === ".png" ? "image/png" : "image/jpeg",
23386
23402
  dataBase64: bytes.toString("base64")
23387
23403
  };
@@ -23398,7 +23414,7 @@ function avatarAssetTarget(resource) {
23398
23414
  return void 0;
23399
23415
  }
23400
23416
  var ALLOWED_AVATAR_EXTENSIONS;
23401
- var init_assets2 = __esm({
23417
+ var init_assets = __esm({
23402
23418
  "../../packages/schemas/src/project-apply-files/assets.ts"() {
23403
23419
  "use strict";
23404
23420
  init_agents();
@@ -23555,7 +23571,7 @@ var init_project_apply_files = __esm({
23555
23571
  init_project_resources();
23556
23572
  init_agent_authoring();
23557
23573
  init_apply_result();
23558
- init_assets2();
23574
+ init_assets();
23559
23575
  init_source();
23560
23576
  }
23561
23577
  });
@@ -23570,6 +23586,7 @@ var init_project_apply_files2 = __esm({
23570
23586
 
23571
23587
  // src/commands/apply/files.ts
23572
23588
  import {
23589
+ existsSync as existsSync4,
23573
23590
  readFileSync as readFileSync4,
23574
23591
  readdirSync as readdirSync3,
23575
23592
  realpathSync,
@@ -23584,7 +23601,7 @@ import {
23584
23601
  relative,
23585
23602
  resolve as resolve2
23586
23603
  } from "path";
23587
- function readProjectApplyRequest(options) {
23604
+ function readProjectApplyBundleInput(options) {
23588
23605
  if (options.file && options.directory) {
23589
23606
  throw new Error("Cannot use --file with --directory.");
23590
23607
  }
@@ -23592,21 +23609,45 @@ function readProjectApplyRequest(options) {
23592
23609
  const file2 = resolve2(options.file);
23593
23610
  const projectRoot2 = applyFileProjectRoot(file2);
23594
23611
  const sourceRoot = applyFileSourceRoot(file2, projectRoot2);
23595
- return readProjectApplyFileSource({
23612
+ const files2 = sourceFiles(sourceRoot, projectRoot2);
23613
+ const request = readProjectApplyFileSource({
23596
23614
  file: sourceFile(file2, projectRoot2),
23597
- files: sourceFiles(sourceRoot, projectRoot2),
23615
+ files: files2,
23598
23616
  readAsset: filesystemAssetReader(projectRoot2)
23599
23617
  });
23618
+ return {
23619
+ request,
23620
+ bundle: applyBundle(
23621
+ withProjectApplyAssetFiles({ files: files2, request, projectRoot: projectRoot2 })
23622
+ ),
23623
+ entrypoint: {
23624
+ kind: "file",
23625
+ filePath: sourcePathRelative(projectRoot2, file2)
23626
+ }
23627
+ };
23600
23628
  }
23601
23629
  const directory = resolve2(options.directory ?? join5(process.cwd(), ".auto"));
23602
23630
  const projectRoot = applyProjectRoot(directory);
23603
- return readProjectApplyDirectorySource({
23604
- files: sourceFiles(directory, projectRoot),
23605
- resourceRoot: sourcePathRelative(projectRoot, directory),
23606
- displayResourceRoot: displayResourceRoot(directory),
23607
- emptyMessage: `No resource files found in ${directory}`,
23608
- readAsset: filesystemAssetReader(projectRoot)
23609
- });
23631
+ const files = sourceFiles(directory, projectRoot);
23632
+ const resourceRoot = sourcePathRelative(projectRoot, directory);
23633
+ return {
23634
+ request: readProjectApplyDirectorySource({
23635
+ files,
23636
+ resourceRoot,
23637
+ displayResourceRoot: displayResourceRoot(directory),
23638
+ emptyMessage: `No resource files found in ${directory}`,
23639
+ readAsset: filesystemAssetReader(projectRoot)
23640
+ }),
23641
+ bundle: applyBundle(files),
23642
+ entrypoint: {
23643
+ kind: "directory",
23644
+ resourceRoot,
23645
+ displayResourceRoot: displayResourceRoot(directory)
23646
+ }
23647
+ };
23648
+ }
23649
+ function serializeProjectApplyBundle(bundle) {
23650
+ return JSON.stringify(ProjectApplyBundleSchema.parse(bundle));
23610
23651
  }
23611
23652
  function sourceFiles(root, projectRoot) {
23612
23653
  let entries;
@@ -23632,6 +23673,28 @@ function sourceFile(path2, projectRoot) {
23632
23673
  contentBase64: readFileSync4(path2).toString("base64")
23633
23674
  };
23634
23675
  }
23676
+ function applyBundle(files) {
23677
+ return ProjectApplyBundleSchema.parse({
23678
+ version: PROJECT_APPLY_BUNDLE_VERSION,
23679
+ files: [...files].sort(
23680
+ (left, right) => left.path.localeCompare(right.path)
23681
+ )
23682
+ });
23683
+ }
23684
+ function withProjectApplyAssetFiles(input) {
23685
+ const files = [...input.files];
23686
+ const includedPaths = new Set(files.map((file2) => file2.path));
23687
+ for (const assetPath of Object.keys(input.request.assets)) {
23688
+ if (includedPaths.has(assetPath)) {
23689
+ continue;
23690
+ }
23691
+ files.push(
23692
+ sourceFile(resolve2(input.projectRoot, assetPath), input.projectRoot)
23693
+ );
23694
+ includedPaths.add(assetPath);
23695
+ }
23696
+ return files;
23697
+ }
23635
23698
  function filesystemAssetReader(projectRoot) {
23636
23699
  return ({ asset, resourceName }) => {
23637
23700
  const path2 = validateAgentAvatarAsset({
@@ -23655,6 +23718,9 @@ function applyFileProjectRoot(file2) {
23655
23718
  if (basename3(dir) === ".auto") {
23656
23719
  return dirname5(dir);
23657
23720
  }
23721
+ if (directoryHasAutoRoot(dir)) {
23722
+ return dir;
23723
+ }
23658
23724
  const parent = dirname5(dir);
23659
23725
  if (parent === dir) {
23660
23726
  return process.cwd();
@@ -23666,6 +23732,13 @@ function applyFileSourceRoot(file2, projectRoot) {
23666
23732
  const autoRoot = resolve2(projectRoot, ".auto");
23667
23733
  return file2 === autoRoot || isInside(file2, autoRoot) ? autoRoot : dirname5(file2);
23668
23734
  }
23735
+ function directoryHasAutoRoot(directory) {
23736
+ const autoRoot = resolve2(directory, ".auto");
23737
+ if (!existsSync4(autoRoot)) {
23738
+ return false;
23739
+ }
23740
+ return statSync2(autoRoot).isDirectory();
23741
+ }
23669
23742
  function displayResourceRoot(directory) {
23670
23743
  return basename3(directory) === ".auto" ? ".auto" : directory;
23671
23744
  }
@@ -23741,59 +23814,88 @@ var init_files = __esm({
23741
23814
  });
23742
23815
 
23743
23816
  // src/commands/apply/actions.ts
23817
+ import { createHash as createHash5 } from "crypto";
23744
23818
  async function applyResource(input) {
23745
23819
  if (input.commandOptions.connect && input.commandOptions.json) {
23746
23820
  throw new Error("Cannot use --connect with --json output.");
23747
23821
  }
23748
- const request = readProjectApplyRequest(input.commandOptions);
23749
- await applyProjectInput({
23822
+ const bundleInput = readProjectApplyBundleInput(input.commandOptions);
23823
+ const commandOptions = {
23824
+ ...input.commandOptions,
23825
+ prune: input.commandOptions.file ? false : input.commandOptions.prune ?? bundleInput.request.prune
23826
+ };
23827
+ await applyProjectBundleInput({
23828
+ commandOptions,
23829
+ client: input.client,
23830
+ input: bundleInput,
23831
+ writeOutput: input.writeOutput,
23832
+ style: input.style
23833
+ });
23834
+ }
23835
+ async function applyProjectBundleInput(input) {
23836
+ const dryRun = input.commandOptions.dryRun ?? input.input.request.dryRun;
23837
+ const prune = input.commandOptions.prune ?? input.input.request.prune;
23838
+ const body = serializeProjectApplyBundle(input.input.bundle);
23839
+ const sizeBytes = Buffer.byteLength(body, "utf8");
23840
+ if (sizeBytes > MAX_PROJECT_APPLY_BUNDLE_BYTES) {
23841
+ throw new Error(
23842
+ `Project apply bundle is ${formatMegabytes(sizeBytes)}MB, over the ${formatMegabytes(MAX_PROJECT_APPLY_BUNDLE_BYTES)}MB upload limit.`
23843
+ );
23844
+ }
23845
+ const upload = await input.client.prepareProjectApplyBundleUpload(
23846
+ {
23847
+ sha256: createHash5("sha256").update(body).digest("hex"),
23848
+ sizeBytes
23849
+ },
23850
+ { apiBaseUrl: input.commandOptions.apiBaseUrl }
23851
+ );
23852
+ await input.client.uploadProjectApplyBundle({
23853
+ uploadUrl: upload.uploadUrl,
23854
+ method: upload.method,
23855
+ contentType: upload.contentType,
23856
+ body
23857
+ });
23858
+ const response = await input.client.applyProjectResources(
23859
+ {
23860
+ source: {
23861
+ kind: "bundle",
23862
+ bundle: upload.source,
23863
+ entrypoint: input.input.entrypoint
23864
+ },
23865
+ dryRun,
23866
+ prune
23867
+ },
23868
+ { apiBaseUrl: input.commandOptions.apiBaseUrl }
23869
+ );
23870
+ await writeProjectApplyResponse({
23750
23871
  commandOptions: {
23751
23872
  ...input.commandOptions,
23752
- prune: input.commandOptions.file ? false : input.commandOptions.prune ?? request.prune
23873
+ dryRun,
23874
+ prune
23753
23875
  },
23754
23876
  client: input.client,
23755
- request,
23877
+ request: input.input.request,
23878
+ response,
23756
23879
  writeOutput: input.writeOutput,
23757
23880
  style: input.style
23758
23881
  });
23759
23882
  }
23760
- async function applyProjectInput(input) {
23883
+ async function writeProjectApplyResponse(input) {
23761
23884
  const style = input.style ?? plainStyle;
23762
- const dryRun = input.commandOptions.dryRun ?? input.request.dryRun;
23763
- const resolved = await resolveApplyAssets({
23764
- client: input.client,
23765
- request: input.request,
23766
- apiBaseUrl: input.commandOptions.apiBaseUrl,
23767
- dryRun
23768
- });
23769
- const request = {
23770
- ...input.request.delete.length > 0 ? { delete: input.request.delete } : {},
23771
- dryRun,
23772
- prune: input.commandOptions.prune ?? input.request.prune,
23773
- resources: resolved.resources,
23774
- ...Object.keys(resolved.assets).length > 0 ? { assets: resolved.assets } : {}
23775
- };
23776
- assertApplyRequestBodySize({
23777
- body: JSON.stringify(request),
23778
- assets: resolved.assets
23779
- });
23780
- const response = await input.client.applyProjectResources(request, {
23781
- apiBaseUrl: input.commandOptions.apiBaseUrl
23782
- });
23783
- const resources = response.resources.map((resource, index) => ({
23784
- kind: appliedResourceKind(input.request, response, index),
23885
+ const resources = input.response.resources.map((resource, index) => ({
23886
+ kind: appliedResourceKind(input.request, input.response, index),
23785
23887
  resource
23786
23888
  }));
23787
23889
  if (input.commandOptions.json) {
23788
- input.writeOutput(JSON.stringify(response));
23890
+ input.writeOutput(JSON.stringify(input.response));
23789
23891
  return;
23790
23892
  }
23791
- if (response.dryRun) {
23893
+ if (input.response.dryRun) {
23792
23894
  const actionWidth = Math.max(
23793
- ...response.plan.map((item) => item.action.length),
23895
+ ...input.response.plan.map((item) => item.action.length),
23794
23896
  0
23795
23897
  );
23796
- for (const item of response.plan) {
23898
+ for (const item of input.response.plan) {
23797
23899
  input.writeOutput(
23798
23900
  `${planActionStyle(
23799
23901
  style,
@@ -23812,7 +23914,7 @@ async function applyProjectInput(input) {
23812
23914
  );
23813
23915
  }
23814
23916
  }
23815
- writeDiagnostics(response.diagnostics, input.writeOutput, style);
23917
+ writeDiagnostics(input.response.diagnostics, input.writeOutput, style);
23816
23918
  return;
23817
23919
  }
23818
23920
  for (const { kind, resource } of resources) {
@@ -23828,7 +23930,7 @@ async function applyProjectInput(input) {
23828
23930
  `${style.label("resource_version")} ${resource.metadata.resourceVersion}`
23829
23931
  );
23830
23932
  }
23831
- for (const trigger of response.triggers) {
23933
+ for (const trigger of input.response.triggers) {
23832
23934
  input.writeOutput(`${style.label("webhook_event")} ${trigger.event}`);
23833
23935
  input.writeOutput(`${style.label("webhook_endpoint")} ${trigger.endpoint}`);
23834
23936
  input.writeOutput(
@@ -23836,12 +23938,12 @@ async function applyProjectInput(input) {
23836
23938
  );
23837
23939
  input.writeOutput(`${style.label("webhook_status")} ${trigger.status}`);
23838
23940
  }
23839
- for (const resource of response.pruned) {
23941
+ for (const resource of input.response.pruned) {
23840
23942
  input.writeOutput(
23841
23943
  `${style.warn("pruned")} ${resource.kind}/${resource.name}`
23842
23944
  );
23843
23945
  }
23844
- writeDiagnostics(response.diagnostics, input.writeOutput, style);
23946
+ writeDiagnostics(input.response.diagnostics, input.writeOutput, style);
23845
23947
  if (input.commandOptions.connect) {
23846
23948
  const connections = mcpOAuthAgentToolConnectionsFromAppliedResources(resources);
23847
23949
  for (const item of connections) {
@@ -23878,12 +23980,15 @@ function planActionStyle(style, action) {
23878
23980
  return (text) => text;
23879
23981
  }
23880
23982
  }
23983
+ function formatMegabytes(bytes) {
23984
+ return (bytes / (1024 * 1024)).toFixed(1);
23985
+ }
23881
23986
  var init_actions = __esm({
23882
23987
  "src/commands/apply/actions.ts"() {
23883
23988
  "use strict";
23989
+ init_src();
23884
23990
  init_style();
23885
23991
  init_agent_tool_connect();
23886
- init_assets();
23887
23992
  init_files();
23888
23993
  }
23889
23994
  });
@@ -23978,7 +24083,13 @@ var init_resources3 = __esm({
23978
24083
 
23979
24084
  // src/commands/edit/actions.ts
23980
24085
  import { spawn as spawn2 } from "child_process";
23981
- import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
24086
+ import {
24087
+ mkdirSync as mkdirSync3,
24088
+ mkdtempSync as mkdtempSync2,
24089
+ readFileSync as readFileSync5,
24090
+ rmSync as rmSync2,
24091
+ writeFileSync as writeFileSync4
24092
+ } from "fs";
23982
24093
  import { tmpdir as tmpdir2 } from "os";
23983
24094
  import { join as join6 } from "path";
23984
24095
  import { parseAllDocuments as parseYamlDocuments3, stringify as stringify4 } from "yaml";
@@ -23997,11 +24108,13 @@ async function editResource(input) {
23997
24108
  const current = await requireProjectResource(input.client, reference, {
23998
24109
  apiBaseUrl: input.commandOptions.apiBaseUrl
23999
24110
  });
24000
- const document = editableResourceDocument(reference.kind, current);
24111
+ const document = editableAgentFacade(current);
24001
24112
  const source = `${stringify4(document).trimEnd()}
24002
24113
  `;
24003
24114
  const tempRoot = mkdtempSync2(join6(tmpdir2(), "auto-edit-"));
24004
- const filePath = join6(tempRoot, `${reference.kind}-${reference.name}.yaml`);
24115
+ const agentsDir = join6(tempRoot, ".auto", "agents");
24116
+ mkdirSync3(agentsDir, { recursive: true });
24117
+ const filePath = join6(agentsDir, `${reference.name}.yaml`);
24005
24118
  writeFileSync4(filePath, source, "utf8");
24006
24119
  let removeTempFile = false;
24007
24120
  try {
@@ -24012,22 +24125,16 @@ async function editResource(input) {
24012
24125
  removeTempFile = true;
24013
24126
  return { changed: false, resource: reference };
24014
24127
  }
24015
- const editedResource = readEditedResource(filePath, reference);
24016
- const request = {
24017
- delete: [],
24018
- dryRun: false,
24019
- prune: false,
24020
- resources: [editedResource],
24021
- assets: {}
24022
- };
24023
- await applyProjectInput({
24128
+ assertEditedResourceIdentity(filePath, reference);
24129
+ const bundleInput = readProjectApplyBundleInput({ file: filePath });
24130
+ await applyProjectBundleInput({
24024
24131
  commandOptions: {
24025
24132
  apiBaseUrl: input.commandOptions.apiBaseUrl,
24026
24133
  dryRun: input.commandOptions.dryRun,
24027
24134
  prune: false
24028
24135
  },
24029
24136
  client: input.client,
24030
- request,
24137
+ input: bundleInput,
24031
24138
  writeOutput: input.writeOutput
24032
24139
  });
24033
24140
  removeTempFile = true;
@@ -24076,44 +24183,41 @@ async function runEditor(editor, filePath) {
24076
24183
  });
24077
24184
  });
24078
24185
  }
24079
- function readEditedResource(filePath, expected) {
24186
+ function assertEditedResourceIdentity(filePath, expected) {
24080
24187
  const source = readFileSync5(filePath, "utf8");
24081
- let documents;
24188
+ let parsedDocuments;
24082
24189
  try {
24083
- documents = parseYamlDocuments3(source).filter((document) => document.contents !== null).map((document) => document.toJSON());
24190
+ parsedDocuments = parseYamlDocuments3(source);
24084
24191
  } catch (error51) {
24085
24192
  throw new Error(
24086
24193
  `Invalid edited resource: ${error51 instanceof Error ? error51.message : String(error51)}`
24087
24194
  );
24088
24195
  }
24196
+ const parseError = parsedDocuments.flatMap((document2) => document2.errors)[0];
24197
+ if (parseError) {
24198
+ throw new Error(`Invalid edited resource: ${parseError.message}`);
24199
+ }
24200
+ const documents = parsedDocuments.filter((document2) => document2.contents !== null).map((document2) => document2.toJSON());
24089
24201
  if (documents.length !== 1) {
24090
24202
  throw new Error("Edited resource must contain exactly one YAML document.");
24091
24203
  }
24092
- const parsed = ProjectApplyResourceSchema.safeParse(documents[0]);
24093
- if (!parsed.success) {
24094
- throw new Error(`Invalid edited resource: ${parsed.error.message}`);
24095
- }
24096
- if (parsed.data.kind !== expected.kind) {
24097
- throw new Error(
24098
- `Edited resource kind changed from "${expected.kind}" to "${parsed.data.kind}".`
24099
- );
24204
+ const document = documents[0];
24205
+ const name = typeof document === "object" && document !== null && "name" in document && typeof document.name === "string" ? document.name : void 0;
24206
+ if (name === void 0) {
24207
+ throw new Error("Invalid edited resource: missing agent name.");
24100
24208
  }
24101
- if (parsed.data.metadata.name !== expected.name) {
24209
+ if (name !== expected.name) {
24102
24210
  throw new Error(
24103
- `Edited resource name changed from "${expected.name}" to "${parsed.data.metadata.name}".`
24211
+ `Edited resource name changed from "${expected.name}" to "${name}".`
24104
24212
  );
24105
24213
  }
24106
- return parsed.data;
24107
24214
  }
24108
- function editableResourceDocument(kind, resource) {
24215
+ function editableAgentFacade(resource) {
24109
24216
  return {
24110
- kind,
24111
- metadata: {
24112
- name: resource.metadata.name,
24113
- ...resource.metadata.labels ? { labels: resource.metadata.labels } : {},
24114
- ...resource.metadata.annotations ? { annotations: resource.metadata.annotations } : {}
24115
- },
24116
- spec: resource.spec
24217
+ name: resource.metadata.name,
24218
+ ...resource.metadata.labels ? { labels: resource.metadata.labels } : {},
24219
+ ...resource.metadata.annotations ? { annotations: resource.metadata.annotations } : {},
24220
+ ...resource.spec
24117
24221
  };
24118
24222
  }
24119
24223
  var init_actions2 = __esm({
@@ -24122,6 +24226,7 @@ var init_actions2 = __esm({
24122
24226
  init_src();
24123
24227
  init_resources3();
24124
24228
  init_actions();
24229
+ init_files();
24125
24230
  }
24126
24231
  });
24127
24232
 
@@ -29505,7 +29610,7 @@ var init_launcher = __esm({
29505
29610
  });
29506
29611
 
29507
29612
  // src/cli/program.ts
29508
- import { existsSync as existsSync4 } from "fs";
29613
+ import { existsSync as existsSync5 } from "fs";
29509
29614
  import { Command, Option as Option4 } from "commander";
29510
29615
 
29511
29616
  // src/commands/account/commands.ts
@@ -35462,8 +35567,12 @@ function registerSessionCommands(program, context) {
35462
35567
  }
35463
35568
 
35464
35569
  // src/commands/setup/actions.ts
35570
+ init_browser();
35465
35571
  init_file();
35466
35572
  init_login();
35573
+ var SETUP_STATUS_POLL_INTERVAL_MS = 5e3;
35574
+ var SETUP_STATUS_HINT_EVERY_POLLS = 12;
35575
+ var SETUP_STATUS_MAX_CONSECUTIVE_ERRORS = 12;
35467
35576
  async function setupAction(context, options) {
35468
35577
  const apiBaseUrl = apiUrlFromOptions(context, options);
35469
35578
  const client = createContextApiClient(context);
@@ -35494,15 +35603,26 @@ async function setupAction(context, options) {
35494
35603
  context.writeOutput("");
35495
35604
  context.writeOutput(`Opened PR #${response.pullRequest.number}.`);
35496
35605
  if (response.pullRequest.url) {
35606
+ if (options.browser !== false) {
35607
+ (options.openBrowser ?? openBrowser)(response.pullRequest.url);
35608
+ }
35497
35609
  context.writeOutput(response.pullRequest.url);
35498
35610
  }
35499
35611
  context.writeOutput("");
35500
- context.writeOutput("Next steps:");
35501
- context.writeOutput("1. Review and merge the PR.");
35502
35612
  context.writeOutput(
35503
- "2. Wait for GitHub Sync to apply the merged `.auto` directory."
35613
+ "Review and merge the PR. Auto will wait here and detect when the onboarding agent has been applied."
35504
35614
  );
35505
- context.writeOutput("3. Tag `@auto.onboarding` in Slack to begin.");
35615
+ await waitForOnboardingReady(context, client, {
35616
+ apiBaseUrl,
35617
+ githubConnection: github.name,
35618
+ repo,
35619
+ pullRequestNumber: response.pullRequest.number,
35620
+ pollIntervalMs: options.statusPollIntervalMs,
35621
+ sleep: options.sleep
35622
+ });
35623
+ context.writeOutput("");
35624
+ context.writeOutput("Onboarding is ready.");
35625
+ context.writeOutput("Tag `@auto.onboarding` in Slack to begin.");
35506
35626
  }
35507
35627
  async function showPitchAndWait(context) {
35508
35628
  context.writeOutput(setupPitchText());
@@ -35797,6 +35917,68 @@ async function askRequired(context, question) {
35797
35917
  readline.close();
35798
35918
  }
35799
35919
  }
35920
+ async function waitForOnboardingReady(context, client, input) {
35921
+ const sleep4 = input.sleep ?? defaultSleep;
35922
+ const pollIntervalMs = input.pollIntervalMs ?? SETUP_STATUS_POLL_INTERVAL_MS;
35923
+ let reportedMerged = false;
35924
+ let reportedApplied = false;
35925
+ let pollCount = 0;
35926
+ let consecutiveStatusErrors = 0;
35927
+ for (; ; ) {
35928
+ pollCount += 1;
35929
+ const status = await client.getSetupOnboardingPullRequestStatus(
35930
+ {
35931
+ githubConnection: input.githubConnection,
35932
+ repo: input.repo,
35933
+ pullRequestNumber: input.pullRequestNumber
35934
+ },
35935
+ { apiBaseUrl: input.apiBaseUrl }
35936
+ ).catch((error51) => {
35937
+ consecutiveStatusErrors += 1;
35938
+ if (consecutiveStatusErrors === 1) {
35939
+ context.writeOutput(
35940
+ "Status check failed; retrying while the onboarding PR remains open."
35941
+ );
35942
+ }
35943
+ if (consecutiveStatusErrors >= SETUP_STATUS_MAX_CONSECUTIVE_ERRORS) {
35944
+ throw error51;
35945
+ }
35946
+ return void 0;
35947
+ });
35948
+ if (!status) {
35949
+ await sleep4(pollIntervalMs);
35950
+ continue;
35951
+ }
35952
+ consecutiveStatusErrors = 0;
35953
+ if (!status.pullRequest.merged && status.pullRequest.state === "closed") {
35954
+ throw new Error(
35955
+ "The onboarding PR was closed without being merged. Re-run `auto setup` to open it again."
35956
+ );
35957
+ }
35958
+ if (!status.pullRequest.merged && status.pullRequest.state !== "open") {
35959
+ throw new Error(
35960
+ `The onboarding PR is in unexpected state "${status.pullRequest.state}". Check the PR, then rerun \`auto setup\` if needed.`
35961
+ );
35962
+ }
35963
+ if (status.pullRequest.merged && !reportedMerged) {
35964
+ context.writeOutput("Detected PR merge.");
35965
+ reportedMerged = true;
35966
+ }
35967
+ if (status.apply.applied && !reportedApplied) {
35968
+ context.writeOutput("Detected GitHub Sync apply.");
35969
+ reportedApplied = true;
35970
+ }
35971
+ if (status.ready) {
35972
+ return;
35973
+ }
35974
+ if (pollCount % SETUP_STATUS_HINT_EVERY_POLLS === 0) {
35975
+ context.writeOutput(
35976
+ status.pullRequest.merged ? "Still waiting for GitHub Sync to apply the onboarding agent..." : "Still waiting for the onboarding PR to be merged..."
35977
+ );
35978
+ }
35979
+ await sleep4(pollIntervalMs);
35980
+ }
35981
+ }
35800
35982
  function organizationLabel(organization) {
35801
35983
  return `${organization.organizationName} (${organization.organizationSlug})`;
35802
35984
  }
@@ -35806,6 +35988,9 @@ function isRecord3(value) {
35806
35988
  function isDefined(value) {
35807
35989
  return value !== void 0;
35808
35990
  }
35991
+ function defaultSleep(delayMs) {
35992
+ return new Promise((resolve3) => setTimeout(resolve3, delayMs));
35993
+ }
35809
35994
 
35810
35995
  // src/commands/setup/commands.ts
35811
35996
  function registerSetupCommands(program, context) {
@@ -36061,7 +36246,7 @@ function createProgram(options = {}) {
36061
36246
  assertValidProfileName(pin);
36062
36247
  const base = options.configPath ?? defaultConfigPath();
36063
36248
  const pinnedPath = profileFilePath(base, pin);
36064
- if (!existsSync4(pinnedPath)) {
36249
+ if (!existsSync5(pinnedPath)) {
36065
36250
  const names = listProfiles(base).map((profile) => profile.name);
36066
36251
  throw new Error(
36067
36252
  `No stored profile "${pin}". Stored profiles: ${names.join(", ") || "(none)"}.`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autohq/cli",
3
- "version": "0.1.165",
3
+ "version": "0.1.167",
4
4
  "license": "SEE LICENSE IN README.md",
5
5
  "publishConfig": {
6
6
  "access": "public"