@warmhub/cli 0.132.2 → 0.134.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 +139 -23
  2. package/package.json +1 -1
package/dist/wh.js CHANGED
@@ -26118,6 +26118,16 @@ function illegalOpSequences(operations, errors, checkAddAdd, options) {
26118
26118
  }
26119
26119
  }
26120
26120
 
26121
+ // ../../packages/rules/src/reserved-roots.ts
26122
+ var RESERVED_THING_ROOT = "hub";
26123
+ var RESERVED_THING_ROOT_PREFIX = `${RESERVED_THING_ROOT}/`;
26124
+ function isReservedThingRoot(name) {
26125
+ return name === RESERVED_THING_ROOT || name.startsWith(RESERVED_THING_ROOT_PREFIX);
26126
+ }
26127
+ function reservedThingRootMessage(name) {
26128
+ return `Name "${name}" is under the reserved root "${RESERVED_THING_ROOT_PREFIX}"; only Shapes live there, as ${RESERVED_THING_ROOT_PREFIX}shapes/<Name>`;
26129
+ }
26130
+
26121
26131
  // ../../packages/rules/src/preflight-operation.ts
26122
26132
  var collectionTypes = ["arc", "bond", "set", "list", "pair"];
26123
26133
  var canonicalCollectionTypes = ["arc", "bond", "pair", "set", "list"];
