midsummer-sol 0.3.6 → 0.3.8

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 (3) hide show
  1. package/package.json +1 -1
  2. package/sol-mcp.js +109 -20
  3. package/sol.js +147 -32
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "midsummer-sol",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Sol — agent-native version control (a new git). CLI, MCP server, and no-filesystem SDK.",
5
5
  "bin": { "sol": "./sol.js", "sol-mcp": "./sol-mcp.js", "sol-secret-mcp": "./sol-secret-mcp.js" },
6
6
  "main": "./index.js",
package/sol-mcp.js CHANGED
@@ -3036,6 +3036,7 @@ __export(exports_lib, {
3036
3036
  allLocalNodes: () => allLocalNodes,
3037
3037
  addInclude: () => addInclude,
3038
3038
  actor: () => actor,
3039
+ acquireLockAt: () => acquireLockAt,
3039
3040
  acquireLock: () => acquireLock,
3040
3041
  LazyStore: () => LazyStore,
3041
3042
  DEFAULT_IGNORE: () => DEFAULT_IGNORE
@@ -3269,9 +3270,9 @@ function pidAlive(pid) {
3269
3270
  return e?.code === "EPERM";
3270
3271
  }
3271
3272
  }
3272
- function acquireLock() {
3273
- const lockFile = join5(lockDir(), "lock");
3274
- const deadline = Date.now() + 15000;
3273
+ function acquireLockAt(lockFile, opts = {}) {
3274
+ const deadline = Date.now() + (opts.timeoutMs ?? 15000);
3275
+ const onTimeout = opts.onTimeout ?? "die";
3275
3276
  for (;; ) {
3276
3277
  try {
3277
3278
  writeFileSync5(lockFile, String(process.pid), { flag: "wx" });
@@ -3294,8 +3295,11 @@ function acquireLock() {
3294
3295
  } catch {
3295
3296
  continue;
3296
3297
  }
3297
- if (Date.now() > deadline)
3298
- die("repo is locked by another sol process (timed out)");
3298
+ if (Date.now() > deadline) {
3299
+ if (onTimeout === "undefined")
3300
+ return;
3301
+ die(opts.timeoutMsg ?? "repo is locked by another sol process (timed out)");
3302
+ }
3299
3303
  sleepSync(25);
3300
3304
  }
3301
3305
  }
@@ -3311,6 +3315,9 @@ function acquireLock() {
3311
3315
  process.on("exit", release);
3312
3316
  return release;
3313
3317
  }
3318
+ function acquireLock() {
3319
+ return acquireLockAt(join5(lockDir(), "lock"));
3320
+ }
3314
3321
  function loadStore() {
3315
3322
  return new LazyStore(objectsDir());
3316
3323
  }
@@ -4160,6 +4167,7 @@ __export(exports_remote, {
4160
4167
  saveRemote: () => saveRemote,
4161
4168
  remoteRefs: () => remoteRefs,
4162
4169
  remotePushPack: () => remotePushPack,
4170
+ remotePushGiantLeaf: () => remotePushGiantLeaf,
4163
4171
  remotePushBlobs: () => remotePushBlobs,
4164
4172
  remotePush: () => remotePush,
4165
4173
  remotePromote: () => remotePromote,
@@ -4184,6 +4192,7 @@ __export(exports_remote, {
4184
4192
  loadRemote: () => loadRemote,
4185
4193
  forksList: () => forksList,
4186
4194
  forkMeta: () => forkMeta,
4195
+ exportStreaming: () => exportStreaming,
4187
4196
  classifyNodes: () => classifyNodes,
4188
4197
  accessSet: () => accessSet,
4189
4198
  accessGet: () => accessGet
@@ -4250,6 +4259,37 @@ async function exportStreaming(cfg, token) {
4250
4259
  throw new Error("remote /export returned an empty stream");
4251
4260
  return { ...header, nodes };
4252
4261
  }
4262
+ async function exportManifest(cfg, token) {
4263
+ const res = await fetch(endpoint(cfg, "/export/manifest"), {
4264
+ headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }
4265
+ });
4266
+ if (res.status === 404)
4267
+ return exportStreaming(cfg, token);
4268
+ if (!res.ok)
4269
+ throw new Error(`remote /export/manifest -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
4270
+ const m = await res.json();
4271
+ if (!Array.isArray(m.packIds))
4272
+ return exportStreaming(cfg, token);
4273
+ const tasks = [
4274
+ ...(m.packIds ?? []).map((packId) => () => fetchPack(cfg, token, packId, false)),
4275
+ ...(m.legacyNodes ?? []).map((hash) => () => fetchPack(cfg, token, hash, true))
4276
+ ];
4277
+ const packNodes = await pool(tasks, CLONE_PACK_CONCURRENCY);
4278
+ const nodes = [];
4279
+ for (const ns of packNodes)
4280
+ for (const n of ns)
4281
+ nodes.push(n);
4282
+ return { schema: m.schema, head: m.head, seq: m.seq, tip: m.tip, ops: m.ops, nodes, refs: m.refs, checkout: m.checkout };
4283
+ }
4284
+ async function fetchPack(cfg, token, id, legacy) {
4285
+ return retryTransient(async () => {
4286
+ const path = `/pack/${encodeURIComponent(id)}${legacy ? "?legacy=1" : ""}`;
4287
+ const res = await fetch(endpoint(cfg, path), { headers: { authorization: `Bearer ${token}` } });
4288
+ if (!res.ok)
4289
+ throw new Error(`remote /pack -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
4290
+ return decodePackLine((await res.text()).trim());
4291
+ });
4292
+ }
4253
4293
  function classifyNodes(nodes) {
4254
4294
  const trees = [];
4255
4295
  const leaves = [];
@@ -4307,13 +4347,34 @@ async function retryTransient(fn, attempts = 5) {
4307
4347
  }
4308
4348
  throw last;
4309
4349
  }
4350
+ function canonicalPackBytesClient(entries) {
4351
+ const sorted = [...entries].sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
4352
+ const obj = {};
4353
+ for (const [h, n] of sorted)
4354
+ obj[h] = n;
4355
+ return JSON.stringify(obj);
4356
+ }
4357
+ async function remotePushGiantLeaf(cfg, token, node) {
4358
+ const hash = hashNode(node);
4359
+ const body = canonicalPackBytesClient([[hash, node]]);
4360
+ const packId = hashString(body);
4361
+ const packBody = gzipSync3(Buffer.from(body, "utf8")).toString("base64");
4362
+ const path = `/push/blobs?giant=${encodeURIComponent(hash)}&packId=${encodeURIComponent(packId)}`;
4363
+ return retryTransient(() => call(cfg, token, path, { method: "POST", body: packBody }));
4364
+ }
4310
4365
  async function remotePushPack(cfg, token, body) {
4311
4366
  const { trees, leaves, total } = classifyNodes(body.nodes);
4312
4367
  if (total <= SMALL_PUSH_BYTES) {
4313
4368
  return retryTransient(() => call(cfg, token, "/push/pack", { method: "POST", body: gzipSync3(JSON.stringify(body)), headers: { "content-encoding": "gzip" } }));
4314
4369
  }
4315
- const blobPacks = splitLeafPacks(leaves, BLOB_PACK_BYTES);
4316
- await pool(blobPacks.map((pack) => () => remotePushBlobs(cfg, token, pack)), BLOB_PACK_CONCURRENCY);
4370
+ const giants = leaves.filter((n) => nodeBytes(n) > GIANT_LEAF_BYTES);
4371
+ const normal = leaves.filter((n) => nodeBytes(n) <= GIANT_LEAF_BYTES);
4372
+ const blobPacks = splitLeafPacks(normal, BLOB_PACK_BYTES);
4373
+ const tasks = [
4374
+ ...blobPacks.map((pack) => () => remotePushBlobs(cfg, token, pack)),
4375
+ ...giants.map((node) => () => remotePushGiantLeaf(cfg, token, node))
4376
+ ];
4377
+ await pool(tasks, BLOB_PACK_CONCURRENCY);
4317
4378
  return retryTransient(() => call(cfg, token, "/push/pack", {
4318
4379
  method: "POST",
4319
4380
  body: gzipSync3(JSON.stringify({ ...body, nodes: trees })),
@@ -4340,11 +4401,13 @@ async function writeBundle(solDir2, bundle, from = 0) {
4340
4401
  writeFileSync6(join6(solDir2, "HEAD"), JSON.stringify({ head: bundle.head, seq: bundle.seq, logTip: bundle.tip }));
4341
4402
  return fresh.length;
4342
4403
  }
4343
- var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), remoteExport = (cfg, token) => exportStreaming(cfg, token), remoteRefs = (cfg, token) => call(cfg, token, "/refs"), remotePush = (cfg, token, body) => call(cfg, token, "/push", { method: "POST", body: JSON.stringify(body) }), remotePromote = (cfg, token, branch) => call(cfg, token, "/promote", { method: "POST", body: JSON.stringify({ branch }) }), SMALL_PUSH_BYTES, BLOB_PACK_BYTES, BLOB_PACK_CONCURRENCY = 1, nodeBytes = (n) => JSON.stringify(n).length, remotePushBlobs = (cfg, token, nodes) => retryTransient(() => call(cfg, token, "/push/blobs", { method: "POST", body: gzipSync3(JSON.stringify({ nodes })), headers: { "content-encoding": "gzip" } })), mrOpen = (cfg, token, body) => call(cfg, token, "/mr", { method: "POST", body: JSON.stringify(body) }), mrList = (cfg, token) => call(cfg, token, "/mrs"), mrDiff = (cfg, token, id) => call(cfg, token, `/mr/diff?id=${id}`), mrGet = (cfg, token, id) => call(cfg, token, `/mr?id=${id}`), mrAction = (cfg, token, action, body) => call(cfg, token, `/mr/${action}`, { method: "POST", body: JSON.stringify(body) }), accessGet = (cfg, token) => call(cfg, token, "/access"), ownerSet = (cfg, token, ownerHandle) => call(cfg, token, "/owner", { method: "POST", body: JSON.stringify({ ownerHandle }) }), accessSet = (cfg, token, body) => call(cfg, token, "/access", { method: "POST", body: JSON.stringify(body) }), policyCheck = (cfg, token, paths) => call(cfg, token, "/policy/check", { method: "POST", body: JSON.stringify({ paths }) }), policyGet = (cfg, token) => call(cfg, token, "/policy"), policyUpsert = (cfg, token, rule) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "upsert", rule }) }), policyRemove = (cfg, token, pattern) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "remove", pattern }) }), recipientsForPath = (cfg, token, path) => call(cfg, token, `/recipients?path=${encodeURIComponent(path)}`), recipientsForAudience = (cfg, token, audience, recovery) => call(cfg, token, `/recipients?audience=${encodeURIComponent(JSON.stringify(audience))}${recovery?.length ? `&recovery=${encodeURIComponent(recovery.join(","))}` : ""}`), remoteEnvPush = (cfg, token, bundle) => call(cfg, token, "/env/push", { method: "POST", body: JSON.stringify(bundle) }), remoteEnvAnchor = (cfg, token) => call(cfg, token, "/env/anchor"), remoteEnvPull = (cfg, token) => call(cfg, token, "/env/pull"), forkMeta = (cfg, token, parent) => call(cfg, token, "/fork-meta", { method: "POST", body: JSON.stringify({ parent }) }), forksList = (cfg, token) => call(cfg, token, "/forks"), saveRemote = (solDir2, cfg) => writeFileSync6(join6(solDir2, "remote.json"), JSON.stringify(cfg, null, 2));
4404
+ var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), CLONE_PACK_CONCURRENCY = 12, remoteExport = (cfg, token) => exportManifest(cfg, token), remoteRefs = (cfg, token) => call(cfg, token, "/refs"), remotePush = (cfg, token, body) => call(cfg, token, "/push", { method: "POST", body: JSON.stringify(body) }), remotePromote = (cfg, token, branch) => call(cfg, token, "/promote", { method: "POST", body: JSON.stringify({ branch }) }), SMALL_PUSH_BYTES, BLOB_PACK_BYTES, BLOB_PACK_CONCURRENCY = 6, GIANT_LEAF_BYTES, nodeBytes = (n) => JSON.stringify(n).length, remotePushBlobs = (cfg, token, nodes) => retryTransient(() => call(cfg, token, "/push/blobs", { method: "POST", body: gzipSync3(JSON.stringify({ nodes })), headers: { "content-encoding": "gzip" } })), mrOpen = (cfg, token, body) => call(cfg, token, "/mr", { method: "POST", body: JSON.stringify(body) }), mrList = (cfg, token) => call(cfg, token, "/mrs"), mrDiff = (cfg, token, id) => call(cfg, token, `/mr/diff?id=${id}`), mrGet = (cfg, token, id) => call(cfg, token, `/mr?id=${id}`), mrAction = (cfg, token, action, body) => call(cfg, token, `/mr/${action}`, { method: "POST", body: JSON.stringify(body) }), accessGet = (cfg, token) => call(cfg, token, "/access"), ownerSet = (cfg, token, ownerHandle) => call(cfg, token, "/owner", { method: "POST", body: JSON.stringify({ ownerHandle }) }), accessSet = (cfg, token, body) => call(cfg, token, "/access", { method: "POST", body: JSON.stringify(body) }), policyCheck = (cfg, token, paths) => call(cfg, token, "/policy/check", { method: "POST", body: JSON.stringify({ paths }) }), policyGet = (cfg, token) => call(cfg, token, "/policy"), policyUpsert = (cfg, token, rule) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "upsert", rule }) }), policyRemove = (cfg, token, pattern) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "remove", pattern }) }), recipientsForPath = (cfg, token, path) => call(cfg, token, `/recipients?path=${encodeURIComponent(path)}`), recipientsForAudience = (cfg, token, audience, recovery) => call(cfg, token, `/recipients?audience=${encodeURIComponent(JSON.stringify(audience))}${recovery?.length ? `&recovery=${encodeURIComponent(recovery.join(","))}` : ""}`), remoteEnvPush = (cfg, token, bundle) => call(cfg, token, "/env/push", { method: "POST", body: JSON.stringify(bundle) }), remoteEnvAnchor = (cfg, token) => call(cfg, token, "/env/anchor"), remoteEnvPull = (cfg, token) => call(cfg, token, "/env/pull"), forkMeta = (cfg, token, parent) => call(cfg, token, "/fork-meta", { method: "POST", body: JSON.stringify({ parent }) }), forksList = (cfg, token) => call(cfg, token, "/forks"), saveRemote = (solDir2, cfg) => writeFileSync6(join6(solDir2, "remote.json"), JSON.stringify(cfg, null, 2));
4344
4405
  var init_remote = __esm(() => {
4345
4406
  init_file_store2();
4407
+ init_store();
4346
4408
  SMALL_PUSH_BYTES = 24 * 1024 * 1024;
4347
4409
  BLOB_PACK_BYTES = 16 * 1024 * 1024;
4410
+ GIANT_LEAF_BYTES = 24 * 1024 * 1024;
4348
4411
  });
