@warmhub/cli 0.46.0 → 0.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/wh.js +189 -60
  2. package/package.json +1 -1
package/dist/wh.js CHANGED
@@ -19192,16 +19192,28 @@ var PLATFORM_STATUS_PROBE_ARTIFACT_FIELDS = {
19192
19192
  }
19193
19193
  };
19194
19194
  // ../../packages/rules/src/reserved-orgs.ts
19195
+ var RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES = [
19196
+ "_app",
19197
+ "_static",
19198
+ "api",
19199
+ "health",
19200
+ "healthz",
19201
+ "mcp",
19202
+ "readyz",
19203
+ "robots.txt",
19204
+ "sse",
19205
+ "trpc",
19206
+ "version"
19207
+ ];
19195
19208
  var RESERVED_ORG_NAMES = [
19209
+ ...RESERVED_RAW_CONTENT_TOP_LEVEL_NAMES,
19196
19210
  "admin",
19197
- "api",
19198
19211
  "billing",
19199
19212
  "blog",
19200
19213
  "docs",
19201
19214
  "help",
19202
19215
  "login",
19203
19216
  "public",
19204
- "robots.txt",
19205
19217
  "settings",
19206
19218
  "signup",
19207
19219
  "status",
@@ -19515,7 +19527,7 @@ function findSystemComponent(componentId) {
19515
19527
  // ../../packages/sdk-ts/package.json
19516
19528
  var package_default = {
19517
19529
  name: "@warmhub/sdk-ts",
19518
- version: "0.45.0",
19530
+ version: "0.47.0",
19519
19531
  private: false,
19520
19532
  type: "module",
19521
19533
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -20755,13 +20767,14 @@ class WarmHubClient {
20755
20767
  throw toWarmHubError(error);
20756
20768
  }
20757
20769
  },
20758
- create: async (orgName, repoName, description, visibility) => {
20770
+ create: async (orgName, repoName, description, visibility, displayName) => {
20759
20771
  try {
20760
20772
  return await this.trpc.repo.create.mutate({
20761
20773
  orgName,
20762
20774
  repoName,
20763
20775
  description,
20764
- visibility
20776
+ visibility,
20777
+ displayName
20765
20778
  });
20766
20779
  } catch (error) {
20767
20780
  throw toWarmHubError(error);
@@ -20778,6 +20791,17 @@ class WarmHubClient {
20778
20791
  throw toWarmHubError(error);
20779
20792
  }
20780
20793
  },
20794
+ setDisplayName: async (orgName, repoName, displayName) => {
20795
+ try {
20796
+ return await this.trpc.repo.setDisplayName.mutate({
20797
+ orgName,
20798
+ repoName,
20799
+ displayName
20800
+ });
20801
+ } catch (error) {
20802
+ throw toWarmHubError(error);
20803
+ }
20804
+ },
20781
20805
  setVisibility: async (orgName, repoName, visibility) => {
20782
20806
  try {
20783
20807
  return await this.trpc.repo.setVisibility.mutate({
@@ -20800,6 +20824,13 @@ class WarmHubClient {
20800
20824
  throw toWarmHubError(error);
20801
20825
  }
20802
20826
  },
20827
+ update: async (input) => {
20828
+ try {
20829
+ return await this.trpc.repo.update.mutate(input);
20830
+ } catch (error) {
20831
+ throw toWarmHubError(error);
20832
+ }
20833
+ },
20803
20834
  archive: async (orgName, repoName) => {
20804
20835
  try {
20805
20836
  return await this.trpc.repo.archive.mutate({
@@ -30080,6 +30111,17 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30080
30111
  };
30081
30112
  }
30082
30113
  steps.push({ step: "validate", status: "ok" });
30114
+ const partitionedShapes = partitionByProvisioning(manifest.shapes, "Shape");
30115
+ const partitionedCreds = partitionByProvisioning(manifest.credentials, "CredentialSet");
30116
+ const partitionedSubs = partitionByProvisioning(manifest.subscriptions, "Subscription");
30117
+ const setupCreates = [
30118
+ ...partitionedShapes.setupRefs,
30119
+ ...partitionedCreds.setupRefs,
30120
+ ...partitionedSubs.setupRefs
30121
+ ];
30122
+ const reconcileShapes = partitionedShapes.manifestEntries;
30123
+ const reconcileCreds = partitionedCreds.manifestEntries;
30124
+ const reconcileSubs = partitionedSubs.manifestEntries;
30083
30125
  await ensureSharedInfra(client, org, repo);
30084
30126
  steps.push({ step: "ensure-shared-infra", status: "ok" });
30085
30127
  const existingData = existingInstall.data;
@@ -30099,7 +30141,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30099
30141
  const liveShapeNames = new Set;
30100
30142
  const liveShapeDataByName = new Map;
30101
30143
  const liveShapeComponentIdByName = new Map;
30102
- for (const shape of manifest.shapes) {
30144
+ for (const shape of reconcileShapes) {
30103
30145
  if (isFailedInstallState || previousState !== "degraded" && !oldShapeNames.has(shape.name)) {
30104
30146
  continue;
30105
30147
  }
@@ -30120,7 +30162,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30120
30162
  } catch {}
30121
30163
  }
30122
30164
  const liveSubNames = new Set;
30123
- for (const sub of manifest.subscriptions) {
30165
+ for (const sub of reconcileSubs) {
30124
30166
  if (wasIncomplete || !oldSubNames.has(sub.name))
30125
30167
  continue;
30126
30168
  try {
@@ -30129,7 +30171,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30129
30171
  } catch {}
30130
30172
  }
30131
30173
  const liveCredNames = new Set;
30132
- for (const cred of manifest.credentials) {
30174
+ for (const cred of reconcileCreds) {
30133
30175
  if (wasIncomplete || !oldCredNames.has(cred.name))
30134
30176
  continue;
30135
30177
  const credentialSetName = resolveManifestCredentialName(cred.name, {
@@ -30141,7 +30183,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30141
30183
  liveCredNames.add(cred.name);
30142
30184
  } catch {}
30143
30185
  }
30144
- const newShapes = manifest.shapes.filter((s) => !liveShapeNames.has(s.name));
30186
+ const newShapes = reconcileShapes.filter((s) => !liveShapeNames.has(s.name));
30145
30187
  if (newShapes.length > 0) {
30146
30188
  const shapeOps = newShapes.map((shape) => ({
30147
30189
  operation: "add",
@@ -30162,7 +30204,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30162
30204
  }
30163
30205
  }
30164
30206
  }
30165
- const changedShapes = manifest.shapes.filter((shape) => {
30207
+ const changedShapes = reconcileShapes.filter((shape) => {
30166
30208
  if (!liveShapeNames.has(shape.name))
30167
30209
  return false;
30168
30210
  const liveData = liveShapeDataByName.get(shape.name);
@@ -30189,7 +30231,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30189
30231
  });
30190
30232
  }
30191
30233
  }
30192
- const newCreds = manifest.credentials.filter((c) => !oldCredNames.has(c.name) || !liveCredNames.has(c.name));
30234
+ const newCreds = reconcileCreds.filter((c) => !oldCredNames.has(c.name) || !liveCredNames.has(c.name));
30193
30235
  for (const cred of newCreds) {
30194
30236
  const credentialSetName = resolveManifestCredentialName(cred.name, {
30195
30237
  orgName: org,
@@ -30218,7 +30260,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30218
30260
  }
30219
30261
  }
30220
30262
  }
30221
- const newSubs = manifest.subscriptions.filter((s) => !oldSubNames.has(s.name) || !liveSubNames.has(s.name));
30263
+ const newSubs = reconcileSubs.filter((s) => !oldSubNames.has(s.name) || !liveSubNames.has(s.name));
30222
30264
  for (const sub of newSubs) {
30223
30265
  let compiled;
30224
30266
  try {
@@ -30269,7 +30311,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30269
30311
  } catch {}
30270
30312
  }
30271
30313
  }
30272
- const existingSubs = manifest.subscriptions.filter((s) => oldSubNames.has(s.name) && liveSubNames.has(s.name));
30314
+ const existingSubs = reconcileSubs.filter((s) => oldSubNames.has(s.name) && liveSubNames.has(s.name));
30273
30315
  for (const sub of existingSubs) {
30274
30316
  const stepName = `update-sub-${sub.name}`;
30275
30317
  let compiled;
@@ -30399,7 +30441,7 @@ async function reconcileComponent(client, org, repo, pkg, source, existingInstal
30399
30441
  state,
30400
30442
  steps,
30401
30443
  errors,
30402
- setupCreates: []
30444
+ setupCreates
30403
30445
  };
30404
30446
  }
30405
30447
 
@@ -33598,7 +33640,7 @@ cat wrefs.txt | wh thing view --format jsonl # one JSON line per *deduped
33598
33640
  - \`wh shape rename <oldName> <newName>\` — Rename shape
33599
33641
 
33600
33642
  ### repo — Repository management
33601
- - \`wh repo create <org/name> [--description]\` — Create repo
33643
+ - \`wh repo create <org/name> [--display-name] [--description] [--visibility]\` — Create repo
33602
33644
  - \`wh repo list [org]\` — List repos
33603
33645
  - \`wh repo view [org/repo]\` — Repo details
33604
33646
 
@@ -33680,7 +33722,7 @@ wh commit submit --add my-item --shape MyShape --kind assertion \\
33680
33722
  wh shape template Hypothesis Evidence -o ops.json # add --kind assertion --about TargetShape/name for assertions
33681
33723
  # edit ops.json — fill FILL_IN placeholders
33682
33724
  wh commit submit --file ops.json -m "batch update" # submit all operations (bare \`wh commit\` is equivalent)
33683
- # --file format: docs.warmhub.ai/cli-reference/write-submit-deep-dive
33725
+ # --file format: docs.warmhub.ai/cli-reference/commit-operations
33684
33726
  \`\`\`
33685
33727
 
33686
33728
  **Bulk write (JSONL stream, >1k ops)** — one chunked stream beats per-record commits (~60× faster):
@@ -33821,6 +33863,11 @@ var PRIME_DOMAIN = defineDomain({
33821
33863
  function usageError8(usage, example) {
33822
33864
  throw new CliError(2 /* UserInput */, "USER_INPUT", usage, undefined, `Example: ${example}`);
33823
33865
  }
33866
+ function ensureNonEmptyDisplayName(value, exampleCommand) {
33867
+ if (value !== undefined && value.trim() === "") {
33868
+ usageError8("--display-name requires a non-empty value", exampleCommand);
33869
+ }
33870
+ }
33824
33871
  function resolveOrgRepoArg(ref, orgFlag) {
33825
33872
  if (ref?.includes("/")) {
33826
33873
  const parts = ref.split("/");
@@ -33840,9 +33887,12 @@ function resolveOrgRepoArg(ref, orgFlag) {
33840
33887
  teachingNote: `Note: prefer \`wh repo create ${orgFlag}/${ref}\` — proceeding with combined form.`
33841
33888
  };
33842
33889
  }
33843
- usageError8("Usage: wh repo create <org/repo> [--description <desc>] [--visibility <public|private>]. Note: org and repo are a single positional argument `<org/name>`, not separate flags.", 'wh repo create myorg/myrepo -d "My repository" --visibility private');
33890
+ usageError8('Usage: wh repo create <org/repo> [--display-name "..."] [--description <desc>] [--visibility <public|private>]. Note: org and repo are a single positional argument `<org/name>`, not separate flags.', 'wh repo create myorg/myrepo -d "My repository" --visibility private');
33844
33891
  }
33845
33892
  var createFlags6 = {
33893
+ "display-name": flag.string({
33894
+ description: "Display name for the repo"
33895
+ }),
33846
33896
  description: flag.string({ short: "d", description: "Repo description" }),
33847
33897
  visibility: flag.string({
33848
33898
  short: "v",
@@ -33865,6 +33915,8 @@ var handleCreate5 = async (ctx, { flags, args }) => {
33865
33915
  if (vis !== undefined && vis !== "public" && vis !== "private") {
33866
33916
  usageError8('Invalid visibility: must be "public" or "private"', "wh repo create myorg/myrepo --visibility private");
33867
33917
  }
33918
+ const displayName2 = flags["display-name"];
33919
+ ensureNonEmptyDisplayName(displayName2, 'wh repo create myorg/myrepo --display-name "My Repo"');
33868
33920
  const c = ctx.colors;
33869
33921
  try {
33870
33922
  await ctx.client.org.get(orgName);
@@ -33876,9 +33928,12 @@ var handleCreate5 = async (ctx, { flags, args }) => {
33876
33928
  throw e;
33877
33929
  }
33878
33930
  }
33879
- const result = await ctx.client.repo.create(orgName, repoName, desc, vis);
33931
+ const result = await ctx.client.repo.create(orgName, repoName, desc, vis, displayName2);
33880
33932
  writeOutput(ctx, result, () => {
33881
33933
  ctx.status(`${c.green}Initialized empty repo${c.reset} ${c.bold}${orgName}/${repoName}${c.reset}`);
33934
+ if (result.displayName && result.displayName !== result.name) {
33935
+ ctx.status(` ${c.dim}${result.displayName}${c.reset}`);
33936
+ }
33882
33937
  if (desc)
33883
33938
  ctx.status(` ${c.dim}${desc}${c.reset}`);
33884
33939
  });
@@ -33904,9 +33959,10 @@ var handleList5 = async (ctx, { flags, args }) => {
33904
33959
  }
33905
33960
  ctx.out(`${c.bold}Repos in ${orgName}:${c.reset}`);
33906
33961
  for (const r of repos.items) {
33962
+ const display = r.displayName && r.displayName !== r.name ? ` ${c.dim}${r.displayName}${c.reset}` : "";
33907
33963
  const desc = r.description ? ` ${c.dim}${r.description}${c.reset}` : "";
33908
33964
  const archived = r.archivedAt ? ` ${c.yellow}[archived]${c.reset}` : "";
33909
- ctx.out(` ${c.cyan}${orgName}/${r.name}${c.reset}${desc}${archived}`);
33965
+ ctx.out(` ${c.cyan}${orgName}/${r.name}${c.reset}${display}${desc}${archived}`);
33910
33966
  }
33911
33967
  });
33912
33968
  };
@@ -33926,6 +33982,9 @@ var handleView6 = async (ctx, { args }) => {
33926
33982
  ]);
33927
33983
  writeOutput(ctx, { ...repoInfo, stats, configureStats }, () => {
33928
33984
  ctx.out(`${c.bold}${org}/${repo}${c.reset}`);
33985
+ if (repoInfo.displayName && repoInfo.displayName !== repoInfo.name) {
33986
+ ctx.out(` ${repoInfo.displayName}`);
33987
+ }
33929
33988
  if (repoInfo.description)
33930
33989
  ctx.out(` ${repoInfo.description}`);
33931
33990
  if (repoInfo.archivedAt) {
@@ -33950,16 +34009,58 @@ var handleVisibility = async (ctx, { args }) => {
33950
34009
  ctx.out(`${c.green}Set${c.reset} ${c.cyan}${orgName}/${repoName}${c.reset} to ${c.bold}${newVisibility}${c.reset}`);
33951
34010
  });
33952
34011
  };
33953
- var handleRepoRename = async (ctx, { args }) => {
34012
+ var repoRenameFlags = {
34013
+ "display-name": flag.string({
34014
+ description: "New display name (must be non-empty)"
34015
+ }),
34016
+ slug: flag.string({
34017
+ description: "New slug (alias for the positional argument)"
34018
+ })
34019
+ };
34020
+ var handleRepoRename = async (ctx, { args, flags }) => {
33954
34021
  const orgRepo = args[0];
33955
- const newName = args[1];
33956
- if (!orgRepo || !newName || !orgRepo.includes("/")) {
33957
- usageError8("Usage: wh repo rename <org/oldName> <newName>", "wh repo rename myorg/oldrepo newrepo");
34022
+ const positionalSlug = args[1];
34023
+ const flagSlug = flags.slug;
34024
+ const displayName2 = flags["display-name"];
34025
+ const rawSlugFromInvocation = ctx.invocation.positional[2];
34026
+ if (!orgRepo?.includes("/")) {
34027
+ usageError8('Usage: wh repo rename <org/repoName> [<newName>] [--slug <slug>] [--display-name "..."]', 'wh repo rename myorg/oldrepo newrepo --display-name "New Repo"');
34028
+ }
34029
+ if (positionalSlug && flagSlug !== undefined && positionalSlug !== flagSlug) {
34030
+ usageError8("Specify the new slug as either a positional or --slug, not both", "wh repo rename myorg/foo bar # or: wh repo rename myorg/foo --slug bar");
34031
+ }
34032
+ const newSlug = positionalSlug !== undefined ? positionalSlug : flagSlug;
34033
+ if (newSlug === undefined && displayName2 === undefined) {
34034
+ usageError8('Usage: wh repo rename <org/repoName> [<newName>] [--slug <slug>] [--display-name "..."]', 'wh repo rename myorg/oldrepo newrepo --display-name "New Repo"');
34035
+ }
34036
+ if (newSlug !== undefined && newSlug.length === 0 || rawSlugFromInvocation === "" || flagSlug === "") {
34037
+ usageError8("New slug must be a non-empty string", "wh repo rename myorg/oldrepo newrepo");
33958
34038
  }
34039
+ ensureNonEmptyDisplayName(displayName2, 'wh repo rename myorg/oldrepo --display-name "New Repo"');
33959
34040
  const [orgName, oldName] = orgRepo.split("/", 2);
33960
34041
  const c = ctx.colors;
33961
- await ctx.client.repo.rename(orgName, oldName, newName);
33962
- ctx.out(`${c.green}Renamed repo${c.reset} ${c.cyan}${orgName}/${oldName}${c.reset} ${c.cyan}${orgName}/${newName}${c.reset}`);
34042
+ const slugChange = newSlug && newSlug !== oldName ? newSlug : undefined;
34043
+ if (displayName2 !== undefined && slugChange) {
34044
+ await ctx.client.repo.update({
34045
+ orgName,
34046
+ repoName: oldName,
34047
+ displayName: displayName2,
34048
+ newName: slugChange
34049
+ });
34050
+ } else if (displayName2 !== undefined) {
34051
+ await ctx.client.repo.setDisplayName(orgName, oldName, displayName2);
34052
+ } else if (newSlug !== undefined) {
34053
+ await ctx.client.repo.rename(orgName, oldName, newSlug);
34054
+ }
34055
+ if (slugChange) {
34056
+ ctx.out(`${c.green}Updated slug${c.reset} ${c.cyan}${orgName}/${oldName}${c.reset} → ${c.cyan}${orgName}/${slugChange}${c.reset}`);
34057
+ } else if (newSlug !== undefined && displayName2 === undefined) {
34058
+ ctx.out(`${c.dim}No changes requested for${c.reset} ${c.cyan}${orgName}/${oldName}${c.reset}`);
34059
+ }
34060
+ if (displayName2 !== undefined) {
34061
+ const repoForDisplay = slugChange ?? oldName;
34062
+ ctx.out(`${c.green}Updated display name${c.reset} ${c.cyan}${orgName}/${repoForDisplay}${c.reset}`);
34063
+ }
33963
34064
  };
33964
34065
  var updateFlags3 = {
33965
34066
  description: flag.string({ short: "d", description: "New repo description" })
@@ -34369,6 +34470,7 @@ var REPO_DOMAIN = defineDomain({
34369
34470
  examples: [
34370
34471
  "wh repo create myorg/myrepo",
34371
34472
  'wh repo create myorg/myrepo -d "My repo"',
34473
+ 'wh repo create myorg/myrepo --display-name "My Repo"',
34372
34474
  'wh repo create myorg/myrepo --visibility private -d "Private repo"'
34373
34475
  ],
34374
34476
  handler: handleCreate5
@@ -34411,9 +34513,15 @@ var REPO_DOMAIN = defineDomain({
34411
34513
  handler: handleVisibility
34412
34514
  },
34413
34515
  rename: {
34414
- summary: "Rename a repo",
34415
- args: "<org/oldName> <newName>",
34416
- examples: ["wh repo rename myorg/oldrepo newrepo"],
34516
+ summary: "Rename a repo and/or update its display name",
34517
+ args: "<org/repoName> [<newName>]",
34518
+ flags: repoRenameFlags,
34519
+ examples: [
34520
+ "wh repo rename myorg/oldrepo newrepo",
34521
+ "wh repo rename myorg/foo --slug bar",
34522
+ 'wh repo rename myorg/foo --display-name "Foo"',
34523
+ 'wh repo rename myorg/foo bar --display-name "Bar"'
34524
+ ],
34417
34525
  handler: handleRepoRename
34418
34526
  },
34419
34527
  update: {
@@ -37247,7 +37355,7 @@ function resolveLogLevel(flags, env) {
37247
37355
  // package.json
37248
37356
  var package_default3 = {
37249
37357
  name: "@warmhub/cli",
37250
- version: "0.46.0",
37358
+ version: "0.48.0",
37251
37359
  private: false,
37252
37360
  type: "module",
37253
37361
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -37491,7 +37599,10 @@ async function maybeHandleComponentShellBoundary(argv, deps = {}) {
37491
37599
  pathExists,
37492
37600
  runGit,
37493
37601
  installFromPath: installFromPathImpl,
37494
- materializeComponentArchive: materializeComponentArchiveImpl
37602
+ resolveRegisteredInstall: resolveRegisteredInstallImpl,
37603
+ downloadRegisteredSource: downloadRegisteredSourceImpl,
37604
+ materializeComponentArchive: materializeComponentArchiveImpl,
37605
+ callRegisteredSetup: callRegisteredSetupImpl
37495
37606
  });
37496
37607
  } catch (error) {
37497
37608
  return printCliError(toCliError2(error), writeErr, {
@@ -37564,13 +37675,33 @@ async function handleGithubInstall(args) {
37564
37675
  }
37565
37676
  async function handleRegisteredInstall(args) {
37566
37677
  const parsedRepo = parseOrgRepo(args.repoFlag, args.config);
37567
- const installRepo = `${parsedRepo.org}/${parsedRepo.repo}`;
37678
+ return performRegisteredInstall({
37679
+ componentRef: args.componentRef,
37680
+ refOverride: args.refOverride,
37681
+ verb: "Installed",
37682
+ client: args.client,
37683
+ parsedRepo,
37684
+ format: args.format,
37685
+ writeOut: args.writeOut,
37686
+ writeErr: args.writeErr,
37687
+ installFromPath: args.installFromPath,
37688
+ resolveRegisteredInstall: args.resolveRegisteredInstall,
37689
+ downloadRegisteredSource: args.downloadRegisteredSource,
37690
+ materializeComponentArchive: args.materializeComponentArchive,
37691
+ callRegisteredSetup: args.callRegisteredSetup
37692
+ });
37693
+ }
37694
+ async function performRegisteredInstall(args) {
37695
+ const installRepo = `${args.parsedRepo.org}/${args.parsedRepo.repo}`;
37568
37696
  const resolved = await args.resolveRegisteredInstall({
37569
37697
  componentRef: args.componentRef,
37570
37698
  installRepo,
37571
37699
  client: args.client
37572
37700
  });
37573
- const ref = normalizeGitRef(args.refOverride ?? resolved.sourceDefaultRef ?? undefined);
37701
+ const persistedInstallId = readPersistedString(args.persistedInstallData, "installId");
37702
+ const persistedRef = readPersistedString(args.persistedInstallData, "sourceRef");
37703
+ const installId = persistedInstallId ?? resolved.installId;
37704
+ const ref = normalizeGitRef(args.refOverride ?? persistedRef ?? resolved.sourceDefaultRef ?? undefined);
37574
37705
  const downloaded = await args.downloadRegisteredSource({
37575
37706
  componentRef: args.componentRef,
37576
37707
  installRepo,
@@ -37581,16 +37712,16 @@ async function handleRegisteredInstall(args) {
37581
37712
  try {
37582
37713
  const resolvedRef = ref ?? downloaded.sourceRef;
37583
37714
  invalidateInstallSnapshotCache(installRepo);
37584
- const result = await args.installFromPath(args.client, parsedRepo.org, parsedRepo.repo, extracted.componentDir, {
37715
+ const result = await args.installFromPath(args.client, args.parsedRepo.org, args.parsedRepo.repo, extracted.componentDir, {
37585
37716
  githubUrl: downloaded.sourceUrl,
37586
37717
  ref: resolvedRef,
37587
37718
  resolvedSha: downloaded.resolvedSha ?? "",
37588
- installId: resolved.installId,
37719
+ installId,
37589
37720
  sourceKind: "registered",
37590
37721
  registeredComponentRef: args.componentRef
37591
37722
  });
37592
37723
  if (!result.ok) {
37593
- await writeInstallResult(args.writeOut, args.writeErr, args.format, "Installed", result, installRepo, args.client);
37724
+ await writeInstallResult(args.writeOut, args.writeErr, args.format, args.verb, result, installRepo, args.client);
37594
37725
  return 1 /* Runtime */;
37595
37726
  }
37596
37727
  if (resolved.hasSetup) {
@@ -37599,7 +37730,7 @@ async function handleRegisteredInstall(args) {
37599
37730
  setupResult = await args.callRegisteredSetup({
37600
37731
  componentRef: args.componentRef,
37601
37732
  installRepo,
37602
- installId: resolved.installId,
37733
+ installId,
37603
37734
  ref: resolvedRef,
37604
37735
  resolvedSha: downloaded.resolvedSha,
37605
37736
  client: args.client
@@ -37607,7 +37738,7 @@ async function handleRegisteredInstall(args) {
37607
37738
  } catch (error) {
37608
37739
  if (isMissingManifestPermissionError(error)) {
37609
37740
  const backendCode = warmHubErrorBackendCode(error) ?? warmHubErrorKind(error);
37610
- throw new CliError(2 /* UserInput */, "USER_INPUT", error.message, undefined, "Ask an org owner/admin to grant the missing permissions on the install repo, then re-run install.", undefined, backendCode);
37741
+ throw new CliError(2 /* UserInput */, "USER_INPUT", error.message, undefined, `Ask an org owner/admin to grant the missing permissions on the install repo, then re-run ${args.verb === "Installed" ? "install" : "update"}.`, undefined, backendCode);
37611
37742
  }
37612
37743
  throw error;
37613
37744
  }
@@ -37615,12 +37746,16 @@ async function handleRegisteredInstall(args) {
37615
37746
  throw new CliError(1 /* Runtime */, "BACKEND", `Component setup failed with status ${setupResult.status}${setupResult.body ? `: ${setupResult.body}` : ""}`);
37616
37747
  }
37617
37748
  }
37618
- await writeInstallResult(args.writeOut, args.writeErr, args.format, "Installed", result, installRepo, args.client);
37749
+ await writeInstallResult(args.writeOut, args.writeErr, args.format, args.verb, result, installRepo, args.client);
37619
37750
  return result.ok ? 0 /* Ok */ : 1 /* Runtime */;
37620
37751
  } finally {
37621
37752
  extracted.cleanup();
37622
37753
  }
37623
37754
  }
37755
+ function readPersistedString(data, key) {
37756
+ const value = data?.[key];
37757
+ return typeof value === "string" && value.length > 0 ? value : undefined;
37758
+ }
37624
37759
  function isMissingManifestPermissionError(error) {
37625
37760
  return warmHubErrorKind(error) === "FORBIDDEN" && error instanceof Error && error.message.startsWith("Cannot install: caller is missing repo permissions required by the manifest:");
37626
37761
  }
@@ -37664,28 +37799,22 @@ async function handleGithubUpdate(args) {
37664
37799
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Component '${args.name}' is a bundled system component. Use 'wh component install ${source.componentId} --repo ${installRepo}' to update it.`);
37665
37800
  }
37666
37801
  if (source.kind === "registered") {
37667
- const installRepo2 = `${parsedRepo.org}/${parsedRepo.repo}`;
37668
- const [ownerOrg, componentName] = source.componentRef.split("/");
37669
- const downloaded = await args.client.component.registry.downloadSource(ownerOrg, componentName, {
37670
- installRepo: installRepo2,
37671
- ...source.ref ? { ref: source.ref } : {}
37802
+ return performRegisteredInstall({
37803
+ componentRef: source.componentRef,
37804
+ refOverride: args.refOverride,
37805
+ persistedInstallData: installData,
37806
+ verb: "Updated",
37807
+ client: args.client,
37808
+ parsedRepo,
37809
+ format: args.format,
37810
+ writeOut: args.writeOut,
37811
+ writeErr: args.writeErr,
37812
+ installFromPath: args.installFromPath,
37813
+ resolveRegisteredInstall: args.resolveRegisteredInstall,
37814
+ downloadRegisteredSource: args.downloadRegisteredSource,
37815
+ materializeComponentArchive: args.materializeComponentArchive,
37816
+ callRegisteredSetup: args.callRegisteredSetup
37672
37817
  });
37673
- const extracted = args.materializeComponentArchive(downloaded.archive, downloaded.componentRef, source.ref ?? downloaded.sourceRef);
37674
- try {
37675
- const updateRef2 = source.ref ?? downloaded.sourceRef;
37676
- invalidateInstallSnapshotCache(installRepo2);
37677
- const result2 = await args.installFromPath(args.client, parsedRepo.org, parsedRepo.repo, extracted.componentDir, {
37678
- githubUrl: downloaded.sourceUrl,
37679
- ref: updateRef2,
37680
- resolvedSha: downloaded.resolvedSha ?? "",
37681
- sourceKind: "registered",
37682
- registeredComponentRef: source.componentRef
37683
- });
37684
- await writeInstallResult(args.writeOut, args.writeErr, args.format, "Updated", result2, installRepo2, args.client);
37685
- return result2.ok ? 0 /* Ok */ : 1 /* Runtime */;
37686
- } finally {
37687
- extracted.cleanup();
37688
- }
37689
37818
  }
37690
37819
  const componentDir = args.getComponentPath(`${source.owner}--${source.repo}`);
37691
37820
  args.ensureCacheDir();
@@ -38253,4 +38382,4 @@ if (!updateCheckSuppressedByArgv && shouldRunUpdateCheck(updateEligibility)) {
38253
38382
  var interceptedExitCode = await maybeHandleComponentShellBoundary(dispatchArgv);
38254
38383
  process.exitCode = interceptedExitCode === undefined ? await runCli(dispatchArgv, { version: package_default3.version }) : interceptedExitCode;
38255
38384
 
38256
- //# debugId=A704BB8C405BE7AC64756E2164756E21
38385
+ //# debugId=4217C1CF64E0C7F164756E2164756E21
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmhub/cli",
3
- "version": "0.46.0",
3
+ "version": "0.48.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",