@hasna/todos 0.15.49 → 0.15.51

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.
@@ -70,7 +70,7 @@ var package_default;
70
70
  var init_package = __esm(() => {
71
71
  package_default = {
72
72
  name: "@hasna/todos",
73
- version: "0.15.49",
73
+ version: "0.15.51",
74
74
  description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
75
75
  type: "module",
76
76
  main: "dist/index.js",
@@ -129,6 +129,7 @@ var init_package = __esm(() => {
129
129
  files: [
130
130
  "dist",
131
131
  "dashboard/dist",
132
+ "postinstall.js",
132
133
  "LICENSE",
133
134
  "README.md"
134
135
  ],
@@ -155,7 +156,7 @@ var init_package = __esm(() => {
155
156
  "test:attested-container-compatibility-vector": "bun test scripts/attested-container-compatibility-vector.test.ts",
156
157
  "issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
157
158
  prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
158
- postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
159
+ postinstall: "node postinstall.js"
159
160
  },
160
161
  keywords: [
161
162
  "todos",
@@ -189,13 +190,15 @@ var init_package = __esm(() => {
189
190
  author: "Andrei Hasna <andrei@hasna.com>",
190
191
  license: "Apache-2.0",
191
192
  dependencies: {
192
- "@hasna/contracts": "0.14.0",
193
+ "@hasna/contracts": "0.14.2",
193
194
  "@hasna/events": "^0.1.11",
195
+ "@hasna/paths": "0.1.0",
194
196
  "@modelcontextprotocol/sdk": "^1.12.1",
195
197
  chalk: "^5.4.1",
196
198
  commander: "^13.1.0",
197
199
  ink: "^5.2.0",
198
200
  react: "^18.3.1",
201
+ "signal-exit": "3.0.7",
199
202
  zod: "3.25.76"
200
203
  },
201
204
  overrides: {
@@ -225,7 +228,7 @@ var init_package_version = __esm(() => {
225
228
  init_package();
226
229
  });
227
230
 
228
- // node_modules/.bun/@hasna+contracts@0.14.0+619f74e7b30eeaf4/node_modules/@hasna/contracts/dist/auth/index.js
231
+ // node_modules/.bun/@hasna+contracts@0.14.2+a5fb9613d5af3331/node_modules/@hasna/contracts/dist/auth/index.js
229
232
  import { createHash, createHmac, randomBytes, timingSafeEqual } from "crypto";
230
233
  function isValidTenantId(value) {
231
234
  return typeof value === "string" && TENANT_ID_PATTERN.test(value);
@@ -1308,18 +1311,112 @@ function normalizeAgentNameInput(name) {
1308
1311
  return name.trim().toLowerCase();
1309
1312
  }
1310
1313
 
1311
- // src/lib/sync-utils.ts
1312
- import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
1314
+ // node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
1313
1315
  import { homedir } from "os";
1314
1316
  import { join } from "path";
1317
+ function assertApp(app) {
1318
+ if (typeof app !== "string" || app.length === 0) {
1319
+ throw new TypeError("paths: app must be a non-empty string");
1320
+ }
1321
+ if (!APP_SLUG_RE.test(app)) {
1322
+ throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
1323
+ }
1324
+ }
1325
+ function envOf(options) {
1326
+ return options.env ?? process.env;
1327
+ }
1328
+ function envValue(options, kind) {
1329
+ const value = envOf(options)[KIND_ENV[kind]];
1330
+ return typeof value === "string" && value.length > 0 ? value : undefined;
1331
+ }
1332
+ function isMacOS(platform) {
1333
+ return platform === "darwin";
1334
+ }
1335
+ function baseDir(kind, options) {
1336
+ const override = envValue(options, kind);
1337
+ if (override)
1338
+ return override;
1339
+ const home = options.home ?? homedir();
1340
+ const platform = options.platform ?? process.platform;
1341
+ if (isMacOS(platform)) {
1342
+ switch (kind) {
1343
+ case "config":
1344
+ case "data":
1345
+ return join(home, "Library", "Application Support", "Hasna");
1346
+ case "cache":
1347
+ return join(home, "Library", "Caches", "Hasna");
1348
+ case "state":
1349
+ return join(home, "Library", "Logs", "Hasna");
1350
+ }
1351
+ }
1352
+ switch (kind) {
1353
+ case "config":
1354
+ return join(home, ".config", "hasna");
1355
+ case "data":
1356
+ return join(home, ".local", "share", "hasna");
1357
+ case "state":
1358
+ return join(home, ".local", "state", "hasna");
1359
+ case "cache":
1360
+ return join(home, ".cache", "hasna");
1361
+ }
1362
+ }
1363
+ function resolvePath(kind, options) {
1364
+ assertApp(options.app);
1365
+ const appSegment = options.internal === true ? join("internal", options.app) : options.app;
1366
+ return join(baseDir(kind, options), appSegment);
1367
+ }
1368
+ function dataDir(options) {
1369
+ return resolvePath("data", options);
1370
+ }
1371
+ var KIND_ENV, APP_SLUG_RE;
1372
+ var init_dist = __esm(() => {
1373
+ KIND_ENV = {
1374
+ config: "HASNA_CONFIG_HOME",
1375
+ data: "HASNA_DATA_HOME",
1376
+ state: "HASNA_STATE_HOME",
1377
+ cache: "HASNA_CACHE_HOME"
1378
+ };
1379
+ APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
1380
+ });
1381
+
1382
+ // src/lib/paths.ts
1383
+ import { existsSync } from "fs";
1384
+ import { homedir as homedir2 } from "os";
1385
+ import { join as join2, resolve } from "path";
1386
+ function effectiveHome(env = process.env) {
1387
+ return env.HOME || env.USERPROFILE || homedir2();
1388
+ }
1389
+ function legacyHomeDir(env = process.env) {
1390
+ return join2(effectiveHome(env), ".hasna", "todos");
1391
+ }
1392
+ function resolverHome(env = process.env) {
1393
+ return dataDir({ app: "todos", home: effectiveHome(env), env });
1394
+ }
1395
+ function adoptResolverHome(resolved, env = process.env) {
1396
+ const dataOverride = env.HASNA_DATA_HOME;
1397
+ if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
1398
+ return true;
1399
+ return existsSync(join2(resolved, "todos.db")) || existsSync(join2(resolved, "config.json"));
1400
+ }
1401
+ function getTodosDir(env = process.env) {
1402
+ const resolved = resolverHome(env);
1403
+ return resolve(adoptResolverHome(resolved, env) ? resolved : legacyHomeDir(env));
1404
+ }
1405
+ var init_paths = __esm(() => {
1406
+ init_dist();
1407
+ });
1408
+
1409
+ // src/lib/sync-utils.ts
1410
+ import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
1411
+ import { homedir as homedir3 } from "os";
1315
1412
  function getHomeDir() {
1316
- return process.env["HOME"] || process.env["USERPROFILE"] || homedir();
1413
+ return process.env["HOME"] || process.env["USERPROFILE"] || homedir3();
1317
1414
  }
1318
1415
  function getTodosGlobalDir() {
1319
- return join(getHomeDir(), ".hasna", "todos");
1416
+ return getTodosDir();
1320
1417
  }
1321
1418
  function ensureDir(dir) {
1322
- if (!existsSync(dir))
1419
+ if (!existsSync2(dir))
1323
1420
  mkdirSync(dir, { recursive: true });
1324
1421
  }
1325
1422
  function readJsonFile(path) {
@@ -1340,18 +1437,19 @@ function appendSyncConflict(metadata, conflict, limit = 5) {
1340
1437
  }
1341
1438
  var HOME;
1342
1439
  var init_sync_utils = __esm(() => {
1440
+ init_paths();
1343
1441
  HOME = getHomeDir();
1344
1442
  });
1345
1443
 
1346
1444
  // src/lib/creator-identity.ts
1347
- import { existsSync as existsSync2, rmSync } from "fs";
1348
- import { join as join2 } from "path";
1445
+ import { existsSync as existsSync3, rmSync } from "fs";
1446
+ import { join as join3 } from "path";
1349
1447
  function identityFilePath() {
1350
- return join2(getTodosGlobalDir(), "identity.json");
1448
+ return join3(getTodosGlobalDir(), "identity.json");
1351
1449
  }
1352
1450
  function readPersistedIdentity() {
1353
1451
  const path = identityFilePath();
1354
- if (!existsSync2(path))
1452
+ if (!existsSync3(path))
1355
1453
  return null;
1356
1454
  const parsed = readJsonFile(path);
1357
1455
  if (!parsed || typeof parsed.agent_id !== "string" || !parsed.agent_id.trim())
@@ -1499,15 +1597,15 @@ var init_plan_project_link_contract = __esm(() => {
1499
1597
  });
1500
1598
 
1501
1599
  // src/lib/config.ts
1502
- import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
1503
- import { dirname, join as join3 } from "path";
1600
+ import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
1601
+ import { dirname, join as join4 } from "path";
1504
1602
  function getConfigPath() {
1505
- return join3(getTodosGlobalDir(), "config.json");
1603
+ return join4(getTodosGlobalDir(), "config.json");
1506
1604
  }
1507
1605
  function loadConfig() {
1508
1606
  if (cached)
1509
1607
  return cached;
1510
- if (!existsSync3(getConfigPath())) {
1608
+ if (!existsSync4(getConfigPath())) {
1511
1609
  cached = {};
1512
1610
  return cached;
1513
1611
  }
@@ -5357,7 +5455,7 @@ async function retryOnTransientPostgresError(fn, attempts = 2, delayMs = 150) {
5357
5455
  lastError = error;
5358
5456
  if (!isTransientPostgresError(error) || attempt === attempts)
5359
5457
  throw error;
5360
- await new Promise((resolve) => setTimeout(resolve, delayMs * attempt));
5458
+ await new Promise((resolve2) => setTimeout(resolve2, delayMs * attempt));
5361
5459
  }
5362
5460
  }
5363
5461
  throw lastError;
@@ -11134,9 +11232,9 @@ var init_schema = __esm(() => {
11134
11232
  });
11135
11233
 
11136
11234
  // src/db/machines.ts
11137
- import { existsSync as existsSync4 } from "fs";
11235
+ import { existsSync as existsSync5 } from "fs";
11138
11236
  import { hostname as osHostname, platform as osPlatform, arch as osArch } from "os";
11139
- import { resolve } from "path";
11237
+ import { resolve as resolve2 } from "path";
11140
11238
  import { spawnSync } from "child_process";
11141
11239
  function parseMetadata(value) {
11142
11240
  if (!value)
@@ -11167,7 +11265,7 @@ function discoverGitRoot(workspacePath) {
11167
11265
  }
11168
11266
  function topologyMetadata(input, existing = {}) {
11169
11267
  const next = { ...existing };
11170
- const workspacePath = input.workspace_path ? resolve(input.workspace_path) : undefined;
11268
+ const workspacePath = input.workspace_path ? resolve2(input.workspace_path) : undefined;
11171
11269
  const entries = {
11172
11270
  tailscale_name: input.tailscale_name,
11173
11271
  tailscale_ip: input.tailscale_ip,
@@ -11341,7 +11439,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
11341
11439
  message: `${project.name} has ${distinctPaths.length} different machine-local paths`
11342
11440
  });
11343
11441
  }
11344
- if (localRow && !existsSync4(localRow.path)) {
11442
+ if (localRow && !existsSync5(localRow.path)) {
11345
11443
  pathIssues.push({
11346
11444
  type: "path_missing",
11347
11445
  project_id: project.id,
@@ -11352,7 +11450,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
11352
11450
  message: `Local path does not exist on this machine: ${localRow.path}`
11353
11451
  });
11354
11452
  }
11355
- if (!localRow && project.path && machineById.has(localMachine.id) && !existsSync4(project.path)) {
11453
+ if (!localRow && project.path && machineById.has(localMachine.id) && !existsSync5(project.path)) {
11356
11454
  pathIssues.push({
11357
11455
  type: "path_missing",
11358
11456
  project_id: project.id,
@@ -11729,18 +11827,18 @@ __export(exports_database, {
11729
11827
  LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
11730
11828
  });
11731
11829
  import { Database } from "bun:sqlite";
11732
- import { existsSync as existsSync5, mkdirSync as mkdirSync2 } from "fs";
11733
- import { dirname as dirname2, join as join4, resolve as resolve2 } from "path";
11830
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2 } from "fs";
11831
+ import { dirname as dirname2, join as join5, resolve as resolve3 } from "path";
11734
11832
  function isInMemoryDb(path) {
11735
11833
  return path === ":memory:" || path.startsWith("file::memory:");
11736
11834
  }
11737
11835
  function findNearestProjectDb(startDir) {
11738
11836
  const gitRoot = findGitRoot(startDir);
11739
- const stopAt = gitRoot ? resolve2(gitRoot) : resolve2(startDir);
11740
- let dir = resolve2(startDir);
11837
+ const stopAt = gitRoot ? resolve3(gitRoot) : resolve3(startDir);
11838
+ let dir = resolve3(startDir);
11741
11839
  while (true) {
11742
- const candidate = join4(dir, ".hasna", "todos", "todos.db");
11743
- if (existsSync5(candidate))
11840
+ const candidate = join5(dir, ".hasna", "todos", "todos.db");
11841
+ if (existsSync6(candidate))
11744
11842
  return candidate;
11745
11843
  if (dir === stopAt)
11746
11844
  break;
@@ -11752,9 +11850,9 @@ function findNearestProjectDb(startDir) {
11752
11850
  return null;
11753
11851
  }
11754
11852
  function findGitRoot(startDir) {
11755
- let dir = resolve2(startDir);
11853
+ let dir = resolve3(startDir);
11756
11854
  while (true) {
11757
- if (existsSync5(join4(dir, ".git")))
11855
+ if (existsSync6(join5(dir, ".git")))
11758
11856
  return dir;
11759
11857
  const parent = dirname2(dir);
11760
11858
  if (parent === dir)
@@ -11764,7 +11862,7 @@ function findGitRoot(startDir) {
11764
11862
  return null;
11765
11863
  }
11766
11864
  function getGlobalDbPath() {
11767
- return join4(getHomeDir(), ".hasna", "todos", "todos.db");
11865
+ return join5(getTodosGlobalDir(), "todos.db");
11768
11866
  }
11769
11867
  function hasExplicitProjectArg(args = process.argv.slice(2)) {
11770
11868
  return args.some((arg) => arg === "--project" || arg.startsWith("--project="));
@@ -11802,7 +11900,7 @@ function getDbPath() {
11802
11900
  if (process.env["TODOS_DB_SCOPE"] === "project") {
11803
11901
  const gitRoot = findGitRoot(cwd);
11804
11902
  if (gitRoot && canCreateScopedProjectDb()) {
11805
- return join4(gitRoot, ".hasna", "todos", "todos.db");
11903
+ return join5(gitRoot, ".hasna", "todos", "todos.db");
11806
11904
  }
11807
11905
  }
11808
11906
  return getGlobalDbPath();
@@ -11813,8 +11911,8 @@ function getDatabasePath() {
11813
11911
  function ensureDir2(filePath) {
11814
11912
  if (isInMemoryDb(filePath))
11815
11913
  return;
11816
- const dir = dirname2(resolve2(filePath));
11817
- if (!existsSync5(dir)) {
11914
+ const dir = dirname2(resolve3(filePath));
11915
+ if (!existsSync6(dir)) {
11818
11916
  mkdirSync2(dir, { recursive: true });
11819
11917
  }
11820
11918
  }
@@ -12653,14 +12751,14 @@ var init_completion_guard = __esm(() => {
12653
12751
 
12654
12752
  // src/lib/event-emission-safety.ts
12655
12753
  import { tmpdir } from "os";
12656
- import { resolve as resolve3, sep } from "path";
12754
+ import { resolve as resolve4, sep } from "path";
12657
12755
  function envFlag(name) {
12658
12756
  const value = process.env[name]?.trim().toLowerCase();
12659
12757
  return value === "1" || value === "true" || value === "yes" || value === "on";
12660
12758
  }
12661
12759
  function isUnder(parent, child) {
12662
- const normalizedParent = resolve3(parent);
12663
- const normalizedChild = resolve3(child);
12760
+ const normalizedParent = resolve4(parent);
12761
+ const normalizedChild = resolve4(child);
12664
12762
  return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}${sep}`);
12665
12763
  }
12666
12764
  function databasePathFromDatabase(db) {
@@ -12703,9 +12801,9 @@ var init_event_emission_safety = __esm(() => {
12703
12801
  });
12704
12802
 
12705
12803
  // src/lib/workspace-trust.ts
12706
- import { relative, resolve as resolve4 } from "path";
12804
+ import { relative, resolve as resolve5 } from "path";
12707
12805
  function normalizePath(path) {
12708
- return resolve4(path);
12806
+ return resolve5(path);
12709
12807
  }
12710
12808
  function unique2(values) {
12711
12809
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
@@ -12887,9 +12985,9 @@ var init_workspace_trust = __esm(() => {
12887
12985
  });
12888
12986
 
12889
12987
  // src/lib/runner-sandbox.ts
12890
- import { relative as relative2, resolve as resolve5 } from "path";
12988
+ import { relative as relative2, resolve as resolve6 } from "path";
12891
12989
  function normalizePath2(path) {
12892
- return resolve5(path);
12990
+ return resolve6(path);
12893
12991
  }
12894
12992
  function unique3(values) {
12895
12993
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
@@ -13079,7 +13177,7 @@ var init_runner_sandbox = __esm(() => {
13079
13177
  // src/lib/event-hooks.ts
13080
13178
  import { createHash as createHash5, randomUUID as randomUUID2 } from "crypto";
13081
13179
  import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
13082
- import { dirname as dirname3, resolve as resolve6 } from "path";
13180
+ import { dirname as dirname3, resolve as resolve7 } from "path";
13083
13181
  import { createConnection } from "net";
13084
13182
  function safeName(name) {
13085
13183
  const trimmed = name.trim();
@@ -13217,7 +13315,7 @@ async function deliverHook(hook, envelope) {
13217
13315
  if (hook.target === "stdout") {
13218
13316
  output = line.trim();
13219
13317
  } else if (hook.target === "file") {
13220
- const filePath = resolve6(hook.file_path);
13318
+ const filePath = resolve7(hook.file_path);
13221
13319
  mkdirSync3(dirname3(filePath), { recursive: true });
13222
13320
  appendFileSync(filePath, line);
13223
13321
  } else if (hook.target === "socket") {
@@ -13338,9 +13436,9 @@ var init_event_hooks = __esm(() => {
13338
13436
  // node_modules/.bun/@hasna+events@0.1.16/node_modules/@hasna/events/dist/index.js
13339
13437
  import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
13340
13438
  import { Buffer as Buffer2 } from "buffer";
13341
- import { existsSync as existsSync6 } from "fs";
13342
- import { homedir as homedir2 } from "os";
13343
- import { join as join5 } from "path";
13439
+ import { existsSync as existsSync7 } from "fs";
13440
+ import { homedir as homedir4 } from "os";
13441
+ import { join as join6 } from "path";
13344
13442
  import { createHmac as createHmac2, timingSafeEqual as timingSafeEqual2 } from "crypto";
13345
13443
  import { randomUUID as randomUUID3 } from "crypto";
13346
13444
  import { spawn } from "child_process";
@@ -13441,7 +13539,7 @@ function channelMatchesEvent(channel, event) {
13441
13539
  return channel.filters.some((filter) => eventMatchesFilter(event, filter));
13442
13540
  }
13443
13541
  function getEventsDataDir(override) {
13444
- return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join5(homedir2(), ".hasna", "events");
13542
+ return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join6(homedir4(), ".hasna", "events");
13445
13543
  }
13446
13544
 
13447
13545
  class JsonEventsStore {
@@ -13450,12 +13548,12 @@ class JsonEventsStore {
13450
13548
  channelsPath;
13451
13549
  eventsPath;
13452
13550
  deliveriesPath;
13453
- constructor(dataDir = getEventsDataDir()) {
13454
- this.dataDir = dataDir;
13455
- this.runtime = localJsonRuntime(dataDir);
13456
- this.channelsPath = join5(dataDir, "channels.json");
13457
- this.eventsPath = join5(dataDir, "events.json");
13458
- this.deliveriesPath = join5(dataDir, "deliveries.json");
13551
+ constructor(dataDir2 = getEventsDataDir()) {
13552
+ this.dataDir = dataDir2;
13553
+ this.runtime = localJsonRuntime(dataDir2);
13554
+ this.channelsPath = join6(dataDir2, "channels.json");
13555
+ this.eventsPath = join6(dataDir2, "events.json");
13556
+ this.deliveriesPath = join6(dataDir2, "deliveries.json");
13459
13557
  }
13460
13558
  async init() {
13461
13559
  await mkdir(this.dataDir, { recursive: true, mode: 448 });
@@ -13572,7 +13670,7 @@ class JsonEventsStore {
13572
13670
  };
13573
13671
  }
13574
13672
  async ensureArrayFile(path) {
13575
- if (!existsSync6(path)) {
13673
+ if (!existsSync7(path)) {
13576
13674
  await writeFile(path, `[]
13577
13675
  `, { encoding: "utf-8", mode: 384 });
13578
13676
  }
@@ -13602,7 +13700,7 @@ class JsonEventsStore {
13602
13700
  });
13603
13701
  }
13604
13702
  }
13605
- function localJsonRuntime(dataDir = getEventsDataDir()) {
13703
+ function localJsonRuntime(dataDir2 = getEventsDataDir()) {
13606
13704
  return {
13607
13705
  mode: "local-files",
13608
13706
  name: "json-events-store",
@@ -13615,7 +13713,7 @@ function localJsonRuntime(dataDir = getEventsDataDir()) {
13615
13713
  durable: true,
13616
13714
  idempotency: "best-effort-local",
13617
13715
  replayCursors: true,
13618
- description: `Local JSON files in ${dataDir}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
13716
+ description: `Local JSON files in ${dataDir2}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
13619
13717
  };
13620
13718
  }
13621
13719
  function encodeLocalJsonEventCursor(offset, options = {}) {
@@ -13794,7 +13892,7 @@ async function dispatchCommand(event, channel) {
13794
13892
  HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
13795
13893
  HASNA_EVENT_JSON: eventJson
13796
13894
  };
13797
- return new Promise((resolve7) => {
13895
+ return new Promise((resolve8) => {
13798
13896
  const child = spawn(channel.command.command, channel.command.args ?? [], {
13799
13897
  cwd: channel.command.cwd,
13800
13898
  env,
@@ -13812,7 +13910,7 @@ async function dispatchCommand(event, channel) {
13812
13910
  });
13813
13911
  child.on("error", (error) => {
13814
13912
  clearTimeout(timeout);
13815
- resolve7({
13913
+ resolve8({
13816
13914
  attempt: 1,
13817
13915
  status: "failed",
13818
13916
  startedAt,
@@ -13825,7 +13923,7 @@ async function dispatchCommand(event, channel) {
13825
13923
  child.on("close", (code, signal) => {
13826
13924
  clearTimeout(timeout);
13827
13925
  const success = code === 0;
13828
- resolve7({
13926
+ resolve8({
13829
13927
  attempt: 1,
13830
13928
  status: success ? "success" : "failed",
13831
13929
  startedAt,
@@ -14167,7 +14265,7 @@ function normalizeRetryPolicy(policy) {
14167
14265
  };
14168
14266
  }
14169
14267
  var HASNA_EVENTS_DIR_ENV = "HASNA_EVENTS_DIR", HASNA_EVENTS_HOME_ENV = "HASNA_EVENTS_HOME", LOCAL_JSON_EVENT_CURSOR_PREFIX = "local-json-v1:", DEFAULT_EVENT_PAGE_LIMIT = 100, MAX_EVENT_PAGE_LIMIT = 1000, DEFAULT_SIGNATURE_TOLERANCE_MS, EventValidationError, defaultEventTypeCatalog, APP_EVENT_V1_MAX_DATA_BYTES;
14170
- var init_dist = __esm(() => {
14268
+ var init_dist2 = __esm(() => {
14171
14269
  DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
14172
14270
  EventValidationError = class EventValidationError extends Error {
14173
14271
  eventType;
@@ -14587,7 +14685,7 @@ function emitSharedTaskEventQuiet(input) {
14587
14685
  }
14588
14686
  var SOURCE = "todos";
14589
14687
  var init_shared_events = __esm(() => {
14590
- init_dist();
14688
+ init_dist2();
14591
14689
  init_database();
14592
14690
  init_projects();
14593
14691
  init_task_lists();
@@ -16449,17 +16547,17 @@ function sanitizeCreateTaskInput(input) {
16449
16547
  return {
16450
16548
  ...input,
16451
16549
  title: sanitizePreWriteText(input.title, "task.title"),
16452
- description: input.description !== undefined ? sanitizePreWriteText(input.description, "task.description") : undefined,
16550
+ description: input.description == null ? input.description : sanitizePreWriteText(input.description, "task.description"),
16453
16551
  tags: input.tags !== undefined ? sanitizePreWriteValue(input.tags, "task.tags") : undefined,
16454
16552
  metadata: input.metadata !== undefined ? sanitizePreWriteValue(input.metadata, "task.metadata") : undefined,
16455
- reason: input.reason !== undefined ? sanitizePreWriteText(input.reason, "task.reason") : undefined
16553
+ reason: input.reason == null ? input.reason : sanitizePreWriteText(input.reason, "task.reason")
16456
16554
  };
16457
16555
  }
16458
16556
  function sanitizeUpdateTaskInput(input) {
16459
16557
  return {
16460
16558
  ...input,
16461
16559
  title: input.title !== undefined ? sanitizePreWriteText(input.title, "task.title") : undefined,
16462
- description: input.description !== undefined ? sanitizePreWriteText(input.description, "task.description") : undefined,
16560
+ description: input.description == null ? input.description : sanitizePreWriteText(input.description, "task.description"),
16463
16561
  tags: input.tags !== undefined ? sanitizePreWriteValue(input.tags, "task.tags") : undefined,
16464
16562
  metadata: input.metadata !== undefined ? sanitizePreWriteValue(input.metadata, "task.metadata") : undefined
16465
16563
  };
@@ -18456,28 +18554,28 @@ var init_boards = __esm(() => {
18456
18554
 
18457
18555
  // src/lib/artifact-store.ts
18458
18556
  import { createHash as createHash6 } from "crypto";
18459
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync3, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
18460
- import { basename, dirname as dirname4, join as join6, resolve as resolve7 } from "path";
18557
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync3, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
18558
+ import { basename, dirname as dirname4, join as join7, resolve as resolve8 } from "path";
18461
18559
  import { tmpdir as tmpdir2 } from "os";
18462
18560
  function isInMemoryDb2(path) {
18463
18561
  return path === ":memory:" || path.startsWith("file::memory:");
18464
18562
  }
18465
18563
  function artifactStoreRoot() {
18466
18564
  if (process.env["HASNA_TODOS_ARTIFACTS_DIR"])
18467
- return resolve7(process.env["HASNA_TODOS_ARTIFACTS_DIR"]);
18565
+ return resolve8(process.env["HASNA_TODOS_ARTIFACTS_DIR"]);
18468
18566
  if (process.env["TODOS_ARTIFACTS_DIR"])
18469
- return resolve7(process.env["TODOS_ARTIFACTS_DIR"]);
18567
+ return resolve8(process.env["TODOS_ARTIFACTS_DIR"]);
18470
18568
  const dbPath = getDatabasePath();
18471
18569
  if (isInMemoryDb2(dbPath))
18472
- return join6(tmpdir2(), "hasna-todos-artifacts");
18473
- return join6(dirname4(resolve7(dbPath)), "artifacts");
18570
+ return join7(tmpdir2(), "hasna-todos-artifacts");
18571
+ return join7(dirname4(resolve8(dbPath)), "artifacts");
18474
18572
  }
18475
18573
  function artifactStorePath(relativePath) {
18476
18574
  const normalized = relativePath.replace(/\\/g, "/");
18477
18575
  if (normalized.includes("..") || normalized.startsWith("/") || normalized.length === 0) {
18478
18576
  throw new Error("Invalid artifact store path");
18479
18577
  }
18480
- return join6(artifactStoreRoot(), normalized);
18578
+ return join7(artifactStoreRoot(), normalized);
18481
18579
  }
18482
18580
  function sha2562(buffer) {
18483
18581
  return createHash6("sha256").update(buffer).digest("hex");
@@ -18517,8 +18615,8 @@ function mediaTypeFor(path, textLike) {
18517
18615
  return "application/octet-stream";
18518
18616
  }
18519
18617
  function storeArtifactContent(input) {
18520
- const sourcePath = resolve7(input.path);
18521
- if (!existsSync7(sourcePath))
18618
+ const sourcePath = resolve8(input.path);
18619
+ if (!existsSync8(sourcePath))
18522
18620
  return null;
18523
18621
  const sourceStat = statSync2(sourcePath);
18524
18622
  if (!sourceStat.isFile())
@@ -18535,9 +18633,9 @@ function storeArtifactContent(input) {
18535
18633
  redactionStatus = "redacted";
18536
18634
  }
18537
18635
  const storedSha = sha2562(storedBuffer);
18538
- const relativePath = join6("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
18636
+ const relativePath = join7("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
18539
18637
  const destination = artifactStorePath(relativePath);
18540
- if (!existsSync7(destination)) {
18638
+ if (!existsSync8(destination)) {
18541
18639
  mkdirSync4(dirname4(destination), { recursive: true });
18542
18640
  writeFileSync2(destination, storedBuffer);
18543
18641
  }
@@ -18597,7 +18695,7 @@ function verifyStoredArtifact(input) {
18597
18695
  };
18598
18696
  }
18599
18697
  const storedPath = artifactStorePath(store.relative_path);
18600
- if (!existsSync7(storedPath)) {
18698
+ if (!existsSync8(storedPath)) {
18601
18699
  return {
18602
18700
  id: input.id,
18603
18701
  path: input.path,
@@ -31161,8 +31259,8 @@ var exports_doctor = {};
31161
31259
  __export(exports_doctor, {
31162
31260
  runTodosDoctor: () => runTodosDoctor
31163
31261
  });
31164
- import { chmodSync, copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync5, statSync as statSync3 } from "fs";
31165
- import { basename as basename2, dirname as dirname5, join as join7 } from "path";
31262
+ import { chmodSync, copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync5, statSync as statSync3 } from "fs";
31263
+ import { basename as basename2, dirname as dirname5, join as join8 } from "path";
31166
31264
  function tableExists2(db, table) {
31167
31265
  return Boolean(db.query("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(table));
31168
31266
  }
@@ -31256,7 +31354,7 @@ function findMissingProjectRoots(db) {
31256
31354
  continue;
31257
31355
  if (!row.path.startsWith("/"))
31258
31356
  continue;
31259
- if (!existsSync8(row.path))
31357
+ if (!existsSync9(row.path))
31260
31358
  missing++;
31261
31359
  }
31262
31360
  return missing;
@@ -31316,16 +31414,16 @@ function databasePermissionsAreUnsafe(dbPath) {
31316
31414
  function createBackup(dbPath) {
31317
31415
  if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
31318
31416
  return;
31319
- if (!existsSync8(dbPath))
31417
+ if (!existsSync9(dbPath))
31320
31418
  return;
31321
31419
  const stamp = now().replace(/[:.]/g, "-");
31322
- const backupDir = join7(dirname5(dbPath), `${basename2(dbPath)}.backup-${stamp}`);
31420
+ const backupDir = join8(dirname5(dbPath), `${basename2(dbPath)}.backup-${stamp}`);
31323
31421
  const files = [];
31324
31422
  mkdirSync5(backupDir, { recursive: true });
31325
31423
  for (const source of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
31326
- if (!existsSync8(source))
31424
+ if (!existsSync9(source))
31327
31425
  continue;
31328
- const target = join7(backupDir, basename2(source));
31426
+ const target = join8(backupDir, basename2(source));
31329
31427
  copyFileSync(source, target);
31330
31428
  files.push(target);
31331
31429
  }
@@ -31584,7 +31682,7 @@ var init_doctor = __esm(() => {
31584
31682
  });
31585
31683
 
31586
31684
  // src/server/routes.ts
31587
- import { join as join8, resolve as resolve8, sep as sep2 } from "path";
31685
+ import { join as join9, resolve as resolve9, sep as sep2 } from "path";
31588
31686
  function parseFieldsParam(url) {
31589
31687
  const fieldsParam = url.searchParams.get("fields");
31590
31688
  return fieldsParam ? fieldsParam.split(",").map((f) => f.trim()).filter(Boolean) : undefined;
@@ -32421,9 +32519,9 @@ function handleStaticFiles(path, method, ctx, json5, serveStaticFile2) {
32421
32519
  if (!ctx.dashboardExists || method !== "GET" && method !== "HEAD")
32422
32520
  return null;
32423
32521
  if (path !== "/") {
32424
- const filePath = join8(ctx.dashboardDir, path);
32425
- const resolvedFile = resolve8(filePath);
32426
- const resolvedBase = resolve8(ctx.dashboardDir);
32522
+ const filePath = join9(ctx.dashboardDir, path);
32523
+ const resolvedFile = resolve9(filePath);
32524
+ const resolvedBase = resolve9(ctx.dashboardDir);
32427
32525
  if (!resolvedFile.startsWith(resolvedBase + sep2) && resolvedFile !== resolvedBase) {
32428
32526
  return json5({ error: "Forbidden" }, 403);
32429
32527
  }
@@ -32431,7 +32529,7 @@ function handleStaticFiles(path, method, ctx, json5, serveStaticFile2) {
32431
32529
  if (res2)
32432
32530
  return res2;
32433
32531
  }
32434
- const indexPath = join8(ctx.dashboardDir, "index.html");
32532
+ const indexPath = join9(ctx.dashboardDir, "index.html");
32435
32533
  const res = serveStaticFile2(indexPath);
32436
32534
  if (res)
32437
32535
  return res;
@@ -32538,7 +32636,7 @@ class TodosShadowOutbox {
32538
32636
  const remaining = deadline - Date.now();
32539
32637
  if (remaining <= 0)
32540
32638
  break;
32541
- await new Promise((resolve9) => setTimeout(resolve9, Math.min(200, remaining)));
32639
+ await new Promise((resolve10) => setTimeout(resolve10, Math.min(200, remaining)));
32542
32640
  }
32543
32641
  }
32544
32642
  return this.getStats();
@@ -44573,9 +44671,9 @@ data:
44573
44671
  const initRequest = messages.find((m) => isInitializeRequest(m));
44574
44672
  const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
44575
44673
  if (this._enableJsonResponse) {
44576
- return new Promise((resolve9) => {
44674
+ return new Promise((resolve10) => {
44577
44675
  this._streamMapping.set(streamId, {
44578
- resolveJson: resolve9,
44676
+ resolveJson: resolve10,
44579
44677
  cleanup: () => {
44580
44678
  this._streamMapping.delete(streamId);
44581
44679
  }
@@ -47002,7 +47100,7 @@ class Protocol {
47002
47100
  return;
47003
47101
  }
47004
47102
  const pollInterval = task3.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
47005
- await new Promise((resolve9) => setTimeout(resolve9, pollInterval));
47103
+ await new Promise((resolve10) => setTimeout(resolve10, pollInterval));
47006
47104
  options?.signal?.throwIfAborted();
47007
47105
  }
47008
47106
  } catch (error3) {
@@ -47014,7 +47112,7 @@ class Protocol {
47014
47112
  }
47015
47113
  request(request, resultSchema, options) {
47016
47114
  const { relatedRequestId, resumptionToken, onresumptiontoken, task: task2, relatedTask } = options ?? {};
47017
- return new Promise((resolve9, reject) => {
47115
+ return new Promise((resolve10, reject) => {
47018
47116
  const earlyReject = (error3) => {
47019
47117
  reject(error3);
47020
47118
  };
@@ -47092,7 +47190,7 @@ class Protocol {
47092
47190
  if (!parseResult.success) {
47093
47191
  reject(parseResult.error);
47094
47192
  } else {
47095
- resolve9(parseResult.data);
47193
+ resolve10(parseResult.data);
47096
47194
  }
47097
47195
  } catch (error3) {
47098
47196
  reject(error3);
@@ -47283,12 +47381,12 @@ class Protocol {
47283
47381
  interval = task2.pollInterval;
47284
47382
  }
47285
47383
  } catch {}
47286
- return new Promise((resolve9, reject) => {
47384
+ return new Promise((resolve10, reject) => {
47287
47385
  if (signal.aborted) {
47288
47386
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
47289
47387
  return;
47290
47388
  }
47291
- const timeoutId = setTimeout(resolve9, interval);
47389
+ const timeoutId = setTimeout(resolve10, interval);
47292
47390
  signal.addEventListener("abort", () => {
47293
47391
  clearTimeout(timeoutId);
47294
47392
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -50273,7 +50371,7 @@ var require_compile = __commonJS((exports) => {
50273
50371
  const schOrFunc = root.refs[ref];
50274
50372
  if (schOrFunc)
50275
50373
  return schOrFunc;
50276
- let _sch = resolve9.call(this, root, ref);
50374
+ let _sch = resolve10.call(this, root, ref);
50277
50375
  if (_sch === undefined) {
50278
50376
  const schema2 = (_a = root.localRefs) === null || _a === undefined ? undefined : _a[ref];
50279
50377
  const { schemaId } = this.opts;
@@ -50300,7 +50398,7 @@ var require_compile = __commonJS((exports) => {
50300
50398
  function sameSchemaEnv(s1, s2) {
50301
50399
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
50302
50400
  }
50303
- function resolve9(root, ref) {
50401
+ function resolve10(root, ref) {
50304
50402
  let sch;
50305
50403
  while (typeof (sch = this.refs[ref]) == "string")
50306
50404
  ref = sch;
@@ -50886,7 +50984,7 @@ var require_fast_uri = __commonJS((exports, module) => {
50886
50984
  }
50887
50985
  return uri;
50888
50986
  }
50889
- function resolve9(baseURI, relativeURI, options) {
50987
+ function resolve10(baseURI, relativeURI, options) {
50890
50988
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
50891
50989
  const resolved = resolveComponent(parse6(baseURI, schemelessOptions), parse6(relativeURI, schemelessOptions), schemelessOptions, true);
50892
50990
  schemelessOptions.skipEscape = true;
@@ -51145,7 +51243,7 @@ var require_fast_uri = __commonJS((exports, module) => {
51145
51243
  var fastUri = {
51146
51244
  SCHEMES,
51147
51245
  normalize: normalize2,
51148
- resolve: resolve9,
51246
+ resolve: resolve10,
51149
51247
  resolveComponent,
51150
51248
  equal,
51151
51249
  serialize,
@@ -54716,7 +54814,7 @@ class McpServer {
54716
54814
  let task2 = createTaskResult.task;
54717
54815
  const pollInterval = task2.pollInterval ?? 5000;
54718
54816
  while (task2.status !== "completed" && task2.status !== "failed" && task2.status !== "cancelled") {
54719
- await new Promise((resolve9) => setTimeout(resolve9, pollInterval));
54817
+ await new Promise((resolve10) => setTimeout(resolve10, pollInterval));
54720
54818
  const updatedTask = await extra.taskStore.getTask(taskId);
54721
54819
  if (!updatedTask) {
54722
54820
  throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -55361,12 +55459,12 @@ class StdioServerTransport {
55361
55459
  this.onclose?.();
55362
55460
  }
55363
55461
  send(message) {
55364
- return new Promise((resolve9) => {
55462
+ return new Promise((resolve10) => {
55365
55463
  const json7 = serializeMessage(message);
55366
55464
  if (this._stdout.write(json7)) {
55367
- resolve9();
55465
+ resolve10();
55368
55466
  } else {
55369
- this._stdout.once("drain", resolve9);
55467
+ this._stdout.once("drain", resolve10);
55370
55468
  }
55371
55469
  });
55372
55470
  }
@@ -56515,10 +56613,10 @@ var init_token_utils = __esm(() => {
56515
56613
 
56516
56614
  // src/lib/assignee-validation.ts
56517
56615
  import { readFileSync as readFileSync4 } from "fs";
56518
- import { homedir as homedir3 } from "os";
56519
- import { join as join9 } from "path";
56616
+ import { homedir as homedir5 } from "os";
56617
+ import { join as join10 } from "path";
56520
56618
  function defaultSeatRosterPath() {
56521
- return process.env["TODOS_SEAT_ROSTER_PATH"] || join9(homedir3(), ".hasna", "identities", "hasna-seats.roster.json");
56619
+ return process.env["TODOS_SEAT_ROSTER_PATH"] || join10(homedir5(), ".hasna", "identities", "hasna-seats.roster.json");
56522
56620
  }
56523
56621
  function loadSeatSlugs(path = defaultSeatRosterPath()) {
56524
56622
  try {
@@ -56608,10 +56706,11 @@ var init_assignee_context = __esm(() => {
56608
56706
  init_assignee_validation();
56609
56707
  });
56610
56708
 
56611
- // node_modules/.bun/@hasna+contracts@0.14.0+619f74e7b30eeaf4/node_modules/@hasna/contracts/dist/client/storage.js
56709
+ // node_modules/.bun/@hasna+contracts@0.14.2+a5fb9613d5af3331/node_modules/@hasna/contracts/dist/client/storage.js
56612
56710
  import { isIP } from "net";
56613
56711
  import { readFileSync as readFileSync5, statSync as statSync4 } from "fs";
56614
- import { join as join10 } from "path";
56712
+ import { createRequire } from "module";
56713
+ import { join as join11 } from "path";
56615
56714
  function envToken(name) {
56616
56715
  return name.toUpperCase().replace(/-/g, "_");
56617
56716
  }
@@ -56625,24 +56724,48 @@ function clientTransportEnvKeys(name) {
56625
56724
  function credentialOverrideEnvKey(name) {
56626
56725
  return `HASNA_${envToken(name)}_API_KEY_OVERRIDE`;
56627
56726
  }
56727
+ function credentialPointerEnvKey(name) {
56728
+ return `HASNA_${envToken(name)}_API_KEY_REF`;
56729
+ }
56628
56730
  function homeDir(env) {
56629
56731
  const home = env.HOME?.trim();
56630
56732
  return home ? home : null;
56631
56733
  }
56632
- function credentialDiskSources(name, env) {
56633
- return profileDiskSources(name, env, null);
56634
- }
56635
- function profileDiskSources(name, env, profile) {
56734
+ function credentialDiskSourceList(name, env, profile = null) {
56636
56735
  const home = homeDir(env);
56637
56736
  if (!home || !SAFE_APP_SLUG.test(name))
56638
56737
  return [];
56639
56738
  const stem = profile ? `${name}.${profile}` : name;
56640
56739
  const configStem = profile ? `${name}-${profile}` : name;
56641
56740
  return [
56642
- join10(home, HASNA_STATE_DIR, FLEET_CREDENTIAL_DIR, `${stem}.env`),
56643
- join10(home, CONFIG_DIR, CONFIG_NAMESPACE, `${configStem}-cloud.env`)
56741
+ {
56742
+ path: join11(home, HASNA_STATE_DIR, FLEET_CREDENTIAL_DIR, `${stem}.env`),
56743
+ tier: "fleet-env",
56744
+ deprecated: false
56745
+ },
56746
+ {
56747
+ path: join11(home, HASNA_STATE_DIR, LEGACY_CLOUD_DIR, `${stem}.env`),
56748
+ tier: "legacy-cloud",
56749
+ deprecated: true
56750
+ },
56751
+ {
56752
+ path: join11(home, CONFIG_DIR, CONFIG_NAMESPACE, `${configStem}.env`),
56753
+ tier: "config",
56754
+ deprecated: false
56755
+ },
56756
+ {
56757
+ path: join11(home, CONFIG_DIR, CONFIG_NAMESPACE, `${configStem}-cloud.env`),
56758
+ tier: "config-legacy",
56759
+ deprecated: true
56760
+ }
56644
56761
  ];
56645
56762
  }
56763
+ function credentialDiskSources(name, env) {
56764
+ return credentialDiskSourceList(name, env, null).map((s) => s.path);
56765
+ }
56766
+ function profileDiskSources(name, env, profile) {
56767
+ return credentialDiskSourceList(name, env, profile).map((s) => s.path);
56768
+ }
56646
56769
  function parseEnvFile(text) {
56647
56770
  const values = new Map;
56648
56771
  for (const rawLine of text.split(/\r?\n/)) {
@@ -56709,6 +56832,9 @@ function appConfigDiskValue(name, env, keys) {
56709
56832
  return null;
56710
56833
  }
56711
56834
  function assertUsableCredential(appName, source, value) {
56835
+ if (VAULT_POINTER_SHAPE.test(value)) {
56836
+ throw new CredentialResolutionError(appName, `The credential from ${source} looks like a secrets-vault pointer (a path-shaped reference like ` + `'namespace/app/live/api_key'). A vault path is NEVER accepted as a literal API key. ` + `Use ${credentialPointerEnvKey(appName)} to resolve the key through the vault, or provide the actual key value.`, [source]);
56837
+ }
56712
56838
  if (!ILLEGAL_IN_HEADER_VALUE.test(value))
56713
56839
  return;
56714
56840
  throw new CredentialResolutionError(appName, `The credential from ${source} contains characters that cannot be sent in an HTTP header ` + `(a control character or non-ASCII byte). A file written with CR-only line endings is the usual ` + `cause. Rewrite that credential file with one LF-terminated KEY=value line. ` + `The value is not shown here, and is deliberately never logged.`, [source]);
@@ -56730,6 +56856,14 @@ function sealCredential(fields) {
56730
56856
  writable: false,
56731
56857
  configurable: false
56732
56858
  });
56859
+ if (fields.pointerVaultKey !== undefined) {
56860
+ Object.defineProperty(sealed, "pointerVaultKey", {
56861
+ value: fields.pointerVaultKey,
56862
+ enumerable: false,
56863
+ writable: false,
56864
+ configurable: false
56865
+ });
56866
+ }
56733
56867
  Object.defineProperty(sealed, INSPECT_CUSTOM, {
56734
56868
  value: () => ({ ...visible, apiKey: "[redacted]" }),
56735
56869
  enumerable: false,
@@ -56781,7 +56915,8 @@ function validateAndSealResolvedCredential(appName, credential) {
56781
56915
  deliberate: credential.deliberate,
56782
56916
  deprecated: credential.deprecated,
56783
56917
  diskCandidates: credential.diskCandidates,
56784
- warning: credential.warning
56918
+ warning: credential.warning,
56919
+ ...credential.pointerVaultKey !== undefined ? { pointerVaultKey: credential.pointerVaultKey } : {}
56785
56920
  });
56786
56921
  }
56787
56922
  function firstEnvValue(env, keys) {
@@ -56841,6 +56976,27 @@ function resolveCredential(name, env, options = {}) {
56841
56976
  warning: null
56842
56977
  });
56843
56978
  }
56979
+ const pointerKeyName = credentialPointerEnvKey(name);
56980
+ const pointerRaw = env[pointerKeyName];
56981
+ if (pointerRaw !== undefined) {
56982
+ const pointer = pointerRaw.trim();
56983
+ if (!pointer) {
56984
+ throw new CredentialResolutionError(name, `${pointerKeyName} is set but empty. It is a deliberate vault pointer, so it is not resolved around: ` + `either give it a vault item key or unset it to fall back to the credential on disk.`, [pointerKeyName]);
56985
+ }
56986
+ if (!VAULT_POINTER_SHAPE.test(pointer)) {
56987
+ throw new CredentialResolutionError(name, `${pointerKeyName} must name a vault ITEM KEY (a path-shaped reference like ` + `'namespace/app/live/api_key'), not a credential value. A pointer that carries a literal is refused.`, [pointerKeyName]);
56988
+ }
56989
+ return sealCredential({
56990
+ apiKey: "",
56991
+ pointerVaultKey: pointer,
56992
+ tier: "pointer",
56993
+ source: pointerKeyName,
56994
+ deliberate: true,
56995
+ deprecated: false,
56996
+ diskCandidates: diskPaths,
56997
+ warning: null
56998
+ });
56999
+ }
56844
57000
  const profile = options.profile?.trim() || env[CREDENTIAL_PROFILE_ENV_KEY]?.trim();
56845
57001
  if (profile) {
56846
57002
  const profileSource = options.profile?.trim() ? "explicit profile argument" : CREDENTIAL_PROFILE_ENV_KEY;
@@ -56865,26 +57021,42 @@ function resolveCredential(name, env, options = {}) {
56865
57021
  }
56866
57022
  throw new CredentialResolutionError(name, `Profile '${profile}' (from ${profileSource}) has no ${apiKeyKeys[0]} for '${name}'. ` + `Looked in: ${paths.join(", ") || "<no HOME in this environment>"}. ` + `A profile names WHICH identity to use, so it is never resolved around \u2014 ` + `create the profile's credential file or unset ${CREDENTIAL_PROFILE_ENV_KEY}.`, paths);
56867
57023
  }
56868
- const diskHits = diskPaths.map((path) => ({ path, value: readCredentialFile(path, apiKeyKeys) })).filter((hit) => hit.value !== null);
57024
+ const diskSourceList = credentialDiskSourceList(name, env, null);
57025
+ const diskHits = diskSourceList.map((src) => ({ src, value: readCredentialFile(src.path, apiKeyKeys) })).filter((hit) => hit.value !== null);
56869
57026
  if (diskHits.length > 0) {
56870
57027
  const winner = diskHits[0];
56871
- assertUsableCredential(name, winner.path, winner.value);
57028
+ assertUsableCredential(name, winner.src.path, winner.value);
56872
57029
  const divergentSources = [
56873
- ...diskHits.slice(1).filter((hit) => hit.value !== winner.value).map((hit) => hit.path),
57030
+ ...diskHits.slice(1).filter((hit) => hit.value !== winner.value).map((hit) => hit.src.path),
56874
57031
  ...(() => {
56875
57032
  const legacyHit = firstEnvValue(env, apiKeyKeys);
56876
57033
  return legacyHit && legacyHit.value !== winner.value ? [legacyHit.key] : [];
56877
57034
  })()
56878
57035
  ];
56879
- const warning = divergentSources.length > 0 ? `Credential sources disagree for '${name}': ${winner.path} and ` + `${divergentSources.join(", ")} hold different keys. ${winner.path} wins, because a file on ` + `disk is re-read on every call while an environment variable is a snapshot. Reconcile them \u2014 ` + `a rotation that updated only one leaves the other to fail 401 wherever it is loaded first.` : null;
57036
+ const warning = divergentSources.length > 0 ? `Credential sources disagree for '${name}': ${winner.src.path} and ` + `${divergentSources.join(", ")} hold different keys. ${winner.src.path} wins, because a file on ` + `disk is re-read on every call while an environment variable is a snapshot. Reconcile them \u2014 ` + `a rotation that updated only one leaves the other to fail 401 wherever it is loaded first.` : null;
57037
+ let deprecated = winner.src.deprecated;
57038
+ let finalWarning = warning;
57039
+ if (winner.src.deprecated) {
57040
+ deprecated = true;
57041
+ const sink = options.onDeprecation ?? defaultDeprecationSink;
57042
+ const notified = deprecationNotified();
57043
+ const noticeKey = `${name}:${winner.src.path}`;
57044
+ if (!notified.has(noticeKey)) {
57045
+ notified.add(noticeKey);
57046
+ const target = diskSourceList[0]?.path ?? "<none>";
57047
+ const message = `[${name}] DEPRECATED: the API key came from ${winner.src.path} \u2014 a legacy credential location. ` + `The primary location is ${target} (~/.hasna/fleet-env/<app>.env). The legacy 'cloud' tiers are ` + `removed after ${LEGACY_CLOUD_REMOVAL_DEADLINE}. Migrate the key to the primary location.`;
57048
+ sink(message);
57049
+ }
57050
+ finalWarning = [warning, `Legacy credential source: ${winner.src.path}. Removed after ${LEGACY_CLOUD_REMOVAL_DEADLINE}.`].filter(Boolean).join(" ") || null;
57051
+ }
56880
57052
  return sealCredential({
56881
57053
  apiKey: winner.value,
56882
- tier: "disk",
56883
- source: winner.path,
57054
+ tier: winner.src.tier,
57055
+ source: winner.src.path,
56884
57056
  deliberate: false,
56885
- deprecated: false,
57057
+ deprecated,
56886
57058
  diskCandidates: diskPaths,
56887
- warning
57059
+ warning: finalWarning
56888
57060
  });
56889
57061
  }
56890
57062
  const legacy = firstEnvValue(env, apiKeyKeys);
@@ -56910,6 +57082,45 @@ function resolveCredential(name, env, options = {}) {
56910
57082
  }
56911
57083
  return null;
56912
57084
  }
57085
+ async function completePointerCredential(name, pointerResolution, env = process.env) {
57086
+ const vaultKey = pointerResolution.pointerVaultKey;
57087
+ const pointerEnvKey = pointerResolution.source;
57088
+ if (!vaultKey) {
57089
+ throw new CredentialResolutionError(name, `Pointer resolution from ${pointerEnvKey} carries no vault item key; this is a defect in the resolver.`, [pointerEnvKey]);
57090
+ }
57091
+ let secretsSdk;
57092
+ try {
57093
+ secretsSdk = requireSecretsSdk(SECRETS_PACKAGE_SPECIFIER);
57094
+ } catch {
57095
+ throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets SDK (@hasna/secrets) is not installed ` + `in this process. A vault pointer is TERMINAL: install @hasna/secrets to resolve it, or unset ${pointerEnvKey}.`, [pointerEnvKey]);
57096
+ }
57097
+ let client;
57098
+ try {
57099
+ client = secretsSdk.createSecretsClientFromEnv(env);
57100
+ } catch {
57101
+ throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets client could not be configured from this ` + `environment (the secrets service URL and key env are missing or invalid). A vault pointer is TERMINAL and ` + `never falls through to a literal or disk credential.`, [pointerEnvKey]);
57102
+ }
57103
+ let secret;
57104
+ try {
57105
+ secret = await client.getSecret({ key: vaultKey });
57106
+ } catch {
57107
+ throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the vault could not be reached or the item is ` + `unavailable. A vault pointer is TERMINAL and never falls through to a literal or disk credential.`, [pointerEnvKey]);
57108
+ }
57109
+ const value = secret.value;
57110
+ if (!value) {
57111
+ throw new CredentialResolutionError(name, `${pointerEnvKey} resolved vault item '${vaultKey}', but it holds no value. A vault pointer is TERMINAL.`, [pointerEnvKey]);
57112
+ }
57113
+ assertUsableCredential(name, `${pointerEnvKey} -> vault:${vaultKey}`, value);
57114
+ return sealCredential({
57115
+ apiKey: value,
57116
+ tier: "pointer",
57117
+ source: `${pointerEnvKey} -> vault:${vaultKey}`,
57118
+ deliberate: true,
57119
+ deprecated: false,
57120
+ diskCandidates: pointerResolution.diskCandidates,
57121
+ warning: null
57122
+ });
57123
+ }
56913
57124
  function isValidDnsDomain(value) {
56914
57125
  if (value.length === 0 || value.length > 253 || ASCII_CONTROL_PATTERN.test(value) || /[^\x00-\x7f]/.test(value)) {
56915
57126
  return false;
@@ -57133,6 +57344,13 @@ function currentCredential(name, apiKey) {
57133
57344
  }
57134
57345
  return explicitCredential(name, apiKey);
57135
57346
  }
57347
+ async function resolveRequestCredential(name, apiKey, env = process.env) {
57348
+ const resolved = currentCredential(name, apiKey);
57349
+ if (resolved.tier === "pointer") {
57350
+ return completePointerCredential(name, resolved, env);
57351
+ }
57352
+ return resolved;
57353
+ }
57136
57354
  function authFailureGuidance(credential) {
57137
57355
  const origin = `The API key for this request came from ${credential.source}`;
57138
57356
  if (credential.deliberate) {
@@ -57278,7 +57496,7 @@ function createHasnaHttpTransport(options) {
57278
57496
  const retry = resolveRetry(opts.retry);
57279
57497
  const methodRetryable = IDEMPOTENT_METHODS.has(upper) || Boolean(opts.idempotencyKey);
57280
57498
  const maxAttempts = retry && methodRetryable ? retry.retries + 1 : 1;
57281
- const credential = currentCredential(options.name, options.apiKey);
57499
+ const credential = await resolveRequestCredential(options.name, options.apiKey);
57282
57500
  let last = null;
57283
57501
  for (let attempt = 1;attempt <= maxAttempts; attempt++) {
57284
57502
  const result = await once(upper, rel, url, body2, opts, credential);
@@ -57441,7 +57659,7 @@ function resolveStorageClient(name, env = process.env, overrides) {
57441
57659
  }
57442
57660
  return { transport: "sqlite", client: null };
57443
57661
  }
57444
- var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE", CredentialResolutionError, HASNA_STATE_DIR = ".hasna", FLEET_CREDENTIAL_DIR = "cloud", CONFIG_DIR = ".config", CONFIG_NAMESPACE = "hasna", MAX_CREDENTIAL_FILE_BYTES, SAFE_APP_SLUG, SAFE_PROFILE, ILLEGAL_IN_HEADER_VALUE, CREDENTIAL_SHAPED_KEY, INSPECT_CUSTOM, CREDENTIAL_SEAL, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", DEPRECATION_REGISTRY, ASCII_CONTROL_PATTERN, DNS_LABEL_PATTERN, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS, AUTHORITY_OVERRIDE_HEADERS, defaultSleep = (ms) => new Promise((resolve9) => setTimeout(resolve9, ms));
57662
+ var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE", CredentialResolutionError, HASNA_STATE_DIR = ".hasna", FLEET_CREDENTIAL_DIR = "fleet-env", LEGACY_CLOUD_DIR = "cloud", CONFIG_DIR = ".config", CONFIG_NAMESPACE = "hasna", LEGACY_CLOUD_REMOVAL_DEADLINE = "2026-10-01", MAX_CREDENTIAL_FILE_BYTES, SAFE_APP_SLUG, SAFE_PROFILE, ILLEGAL_IN_HEADER_VALUE, VAULT_POINTER_SHAPE, CREDENTIAL_SHAPED_KEY, INSPECT_CUSTOM, CREDENTIAL_SEAL, CALLER_SUPPLIED_CREDENTIAL_PROVIDER_SOURCE = "caller-supplied CredentialProvider", DEPRECATION_REGISTRY, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk, ASCII_CONTROL_PATTERN, DNS_LABEL_PATTERN, HasnaHttpError, DEFAULT_RETRY_STATUSES, IDEMPOTENT_METHODS, AUTHORITY_OVERRIDE_HEADERS, defaultSleep = (ms) => new Promise((resolve10) => setTimeout(resolve10, ms));
57445
57663
  var init_storage = __esm(() => {
57446
57664
  CredentialResolutionError = class CredentialResolutionError extends Error {
57447
57665
  appName;
@@ -57457,10 +57675,13 @@ var init_storage = __esm(() => {
57457
57675
  SAFE_APP_SLUG = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
57458
57676
  SAFE_PROFILE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
57459
57677
  ILLEGAL_IN_HEADER_VALUE = /[^\t\x20-\x7e]/;
57678
+ VAULT_POINTER_SHAPE = /^[a-z0-9][a-z0-9-]*(?:\/[a-z0-9][a-z0-9-_.]*){2,}$/;
57460
57679
  CREDENTIAL_SHAPED_KEY = /(?:^|_)(?:API_KEY|KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|AUTH)(?:_|$)/;
57461
57680
  INSPECT_CUSTOM = Symbol.for("nodejs.util.inspect.custom");
57462
57681
  CREDENTIAL_SEAL = Symbol.for("hasna:contracts:sealedCredential");
57463
57682
  DEPRECATION_REGISTRY = Symbol.for("hasna:contracts:credentialDeprecationNotices");
57683
+ SECRETS_PACKAGE_SPECIFIER = "@hasna/" + "secrets";
57684
+ requireSecretsSdk = createRequire(import.meta.url);
57464
57685
  ASCII_CONTROL_PATTERN = /[\u0000-\u001f\u007f]/;
57465
57686
  DNS_LABEL_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
57466
57687
  HasnaHttpError = class HasnaHttpError extends Error {
@@ -58339,7 +58560,7 @@ var init_page_validation = __esm(() => {
58339
58560
 
58340
58561
  // src/cli/cloud-router.ts
58341
58562
  import { randomUUID as randomUUID4 } from "crypto";
58342
- import { resolve as resolvePath } from "path";
58563
+ import { resolve as resolvePath2 } from "path";
58343
58564
  function emitTodosLocalFallbackNotice(env) {
58344
58565
  if (todosLocalFallbackNoticeEmitted)
58345
58566
  return;
@@ -58905,11 +59126,11 @@ function resolveCloudProjectRef(projects, ref) {
58905
59126
  const input = ref.trim();
58906
59127
  const normalizedRef = input.toLowerCase();
58907
59128
  const pathLike = input.startsWith(".") || input.includes("/") || input.includes("\\");
58908
- const normalizedPath = pathLike ? resolvePath(input) : undefined;
59129
+ const normalizedPath = pathLike ? resolvePath2(input) : undefined;
58909
59130
  const slug = cloudProjectSlug(pathLike ? cloudProjectPathBasename(input) : input);
58910
59131
  const matchGroups = [
58911
59132
  uniqueProjectMatches(projects, (project) => project.id.toLowerCase() === normalizedRef),
58912
- uniqueProjectMatches(projects, (project) => project.path === input || normalizedPath !== undefined && resolvePath(project.path) === normalizedPath),
59133
+ uniqueProjectMatches(projects, (project) => project.path === input || normalizedPath !== undefined && resolvePath2(project.path) === normalizedPath),
58913
59134
  uniqueProjectMatches(projects, (project) => project.name.toLowerCase() === normalizedRef),
58914
59135
  uniqueProjectMatches(projects, (project) => project.task_list_id === input || cloudProjectSlug(project.name) === slug || cloudProjectSlug(cloudProjectPathBasename(project.path)) === slug),
58915
59136
  uniqueProjectMatches(projects, (project) => project.id.toLowerCase().startsWith(normalizedRef))
@@ -59493,8 +59714,8 @@ var init_task_crud2 = __esm(() => {
59493
59714
  });
59494
59715
 
59495
59716
  // src/lib/project-bootstrap.ts
59496
- import { existsSync as existsSync9, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
59497
- import { basename as basename3, dirname as dirname6, resolve as resolve9 } from "path";
59717
+ import { existsSync as existsSync10, readFileSync as readFileSync6, statSync as statSync5 } from "fs";
59718
+ import { basename as basename3, dirname as dirname6, resolve as resolve10 } from "path";
59498
59719
  function safeStat(path) {
59499
59720
  try {
59500
59721
  return statSync5(path);
@@ -59503,7 +59724,7 @@ function safeStat(path) {
59503
59724
  }
59504
59725
  }
59505
59726
  function canonicalPath(input) {
59506
- const resolved = resolve9(input);
59727
+ const resolved = resolve10(input);
59507
59728
  const stats = safeStat(resolved);
59508
59729
  if (stats?.isFile())
59509
59730
  return dirname6(resolved);
@@ -59512,7 +59733,7 @@ function canonicalPath(input) {
59512
59733
  function findUp(start, marker) {
59513
59734
  let current = canonicalPath(start);
59514
59735
  while (true) {
59515
- if (existsSync9(resolve9(current, marker)))
59736
+ if (existsSync10(resolve10(current, marker)))
59516
59737
  return current;
59517
59738
  const parent = dirname6(current);
59518
59739
  if (parent === current)
@@ -59523,8 +59744,8 @@ function findUp(start, marker) {
59523
59744
  function readPackageJson(path) {
59524
59745
  if (!path)
59525
59746
  return null;
59526
- const file = resolve9(path, "package.json");
59527
- if (!existsSync9(file))
59747
+ const file = resolve10(path, "package.json");
59748
+ if (!existsSync10(file))
59528
59749
  return null;
59529
59750
  try {
59530
59751
  const parsed = JSON.parse(readFileSync6(file, "utf-8"));
@@ -59546,7 +59767,7 @@ function workspaceMarker(root, rootPackage) {
59546
59767
  if (rootPackage?.workspaces)
59547
59768
  markers.push("package.json#workspaces");
59548
59769
  for (const marker of ["pnpm-workspace.yaml", "turbo.json", "nx.json", "lerna.json", "rush.json", "bun.lock", "bun.lockb"]) {
59549
- if (existsSync9(resolve9(root, marker)))
59770
+ if (existsSync10(resolve10(root, marker)))
59550
59771
  markers.push(marker);
59551
59772
  }
59552
59773
  const kind = markers.find((marker) => marker !== "bun.lock" && marker !== "bun.lockb") ?? null;
@@ -59859,7 +60080,7 @@ var init_tags = __esm(() => {
59859
60080
  });
59860
60081
 
59861
60082
  // src/lib/retention-cleanup.ts
59862
- import { existsSync as existsSync10, unlinkSync } from "fs";
60083
+ import { existsSync as existsSync11, unlinkSync } from "fs";
59863
60084
  function normalizeScopes(scopes) {
59864
60085
  if (!scopes || scopes.length === 0)
59865
60086
  return [...ALL_SCOPES];
@@ -60062,7 +60283,7 @@ function applyRetentionCleanup(input, db) {
60062
60283
  for (const artifact of report.candidates.artifact_files) {
60063
60284
  try {
60064
60285
  const path = artifactStorePath(artifact.relative_path);
60065
- if (!existsSync10(path)) {
60286
+ if (!existsSync11(path)) {
60066
60287
  report.warnings.push(`stored artifact already missing: ${artifact.relative_path}`);
60067
60288
  continue;
60068
60289
  }
@@ -60089,8 +60310,8 @@ var init_retention_cleanup = __esm(() => {
60089
60310
  });
60090
60311
 
60091
60312
  // src/lib/mention-resolver.ts
60092
- import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync6 } from "fs";
60093
- import { basename as basename4, isAbsolute, join as join11, relative as relative3, resolve as resolve10, sep as sep3 } from "path";
60313
+ import { existsSync as existsSync12, readdirSync as readdirSync2, readFileSync as readFileSync7, statSync as statSync6 } from "fs";
60314
+ import { basename as basename4, isAbsolute, join as join12, relative as relative3, resolve as resolve11, sep as sep3 } from "path";
60094
60315
  function blankResolution(parsed) {
60095
60316
  return {
60096
60317
  input: parsed.input,
@@ -60113,7 +60334,7 @@ function backlink(kind, key2, label, target = key2) {
60113
60334
  return { kind, key: key2, label, target };
60114
60335
  }
60115
60336
  function normalizeWorkspace(workspace) {
60116
- return resolve10(workspace || process.cwd());
60337
+ return resolve11(workspace || process.cwd());
60117
60338
  }
60118
60339
  function isInside(root, absolutePath) {
60119
60340
  const rel = relative3(root, absolutePath);
@@ -60181,14 +60402,14 @@ function resolveFile(parsed, workspace) {
60181
60402
  resolution.warnings.push("path is empty or escapes the workspace");
60182
60403
  return resolution;
60183
60404
  }
60184
- const absolutePath = resolve10(workspace, relPath);
60405
+ const absolutePath = resolve11(workspace, relPath);
60185
60406
  if (!isInside(workspace, absolutePath)) {
60186
60407
  resolution.path = relPath;
60187
60408
  resolution.warnings.push("path escapes the workspace");
60188
60409
  return resolution;
60189
60410
  }
60190
60411
  resolution.path = relPath;
60191
- if (!existsSync11(absolutePath)) {
60412
+ if (!existsSync12(absolutePath)) {
60192
60413
  resolution.warnings.push("file does not exist in the local workspace");
60193
60414
  return resolution;
60194
60415
  }
@@ -60221,7 +60442,7 @@ function walkSourceFiles(root, current = root, files = []) {
60221
60442
  if (SKIP_DIRS.has(entry2.name))
60222
60443
  continue;
60223
60444
  }
60224
- const absolutePath = join11(current, entry2.name);
60445
+ const absolutePath = join12(current, entry2.name);
60225
60446
  if (entry2.isDirectory()) {
60226
60447
  if (!SKIP_DIRS.has(entry2.name))
60227
60448
  walkSourceFiles(root, absolutePath, files);
@@ -60526,9 +60747,9 @@ var init_mention_resolver = __esm(() => {
60526
60747
  });
60527
60748
 
60528
60749
  // src/lib/policy-packs.ts
60529
- import { relative as relative4, resolve as resolve11 } from "path";
60750
+ import { relative as relative4, resolve as resolve12 } from "path";
60530
60751
  function normalizePath3(path) {
60531
- return resolve11(path);
60752
+ return resolve12(path);
60532
60753
  }
60533
60754
  function unique4(values) {
60534
60755
  return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
@@ -60583,7 +60804,7 @@ function commandMatches(commands, pattern) {
60583
60804
  }
60584
60805
  function pathMatches(paths, pattern, root) {
60585
60806
  return paths.filter((path) => {
60586
- const candidate = path.startsWith("/") ? path : resolve11(root, path);
60807
+ const candidate = path.startsWith("/") ? path : resolve12(root, path);
60587
60808
  if (!isPathInside3(root, candidate))
60588
60809
  return matchesPattern3(path, pattern);
60589
60810
  return matchesPattern3(path, pattern) || matchesPattern3(relative4(root, candidate), pattern);
@@ -63962,7 +64183,7 @@ var init_audit_ledger = __esm(() => {
63962
64183
 
63963
64184
  // src/lib/release-compatibility.ts
63964
64185
  import { readFileSync as readFileSync8 } from "fs";
63965
- import { join as join12, resolve as resolve12 } from "path";
64186
+ import { join as join13, resolve as resolve13 } from "path";
63966
64187
  import { Database as Database2 } from "bun:sqlite";
63967
64188
  function pass(id, message, details) {
63968
64189
  return { id, status: "passed", message, details };
@@ -63974,7 +64195,7 @@ function warn(id, message, details) {
63974
64195
  return { id, status: "warning", message, details };
63975
64196
  }
63976
64197
  function readPackageJson2(root) {
63977
- return JSON.parse(readFileSync8(join12(root, "package.json"), "utf8"));
64198
+ return JSON.parse(readFileSync8(join13(root, "package.json"), "utf8"));
63978
64199
  }
63979
64200
  function sortedKeys(value) {
63980
64201
  return Object.keys(value ?? {}).sort((left, right) => left.localeCompare(right));
@@ -64070,7 +64291,7 @@ function checkChangelog() {
64070
64291
  ];
64071
64292
  }
64072
64293
  function createReleaseCompatibilityReport(options = {}) {
64073
- const root = resolve12(options.root ?? process.cwd());
64294
+ const root = resolve13(options.root ?? process.cwd());
64074
64295
  const packageJson = readPackageJson2(root);
64075
64296
  const simulatedLevels = options.simulated_levels ?? defaultSimulationLevels();
64076
64297
  const checks4 = [
@@ -91181,7 +91402,7 @@ var require_protocol = __commonJS((exports) => {
91181
91402
  return;
91182
91403
  }
91183
91404
  const pollInterval = task3.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
91184
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
91405
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
91185
91406
  options?.signal?.throwIfAborted();
91186
91407
  }
91187
91408
  } catch (error3) {
@@ -91193,7 +91414,7 @@ var require_protocol = __commonJS((exports) => {
91193
91414
  }
91194
91415
  request(request, resultSchema, options) {
91195
91416
  const { relatedRequestId, resumptionToken, onresumptiontoken, task: task2, relatedTask } = options ?? {};
91196
- return new Promise((resolve13, reject) => {
91417
+ return new Promise((resolve14, reject) => {
91197
91418
  const earlyReject = (error3) => {
91198
91419
  reject(error3);
91199
91420
  };
@@ -91271,7 +91492,7 @@ var require_protocol = __commonJS((exports) => {
91271
91492
  if (!parseResult.success) {
91272
91493
  reject(parseResult.error);
91273
91494
  } else {
91274
- resolve13(parseResult.data);
91495
+ resolve14(parseResult.data);
91275
91496
  }
91276
91497
  } catch (error3) {
91277
91498
  reject(error3);
@@ -91462,12 +91683,12 @@ var require_protocol = __commonJS((exports) => {
91462
91683
  interval = task2.pollInterval;
91463
91684
  }
91464
91685
  } catch {}
91465
- return new Promise((resolve13, reject) => {
91686
+ return new Promise((resolve14, reject) => {
91466
91687
  if (signal.aborted) {
91467
91688
  reject(new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, "Request cancelled"));
91468
91689
  return;
91469
91690
  }
91470
- const timeoutId = setTimeout(resolve13, interval);
91691
+ const timeoutId = setTimeout(resolve14, interval);
91471
91692
  signal.addEventListener("abort", () => {
91472
91693
  clearTimeout(timeoutId);
91473
91694
  reject(new types_js_1.McpError(types_js_1.ErrorCode.InvalidRequest, "Request cancelled"));
@@ -92661,7 +92882,7 @@ var require_mcp = __commonJS((exports) => {
92661
92882
  let task2 = createTaskResult.task;
92662
92883
  const pollInterval = task2.pollInterval ?? 5000;
92663
92884
  while (task2.status !== "completed" && task2.status !== "failed" && task2.status !== "cancelled") {
92664
- await new Promise((resolve13) => setTimeout(resolve13, pollInterval));
92885
+ await new Promise((resolve14) => setTimeout(resolve14, pollInterval));
92665
92886
  const updatedTask = await extra.taskStore.getTask(taskId);
92666
92887
  if (!updatedTask) {
92667
92888
  throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Task ${taskId} not found during polling`);
@@ -93980,7 +94201,7 @@ var init_agent_run_dispatcher = __esm(() => {
93980
94201
  });
93981
94202
 
93982
94203
  // src/lib/verification-providers.ts
93983
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
94204
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
93984
94205
  function normalizeName5(name) {
93985
94206
  const normalized = name.trim().toLowerCase();
93986
94207
  if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(normalized)) {
@@ -94077,7 +94298,7 @@ function classifyLog(text) {
94077
94298
  async function sleep2(ms) {
94078
94299
  if (ms <= 0)
94079
94300
  return;
94080
- await new Promise((resolve13) => setTimeout(resolve13, ms));
94301
+ await new Promise((resolve14) => setTimeout(resolve14, ms));
94081
94302
  }
94082
94303
  async function runCommandProvider(provider, input) {
94083
94304
  const commandTemplate = input.command || provider.command;
@@ -94132,7 +94353,7 @@ Timed out after ${provider.timeout_ms}ms`);
94132
94353
  };
94133
94354
  }
94134
94355
  function runCiLogProvider(input) {
94135
- const text = input.log_text ?? (input.log_path && existsSync12(input.log_path) ? readFileSync9(input.log_path, "utf-8") : "");
94356
+ const text = input.log_text ?? (input.log_path && existsSync13(input.log_path) ? readFileSync9(input.log_path, "utf-8") : "");
94136
94357
  return {
94137
94358
  status: classifyLog(text),
94138
94359
  attempts: 1,
@@ -94144,7 +94365,7 @@ function runBrowserProvider(input) {
94144
94365
  if (!input.artifact_path) {
94145
94366
  return { status: "unknown", attempts: 1, exit_code: null, output_summary: "browser provider needs a screenshot or artifact path" };
94146
94367
  }
94147
- if (!existsSync12(input.artifact_path)) {
94368
+ if (!existsSync13(input.artifact_path)) {
94148
94369
  return { status: "failed", attempts: 1, exit_code: null, output_summary: `artifact not found: ${input.artifact_path}` };
94149
94370
  }
94150
94371
  return {
@@ -96874,7 +97095,7 @@ var init_local_bridge = __esm(() => {
96874
97095
  // src/lib/local-backups.ts
96875
97096
  import { createHash as createHash12 } from "crypto";
96876
97097
  import { readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "fs";
96877
- import { dirname as dirname7, resolve as resolve13 } from "path";
97098
+ import { dirname as dirname7, resolve as resolve14 } from "path";
96878
97099
  import { mkdirSync as mkdirSync6 } from "fs";
96879
97100
  function stableJson2(value) {
96880
97101
  if (value === null || typeof value !== "object")
@@ -96976,14 +97197,14 @@ function createLocalBackup(options = {}, db) {
96976
97197
  return backup;
96977
97198
  }
96978
97199
  function writeLocalBackupFile(backup, outputPath) {
96979
- const path = resolve13(outputPath);
97200
+ const path = resolve14(outputPath);
96980
97201
  mkdirSync6(dirname7(path), { recursive: true });
96981
97202
  writeFileSync3(path, `${JSON.stringify(backup, null, 2)}
96982
97203
  `);
96983
97204
  return path;
96984
97205
  }
96985
97206
  function readLocalBackupFile(path) {
96986
- return JSON.parse(readFileSync10(resolve13(path), "utf-8"));
97207
+ return JSON.parse(readFileSync10(resolve14(path), "utf-8"));
96987
97208
  }
96988
97209
  function verifyLocalBackup(value, options = {}, db) {
96989
97210
  const verifiedAt = options.verified_at ?? now();
@@ -98435,8 +98656,8 @@ __export(exports_local_extensions, {
98435
98656
  discoverLocalExtensions: () => discoverLocalExtensions
98436
98657
  });
98437
98658
  import { createHash as createHash15, createVerify } from "crypto";
98438
- import { existsSync as existsSync13, readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync7 } from "fs";
98439
- import { basename as basename5, join as join13, resolve as resolve14 } from "path";
98659
+ import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync as readFileSync11, statSync as statSync7 } from "fs";
98660
+ import { basename as basename5, join as join14, resolve as resolve15 } from "path";
98440
98661
  function isObject3(value) {
98441
98662
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
98442
98663
  }
@@ -98694,11 +98915,11 @@ function verifyExtensionSignature(input) {
98694
98915
  return verifier.verify(input.public_key, decodeSignature(input.signature));
98695
98916
  }
98696
98917
  function inspectExtensionSource(source3) {
98697
- const resolved = resolve14(source3);
98698
- if (!existsSync13(resolved))
98918
+ const resolved = resolve15(source3);
98919
+ if (!existsSync14(resolved))
98699
98920
  throw new Error(`extension source not found: ${source3}`);
98700
98921
  const stat = statSync7(resolved);
98701
- const manifestPath = stat.isDirectory() ? [join13(resolved, "todos.extension.json"), join13(resolved, "extension.json")].find(existsSync13) : resolved;
98922
+ const manifestPath = stat.isDirectory() ? [join14(resolved, "todos.extension.json"), join14(resolved, "extension.json")].find(existsSync14) : resolved;
98702
98923
  if (!manifestPath)
98703
98924
  throw new Error(`extension directory ${source3} is missing todos.extension.json`);
98704
98925
  const raw = readFileSync11(manifestPath);
@@ -98792,26 +99013,26 @@ function testExtensionCompatibility(sourceOrManifest) {
98792
99013
  function projectExtensionSources(projectPath) {
98793
99014
  if (!projectPath)
98794
99015
  return [];
98795
- const root = resolve14(projectPath);
99016
+ const root = resolve15(projectPath);
98796
99017
  const candidates = [
98797
- join13(root, "todos.extension.json"),
98798
- join13(root, ".todos", "todos.extension.json")
99018
+ join14(root, "todos.extension.json"),
99019
+ join14(root, ".todos", "todos.extension.json")
98799
99020
  ];
98800
- const extensionDir = join13(root, ".todos", "extensions");
98801
- if (existsSync13(extensionDir)) {
99021
+ const extensionDir = join14(root, ".todos", "extensions");
99022
+ if (existsSync14(extensionDir)) {
98802
99023
  for (const entry2 of readdirSync3(extensionDir)) {
98803
99024
  if (entry2.startsWith("."))
98804
99025
  continue;
98805
- const full = join13(extensionDir, entry2);
99026
+ const full = join14(extensionDir, entry2);
98806
99027
  if (statSync7(full).isDirectory() || entry2.endsWith(".json"))
98807
99028
  candidates.push(full);
98808
99029
  }
98809
99030
  }
98810
- return candidates.filter(existsSync13);
99031
+ return candidates.filter(existsSync14);
98811
99032
  }
98812
99033
  function discoverLocalExtensions(options = {}) {
98813
99034
  const config2 = loadConfig();
98814
- const projectPath = options.project_path ? resolve14(options.project_path) : null;
99035
+ const projectPath = options.project_path ? resolve15(options.project_path) : null;
98815
99036
  const configuredSources = [
98816
99037
  ...config2.extension_sources || [],
98817
99038
  ...projectPath ? config2.project_overrides?.[projectPath]?.extension_sources || [] : []
@@ -98819,7 +99040,7 @@ function discoverLocalExtensions(options = {}) {
98819
99040
  const sources = Array.from(new Set([
98820
99041
  ...configuredSources,
98821
99042
  ...projectExtensionSources(projectPath || undefined)
98822
- ])).map((source3) => projectPath && !source3.startsWith("/") ? resolve14(projectPath, source3) : resolve14(source3));
99043
+ ])).map((source3) => projectPath && !source3.startsWith("/") ? resolve15(projectPath, source3) : resolve15(source3));
98823
99044
  const warnings = [];
98824
99045
  const discovered = [];
98825
99046
  for (const source3 of sources) {
@@ -103214,9 +103435,9 @@ __export(exports_extract, {
103214
103435
  buildCodebaseIndex: () => buildCodebaseIndex,
103215
103436
  EXTRACT_TAGS: () => EXTRACT_TAGS
103216
103437
  });
103217
- import { existsSync as existsSync14, readFileSync as readFileSync12, statSync as statSync8 } from "fs";
103438
+ import { existsSync as existsSync15, readFileSync as readFileSync12, statSync as statSync8 } from "fs";
103218
103439
  import { createHash as createHash17 } from "crypto";
103219
- import { relative as relative5, resolve as resolve15, join as join14 } from "path";
103440
+ import { relative as relative5, resolve as resolve16, join as join15 } from "path";
103220
103441
  function stableHash(value) {
103221
103442
  return createHash17("sha256").update(value).digest("hex");
103222
103443
  }
@@ -103224,9 +103445,9 @@ function normalizePathForMatch(value) {
103224
103445
  return value.replace(/\\/g, "/").replace(/^\.\//, "");
103225
103446
  }
103226
103447
  function readGitignorePatterns(basePath) {
103227
- const root = statSync8(basePath).isFile() ? resolve15(basePath, "..") : basePath;
103228
- const gitignorePath = join14(root, ".gitignore");
103229
- if (!existsSync14(gitignorePath))
103448
+ const root = statSync8(basePath).isFile() ? resolve16(basePath, "..") : basePath;
103449
+ const gitignorePath = join15(root, ".gitignore");
103450
+ if (!existsSync15(gitignorePath))
103230
103451
  return [];
103231
103452
  try {
103232
103453
  return readFileSync12(gitignorePath, "utf-8").split(`
@@ -103360,7 +103581,7 @@ function collectFiles(basePath, extensions, excludes, respectGitignore) {
103360
103581
  return files.sort();
103361
103582
  }
103362
103583
  function buildCodebaseIndex(options) {
103363
- const basePath = resolve15(options.path);
103584
+ const basePath = resolve16(options.path);
103364
103585
  const tags = options.patterns || [...EXTRACT_TAGS];
103365
103586
  const extensions = options.extensions ? new Set(options.extensions.map((e) => e.startsWith(".") ? e : `.${e}`)) : DEFAULT_EXTENSIONS;
103366
103587
  const excludes = options.exclude || [];
@@ -103368,10 +103589,10 @@ function buildCodebaseIndex(options) {
103368
103589
  const files = collectFiles(basePath, extensions, excludes, respectGitignore);
103369
103590
  const indexed = [];
103370
103591
  for (const file of files) {
103371
- const fullPath = statSync8(basePath).isFile() ? basePath : join14(basePath, file);
103592
+ const fullPath = statSync8(basePath).isFile() ? basePath : join15(basePath, file);
103372
103593
  try {
103373
103594
  const source3 = readFileSync12(fullPath, "utf-8");
103374
- const relPath = statSync8(basePath).isFile() ? relative5(resolve15(basePath, ".."), fullPath) : file;
103595
+ const relPath = statSync8(basePath).isFile() ? relative5(resolve16(basePath, ".."), fullPath) : file;
103375
103596
  indexed.push({
103376
103597
  file: relPath,
103377
103598
  checksum: stableHash(source3).slice(0, 24),
@@ -103391,7 +103612,7 @@ function buildCodebaseIndex(options) {
103391
103612
  };
103392
103613
  }
103393
103614
  function extractTodos(options, db) {
103394
- const basePath = resolve15(options.path);
103615
+ const basePath = resolve16(options.path);
103395
103616
  const tags = options.patterns || [...EXTRACT_TAGS];
103396
103617
  const extensions = options.extensions ? new Set(options.extensions.map((e) => e.startsWith(".") ? e : `.${e}`)) : DEFAULT_EXTENSIONS;
103397
103618
  const excludes = options.exclude || [];
@@ -103399,10 +103620,10 @@ function extractTodos(options, db) {
103399
103620
  const files = collectFiles(basePath, extensions, excludes, respectGitignore);
103400
103621
  const allComments = [];
103401
103622
  for (const file of files) {
103402
- const fullPath = statSync8(basePath).isFile() ? basePath : join14(basePath, file);
103623
+ const fullPath = statSync8(basePath).isFile() ? basePath : join15(basePath, file);
103403
103624
  try {
103404
103625
  const source3 = readFileSync12(fullPath, "utf-8");
103405
- const relPath = statSync8(basePath).isFile() ? relative5(resolve15(basePath, ".."), fullPath) : file;
103626
+ const relPath = statSync8(basePath).isFile() ? relative5(resolve16(basePath, ".."), fullPath) : file;
103406
103627
  const comments = extractFromSource(source3, relPath, tags);
103407
103628
  allComments.push(...comments);
103408
103629
  } catch {}
@@ -103496,7 +103717,7 @@ async function watchSourceTodos(options, onRun) {
103496
103717
  const interval = Math.max(100, options.interval_ms || 2000);
103497
103718
  const once = options.once !== false && (!options.max_runs || options.max_runs <= 1);
103498
103719
  const maxRuns = options.max_runs ?? (once ? 1 : Number.POSITIVE_INFINITY);
103499
- const root = resolve15(options.path);
103720
+ const root = resolve16(options.path);
103500
103721
  const runs = [];
103501
103722
  let previous = new Map;
103502
103723
  for (let runNumber = 1;runNumber <= maxRuns; runNumber++) {
@@ -104055,7 +104276,7 @@ Last seen: ${agent.last_seen_at}`
104055
104276
  `Suggested names: ${suggestions.slice(0, 8).join(", ")}`,
104056
104277
  allActive.length > 0 ? `Active agents (avoid these names): ${allActive.map((a) => `${a.name} (seen ${Math.round((Date.now() - new Date(a.last_seen_at).getTime()) / 60000)}m ago)`).join(", ")}` : "No active agents.",
104057
104278
  `
104058
- To restrict names, configure agent_pool or project_pools in ~/.hasna/todos/config.json`
104279
+ To restrict names, configure agent_pool or project_pools in the todos data home config file (default <data home>/config.json)`
104059
104280
  ];
104060
104281
  return { content: [{ type: "text", text: lines2.join(`
104061
104282
  `) }] };
@@ -104358,7 +104579,7 @@ __export(exports_builtin_templates, {
104358
104579
  BUILTIN_TEMPLATES: () => BUILTIN_TEMPLATES
104359
104580
  });
104360
104581
  import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "fs";
104361
- import { join as join15 } from "path";
104582
+ import { join as join16 } from "path";
104362
104583
  function templateMetadata(template) {
104363
104584
  return {
104364
104585
  source: BUILTIN_TEMPLATE_LIBRARY_SOURCE,
@@ -104417,7 +104638,7 @@ function writeBuiltinTemplateFiles(directory) {
104417
104638
  mkdirSync7(directory, { recursive: true });
104418
104639
  const files = [];
104419
104640
  for (const entry2 of exportBuiltinTemplateFiles()) {
104420
- const path = join15(directory, entry2.filename);
104641
+ const path = join16(directory, entry2.filename);
104421
104642
  writeFileSync4(path, `${JSON.stringify(entry2.template, null, 2)}
104422
104643
  `, "utf-8");
104423
104644
  files.push(path);
@@ -104943,16 +105164,16 @@ __export(exports_environment_snapshots, {
104943
105164
  captureEnvironmentSnapshot: () => captureEnvironmentSnapshot
104944
105165
  });
104945
105166
  import { createHash as createHash18 } from "crypto";
104946
- import { existsSync as existsSync15, readFileSync as readFileSync13, statSync as statSync9 } from "fs";
105167
+ import { existsSync as existsSync16, readFileSync as readFileSync13, statSync as statSync9 } from "fs";
104947
105168
  import { hostname as hostname3, platform, arch } from "os";
104948
- import { dirname as dirname8, join as join16, resolve as resolve16 } from "path";
105169
+ import { dirname as dirname8, join as join17, resolve as resolve17 } from "path";
104949
105170
  import { tmpdir as tmpdir3 } from "os";
104950
105171
  function sha2567(value) {
104951
105172
  return createHash18("sha256").update(value).digest("hex");
104952
105173
  }
104953
105174
  function fileRecord(root, relativePath) {
104954
- const path = join16(root, relativePath);
104955
- if (!existsSync15(path))
105175
+ const path = join17(root, relativePath);
105176
+ if (!existsSync16(path))
104956
105177
  return null;
104957
105178
  const stat = statSync9(path);
104958
105179
  if (!stat.isFile())
@@ -104964,7 +105185,7 @@ function manifestRecord(root, relativePath) {
104964
105185
  const base = fileRecord(root, relativePath);
104965
105186
  if (!base)
104966
105187
  return null;
104967
- const parsed = readJsonFile(join16(root, relativePath));
105188
+ const parsed = readJsonFile(join17(root, relativePath));
104968
105189
  if (!parsed)
104969
105190
  return { ...base, redacted: {} };
104970
105191
  const redacted = redactValue({
@@ -105059,15 +105280,15 @@ function commandEnv(env, includeValues) {
105059
105280
  function defaultSnapshotDir() {
105060
105281
  const dbPath = getDatabasePath();
105061
105282
  if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
105062
- return join16(tmpdir3(), "hasna-todos", "environment-snapshots");
105063
- return join16(dirname8(resolve16(dbPath)), "environment-snapshots");
105283
+ return join17(tmpdir3(), "hasna-todos", "environment-snapshots");
105284
+ return join17(dirname8(resolve17(dbPath)), "environment-snapshots");
105064
105285
  }
105065
105286
  function snapshotWithId(snapshot) {
105066
105287
  const digest4 = sha2567(JSON.stringify(snapshot)).slice(0, 24);
105067
105288
  return { id: `env_${digest4}`, ...snapshot };
105068
105289
  }
105069
105290
  function captureEnvironmentSnapshot(input = {}) {
105070
- const root = resolve16(input.root || process.cwd());
105291
+ const root = resolve17(input.root || process.cwd());
105071
105292
  const env = input.env || process.env;
105072
105293
  const warnings = [];
105073
105294
  const manifests = MANIFEST_FILES.map((file) => manifestRecord(root, file)).filter((file) => Boolean(file));
@@ -105107,13 +105328,13 @@ function captureEnvironmentSnapshot(input = {}) {
105107
105328
  });
105108
105329
  }
105109
105330
  function writeEnvironmentSnapshot(snapshot, outputPath) {
105110
- const path = outputPath ? resolve16(outputPath) : join16(defaultSnapshotDir(), `${snapshot.id}.json`);
105331
+ const path = outputPath ? resolve17(outputPath) : join17(defaultSnapshotDir(), `${snapshot.id}.json`);
105111
105332
  ensureDir(dirname8(path));
105112
105333
  writeJsonFile(path, snapshot);
105113
105334
  return path;
105114
105335
  }
105115
105336
  function readEnvironmentSnapshot(path) {
105116
- const snapshot = readJsonFile(resolve16(path));
105337
+ const snapshot = readJsonFile(resolve17(path));
105117
105338
  if (!snapshot || snapshot.schema_version !== 1 || typeof snapshot.id !== "string") {
105118
105339
  throw new Error(`Invalid environment snapshot: ${path}`);
105119
105340
  }
@@ -105939,8 +106160,8 @@ class SqlitePrGroupLedgerPersistence {
105939
106160
  async transaction(fn) {
105940
106161
  const previous = sqliteTransactionTails2.get(this.db) ?? Promise.resolve();
105941
106162
  let release;
105942
- const current = new Promise((resolve17) => {
105943
- release = resolve17;
106163
+ const current = new Promise((resolve18) => {
106164
+ release = resolve18;
105944
106165
  });
105945
106166
  sqliteTransactionTails2.set(this.db, current);
105946
106167
  await previous;
@@ -106038,27 +106259,27 @@ __export(exports_serve, {
106038
106259
  SECURITY_HEADERS: () => SECURITY_HEADERS,
106039
106260
  MIME_TYPES: () => MIME_TYPES
106040
106261
  });
106041
- import { existsSync as existsSync16 } from "fs";
106042
- import { join as join17, dirname as dirname9, extname } from "path";
106262
+ import { existsSync as existsSync17 } from "fs";
106263
+ import { join as join18, dirname as dirname9, extname } from "path";
106043
106264
  import { fileURLToPath } from "url";
106044
106265
  function resolveDashboardDir() {
106045
106266
  const candidates = [];
106046
106267
  try {
106047
106268
  const scriptDir = dirname9(fileURLToPath(import.meta.url));
106048
- candidates.push(join17(scriptDir, "..", "dashboard", "dist"));
106049
- candidates.push(join17(scriptDir, "..", "..", "dashboard", "dist"));
106269
+ candidates.push(join18(scriptDir, "..", "dashboard", "dist"));
106270
+ candidates.push(join18(scriptDir, "..", "..", "dashboard", "dist"));
106050
106271
  } catch {}
106051
106272
  if (process.argv[1]) {
106052
106273
  const mainDir = dirname9(process.argv[1]);
106053
- candidates.push(join17(mainDir, "..", "dashboard", "dist"));
106054
- candidates.push(join17(mainDir, "..", "..", "dashboard", "dist"));
106274
+ candidates.push(join18(mainDir, "..", "dashboard", "dist"));
106275
+ candidates.push(join18(mainDir, "..", "..", "dashboard", "dist"));
106055
106276
  }
106056
- candidates.push(join17(process.cwd(), "dashboard", "dist"));
106277
+ candidates.push(join18(process.cwd(), "dashboard", "dist"));
106057
106278
  for (const candidate of candidates) {
106058
- if (existsSync16(candidate))
106279
+ if (existsSync17(candidate))
106059
106280
  return candidate;
106060
106281
  }
106061
- return join17(process.cwd(), "dashboard", "dist");
106282
+ return join18(process.cwd(), "dashboard", "dist");
106062
106283
  }
106063
106284
  function getProvidedApiKey(req) {
106064
106285
  const headerKey = req.headers.get("x-api-key");
@@ -106130,7 +106351,7 @@ function json4(data, status3 = 200, headers) {
106130
106351
  });
106131
106352
  }
106132
106353
  function serveStaticFile(filePath) {
106133
- if (!existsSync16(filePath))
106354
+ if (!existsSync17(filePath))
106134
106355
  return null;
106135
106356
  const ext = extname(filePath);
106136
106357
  const contentType2 = MIME_TYPES[ext] || "application/octet-stream";
@@ -106231,7 +106452,7 @@ data: ${data}
106231
106452
  filteredSseClients.delete(client);
106232
106453
  }
106233
106454
  const dashboardDir = resolveDashboardDir();
106234
- const dashboardExists = existsSync16(dashboardDir);
106455
+ const dashboardExists = existsSync17(dashboardDir);
106235
106456
  if (!dashboardExists) {
106236
106457
  console.error(`
106237
106458
  Dashboard not found at: ${dashboardDir}`);