@warmhub/cli 0.101.0 → 0.103.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 +247 -198
  2. package/package.json +1 -1
package/dist/wh.js CHANGED
@@ -20614,6 +20614,99 @@ function joinFieldIdentityPath(...segments) {
20614
20614
  function joinFieldPathWithEscaper(escapeSegment, segments) {
20615
20615
  return segments.map((segment) => typeof segment === "number" ? `[${segment}]` : escapeSegment(segment)).join(".").replace(/\.\[/g, "[");
20616
20616
  }
20617
+ // ../../packages/rules/src/operation-event-identity.ts
20618
+ var STREAM_CHUNK_NAMESPACE = "003e7e6c-2f1e-53ea-9dfa-627edd04a8cc";
20619
+ var CANONICAL_UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
20620
+ function uuidBytes(value) {
20621
+ if (!CANONICAL_UUID.test(value)) {
20622
+ throw new Error("Operation-event submission ID must be a canonical UUID");
20623
+ }
20624
+ const hex = value.toLowerCase().replaceAll("-", "");
20625
+ return Uint8Array.from({ length: 16 }, (_, index) => Number.parseInt(hex.slice(index * 2, index * 2 + 2), 16));
20626
+ }
20627
+ function rotateLeft(value, bits) {
20628
+ return (value << bits | value >>> 32 - bits) >>> 0;
20629
+ }
20630
+ function sha1(input) {
20631
+ const bitLength = input.length * 8;
20632
+ const paddedLength = Math.ceil((input.length + 9) / 64) * 64;
20633
+ const padded = new Uint8Array(paddedLength);
20634
+ padded.set(input);
20635
+ padded[input.length] = 128;
20636
+ const view = new DataView(padded.buffer);
20637
+ view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296));
20638
+ view.setUint32(paddedLength - 4, bitLength >>> 0);
20639
+ let h0 = 1732584193;
20640
+ let h1 = 4023233417;
20641
+ let h2 = 2562383102;
20642
+ let h3 = 271733878;
20643
+ let h4 = 3285377520;
20644
+ const words = new Uint32Array(80);
20645
+ for (let offset = 0;offset < paddedLength; offset += 64) {
20646
+ for (let index = 0;index < 16; index += 1) {
20647
+ words[index] = view.getUint32(offset + index * 4);
20648
+ }
20649
+ for (let index = 16;index < 80; index += 1) {
20650
+ words[index] = rotateLeft((words[index - 3] ?? 0) ^ (words[index - 8] ?? 0) ^ (words[index - 14] ?? 0) ^ (words[index - 16] ?? 0), 1);
20651
+ }
20652
+ let a = h0;
20653
+ let b = h1;
20654
+ let c = h2;
20655
+ let d = h3;
20656
+ let e = h4;
20657
+ for (let index = 0;index < 80; index += 1) {
20658
+ let f;
20659
+ let k;
20660
+ if (index < 20) {
20661
+ f = b & c | ~b & d;
20662
+ k = 1518500249;
20663
+ } else if (index < 40) {
20664
+ f = b ^ c ^ d;
20665
+ k = 1859775393;
20666
+ } else if (index < 60) {
20667
+ f = b & c | b & d | c & d;
20668
+ k = 2400959708;
20669
+ } else {
20670
+ f = b ^ c ^ d;
20671
+ k = 3395469782;
20672
+ }
20673
+ const next = rotateLeft(a, 5) + f + e + k + (words[index] ?? 0) >>> 0;
20674
+ e = d;
20675
+ d = c;
20676
+ c = rotateLeft(b, 30);
20677
+ b = a;
20678
+ a = next;
20679
+ }
20680
+ h0 = h0 + a >>> 0;
20681
+ h1 = h1 + b >>> 0;
20682
+ h2 = h2 + c >>> 0;
20683
+ h3 = h3 + d >>> 0;
20684
+ h4 = h4 + e >>> 0;
20685
+ }
20686
+ const digest = new Uint8Array(20);
20687
+ const digestView = new DataView(digest.buffer);
20688
+ for (const [index, value] of [h0, h1, h2, h3, h4].entries()) {
20689
+ digestView.setUint32(index * 4, value);
20690
+ }
20691
+ return digest;
20692
+ }
20693
+ function formatUuid(bytes) {
20694
+ const hex = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 32);
20695
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
20696
+ }
20697
+ function operationEventStreamRequestId(submissionId, chunkOrdinal) {
20698
+ if (!Number.isInteger(chunkOrdinal) || chunkOrdinal < 0 || chunkOrdinal > 2147483647) {
20699
+ throw new Error("Stream chunk ordinal must be an integer from 0 through 2147483647");
20700
+ }
20701
+ uuidBytes(submissionId);
20702
+ const normalizedSubmissionId = submissionId.toLowerCase();
20703
+ const namespace = uuidBytes(STREAM_CHUNK_NAMESPACE);
20704
+ const name = new TextEncoder().encode(`${normalizedSubmissionId}:${chunkOrdinal}`);
20705
+ const digest = sha1(Uint8Array.from([...namespace, ...name])).slice(0, 16);
20706
+ digest[6] = (digest[6] ?? 0) & 15 | 80;
20707
+ digest[8] = (digest[8] ?? 0) & 63 | 128;
20708
+ return formatUuid(digest);
20709
+ }
20617
20710
  // ../../packages/rules/src/org-qualified-ref.ts