4349
4412
 
4350
4413
  // src/bin/test-gate.ts
@@ -9745,21 +9808,41 @@ function tokenClaims(token) {
9745
9808
  return {};
9746
9809
  }
9747
9810
  }
9748
- async function loadStoredToken() {
9749
- if (!existsSync20(CRED_PATH))
9750
- return;
9751
- let creds;
9811
+ function readCreds() {
9752
9812
  try {
9753
- creds = JSON.parse(readFileSync20(CRED_PATH, "utf8"));
9813
+ return JSON.parse(readFileSync20(CRED_PATH, "utf8"));
9754
9814
  } catch {
9755
9815
  return;
9756
9816
  }
9757
- if (!creds.accessToken)
9817
+ }
9818
+ function accessTokenFresh(accessToken) {
9819
+ if (!accessToken)
9820
+ return false;
9821
+ const exp = tokenClaims(accessToken).exp;
9822
+ return typeof exp === "number" && exp * 1000 > Date.now() + 30000;
9823
+ }
9824
+ async function loadStoredToken() {
9825
+ if (!existsSync20(CRED_PATH))
9826
+ return;
9827
+ let creds = readCreds();
9828
+ if (!creds?.accessToken)
9758
9829
  return;
9759
- const exp = tokenClaims(creds.accessToken).exp;
9760
- if (typeof exp === "number" && exp * 1000 > Date.now() + 30000)
9830
+ if (accessTokenFresh(creds.accessToken))
9761
9831
  return creds.accessToken;
9762
- if (creds.refreshToken && creds.webUrl) {
9832
+ if (!(creds.refreshToken && creds.webUrl))
9833
+ return creds.accessToken;
9834
+ const release = acquireLockAt(join19(dirname5(CRED_PATH), "credentials.lock"), {
9835
+ timeoutMs: 1e4,
9836
+ onTimeout: "undefined"
9837
+ });
9838
+ try {
9839
+ if (release) {
9840
+ const fresh = readCreds();
9841
+ if (fresh?.accessToken && accessTokenFresh(fresh.accessToken))
9842
+ return fresh.accessToken;
9843
+ if (fresh)
9844
+ creds = fresh;
9845
+ }
9763
9846
  try {
9764
9847
  const res = await fetch(`${creds.webUrl}/api/auth/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ refreshToken: creds.refreshToken }) });
9765
9848
  if (res.ok) {
@@ -9770,8 +9853,10 @@ async function loadStoredToken() {
9770
9853
  }
9771
9854
  }
9772
9855
  } catch {}
9856
+ return creds.accessToken;
9857
+ } finally {
9858
+ release?.();
9773
9859
  }
9774
- return creds.accessToken;
9775
9860
  }
9776
9861
  function authExpired() {
9777
9862
  return die("session expired — run `sol auth login` (or set SOL_TOKEN)");
@@ -12514,8 +12599,12 @@ WARNING: "${path}" was committed as PLAINTEXT before this seal — the pre-seal
12514
12599
  const days = Number(patAction) || 90;
12515
12600
  const name = (Number(patAction) ? args[2] : patAction) || undefined;
12516
12601
  const res = await fetch(`${creds.webUrl}/api/auth/pat`, { method: "POST", headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }, body: JSON.stringify({ days, ...name ? { name } : {} }) });
12517
- if (!res.ok)
12518
- die(`could not mint a PAT (${res.status})`);
12602
+ if (!res.ok) {
12603
+ const reason = await res.json().then((b) => b?.error?.detail || b?.error?.message).catch(() => {
12604
+ return;
12605
+ });
12606
+ die(`could not mint a PAT (${res.status})${reason ? `: ${reason}` : ""}`);
12607
+ }
12519
12608
  const out = await res.json();
12520
12609
  console.log(`
12521
12610
  Personal Access Token "${out.name}" (id ${out.id}, expires in ${days} days) — store it now, it is not shown again:
package/sol.js CHANGED
@@ -2269,6 +2269,7 @@ __export(exports_lib, {
2269
2269
  allLocalNodes: () => allLocalNodes,
2270
2270
  addInclude: () => addInclude,
2271
2271
  actor: () => actor,
2272
+ acquireLockAt: () => acquireLockAt,
2272
2273
  acquireLock: () => acquireLock,
2273
2274
  LazyStore: () => LazyStore,
2274
2275
  DEFAULT_IGNORE: () => DEFAULT_IGNORE
@@ -2502,9 +2503,9 @@ function pidAlive(pid) {
2502
2503
  return e?.code === "EPERM";
2503
2504
  }
2504
2505
  }
2505
- function acquireLock() {
2506
- const lockFile = join4(lockDir(), "lock");
2507
- const deadline = Date.now() + 15000;
2506
+ function acquireLockAt(lockFile, opts = {}) {
2507
+ const deadline = Date.now() + (opts.timeoutMs ?? 15000);
2508
+ const onTimeout = opts.onTimeout ?? "die";
2508
2509
  for (;; ) {
2509
2510
  try {
2510
2511
  writeFileSync4(lockFile, String(process.pid), { flag: "wx" });
@@ -2527,8 +2528,11 @@ function acquireLock() {
2527
2528
  } catch {
2528
2529
  continue;
2529
2530
  }
2530
- if (Date.now() > deadline)
2531
- die("repo is locked by another sol process (timed out)");
2531
+ if (Date.now() > deadline) {
2532
+ if (onTimeout === "undefined")
2533
+ return;
2534
+ die(opts.timeoutMsg ?? "repo is locked by another sol process (timed out)");
2535
+ }
2532
2536
  sleepSync(25);
2533
2537
  }
2534
2538
  }
@@ -2544,6 +2548,9 @@ function acquireLock() {
2544
2548
  process.on("exit", release);
2545
2549
  return release;
2546
2550
  }
2551
+ function acquireLock() {
2552
+ return acquireLockAt(join4(lockDir(), "lock"));
2553
+ }
2547
2554
  function loadStore() {
2548
2555
  return new LazyStore(objectsDir());
2549
2556
  }
@@ -3393,6 +3400,7 @@ __export(exports_remote, {
3393
3400
  saveRemote: () => saveRemote,
3394
3401
  remoteRefs: () => remoteRefs,
3395
3402
  remotePushPack: () => remotePushPack,
3403
+ remotePushGiantLeaf: () => remotePushGiantLeaf,
3396
3404
  remotePushBlobs: () => remotePushBlobs,
3397
3405
  remotePush: () => remotePush,
3398
3406
  remotePromote: () => remotePromote,
@@ -3417,6 +3425,7 @@ __export(exports_remote, {
3417
3425
  loadRemote: () => loadRemote,
3418
3426
  forksList: () => forksList,
3419
3427
  forkMeta: () => forkMeta,
3428
+ exportStreaming: () => exportStreaming,
3420
3429
  classifyNodes: () => classifyNodes,
3421
3430
  accessSet: () => accessSet,
3422
3431
  accessGet: () => accessGet
@@ -3483,6 +3492,37 @@ async function exportStreaming(cfg, token) {
3483
3492
  throw new Error("remote /export returned an empty stream");
3484
3493
  return { ...header, nodes };
3485
3494
  }
3495
+ async function exportManifest(cfg, token) {
3496
+ const res = await fetch(endpoint(cfg, "/export/manifest"), {
3497
+ headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }
3498
+ });
3499
+ if (res.status === 404)
3500
+ return exportStreaming(cfg, token);
3501
+ if (!res.ok)
3502
+ throw new Error(`remote /export/manifest -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
3503
+ const m = await res.json();
3504
+ if (!Array.isArray(m.packIds))
3505
+ return exportStreaming(cfg, token);
3506
+ const tasks = [
3507
+ ...(m.packIds ?? []).map((packId) => () => fetchPack(cfg, token, packId, false)),
3508
+ ...(m.legacyNodes ?? []).map((hash) => () => fetchPack(cfg, token, hash, true))
3509
+ ];
3510
+ const packNodes = await pool(tasks, CLONE_PACK_CONCURRENCY);
3511
+ const nodes = [];
3512
+ for (const ns of packNodes)
3513
+ for (const n of ns)
3514
+ nodes.push(n);
3515
+ return { schema: m.schema, head: m.head, seq: m.seq, tip: m.tip, ops: m.ops, nodes, refs: m.refs, checkout: m.checkout };
3516
+ }
3517
+ async function fetchPack(cfg, token, id, legacy) {
3518
+ return retryTransient(async () => {
3519
+ const path = `/pack/${encodeURIComponent(id)}${legacy ? "?legacy=1" : ""}`;
3520
+ const res = await fetch(endpoint(cfg, path), { headers: { authorization: `Bearer ${token}` } });
3521
+ if (!res.ok)
3522
+ throw new Error(`remote /pack -> ${res.status}: ${(await res.text().catch(() => "")).slice(0, 200)}`);
3523
+ return decodePackLine((await res.text()).trim());
3524
+ });
3525
+ }
3486
3526
  function classifyNodes(nodes) {
3487
3527
  const trees = [];
3488
3528
  const leaves = [];
@@ -3540,13 +3580,34 @@ async function retryTransient(fn, attempts = 5) {
3540
3580
  }
3541
3581
  throw last;
3542
3582
  }
3583
+ function canonicalPackBytesClient(entries) {
3584
+ const sorted = [...entries].sort((a, b) => a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0);
3585
+ const obj = {};
3586
+ for (const [h, n] of sorted)
3587
+ obj[h] = n;
3588
+ return JSON.stringify(obj);
3589
+ }
3590
+ async function remotePushGiantLeaf(cfg, token, node) {
3591
+ const hash = hashNode(node);
3592
+ const body = canonicalPackBytesClient([[hash, node]]);
3593
+ const packId = hashString(body);
3594
+ const packBody = gzipSync2(Buffer.from(body, "utf8")).toString("base64");
3595
+ const path = `/push/blobs?giant=${encodeURIComponent(hash)}&packId=${encodeURIComponent(packId)}`;
3596
+ return retryTransient(() => call(cfg, token, path, { method: "POST", body: packBody }));
3597
+ }
3543
3598
  async function remotePushPack(cfg, token, body) {
3544
3599
  const { trees, leaves, total } = classifyNodes(body.nodes);
3545
3600
  if (total <= SMALL_PUSH_BYTES) {
3546
3601
  return retryTransient(() => call(cfg, token, "/push/pack", { method: "POST", body: gzipSync2(JSON.stringify(body)), headers: { "content-encoding": "gzip" } }));
3547
3602
  }
3548
- const blobPacks = splitLeafPacks(leaves, BLOB_PACK_BYTES);
3549
- await pool(blobPacks.map((pack) => () => remotePushBlobs(cfg, token, pack)), BLOB_PACK_CONCURRENCY);
3603
+ const giants = leaves.filter((n) => nodeBytes(n) > GIANT_LEAF_BYTES);
3604
+ const normal = leaves.filter((n) => nodeBytes(n) <= GIANT_LEAF_BYTES);
3605
+ const blobPacks = splitLeafPacks(normal, BLOB_PACK_BYTES);
3606
+ const tasks = [
3607
+ ...blobPacks.map((pack) => () => remotePushBlobs(cfg, token, pack)),
3608
+ ...giants.map((node) => () => remotePushGiantLeaf(cfg, token, node))
3609
+ ];
3610
+ await pool(tasks, BLOB_PACK_CONCURRENCY);
3550
3611
  return retryTransient(() => call(cfg, token, "/push/pack", {
3551
3612
  method: "POST",
3552
3613
  body: gzipSync2(JSON.stringify({ ...body, nodes: trees })),
@@ -3573,11 +3634,13 @@ async function writeBundle(solDir2, bundle, from = 0) {
3573
3634
  writeFileSync5(join5(solDir2, "HEAD"), JSON.stringify({ head: bundle.head, seq: bundle.seq, logTip: bundle.tip }));
3574
3635
  return fresh.length;
3575
3636
  }
3576
- var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), remoteExport = (cfg, token) => exportStreaming(cfg, token), remoteRefs = (cfg, token) => call(cfg, token, "/refs"), remotePush = (cfg, token, body) => call(cfg, token, "/push", { method: "POST", body: JSON.stringify(body) }), remotePromote = (cfg, token, branch) => call(cfg, token, "/promote", { method: "POST", body: JSON.stringify({ branch }) }), SMALL_PUSH_BYTES, BLOB_PACK_BYTES, BLOB_PACK_CONCURRENCY = 1, nodeBytes = (n) => JSON.stringify(n).length, remotePushBlobs = (cfg, token, nodes) => retryTransient(() => call(cfg, token, "/push/blobs", { method: "POST", body: gzipSync2(JSON.stringify({ nodes })), headers: { "content-encoding": "gzip" } })), mrOpen = (cfg, token, body) => call(cfg, token, "/mr", { method: "POST", body: JSON.stringify(body) }), mrList = (cfg, token) => call(cfg, token, "/mrs"), mrDiff = (cfg, token, id) => call(cfg, token, `/mr/diff?id=${id}`), mrGet = (cfg, token, id) => call(cfg, token, `/mr?id=${id}`), mrAction = (cfg, token, action, body) => call(cfg, token, `/mr/${action}`, { method: "POST", body: JSON.stringify(body) }), accessGet = (cfg, token) => call(cfg, token, "/access"), ownerSet = (cfg, token, ownerHandle) => call(cfg, token, "/owner", { method: "POST", body: JSON.stringify({ ownerHandle }) }), accessSet = (cfg, token, body) => call(cfg, token, "/access", { method: "POST", body: JSON.stringify(body) }), policyCheck = (cfg, token, paths) => call(cfg, token, "/policy/check", { method: "POST", body: JSON.stringify({ paths }) }), policyGet = (cfg, token) => call(cfg, token, "/policy"), policyUpsert = (cfg, token, rule) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "upsert", rule }) }), policyRemove = (cfg, token, pattern) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "remove", pattern }) }), recipientsForPath = (cfg, token, path) => call(cfg, token, `/recipients?path=${encodeURIComponent(path)}`), recipientsForAudience = (cfg, token, audience, recovery) => call(cfg, token, `/recipients?audience=${encodeURIComponent(JSON.stringify(audience))}${recovery?.length ? `&recovery=${encodeURIComponent(recovery.join(","))}` : ""}`), remoteEnvPush = (cfg, token, bundle) => call(cfg, token, "/env/push", { method: "POST", body: JSON.stringify(bundle) }), remoteEnvAnchor = (cfg, token) => call(cfg, token, "/env/anchor"), remoteEnvPull = (cfg, token) => call(cfg, token, "/env/pull"), forkMeta = (cfg, token, parent) => call(cfg, token, "/fork-meta", { method: "POST", body: JSON.stringify({ parent }) }), forksList = (cfg, token) => call(cfg, token, "/forks"), saveRemote = (solDir2, cfg) => writeFileSync5(join5(solDir2, "remote.json"), JSON.stringify(cfg, null, 2));
3637
+ var endpoint = (cfg, path) => `${cfg.url.replace(/\/+$/, "")}${path}${path.includes("?") ? "&" : "?"}repo=${encodeURIComponent(cfg.repo)}`, remoteHead = (cfg, token) => call(cfg, token, "/head"), remoteGate = (cfg, token, branch) => call(cfg, token, `/head?gateState=true${branch ? `&branch=${encodeURIComponent(branch)}` : ""}`), CLONE_PACK_CONCURRENCY = 12, remoteExport = (cfg, token) => exportManifest(cfg, token), remoteRefs = (cfg, token) => call(cfg, token, "/refs"), remotePush = (cfg, token, body) => call(cfg, token, "/push", { method: "POST", body: JSON.stringify(body) }), remotePromote = (cfg, token, branch) => call(cfg, token, "/promote", { method: "POST", body: JSON.stringify({ branch }) }), SMALL_PUSH_BYTES, BLOB_PACK_BYTES, BLOB_PACK_CONCURRENCY = 6, GIANT_LEAF_BYTES, nodeBytes = (n) => JSON.stringify(n).length, remotePushBlobs = (cfg, token, nodes) => retryTransient(() => call(cfg, token, "/push/blobs", { method: "POST", body: gzipSync2(JSON.stringify({ nodes })), headers: { "content-encoding": "gzip" } })), mrOpen = (cfg, token, body) => call(cfg, token, "/mr", { method: "POST", body: JSON.stringify(body) }), mrList = (cfg, token) => call(cfg, token, "/mrs"), mrDiff = (cfg, token, id) => call(cfg, token, `/mr/diff?id=${id}`), mrGet = (cfg, token, id) => call(cfg, token, `/mr?id=${id}`), mrAction = (cfg, token, action, body) => call(cfg, token, `/mr/${action}`, { method: "POST", body: JSON.stringify(body) }), accessGet = (cfg, token) => call(cfg, token, "/access"), ownerSet = (cfg, token, ownerHandle) => call(cfg, token, "/owner", { method: "POST", body: JSON.stringify({ ownerHandle }) }), accessSet = (cfg, token, body) => call(cfg, token, "/access", { method: "POST", body: JSON.stringify(body) }), policyCheck = (cfg, token, paths) => call(cfg, token, "/policy/check", { method: "POST", body: JSON.stringify({ paths }) }), policyGet = (cfg, token) => call(cfg, token, "/policy"), policyUpsert = (cfg, token, rule) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "upsert", rule }) }), policyRemove = (cfg, token, pattern) => call(cfg, token, "/policy?write=1", { method: "POST", body: JSON.stringify({ op: "remove", pattern }) }), recipientsForPath = (cfg, token, path) => call(cfg, token, `/recipients?path=${encodeURIComponent(path)}`), recipientsForAudience = (cfg, token, audience, recovery) => call(cfg, token, `/recipients?audience=${encodeURIComponent(JSON.stringify(audience))}${recovery?.length ? `&recovery=${encodeURIComponent(recovery.join(","))}` : ""}`), remoteEnvPush = (cfg, token, bundle) => call(cfg, token, "/env/push", { method: "POST", body: JSON.stringify(bundle) }), remoteEnvAnchor = (cfg, token) => call(cfg, token, "/env/anchor"), remoteEnvPull = (cfg, token) => call(cfg, token, "/env/pull"), forkMeta = (cfg, token, parent) => call(cfg, token, "/fork-meta", { method: "POST", body: JSON.stringify({ parent }) }), forksList = (cfg, token) => call(cfg, token, "/forks"), saveRemote = (solDir2, cfg) => writeFileSync5(join5(solDir2, "remote.json"), JSON.stringify(cfg, null, 2));
3577
3638
  var init_remote = __esm(() => {
3578
3639
  init_file_store();
3640
+ init_store();
3579
3641
  SMALL_PUSH_BYTES = 24 * 1024 * 1024;
3580
3642
  BLOB_PACK_BYTES = 16 * 1024 * 1024;
3643
+ GIANT_LEAF_BYTES = 24 * 1024 * 1024;
3581
3644
  });
3582
3645
 
3583
3646
  // src/bin/test-gate.ts
@@ -9513,21 +9576,41 @@ function tokenClaims(token) {
9513
9576
  return {};
9514
9577
  }
9515
9578
  }
9516
- async function loadStoredToken() {
9517
- if (!existsSync19(CRED_PATH))
9518
- return;
9519
- let creds;
9579
+ function readCreds() {
9520
9580
  try {
9521
- creds = JSON.parse(readFileSync19(CRED_PATH, "utf8"));
9581
+ return JSON.parse(readFileSync19(CRED_PATH, "utf8"));
9522
9582
  } catch {
9523
9583
  return;
9524
9584
  }
9525
- if (!creds.accessToken)
9585
+ }
9586
+ function accessTokenFresh(accessToken) {
9587
+ if (!accessToken)
9588
+ return false;
9589
+ const exp = tokenClaims(accessToken).exp;
9590
+ return typeof exp === "number" && exp * 1000 > Date.now() + 30000;
9591
+ }
9592
+ async function loadStoredToken() {
9593
+ if (!existsSync19(CRED_PATH))
9526
9594
  return;
9527
- const exp = tokenClaims(creds.accessToken).exp;
9528
- if (typeof exp === "number" && exp * 1000 > Date.now() + 30000)
9595
+ let creds = readCreds();
9596
+ if (!creds?.accessToken)
9597
+ return;
9598
+ if (accessTokenFresh(creds.accessToken))
9599
+ return creds.accessToken;
9600
+ if (!(creds.refreshToken && creds.webUrl))
9529
9601
  return creds.accessToken;
9530
- if (creds.refreshToken && creds.webUrl) {
9602
+ const release = acquireLockAt(join18(dirname5(CRED_PATH), "credentials.lock"), {
9603
+ timeoutMs: 1e4,
9604
+ onTimeout: "undefined"
9605
+ });
9606
+ try {
9607
+ if (release) {
9608
+ const fresh = readCreds();
9609
+ if (fresh?.accessToken && accessTokenFresh(fresh.accessToken))
9610
+ return fresh.accessToken;
9611
+ if (fresh)
9612
+ creds = fresh;
9613
+ }
9531
9614
  try {
9532
9615
  const res = await fetch(`${creds.webUrl}/api/auth/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ refreshToken: creds.refreshToken }) });
9533
9616
  if (res.ok) {
@@ -9538,8 +9621,10 @@ async function loadStoredToken() {
9538
9621
  }
9539
9622
  }
9540
9623
  } catch {}
9624
+ return creds.accessToken;
9625
+ } finally {
9626
+ release?.();
9541
9627
  }
9542
- return creds.accessToken;
9543
9628
  }
9544
9629
  function authExpired() {
9545
9630
  return die("session expired — run `sol auth login` (or set SOL_TOKEN)");
@@ -12282,8 +12367,12 @@ WARNING: "${path}" was committed as PLAINTEXT before this seal — the pre-seal
12282
12367
  const days = Number(patAction) || 90;
12283
12368
  const name = (Number(patAction) ? args[2] : patAction) || undefined;
12284
12369
  const res = await fetch(`${creds.webUrl}/api/auth/pat`, { method: "POST", headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }, body: JSON.stringify({ days, ...name ? { name } : {} }) });
12285
- if (!res.ok)
12286
- die(`could not mint a PAT (${res.status})`);
12370
+ if (!res.ok) {
12371
+ const reason = await res.json().then((b) => b?.error?.detail || b?.error?.message).catch(() => {
12372
+ return;
12373
+ });
12374
+ die(`could not mint a PAT (${res.status})${reason ? `: ${reason}` : ""}`);
12375
+ }
12287
12376
  const out = await res.json();
12288
12377
  console.log(`
12289
12378
  Personal Access Token "${out.name}" (id ${out.id}, expires in ${days} days) — store it now, it is not shown again:
@@ -13797,21 +13886,41 @@ function tokenClaims2(token) {
13797
13886
  return {};
13798
13887
  }
13799
13888
  }
13800
- async function loadStoredToken2() {
13801
- if (!existsSync20(CRED_PATH2))
13802
- return;
13803
- let creds;
13889
+ function readCreds2() {
13804
13890
  try {
13805
- creds = JSON.parse(readFileSync20(CRED_PATH2, "utf8"));
13891
+ return JSON.parse(readFileSync20(CRED_PATH2, "utf8"));
13806
13892
  } catch {
13807
13893
  return;
13808
13894
  }
13809
- if (!creds.accessToken)
13895
+ }
13896
+ function accessTokenFresh2(accessToken) {
13897
+ if (!accessToken)
13898
+ return false;
13899
+ const exp = tokenClaims2(accessToken).exp;
13900
+ return typeof exp === "number" && exp * 1000 > Date.now() + 30000;
13901
+ }
13902
+ async function loadStoredToken2() {
13903
+ if (!existsSync20(CRED_PATH2))
13810
13904
  return;
13811
- const exp = tokenClaims2(creds.accessToken).exp;
13812
- if (typeof exp === "number" && exp * 1000 > Date.now() + 30000)
13905
+ let creds = readCreds2();
13906
+ if (!creds?.accessToken)
13907
+ return;
13908
+ if (accessTokenFresh2(creds.accessToken))
13909
+ return creds.accessToken;
13910
+ if (!(creds.refreshToken && creds.webUrl))
13813
13911
  return creds.accessToken;
13814
- if (creds.refreshToken && creds.webUrl) {
13912
+ const release = acquireLockAt(join20(dirname7(CRED_PATH2), "credentials.lock"), {
13913
+ timeoutMs: 1e4,
13914
+ onTimeout: "undefined"
13915
+ });
13916
+ try {
13917
+ if (release) {
13918
+ const fresh = readCreds2();
13919
+ if (fresh?.accessToken && accessTokenFresh2(fresh.accessToken))
13920
+ return fresh.accessToken;
13921
+ if (fresh)
13922
+ creds = fresh;
13923
+ }
13815
13924
  try {
13816
13925
  const res = await fetch(`${creds.webUrl}/api/auth/refresh`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ refreshToken: creds.refreshToken }) });
13817
13926
  if (res.ok) {
@@ -13822,8 +13931,10 @@ async function loadStoredToken2() {
13822
13931
  }
13823
13932
  }
13824
13933
  } catch {}
13934
+ return creds.accessToken;
13935
+ } finally {
13936
+ release?.();
13825
13937
  }
13826
- return creds.accessToken;
13827
13938
  }
13828
13939
  function authExpired2() {
13829
13940
  return die("session expired — run `sol auth login` (or set SOL_TOKEN)");
@@ -16566,8 +16677,12 @@ WARNING: "${path}" was committed as PLAINTEXT before this seal — the pre-seal
16566
16677
  const days = Number(patAction) || 90;
16567
16678
  const name = (Number(patAction) ? args[2] : patAction) || undefined;
16568
16679
  const res = await fetch(`${creds.webUrl}/api/auth/pat`, { method: "POST", headers: { authorization: `Bearer ${token}`, "content-type": "application/json" }, body: JSON.stringify({ days, ...name ? { name } : {} }) });
16569
- if (!res.ok)
16570
- die(`could not mint a PAT (${res.status})`);
16680
+ if (!res.ok) {
16681
+ const reason = await res.json().then((b) => b?.error?.detail || b?.error?.message).catch(() => {
16682
+ return;
16683
+ });
16684
+ die(`could not mint a PAT (${res.status})${reason ? `: ${reason}` : ""}`);
16685
+ }
16571
16686
  const out = await res.json();
16572
16687
  console.log(`
16573
16688
  Personal Access Token "${out.name}" (id ${out.id}, expires in ${days} days) — store it now, it is not shown again: