@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.
- package/dist/cli/commands/query-commands.d.ts.map +1 -1
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/index.js +482 -336
- package/dist/contracts.js +193 -94
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/index.js +394 -295
- package/dist/lib/model-config.d.ts +2 -1
- package/dist/lib/model-config.d.ts.map +1 -1
- package/dist/lib/paths.d.ts +40 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/sync-utils.d.ts +7 -0
- package/dist/lib/sync-utils.d.ts.map +1 -1
- package/dist/mcp/index.js +268 -170
- package/dist/mcp.js +6 -3
- package/dist/project-registration.js +191 -92
- package/dist/registry.js +193 -94
- package/dist/release-provenance.json +5 -5
- package/dist/sdk/index.js +100 -8
- package/dist/server/index.js +437 -216
- package/dist/storage.js +183 -87
- package/dist/task-manifest.js +113 -17
- package/dist/testing.d.ts +10 -9
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +2 -2
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +6 -3
- package/postinstall.js +34 -0
package/dist/mcp/index.js
CHANGED
|
@@ -4089,18 +4089,112 @@ var init_identity_mapping = __esm(() => {
|
|
|
4089
4089
|
});
|
|
4090
4090
|
});
|
|
4091
4091
|
|
|
4092
|
-
//
|
|
4093
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
4092
|
+
// node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
|
|
4094
4093
|
import { homedir } from "os";
|
|
4095
4094
|
import { join } from "path";
|
|
4095
|
+
function assertApp(app) {
|
|
4096
|
+
if (typeof app !== "string" || app.length === 0) {
|
|
4097
|
+
throw new TypeError("paths: app must be a non-empty string");
|
|
4098
|
+
}
|
|
4099
|
+
if (!APP_SLUG_RE.test(app)) {
|
|
4100
|
+
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
4101
|
+
}
|
|
4102
|
+
}
|
|
4103
|
+
function envOf(options) {
|
|
4104
|
+
return options.env ?? process.env;
|
|
4105
|
+
}
|
|
4106
|
+
function envValue(options, kind) {
|
|
4107
|
+
const value = envOf(options)[KIND_ENV[kind]];
|
|
4108
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
4109
|
+
}
|
|
4110
|
+
function isMacOS(platform) {
|
|
4111
|
+
return platform === "darwin";
|
|
4112
|
+
}
|
|
4113
|
+
function baseDir(kind, options) {
|
|
4114
|
+
const override = envValue(options, kind);
|
|
4115
|
+
if (override)
|
|
4116
|
+
return override;
|
|
4117
|
+
const home = options.home ?? homedir();
|
|
4118
|
+
const platform = options.platform ?? process.platform;
|
|
4119
|
+
if (isMacOS(platform)) {
|
|
4120
|
+
switch (kind) {
|
|
4121
|
+
case "config":
|
|
4122
|
+
case "data":
|
|
4123
|
+
return join(home, "Library", "Application Support", "Hasna");
|
|
4124
|
+
case "cache":
|
|
4125
|
+
return join(home, "Library", "Caches", "Hasna");
|
|
4126
|
+
case "state":
|
|
4127
|
+
return join(home, "Library", "Logs", "Hasna");
|
|
4128
|
+
}
|
|
4129
|
+
}
|
|
4130
|
+
switch (kind) {
|
|
4131
|
+
case "config":
|
|
4132
|
+
return join(home, ".config", "hasna");
|
|
4133
|
+
case "data":
|
|
4134
|
+
return join(home, ".local", "share", "hasna");
|
|
4135
|
+
case "state":
|
|
4136
|
+
return join(home, ".local", "state", "hasna");
|
|
4137
|
+
case "cache":
|
|
4138
|
+
return join(home, ".cache", "hasna");
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
function resolvePath(kind, options) {
|
|
4142
|
+
assertApp(options.app);
|
|
4143
|
+
const appSegment = options.internal === true ? join("internal", options.app) : options.app;
|
|
4144
|
+
return join(baseDir(kind, options), appSegment);
|
|
4145
|
+
}
|
|
4146
|
+
function dataDir(options) {
|
|
4147
|
+
return resolvePath("data", options);
|
|
4148
|
+
}
|
|
4149
|
+
var KIND_ENV, APP_SLUG_RE;
|
|
4150
|
+
var init_dist = __esm(() => {
|
|
4151
|
+
KIND_ENV = {
|
|
4152
|
+
config: "HASNA_CONFIG_HOME",
|
|
4153
|
+
data: "HASNA_DATA_HOME",
|
|
4154
|
+
state: "HASNA_STATE_HOME",
|
|
4155
|
+
cache: "HASNA_CACHE_HOME"
|
|
4156
|
+
};
|
|
4157
|
+
APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
4158
|
+
});
|
|
4159
|
+
|
|
4160
|
+
// src/lib/paths.ts
|
|
4161
|
+
import { existsSync as existsSync2 } from "fs";
|
|
4162
|
+
import { homedir as homedir2 } from "os";
|
|
4163
|
+
import { join as join2, resolve as resolve2 } from "path";
|
|
4164
|
+
function effectiveHome(env = process.env) {
|
|
4165
|
+
return env.HOME || env.USERPROFILE || homedir2();
|
|
4166
|
+
}
|
|
4167
|
+
function legacyHomeDir(env = process.env) {
|
|
4168
|
+
return join2(effectiveHome(env), ".hasna", "todos");
|
|
4169
|
+
}
|
|
4170
|
+
function resolverHome(env = process.env) {
|
|
4171
|
+
return dataDir({ app: "todos", home: effectiveHome(env), env });
|
|
4172
|
+
}
|
|
4173
|
+
function adoptResolverHome(resolved, env = process.env) {
|
|
4174
|
+
const dataOverride = env.HASNA_DATA_HOME;
|
|
4175
|
+
if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
|
|
4176
|
+
return true;
|
|
4177
|
+
return existsSync2(join2(resolved, "todos.db")) || existsSync2(join2(resolved, "config.json"));
|
|
4178
|
+
}
|
|
4179
|
+
function getTodosDir(env = process.env) {
|
|
4180
|
+
const resolved = resolverHome(env);
|
|
4181
|
+
return resolve2(adoptResolverHome(resolved, env) ? resolved : legacyHomeDir(env));
|
|
4182
|
+
}
|
|
4183
|
+
var init_paths = __esm(() => {
|
|
4184
|
+
init_dist();
|
|
4185
|
+
});
|
|
4186
|
+
|
|
4187
|
+
// src/lib/sync-utils.ts
|
|
4188
|
+
import { existsSync as existsSync3, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
4189
|
+
import { homedir as homedir3 } from "os";
|
|
4096
4190
|
function getHomeDir() {
|
|
4097
|
-
return process.env["HOME"] || process.env["USERPROFILE"] ||
|
|
4191
|
+
return process.env["HOME"] || process.env["USERPROFILE"] || homedir3();
|
|
4098
4192
|
}
|
|
4099
4193
|
function getTodosGlobalDir() {
|
|
4100
|
-
return
|
|
4194
|
+
return getTodosDir();
|
|
4101
4195
|
}
|
|
4102
4196
|
function ensureDir(dir) {
|
|
4103
|
-
if (!
|
|
4197
|
+
if (!existsSync3(dir))
|
|
4104
4198
|
mkdirSync(dir, { recursive: true });
|
|
4105
4199
|
}
|
|
4106
4200
|
function readJsonFile(path) {
|
|
@@ -4121,6 +4215,7 @@ function appendSyncConflict(metadata, conflict, limit = 5) {
|
|
|
4121
4215
|
}
|
|
4122
4216
|
var HOME;
|
|
4123
4217
|
var init_sync_utils = __esm(() => {
|
|
4218
|
+
init_paths();
|
|
4124
4219
|
HOME = getHomeDir();
|
|
4125
4220
|
});
|
|
4126
4221
|
|
|
@@ -4431,18 +4526,18 @@ __export(exports_database, {
|
|
|
4431
4526
|
LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
|
|
4432
4527
|
});
|
|
4433
4528
|
import { Database } from "bun:sqlite";
|
|
4434
|
-
import { existsSync as
|
|
4435
|
-
import { dirname, join as
|
|
4529
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2 } from "fs";
|
|
4530
|
+
import { dirname, join as join3, resolve as resolve3 } from "path";
|
|
4436
4531
|
function isInMemoryDb(path) {
|
|
4437
4532
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
4438
4533
|
}
|
|
4439
4534
|
function findNearestProjectDb(startDir) {
|
|
4440
4535
|
const gitRoot = findGitRoot(startDir);
|
|
4441
|
-
const stopAt = gitRoot ?
|
|
4442
|
-
let dir =
|
|
4536
|
+
const stopAt = gitRoot ? resolve3(gitRoot) : resolve3(startDir);
|
|
4537
|
+
let dir = resolve3(startDir);
|
|
4443
4538
|
while (true) {
|
|
4444
|
-
const candidate =
|
|
4445
|
-
if (
|
|
4539
|
+
const candidate = join3(dir, ".hasna", "todos", "todos.db");
|
|
4540
|
+
if (existsSync4(candidate))
|
|
4446
4541
|
return candidate;
|
|
4447
4542
|
if (dir === stopAt)
|
|
4448
4543
|
break;
|
|
@@ -4454,9 +4549,9 @@ function findNearestProjectDb(startDir) {
|
|
|
4454
4549
|
return null;
|
|
4455
4550
|
}
|
|
4456
4551
|
function findGitRoot(startDir) {
|
|
4457
|
-
let dir =
|
|
4552
|
+
let dir = resolve3(startDir);
|
|
4458
4553
|
while (true) {
|
|
4459
|
-
if (
|
|
4554
|
+
if (existsSync4(join3(dir, ".git")))
|
|
4460
4555
|
return dir;
|
|
4461
4556
|
const parent = dirname(dir);
|
|
4462
4557
|
if (parent === dir)
|
|
@@ -4466,7 +4561,7 @@ function findGitRoot(startDir) {
|
|
|
4466
4561
|
return null;
|
|
4467
4562
|
}
|
|
4468
4563
|
function getGlobalDbPath() {
|
|
4469
|
-
return
|
|
4564
|
+
return join3(getTodosGlobalDir(), "todos.db");
|
|
4470
4565
|
}
|
|
4471
4566
|
function hasExplicitProjectArg(args = process.argv.slice(2)) {
|
|
4472
4567
|
return args.some((arg) => arg === "--project" || arg.startsWith("--project="));
|
|
@@ -4504,7 +4599,7 @@ function getDbPath() {
|
|
|
4504
4599
|
if (process.env["TODOS_DB_SCOPE"] === "project") {
|
|
4505
4600
|
const gitRoot = findGitRoot(cwd);
|
|
4506
4601
|
if (gitRoot && canCreateScopedProjectDb()) {
|
|
4507
|
-
return
|
|
4602
|
+
return join3(gitRoot, ".hasna", "todos", "todos.db");
|
|
4508
4603
|
}
|
|
4509
4604
|
}
|
|
4510
4605
|
return getGlobalDbPath();
|
|
@@ -4515,8 +4610,8 @@ function getDatabasePath() {
|
|
|
4515
4610
|
function ensureDir2(filePath) {
|
|
4516
4611
|
if (isInMemoryDb(filePath))
|
|
4517
4612
|
return;
|
|
4518
|
-
const dir = dirname(
|
|
4519
|
-
if (!
|
|
4613
|
+
const dir = dirname(resolve3(filePath));
|
|
4614
|
+
if (!existsSync4(dir)) {
|
|
4520
4615
|
mkdirSync2(dir, { recursive: true });
|
|
4521
4616
|
}
|
|
4522
4617
|
}
|
|
@@ -9433,15 +9528,15 @@ var init_zod = __esm(() => {
|
|
|
9433
9528
|
});
|
|
9434
9529
|
|
|
9435
9530
|
// src/lib/config.ts
|
|
9436
|
-
import { existsSync as
|
|
9437
|
-
import { dirname as dirname2, join as
|
|
9531
|
+
import { existsSync as existsSync5, readFileSync as readFileSync2 } from "fs";
|
|
9532
|
+
import { dirname as dirname2, join as join4 } from "path";
|
|
9438
9533
|
function getConfigPath() {
|
|
9439
|
-
return
|
|
9534
|
+
return join4(getTodosGlobalDir(), "config.json");
|
|
9440
9535
|
}
|
|
9441
9536
|
function loadConfig() {
|
|
9442
9537
|
if (cached)
|
|
9443
9538
|
return cached;
|
|
9444
|
-
if (!
|
|
9539
|
+
if (!existsSync5(getConfigPath())) {
|
|
9445
9540
|
cached = {};
|
|
9446
9541
|
return cached;
|
|
9447
9542
|
}
|
|
@@ -10404,14 +10499,14 @@ var init_completion_guard = __esm(() => {
|
|
|
10404
10499
|
|
|
10405
10500
|
// src/lib/event-emission-safety.ts
|
|
10406
10501
|
import { tmpdir } from "os";
|
|
10407
|
-
import { resolve as
|
|
10502
|
+
import { resolve as resolve4, sep } from "path";
|
|
10408
10503
|
function envFlag(name) {
|
|
10409
10504
|
const value = process.env[name]?.trim().toLowerCase();
|
|
10410
10505
|
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
10411
10506
|
}
|
|
10412
10507
|
function isUnder(parent, child) {
|
|
10413
|
-
const normalizedParent =
|
|
10414
|
-
const normalizedChild =
|
|
10508
|
+
const normalizedParent = resolve4(parent);
|
|
10509
|
+
const normalizedChild = resolve4(child);
|
|
10415
10510
|
return normalizedChild === normalizedParent || normalizedChild.startsWith(`${normalizedParent}${sep}`);
|
|
10416
10511
|
}
|
|
10417
10512
|
function databasePathFromDatabase(db) {
|
|
@@ -10454,9 +10549,9 @@ var init_event_emission_safety = __esm(() => {
|
|
|
10454
10549
|
});
|
|
10455
10550
|
|
|
10456
10551
|
// src/lib/workspace-trust.ts
|
|
10457
|
-
import { relative, resolve as
|
|
10552
|
+
import { relative, resolve as resolve5 } from "path";
|
|
10458
10553
|
function normalizePath(path) {
|
|
10459
|
-
return
|
|
10554
|
+
return resolve5(path);
|
|
10460
10555
|
}
|
|
10461
10556
|
function unique2(values) {
|
|
10462
10557
|
return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
|
|
@@ -10638,9 +10733,9 @@ var init_workspace_trust = __esm(() => {
|
|
|
10638
10733
|
});
|
|
10639
10734
|
|
|
10640
10735
|
// src/lib/runner-sandbox.ts
|
|
10641
|
-
import { relative as relative2, resolve as
|
|
10736
|
+
import { relative as relative2, resolve as resolve6 } from "path";
|
|
10642
10737
|
function normalizePath2(path) {
|
|
10643
|
-
return
|
|
10738
|
+
return resolve6(path);
|
|
10644
10739
|
}
|
|
10645
10740
|
function unique3(values) {
|
|
10646
10741
|
return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
|
|
@@ -10830,7 +10925,7 @@ var init_runner_sandbox = __esm(() => {
|
|
|
10830
10925
|
// src/lib/event-hooks.ts
|
|
10831
10926
|
import { createHash, randomUUID } from "crypto";
|
|
10832
10927
|
import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
10833
|
-
import { dirname as dirname3, resolve as
|
|
10928
|
+
import { dirname as dirname3, resolve as resolve7 } from "path";
|
|
10834
10929
|
import { createConnection } from "net";
|
|
10835
10930
|
function safeName(name) {
|
|
10836
10931
|
const trimmed = name.trim();
|
|
@@ -10968,7 +11063,7 @@ async function deliverHook(hook, envelope) {
|
|
|
10968
11063
|
if (hook.target === "stdout") {
|
|
10969
11064
|
output = line.trim();
|
|
10970
11065
|
} else if (hook.target === "file") {
|
|
10971
|
-
const filePath =
|
|
11066
|
+
const filePath = resolve7(hook.file_path);
|
|
10972
11067
|
mkdirSync3(dirname3(filePath), { recursive: true });
|
|
10973
11068
|
appendFileSync(filePath, line);
|
|
10974
11069
|
} else if (hook.target === "socket") {
|
|
@@ -11089,9 +11184,9 @@ var init_event_hooks = __esm(() => {
|
|
|
11089
11184
|
// node_modules/.bun/@hasna+events@0.1.16/node_modules/@hasna/events/dist/index.js
|
|
11090
11185
|
import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
11091
11186
|
import { Buffer as Buffer2 } from "buffer";
|
|
11092
|
-
import { existsSync as
|
|
11093
|
-
import { homedir as
|
|
11094
|
-
import { join as
|
|
11187
|
+
import { existsSync as existsSync6 } from "fs";
|
|
11188
|
+
import { homedir as homedir4 } from "os";
|
|
11189
|
+
import { join as join5 } from "path";
|
|
11095
11190
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
11096
11191
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
11097
11192
|
import { spawn } from "child_process";
|
|
@@ -11192,7 +11287,7 @@ function channelMatchesEvent(channel, event) {
|
|
|
11192
11287
|
return channel.filters.some((filter) => eventMatchesFilter(event, filter));
|
|
11193
11288
|
}
|
|
11194
11289
|
function getEventsDataDir(override) {
|
|
11195
|
-
return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] ||
|
|
11290
|
+
return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join5(homedir4(), ".hasna", "events");
|
|
11196
11291
|
}
|
|
11197
11292
|
|
|
11198
11293
|
class JsonEventsStore {
|
|
@@ -11201,12 +11296,12 @@ class JsonEventsStore {
|
|
|
11201
11296
|
channelsPath;
|
|
11202
11297
|
eventsPath;
|
|
11203
11298
|
deliveriesPath;
|
|
11204
|
-
constructor(
|
|
11205
|
-
this.dataDir =
|
|
11206
|
-
this.runtime = localJsonRuntime(
|
|
11207
|
-
this.channelsPath =
|
|
11208
|
-
this.eventsPath =
|
|
11209
|
-
this.deliveriesPath =
|
|
11299
|
+
constructor(dataDir2 = getEventsDataDir()) {
|
|
11300
|
+
this.dataDir = dataDir2;
|
|
11301
|
+
this.runtime = localJsonRuntime(dataDir2);
|
|
11302
|
+
this.channelsPath = join5(dataDir2, "channels.json");
|
|
11303
|
+
this.eventsPath = join5(dataDir2, "events.json");
|
|
11304
|
+
this.deliveriesPath = join5(dataDir2, "deliveries.json");
|
|
11210
11305
|
}
|
|
11211
11306
|
async init() {
|
|
11212
11307
|
await mkdir(this.dataDir, { recursive: true, mode: 448 });
|
|
@@ -11323,7 +11418,7 @@ class JsonEventsStore {
|
|
|
11323
11418
|
};
|
|
11324
11419
|
}
|
|
11325
11420
|
async ensureArrayFile(path) {
|
|
11326
|
-
if (!
|
|
11421
|
+
if (!existsSync6(path)) {
|
|
11327
11422
|
await writeFile(path, `[]
|
|
11328
11423
|
`, { encoding: "utf-8", mode: 384 });
|
|
11329
11424
|
}
|
|
@@ -11353,7 +11448,7 @@ class JsonEventsStore {
|
|
|
11353
11448
|
});
|
|
11354
11449
|
}
|
|
11355
11450
|
}
|
|
11356
|
-
function localJsonRuntime(
|
|
11451
|
+
function localJsonRuntime(dataDir2 = getEventsDataDir()) {
|
|
11357
11452
|
return {
|
|
11358
11453
|
mode: "local-files",
|
|
11359
11454
|
name: "json-events-store",
|
|
@@ -11366,7 +11461,7 @@ function localJsonRuntime(dataDir = getEventsDataDir()) {
|
|
|
11366
11461
|
durable: true,
|
|
11367
11462
|
idempotency: "best-effort-local",
|
|
11368
11463
|
replayCursors: true,
|
|
11369
|
-
description: `Local JSON files in ${
|
|
11464
|
+
description: `Local JSON files in ${dataDir2}; no SQLite, Postgres, S3, or AWS runtime is configured by this store.`
|
|
11370
11465
|
};
|
|
11371
11466
|
}
|
|
11372
11467
|
function encodeLocalJsonEventCursor(offset, options = {}) {
|
|
@@ -11545,7 +11640,7 @@ async function dispatchCommand(event, channel) {
|
|
|
11545
11640
|
HASNA_EVENT_SCHEMA_VERSION: event.schemaVersion,
|
|
11546
11641
|
HASNA_EVENT_JSON: eventJson
|
|
11547
11642
|
};
|
|
11548
|
-
return new Promise((
|
|
11643
|
+
return new Promise((resolve8) => {
|
|
11549
11644
|
const child = spawn(channel.command.command, channel.command.args ?? [], {
|
|
11550
11645
|
cwd: channel.command.cwd,
|
|
11551
11646
|
env,
|
|
@@ -11563,7 +11658,7 @@ async function dispatchCommand(event, channel) {
|
|
|
11563
11658
|
});
|
|
11564
11659
|
child.on("error", (error) => {
|
|
11565
11660
|
clearTimeout(timeout);
|
|
11566
|
-
|
|
11661
|
+
resolve8({
|
|
11567
11662
|
attempt: 1,
|
|
11568
11663
|
status: "failed",
|
|
11569
11664
|
startedAt,
|
|
@@ -11576,7 +11671,7 @@ async function dispatchCommand(event, channel) {
|
|
|
11576
11671
|
child.on("close", (code, signal) => {
|
|
11577
11672
|
clearTimeout(timeout);
|
|
11578
11673
|
const success = code === 0;
|
|
11579
|
-
|
|
11674
|
+
resolve8({
|
|
11580
11675
|
attempt: 1,
|
|
11581
11676
|
status: success ? "success" : "failed",
|
|
11582
11677
|
startedAt,
|
|
@@ -11918,7 +12013,7 @@ function normalizeRetryPolicy(policy) {
|
|
|
11918
12013
|
};
|
|
11919
12014
|
}
|
|
11920
12015
|
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;
|
|
11921
|
-
var
|
|
12016
|
+
var init_dist2 = __esm(() => {
|
|
11922
12017
|
DEFAULT_SIGNATURE_TOLERANCE_MS = 5 * 60 * 1000;
|
|
11923
12018
|
EventValidationError = class EventValidationError extends Error {
|
|
11924
12019
|
eventType;
|
|
@@ -12338,7 +12433,7 @@ function emitSharedTaskEventQuiet(input) {
|
|
|
12338
12433
|
}
|
|
12339
12434
|
var SOURCE = "todos";
|
|
12340
12435
|
var init_shared_events = __esm(() => {
|
|
12341
|
-
|
|
12436
|
+
init_dist2();
|
|
12342
12437
|
init_database();
|
|
12343
12438
|
init_projects();
|
|
12344
12439
|
init_task_lists();
|
|
@@ -12882,14 +12977,14 @@ var init_task_parent_integrity = __esm(() => {
|
|
|
12882
12977
|
});
|
|
12883
12978
|
|
|
12884
12979
|
// src/lib/creator-identity.ts
|
|
12885
|
-
import { existsSync as
|
|
12886
|
-
import { join as
|
|
12980
|
+
import { existsSync as existsSync7, rmSync } from "fs";
|
|
12981
|
+
import { join as join6 } from "path";
|
|
12887
12982
|
function identityFilePath() {
|
|
12888
|
-
return
|
|
12983
|
+
return join6(getTodosGlobalDir(), "identity.json");
|
|
12889
12984
|
}
|
|
12890
12985
|
function readPersistedIdentity() {
|
|
12891
12986
|
const path = identityFilePath();
|
|
12892
|
-
if (!
|
|
12987
|
+
if (!existsSync7(path))
|
|
12893
12988
|
return null;
|
|
12894
12989
|
const parsed = readJsonFile(path);
|
|
12895
12990
|
if (!parsed || typeof parsed.agent_id !== "string" || !parsed.agent_id.trim())
|
|
@@ -14420,17 +14515,17 @@ function sanitizeCreateTaskInput(input) {
|
|
|
14420
14515
|
return {
|
|
14421
14516
|
...input,
|
|
14422
14517
|
title: sanitizePreWriteText(input.title, "task.title"),
|
|
14423
|
-
description: input.description
|
|
14518
|
+
description: input.description == null ? input.description : sanitizePreWriteText(input.description, "task.description"),
|
|
14424
14519
|
tags: input.tags !== undefined ? sanitizePreWriteValue(input.tags, "task.tags") : undefined,
|
|
14425
14520
|
metadata: input.metadata !== undefined ? sanitizePreWriteValue(input.metadata, "task.metadata") : undefined,
|
|
14426
|
-
reason: input.reason
|
|
14521
|
+
reason: input.reason == null ? input.reason : sanitizePreWriteText(input.reason, "task.reason")
|
|
14427
14522
|
};
|
|
14428
14523
|
}
|
|
14429
14524
|
function sanitizeUpdateTaskInput(input) {
|
|
14430
14525
|
return {
|
|
14431
14526
|
...input,
|
|
14432
14527
|
title: input.title !== undefined ? sanitizePreWriteText(input.title, "task.title") : undefined,
|
|
14433
|
-
description: input.description
|
|
14528
|
+
description: input.description == null ? input.description : sanitizePreWriteText(input.description, "task.description"),
|
|
14434
14529
|
tags: input.tags !== undefined ? sanitizePreWriteValue(input.tags, "task.tags") : undefined,
|
|
14435
14530
|
metadata: input.metadata !== undefined ? sanitizePreWriteValue(input.metadata, "task.metadata") : undefined
|
|
14436
14531
|
};
|
|
@@ -16427,28 +16522,28 @@ var init_boards = __esm(() => {
|
|
|
16427
16522
|
|
|
16428
16523
|
// src/lib/artifact-store.ts
|
|
16429
16524
|
import { createHash as createHash2 } from "crypto";
|
|
16430
|
-
import { existsSync as
|
|
16431
|
-
import { basename, dirname as dirname4, join as
|
|
16525
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync3, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
16526
|
+
import { basename, dirname as dirname4, join as join7, resolve as resolve8 } from "path";
|
|
16432
16527
|
import { tmpdir as tmpdir2 } from "os";
|
|
16433
16528
|
function isInMemoryDb2(path) {
|
|
16434
16529
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
16435
16530
|
}
|
|
16436
16531
|
function artifactStoreRoot() {
|
|
16437
16532
|
if (process.env["HASNA_TODOS_ARTIFACTS_DIR"])
|
|
16438
|
-
return
|
|
16533
|
+
return resolve8(process.env["HASNA_TODOS_ARTIFACTS_DIR"]);
|
|
16439
16534
|
if (process.env["TODOS_ARTIFACTS_DIR"])
|
|
16440
|
-
return
|
|
16535
|
+
return resolve8(process.env["TODOS_ARTIFACTS_DIR"]);
|
|
16441
16536
|
const dbPath = getDatabasePath();
|
|
16442
16537
|
if (isInMemoryDb2(dbPath))
|
|
16443
|
-
return
|
|
16444
|
-
return
|
|
16538
|
+
return join7(tmpdir2(), "hasna-todos-artifacts");
|
|
16539
|
+
return join7(dirname4(resolve8(dbPath)), "artifacts");
|
|
16445
16540
|
}
|
|
16446
16541
|
function artifactStorePath(relativePath) {
|
|
16447
16542
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
16448
16543
|
if (normalized.includes("..") || normalized.startsWith("/") || normalized.length === 0) {
|
|
16449
16544
|
throw new Error("Invalid artifact store path");
|
|
16450
16545
|
}
|
|
16451
|
-
return
|
|
16546
|
+
return join7(artifactStoreRoot(), normalized);
|
|
16452
16547
|
}
|
|
16453
16548
|
function sha256(buffer) {
|
|
16454
16549
|
return createHash2("sha256").update(buffer).digest("hex");
|
|
@@ -16488,8 +16583,8 @@ function mediaTypeFor(path, textLike) {
|
|
|
16488
16583
|
return "application/octet-stream";
|
|
16489
16584
|
}
|
|
16490
16585
|
function storeArtifactContent(input) {
|
|
16491
|
-
const sourcePath =
|
|
16492
|
-
if (!
|
|
16586
|
+
const sourcePath = resolve8(input.path);
|
|
16587
|
+
if (!existsSync8(sourcePath))
|
|
16493
16588
|
return null;
|
|
16494
16589
|
const sourceStat = statSync2(sourcePath);
|
|
16495
16590
|
if (!sourceStat.isFile())
|
|
@@ -16506,9 +16601,9 @@ function storeArtifactContent(input) {
|
|
|
16506
16601
|
redactionStatus = "redacted";
|
|
16507
16602
|
}
|
|
16508
16603
|
const storedSha = sha256(storedBuffer);
|
|
16509
|
-
const relativePath =
|
|
16604
|
+
const relativePath = join7("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
|
|
16510
16605
|
const destination = artifactStorePath(relativePath);
|
|
16511
|
-
if (!
|
|
16606
|
+
if (!existsSync8(destination)) {
|
|
16512
16607
|
mkdirSync4(dirname4(destination), { recursive: true });
|
|
16513
16608
|
writeFileSync2(destination, storedBuffer);
|
|
16514
16609
|
}
|
|
@@ -16568,7 +16663,7 @@ function verifyStoredArtifact(input) {
|
|
|
16568
16663
|
};
|
|
16569
16664
|
}
|
|
16570
16665
|
const storedPath = artifactStorePath(store.relative_path);
|
|
16571
|
-
if (!
|
|
16666
|
+
if (!existsSync8(storedPath)) {
|
|
16572
16667
|
return {
|
|
16573
16668
|
id: input.id,
|
|
16574
16669
|
path: input.path,
|
|
@@ -19046,10 +19141,10 @@ var init_token_utils = __esm(() => {
|
|
|
19046
19141
|
|
|
19047
19142
|
// src/lib/assignee-validation.ts
|
|
19048
19143
|
import { readFileSync as readFileSync4 } from "fs";
|
|
19049
|
-
import { homedir as
|
|
19050
|
-
import { join as
|
|
19144
|
+
import { homedir as homedir5 } from "os";
|
|
19145
|
+
import { join as join8 } from "path";
|
|
19051
19146
|
function defaultSeatRosterPath() {
|
|
19052
|
-
return process.env["TODOS_SEAT_ROSTER_PATH"] ||
|
|
19147
|
+
return process.env["TODOS_SEAT_ROSTER_PATH"] || join8(homedir5(), ".hasna", "identities", "hasna-seats.roster.json");
|
|
19053
19148
|
}
|
|
19054
19149
|
function loadSeatSlugs(path = defaultSeatRosterPath()) {
|
|
19055
19150
|
try {
|
|
@@ -21518,7 +21613,7 @@ var init_page_validation = __esm(() => {
|
|
|
21518
21613
|
// src/cli/cloud-router.ts
|
|
21519
21614
|
import { resolveStorageClient } from "@hasna/contracts/client/storage";
|
|
21520
21615
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
21521
|
-
import { resolve as
|
|
21616
|
+
import { resolve as resolvePath2 } from "path";
|
|
21522
21617
|
function emitTodosLocalFallbackNotice(env) {
|
|
21523
21618
|
if (todosLocalFallbackNoticeEmitted)
|
|
21524
21619
|
return;
|
|
@@ -22084,11 +22179,11 @@ function resolveCloudProjectRef(projects, ref) {
|
|
|
22084
22179
|
const input = ref.trim();
|
|
22085
22180
|
const normalizedRef = input.toLowerCase();
|
|
22086
22181
|
const pathLike = input.startsWith(".") || input.includes("/") || input.includes("\\");
|
|
22087
|
-
const normalizedPath = pathLike ?
|
|
22182
|
+
const normalizedPath = pathLike ? resolvePath2(input) : undefined;
|
|
22088
22183
|
const slug = cloudProjectSlug(pathLike ? cloudProjectPathBasename(input) : input);
|
|
22089
22184
|
const matchGroups = [
|
|
22090
22185
|
uniqueProjectMatches(projects, (project) => project.id.toLowerCase() === normalizedRef),
|
|
22091
|
-
uniqueProjectMatches(projects, (project) => project.path === input || normalizedPath !== undefined &&
|
|
22186
|
+
uniqueProjectMatches(projects, (project) => project.path === input || normalizedPath !== undefined && resolvePath2(project.path) === normalizedPath),
|
|
22092
22187
|
uniqueProjectMatches(projects, (project) => project.name.toLowerCase() === normalizedRef),
|
|
22093
22188
|
uniqueProjectMatches(projects, (project) => project.task_list_id === input || cloudProjectSlug(project.name) === slug || cloudProjectSlug(cloudProjectPathBasename(project.path)) === slug),
|
|
22094
22189
|
uniqueProjectMatches(projects, (project) => project.id.toLowerCase().startsWith(normalizedRef))
|
|
@@ -22671,8 +22766,8 @@ var init_task_crud2 = __esm(() => {
|
|
|
22671
22766
|
});
|
|
22672
22767
|
|
|
22673
22768
|
// src/lib/project-bootstrap.ts
|
|
22674
|
-
import { existsSync as
|
|
22675
|
-
import { basename as basename2, dirname as dirname5, resolve as
|
|
22769
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5, statSync as statSync3 } from "fs";
|
|
22770
|
+
import { basename as basename2, dirname as dirname5, resolve as resolve9 } from "path";
|
|
22676
22771
|
function safeStat(path) {
|
|
22677
22772
|
try {
|
|
22678
22773
|
return statSync3(path);
|
|
@@ -22681,7 +22776,7 @@ function safeStat(path) {
|
|
|
22681
22776
|
}
|
|
22682
22777
|
}
|
|
22683
22778
|
function canonicalPath(input) {
|
|
22684
|
-
const resolved =
|
|
22779
|
+
const resolved = resolve9(input);
|
|
22685
22780
|
const stats = safeStat(resolved);
|
|
22686
22781
|
if (stats?.isFile())
|
|
22687
22782
|
return dirname5(resolved);
|
|
@@ -22690,7 +22785,7 @@ function canonicalPath(input) {
|
|
|
22690
22785
|
function findUp(start, marker) {
|
|
22691
22786
|
let current = canonicalPath(start);
|
|
22692
22787
|
while (true) {
|
|
22693
|
-
if (
|
|
22788
|
+
if (existsSync9(resolve9(current, marker)))
|
|
22694
22789
|
return current;
|
|
22695
22790
|
const parent = dirname5(current);
|
|
22696
22791
|
if (parent === current)
|
|
@@ -22701,8 +22796,8 @@ function findUp(start, marker) {
|
|
|
22701
22796
|
function readPackageJson(path) {
|
|
22702
22797
|
if (!path)
|
|
22703
22798
|
return null;
|
|
22704
|
-
const file =
|
|
22705
|
-
if (!
|
|
22799
|
+
const file = resolve9(path, "package.json");
|
|
22800
|
+
if (!existsSync9(file))
|
|
22706
22801
|
return null;
|
|
22707
22802
|
try {
|
|
22708
22803
|
const parsed = JSON.parse(readFileSync5(file, "utf-8"));
|
|
@@ -22724,7 +22819,7 @@ function workspaceMarker(root, rootPackage) {
|
|
|
22724
22819
|
if (rootPackage?.workspaces)
|
|
22725
22820
|
markers.push("package.json#workspaces");
|
|
22726
22821
|
for (const marker of ["pnpm-workspace.yaml", "turbo.json", "nx.json", "lerna.json", "rush.json", "bun.lock", "bun.lockb"]) {
|
|
22727
|
-
if (
|
|
22822
|
+
if (existsSync9(resolve9(root, marker)))
|
|
22728
22823
|
markers.push(marker);
|
|
22729
22824
|
}
|
|
22730
22825
|
const kind = markers.find((marker) => marker !== "bun.lock" && marker !== "bun.lockb") ?? null;
|
|
@@ -23037,7 +23132,7 @@ var init_tags = __esm(() => {
|
|
|
23037
23132
|
});
|
|
23038
23133
|
|
|
23039
23134
|
// src/lib/retention-cleanup.ts
|
|
23040
|
-
import { existsSync as
|
|
23135
|
+
import { existsSync as existsSync10, unlinkSync } from "fs";
|
|
23041
23136
|
function normalizeScopes(scopes) {
|
|
23042
23137
|
if (!scopes || scopes.length === 0)
|
|
23043
23138
|
return [...ALL_SCOPES];
|
|
@@ -23240,7 +23335,7 @@ function applyRetentionCleanup(input, db) {
|
|
|
23240
23335
|
for (const artifact of report.candidates.artifact_files) {
|
|
23241
23336
|
try {
|
|
23242
23337
|
const path = artifactStorePath(artifact.relative_path);
|
|
23243
|
-
if (!
|
|
23338
|
+
if (!existsSync10(path)) {
|
|
23244
23339
|
report.warnings.push(`stored artifact already missing: ${artifact.relative_path}`);
|
|
23245
23340
|
continue;
|
|
23246
23341
|
}
|
|
@@ -23267,8 +23362,8 @@ var init_retention_cleanup = __esm(() => {
|
|
|
23267
23362
|
});
|
|
23268
23363
|
|
|
23269
23364
|
// src/lib/mention-resolver.ts
|
|
23270
|
-
import { existsSync as
|
|
23271
|
-
import { basename as basename3, isAbsolute, join as
|
|
23365
|
+
import { existsSync as existsSync11, readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
|
|
23366
|
+
import { basename as basename3, isAbsolute, join as join9, relative as relative3, resolve as resolve10, sep as sep2 } from "path";
|
|
23272
23367
|
function blankResolution(parsed) {
|
|
23273
23368
|
return {
|
|
23274
23369
|
input: parsed.input,
|
|
@@ -23291,7 +23386,7 @@ function backlink(kind, key, label, target = key) {
|
|
|
23291
23386
|
return { kind, key, label, target };
|
|
23292
23387
|
}
|
|
23293
23388
|
function normalizeWorkspace(workspace) {
|
|
23294
|
-
return
|
|
23389
|
+
return resolve10(workspace || process.cwd());
|
|
23295
23390
|
}
|
|
23296
23391
|
function isInside(root, absolutePath) {
|
|
23297
23392
|
const rel = relative3(root, absolutePath);
|
|
@@ -23359,14 +23454,14 @@ function resolveFile(parsed, workspace) {
|
|
|
23359
23454
|
resolution.warnings.push("path is empty or escapes the workspace");
|
|
23360
23455
|
return resolution;
|
|
23361
23456
|
}
|
|
23362
|
-
const absolutePath =
|
|
23457
|
+
const absolutePath = resolve10(workspace, relPath);
|
|
23363
23458
|
if (!isInside(workspace, absolutePath)) {
|
|
23364
23459
|
resolution.path = relPath;
|
|
23365
23460
|
resolution.warnings.push("path escapes the workspace");
|
|
23366
23461
|
return resolution;
|
|
23367
23462
|
}
|
|
23368
23463
|
resolution.path = relPath;
|
|
23369
|
-
if (!
|
|
23464
|
+
if (!existsSync11(absolutePath)) {
|
|
23370
23465
|
resolution.warnings.push("file does not exist in the local workspace");
|
|
23371
23466
|
return resolution;
|
|
23372
23467
|
}
|
|
@@ -23399,7 +23494,7 @@ function walkSourceFiles(root, current = root, files = []) {
|
|
|
23399
23494
|
if (SKIP_DIRS.has(entry.name))
|
|
23400
23495
|
continue;
|
|
23401
23496
|
}
|
|
23402
|
-
const absolutePath =
|
|
23497
|
+
const absolutePath = join9(current, entry.name);
|
|
23403
23498
|
if (entry.isDirectory()) {
|
|
23404
23499
|
if (!SKIP_DIRS.has(entry.name))
|
|
23405
23500
|
walkSourceFiles(root, absolutePath, files);
|
|
@@ -23704,9 +23799,9 @@ var init_mention_resolver = __esm(() => {
|
|
|
23704
23799
|
});
|
|
23705
23800
|
|
|
23706
23801
|
// src/lib/policy-packs.ts
|
|
23707
|
-
import { relative as relative4, resolve as
|
|
23802
|
+
import { relative as relative4, resolve as resolve11 } from "path";
|
|
23708
23803
|
function normalizePath3(path) {
|
|
23709
|
-
return
|
|
23804
|
+
return resolve11(path);
|
|
23710
23805
|
}
|
|
23711
23806
|
function unique4(values) {
|
|
23712
23807
|
return Array.from(new Set((values || []).map((value) => value.trim()).filter(Boolean)));
|
|
@@ -23761,7 +23856,7 @@ function commandMatches(commands, pattern) {
|
|
|
23761
23856
|
}
|
|
23762
23857
|
function pathMatches(paths, pattern, root) {
|
|
23763
23858
|
return paths.filter((path) => {
|
|
23764
|
-
const candidate = path.startsWith("/") ? path :
|
|
23859
|
+
const candidate = path.startsWith("/") ? path : resolve11(root, path);
|
|
23765
23860
|
if (!isPathInside3(root, candidate))
|
|
23766
23861
|
return matchesPattern3(path, pattern);
|
|
23767
23862
|
return matchesPattern3(path, pattern) || matchesPattern3(relative4(root, candidate), pattern);
|
|
@@ -27140,7 +27235,7 @@ var init_audit_ledger = __esm(() => {
|
|
|
27140
27235
|
|
|
27141
27236
|
// src/lib/release-compatibility.ts
|
|
27142
27237
|
import { readFileSync as readFileSync7 } from "fs";
|
|
27143
|
-
import { join as
|
|
27238
|
+
import { join as join10, resolve as resolve12 } from "path";
|
|
27144
27239
|
import { Database as Database2 } from "bun:sqlite";
|
|
27145
27240
|
function pass(id, message, details) {
|
|
27146
27241
|
return { id, status: "passed", message, details };
|
|
@@ -27152,7 +27247,7 @@ function warn(id, message, details) {
|
|
|
27152
27247
|
return { id, status: "warning", message, details };
|
|
27153
27248
|
}
|
|
27154
27249
|
function readPackageJson2(root) {
|
|
27155
|
-
return JSON.parse(readFileSync7(
|
|
27250
|
+
return JSON.parse(readFileSync7(join10(root, "package.json"), "utf8"));
|
|
27156
27251
|
}
|
|
27157
27252
|
function sortedKeys(value) {
|
|
27158
27253
|
return Object.keys(value ?? {}).sort((left, right) => left.localeCompare(right));
|
|
@@ -27248,7 +27343,7 @@ function checkChangelog() {
|
|
|
27248
27343
|
];
|
|
27249
27344
|
}
|
|
27250
27345
|
function createReleaseCompatibilityReport(options = {}) {
|
|
27251
|
-
const root =
|
|
27346
|
+
const root = resolve12(options.root ?? process.cwd());
|
|
27252
27347
|
const packageJson = readPackageJson2(root);
|
|
27253
27348
|
const simulatedLevels = options.simulated_levels ?? defaultSimulationLevels();
|
|
27254
27349
|
const checks = [
|
|
@@ -31170,8 +31265,8 @@ var exports_doctor = {};
|
|
|
31170
31265
|
__export(exports_doctor, {
|
|
31171
31266
|
runTodosDoctor: () => runTodosDoctor
|
|
31172
31267
|
});
|
|
31173
|
-
import { chmodSync, copyFileSync, existsSync as
|
|
31174
|
-
import { basename as basename4, dirname as dirname6, join as
|
|
31268
|
+
import { chmodSync, copyFileSync, existsSync as existsSync12, mkdirSync as mkdirSync5, statSync as statSync5 } from "fs";
|
|
31269
|
+
import { basename as basename4, dirname as dirname6, join as join11 } from "path";
|
|
31175
31270
|
function tableExists2(db, table) {
|
|
31176
31271
|
return Boolean(db.query("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(table));
|
|
31177
31272
|
}
|
|
@@ -31265,7 +31360,7 @@ function findMissingProjectRoots(db) {
|
|
|
31265
31360
|
continue;
|
|
31266
31361
|
if (!row.path.startsWith("/"))
|
|
31267
31362
|
continue;
|
|
31268
|
-
if (!
|
|
31363
|
+
if (!existsSync12(row.path))
|
|
31269
31364
|
missing++;
|
|
31270
31365
|
}
|
|
31271
31366
|
return missing;
|
|
@@ -31325,16 +31420,16 @@ function databasePermissionsAreUnsafe(dbPath) {
|
|
|
31325
31420
|
function createBackup(dbPath) {
|
|
31326
31421
|
if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
|
|
31327
31422
|
return;
|
|
31328
|
-
if (!
|
|
31423
|
+
if (!existsSync12(dbPath))
|
|
31329
31424
|
return;
|
|
31330
31425
|
const stamp = now().replace(/[:.]/g, "-");
|
|
31331
|
-
const backupDir =
|
|
31426
|
+
const backupDir = join11(dirname6(dbPath), `${basename4(dbPath)}.backup-${stamp}`);
|
|
31332
31427
|
const files = [];
|
|
31333
31428
|
mkdirSync5(backupDir, { recursive: true });
|
|
31334
31429
|
for (const source of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
|
|
31335
|
-
if (!
|
|
31430
|
+
if (!existsSync12(source))
|
|
31336
31431
|
continue;
|
|
31337
|
-
const target =
|
|
31432
|
+
const target = join11(backupDir, basename4(source));
|
|
31338
31433
|
copyFileSync(source, target);
|
|
31339
31434
|
files.push(target);
|
|
31340
31435
|
}
|
|
@@ -34095,7 +34190,7 @@ var init_agent_run_dispatcher = __esm(() => {
|
|
|
34095
34190
|
});
|
|
34096
34191
|
|
|
34097
34192
|
// src/lib/verification-providers.ts
|
|
34098
|
-
import { existsSync as
|
|
34193
|
+
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
34099
34194
|
function normalizeName5(name) {
|
|
34100
34195
|
const normalized = name.trim().toLowerCase();
|
|
34101
34196
|
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(normalized)) {
|
|
@@ -34192,7 +34287,7 @@ function classifyLog(text) {
|
|
|
34192
34287
|
async function sleep2(ms) {
|
|
34193
34288
|
if (ms <= 0)
|
|
34194
34289
|
return;
|
|
34195
|
-
await new Promise((
|
|
34290
|
+
await new Promise((resolve13) => setTimeout(resolve13, ms));
|
|
34196
34291
|
}
|
|
34197
34292
|
async function runCommandProvider(provider, input) {
|
|
34198
34293
|
const commandTemplate = input.command || provider.command;
|
|
@@ -34247,7 +34342,7 @@ Timed out after ${provider.timeout_ms}ms`);
|
|
|
34247
34342
|
};
|
|
34248
34343
|
}
|
|
34249
34344
|
function runCiLogProvider(input) {
|
|
34250
|
-
const text = input.log_text ?? (input.log_path &&
|
|
34345
|
+
const text = input.log_text ?? (input.log_path && existsSync13(input.log_path) ? readFileSync8(input.log_path, "utf-8") : "");
|
|
34251
34346
|
return {
|
|
34252
34347
|
status: classifyLog(text),
|
|
34253
34348
|
attempts: 1,
|
|
@@ -34259,7 +34354,7 @@ function runBrowserProvider(input) {
|
|
|
34259
34354
|
if (!input.artifact_path) {
|
|
34260
34355
|
return { status: "unknown", attempts: 1, exit_code: null, output_summary: "browser provider needs a screenshot or artifact path" };
|
|
34261
34356
|
}
|
|
34262
|
-
if (!
|
|
34357
|
+
if (!existsSync13(input.artifact_path)) {
|
|
34263
34358
|
return { status: "failed", attempts: 1, exit_code: null, output_summary: `artifact not found: ${input.artifact_path}` };
|
|
34264
34359
|
}
|
|
34265
34360
|
return {
|
|
@@ -36417,7 +36512,7 @@ var package_default;
|
|
|
36417
36512
|
var init_package = __esm(() => {
|
|
36418
36513
|
package_default = {
|
|
36419
36514
|
name: "@hasna/todos",
|
|
36420
|
-
version: "0.15.
|
|
36515
|
+
version: "0.15.51",
|
|
36421
36516
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
36422
36517
|
type: "module",
|
|
36423
36518
|
main: "dist/index.js",
|
|
@@ -36476,6 +36571,7 @@ var init_package = __esm(() => {
|
|
|
36476
36571
|
files: [
|
|
36477
36572
|
"dist",
|
|
36478
36573
|
"dashboard/dist",
|
|
36574
|
+
"postinstall.js",
|
|
36479
36575
|
"LICENSE",
|
|
36480
36576
|
"README.md"
|
|
36481
36577
|
],
|
|
@@ -36502,7 +36598,7 @@ var init_package = __esm(() => {
|
|
|
36502
36598
|
"test:attested-container-compatibility-vector": "bun test scripts/attested-container-compatibility-vector.test.ts",
|
|
36503
36599
|
"issue:release-review": "bun run scripts/issue-npm-release-agent-review.ts",
|
|
36504
36600
|
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
36505
|
-
postinstall: "
|
|
36601
|
+
postinstall: "node postinstall.js"
|
|
36506
36602
|
},
|
|
36507
36603
|
keywords: [
|
|
36508
36604
|
"todos",
|
|
@@ -36536,13 +36632,15 @@ var init_package = __esm(() => {
|
|
|
36536
36632
|
author: "Andrei Hasna <andrei@hasna.com>",
|
|
36537
36633
|
license: "Apache-2.0",
|
|
36538
36634
|
dependencies: {
|
|
36539
|
-
"@hasna/contracts": "0.14.
|
|
36635
|
+
"@hasna/contracts": "0.14.2",
|
|
36540
36636
|
"@hasna/events": "^0.1.11",
|
|
36637
|
+
"@hasna/paths": "0.1.0",
|
|
36541
36638
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
36542
36639
|
chalk: "^5.4.1",
|
|
36543
36640
|
commander: "^13.1.0",
|
|
36544
36641
|
ink: "^5.2.0",
|
|
36545
36642
|
react: "^18.3.1",
|
|
36643
|
+
"signal-exit": "3.0.7",
|
|
36546
36644
|
zod: "3.25.76"
|
|
36547
36645
|
},
|
|
36548
36646
|
overrides: {
|
|
@@ -37149,7 +37247,7 @@ var init_local_bridge = __esm(() => {
|
|
|
37149
37247
|
// src/lib/local-backups.ts
|
|
37150
37248
|
import { createHash as createHash7 } from "crypto";
|
|
37151
37249
|
import { readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "fs";
|
|
37152
|
-
import { dirname as dirname7, resolve as
|
|
37250
|
+
import { dirname as dirname7, resolve as resolve13 } from "path";
|
|
37153
37251
|
import { mkdirSync as mkdirSync6 } from "fs";
|
|
37154
37252
|
function stableJson2(value) {
|
|
37155
37253
|
if (value === null || typeof value !== "object")
|
|
@@ -37251,14 +37349,14 @@ function createLocalBackup(options = {}, db) {
|
|
|
37251
37349
|
return backup;
|
|
37252
37350
|
}
|
|
37253
37351
|
function writeLocalBackupFile(backup, outputPath) {
|
|
37254
|
-
const path =
|
|
37352
|
+
const path = resolve13(outputPath);
|
|
37255
37353
|
mkdirSync6(dirname7(path), { recursive: true });
|
|
37256
37354
|
writeFileSync3(path, `${JSON.stringify(backup, null, 2)}
|
|
37257
37355
|
`);
|
|
37258
37356
|
return path;
|
|
37259
37357
|
}
|
|
37260
37358
|
function readLocalBackupFile(path) {
|
|
37261
|
-
return JSON.parse(readFileSync9(
|
|
37359
|
+
return JSON.parse(readFileSync9(resolve13(path), "utf-8"));
|
|
37262
37360
|
}
|
|
37263
37361
|
function verifyLocalBackup(value, options = {}, db) {
|
|
37264
37362
|
const verifiedAt = options.verified_at ?? now();
|
|
@@ -38710,8 +38808,8 @@ __export(exports_local_extensions, {
|
|
|
38710
38808
|
discoverLocalExtensions: () => discoverLocalExtensions
|
|
38711
38809
|
});
|
|
38712
38810
|
import { createHash as createHash10, createVerify } from "crypto";
|
|
38713
|
-
import { existsSync as
|
|
38714
|
-
import { basename as basename5, join as
|
|
38811
|
+
import { existsSync as existsSync14, readdirSync as readdirSync3, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
|
|
38812
|
+
import { basename as basename5, join as join12, resolve as resolve14 } from "path";
|
|
38715
38813
|
function isObject2(value) {
|
|
38716
38814
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
38717
38815
|
}
|
|
@@ -38969,11 +39067,11 @@ function verifyExtensionSignature(input) {
|
|
|
38969
39067
|
return verifier.verify(input.public_key, decodeSignature(input.signature));
|
|
38970
39068
|
}
|
|
38971
39069
|
function inspectExtensionSource(source3) {
|
|
38972
|
-
const resolved =
|
|
38973
|
-
if (!
|
|
39070
|
+
const resolved = resolve14(source3);
|
|
39071
|
+
if (!existsSync14(resolved))
|
|
38974
39072
|
throw new Error(`extension source not found: ${source3}`);
|
|
38975
39073
|
const stat = statSync6(resolved);
|
|
38976
|
-
const manifestPath = stat.isDirectory() ? [
|
|
39074
|
+
const manifestPath = stat.isDirectory() ? [join12(resolved, "todos.extension.json"), join12(resolved, "extension.json")].find(existsSync14) : resolved;
|
|
38977
39075
|
if (!manifestPath)
|
|
38978
39076
|
throw new Error(`extension directory ${source3} is missing todos.extension.json`);
|
|
38979
39077
|
const raw = readFileSync10(manifestPath);
|
|
@@ -39067,26 +39165,26 @@ function testExtensionCompatibility(sourceOrManifest) {
|
|
|
39067
39165
|
function projectExtensionSources(projectPath) {
|
|
39068
39166
|
if (!projectPath)
|
|
39069
39167
|
return [];
|
|
39070
|
-
const root =
|
|
39168
|
+
const root = resolve14(projectPath);
|
|
39071
39169
|
const candidates = [
|
|
39072
|
-
|
|
39073
|
-
|
|
39170
|
+
join12(root, "todos.extension.json"),
|
|
39171
|
+
join12(root, ".todos", "todos.extension.json")
|
|
39074
39172
|
];
|
|
39075
|
-
const extensionDir =
|
|
39076
|
-
if (
|
|
39173
|
+
const extensionDir = join12(root, ".todos", "extensions");
|
|
39174
|
+
if (existsSync14(extensionDir)) {
|
|
39077
39175
|
for (const entry of readdirSync3(extensionDir)) {
|
|
39078
39176
|
if (entry.startsWith("."))
|
|
39079
39177
|
continue;
|
|
39080
|
-
const full =
|
|
39178
|
+
const full = join12(extensionDir, entry);
|
|
39081
39179
|
if (statSync6(full).isDirectory() || entry.endsWith(".json"))
|
|
39082
39180
|
candidates.push(full);
|
|
39083
39181
|
}
|
|
39084
39182
|
}
|
|
39085
|
-
return candidates.filter(
|
|
39183
|
+
return candidates.filter(existsSync14);
|
|
39086
39184
|
}
|
|
39087
39185
|
function discoverLocalExtensions(options = {}) {
|
|
39088
39186
|
const config = loadConfig();
|
|
39089
|
-
const projectPath = options.project_path ?
|
|
39187
|
+
const projectPath = options.project_path ? resolve14(options.project_path) : null;
|
|
39090
39188
|
const configuredSources = [
|
|
39091
39189
|
...config.extension_sources || [],
|
|
39092
39190
|
...projectPath ? config.project_overrides?.[projectPath]?.extension_sources || [] : []
|
|
@@ -39094,7 +39192,7 @@ function discoverLocalExtensions(options = {}) {
|
|
|
39094
39192
|
const sources = Array.from(new Set([
|
|
39095
39193
|
...configuredSources,
|
|
39096
39194
|
...projectExtensionSources(projectPath || undefined)
|
|
39097
|
-
])).map((source3) => projectPath && !source3.startsWith("/") ?
|
|
39195
|
+
])).map((source3) => projectPath && !source3.startsWith("/") ? resolve14(projectPath, source3) : resolve14(source3));
|
|
39098
39196
|
const warnings = [];
|
|
39099
39197
|
const discovered = [];
|
|
39100
39198
|
for (const source3 of sources) {
|
|
@@ -43489,9 +43587,9 @@ __export(exports_extract, {
|
|
|
43489
43587
|
buildCodebaseIndex: () => buildCodebaseIndex,
|
|
43490
43588
|
EXTRACT_TAGS: () => EXTRACT_TAGS
|
|
43491
43589
|
});
|
|
43492
|
-
import { existsSync as
|
|
43590
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11, statSync as statSync7 } from "fs";
|
|
43493
43591
|
import { createHash as createHash12 } from "crypto";
|
|
43494
|
-
import { relative as relative5, resolve as
|
|
43592
|
+
import { relative as relative5, resolve as resolve15, join as join13 } from "path";
|
|
43495
43593
|
function stableHash(value) {
|
|
43496
43594
|
return createHash12("sha256").update(value).digest("hex");
|
|
43497
43595
|
}
|
|
@@ -43499,9 +43597,9 @@ function normalizePathForMatch(value) {
|
|
|
43499
43597
|
return value.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
43500
43598
|
}
|
|
43501
43599
|
function readGitignorePatterns(basePath) {
|
|
43502
|
-
const root = statSync7(basePath).isFile() ?
|
|
43503
|
-
const gitignorePath =
|
|
43504
|
-
if (!
|
|
43600
|
+
const root = statSync7(basePath).isFile() ? resolve15(basePath, "..") : basePath;
|
|
43601
|
+
const gitignorePath = join13(root, ".gitignore");
|
|
43602
|
+
if (!existsSync15(gitignorePath))
|
|
43505
43603
|
return [];
|
|
43506
43604
|
try {
|
|
43507
43605
|
return readFileSync11(gitignorePath, "utf-8").split(`
|
|
@@ -43635,7 +43733,7 @@ function collectFiles(basePath, extensions, excludes, respectGitignore) {
|
|
|
43635
43733
|
return files.sort();
|
|
43636
43734
|
}
|
|
43637
43735
|
function buildCodebaseIndex(options) {
|
|
43638
|
-
const basePath =
|
|
43736
|
+
const basePath = resolve15(options.path);
|
|
43639
43737
|
const tags = options.patterns || [...EXTRACT_TAGS];
|
|
43640
43738
|
const extensions = options.extensions ? new Set(options.extensions.map((e) => e.startsWith(".") ? e : `.${e}`)) : DEFAULT_EXTENSIONS;
|
|
43641
43739
|
const excludes = options.exclude || [];
|
|
@@ -43643,10 +43741,10 @@ function buildCodebaseIndex(options) {
|
|
|
43643
43741
|
const files = collectFiles(basePath, extensions, excludes, respectGitignore);
|
|
43644
43742
|
const indexed = [];
|
|
43645
43743
|
for (const file of files) {
|
|
43646
|
-
const fullPath = statSync7(basePath).isFile() ? basePath :
|
|
43744
|
+
const fullPath = statSync7(basePath).isFile() ? basePath : join13(basePath, file);
|
|
43647
43745
|
try {
|
|
43648
43746
|
const source3 = readFileSync11(fullPath, "utf-8");
|
|
43649
|
-
const relPath = statSync7(basePath).isFile() ? relative5(
|
|
43747
|
+
const relPath = statSync7(basePath).isFile() ? relative5(resolve15(basePath, ".."), fullPath) : file;
|
|
43650
43748
|
indexed.push({
|
|
43651
43749
|
file: relPath,
|
|
43652
43750
|
checksum: stableHash(source3).slice(0, 24),
|
|
@@ -43666,7 +43764,7 @@ function buildCodebaseIndex(options) {
|
|
|
43666
43764
|
};
|
|
43667
43765
|
}
|
|
43668
43766
|
function extractTodos(options, db) {
|
|
43669
|
-
const basePath =
|
|
43767
|
+
const basePath = resolve15(options.path);
|
|
43670
43768
|
const tags = options.patterns || [...EXTRACT_TAGS];
|
|
43671
43769
|
const extensions = options.extensions ? new Set(options.extensions.map((e) => e.startsWith(".") ? e : `.${e}`)) : DEFAULT_EXTENSIONS;
|
|
43672
43770
|
const excludes = options.exclude || [];
|
|
@@ -43674,10 +43772,10 @@ function extractTodos(options, db) {
|
|
|
43674
43772
|
const files = collectFiles(basePath, extensions, excludes, respectGitignore);
|
|
43675
43773
|
const allComments = [];
|
|
43676
43774
|
for (const file of files) {
|
|
43677
|
-
const fullPath = statSync7(basePath).isFile() ? basePath :
|
|
43775
|
+
const fullPath = statSync7(basePath).isFile() ? basePath : join13(basePath, file);
|
|
43678
43776
|
try {
|
|
43679
43777
|
const source3 = readFileSync11(fullPath, "utf-8");
|
|
43680
|
-
const relPath = statSync7(basePath).isFile() ? relative5(
|
|
43778
|
+
const relPath = statSync7(basePath).isFile() ? relative5(resolve15(basePath, ".."), fullPath) : file;
|
|
43681
43779
|
const comments = extractFromSource(source3, relPath, tags);
|
|
43682
43780
|
allComments.push(...comments);
|
|
43683
43781
|
} catch {}
|
|
@@ -43771,7 +43869,7 @@ async function watchSourceTodos(options, onRun) {
|
|
|
43771
43869
|
const interval = Math.max(100, options.interval_ms || 2000);
|
|
43772
43870
|
const once = options.once !== false && (!options.max_runs || options.max_runs <= 1);
|
|
43773
43871
|
const maxRuns = options.max_runs ?? (once ? 1 : Number.POSITIVE_INFINITY);
|
|
43774
|
-
const root =
|
|
43872
|
+
const root = resolve15(options.path);
|
|
43775
43873
|
const runs = [];
|
|
43776
43874
|
let previous = new Map;
|
|
43777
43875
|
for (let runNumber = 1;runNumber <= maxRuns; runNumber++) {
|
|
@@ -44330,7 +44428,7 @@ Last seen: ${agent.last_seen_at}`
|
|
|
44330
44428
|
`Suggested names: ${suggestions.slice(0, 8).join(", ")}`,
|
|
44331
44429
|
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.",
|
|
44332
44430
|
`
|
|
44333
|
-
To restrict names, configure agent_pool or project_pools in
|
|
44431
|
+
To restrict names, configure agent_pool or project_pools in the todos data home config file (default <data home>/config.json)`
|
|
44334
44432
|
];
|
|
44335
44433
|
return { content: [{ type: "text", text: lines2.join(`
|
|
44336
44434
|
`) }] };
|
|
@@ -44633,7 +44731,7 @@ __export(exports_builtin_templates, {
|
|
|
44633
44731
|
BUILTIN_TEMPLATES: () => BUILTIN_TEMPLATES
|
|
44634
44732
|
});
|
|
44635
44733
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
44636
|
-
import { join as
|
|
44734
|
+
import { join as join14 } from "path";
|
|
44637
44735
|
function templateMetadata(template) {
|
|
44638
44736
|
return {
|
|
44639
44737
|
source: BUILTIN_TEMPLATE_LIBRARY_SOURCE,
|
|
@@ -44692,7 +44790,7 @@ function writeBuiltinTemplateFiles(directory) {
|
|
|
44692
44790
|
mkdirSync7(directory, { recursive: true });
|
|
44693
44791
|
const files = [];
|
|
44694
44792
|
for (const entry of exportBuiltinTemplateFiles()) {
|
|
44695
|
-
const path =
|
|
44793
|
+
const path = join14(directory, entry.filename);
|
|
44696
44794
|
writeFileSync4(path, `${JSON.stringify(entry.template, null, 2)}
|
|
44697
44795
|
`, "utf-8");
|
|
44698
44796
|
files.push(path);
|
|
@@ -45218,16 +45316,16 @@ __export(exports_environment_snapshots, {
|
|
|
45218
45316
|
captureEnvironmentSnapshot: () => captureEnvironmentSnapshot
|
|
45219
45317
|
});
|
|
45220
45318
|
import { createHash as createHash13 } from "crypto";
|
|
45221
|
-
import { existsSync as
|
|
45319
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12, statSync as statSync8 } from "fs";
|
|
45222
45320
|
import { hostname as hostname2, platform, arch } from "os";
|
|
45223
|
-
import { dirname as dirname8, join as
|
|
45321
|
+
import { dirname as dirname8, join as join15, resolve as resolve16 } from "path";
|
|
45224
45322
|
import { tmpdir as tmpdir3 } from "os";
|
|
45225
45323
|
function sha2567(value) {
|
|
45226
45324
|
return createHash13("sha256").update(value).digest("hex");
|
|
45227
45325
|
}
|
|
45228
45326
|
function fileRecord(root, relativePath) {
|
|
45229
|
-
const path =
|
|
45230
|
-
if (!
|
|
45327
|
+
const path = join15(root, relativePath);
|
|
45328
|
+
if (!existsSync16(path))
|
|
45231
45329
|
return null;
|
|
45232
45330
|
const stat = statSync8(path);
|
|
45233
45331
|
if (!stat.isFile())
|
|
@@ -45239,7 +45337,7 @@ function manifestRecord(root, relativePath) {
|
|
|
45239
45337
|
const base = fileRecord(root, relativePath);
|
|
45240
45338
|
if (!base)
|
|
45241
45339
|
return null;
|
|
45242
|
-
const parsed = readJsonFile(
|
|
45340
|
+
const parsed = readJsonFile(join15(root, relativePath));
|
|
45243
45341
|
if (!parsed)
|
|
45244
45342
|
return { ...base, redacted: {} };
|
|
45245
45343
|
const redacted = redactValue({
|
|
@@ -45334,15 +45432,15 @@ function commandEnv(env, includeValues) {
|
|
|
45334
45432
|
function defaultSnapshotDir() {
|
|
45335
45433
|
const dbPath = getDatabasePath();
|
|
45336
45434
|
if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
|
|
45337
|
-
return
|
|
45338
|
-
return
|
|
45435
|
+
return join15(tmpdir3(), "hasna-todos", "environment-snapshots");
|
|
45436
|
+
return join15(dirname8(resolve16(dbPath)), "environment-snapshots");
|
|
45339
45437
|
}
|
|
45340
45438
|
function snapshotWithId(snapshot) {
|
|
45341
45439
|
const digest = sha2567(JSON.stringify(snapshot)).slice(0, 24);
|
|
45342
45440
|
return { id: `env_${digest}`, ...snapshot };
|
|
45343
45441
|
}
|
|
45344
45442
|
function captureEnvironmentSnapshot(input = {}) {
|
|
45345
|
-
const root =
|
|
45443
|
+
const root = resolve16(input.root || process.cwd());
|
|
45346
45444
|
const env = input.env || process.env;
|
|
45347
45445
|
const warnings = [];
|
|
45348
45446
|
const manifests = MANIFEST_FILES.map((file) => manifestRecord(root, file)).filter((file) => Boolean(file));
|
|
@@ -45382,13 +45480,13 @@ function captureEnvironmentSnapshot(input = {}) {
|
|
|
45382
45480
|
});
|
|
45383
45481
|
}
|
|
45384
45482
|
function writeEnvironmentSnapshot(snapshot, outputPath) {
|
|
45385
|
-
const path = outputPath ?
|
|
45483
|
+
const path = outputPath ? resolve16(outputPath) : join15(defaultSnapshotDir(), `${snapshot.id}.json`);
|
|
45386
45484
|
ensureDir(dirname8(path));
|
|
45387
45485
|
writeJsonFile(path, snapshot);
|
|
45388
45486
|
return path;
|
|
45389
45487
|
}
|
|
45390
45488
|
function readEnvironmentSnapshot(path) {
|
|
45391
|
-
const snapshot = readJsonFile(
|
|
45489
|
+
const snapshot = readJsonFile(resolve16(path));
|
|
45392
45490
|
if (!snapshot || snapshot.schema_version !== 1 || typeof snapshot.id !== "string") {
|
|
45393
45491
|
throw new Error(`Invalid environment snapshot: ${path}`);
|
|
45394
45492
|
}
|
|
@@ -47360,7 +47458,7 @@ class TodosShadowOutbox {
|
|
|
47360
47458
|
const remaining = deadline - Date.now();
|
|
47361
47459
|
if (remaining <= 0)
|
|
47362
47460
|
break;
|
|
47363
|
-
await new Promise((
|
|
47461
|
+
await new Promise((resolve17) => setTimeout(resolve17, Math.min(200, remaining)));
|
|
47364
47462
|
}
|
|
47365
47463
|
}
|
|
47366
47464
|
return this.getStats();
|
|
@@ -50213,7 +50311,7 @@ async function retryOnTransientPostgresError(fn, attempts = 2, delayMs = 150) {
|
|
|
50213
50311
|
lastError = error;
|
|
50214
50312
|
if (!isTransientPostgresError(error) || attempt === attempts)
|
|
50215
50313
|
throw error;
|
|
50216
|
-
await new Promise((
|
|
50314
|
+
await new Promise((resolve17) => setTimeout(resolve17, delayMs * attempt));
|
|
50217
50315
|
}
|
|
50218
50316
|
}
|
|
50219
50317
|
throw lastError;
|
|
@@ -56648,7 +56746,7 @@ var init_headless_boundaries = __esm(() => {
|
|
|
56648
56746
|
});
|
|
56649
56747
|
|
|
56650
56748
|
// src/server/routes.ts
|
|
56651
|
-
import { join as
|
|
56749
|
+
import { join as join16, resolve as resolve17, sep as sep3 } from "path";
|
|
56652
56750
|
function parseFieldsParam(url) {
|
|
56653
56751
|
const fieldsParam = url.searchParams.get("fields");
|
|
56654
56752
|
return fieldsParam ? fieldsParam.split(",").map((f) => f.trim()).filter(Boolean) : undefined;
|
|
@@ -57485,9 +57583,9 @@ function handleStaticFiles(path, method, ctx, json5, serveStaticFile2) {
|
|
|
57485
57583
|
if (!ctx.dashboardExists || method !== "GET" && method !== "HEAD")
|
|
57486
57584
|
return null;
|
|
57487
57585
|
if (path !== "/") {
|
|
57488
|
-
const filePath =
|
|
57489
|
-
const resolvedFile =
|
|
57490
|
-
const resolvedBase =
|
|
57586
|
+
const filePath = join16(ctx.dashboardDir, path);
|
|
57587
|
+
const resolvedFile = resolve17(filePath);
|
|
57588
|
+
const resolvedBase = resolve17(ctx.dashboardDir);
|
|
57491
57589
|
if (!resolvedFile.startsWith(resolvedBase + sep3) && resolvedFile !== resolvedBase) {
|
|
57492
57590
|
return json5({ error: "Forbidden" }, 403);
|
|
57493
57591
|
}
|
|
@@ -57495,7 +57593,7 @@ function handleStaticFiles(path, method, ctx, json5, serveStaticFile2) {
|
|
|
57495
57593
|
if (res2)
|
|
57496
57594
|
return res2;
|
|
57497
57595
|
}
|
|
57498
|
-
const indexPath =
|
|
57596
|
+
const indexPath = join16(ctx.dashboardDir, "index.html");
|
|
57499
57597
|
const res = serveStaticFile2(indexPath);
|
|
57500
57598
|
if (res)
|
|
57501
57599
|
return res;
|
|
@@ -63476,8 +63574,8 @@ class SqlitePrGroupLedgerPersistence {
|
|
|
63476
63574
|
async transaction(fn) {
|
|
63477
63575
|
const previous = sqliteTransactionTails2.get(this.db) ?? Promise.resolve();
|
|
63478
63576
|
let release;
|
|
63479
|
-
const current = new Promise((
|
|
63480
|
-
release =
|
|
63577
|
+
const current = new Promise((resolve18) => {
|
|
63578
|
+
release = resolve18;
|
|
63481
63579
|
});
|
|
63482
63580
|
sqliteTransactionTails2.set(this.db, current);
|
|
63483
63581
|
await previous;
|
|
@@ -63575,27 +63673,27 @@ __export(exports_serve, {
|
|
|
63575
63673
|
SECURITY_HEADERS: () => SECURITY_HEADERS,
|
|
63576
63674
|
MIME_TYPES: () => MIME_TYPES
|
|
63577
63675
|
});
|
|
63578
|
-
import { existsSync as
|
|
63579
|
-
import { join as
|
|
63676
|
+
import { existsSync as existsSync17 } from "fs";
|
|
63677
|
+
import { join as join17, dirname as dirname9, extname } from "path";
|
|
63580
63678
|
import { fileURLToPath } from "url";
|
|
63581
63679
|
function resolveDashboardDir() {
|
|
63582
63680
|
const candidates = [];
|
|
63583
63681
|
try {
|
|
63584
63682
|
const scriptDir = dirname9(fileURLToPath(import.meta.url));
|
|
63585
|
-
candidates.push(
|
|
63586
|
-
candidates.push(
|
|
63683
|
+
candidates.push(join17(scriptDir, "..", "dashboard", "dist"));
|
|
63684
|
+
candidates.push(join17(scriptDir, "..", "..", "dashboard", "dist"));
|
|
63587
63685
|
} catch {}
|
|
63588
63686
|
if (process.argv[1]) {
|
|
63589
63687
|
const mainDir = dirname9(process.argv[1]);
|
|
63590
|
-
candidates.push(
|
|
63591
|
-
candidates.push(
|
|
63688
|
+
candidates.push(join17(mainDir, "..", "dashboard", "dist"));
|
|
63689
|
+
candidates.push(join17(mainDir, "..", "..", "dashboard", "dist"));
|
|
63592
63690
|
}
|
|
63593
|
-
candidates.push(
|
|
63691
|
+
candidates.push(join17(process.cwd(), "dashboard", "dist"));
|
|
63594
63692
|
for (const candidate of candidates) {
|
|
63595
|
-
if (
|
|
63693
|
+
if (existsSync17(candidate))
|
|
63596
63694
|
return candidate;
|
|
63597
63695
|
}
|
|
63598
|
-
return
|
|
63696
|
+
return join17(process.cwd(), "dashboard", "dist");
|
|
63599
63697
|
}
|
|
63600
63698
|
function getProvidedApiKey(req) {
|
|
63601
63699
|
const headerKey = req.headers.get("x-api-key");
|
|
@@ -63667,7 +63765,7 @@ function json4(data, status3 = 200, headers) {
|
|
|
63667
63765
|
});
|
|
63668
63766
|
}
|
|
63669
63767
|
function serveStaticFile(filePath) {
|
|
63670
|
-
if (!
|
|
63768
|
+
if (!existsSync17(filePath))
|
|
63671
63769
|
return null;
|
|
63672
63770
|
const ext = extname(filePath);
|
|
63673
63771
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
@@ -63768,7 +63866,7 @@ data: ${data}
|
|
|
63768
63866
|
filteredSseClients.delete(client);
|
|
63769
63867
|
}
|
|
63770
63868
|
const dashboardDir = resolveDashboardDir();
|
|
63771
|
-
const dashboardExists =
|
|
63869
|
+
const dashboardExists = existsSync17(dashboardDir);
|
|
63772
63870
|
if (!dashboardExists) {
|
|
63773
63871
|
console.error(`
|
|
63774
63872
|
Dashboard not found at: ${dashboardDir}`);
|