@@ -26133,6 +26143,7 @@ function parseCollectionOp(value) {
26133
26143
  function preflightOpDiagnostics(op, operationIndex) {
26134
26144
  const errors = [];
26135
26145
  errors.push(...builtinShapeGuard(op, operationIndex));
26146
+ errors.push(...reservedRootGuard(op, operationIndex));
26136
26147
  errors.push(...contentNameGuard(op, operationIndex));
26137
26148
  errors.push(...plusSignGuard(op, operationIndex));
26138
26149
  errors.push(...validateCollectionAbouts(op, operationIndex));
@@ -26187,6 +26198,29 @@ function builtinShapeGuard(op, operationIndex) {
26187
26198
  }
26188
26199
  return errors;
26189
26200
  }
26201
+ function reservedRootRefusal(name, operationIndex) {
26202
+ return {
26203
+ code: "RESERVED_NAME",
26204
+ operationIndex,
26205
+ message: reservedThingRootMessage(name)
26206
+ };
26207
+ }
26208
+ function reservedRootGuard(op, operationIndex) {
26209
+ if (op.kind === "shape")
26210
+ return [];
26211
+ if (op.operation === "add" && op.name) {
26212
+ const stored = op.kind === "collection" ? op.name : splitLocalPath(op.name)?.bareName;
26213
+ if (stored !== undefined && isReservedThingRoot(stored)) {
26214
+ return [reservedRootRefusal(stored, operationIndex)];
26215
+ }
26216
+ return [];
26217
+ }
26218
+ const isShapeRename = op.name !== undefined && splitLocalPath(op.name) === null;
26219
+ if (op.operation === "rename" && !isShapeRename && op.newName !== undefined && isReservedThingRoot(op.newName)) {
26220
+ return [reservedRootRefusal(op.newName, operationIndex)];
26221
+ }
26222
+ return [];
26223
+ }
26190
26224
  function contentNameGuard(op, operationIndex) {
26191
26225
  if (op.kind !== "thing" || !op.name)
26192
26226
  return [];
@@ -45429,7 +45463,7 @@ function createStreamingSubmissionHandle(input, deps) {
45429
45463
  // ../../packages/sdk-ts/package.json
45430
45464
  var package_default = {
45431
45465
  name: "@warmhub/sdk-ts",
45432
- version: "0.130.2",
45466
+ version: "0.132.0",
45433
45467
  private: false,
45434
45468
  type: "module",
45435
45469
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -49791,10 +49825,10 @@ class WorkOsAuthError extends Error {
49791
49825
  this.status = status;
49792
49826
  }
49793
49827
  }
49794
- async function refreshAccessToken(tokens, signal) {
49828
+ async function refreshAccessToken(tokens, signal, options = {}) {
49795
49829
  const log = getLog();
49796
49830
  const { clientId } = tokens;
49797
- const workosUrl = "https://api.workos.com";
49831
+ const workosUrl = (options.workosUrl ?? "https://api.workos.com").replace(/\/$/, "");
49798
49832
  const path = "/user_management/authenticate";
49799
49833
  const requestId = `${process.pid}-${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
49800
49834
  log.debug("http.request", {
@@ -49804,7 +49838,8 @@ async function refreshAccessToken(tokens, signal) {
49804
49838
  request_id: requestId
49805
49839
  });
49806
49840
  const startedAt = Date.now();
49807
- const requestSignal = signal ?? AbortSignal.timeout(WORKOS_REFRESH_TIMEOUT_MS);
49841
+ const timeoutSignal = AbortSignal.timeout(options.requestTimeoutMs ?? WORKOS_REFRESH_TIMEOUT_MS);
49842
+ const requestSignal = signal ? AbortSignal.any([signal, timeoutSignal]) : timeoutSignal;
49808
49843
  let res;
49809
49844
  try {
49810
49845
  res = await fetch(`${workosUrl}${path}`, {
@@ -50379,6 +50414,9 @@ function corruptedAuthError(path, cause) {
50379
50414
  }
50380
50415
 
50381
50416
  // ../../packages/warmhub-cli/src/auth.ts
50417
+ var AUTH_REFRESH_BUDGET_MS = 30000;
50418
+ var AUTH_REFRESH_RETRY_DELAY_MS = 1000;
50419
+ var TRANSIENT_REFRESH_COOLDOWN_MS = 5000;
50382
50420
  function isAuthLockError(error51, authPath) {
50383
50421
  return error51 instanceof Error && error51.code === "ELOCKED" && (error51.file === undefined || error51.file === authPath);
50384
50422
  }
@@ -50400,6 +50438,17 @@ function delay2(ms, signal) {
50400
50438
  signal?.addEventListener("abort", onAbort, { once: true });
50401
50439
  });
50402
50440
  }
50441
+ function refreshCooldownActive(failedAt) {
50442
+ if (!failedAt)
50443
+ return false;
50444
+ const ageMs = Date.now() - new Date(failedAt).getTime();
50445
+ return ageMs >= 0 && ageMs < TRANSIENT_REFRESH_COOLDOWN_MS;
50446
+ }
50447
+ function withoutRefreshFailure(profile) {
50448
+ const next = { ...profile };
50449
+ delete next.transientRefreshFailedAt;
50450
+ return next;
50451
+ }
50403
50452
  function getTokenInfo(profile) {
50404
50453
  const envToken = process.env.WH_TOKEN;
50405
50454
  if (envToken) {
@@ -50428,7 +50477,7 @@ function getTokenInfo(profile) {
50428
50477
  canRefresh: source === "device" && !!tokens.refreshToken
50429
50478
  };
50430
50479
  }
50431
- async function getValidToken(profile, signal) {
50480
+ async function getValidToken(profile, signal, options = {}) {
50432
50481
  const log = getLog();
50433
50482
  const envToken = process.env.WH_TOKEN;
50434
50483
  if (envToken) {
@@ -50460,7 +50509,10 @@ async function getValidToken(profile, signal) {
50460
50509
  const classification = err.error === "invalid_grant" ? "invalid_grant" : "terminal";
50461
50510
  const staleProf = getProfile(profileName, authPath);
50462
50511
  if (staleProf) {
50463
- saveProfileWhileLocked(profileName, { ...staleProf, tokens: { ...staleProf.tokens, refreshToken: "" } }, authPath);
50512
+ saveProfileWhileLocked(profileName, withoutRefreshFailure({
50513
+ ...staleProf,
50514
+ tokens: { ...staleProf.tokens, refreshToken: "" }
50515
+ }), authPath);
50464
50516
  log.error("auth.refresh_token.wiped", {
50465
50517
  profile: profileName,
50466
50518
  reason: classification
@@ -50472,6 +50524,16 @@ async function getValidToken(profile, signal) {
50472
50524
  }
50473
50525
  throw new CliError(5 /* Auth */, "AUTH", `Session could not be refreshed (${err.error}).${err.errorDescription ? ` ${err.errorDescription}` : ""}`, err, `Run ${loginCmd} to re-authenticate.`);
50474
50526
  };
50527
+ const transientRefreshError = (cause) => new CliError(5 /* Auth */, "AUTH", "Token refresh failed (transient).", cause, `Check network connectivity, or run ${loginCmd} to re-authenticate.`);
50528
+ const markTransientRefreshFailure = () => {
50529
+ const failedProf = getProfile(profileName, authPath);
50530
+ if (!failedProf)
50531
+ return;
50532
+ saveProfileWhileLocked(profileName, {
50533
+ ...failedProf,
50534
+ transientRefreshFailedAt: new Date().toISOString()
50535
+ }, authPath);
50536
+ };
50475
50537
  try {
50476
50538
  return await withAuthLock(authPath, async () => {
50477
50539
  const lockedProf = getProfile(profileName, authPath);
@@ -50486,14 +50548,20 @@ async function getValidToken(profile, signal) {
50486
50548
  if (!lockedTokens.refreshToken) {
50487
50549
  throw new CliError(5 /* Auth */, "AUTH", "Session expired.", undefined, `Run ${loginCmd} to re-authenticate.`);
50488
50550
  }
50551
+ if (refreshCooldownActive(lockedProf.transientRefreshFailedAt)) {
50552
+ log.info("auth.refresh.cooldown", { profile: profileName });
50553
+ throw transientRefreshError();
50554
+ }
50555
+ const budgetSignal = AbortSignal.timeout(options.refreshBudgetMs ?? AUTH_REFRESH_BUDGET_MS);
50556
+ const refreshSignal = signal ? AbortSignal.any([signal, budgetSignal]) : budgetSignal;
50489
50557
  const refreshStarted = Date.now();
50490
50558
  log.info("auth.refresh.start", {
50491
50559
  profile: profileName,
50492
50560
  client_id: lockedTokens.clientId
50493
50561
  });
50494
50562
  try {
50495
- const refreshed = await refreshAccessToken(lockedTokens, signal);
50496
- saveProfileWhileLocked(profileName, { ...lockedProf, tokens: refreshed }, authPath);
50563
+ const refreshed = await refreshAccessToken(lockedTokens, refreshSignal);
50564
+ saveProfileWhileLocked(profileName, withoutRefreshFailure({ ...lockedProf, tokens: refreshed }), authPath);
50497
50565
  log.info("auth.refresh.ok", {
50498
50566
  profile: profileName,
50499
50567
  duration_ms: Date.now() - refreshStarted,
@@ -50521,15 +50589,25 @@ async function getValidToken(profile, signal) {
50521
50589
  duration_ms: Date.now() - refreshStarted,
50522
50590
  error_name: err instanceof Error ? err.name : "Unknown"
50523
50591
  });
50524
- await delay2(1000, signal);
50592
+ try {
50593
+ await delay2(options.retryDelayMs ?? AUTH_REFRESH_RETRY_DELAY_MS, refreshSignal);
50594
+ } catch (delayErr) {
50595
+ if (signal?.aborted)
50596
+ throw delayErr;
50597
+ markTransientRefreshFailure();
50598
+ throw transientRefreshError(delayErr);
50599
+ }
50525
50600
  log.info("auth.refresh.retry", { profile: profileName, attempt: 2 });
50526
50601
  let retryStarted = Date.now();
50527
50602
  try {
50528
50603
  const retryProf = getProfile(profileName, authPath);
50529
50604
  const retryTokens = retryProf?.tokens ?? lockedTokens;
50530
50605
  retryStarted = Date.now();
50531
- const refreshed = await refreshAccessToken(retryTokens, signal);
50532
- saveProfileWhileLocked(profileName, { ...retryProf ?? lockedProf, tokens: refreshed }, authPath);
50606
+ const refreshed = await refreshAccessToken(retryTokens, refreshSignal);
50607
+ saveProfileWhileLocked(profileName, withoutRefreshFailure({
50608
+ ...retryProf ?? lockedProf,
50609
+ tokens: refreshed
50610
+ }), authPath);
50533
50611
  log.info("auth.refresh.ok", {
50534
50612
  profile: profileName,
50535
50613
  duration_ms: Date.now() - retryStarted,
@@ -50554,7 +50632,8 @@ async function getValidToken(profile, signal) {
50554
50632
  failTerminalRefresh(retryErr);
50555
50633
  }
50556
50634
  log.info("auth.refresh.failed", fields);
50557
- throw new CliError(5 /* Auth */, "AUTH", "Token refresh failed (transient).", retryErr, `Check network connectivity, or run ${loginCmd} to re-authenticate.`);
50635
+ markTransientRefreshFailure();
50636
+ throw transientRefreshError(retryErr);
50558
50637
  }
50559
50638
  }
50560
50639
  });
@@ -50873,7 +50952,7 @@ function shouldGuardDomain(domainPath, canonicalVerb, args) {
50873
50952
  }
50874
50953
  async function probeCapabilities(ctx) {
50875
50954
  try {
50876
- return await ctx.client.diagnostics.capabilities();
50955
+ return await (ctx.compatibilityClient ?? ctx.client).diagnostics.capabilities();
50877
50956
  } catch {
50878
50957
  return;
50879
50958
  }
@@ -50887,7 +50966,7 @@ async function checkCompatibility(ctx, domainPath, canonicalVerb, args) {
50887
50966
  }
50888
50967
  let capabilities;
50889
50968
  try {
50890
- const diagnostics = ctx.client.diagnostics;
50969
+ const diagnostics = (ctx.compatibilityClient ?? ctx.client).diagnostics;
50891
50970
  if (typeof diagnostics.assertCompatible === "function") {
50892
50971
  await diagnostics.assertCompatible();
50893
50972
  if (clientFlags.length > 0)
@@ -50896,6 +50975,8 @@ async function checkCompatibility(ctx, domainPath, canonicalVerb, args) {
50896
50975
  capabilities = await diagnostics.capabilities();
50897
50976
  }
50898
50977
  } catch (err) {
50978
+ if (err instanceof CliError && err.kind === "AUTH")
50979
+ throw err;
50899
50980
  const message = err instanceof Error ? err.message : String(err);
50900
50981
  if (message.includes("Could not find") || message.includes("NOT_FOUND") || message.includes("is not a function")) {
50901
50982
  ctx.err("Backend does not support capabilities check (upgrade backend)");
@@ -54270,7 +54351,7 @@ var handleRefs = async (ctx, { flags, args }) => {
54270
54351
  }
54271
54352
  const result2 = withDecorations({ items, nextCursor: undefined }, decorations);
54272
54353
  writePageOutput(ctx, items, { limit: pageLimit, nextCursor: null, decorations }, () => renderRefs(ctx.out, ctx.colors, result2, wref, direction));
54273
- maybeEmitAboutHint(ctx, direction, items.length, refsQueryIsNarrowed);
54354
+ maybeEmitAboutHint(ctx, direction, items.length, refsQueryIsNarrowed, false);
54274
54355
  return;
54275
54356
  }
54276
54357
  const result = await fetchPage(cursor);
@@ -54282,13 +54363,15 @@ var handleRefs = async (ctx, { flags, args }) => {
54282
54363
  nextCursor: result.nextCursor ?? null,
54283
54364
  decorations: getResponseDecorations(result)
54284
54365
  }, () => renderRefs(ctx.out, ctx.colors, result, wref, direction));
54285
- maybeEmitAboutHint(ctx, direction, result.items?.length ?? 0, refsQueryIsNarrowed);
54366
+ maybeEmitAboutHint(ctx, direction, result.items?.length ?? 0, refsQueryIsNarrowed, Boolean(result.nextCursor));
54286
54367
  };
54287
- function maybeEmitAboutHint(ctx, direction, itemCount, refsQueryIsNarrowed) {
54368
+ function maybeEmitAboutHint(ctx, direction, itemCount, refsQueryIsNarrowed, hasMore) {
54288
54369
  if (direction !== "inbound")
54289
54370
  return;
54290
54371
  if (refsQueryIsNarrowed)
54291
54372
  return;
54373
+ if (hasMore)
54374
+ return;
54292
54375
  if (itemCount > 0)
54293
54376
  return;
54294
54377
  if (ctx.format === "json" || ctx.format === "jsonl")
@@ -55550,7 +55633,20 @@ Run \`wh auth login --profile ${explicitProfile}\` to create it.`);
55550
55633
  clientFlags,
55551
55634
  decorateResponses: decorate
55552
55635
  });
55553
- return { config: config2, profile: effectiveProfile, client, clientFlags, decorate };
55636
+ const compatibilityClient = args.client ?? createUnauthenticatedClient(config2, {
55637
+ functionLogs: args.functionLogs,
55638
+ signal: args.signal,
55639
+ clientFlags,
55640
+ decorateResponses: decorate
55641
+ });
55642
+ return {
55643
+ config: config2,
55644
+ profile: effectiveProfile,
55645
+ client,
55646
+ compatibilityClient,
55647
+ clientFlags,
55648
+ decorate
55649
+ };
55554
55650
  }
55555
55651
 
55556
55652
  // ../../packages/warmhub-cli/src/domains/auth-shared.ts
@@ -57334,6 +57430,9 @@ var createFlags3 = {
57334
57430
  committer: flag.string({
57335
57431
  description: "Committer wref (shape or shaped thing; e.g. Agent/bot-1)"
57336
57432
  }),
57433
+ "component-ref": flag.string({
57434
+ description: "attribute writes to an actively installed component (Org/Name); the server checks caller authorization."
57435
+ }),
57337
57436
  add: flag.string({
57338
57437
  description: "Add a new thing (bare name — use --shape to set the shape). Repeatable; pair each --add with its own --data. For >20 ops, use --file <path>.",
57339
57438
  multiple: true
@@ -58111,6 +58210,7 @@ async function applyJsonlCommit(ctx, args) {
58111
58210
  repoName: args.repo,
58112
58211
  streamId,
58113
58212
  submissionId: args.submissionId,
58213
+ ...args.componentRef !== undefined ? { componentRef: args.componentRef } : {},
58114
58214
  ...args.committer ? { committer: args.committer } : {},
58115
58215
  ...args.message ? { message: args.message } : {},
58116
58216
  ...args.returnRepoSeq === true ? { returnRepoSeq: true } : {},
@@ -58473,6 +58573,7 @@ async function executeCommitValidation(ctx, args) {
58473
58573
  const options = {
58474
58574
  ...args.message !== undefined ? { message: args.message } : {},
58475
58575
  ...args.committer !== undefined ? { committer: args.committer } : {},
58576
+ ...args.componentRef !== undefined ? { componentRef: args.componentRef } : {},
58476
58577
  ...args.skipExisting ? { skipExisting: true } : {},
58477
58578
  ...args.includeWouldBeBody ? { includeWouldBeBody: true } : {},
58478
58579
  ...ctx.signal ? { signal: ctx.signal } : {}
@@ -58518,6 +58619,7 @@ async function executeCommitValidation(ctx, args) {
58518
58619
  var handleSubmit = async (ctx, { flags, args }) => {
58519
58620
  const { org, repo } = parseOrgRepo(getRepoRef(ctx) ?? args[0], ctx.config);
58520
58621
  const committer = flags.committer;
58622
+ const componentRef = flags["component-ref"];
58521
58623
  const messageFlag = flags.message;
58522
58624
  const opsJson = flags.ops;
58523
58625
  const opsFile = flags.file;
@@ -58709,6 +58811,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
58709
58811
  operations,
58710
58812
  message,
58711
58813
  committer,
58814
+ componentRef,
58712
58815
  skipExisting,
58713
58816
  includeWouldBeBody: flags["include-would-be-body"] === true,
58714
58817
  progressRequested,
@@ -58737,6 +58840,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
58737
58840
  org,
58738
58841
  repo,
58739
58842
  committer,
58843
+ componentRef,
58740
58844
  message,
58741
58845
  chunkSize,
58742
58846
  progressRequested,
@@ -58749,6 +58853,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
58749
58853
  org,
58750
58854
  repo,
58751
58855
  committer,
58856
+ componentRef,
58752
58857
  message,
58753
58858
  opsFile,
58754
58859
  chunkSize,
@@ -58761,6 +58866,7 @@ var handleSubmit = async (ctx, { flags, args }) => {
58761
58866
  allowNulBytes
58762
58867
  }) : identifyCommitSubmitOutput(await ctx.client.commit.apply(org, repo, message, operations, {
58763
58868
  committer,
58869
+ componentRef,
58764
58870
  skipExisting,
58765
58871
  submissionId,
58766
58872
  ...returnRepoSeq === true ? { returnRepoSeq: true } : {}
@@ -58923,6 +59029,7 @@ function assertServerStreamOptions(ctx, flags, source) {
58923
59029
  userInput("--submission-id must be a UUID.");
58924
59030
  }
58925
59031
  const incompatible = [
59032
+ ["--component-ref", flags["component-ref"] !== undefined],
58926
59033
  ["--chunk-size", flags["chunk-size"] !== undefined],
58927
59034
  ["--skip-existing", flags["skip-existing"] === true],
58928
59035
  ["--progress", flags.progress === true],
@@ -61574,7 +61681,7 @@ async function checkRepoLicenseDeclaration(ctx, repo, repoInfo) {
61574
61681
  name: "repo-license",
61575
61682
  status: "warn",
61576
61683
  message: `Public repo ${safeRepoRef} has no repository license declaration.`,
61577
- detail: `Choose the correct license, then create the native LicenseSubject/repo thing and LicenseDeclaration/repo assertion. Set spdxIdRaw and, when applicable, licenseWref to a canonical License in ${LICENSE_SUBSTRATE}. No component installation is required.`
61684
+ detail: `Choose the correct license, then create the native LicenseSubject/license/subject thing and the LicenseDeclaration/license assertion about it. Set spdxIdRaw and, when applicable, licenseWref to a canonical License in ${LICENSE_SUBSTRATE}. No component installation is required.`
61578
61685
  };
61579
61686
  } catch (error51) {
61580
61687
  const failure = classifyDoctorLookupError(error51);
@@ -69699,9 +69806,17 @@ async function runPreparedCli(rawArgv, prepared, opts) {
69699
69806
  requestedMode: requestedFunctionLogs
69700
69807
  });
69701
69808
  const localOnlyCommand = isLocalOnlyInvocation(invocation);
69702
- const { config: config2, client, profile, clientFlags, decorate } = localOnlyCommand ? {
69809
+ const {
69810
+ config: config2,
69811
+ client,
69812
+ compatibilityClient,
69813
+ profile,
69814
+ clientFlags,
69815
+ decorate
69816
+ } = localOnlyCommand ? {
69703
69817
  config: loadConfig(),
69704
69818
  client: createLocalOnlyClient(),
69819
+ compatibilityClient: undefined,
69705
69820
  profile: "default",
69706
69821
  clientFlags: [],
69707
69822
  decorate: true
@@ -69722,6 +69837,7 @@ async function runPreparedCli(rawArgv, prepared, opts) {
69722
69837
  const signal = abortController.signal;
69723
69838
  const commandContext = {
69724
69839
  client,
69840
+ compatibilityClient,
69725
69841
  config: config2,
69726
69842
  invocation,
69727
69843
  profile,
@@ -69848,7 +69964,7 @@ function resolveLogLevel(flagLevel, env) {
69848
69964
  // package.json
69849
69965
  var package_default3 = {
69850
69966
  name: "@warmhub/cli",
69851
- version: "0.132.2",
69967
+ version: "0.134.0",
69852
69968
  private: false,
69853
69969
  type: "module",
69854
69970
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -70473,5 +70589,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
70473
70589
  version: package_default3.version
70474
70590
  }) : interceptedExitCode;
70475
70591
 
70476
- //# debugId=FFF74F1A1894DD3464756E2164756E21
70477
- //# warmhub-cli-build-info {"cliVersion":"0.132.2","sdkVersion":"0.130.2"}
70592
+ //# debugId=59E58BA2C90F5E3C64756E2164756E21
70593
+ //# warmhub-cli-build-info {"cliVersion":"0.134.0","sdkVersion":"0.132.0"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmhub/cli",
3
- "version": "0.132.2",
3
+ "version": "0.134.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.",