@cortexkit/anthropic-auth-core 2.2.1 → 2.2.2

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.
package/dist/index.js CHANGED
@@ -644,6 +644,7 @@ class LockOwnershipError extends Error {
644
644
  async function withLock(target, options, fn) {
645
645
  const started = performance.now();
646
646
  for (;; ) {
647
+ options.signal?.throwIfAborted();
647
648
  const lock = await acquireRefreshFileLock({
648
649
  path: target,
649
650
  name: options.name,
@@ -654,6 +655,7 @@ async function withLock(target, options, fn) {
654
655
  });
655
656
  if (lock) {
656
657
  try {
658
+ options.signal?.throwIfAborted();
657
659
  return await fn(lock);
658
660
  } finally {
659
661
  await lock.release();
@@ -2530,6 +2532,7 @@ Please quit all OpenCode, LiteCode, and Pi processes before running setup.`);
2530
2532
  }
2531
2533
  async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2532
2534
  const windows = (options.platform ?? process.platform) === "win32";
2535
+ const selfPid = options.selfPid ?? process.pid;
2533
2536
  let inspection = {
2534
2537
  step: windows ? "tasklist" : "ps",
2535
2538
  exitCode: null,
@@ -2598,7 +2601,7 @@ async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2598
2601
  }
2599
2602
  if (!processes.length)
2600
2603
  throw new ProcessInspectionError(inspection);
2601
- const runtimes = processes.filter((entry) => entry.pid !== process.pid && /^(?:node|bun)\.exe$/i.test(entry.command));
2604
+ const runtimes = processes.filter((entry) => entry.pid !== selfPid && /^(?:node|bun)\.exe$/i.test(entry.command));
2602
2605
  if (windows && runtimes.length && options.inspectRuntimes !== false) {
2603
2606
  const details = await inspect("CIM", "powershell.exe", [
2604
2607
  "-NoProfile",
@@ -2631,7 +2634,8 @@ async function listSetupProcesses(runner = defaultCommandRunner, options = {}) {
2631
2634
  }
2632
2635
  }
2633
2636
  function createProcessFence(runner = defaultCommandRunner, options = {}) {
2634
- const isHost = (entry) => entry.pid !== process.pid && hostName(entry.command) !== null;
2637
+ const selfPid = options.selfPid ?? process.pid;
2638
+ const isHost = (entry) => entry.pid !== selfPid && hostName(entry.command) !== null;
2635
2639
  return {
2636
2640
  async listRunningHosts(env) {
2637
2641
  return (await listSetupProcesses(runner, { ...options, env })).filter(isHost);
@@ -2645,7 +2649,7 @@ function createProcessFence(runner = defaultCommandRunner, options = {}) {
2645
2649
  const windows = (options.platform ?? process.platform) === "win32";
2646
2650
  return {
2647
2651
  hosts: processes.filter(isHost),
2648
- uncheckedRuntimes: windows ? processes.filter((entry) => entry.pid !== process.pid && /^(?:node|bun)\.exe$/i.test(entry.command)).length : 0
2652
+ uncheckedRuntimes: windows ? processes.filter((entry) => entry.pid !== selfPid && /^(?:node|bun)\.exe$/i.test(entry.command)).length : 0
2649
2653
  };
2650
2654
  }
2651
2655
  };
@@ -13272,6 +13276,12 @@ function isQuotaCounter(value) {
13272
13276
  function isQuotaCounters(value) {
13273
13277
  return isRecord8(value) && Object.values(value).every(isQuotaCounter);
13274
13278
  }
13279
+ function isBoolean(value) {
13280
+ return typeof value === "boolean";
13281
+ }
13282
+ function isQuotaCredits(value) {
13283
+ return isRecord8(value) && typeof value.hasCredits === "boolean" && typeof value.unlimited === "boolean" && optional(value, "balance", isFiniteNumber) && optional(value, "overageLimitReached", isBoolean) && isFiniteNumber(value.checkedAt);
13284
+ }
13275
13285
  function readQuotaCounters(value) {
13276
13286
  if (!isRecord8(value))
13277
13287
  return;
@@ -13283,11 +13293,16 @@ function decodeQuotaMap(value) {
13283
13293
  return value;
13284
13294
  if (!isRecord8(value))
13285
13295
  return;
13286
- const { counters: rawCounters, ...rest } = value;
13296
+ const { counters: rawCounters, credits: rawCredits, ...rest } = value;
13287
13297
  if (!isQuotaMap(rest))
13288
13298
  return;
13289
13299
  const counters = readQuotaCounters(rawCounters);
13290
- return { ...rest, ...counters === undefined ? {} : { counters } };
13300
+ const credits = isQuotaCredits(rawCredits) ? rawCredits : undefined;
13301
+ return {
13302
+ ...rest,
13303
+ ...counters === undefined ? {} : { counters },
13304
+ ...credits === undefined ? {} : { credits }
13305
+ };
13291
13306
  }
13292
13307
  function isQuotaMap(value) {
13293
13308
  if (!isRecord8(value) || !Array.isArray(value.limits))
@@ -13301,7 +13316,7 @@ function isQuotaMap(value) {
13301
13316
  return false;
13302
13317
  seen.add(key);
13303
13318
  }
13304
- return optional(value, "budget", isCreditBudgetEntry) && optional(value, "counters", isQuotaCounters);
13319
+ return optional(value, "budget", isCreditBudgetEntry) && optional(value, "counters", isQuotaCounters) && optional(value, "credits", isQuotaCredits);
13305
13320
  }
13306
13321
 
13307
13322
  // ../../node_modules/@cortexkit/common-auth/dist/quota/merge.js
@@ -13360,7 +13375,7 @@ function isQuotaObservation(value) {
13360
13375
  }
13361
13376
  if (!coverage.every(isObservedPair))
13362
13377
  return false;
13363
- return (value.budget === undefined || isObservedBudget(value.budget)) && (value.counters === undefined || isQuotaCounters(value.counters));
13378
+ return (value.budget === undefined || isObservedBudget(value.budget)) && (value.counters === undefined || isQuotaCounters(value.counters)) && (value.credits === undefined || isQuotaCredits(value.credits));
13364
13379
  }
13365
13380
  function compareEntries(left, right) {
13366
13381
  if (left.scope !== right.scope)
@@ -13386,6 +13401,14 @@ function mergeCounters(stored, observed) {
13386
13401
  }
13387
13402
  return counters.size === 0 ? undefined : Object.fromEntries(counters);
13388
13403
  }
13404
+ function mergeCredits(stored, observed) {
13405
+ if (observed === undefined)
13406
+ return stored;
13407
+ if (stored !== undefined && observed.checkedAt < stored.checkedAt) {
13408
+ return stored;
13409
+ }
13410
+ return { ...observed };
13411
+ }
13389
13412
  function mergeQuotaObservation(stored, observation) {
13390
13413
  const decoded = stored === undefined ? undefined : decodeQuotaMap(stored);
13391
13414
  if (stored !== undefined && decoded === undefined) {
@@ -13429,14 +13452,16 @@ function mergeQuotaObservation(stored, observation) {
13429
13452
  const existing = entries.get(key);
13430
13453
  entries.set(key, existing === undefined || existing.kind === "absent" ? { scope, label: pair.label, kind: "absent", checkedAt: at } : { scope, label: pair.label, kind: "retired", retiredAt: at });
13431
13454
  }
13432
- const { limits: _limits, budget: _budget, counters: _counters, ...unknownKeys } = base;
13455
+ const { limits: _limits, budget: _budget, counters: _counters, credits: _credits, ...unknownKeys } = base;
13433
13456
  const budget = mergeBudget(base.budget, observation.budget, at);
13434
13457
  const counters = mergeCounters(base.counters, observation.counters);
13458
+ const credits = mergeCredits(base.credits, observation.credits);
13435
13459
  return {
13436
13460
  ...unknownKeys,
13437
13461
  limits: [...entries.values()].sort(compareEntries),
13438
13462
  ...budget === undefined ? {} : { budget },
13439
- ...counters === undefined ? {} : { counters }
13463
+ ...counters === undefined ? {} : { counters },
13464
+ ...credits === undefined ? {} : { credits }
13440
13465
  };
13441
13466
  }
13442
13467
 
@@ -13512,6 +13537,13 @@ function quotaWindowParts(quota, options) {
13512
13537
  const parts = windows.map(({ part }) => part);
13513
13538
  return age === undefined ? { windows: parts } : { windows: parts, age };
13514
13539
  }
13540
+ function withShortNames(windows) {
13541
+ const abbreviations = scopeAbbreviations(windows.filter(({ part, scope }) => part.kind === "window" && scope !== ALL_SCOPE).map(({ scope }) => scope));
13542
+ for (const window of windows) {
13543
+ window.part.short = window.part.kind === "budget" ? "cr" : window.scope === ALL_SCOPE ? window.part.name : abbreviations.get(window.scope) ?? window.scope;
13544
+ }
13545
+ return windows;
13546
+ }
13515
13547
  function scopedWindowParts(quota, options) {
13516
13548
  if (!quota)
13517
13549
  return { windows: [] };
@@ -13525,6 +13557,7 @@ function scopedWindowParts(quota, options) {
13525
13557
  part: {
13526
13558
  kind: "window",
13527
13559
  name: quotaWindowName(limit),
13560
+ short: "",
13528
13561
  figure: percentLeft(limit.remainingPercent ?? 0),
13529
13562
  remainingPercent,
13530
13563
  checkedAt: limit.checkedAt,
@@ -13542,6 +13575,7 @@ function scopedWindowParts(quota, options) {
13542
13575
  part: {
13543
13576
  kind: "budget",
13544
13577
  name: "credits",
13578
+ short: "",
13545
13579
  figure,
13546
13580
  ...remainingPercent === undefined ? {} : { remainingPercent: clampPercent2(remainingPercent) },
13547
13581
  checkedAt: budget.checkedAt,
@@ -13549,6 +13583,7 @@ function scopedWindowParts(quota, options) {
13549
13583
  }
13550
13584
  });
13551
13585
  }
13586
+ withShortNames(windows);
13552
13587
  if (windows.length > 0) {
13553
13588
  const age = now - Math.min(...windows.map(({ part }) => part.checkedAt));
13554
13589
  if (age > (options.staleAfterMs ?? QUOTA_STALE_AFTER_MS)) {
@@ -13629,15 +13664,14 @@ function narrowTextParts(quota, options) {
13629
13664
  return grouped;
13630
13665
  const general = windows.filter(({ part, scope }) => part.kind === "window" && scope === ALL_SCOPE);
13631
13666
  const scoped = windows.filter(({ part, scope }) => part.kind === "window" && scope !== ALL_SCOPE);
13632
- const abbreviations = scopeAbbreviations(scoped.map(({ scope }) => scope));
13633
13667
  const budget = windows.find(({ part }) => part.kind === "budget");
13634
13668
  const budgetLeft = budget?.spent ? 0 : budget?.part.remainingPercent;
13635
13669
  const extras = [
13636
- ...scoped.map(({ scope, part }) => ({
13637
- label: abbreviations.get(scope) ?? scope,
13670
+ ...scoped.map(({ part }) => ({
13671
+ label: part.short,
13638
13672
  remaining: part.remainingPercent ?? 0
13639
13673
  })),
13640
- ...budgetLeft === undefined ? [] : [{ label: "cr", remaining: budgetLeft }]
13674
+ ...budgetLeft === undefined || budget === undefined ? [] : [{ label: budget.part.short, remaining: budgetLeft }]
13641
13675
  ];
13642
13676
  const tightest = extras.reduce((best, item) => best === undefined || item.remaining < best.remaining ? item : best, undefined);
13643
13677
  const pieces = general.map(({ part }) => `${part.name} ${wholePercent(part.remainingPercent ?? 0)}%`);
@@ -17774,8 +17808,12 @@ class ClaustrumScopedCustody {
17774
17808
  }
17775
17809
  }
17776
17810
 
17811
+ // ../../node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
17812
+ import { resolve as resolve8 } from "node:path";
17813
+
17777
17814
  // ../../node_modules/@cortexkit/common-auth/dist/claustrum/roster.js
17778
17815
  import { createHash as createHash12 } from "node:crypto";
17816
+ import { resolve as resolve7 } from "node:path";
17779
17817
 
17780
17818
  // ../../node_modules/@cortexkit/common-auth/dist/claustrum/interlock.js
17781
17819
  function matches(entry2, credentialId, accountIdentity) {
@@ -18028,11 +18066,12 @@ async function readVaultRoster(path2) {
18028
18066
  var WRITE_LOCK = {
18029
18067
  name: "claustrum-roster-write",
18030
18068
  ttlMs: 1e4,
18031
- timeoutMs: 5000
18069
+ timeoutMs: 5000,
18070
+ renew: true
18032
18071
  };
18033
18072
  var DISCOVERY_LEASE = { name: "claustrum-roster", ttlMs: 30000 };
18034
18073
  async function mutateVaultRoster(path2, change, options = {}) {
18035
- return withLock(path2, WRITE_LOCK, async (lock) => {
18074
+ return withLock(path2, { ...WRITE_LOCK, signal: options.signal }, async (lock) => {
18036
18075
  const current = await readVaultRoster(path2);
18037
18076
  const { next, result } = await change(current, {
18038
18077
  assertOwned: () => lock.assertOwned()
@@ -18042,6 +18081,7 @@ async function mutateVaultRoster(path2, change, options = {}) {
18042
18081
  await writeJsonAtomic(path2, next, {
18043
18082
  beforeRename: async () => {
18044
18083
  await options.beforePublish?.();
18084
+ options.signal?.throwIfAborted();
18045
18085
  await lock.assertOwned();
18046
18086
  }
18047
18087
  });
@@ -18091,43 +18131,52 @@ function receiptFence(row, receipt) {
18091
18131
  return "bind";
18092
18132
  return "refuse";
18093
18133
  }
18094
- function recordVaultQuota(path2, input) {
18095
- return mutateVaultRoster(path2, (current) => {
18096
- const row = current?.rows.find((entry2) => entry2.routeId === input.routeId);
18097
- const fence = !current || !row ? "refuse" : receiptFence(row, input);
18098
- if (!current || !row || fence === "refuse")
18099
- return { result: false };
18100
- const quota2 = mergeQuotaObservation(row.quota, input.observation);
18101
- const bound = fence === "bind" ? { accountIdentity: input.accountIdentity, unclaimed: true } : {};
18102
- return {
18103
- next: {
18104
- ...current,
18105
- rows: current.rows.map((entry2) => entry2 === row ? { ...entry2, ...bound, quota: quota2 } : entry2)
18106
- },
18107
- result: true
18108
- };
18134
+ async function recordVaultQuota(path2, input) {
18135
+ const { routeId, observation, ...receipt } = input;
18136
+ return enqueueFencedVaultQuota(path2, {
18137
+ routeId,
18138
+ observation,
18139
+ accountIdentity: receipt.accountIdentity,
18140
+ receipt
18109
18141
  });
18110
18142
  }
18143
+ async function enqueueFencedVaultQuota(path2, publication2) {
18144
+ if (!isQuotaObservation(publication2.observation))
18145
+ return false;
18146
+ const current = pendingVaultQuota(path2, await readVaultRoster(path2));
18147
+ if (!applyVaultQuota(current, publication2).kept)
18148
+ return false;
18149
+ return enqueueVaultQuota(path2, publication2);
18150
+ }
18111
18151
  function recordVaultAccountQuota(path2, input) {
18112
- return mutateVaultRoster(path2, (current) => {
18113
- const row = current?.rows.find((entry2) => entry2.routeId === input.routeId);
18114
- if (!current || !row || row.accountIdentity === undefined || row.accountIdentity !== input.accountIdentity)
18115
- return { result: false };
18116
- const quota2 = mergeQuotaObservation(row.quota, input.observation);
18117
- return {
18118
- next: {
18119
- ...current,
18120
- rows: current.rows.map((entry2) => entry2 === row ? { ...entry2, quota: quota2 } : entry2)
18121
- },
18122
- result: true
18123
- };
18124
- });
18152
+ return enqueueFencedVaultQuota(path2, input);
18153
+ }
18154
+ function applyVaultQuota(current, input) {
18155
+ const row = current?.rows.find((entry2) => entry2.routeId === input.routeId);
18156
+ const fence = !row ? "refuse" : input.receipt ? receiptFence(row, input.receipt) : row.accountIdentity !== undefined && row.accountIdentity === input.accountIdentity ? "hold" : "refuse";
18157
+ if (!current || !row || fence === "refuse")
18158
+ return { roster: current, kept: false };
18159
+ const quota2 = mergeQuotaObservation(row.quota, input.observation);
18160
+ const bound = fence === "bind" ? { accountIdentity: input.accountIdentity, unclaimed: true } : {};
18161
+ return {
18162
+ roster: {
18163
+ ...current,
18164
+ rows: current.rows.map((entry2) => entry2 === row ? { ...entry2, ...bound, quota: quota2 } : entry2)
18165
+ },
18166
+ kept: true
18167
+ };
18168
+ }
18169
+ var pendingDiscoveries = new Map;
18170
+ function forgetPendingVaultDiscovery(path2) {
18171
+ pendingDiscoveries.delete(resolve7(path2));
18125
18172
  }
18126
18173
  async function refreshVaultRoster(options) {
18127
18174
  options.signal?.throwIfAborted();
18128
18175
  const active = async () => await options.isActive?.() ?? true;
18129
- if (!await active())
18176
+ if (!await active()) {
18177
+ forgetPendingVaultDiscovery(options.path);
18130
18178
  return;
18179
+ }
18131
18180
  const lease = await acquireRefreshFileLock({
18132
18181
  ...DISCOVERY_LEASE,
18133
18182
  path: options.path,
@@ -18140,8 +18189,18 @@ async function refreshVaultRoster(options) {
18140
18189
  throw new ClaustrumConsumerError("roster-busy", "Claustrum account discovery is already in progress");
18141
18190
  return persisted;
18142
18191
  }
18192
+ const key = resolve7(options.path);
18193
+ let discovered;
18143
18194
  try {
18144
- const inventory = await options.custody.discover(options.signal);
18195
+ const previous = await readVaultRoster(options.path);
18196
+ const pending = pendingDiscoveries.get(key);
18197
+ discovered = pending && (pending.previousView === previous?.view || pending.inventory.view === previous?.view) ? pending : {
18198
+ inventory: await options.custody.discover(options.signal),
18199
+ previousView: previous?.view
18200
+ };
18201
+ pendingDiscoveries.delete(key);
18202
+ const { inventory } = discovered;
18203
+ options.onInventory?.(inventory);
18145
18204
  options.signal?.throwIfAborted();
18146
18205
  return await mutateVaultRoster(options.path, async (current) => {
18147
18206
  if (!await active())
@@ -18152,12 +18211,238 @@ async function refreshVaultRoster(options) {
18152
18211
  const next = projectVaultRoster(current, inventory, projection);
18153
18212
  const changed = JSON.stringify(current) !== JSON.stringify(next);
18154
18213
  return { ...changed && { next }, result: next };
18214
+ }, {
18215
+ beforePublish: async () => {
18216
+ options.signal?.throwIfAborted();
18217
+ await lease.assertOwned();
18218
+ }
18155
18219
  });
18220
+ } catch (error) {
18221
+ if (error instanceof LockContentionError && discovered && !options.signal?.aborted && await active())
18222
+ pendingDiscoveries.set(key, discovered);
18223
+ throw error;
18156
18224
  } finally {
18157
18225
  await lease.release();
18158
18226
  }
18159
18227
  }
18160
18228
 
18229
+ // ../../node_modules/@cortexkit/common-auth/dist/claustrum/quota-writer.js
18230
+ var writers = new Map;
18231
+ var logger2 = createLogger("claustrum");
18232
+ var COALESCE_MS = 100;
18233
+ function writerFor(path2) {
18234
+ const key = resolve8(path2);
18235
+ let writer = writers.get(key);
18236
+ if (!writer) {
18237
+ writer = {
18238
+ path: key,
18239
+ pending: new Map,
18240
+ listeners: new Set,
18241
+ wake: new Set,
18242
+ abort: new AbortController,
18243
+ failures: 0,
18244
+ draining: false,
18245
+ order: 0
18246
+ };
18247
+ writers.set(key, writer);
18248
+ }
18249
+ return writer;
18250
+ }
18251
+ function retainVaultQuotaWriter(path2, listener) {
18252
+ const writer = writerFor(path2);
18253
+ writer.listeners.add(listener);
18254
+ let released;
18255
+ return () => released ??= (() => {
18256
+ writer.listeners.delete(listener);
18257
+ return writer.listeners.size ? Promise.resolve() : drainVaultQuota(path2);
18258
+ })();
18259
+ }
18260
+ function fields(publication2) {
18261
+ const result = new Map;
18262
+ const { observation } = publication2;
18263
+ const witness = JSON.stringify([
18264
+ publication2.routeId,
18265
+ publication2.receipt?.credentialId,
18266
+ publication2.receipt?.accountIdentitySource,
18267
+ publication2.receipt?.expectedAccountIdentity
18268
+ ]);
18269
+ const add = (key, at, part) => result.set(`${witness}:${key}`, {
18270
+ at,
18271
+ order: 0,
18272
+ publication: { ...publication2, observation: part }
18273
+ });
18274
+ const keyFor = (scope, label) => JSON.stringify([scope ?? "all", label]);
18275
+ const read = new Set;
18276
+ for (const reading2 of observation.readings ?? []) {
18277
+ const key = keyFor(reading2.scope, reading2.label);
18278
+ read.add(key);
18279
+ add(key, observation.checkedAt, {
18280
+ checkedAt: observation.checkedAt,
18281
+ readings: [{ ...reading2 }]
18282
+ });
18283
+ }
18284
+ for (const pair of observation.coverage ?? []) {
18285
+ const key = keyFor(pair.scope, pair.label);
18286
+ if (!read.has(key))
18287
+ add(key, observation.checkedAt, {
18288
+ checkedAt: observation.checkedAt,
18289
+ coverage: [{ ...pair }]
18290
+ });
18291
+ }
18292
+ if (observation.budget)
18293
+ add("budget", observation.checkedAt, {
18294
+ checkedAt: observation.checkedAt,
18295
+ budget: { ...observation.budget }
18296
+ });
18297
+ for (const [name, counter2] of Object.entries(observation.counters ?? {})) {
18298
+ add(`counter:${name}`, counter2.checkedAt, {
18299
+ checkedAt: observation.checkedAt,
18300
+ counters: { [name]: { ...counter2 } }
18301
+ });
18302
+ }
18303
+ if (observation.credits)
18304
+ add("credits", observation.credits.checkedAt, {
18305
+ checkedAt: observation.checkedAt,
18306
+ credits: { ...observation.credits }
18307
+ });
18308
+ if (!result.size)
18309
+ add("empty", observation.checkedAt, { checkedAt: observation.checkedAt });
18310
+ return result;
18311
+ }
18312
+ function enqueueVaultQuota(path2, publication2) {
18313
+ if (!isQuotaObservation(publication2.observation))
18314
+ return Promise.resolve(false);
18315
+ const writer = writerFor(path2);
18316
+ const account = JSON.stringify([
18317
+ publication2.accountIdentity ?? null,
18318
+ publication2.accountIdentity === undefined ? publication2.routeId : null
18319
+ ]);
18320
+ const pending = writer.pending.get(account) ?? new Map;
18321
+ for (const [key, field] of fields(publication2)) {
18322
+ const previous = pending.get(key);
18323
+ if (!previous || field.at >= previous.at) {
18324
+ field.order = ++writer.order;
18325
+ if (field.publication.observation.coverage)
18326
+ field.priorReading = previous?.publication.observation.readings ? previous.publication : previous?.priorReading;
18327
+ pending.set(key, field);
18328
+ }
18329
+ }
18330
+ if (pending.size)
18331
+ writer.pending.set(account, pending);
18332
+ for (const listener of writer.listeners)
18333
+ listener(publication2);
18334
+ schedule(writer, COALESCE_MS);
18335
+ return Promise.resolve(true);
18336
+ }
18337
+ function orderedFields(pending) {
18338
+ return [...pending.values()].flatMap((account) => [...account.values()]).sort((a, b) => a.order - b.order);
18339
+ }
18340
+ function pendingVaultQuota(path2, roster) {
18341
+ const writer = writers.get(resolve8(path2));
18342
+ if (writer) {
18343
+ for (const field of orderedFields(writer.pending)) {
18344
+ if (field.priorReading)
18345
+ roster = applyVaultQuota(roster, field.priorReading).roster;
18346
+ roster = applyVaultQuota(roster, field.publication).roster;
18347
+ }
18348
+ }
18349
+ return roster;
18350
+ }
18351
+ function schedule(writer, delay3) {
18352
+ if (writer.running || writer.timer || !writer.pending.size || writer.abort.signal.aborted)
18353
+ return;
18354
+ writer.timer = setTimeout(() => {
18355
+ writer.timer = undefined;
18356
+ flush2(writer);
18357
+ }, delay3);
18358
+ if (!writer.draining)
18359
+ writer.timer.unref?.();
18360
+ }
18361
+ function flush2(writer) {
18362
+ if (writer.running || writer.abort.signal.aborted)
18363
+ return;
18364
+ const batch = new Map([...writer.pending].map(([account, pending]) => [
18365
+ account,
18366
+ new Map(pending)
18367
+ ]));
18368
+ writer.running = (async () => {
18369
+ try {
18370
+ await mutateVaultRoster(writer.path, (current) => {
18371
+ let next = current;
18372
+ for (const field of orderedFields(batch)) {
18373
+ if (field.priorReading)
18374
+ next = applyVaultQuota(next, field.priorReading).roster;
18375
+ next = applyVaultQuota(next, field.publication).roster;
18376
+ }
18377
+ return { ...next !== current && { next }, result: undefined };
18378
+ }, { signal: writer.abort.signal });
18379
+ for (const [account, fields2] of batch) {
18380
+ const pending = writer.pending.get(account);
18381
+ for (const [key, field] of fields2) {
18382
+ if (pending?.get(key) === field)
18383
+ pending.delete(key);
18384
+ }
18385
+ if (!pending?.size)
18386
+ writer.pending.delete(account);
18387
+ }
18388
+ writer.failures = 0;
18389
+ } catch (error) {
18390
+ if (!writer.abort.signal.aborted && writer.failures++ === 0) {
18391
+ logger2.warn("vault quota publication delayed; retrying", {
18392
+ error: error instanceof Error ? error.message : String(error)
18393
+ });
18394
+ }
18395
+ } finally {
18396
+ writer.running = undefined;
18397
+ for (const wake of writer.wake)
18398
+ wake();
18399
+ const backoff = writer.failures ? Math.min(5000, 100 * 2 ** Math.min(writer.failures, 6)) * (0.5 + Math.random()) : COALESCE_MS;
18400
+ schedule(writer, backoff);
18401
+ }
18402
+ })();
18403
+ }
18404
+ async function drainVaultQuota(path2, timeoutMs = 1000) {
18405
+ const key = resolve8(path2);
18406
+ const writer = writers.get(key);
18407
+ if (!writer)
18408
+ return;
18409
+ writer.draining = true;
18410
+ clearTimeout(writer.timer);
18411
+ writer.timer = undefined;
18412
+ let deadline;
18413
+ let wake;
18414
+ const drained = new Promise((done) => {
18415
+ wake = () => {
18416
+ if (!writer.pending.size || writer.abort.signal.aborted)
18417
+ done();
18418
+ };
18419
+ writer.wake.add(wake);
18420
+ wake();
18421
+ });
18422
+ try {
18423
+ if (writer.pending.size)
18424
+ flush2(writer);
18425
+ await Promise.race([
18426
+ drained,
18427
+ new Promise((done) => {
18428
+ deadline = setTimeout(done, Math.max(0, timeoutMs));
18429
+ })
18430
+ ]);
18431
+ } finally {
18432
+ clearTimeout(deadline);
18433
+ if (wake)
18434
+ writer.wake.delete(wake);
18435
+ writer.draining = false;
18436
+ if (!writer.listeners.size) {
18437
+ writer.abort.abort();
18438
+ clearTimeout(writer.timer);
18439
+ writer.pending.clear();
18440
+ if (writers.get(key) === writer)
18441
+ writers.delete(key);
18442
+ }
18443
+ }
18444
+ }
18445
+
18161
18446
  // ../../node_modules/@cortexkit/common-auth/dist/claustrum/consumer.js
18162
18447
  class ClaustrumConsumer {
18163
18448
  #options;
@@ -18175,9 +18460,13 @@ class ClaustrumConsumer {
18175
18460
  #releaseInsulaWatch;
18176
18461
  #insulaSkips = new Map;
18177
18462
  #discoveredAt;
18463
+ #releaseQuotaWriter;
18178
18464
  constructor(options) {
18179
18465
  this.#options = options;
18180
18466
  this.#logger = options.logger ?? createLogger("claustrum");
18467
+ this.#releaseQuotaWriter = retainVaultQuotaWriter(options.rosterPath, (publication2) => {
18468
+ this.#roster = applyVaultQuota(this.#roster, publication2).roster;
18469
+ });
18181
18470
  }
18182
18471
  #assertOpen(signal) {
18183
18472
  this.#shutdown.signal.throwIfAborted();
@@ -18191,7 +18480,7 @@ class ClaustrumConsumer {
18191
18480
  this.#shutdown.signal,
18192
18481
  ...signal ? [signal] : []
18193
18482
  ]);
18194
- return new Promise((resolve7, reject) => {
18483
+ return new Promise((resolve9, reject) => {
18195
18484
  const cleanup2 = () => {
18196
18485
  combined.signal.removeEventListener("abort", abort);
18197
18486
  combined.dispose();
@@ -18206,7 +18495,7 @@ class ClaustrumConsumer {
18206
18495
  if (combined.signal.aborted)
18207
18496
  reject(combined.signal.reason);
18208
18497
  else
18209
- resolve7(value);
18498
+ resolve9(value);
18210
18499
  }, (error) => {
18211
18500
  cleanup2();
18212
18501
  reject(error);
@@ -18292,11 +18581,9 @@ class ClaustrumConsumer {
18292
18581
  let discovered;
18293
18582
  const roster = await refreshVaultRoster({
18294
18583
  path: this.#options.rosterPath,
18295
- custody: {
18296
- discover: async (signal) => {
18297
- discovered = await custody.discover(signal);
18298
- return discovered;
18299
- }
18584
+ custody,
18585
+ onInventory: (inventory) => {
18586
+ discovered = inventory;
18300
18587
  },
18301
18588
  isActive: () => this.#active(),
18302
18589
  signal: this.#shutdown.signal,
@@ -18309,7 +18596,7 @@ class ClaustrumConsumer {
18309
18596
  });
18310
18597
  this.#assertOpen();
18311
18598
  const changed = roster?.view !== this.#roster?.view;
18312
- this.#roster = roster;
18599
+ this.#roster = pendingVaultQuota(this.#options.rosterPath, roster);
18313
18600
  custody.retain(roster?.rows ?? []);
18314
18601
  if (discovered && roster?.view !== undefined)
18315
18602
  this.#grantReach = discovered.grantReach ? { view: roster.view, reach: discovered.grantReach } : undefined;
@@ -18406,7 +18693,7 @@ class ClaustrumConsumer {
18406
18693
  return;
18407
18694
  try {
18408
18695
  await readClaustrumEnrollmentToken(this.#options.tokenPath);
18409
- const roster = await readVaultRoster(this.#options.rosterPath);
18696
+ const roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18410
18697
  const row = roster?.rows.find((entry2) => entry2.routeId === routeId);
18411
18698
  return this.#normalizeInsulaQuota(row?.accountIdentity);
18412
18699
  } catch {
@@ -18419,7 +18706,7 @@ class ClaustrumConsumer {
18419
18706
  return { miss: "unreachable" };
18420
18707
  try {
18421
18708
  await readClaustrumEnrollmentToken(this.#options.tokenPath);
18422
- const roster = await readVaultRoster(this.#options.rosterPath);
18709
+ const roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18423
18710
  const account = roster?.rows.find((row) => row.routeId === routeId)?.accountIdentity;
18424
18711
  if (!account || !this.#insula)
18425
18712
  return { miss: "unreachable" };
@@ -18463,7 +18750,7 @@ class ClaustrumConsumer {
18463
18750
  this.#insula = undefined;
18464
18751
  throw new ClaustrumConsumerError("not-active", "Claustrum scoped custody is not active");
18465
18752
  }
18466
- const current = await readVaultRoster(this.#options.rosterPath);
18753
+ const current = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18467
18754
  this.#assertOpen(signal);
18468
18755
  const observed = roster.rows.find((row) => row.routeId === routeId);
18469
18756
  const configured = current?.rows.find((row) => row.routeId === routeId);
@@ -18531,17 +18818,17 @@ class ClaustrumConsumer {
18531
18818
  async decline(routeId) {
18532
18819
  this.#assertOpen();
18533
18820
  await declineVaultRoute(this.#options.rosterPath, routeId);
18534
- this.#roster = await readVaultRoster(this.#options.rosterPath);
18821
+ this.#roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18535
18822
  this.#custody?.retain(this.#roster?.rows ?? []);
18536
18823
  }
18537
18824
  async accept(routeId) {
18538
18825
  this.#assertOpen();
18539
18826
  await acceptVaultRoute(this.#options.rosterPath, routeId);
18540
- this.#roster = await readVaultRoster(this.#options.rosterPath);
18827
+ this.#roster = pendingVaultQuota(this.#options.rosterPath, await readVaultRoster(this.#options.rosterPath));
18541
18828
  }
18542
18829
  async recordQuota(routeId, observation, attempt) {
18543
18830
  this.#assertOpen();
18544
- const kept = await recordVaultQuota(this.#options.rosterPath, {
18831
+ return recordVaultQuota(this.#options.rosterPath, {
18545
18832
  routeId,
18546
18833
  observation,
18547
18834
  credentialId: attempt.credentialId,
@@ -18553,20 +18840,14 @@ class ClaustrumConsumer {
18553
18840
  expectedAccountIdentity: attempt.expectedAccountIdentity
18554
18841
  }
18555
18842
  });
18556
- if (kept)
18557
- this.#roster = await readVaultRoster(this.#options.rosterPath);
18558
- return kept;
18559
18843
  }
18560
18844
  async recordAccountQuota(routeId, accountIdentity, observation) {
18561
18845
  this.#assertOpen();
18562
- const kept = await recordVaultAccountQuota(this.#options.rosterPath, {
18846
+ return recordVaultAccountQuota(this.#options.rosterPath, {
18563
18847
  routeId,
18564
18848
  accountIdentity,
18565
18849
  observation
18566
18850
  });
18567
- if (kept)
18568
- this.#roster = await readVaultRoster(this.#options.rosterPath);
18569
- return kept;
18570
18851
  }
18571
18852
  close() {
18572
18853
  if (this.#shutdown.signal.aborted)
@@ -18581,6 +18862,12 @@ class ClaustrumConsumer {
18581
18862
  this.#insula = undefined;
18582
18863
  this.#roster = undefined;
18583
18864
  this.#grantReach = undefined;
18865
+ this.#releaseQuotaWriter();
18866
+ forgetPendingVaultDiscovery(this.#options.rosterPath);
18867
+ }
18868
+ async dispose() {
18869
+ this.close();
18870
+ await this.#releaseQuotaWriter();
18584
18871
  }
18585
18872
  }
18586
18873
 
@@ -18630,7 +18917,7 @@ class NativeCustodyError extends Error {
18630
18917
  function createNativeCustody(options) {
18631
18918
  const env = { ...options.env ?? process.env };
18632
18919
  const connect = options.connect;
18633
- const logger2 = options.logger;
18920
+ const logger3 = options.logger;
18634
18921
  let closed = false;
18635
18922
  let revoked = false;
18636
18923
  let client;
@@ -18677,8 +18964,8 @@ function createNativeCustody(options) {
18677
18964
  let stopped = false;
18678
18965
  let inner;
18679
18966
  let finish = () => {};
18680
- const ended = new Promise((resolve7) => {
18681
- finish = resolve7;
18967
+ const ended = new Promise((resolve9) => {
18968
+ finish = resolve9;
18682
18969
  });
18683
18970
  const failed = (error) => stopped || closed || error instanceof NativeCustodyError ? { kind: "stopped" } : classifyVaultFailure(error) === "unreachable" ? { kind: "transport_lost", error: new ClaustrumUnreachableError } : { kind: "ended" };
18684
18971
  Promise.resolve().then(connection).then((owned) => {
@@ -18727,8 +19014,8 @@ function createNativeCustody(options) {
18727
19014
  ...options.setTimeout && { setTimeoutImpl: options.setTimeout },
18728
19015
  ...options.clearTimeout && { clearTimeoutImpl: options.clearTimeout },
18729
19016
  logger: {
18730
- warn: () => logger2?.warn("Native custody inventory record skipped"),
18731
- debug: () => logger2?.debug("Native custody failure reported")
19017
+ warn: () => logger3?.warn("Native custody inventory record skipped"),
19018
+ debug: () => logger3?.debug("Native custody failure reported")
18732
19019
  }
18733
19020
  });
18734
19021
  async function run(operation, signal) {
@@ -18852,13 +19139,13 @@ function createNativeCustody(options) {
18852
19139
  }
18853
19140
 
18854
19141
  // src/native-vault-invalidation.ts
18855
- import { resolve as resolve7 } from "node:path";
19142
+ import { resolve as resolve9 } from "node:path";
18856
19143
  var holders = new Set;
18857
19144
  function watchNativeVaultAuthority(holder) {
18858
19145
  const held = {
18859
19146
  ...holder,
18860
- roster: resolve7(holder.roster),
18861
- tokenPath: resolve7(holder.tokenPath)
19147
+ roster: resolve9(holder.roster),
19148
+ tokenPath: resolve9(holder.tokenPath)
18862
19149
  };
18863
19150
  holders.add(held);
18864
19151
  return () => {
@@ -18867,12 +19154,12 @@ function watchNativeVaultAuthority(holder) {
18867
19154
  }
18868
19155
  function retainNativeVaultRoster(path2, roster) {
18869
19156
  for (const holder of holders)
18870
- if (holder.roster === resolve7(path2))
19157
+ if (holder.roster === resolve9(path2))
18871
19158
  holder.retain(roster);
18872
19159
  }
18873
19160
  function closeNativeVaultAuthority(tokenPath) {
18874
19161
  for (const holder of holders)
18875
- if (holder.tokenPath === resolve7(tokenPath))
19162
+ if (holder.tokenPath === resolve9(tokenPath))
18876
19163
  holder.close();
18877
19164
  }
18878
19165
 
@@ -19118,12 +19405,12 @@ async function joinNativePoolWrite(paths, signals, check, onLockEvent) {
19118
19405
  function pause(ms, signals) {
19119
19406
  if (signals.some((signal) => signal.aborted))
19120
19407
  return Promise.resolve();
19121
- return new Promise((resolve8) => {
19408
+ return new Promise((resolve10) => {
19122
19409
  const wake = () => {
19123
19410
  clearTimeout(timer);
19124
19411
  for (const signal of signals)
19125
19412
  signal.removeEventListener("abort", wake);
19126
- resolve8();
19413
+ resolve10();
19127
19414
  };
19128
19415
  const timer = setTimeout(wake, ms);
19129
19416
  for (const signal of signals)
@@ -19379,7 +19666,7 @@ function createNativeRefreshCoordinator(options) {
19379
19666
  name: spec.name,
19380
19667
  timeoutMs: POOL_LOCK_DEFAULTS.timeoutMs
19381
19668
  });
19382
- await new Promise((resolve8) => setTimeout(resolve8, Math.min(POOL_LOCK_DEFAULTS.retryMs, remaining)));
19669
+ await new Promise((resolve10) => setTimeout(resolve10, Math.min(POOL_LOCK_DEFAULTS.retryMs, remaining)));
19383
19670
  }
19384
19671
  }
19385
19672
  async function run(job, request) {
@@ -20819,7 +21106,7 @@ function createNativeUsagePublisher(channel) {
20819
21106
  return {
20820
21107
  observe,
20821
21108
  publish(write) {
20822
- observe(new Promise((resolve8) => setTimeout(resolve8, 0)).then(write));
21109
+ observe(new Promise((resolve10) => setTimeout(resolve10, 0)).then(write));
20823
21110
  },
20824
21111
  async drain() {
20825
21112
  while (pending.size)
@@ -20895,7 +21182,7 @@ class NativeQuotaObservations extends Map {
20895
21182
  }
20896
21183
 
20897
21184
  // src/native-runtime-registry.ts
20898
- import { resolve as resolve8 } from "node:path";
21185
+ import { resolve as resolve10 } from "node:path";
20899
21186
  var identities = new WeakMap;
20900
21187
  var nextIdentity = 0;
20901
21188
  function nativeRuntimeOptionIdentity(value) {
@@ -20924,14 +21211,14 @@ function nativeRuntimeStorageKey(options) {
20924
21211
  "runtime",
20925
21212
  "journal",
20926
21213
  "roster"
20927
- ].map((field) => resolve8(paths[field])),
20928
- resolve8(enrollment.tokenPath),
20929
- resolve8(enrollment.statePath),
20930
- resolve8(connection)
21214
+ ].map((field) => resolve10(paths[field])),
21215
+ resolve10(enrollment.tokenPath),
21216
+ resolve10(enrollment.statePath),
21217
+ resolve10(connection)
20931
21218
  ]);
20932
21219
  }
20933
21220
  function nativeRuntimeConnectionFile(host, env) {
20934
- return resolve8(resolveClaustrumConnectionPath(host === "pi" ? env.PI_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE : undefined, host === "pi" ? {
21221
+ return resolve10(resolveClaustrumConnectionPath(host === "pi" ? env.PI_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE : undefined, host === "pi" ? {
20935
21222
  ...env,
20936
21223
  OPENCODE_ANTHROPIC_AUTH_CLAUSTRUM_CONNECTION_FILE: undefined
20937
21224
  } : env));
@@ -21533,8 +21820,8 @@ function mergeHeaderQuotaSnapshot(existing, incoming) {
21533
21820
  // src/quota-manager.ts
21534
21821
  var nativeSetTimeout = globalThis.setTimeout;
21535
21822
  function pauseOnRealTimer(ms) {
21536
- return new Promise((resolve9) => {
21537
- const id2 = nativeSetTimeout(resolve9, ms);
21823
+ return new Promise((resolve11) => {
21824
+ const id2 = nativeSetTimeout(resolve11, ms);
21538
21825
  if (typeof id2 === "object" && "unref" in id2)
21539
21826
  id2.unref();
21540
21827
  });
@@ -22301,7 +22588,8 @@ async function publishNativeVaultRosterSeed(paths, input, options = {}) {
22301
22588
  }
22302
22589
  async function publishNativeVaultRuntimeSeed(paths, state, options = {}) {
22303
22590
  const imported = decodeNativeRuntime(captureNativePlainData(state), paths.storageId);
22304
- await mutateVaultRoster(paths.roster, async (roster, lease) => {
22591
+ const assertPinned = async () => {
22592
+ const roster = await readVaultRoster(paths.roster);
22305
22593
  for (const [id2, entry2] of Object.entries(imported.accounts)) {
22306
22594
  if (entry2.binding.kind !== "custody")
22307
22595
  continue;
@@ -22310,13 +22598,13 @@ async function publishNativeVaultRuntimeSeed(paths, state, options = {}) {
22310
22598
  if (!row?.accountIdentity || row.accountIdentity !== binding2.accountIdentity || row.credentialId !== binding2.credentialId && !row.aliases?.includes(binding2.credentialId))
22311
22599
  throw new NativeRuntimeError("publication-refused");
22312
22600
  }
22313
- await updateNativeRuntime(paths.runtime, paths.storageId, () => imported, {
22314
- beforeRename: async () => {
22315
- await options.assertOwned?.();
22316
- await lease.assertOwned();
22317
- }
22318
- });
22319
- return { result: undefined };
22601
+ };
22602
+ await assertPinned();
22603
+ await updateNativeRuntime(paths.runtime, paths.storageId, () => imported, {
22604
+ beforeRename: async () => {
22605
+ await options.assertOwned?.();
22606
+ await assertPinned();
22607
+ }
22320
22608
  });
22321
22609
  }
22322
22610
  var NATIVE_VAULT_CONNECT_TIMEOUT_MS = 2000;
@@ -22363,11 +22651,6 @@ function createNativeVaultRuntime(options) {
22363
22651
  onLockEvent: options.onLockEvent
22364
22652
  });
22365
22653
  const observeLock = nativeLockObserver(options.onLockEvent);
22366
- const observeRosterLock = () => observeLock?.({
22367
- type: "acquiring",
22368
- name: "claustrum-roster-write",
22369
- path: paths.roster
22370
- });
22371
22654
  let rosterWatch;
22372
22655
  let rosterWatching = false;
22373
22656
  let rosterView;
@@ -22584,46 +22867,49 @@ function createNativeVaultRuntime(options) {
22584
22867
  await requireActive(signal);
22585
22868
  if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22586
22869
  return;
22587
- observeRosterLock();
22588
- await mutateVaultRoster(paths.roster, async (roster, lease) => {
22589
- if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22590
- return { result: undefined };
22591
- const primary = roster?.rows.find((row) => (row.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID || row.aliases?.includes(NATIVE_PRIMARY_CREDENTIAL_ID)) && row.credentialType === "oauth" && !row.stale && !row.unclaimed && typeof row.accountIdentity === "string" && row.accountIdentity.length > 0);
22592
- const read = await store.readSettings();
22593
- if (read.status !== "ready")
22594
- throw new NativeCustodyError("invalid-state");
22595
- const previous = nativeVaultPrimaryPin(read.settings);
22596
- if (!absentOnly && (!primary && !previous || primary && previous?.routeId === primary.routeId && previous.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID && previous.accountIdentity === primary.accountIdentity))
22597
- return { result: undefined };
22598
- const writer = createNativePoolStore({
22599
- paths,
22600
- quota: nativeQuotaCodec,
22601
- onLockEvent: options.onLockEvent,
22602
- onStep: async (point) => {
22603
- if (point === "before-config-write" || point === "before-state-write") {
22604
- await requireActive(signal);
22605
- await lease.assertOwned();
22606
- }
22607
- }
22608
- });
22609
- await writer.updateSettings(async (settings) => {
22610
- if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22611
- return settings;
22612
- if (primary) {
22613
- settings.mainAccountId = primary.routeId;
22614
- settings.claustrum = {
22615
- primaryAccount: {
22616
- credentialId: NATIVE_PRIMARY_CREDENTIAL_ID,
22617
- accountId: primary.accountIdentity
22618
- }
22619
- };
22620
- } else {
22621
- delete settings.mainAccountId;
22622
- delete settings.claustrum;
22870
+ const roster = await readVaultRoster(paths.roster);
22871
+ if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22872
+ return;
22873
+ const primaryFor = (roster2) => roster2?.rows.find((row) => (row.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID || row.aliases?.includes(NATIVE_PRIMARY_CREDENTIAL_ID)) && row.credentialType === "oauth" && !row.stale && !row.unclaimed && typeof row.accountIdentity === "string" && row.accountIdentity.length > 0);
22874
+ const primary = primaryFor(roster);
22875
+ const read = await store.readSettings();
22876
+ if (read.status !== "ready")
22877
+ throw new NativeCustodyError("invalid-state");
22878
+ const previous = nativeVaultPrimaryPin(read.settings);
22879
+ if (!absentOnly && (!primary && !previous || primary && previous?.routeId === primary.routeId && previous.credentialId === NATIVE_PRIMARY_CREDENTIAL_ID && previous.accountIdentity === primary.accountIdentity))
22880
+ return;
22881
+ const assertPrimary = async () => {
22882
+ await requireActive(signal);
22883
+ const pinned = primaryFor(await readVaultRoster(paths.roster));
22884
+ if (pinned?.routeId !== primary?.routeId || pinned?.accountIdentity !== primary?.accountIdentity)
22885
+ throw new NativeRuntimeError("publication-refused");
22886
+ };
22887
+ const writer = createNativePoolStore({
22888
+ paths,
22889
+ quota: nativeQuotaCodec,
22890
+ onLockEvent: options.onLockEvent,
22891
+ onStep: async (point) => {
22892
+ if (point === "before-config-write" || point === "before-state-write") {
22893
+ await assertPrimary();
22623
22894
  }
22895
+ }
22896
+ });
22897
+ await writer.updateSettings(async (settings) => {
22898
+ if (absentOnly && !await nativeVaultFileAbsent(paths.config))
22624
22899
  return settings;
22625
- });
22626
- return { result: undefined };
22900
+ if (primary) {
22901
+ settings.mainAccountId = primary.routeId;
22902
+ settings.claustrum = {
22903
+ primaryAccount: {
22904
+ credentialId: NATIVE_PRIMARY_CREDENTIAL_ID,
22905
+ accountId: primary.accountIdentity
22906
+ }
22907
+ };
22908
+ } else {
22909
+ delete settings.mainAccountId;
22910
+ delete settings.claustrum;
22911
+ }
22912
+ return settings;
22627
22913
  });
22628
22914
  }
22629
22915
  async function rowFor(roster, routeId) {
@@ -23003,56 +23289,52 @@ function createNativeVaultRuntime(options) {
23003
23289
  ]);
23004
23290
  if ((versions.get(key) ?? 0) > receipt.recordVersion)
23005
23291
  return false;
23006
- observeRosterLock();
23007
- return mutateVaultRoster(paths.roster, async (roster, lease) => {
23008
- const row = await rowFor(roster, route.logicalId);
23009
- if (!row?.accountIdentity || row.routeId !== route.routeId || row.accountIdentity !== receipt.assertedAccountIdentity || row.credentialId !== receipt.credentialId && !row.aliases?.includes(receipt.credentialId))
23010
- return { result: false };
23011
- const accountIdentity = row.accountIdentity;
23012
- let kept = false;
23013
- try {
23014
- const outcome = await updateNativeRuntimeOptional(paths.runtime, paths.storageId, (current) => {
23015
- const old = current.accounts[route.routeId];
23016
- const binding2 = old?.binding;
23017
- if (binding2?.kind === "custody" && binding2.credentialId === receipt.credentialId && binding2.accountIdentity === receipt.assertedAccountIdentity && binding2.recordVersion > receipt.recordVersion)
23018
- throw new NativeRuntimeError("runtime-conflict");
23019
- const same = binding2?.kind === "custody" && binding2.accountIdentity === receipt.assertedAccountIdentity;
23020
- current.accounts[route.routeId] = change({
23021
- ...same ? old : {},
23022
- binding: {
23023
- kind: "custody",
23024
- storageId: paths.storageId,
23025
- routeId: route.routeId,
23026
- credentialId: receipt.credentialId,
23027
- accountIdentity,
23028
- recordVersion: receipt.recordVersion
23029
- }
23030
- });
23031
- kept = true;
23032
- return current;
23033
- }, {
23034
- onLockEvent: options.onLockEvent,
23035
- beforeRename: async () => {
23036
- await requireActive();
23037
- const pinned = await rowFor(roster, route.logicalId);
23038
- if (!pinned || pinned.routeId !== route.routeId || pinned.accountIdentity !== receipt.assertedAccountIdentity)
23039
- throw new NativeRuntimeError("publication-refused");
23040
- const superseded = (versions.get(key) ?? 0) > receipt.recordVersion;
23041
- if (superseded && onSuperseded === "refuse")
23042
- throw new NativeRuntimeError("runtime-conflict");
23043
- await lease.assertOwned();
23044
- return superseded ? "skip" : "publish";
23292
+ const row = await rowFor(await readVaultRoster(paths.roster), route.logicalId);
23293
+ if (!row?.accountIdentity || row.routeId !== route.routeId || row.accountIdentity !== receipt.assertedAccountIdentity || row.credentialId !== receipt.credentialId && !row.aliases?.includes(receipt.credentialId))
23294
+ return false;
23295
+ const accountIdentity = row.accountIdentity;
23296
+ let kept = false;
23297
+ try {
23298
+ const outcome = await updateNativeRuntimeOptional(paths.runtime, paths.storageId, (current) => {
23299
+ const old = current.accounts[route.routeId];
23300
+ const binding2 = old?.binding;
23301
+ if (binding2?.kind === "custody" && binding2.credentialId === receipt.credentialId && binding2.accountIdentity === receipt.assertedAccountIdentity && binding2.recordVersion > receipt.recordVersion)
23302
+ throw new NativeRuntimeError("runtime-conflict");
23303
+ const same = binding2?.kind === "custody" && binding2.accountIdentity === receipt.assertedAccountIdentity && (binding2.credentialId === row.credentialId || row.aliases?.includes(binding2.credentialId));
23304
+ current.accounts[route.routeId] = change({
23305
+ ...same ? old : {},
23306
+ binding: {
23307
+ kind: "custody",
23308
+ storageId: paths.storageId,
23309
+ routeId: route.routeId,
23310
+ credentialId: receipt.credentialId,
23311
+ accountIdentity,
23312
+ recordVersion: receipt.recordVersion
23045
23313
  }
23046
23314
  });
23047
- if (outcome.status === "skipped")
23048
- return { result: false };
23049
- } catch (error) {
23050
- if (error instanceof NativeRuntimeError && error.code === "runtime-conflict")
23051
- return { result: false };
23052
- throw error;
23053
- }
23054
- return { result: kept };
23055
- });
23315
+ kept = true;
23316
+ return current;
23317
+ }, {
23318
+ onLockEvent: options.onLockEvent,
23319
+ beforeRename: async () => {
23320
+ await requireActive();
23321
+ const pinned = await rowFor(await readVaultRoster(paths.roster), route.logicalId);
23322
+ if (!pinned || pinned.routeId !== route.routeId || pinned.accountIdentity !== receipt.assertedAccountIdentity || pinned.credentialId !== receipt.credentialId && !pinned.aliases?.includes(receipt.credentialId))
23323
+ throw new NativeRuntimeError("publication-refused");
23324
+ const superseded = (versions.get(key) ?? 0) > receipt.recordVersion;
23325
+ if (superseded && onSuperseded === "refuse")
23326
+ throw new NativeRuntimeError("runtime-conflict");
23327
+ return superseded ? "skip" : "publish";
23328
+ }
23329
+ });
23330
+ if (outcome.status === "skipped")
23331
+ return false;
23332
+ } catch (error) {
23333
+ if (error instanceof NativeRuntimeError && error.code === "runtime-conflict")
23334
+ return false;
23335
+ throw error;
23336
+ }
23337
+ return kept;
23056
23338
  }
23057
23339
  async function fetchReading(routeId, fetchImpl, signal, read, onFailure, dispatch) {
23058
23340
  const combined = signalFor(signal);
@@ -23136,7 +23418,7 @@ function recencyOnly(patch) {
23136
23418
  return keys4.length === 1 && keys4[0] === "lastUsed" && typeof patch.lastUsed === "number";
23137
23419
  }
23138
23420
  function waitFor(pending, signal) {
23139
- return new Promise((resolve9, reject) => {
23421
+ return new Promise((resolve11, reject) => {
23140
23422
  const abort = () => {
23141
23423
  cleanup2();
23142
23424
  reject(signal.reason);
@@ -23145,7 +23427,7 @@ function waitFor(pending, signal) {
23145
23427
  signal.addEventListener("abort", abort, { once: true });
23146
23428
  pending.then((value) => {
23147
23429
  cleanup2();
23148
- signal.aborted ? reject(signal.reason) : resolve9(value);
23430
+ signal.aborted ? reject(signal.reason) : resolve11(value);
23149
23431
  }, (error) => {
23150
23432
  cleanup2();
23151
23433
  reject(error);
@@ -23219,7 +23501,7 @@ function leaseNativeVaultRuntime(use, close) {
23219
23501
  // src/pool-paths.ts
23220
23502
  import { createHash as createHash17 } from "node:crypto";
23221
23503
  import { realpath as realpath3 } from "node:fs/promises";
23222
- import { basename as basename7, dirname as dirname13, join as join14, resolve as resolve9 } from "node:path";
23504
+ import { basename as basename7, dirname as dirname13, join as join14, resolve as resolve11 } from "node:path";
23223
23505
 
23224
23506
  // src/sticky-routing.ts
23225
23507
  import { createHash as createHash16, randomUUID as randomUUID14 } from "node:crypto";
@@ -23348,8 +23630,8 @@ function migrateStickyRoutingState(source2, rowIdMap) {
23348
23630
  const assignment = state.assignments[String(index)];
23349
23631
  if (!isRecord13(original) || !assignment)
23350
23632
  throw new Error;
23351
- const fields = Object.keys(assignment).filter((field) => field !== "affinityModelId" || Object.hasOwn(original, "affinityModelId"));
23352
- if (Object.keys(original).length !== fields.length || fields.some((field) => !Object.hasOwn(original, field) || !Object.is(original[field], Reflect.get(assignment, field)))) {
23633
+ const fields2 = Object.keys(assignment).filter((field) => field !== "affinityModelId" || Object.hasOwn(original, "affinityModelId"));
23634
+ if (Object.keys(original).length !== fields2.length || fields2.some((field) => !Object.hasOwn(original, field) || !Object.is(original[field], Reflect.get(assignment, field)))) {
23353
23635
  throw new Error;
23354
23636
  }
23355
23637
  const accountId = rowIdMap.get(assignment.accountId);
@@ -23575,7 +23857,7 @@ class StickySessionRouter {
23575
23857
  if (!wait || performance.now() >= deadline) {
23576
23858
  throw new Error("Timed out acquiring sticky routing state lock");
23577
23859
  }
23578
- await new Promise((resolve9) => setTimeout(resolve9, STICKY_ROUTING_LOCK_POLL_MS));
23860
+ await new Promise((resolve11) => setTimeout(resolve11, STICKY_ROUTING_LOCK_POLL_MS));
23579
23861
  }
23580
23862
  }
23581
23863
  recoverLocalPins() {
@@ -23941,7 +24223,7 @@ function resolveLocalRoutingDestination(host, paths, env) {
23941
24223
  return (host === "opencode" ? env.OPENCODE_ANTHROPIC_AUTH_ROUTING_STATE_FILE : env.PI_ANTHROPIC_AUTH_ROUTING_STATE_FILE) || getStickyRoutingStatePath(paths.config);
23942
24224
  }
23943
24225
  async function canonicalPath(path2) {
23944
- const absolute = resolve9(path2);
24226
+ const absolute = resolve11(path2);
23945
24227
  try {
23946
24228
  return await realpath3(absolute);
23947
24229
  } catch (error) {
@@ -24532,7 +24814,7 @@ class PersistentRelaySession {
24532
24814
  return;
24533
24815
  if (this.connecting)
24534
24816
  return await this.connecting;
24535
- this.connecting = new Promise((resolve10, reject) => {
24817
+ this.connecting = new Promise((resolve12, reject) => {
24536
24818
  const url = toWebSocketUrl(this.config.url, this.config.token);
24537
24819
  const parsed = new URL(url);
24538
24820
  parsed.searchParams.set("affinity", this.affinity);
@@ -24554,7 +24836,7 @@ class PersistentRelaySession {
24554
24836
  if (message.type === "ready") {
24555
24837
  this.timers.clearTimeout(timeout);
24556
24838
  this.serverState = message.state;
24557
- resolve10();
24839
+ resolve12();
24558
24840
  return;
24559
24841
  }
24560
24842
  this.handleMessage(message);
@@ -24606,15 +24888,15 @@ class PersistentRelaySession {
24606
24888
  const sentAt = perfNowMs();
24607
24889
  let resolveDone;
24608
24890
  let rejectDone;
24609
- const done = new Promise((resolve10, reject) => {
24610
- resolveDone = resolve10;
24891
+ const done = new Promise((resolve12, reject) => {
24892
+ resolveDone = resolve12;
24611
24893
  rejectDone = reject;
24612
24894
  });
24613
- const response = new Promise((resolve10, reject) => {
24895
+ const response = new Promise((resolve12, reject) => {
24614
24896
  const pending = {
24615
24897
  payload,
24616
24898
  bodyText,
24617
- resolve: resolve10,
24899
+ resolve: resolve12,
24618
24900
  reject,
24619
24901
  streamDone: false,
24620
24902
  accepted: false,
@@ -25938,7 +26220,7 @@ function createNativeAccountRuntime(options) {
25938
26220
  const { mode, paths: paths2, store: store2 } = await selectedStorage();
25939
26221
  for (let attempt = 0;attempt < 4; attempt++) {
25940
26222
  if (attempt)
25941
- await new Promise((resolve10) => setTimeout(resolve10, 10));
26223
+ await new Promise((resolve12) => setTimeout(resolve12, 10));
25942
26224
  const settings = await store2.readSettings();
25943
26225
  if (settings.status !== "ready")
25944
26226
  throw new NativeRuntimeError("publication-refused");
@@ -28234,8 +28516,8 @@ async function runNativeCustodyActivation(options, hooks = {}) {
28234
28516
  }
28235
28517
  async function commitMode(paths, routingPath, plan, context) {
28236
28518
  let openGate = () => {};
28237
- const gate = new Promise((resolve10) => {
28238
- openGate = resolve10;
28519
+ const gate = new Promise((resolve12) => {
28520
+ openGate = resolve12;
28239
28521
  });
28240
28522
  let leases;
28241
28523
  let scope;
@@ -28864,7 +29146,7 @@ function readPlain(value, allowed) {
28864
29146
  const prototype = Object.getPrototypeOf(value);
28865
29147
  if (prototype !== Object.prototype && prototype !== null)
28866
29148
  return "malformed";
28867
- const fields = new Map;
29149
+ const fields2 = new Map;
28868
29150
  let unknownKey = false;
28869
29151
  for (const key of Reflect.ownKeys(value)) {
28870
29152
  if (typeof key !== "string")
@@ -28875,9 +29157,9 @@ function readPlain(value, allowed) {
28875
29157
  if (!allowed.includes(key))
28876
29158
  unknownKey = true;
28877
29159
  else
28878
- fields.set(key, descriptor.value);
29160
+ fields2.set(key, descriptor.value);
28879
29161
  }
28880
- return unknownKey ? "unknown-key" : fields;
29162
+ return unknownKey ? "unknown-key" : fields2;
28881
29163
  }
28882
29164
  function readArray(value) {
28883
29165
  if (value === null || typeof value !== "object")
@@ -28931,13 +29213,13 @@ function readKillswitchEntries(value) {
28931
29213
  return;
28932
29214
  const entries = [];
28933
29215
  for (const item of items2) {
28934
- const fields = readPlain(item, ENTRY_KEYS);
28935
- if (!(fields instanceof Map))
29216
+ const fields2 = readPlain(item, ENTRY_KEYS);
29217
+ if (!(fields2 instanceof Map))
28936
29218
  return;
28937
- const account = fields.get("account");
28938
- const fh = fields.get("fh");
28939
- const sd = fields.get("sd");
28940
- const scoped = fields.get("scoped");
29219
+ const account = fields2.get("account");
29220
+ const fh = fields2.get("fh");
29221
+ const sd = fields2.get("sd");
29222
+ const scoped = fields2.get("scoped");
28941
29223
  if (!isKillswitchAccount(account))
28942
29224
  return;
28943
29225
  if (!isDigitInteger(fh) || !isDigitInteger(sd))
@@ -29021,14 +29303,14 @@ var CONTEXT_KEYS = [
29021
29303
  "signal"
29022
29304
  ];
29023
29305
  function readContext(value) {
29024
- const fields = readPlain(value, CONTEXT_KEYS);
29025
- if (!(fields instanceof Map))
29306
+ const fields2 = readPlain(value, CONTEXT_KEYS);
29307
+ if (!(fields2 instanceof Map))
29026
29308
  return;
29027
- const interactive = fields.get("interactive");
29028
- const custodyMode = fields.get("custodyMode");
29029
- const confirmed = fields.get("confirmed");
29030
- const sessionId = fields.get("sessionId");
29031
- const rawSignal = fields.get("signal");
29309
+ const interactive = fields2.get("interactive");
29310
+ const custodyMode = fields2.get("custodyMode");
29311
+ const confirmed = fields2.get("confirmed");
29312
+ const sessionId = fields2.get("sessionId");
29313
+ const rawSignal = fields2.get("signal");
29032
29314
  if (typeof interactive !== "boolean")
29033
29315
  return;
29034
29316
  if (custodyMode !== "local" && custodyMode !== "claustrum")
@@ -29128,9 +29410,9 @@ var DISCONNECT_RESULTS = new Set([
29128
29410
  "conflict"
29129
29411
  ]);
29130
29412
  function readOutcome(action, outcome) {
29131
- const fields = readPlain(outcome, ["ok", "text"]);
29132
- const ok = fields instanceof Map ? fields.get("ok") : undefined;
29133
- const text5 = fields instanceof Map ? fields.get("text") : undefined;
29413
+ const fields2 = readPlain(outcome, ["ok", "text"]);
29414
+ const ok = fields2 instanceof Map ? fields2.get("ok") : undefined;
29415
+ const text5 = fields2 instanceof Map ? fields2.get("text") : undefined;
29134
29416
  if (typeof ok !== "boolean" || typeof text5 !== "string")
29135
29417
  return Object.freeze({ status: "failed", action, code: "invalid-outcome" });
29136
29418
  return Object.freeze({ status: "executed", action, ok, text: text5 });
@@ -29173,12 +29455,12 @@ function disconnectFailureCode(error) {
29173
29455
  return "execution-failed";
29174
29456
  }
29175
29457
  function createNativeMenuExecutor(options) {
29176
- const fields = readPlain(options, ["host", "dispatch", "disconnectVault"]);
29177
- if (!(fields instanceof Map))
29458
+ const fields2 = readPlain(options, ["host", "dispatch", "disconnectVault"]);
29459
+ if (!(fields2 instanceof Map))
29178
29460
  throw new TypeError("Native menu executor options are invalid");
29179
- const host = fields.get("host");
29180
- const dispatch = fields.get("dispatch");
29181
- const disconnectVault = fields.get("disconnectVault");
29461
+ const host = fields2.get("host");
29462
+ const dispatch = fields2.get("dispatch");
29463
+ const disconnectVault = fields2.get("disconnectVault");
29182
29464
  if (!HOSTS2.has(host))
29183
29465
  throw invalidOption2("host");
29184
29466
  if (typeof dispatch !== "function" || utilTypes7.isProxy(dispatch))
@@ -29933,11 +30215,11 @@ async function refreshForRequest(runtime2, ready) {
29933
30215
  break;
29934
30216
  if (combined.aborted)
29935
30217
  break;
29936
- await new Promise((resolve10) => {
30218
+ await new Promise((resolve12) => {
29937
30219
  const finish = () => {
29938
30220
  clearTimeout(pause2);
29939
30221
  combined.removeEventListener("abort", finish);
29940
- resolve10();
30222
+ resolve12();
29941
30223
  };
29942
30224
  const pause2 = setTimeout(finish, 25);
29943
30225
  combined.addEventListener("abort", finish, { once: true });
@@ -29953,16 +30235,16 @@ async function refreshForRequest(runtime2, ready) {
29953
30235
  function waitForRequest(pending, signal) {
29954
30236
  if (!signal)
29955
30237
  return pending;
29956
- return new Promise((resolve10, reject) => {
30238
+ return new Promise((resolve12, reject) => {
29957
30239
  const abort = () => reject(signal.reason);
29958
30240
  signal.addEventListener("abort", abort, { once: true });
29959
- pending.then(resolve10, reject).finally(() => signal.removeEventListener("abort", abort));
30241
+ pending.then(resolve12, reject).finally(() => signal.removeEventListener("abort", abort));
29960
30242
  if (signal.aborted)
29961
30243
  abort();
29962
30244
  });
29963
30245
  }
29964
30246
  // src/native-vault-connection.ts
29965
- import { dirname as dirname17, join as join16, resolve as resolve11 } from "node:path";
30247
+ import { dirname as dirname17, join as join16, resolve as resolve13 } from "node:path";
29966
30248
  // ../../node_modules/@cortexkit/common-auth/dist/opencode2/integration.js
29967
30249
  var PLACEHOLDER_PREFIX = "common-auth-placeholder";
29968
30250
  var PLACEHOLDER_LIFETIME_MS = 365 * 24 * 60 * 60 * 1000;
@@ -29973,7 +30255,7 @@ function placeholderSecret(integrationID) {
29973
30255
  import { createHash as createHash20 } from "node:crypto";
29974
30256
  import { constants as constants4 } from "node:fs";
29975
30257
  import { lstat as lstat9, mkdir as mkdir13, open as open10, unlink as unlink8 } from "node:fs/promises";
29976
- import { dirname as dirname16, resolve as resolve10 } from "node:path";
30258
+ import { dirname as dirname16, resolve as resolve12 } from "node:path";
29977
30259
  import { setTimeout as sleep } from "node:timers/promises";
29978
30260
 
29979
30261
  // ../../node_modules/@cortexkit/common-auth/dist/pi-slot/lock.js
@@ -30066,7 +30348,7 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
30066
30348
  if (!released && lastUpdate + RENEWAL_STALE < Date.now())
30067
30349
  compromise();
30068
30350
  }
30069
- function schedule(delay3 = UPDATE) {
30351
+ function schedule2(delay3 = UPDATE) {
30070
30352
  if (released)
30071
30353
  return;
30072
30354
  timer = setTimeout(() => {
@@ -30080,7 +30362,7 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
30080
30362
  if (errorCode2(error) === "ENOENT" || lastUpdate + RENEWAL_STALE < Date.now())
30081
30363
  compromise();
30082
30364
  else
30083
- schedule(1000);
30365
+ schedule2(1000);
30084
30366
  }
30085
30367
  async function update() {
30086
30368
  assertFresh();
@@ -30113,14 +30395,14 @@ async function acquirePiLock(authPath, onCompromised, onRenew) {
30113
30395
  mtime = next.getTime();
30114
30396
  lastUpdate = Date.now();
30115
30397
  active.set(path2, { ...identity2, mtime, renewedAt: lastUpdate });
30116
- schedule();
30398
+ schedule2();
30117
30399
  }
30118
30400
  onRenew?.(async () => {
30119
30401
  if (timer)
30120
30402
  clearTimeout(timer);
30121
30403
  await update();
30122
30404
  });
30123
- schedule();
30405
+ schedule2();
30124
30406
  return {
30125
30407
  assertFresh,
30126
30408
  async release() {
@@ -30361,8 +30643,8 @@ function createPiSlot(options, onStep, hooks) {
30361
30643
  if (!provider || !options.authPath || !options.stashPath || !placeholderKey || placeholderKey.startsWith("!") || placeholderKey.includes("$") || !Number.isFinite(timeout) || timeout < 0) {
30362
30644
  throw new PiSlotError("invalid-options");
30363
30645
  }
30364
- const authPath = resolve10(options.authPath);
30365
- const stashPath = resolve10(options.stashPath);
30646
+ const authPath = resolve12(options.authPath);
30647
+ const stashPath = resolve12(options.stashPath);
30366
30648
  if (authPath === stashPath || stashPath === `${authPath}.lock`) {
30367
30649
  throw new PiSlotError("invalid-options");
30368
30650
  }
@@ -30500,7 +30782,7 @@ function createPiSlot(options, onStep, hooks) {
30500
30782
  // src/native-vault-connection.ts
30501
30783
  function nativePiAuthSlotPaths(options) {
30502
30784
  return {
30503
- authPath: resolve11(options.authPath),
30785
+ authPath: resolve13(options.authPath),
30504
30786
  stashPath: join16(dirname17(getHostClaustrumEnrollmentPaths("pi", options.env).tokenPath), "pi-auth-slot", "anthropic.json"),
30505
30787
  provider: "anthropic",
30506
30788
  placeholderKey: placeholderSecret("anthropic")
@@ -30523,7 +30805,7 @@ import { createHash as createHash21 } from "node:crypto";
30523
30805
  import { realpathSync as realpathSync2 } from "node:fs";
30524
30806
  import { mkdir as mkdir14, readdir as readdir3, rm as rm8, stat as stat9, writeFile as writeFile5 } from "node:fs/promises";
30525
30807
  import { tmpdir as tmpdir6 } from "node:os";
30526
- import { join as join17, resolve as resolve12 } from "node:path";
30808
+ import { join as join17, resolve as resolve14 } from "node:path";
30527
30809
  var CLAUDE_PRIME_COMMAND_NAME = "claude-prime";
30528
30810
  var PRIME_TICK_MS = 60000;
30529
30811
  var PRIME_DUE_OFFSET_MS = 60000;
@@ -30714,7 +30996,7 @@ function defaultMarkerDir() {
30714
30996
  return join17(tmpdir6(), "opencode-anthropic-auth", "prime");
30715
30997
  }
30716
30998
  function primeStorageFingerprint(storagePath) {
30717
- const absolutePath = resolve12(storagePath);
30999
+ const absolutePath = resolve14(storagePath);
30718
31000
  let canonicalPath2;
30719
31001
  try {
30720
31002
  canonicalPath2 = realpathSync2(absolutePath);