20618
20711
  function splitOrgQualified(ref) {
20619
20712
  const parts = ref.split("/");
@@ -35180,11 +35273,58 @@ function date4(params) {
35180
35273
 
35181
35274
  // ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
35182
35275
  config(en_default());
35276
+ // ../../packages/rules/src/repository-checkpoint/hash.ts
35277
+ var utf8Encoder = new TextEncoder;
35278
+ async function checkpointSha256Hex(bytes) {
35279
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes)));
35280
+ return Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("");
35281
+ }
35282
+ function checkpointUtf8Bytes(value) {
35283
+ assertCheckpointText(value);
35284
+ return utf8Encoder.encode(value);
35285
+ }
35286
+ function assertCheckpointText(value) {
35287
+ for (let index = 0;index < value.length; index += 1) {
35288
+ const codeUnit = value.charCodeAt(index);
35289
+ if (codeUnit >= 55296 && codeUnit <= 56319) {
35290
+ const trailing = value.charCodeAt(index + 1);
35291
+ if (!(trailing >= 56320 && trailing <= 57343)) {
35292
+ throw new RangeError("Checkpoint text must be valid Unicode");
35293
+ }
35294
+ index += 1;
35295
+ } else if (codeUnit >= 56320 && codeUnit <= 57343) {
35296
+ throw new RangeError("Checkpoint text must be valid Unicode");
35297
+ }
35298
+ }
35299
+ }
35300
+
35301
+ // ../../packages/rules/src/repository-checkpoint/order.ts
35302
+ function compareUnsignedUtf8(left, right) {
35303
+ assertCheckpointText(left);
35304
+ assertCheckpointText(right);
35305
+ let leftIndex = 0;
35306
+ let rightIndex = 0;
35307
+ while (leftIndex < left.length && rightIndex < right.length) {
35308
+ const leftCodePoint = left.codePointAt(leftIndex);
35309
+ const rightCodePoint = right.codePointAt(rightIndex);
35310
+ if (leftCodePoint === undefined || rightCodePoint === undefined)
35311
+ break;
35312
+ const difference = leftCodePoint - rightCodePoint;
35313
+ if (difference !== 0)
35314
+ return difference;
35315
+ leftIndex += leftCodePoint > 65535 ? 2 : 1;
35316
+ rightIndex += rightCodePoint > 65535 ? 2 : 1;
35317
+ }
35318
+ if (leftIndex === left.length && rightIndex === right.length)
35319
+ return 0;
35320
+ return leftIndex === left.length ? -1 : 1;
35321
+ }
35322
+
35183
35323
  // ../../packages/rules/src/repository-checkpoint/types.ts
35184
35324
  var CHECKPOINT_CHUNK_BYTE_LIMIT = 67108864;
35185
35325
  var CHECKPOINT_PART_DIGITS = 10;
35186
35326
  var CHECKPOINT_FORMAT = "warmhub-repository-checkpoint";
35187
- var CHECKPOINT_FORMAT_VERSION = 1;
35327
+ var CHECKPOINT_FORMAT_VERSION = 2;
35188
35328
  var CHECKPOINT_MANIFEST_NAME = "repository-checkpoint.json";
35189
35329
  var checkpointSha256Schema = exports_external.string().regex(/^[0-9a-f]{64}$/);
35190
35330
  var nonnegativeSafeIntegerSchema = exports_external.number().int().nonnegative().safe();
@@ -35205,7 +35345,20 @@ var checkpointRowBaseSchema = exports_external.object({
35205
35345
  active: exports_external.literal(true),
35206
35346
  data: jsonValueSchema
35207
35347
  });
35208
- var pinnedWrefSchema = exports_external.string().regex(/^[^\r\n]+@v[1-9]\d*$/);
35348
+ var pinnedWrefSchema = exports_external.string().regex(/^[^\r\n]+@v[1-9]\d*$/, "Checkpoint wref must be pinned with @vN");
35349
+ var affirmedWrefsSchema = exports_external.array(pinnedWrefSchema).superRefine((wrefs, context) => {
35350
+ for (let index = 1;index < wrefs.length; index += 1) {
35351
+ const previous = wrefs[index - 1];
35352
+ const current = wrefs[index];
35353
+ if (previous !== undefined && current !== undefined && compareUnsignedUtf8(previous, current) >= 0) {
35354
+ context.addIssue({
35355
+ code: "custom",
35356
+ path: [index],
35357
+ message: "Affirmed wrefs must be unique and strictly increasing"
35358
+ });
35359
+ }
35360
+ }
35361
+ });
35209
35362
  var checkpointRowSchema = exports_external.discriminatedUnion("kind", [
35210
35363
  checkpointRowBaseSchema.extend({ kind: exports_external.literal("shape") }).strict(),
35211
35364
  checkpointRowBaseSchema.extend({
@@ -35215,7 +35368,8 @@ var checkpointRowSchema = exports_external.discriminatedUnion("kind", [
35215
35368
  checkpointRowBaseSchema.extend({
35216
35369
  kind: exports_external.literal("assertion"),
35217
35370
  shapeName: exports_external.string().min(1),
35218
- aboutWref: pinnedWrefSchema
35371
+ aboutWref: pinnedWrefSchema,
35372
+ affirmedWrefs: affirmedWrefsSchema
35219
35373
  }).strict()
35220
35374
  ]);
35221
35375
  var checkpointManifestChunkSchema = exports_external.object({
@@ -35245,54 +35399,7 @@ var checkpointManifestFields = {
35245
35399
  streams: exports_external.array(checkpointManifestStreamSchema)
35246
35400
  };
35247
35401
  var checkpointManifestContentSchema = exports_external.object(checkpointManifestFields).strict();
35248
- var checkpointManifestV1Schema = checkpointManifestContentSchema.extend({ contentSha256: checkpointSha256Schema }).strict();
35249
-
35250
- // ../../packages/rules/src/repository-checkpoint/hash.ts
35251
- var utf8Encoder = new TextEncoder;
35252
- async function checkpointSha256Hex(bytes) {
35253
- const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", Uint8Array.from(bytes)));
35254
- return Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("");
35255
- }
35256
- function checkpointUtf8Bytes(value) {
35257
- assertCheckpointText(value);
35258
- return utf8Encoder.encode(value);
35259
- }
35260
- function assertCheckpointText(value) {
35261
- for (let index = 0;index < value.length; index += 1) {
35262
- const codeUnit = value.charCodeAt(index);
35263
- if (codeUnit >= 55296 && codeUnit <= 56319) {
35264
- const trailing = value.charCodeAt(index + 1);
35265
- if (!(trailing >= 56320 && trailing <= 57343)) {
35266
- throw new RangeError("Checkpoint text must be valid Unicode");
35267
- }
35268
- index += 1;
35269
- } else if (codeUnit >= 56320 && codeUnit <= 57343) {
35270
- throw new RangeError("Checkpoint text must be valid Unicode");
35271
- }
35272
- }
35273
- }
35274
-
35275
- // ../../packages/rules/src/repository-checkpoint/order.ts
35276
- function compareUnsignedUtf8(left, right) {
35277
- assertCheckpointText(left);
35278
- assertCheckpointText(right);
35279
- let leftIndex = 0;
35280
- let rightIndex = 0;
35281
- while (leftIndex < left.length && rightIndex < right.length) {
35282
- const leftCodePoint = left.codePointAt(leftIndex);
35283
- const rightCodePoint = right.codePointAt(rightIndex);
35284
- if (leftCodePoint === undefined || rightCodePoint === undefined)
35285
- break;
35286
- const difference = leftCodePoint - rightCodePoint;
35287
- if (difference !== 0)
35288
- return difference;
35289
- leftIndex += leftCodePoint > 65535 ? 2 : 1;
35290
- rightIndex += rightCodePoint > 65535 ? 2 : 1;
35291
- }
35292
- if (leftIndex === left.length && rightIndex === right.length)
35293
- return 0;
35294
- return leftIndex === left.length ? -1 : 1;
35295
- }
35402
+ var checkpointManifestV2Schema = checkpointManifestContentSchema.extend({ contentSha256: checkpointSha256Schema }).strict();
35296
35403
 
35297
35404
  // ../../packages/rules/src/repository-checkpoint/paths.ts
35298
35405
  var MAX_CHECKPOINT_PART = 10 ** CHECKPOINT_PART_DIGITS - 1;
@@ -35322,7 +35429,7 @@ function assertCheckpointPart(part) {
35322
35429
  // ../../packages/rules/src/repository-checkpoint/manifest.ts
35323
35430
  var utf8Decoder = new TextDecoder("utf-8", { fatal: true });
35324
35431
  async function validateCheckpointManifest(input) {
35325
- const manifest = checkpointManifestV1Schema.parse(input);
35432
+ const manifest = checkpointManifestV2Schema.parse(input);
35326
35433
  const { contentSha256, ...content } = manifest;
35327
35434
  await validateCheckpointManifestContent(content);
35328
35435
  const expectedDigest = await checkpointManifestContentSha256(content);
@@ -35339,7 +35446,7 @@ async function encodeCheckpointManifest(input) {
35339
35446
  async function parseCheckpointManifest(bytes) {
35340
35447
  assertCanonicalManifestFraming(bytes);
35341
35448
  const decoded = utf8Decoder.decode(bytes);
35342
- const manifest = await validateCheckpointManifest(checkpointManifestV1Schema.parse(JSON.parse(decoded.slice(0, -1))));
35449
+ const manifest = await validateCheckpointManifest(checkpointManifestV2Schema.parse(JSON.parse(decoded.slice(0, -1))));
35343
35450
  const canonical = await encodeCheckpointManifest(manifest);
35344
35451
  if (!bytesEqual(bytes, canonical)) {
35345
35452
  throw new Error("Checkpoint manifest bytes are not canonical");
@@ -43400,85 +43507,6 @@ class StreamSubmissionAggregator {
43400
43507
  }
43401
43508
  }
43402
43509
  // ../../packages/sdk-ts/src/operation-event-identity.ts
43403
- var STREAM_CHUNK_NAMESPACE = "003e7e6c-2f1e-53ea-9dfa-627edd04a8cc";
43404
- var CANONICAL_UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
43405
- function uuidBytes(value) {
43406
- if (!CANONICAL_UUID.test(value)) {
43407
- throw new Error("Operation-event submission ID must be a canonical UUID");
43408
- }
43409
- const hex3 = value.toLowerCase().replaceAll("-", "");
43410
- return Uint8Array.from({ length: 16 }, (_, index) => Number.parseInt(hex3.slice(index * 2, index * 2 + 2), 16));
43411
- }
43412
- function rotateLeft(value, bits) {
43413
- return (value << bits | value >>> 32 - bits) >>> 0;
43414
- }
43415
- function sha1(input) {
43416
- const bitLength = input.length * 8;
43417
- const paddedLength = Math.ceil((input.length + 9) / 64) * 64;
43418
- const padded = new Uint8Array(paddedLength);
43419
- padded.set(input);
43420
- padded[input.length] = 128;
43421
- const view = new DataView(padded.buffer);
43422
- view.setUint32(paddedLength - 8, Math.floor(bitLength / 4294967296));
43423
- view.setUint32(paddedLength - 4, bitLength >>> 0);
43424
- let h0 = 1732584193;
43425
- let h1 = 4023233417;
43426
- let h2 = 2562383102;
43427
- let h3 = 271733878;
43428
- let h4 = 3285377520;
43429
- const words = new Uint32Array(80);
43430
- for (let offset = 0;offset < paddedLength; offset += 64) {
43431
- for (let index = 0;index < 16; index += 1) {
43432
- words[index] = view.getUint32(offset + index * 4);
43433
- }
43434
- for (let index = 16;index < 80; index += 1) {
43435
- words[index] = rotateLeft(words[index - 3] ^ words[index - 8] ^ words[index - 14] ^ words[index - 16], 1);
43436
- }
43437
- let a = h0;
43438
- let b = h1;
43439
- let c = h2;
43440
- let d = h3;
43441
- let e = h4;
43442
- for (let index = 0;index < 80; index += 1) {
43443
- let f;
43444
- let k;
43445
- if (index < 20) {
43446
- f = b & c | ~b & d;
43447
- k = 1518500249;
43448
- } else if (index < 40) {
43449
- f = b ^ c ^ d;
43450
- k = 1859775393;
43451
- } else if (index < 60) {
43452
- f = b & c | b & d | c & d;
43453
- k = 2400959708;
43454
- } else {
43455
- f = b ^ c ^ d;
43456
- k = 3395469782;
43457
- }
43458
- const next = rotateLeft(a, 5) + f + e + k + words[index] >>> 0;
43459
- e = d;
43460
- d = c;
43461
- c = rotateLeft(b, 30);
43462
- b = a;
43463
- a = next;
43464
- }
43465
- h0 = h0 + a >>> 0;
43466
- h1 = h1 + b >>> 0;
43467
- h2 = h2 + c >>> 0;
43468
- h3 = h3 + d >>> 0;
43469
- h4 = h4 + e >>> 0;
43470
- }
43471
- const digest = new Uint8Array(20);
43472
- const digestView = new DataView(digest.buffer);
43473
- for (const [index, value] of [h0, h1, h2, h3, h4].entries()) {
43474
- digestView.setUint32(index * 4, value);
43475
- }
43476
- return digest;
43477
- }
43478
- function formatUuid(bytes) {
43479
- const hex3 = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, 32);
43480
- return `${hex3.slice(0, 8)}-${hex3.slice(8, 12)}-${hex3.slice(12, 16)}-${hex3.slice(16, 20)}-${hex3.slice(20)}`;
43481
- }
43482
43510
  function createOperationEventSubmissionId() {
43483
43511
  const submissionId = globalThis.crypto?.randomUUID?.();
43484
43512
  if (!submissionId) {
@@ -43487,19 +43515,6 @@ function createOperationEventSubmissionId() {
43487
43515
  return submissionId.toLowerCase();
43488
43516
  }
43489
43517
  var createOperationEventRequestId = createOperationEventSubmissionId;
43490
- function operationEventStreamRequestId(submissionId, chunkOrdinal) {
43491
- if (!Number.isInteger(chunkOrdinal) || chunkOrdinal < 0 || chunkOrdinal > 2147483647) {
43492
- throw new Error("Stream chunk ordinal must be an integer from 0 through 2147483647");
43493
- }
43494
- uuidBytes(submissionId);
43495
- const normalizedSubmissionId = submissionId.toLowerCase();
43496
- const namespace = uuidBytes(STREAM_CHUNK_NAMESPACE);
43497
- const name = new TextEncoder().encode(`${normalizedSubmissionId}:${chunkOrdinal}`);
43498
- const digest = sha1(Uint8Array.from([...namespace, ...name])).slice(0, 16);
43499
- digest[6] = digest[6] & 15 | 80;
43500
- digest[8] = digest[8] & 63 | 128;
43501
- return formatUuid(digest);
43502
- }
43503
43518
 
43504
43519
  // ../../packages/sdk-ts/src/stream-submit-types.ts
43505
43520
  var DEFAULT_STREAM_CHUNK_SIZE = DEFAULT_STREAM_APPEND_CHUNK_SIZE;
@@ -44481,7 +44496,7 @@ function createStreamingSubmissionHandle(input, deps) {
44481
44496
  // ../../packages/sdk-ts/package.json
44482
44497
  var package_default = {
44483
44498
  name: "@warmhub/sdk-ts",
44484
- version: "0.99.0",
44499
+ version: "0.101.0",
44485
44500
  private: false,
44486
44501
  type: "module",
44487
44502
  description: "The TypeScript SDK for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -48065,6 +48080,8 @@ function redactArgv(argv) {
48065
48080
  const out = [];
48066
48081
  for (let i = 0;i < argv.length; i++) {
48067
48082
  const arg = argv[i];
48083
+ if (arg === undefined)
48084
+ continue;
48068
48085
  const eqIdx = arg.indexOf("=");
48069
48086
  if (eqIdx > 0) {
48070
48087
  const lhs = arg.slice(0, eqIdx);
@@ -48286,7 +48303,7 @@ function withLogRotationLock(dir, append) {
48286
48303
  releaseRotateLock(heldLock);
48287
48304
  }
48288
48305
  }
48289
- function rotateIfNeeded(path, dir, hooks) {
48306
+ function rotateIfNeeded(path, dir, options) {
48290
48307
  if (!existsSync2(path))
48291
48308
  return;
48292
48309
  let size;
@@ -48297,12 +48314,12 @@ function rotateIfNeeded(path, dir, hooks) {
48297
48314
  }
48298
48315
  if (size <= FILE_CAP_BYTES)
48299
48316
  return;
48300
- const heldLock = tryAcquireRotateLock(dir, ROTATE_LOCK_TIMEOUT_MS);
48317
+ const heldLock = tryAcquireRotateLock(dir, options?.lockTimeoutMs ?? ROTATE_LOCK_TIMEOUT_MS);
48301
48318
  if (!heldLock)
48302
48319
  return;
48303
48320
  try {
48304
48321
  const raw = readFileSync(path);
48305
- hooks?.afterSnapshot?.();
48322
+ options?.afterSnapshot?.();
48306
48323
  let cut = raw.length - FILE_RETAIN_BYTES;
48307
48324
  if (cut < 0)
48308
48325
  cut = 0;
@@ -48421,7 +48438,7 @@ function parseLockOwner(raw) {
48421
48438
  }
48422
48439
  } catch {}
48423
48440
  const rawPid = raw.split(":", 1)[0];
48424
- if (!/^\d+$/.test(rawPid))
48441
+ if (rawPid === undefined || !/^\d+$/.test(rawPid))
48425
48442
  return null;
48426
48443
  const pid = Number(rawPid);
48427
48444
  return Number.isSafeInteger(pid) && pid > 0 ? { pid, processStart: null } : null;
@@ -48724,7 +48741,10 @@ function isExpired(tokens) {
48724
48741
  }
48725
48742
  function safeDecodeExpiry(jwt2) {
48726
48743
  try {
48727
- const payload = JSON.parse(Buffer.from(jwt2.split(".")[1], "base64url").toString());
48744
+ const encodedPayload = jwt2.split(".")[1];
48745
+ if (encodedPayload === undefined)
48746
+ return null;
48747
+ const payload = JSON.parse(Buffer.from(encodedPayload, "base64url").toString());
48728
48748
  if (typeof payload.exp === "number") {
48729
48749
  return new Date(payload.exp * 1000).toISOString();
48730
48750
  }
@@ -48997,7 +49017,7 @@ function ownerPid(ownerToken) {
48997
49017
  }
48998
49018
  function ownerIdentity(ownerToken) {
48999
49019
  const [, , identity2, nonce] = ownerToken.trim().split(":", 4);
49000
- return nonce && /^[a-f0-9]{64}$/.test(identity2 ?? "") ? identity2 : null;
49020
+ return nonce && identity2 && /^[a-f0-9]{64}$/.test(identity2) ? identity2 : null;
49001
49021
  }
49002
49022
  function processStillOwnsClaim(pid, identity2) {
49003
49023
  if (pid === null)
@@ -49263,7 +49283,9 @@ function saveProfileWhileLocked(name, profile, path) {
49263
49283
  function getProfile(name, path) {
49264
49284
  const p = path ?? getAuthPath();
49265
49285
  const store = loadProfileStore(p);
49266
- return hasProfile(store, name) ? store.profiles[name] : null;
49286
+ if (!hasProfile(store, name))
49287
+ return null;
49288
+ return store.profiles[name] ?? null;
49267
49289
  }
49268
49290
  async function modifyStore(mutator, path) {
49269
49291
  const p = path ?? getAuthPath();
@@ -50431,9 +50453,10 @@ class DomainRegistry {
50431
50453
  }
50432
50454
  }
50433
50455
  resolveDomain(tokens) {
50434
- if (tokens.length < 1)
50456
+ const rootToken = tokens[0];
50457
+ if (rootToken === undefined)
50435
50458
  return;
50436
- const domain2 = this.domains.get(tokens[0]);
50459
+ const domain2 = this.domains.get(rootToken);
50437
50460
  if (!domain2)
50438
50461
  return;
50439
50462
  if (domain2.kind === "flat") {
@@ -50447,9 +50470,15 @@ class DomainRegistry {
50447
50470
  let cursor = domain2;
50448
50471
  const path = [domain2.name];
50449
50472
  let i = 1;
50450
- while (cursor.kind === "noun" && cursor.subdomains && i < tokens.length && cursor.subdomains[tokens[i]]) {
50451
- cursor = cursor.subdomains[tokens[i]];
50452
- path.push(tokens[i]);
50473
+ while (cursor.kind === "noun" && cursor.subdomains && i < tokens.length) {
50474
+ const token = tokens[i];
50475
+ if (token === undefined)
50476
+ break;
50477
+ const subdomain = cursor.subdomains[token];
50478
+ if (subdomain === undefined)
50479
+ break;
50480
+ cursor = subdomain;
50481
+ path.push(token);
50453
50482
  i++;
50454
50483
  }
50455
50484
  if (cursor.kind === "flat") {
@@ -51063,11 +51092,26 @@ function levenshtein(a, b) {
51063
51092
  const m = a.length, n = b.length;
51064
51093
  const dp = Array.from({ length: m + 1 }, (_, i) => Array.from({ length: n + 1 }, (_2, j) => i === 0 ? j : j === 0 ? i : 0));
51065
51094
  for (let i = 1;i <= m; i++) {
51095
+ const row = dp[i];
51096
+ const previousRow = dp[i - 1];
51097
+ if (row === undefined || previousRow === undefined) {
51098
+ throw new RangeError("Levenshtein matrix row is missing");
51099
+ }
51066
51100
  for (let j = 1;j <= n; j++) {
51067
- dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
51101
+ const diagonal = previousRow[j - 1];
51102
+ const above = previousRow[j];
51103
+ const left = row[j - 1];
51104
+ if (diagonal === undefined || above === undefined || left === undefined) {
51105
+ throw new RangeError("Levenshtein matrix cell is missing");
51106
+ }
51107
+ row[j] = a[i - 1] === b[j - 1] ? diagonal : 1 + Math.min(above, left, diagonal);
51068
51108
  }
51069
51109
  }
51070
- return dp[m][n];
51110
+ const distance = dp[m]?.[n];
51111
+ if (distance === undefined) {
51112
+ throw new RangeError("Levenshtein result is missing");
51113
+ }
51114
+ return distance;
51071
51115
  }
51072
51116
  function findClosest(input, candidates, maxDistance = 2) {
51073
51117
  let best;
@@ -53703,7 +53747,8 @@ var handleView = async (ctx, { flags, args, terminator }) => {
53703
53747
  file: flags.file,
53704
53748
  stdin: ctx.stdin ?? process.stdin
53705
53749
  });
53706
- if (wrefs.length === 0) {
53750
+ const singleWref = wrefs[0];
53751
+ if (singleWref === undefined) {
53707
53752
  throw new CliError(2 /* UserInput */, "USER_INPUT", "Missing required <wref>. Pass a wref as a positional arg, via --file <path>, or pipe newline-delimited wrefs on stdin.", undefined, "Example: wh thing view Game/base --depth 2");
53708
53753
  }
53709
53754
  if (wrefs.length > MAX_GET_MANY_WREFS2) {
@@ -53718,7 +53763,6 @@ var handleView = async (ctx, { flags, args, terminator }) => {
53718
53763
  }
53719
53764
  if (isBatch)
53720
53765
  return runBatchView(ctx, wrefs, flags);
53721
- const [singleWref] = wrefs;
53722
53766
  return runSingleView(ctx, singleWref, flags);
53723
53767
  };
53724
53768
 
@@ -54689,13 +54733,7 @@ var handleLogin = async (ctx, { flags }) => {
54689
54733
  deadline: Date.now() + device.expires_in * 1000,
54690
54734
  signal: ctx.signal
54691
54735
  });
54692
- let expiresAt;
54693
- try {
54694
- const payload = JSON.parse(Buffer.from(tokenResponse.access_token.split(".")[1], "base64url").toString());
54695
- expiresAt = typeof payload.exp === "number" ? new Date(payload.exp * 1000).toISOString() : new Date(Date.now() + 5 * 60 * 1000).toISOString();
54696
- } catch {
54697
- expiresAt = new Date(Date.now() + 5 * 60 * 1000).toISOString();
54698
- }
54736
+ const expiresAt = accessTokenExpiry(tokenResponse.access_token);
54699
54737
  await saveProfileWithFlagsLocked(profile, {
54700
54738
  tokens: {
54701
54739
  accessToken: tokenResponse.access_token,
@@ -54861,7 +54899,10 @@ function parseFramedBody(buffer, maxContentLength, bufferByteLength) {
54861
54899
  const match = CONTENT_LENGTH_RE.exec(header);
54862
54900
  if (!match)
54863
54901
  return null;
54864
- const contentLength = parseInt(match[1], 10);
54902
+ const rawContentLength = match[1];
54903
+ if (rawContentLength === undefined)
54904
+ return null;
54905
+ const contentLength = parseInt(rawContentLength, 10);
54865
54906
  if (contentLength > maxContentLength) {
54866
54907
  throw new RangeError(`Content-Length ${contentLength} exceeds the maximum allowed ${maxContentLength} bytes`);
54867
54908
  }
@@ -60591,14 +60632,14 @@ async function collectChecks(ctx) {
60591
60632
  }
60592
60633
  }
60593
60634
  const settingsHealth = await checkClaudeSettingsHealth(harnessPaths);
60594
- if (settingsHealth.malformedFiles.length > 0) {
60595
- const first = settingsHealth.malformedFiles[0];
60635
+ const firstMalformedFile = settingsHealth.malformedFiles[0];
60636
+ if (firstMalformedFile !== undefined) {
60596
60637
  checks3.push({
60597
60638
  key: "claude-settings-health",
60598
60639
  name: "claude-settings-health",
60599
60640
  status: "fail",
60600
- message: `Malformed Claude settings JSON in ${first.path}`,
60601
- detail: first.error,
60641
+ message: `Malformed Claude settings JSON in ${firstMalformedFile.path}`,
60642
+ detail: firstMalformedFile.error,
60602
60643
  fix: "Fix malformed JSON manually, then rerun doctor"
60603
60644
  });
60604
60645
  } else {
@@ -61318,8 +61359,9 @@ data of their own. You read; they watch the data model become legible.
61318
61359
  2. Describe the repo at a high level: call \`warmhub_repo_describe\` and summarize
61319
61360
  what kinds of things it holds, in plain language (1–2 sentences). **Wait.**
61320
61361
  3. Pull a few real records: call \`warmhub_thing_query\` (filter by a shape) and
61321
- then \`warmhub_thing_get\` on one interesting result. Show them one concrete
61322
- thing and explain what its fields mean. **Wait.**
61362
+ then \`warmhub_thing_get\` with \`wrefs: [...]\` on the interesting results it
61363
+ takes a list, so fetch them in one call. Show them one concrete thing and
61364
+ explain what its fields mean. **Wait.**
61323
61365
  4. The bridge moment: ask them a real question about the repo, then answer it by
61324
61366
  querying — so they see the agent get an answer *they didn't have to write*.
61325
61367
 
@@ -61346,8 +61388,9 @@ authored by their agent lands in a repo of their own.
61346
61388
  definition and a short note (a \`Note\` that says they finished onboarding)
61347
61389
  together in one commit. Tell them what you're saving first, then save it.
61348
61390
  **Wait** for their go-ahead before writing.
61349
- 5. Confirm the write: read it back (\`warmhub_thing_get\`) and tell them the commit
61350
- landed and that it's attributed to this agent.
61391
+ 5. Confirm the write: read it back (\`warmhub_thing_get\` with the new wref in
61392
+ \`wrefs\`) and tell them the commit landed and that it's attributed to this
61393
+ agent.
61351
61394
 
61352
61395
  **Done when:** a commit authored by their connected agent exists on HEAD of a
61353
61396
  repo they own, and you've read it back to confirm.
@@ -61378,6 +61421,7 @@ identical for every agent; only the connection details in the header above diffe
61378
61421
 
61379
61422
  // ../../packages/warmhub-cli/src/domains/onboard.ts
61380
61423
  var NEUTRAL_ASK = "present the options as a short numbered list and wait for the user to choose before continuing.";
61424
+ var SUPPORTED_AGENTS = ["claude", "gemini", "codex", "cursor"];
61381
61425
  var ADAPTERS = {
61382
61426
  claude: {
61383
61427
  header: claude_default,
@@ -61396,13 +61440,15 @@ var ADAPTERS = {
61396
61440
  ask: NEUTRAL_ASK
61397
61441
  }
61398
61442
  };
61399
- var SUPPORTED_AGENTS = Object.keys(ADAPTERS);
61443
+ function isSupportedAgent(agent) {
61444
+ return SUPPORTED_AGENTS.some((supported) => supported === agent);
61445
+ }
61400
61446
  function buildOnboarding(opts = {}) {
61401
- const ask = opts.agent ? ADAPTERS[opts.agent].ask : NEUTRAL_ASK;
61402
- const body = onboard_content_default.trimEnd().replace("{{ASK_PRIMITIVE}}", ask);
61403
- if (!opts.agent)
61447
+ const adapter = opts.agent === undefined ? null : ADAPTERS[opts.agent];
61448
+ const body = onboard_content_default.trimEnd().replace("{{ASK_PRIMITIVE}}", adapter === null ? NEUTRAL_ASK : adapter.ask);
61449
+ if (adapter === null)
61404
61450
  return body;
61405
- const header = ADAPTERS[opts.agent].header.trimEnd();
61451
+ const header = adapter.header.trimEnd();
61406
61452
  return `${header}
61407
61453
 
61408
61454
  ---
@@ -61416,7 +61462,7 @@ var onboardFlags = {
61416
61462
  };
61417
61463
  var handleOnboard = async (ctx, { flags }) => {
61418
61464
  const agent = flags.agent;
61419
- if (agent !== undefined && !SUPPORTED_AGENTS.includes(agent)) {
61465
+ if (agent !== undefined && !isSupportedAgent(agent)) {
61420
61466
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Unknown agent '${agent}'.`, undefined, `Supported agents: ${SUPPORTED_AGENTS.join(", ")}. Omit --agent for the model-agnostic script.`);
61421
61467
  }
61422
61468
  const script = buildOnboarding({ agent });
@@ -65532,20 +65578,21 @@ function formatAllowedMatches(allowedMatches) {
65532
65578
  }
65533
65579
 
65534
65580
  // ../../packages/warmhub-cli/src/domains/token.ts
65581
+ var DURATION_MULTIPLIERS = {
65582
+ h: 3600000,
65583
+ d: 86400000,
65584
+ m: 30 * 86400000,
65585
+ y: 365 * 86400000
65586
+ };
65535
65587
  function parseDuration(input) {
65536
65588
  const match = input.match(/^(\d+)([dhmy])$/);
65537
- if (!match) {
65589
+ const rawValue = match?.[1];
65590
+ const unit = match?.[2];
65591
+ const multiplier = unit === undefined ? undefined : DURATION_MULTIPLIERS[unit];
65592
+ if (rawValue === undefined || multiplier === undefined) {
65538
65593
  throw new CliError(2 /* UserInput */, "USER_INPUT", `Invalid duration: "${input}". Expected format: 30d, 90d, 1y`);
65539
65594
  }
65540
- const value = Number(match[1]);
65541
- const unit = match[2];
65542
- const multipliers = {
65543
- h: 3600000,
65544
- d: 86400000,
65545
- m: 30 * 86400000,
65546
- y: 365 * 86400000
65547
- };
65548
- return value * multipliers[unit];
65595
+ return Number(rawValue) * multiplier;
65549
65596
  }
65550
65597
  function tokenStatus(pat) {
65551
65598
  if (pat.revokedAt)
@@ -66556,7 +66603,9 @@ function emitDryRun(ctx, invocation, verb, localFlags) {
66556
66603
  ];
66557
66604
  for (const flag2 of displaySpecs) {
66558
66605
  if (Object.hasOwn(invocation.flags, flag2.long)) {
66559
- flags[flag2.long] = invocation.flags[flag2.long];
66606
+ const value = invocation.flags[flag2.long];
66607
+ if (value !== undefined)
66608
+ flags[flag2.long] = value;
66560
66609
  }
66561
66610
  }
66562
66611
  for (const [long, value] of Object.entries(invocation.flags)) {
@@ -68155,7 +68204,7 @@ function resolveLogLevel(flagLevel, env) {
68155
68204
  // package.json
68156
68205
  var package_default3 = {
68157
68206
  name: "@warmhub/cli",
68158
- version: "0.101.0",
68207
+ version: "0.103.0",
68159
68208
  private: false,
68160
68209
  type: "module",
68161
68210
  description: "The wh CLI for WarmHub — create repos, commit and query data, and compound knowledge with your AI agents.",
@@ -68780,5 +68829,5 @@ process.exitCode = interceptedExitCode === undefined ? await runPreparedCli(laun
68780
68829
  version: package_default3.version
68781
68830
  }) : interceptedExitCode;
68782
68831
 
68783
- //# debugId=D19F329B93F5B10164756E2164756E21
68784
- //# warmhub-cli-build-info {"cliVersion":"0.101.0","sdkVersion":"0.99.0"}
68832
+ //# debugId=9DB78BF7B29E792864756E2164756E21
68833
+ //# warmhub-cli-build-info {"cliVersion":"0.103.0","sdkVersion":"0.101.0"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@warmhub/cli",
3
- "version": "0.101.0",
3
+ "version": "0.103.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.",