@hasna/todos 0.11.90 → 0.11.93
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/README.md +7 -2
- package/dist/cli/cloud-router.d.ts +67 -25
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/agent-commands.d.ts.map +1 -1
- package/dist/cli/commands/plan-template-commands.d.ts.map +1 -1
- package/dist/cli/commands/project-commands.d.ts.map +1 -1
- package/dist/cli/commands/query-commands.d.ts.map +1 -1
- package/dist/cli/commands/storage-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/helpers.d.ts +15 -1
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/index.js +19499 -30656
- package/dist/cli/output-redaction.d.ts +5 -0
- package/dist/cli/output-redaction.d.ts.map +1 -0
- package/dist/cli/stage-a.d.ts +45 -0
- package/dist/cli/stage-a.d.ts.map +1 -0
- package/dist/contracts.js +196 -97
- package/dist/index.js +571 -314
- package/dist/lib/package-version.d.ts +1 -1
- package/dist/lib/package-version.d.ts.map +1 -1
- package/dist/lib/redaction.d.ts.map +1 -1
- package/dist/lib/tmux.d.ts.map +1 -1
- package/dist/mcp/index.js +922 -6847
- package/dist/mcp.js +118 -20
- package/dist/registry.js +196 -97
- package/dist/release-provenance.json +5 -3
- package/dist/sdk/index.js +37 -2
- package/dist/sdk/v1.generated.d.ts +72 -3
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/cloud.d.ts +10 -0
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +2305 -8137
- package/dist/server/openapi.d.ts +366 -2
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/interfaces.d.ts +10 -0
- package/dist/storage/interfaces.d.ts.map +1 -1
- package/dist/storage/local-sqlite.d.ts.map +1 -1
- package/dist/storage/postgres-adapter.d.ts.map +1 -1
- package/dist/storage/postgres-sync.d.ts +22 -0
- package/dist/storage/postgres-sync.d.ts.map +1 -1
- package/dist/storage.js +166 -15
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +9 -6
package/dist/registry.js
CHANGED
|
@@ -2427,7 +2427,7 @@ var init_schema = __esm(() => {
|
|
|
2427
2427
|
});
|
|
2428
2428
|
|
|
2429
2429
|
// src/db/machines.ts
|
|
2430
|
-
import { existsSync
|
|
2430
|
+
import { existsSync } from "fs";
|
|
2431
2431
|
import { hostname as osHostname, platform as osPlatform, arch as osArch } from "os";
|
|
2432
2432
|
import { resolve } from "path";
|
|
2433
2433
|
import { spawnSync } from "child_process";
|
|
@@ -2637,7 +2637,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
|
|
|
2637
2637
|
message: `${project.name} has ${distinctPaths.length} different machine-local paths`
|
|
2638
2638
|
});
|
|
2639
2639
|
}
|
|
2640
|
-
if (localRow && !
|
|
2640
|
+
if (localRow && !existsSync(localRow.path)) {
|
|
2641
2641
|
pathIssues.push({
|
|
2642
2642
|
type: "path_missing",
|
|
2643
2643
|
project_id: project.id,
|
|
@@ -2648,7 +2648,7 @@ function getMachineTopologyDiagnostics(opts = {}, db, at = new Date) {
|
|
|
2648
2648
|
message: `Local path does not exist on this machine: ${localRow.path}`
|
|
2649
2649
|
});
|
|
2650
2650
|
}
|
|
2651
|
-
if (!localRow && project.path && machineById.has(localMachine.id) && !
|
|
2651
|
+
if (!localRow && project.path && machineById.has(localMachine.id) && !existsSync(project.path)) {
|
|
2652
2652
|
pathIssues.push({
|
|
2653
2653
|
type: "path_missing",
|
|
2654
2654
|
project_id: project.id,
|
|
@@ -3036,8 +3036,8 @@ __export(exports_database, {
|
|
|
3036
3036
|
LOCK_EXPIRY_MINUTES: () => LOCK_EXPIRY_MINUTES
|
|
3037
3037
|
});
|
|
3038
3038
|
import { Database } from "bun:sqlite";
|
|
3039
|
-
import { existsSync as
|
|
3040
|
-
import { dirname
|
|
3039
|
+
import { existsSync as existsSync2, mkdirSync } from "fs";
|
|
3040
|
+
import { dirname, join, resolve as resolve2 } from "path";
|
|
3041
3041
|
function isInMemoryDb(path) {
|
|
3042
3042
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
3043
3043
|
}
|
|
@@ -3046,12 +3046,12 @@ function findNearestProjectDb(startDir) {
|
|
|
3046
3046
|
const stopAt = gitRoot ? resolve2(gitRoot) : resolve2(startDir);
|
|
3047
3047
|
let dir = resolve2(startDir);
|
|
3048
3048
|
while (true) {
|
|
3049
|
-
const candidate =
|
|
3050
|
-
if (
|
|
3049
|
+
const candidate = join(dir, ".hasna", "todos", "todos.db");
|
|
3050
|
+
if (existsSync2(candidate))
|
|
3051
3051
|
return candidate;
|
|
3052
3052
|
if (dir === stopAt)
|
|
3053
3053
|
break;
|
|
3054
|
-
const parent =
|
|
3054
|
+
const parent = dirname(dir);
|
|
3055
3055
|
if (parent === dir)
|
|
3056
3056
|
break;
|
|
3057
3057
|
dir = parent;
|
|
@@ -3061,9 +3061,9 @@ function findNearestProjectDb(startDir) {
|
|
|
3061
3061
|
function findGitRoot(startDir) {
|
|
3062
3062
|
let dir = resolve2(startDir);
|
|
3063
3063
|
while (true) {
|
|
3064
|
-
if (
|
|
3064
|
+
if (existsSync2(join(dir, ".git")))
|
|
3065
3065
|
return dir;
|
|
3066
|
-
const parent =
|
|
3066
|
+
const parent = dirname(dir);
|
|
3067
3067
|
if (parent === dir)
|
|
3068
3068
|
break;
|
|
3069
3069
|
dir = parent;
|
|
@@ -3084,11 +3084,11 @@ function getDbPath() {
|
|
|
3084
3084
|
if (process.env["TODOS_DB_SCOPE"] === "project") {
|
|
3085
3085
|
const gitRoot = findGitRoot(cwd);
|
|
3086
3086
|
if (gitRoot) {
|
|
3087
|
-
return
|
|
3087
|
+
return join(gitRoot, ".hasna", "todos", "todos.db");
|
|
3088
3088
|
}
|
|
3089
3089
|
}
|
|
3090
3090
|
const home = process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
3091
|
-
return
|
|
3091
|
+
return join(home, ".hasna", "todos", "todos.db");
|
|
3092
3092
|
}
|
|
3093
3093
|
function getDatabasePath() {
|
|
3094
3094
|
return getDbPath();
|
|
@@ -3096,8 +3096,8 @@ function getDatabasePath() {
|
|
|
3096
3096
|
function ensureDir(filePath) {
|
|
3097
3097
|
if (isInMemoryDb(filePath))
|
|
3098
3098
|
return;
|
|
3099
|
-
const dir =
|
|
3100
|
-
if (!
|
|
3099
|
+
const dir = dirname(resolve2(filePath));
|
|
3100
|
+
if (!existsSync2(dir)) {
|
|
3101
3101
|
mkdirSync(dir, { recursive: true });
|
|
3102
3102
|
}
|
|
3103
3103
|
}
|
|
@@ -3368,26 +3368,26 @@ var init_types = __esm(() => {
|
|
|
3368
3368
|
});
|
|
3369
3369
|
|
|
3370
3370
|
// src/lib/sync-utils.ts
|
|
3371
|
-
import { existsSync as
|
|
3372
|
-
import { join as
|
|
3371
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
3372
|
+
import { join as join2 } from "path";
|
|
3373
3373
|
function getHomeDir() {
|
|
3374
3374
|
return process.env["HOME"] || process.env["USERPROFILE"] || "~";
|
|
3375
3375
|
}
|
|
3376
3376
|
function getTodosGlobalDir() {
|
|
3377
|
-
return
|
|
3377
|
+
return join2(getHomeDir(), ".hasna", "todos");
|
|
3378
3378
|
}
|
|
3379
3379
|
function ensureDir2(dir) {
|
|
3380
|
-
if (!
|
|
3380
|
+
if (!existsSync3(dir))
|
|
3381
3381
|
mkdirSync2(dir, { recursive: true });
|
|
3382
3382
|
}
|
|
3383
3383
|
function listJsonFiles(dir) {
|
|
3384
|
-
if (!
|
|
3384
|
+
if (!existsSync3(dir))
|
|
3385
3385
|
return [];
|
|
3386
3386
|
return readdirSync(dir).filter((f) => f.endsWith(".json"));
|
|
3387
3387
|
}
|
|
3388
3388
|
function readJsonFile(path) {
|
|
3389
3389
|
try {
|
|
3390
|
-
return JSON.parse(
|
|
3390
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
3391
3391
|
} catch {
|
|
3392
3392
|
return null;
|
|
3393
3393
|
}
|
|
@@ -3397,14 +3397,14 @@ function writeJsonFile(path, data) {
|
|
|
3397
3397
|
`);
|
|
3398
3398
|
}
|
|
3399
3399
|
function readHighWaterMark(dir) {
|
|
3400
|
-
const path =
|
|
3401
|
-
if (!
|
|
3400
|
+
const path = join2(dir, ".highwatermark");
|
|
3401
|
+
if (!existsSync3(path))
|
|
3402
3402
|
return 1;
|
|
3403
|
-
const val = parseInt(
|
|
3403
|
+
const val = parseInt(readFileSync(path, "utf-8").trim(), 10);
|
|
3404
3404
|
return isNaN(val) ? 1 : val;
|
|
3405
3405
|
}
|
|
3406
3406
|
function writeHighWaterMark(dir, value) {
|
|
3407
|
-
writeFileSync(
|
|
3407
|
+
writeFileSync(join2(dir, ".highwatermark"), String(value));
|
|
3408
3408
|
}
|
|
3409
3409
|
function getFileMtimeMs(path) {
|
|
3410
3410
|
try {
|
|
@@ -3430,10 +3430,10 @@ var init_sync_utils = __esm(() => {
|
|
|
3430
3430
|
});
|
|
3431
3431
|
|
|
3432
3432
|
// src/lib/config.ts
|
|
3433
|
-
import { existsSync as
|
|
3434
|
-
import { dirname as
|
|
3433
|
+
import { existsSync as existsSync4 } from "fs";
|
|
3434
|
+
import { dirname as dirname2, join as join3 } from "path";
|
|
3435
3435
|
function getConfigPath() {
|
|
3436
|
-
return
|
|
3436
|
+
return join3(getTodosGlobalDir(), "config.json");
|
|
3437
3437
|
}
|
|
3438
3438
|
function normalizeAgent(agent) {
|
|
3439
3439
|
return agent.trim().toLowerCase();
|
|
@@ -3441,7 +3441,7 @@ function normalizeAgent(agent) {
|
|
|
3441
3441
|
function loadConfig() {
|
|
3442
3442
|
if (cached)
|
|
3443
3443
|
return cached;
|
|
3444
|
-
if (!
|
|
3444
|
+
if (!existsSync4(getConfigPath())) {
|
|
3445
3445
|
cached = {};
|
|
3446
3446
|
return cached;
|
|
3447
3447
|
}
|
|
@@ -3454,7 +3454,7 @@ function loadConfig() {
|
|
|
3454
3454
|
}
|
|
3455
3455
|
function saveConfig(config) {
|
|
3456
3456
|
const configPath = getConfigPath();
|
|
3457
|
-
ensureDir2(
|
|
3457
|
+
ensureDir2(dirname2(configPath));
|
|
3458
3458
|
writeJsonFile(configPath, config);
|
|
3459
3459
|
cached = config;
|
|
3460
3460
|
return config;
|
|
@@ -4139,7 +4139,8 @@ var init_redaction = __esm(() => {
|
|
|
4139
4139
|
"input_tokens",
|
|
4140
4140
|
"output_tokens",
|
|
4141
4141
|
"prompt_tokens",
|
|
4142
|
-
"completion_tokens"
|
|
4142
|
+
"completion_tokens",
|
|
4143
|
+
"cost_tokens"
|
|
4143
4144
|
]);
|
|
4144
4145
|
});
|
|
4145
4146
|
|
|
@@ -4523,7 +4524,7 @@ var init_runner_sandbox = __esm(() => {
|
|
|
4523
4524
|
// src/lib/event-hooks.ts
|
|
4524
4525
|
import { createHash, randomUUID } from "crypto";
|
|
4525
4526
|
import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
4526
|
-
import { dirname as
|
|
4527
|
+
import { dirname as dirname3, resolve as resolve6 } from "path";
|
|
4527
4528
|
import { createConnection } from "net";
|
|
4528
4529
|
function safeName(name) {
|
|
4529
4530
|
const trimmed = name.trim();
|
|
@@ -4662,7 +4663,7 @@ async function deliverHook(hook, envelope) {
|
|
|
4662
4663
|
output = line.trim();
|
|
4663
4664
|
} else if (hook.target === "file") {
|
|
4664
4665
|
const filePath = resolve6(hook.file_path);
|
|
4665
|
-
mkdirSync3(
|
|
4666
|
+
mkdirSync3(dirname3(filePath), { recursive: true });
|
|
4666
4667
|
appendFileSync(filePath, line);
|
|
4667
4668
|
} else if (hook.target === "socket") {
|
|
4668
4669
|
await writeSocket(hook.socket_path, line);
|
|
@@ -4781,9 +4782,9 @@ var init_event_hooks = __esm(() => {
|
|
|
4781
4782
|
|
|
4782
4783
|
// node_modules/.bun/@hasna+events@0.1.11/node_modules/@hasna/events/dist/index.js
|
|
4783
4784
|
import { chmod, mkdir, readFile, rename, writeFile } from "fs/promises";
|
|
4784
|
-
import { existsSync as
|
|
4785
|
+
import { existsSync as existsSync5 } from "fs";
|
|
4785
4786
|
import { homedir } from "os";
|
|
4786
|
-
import { join as
|
|
4787
|
+
import { join as join4 } from "path";
|
|
4787
4788
|
import { createHmac, timingSafeEqual } from "crypto";
|
|
4788
4789
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
4789
4790
|
import { spawn } from "child_process";
|
|
@@ -4884,7 +4885,7 @@ function channelMatchesEvent(channel, event) {
|
|
|
4884
4885
|
return channel.filters.some((filter) => eventMatchesFilter(event, filter));
|
|
4885
4886
|
}
|
|
4886
4887
|
function getEventsDataDir(override) {
|
|
4887
|
-
return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] ||
|
|
4888
|
+
return override || process.env[HASNA_EVENTS_DIR_ENV] || process.env[HASNA_EVENTS_HOME_ENV] || join4(homedir(), ".hasna", "events");
|
|
4888
4889
|
}
|
|
4889
4890
|
|
|
4890
4891
|
class JsonEventsStore {
|
|
@@ -4894,9 +4895,9 @@ class JsonEventsStore {
|
|
|
4894
4895
|
deliveriesPath;
|
|
4895
4896
|
constructor(dataDir = getEventsDataDir()) {
|
|
4896
4897
|
this.dataDir = dataDir;
|
|
4897
|
-
this.channelsPath =
|
|
4898
|
-
this.eventsPath =
|
|
4899
|
-
this.deliveriesPath =
|
|
4898
|
+
this.channelsPath = join4(dataDir, "channels.json");
|
|
4899
|
+
this.eventsPath = join4(dataDir, "events.json");
|
|
4900
|
+
this.deliveriesPath = join4(dataDir, "deliveries.json");
|
|
4900
4901
|
}
|
|
4901
4902
|
async init() {
|
|
4902
4903
|
await mkdir(this.dataDir, { recursive: true, mode: 448 });
|
|
@@ -4968,7 +4969,7 @@ class JsonEventsStore {
|
|
|
4968
4969
|
};
|
|
4969
4970
|
}
|
|
4970
4971
|
async ensureArrayFile(path) {
|
|
4971
|
-
if (!
|
|
4972
|
+
if (!existsSync5(path)) {
|
|
4972
4973
|
await writeFile(path, `[]
|
|
4973
4974
|
`, { encoding: "utf-8", mode: 384 });
|
|
4974
4975
|
}
|
|
@@ -5741,7 +5742,7 @@ var init_shared_events = __esm(() => {
|
|
|
5741
5742
|
});
|
|
5742
5743
|
|
|
5743
5744
|
// src/lib/secret-redaction.ts
|
|
5744
|
-
import { readFileSync as
|
|
5745
|
+
import { readFileSync as readFileSync2, existsSync as existsSync6 } from "fs";
|
|
5745
5746
|
function registerCustomRedactor(fn) {
|
|
5746
5747
|
customRedactors.push(fn);
|
|
5747
5748
|
}
|
|
@@ -5806,9 +5807,9 @@ function scanAndRedactText(text, options = {}) {
|
|
|
5806
5807
|
};
|
|
5807
5808
|
}
|
|
5808
5809
|
function scanFileForSecrets(path, options = {}) {
|
|
5809
|
-
if (!
|
|
5810
|
+
if (!existsSync6(path))
|
|
5810
5811
|
throw new Error(`File not found: ${path}`);
|
|
5811
|
-
const content =
|
|
5812
|
+
const content = readFileSync2(path, "utf8");
|
|
5812
5813
|
return scanAndRedactText(content, options);
|
|
5813
5814
|
}
|
|
5814
5815
|
function safeStringify(value, space) {
|
|
@@ -9334,8 +9335,8 @@ var init_boards = __esm(() => {
|
|
|
9334
9335
|
|
|
9335
9336
|
// src/lib/artifact-store.ts
|
|
9336
9337
|
import { createHash as createHash2 } from "crypto";
|
|
9337
|
-
import { existsSync as
|
|
9338
|
-
import { basename, dirname as
|
|
9338
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync3, rmSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
9339
|
+
import { basename, dirname as dirname4, join as join5, resolve as resolve7 } from "path";
|
|
9339
9340
|
import { tmpdir as tmpdir2 } from "os";
|
|
9340
9341
|
function isInMemoryDb2(path) {
|
|
9341
9342
|
return path === ":memory:" || path.startsWith("file::memory:");
|
|
@@ -9347,15 +9348,15 @@ function artifactStoreRoot() {
|
|
|
9347
9348
|
return resolve7(process.env["TODOS_ARTIFACTS_DIR"]);
|
|
9348
9349
|
const dbPath = getDatabasePath();
|
|
9349
9350
|
if (isInMemoryDb2(dbPath))
|
|
9350
|
-
return
|
|
9351
|
-
return
|
|
9351
|
+
return join5(tmpdir2(), "hasna-todos-artifacts");
|
|
9352
|
+
return join5(dirname4(resolve7(dbPath)), "artifacts");
|
|
9352
9353
|
}
|
|
9353
9354
|
function artifactStorePath(relativePath) {
|
|
9354
9355
|
const normalized = relativePath.replace(/\\/g, "/");
|
|
9355
9356
|
if (normalized.includes("..") || normalized.startsWith("/") || normalized.length === 0) {
|
|
9356
9357
|
throw new Error("Invalid artifact store path");
|
|
9357
9358
|
}
|
|
9358
|
-
return
|
|
9359
|
+
return join5(artifactStoreRoot(), normalized);
|
|
9359
9360
|
}
|
|
9360
9361
|
function sha256(buffer) {
|
|
9361
9362
|
return createHash2("sha256").update(buffer).digest("hex");
|
|
@@ -9396,12 +9397,12 @@ function mediaTypeFor(path, textLike) {
|
|
|
9396
9397
|
}
|
|
9397
9398
|
function storeArtifactContent(input) {
|
|
9398
9399
|
const sourcePath = resolve7(input.path);
|
|
9399
|
-
if (!
|
|
9400
|
+
if (!existsSync7(sourcePath))
|
|
9400
9401
|
return null;
|
|
9401
9402
|
const sourceStat = statSync2(sourcePath);
|
|
9402
9403
|
if (!sourceStat.isFile())
|
|
9403
9404
|
throw new Error(`Artifact path is not a file: ${input.path}`);
|
|
9404
|
-
const sourceBuffer =
|
|
9405
|
+
const sourceBuffer = readFileSync3(sourcePath);
|
|
9405
9406
|
const sourceSha = sha256(sourceBuffer);
|
|
9406
9407
|
const textLike = isTextLike(sourceBuffer, input.path);
|
|
9407
9408
|
let storedBuffer = sourceBuffer;
|
|
@@ -9413,10 +9414,10 @@ function storeArtifactContent(input) {
|
|
|
9413
9414
|
redactionStatus = "redacted";
|
|
9414
9415
|
}
|
|
9415
9416
|
const storedSha = sha256(storedBuffer);
|
|
9416
|
-
const relativePath =
|
|
9417
|
+
const relativePath = join5("sha256", storedSha.slice(0, 2), storedSha).replace(/\\/g, "/");
|
|
9417
9418
|
const destination = artifactStorePath(relativePath);
|
|
9418
|
-
if (!
|
|
9419
|
-
mkdirSync4(
|
|
9419
|
+
if (!existsSync7(destination)) {
|
|
9420
|
+
mkdirSync4(dirname4(destination), { recursive: true });
|
|
9420
9421
|
writeFileSync2(destination, storedBuffer);
|
|
9421
9422
|
}
|
|
9422
9423
|
const createdAt = input.created_at || new Date().toISOString();
|
|
@@ -9475,7 +9476,7 @@ function verifyStoredArtifact(input) {
|
|
|
9475
9476
|
};
|
|
9476
9477
|
}
|
|
9477
9478
|
const storedPath = artifactStorePath(store.relative_path);
|
|
9478
|
-
if (!
|
|
9479
|
+
if (!existsSync7(storedPath)) {
|
|
9479
9480
|
return {
|
|
9480
9481
|
id: input.id,
|
|
9481
9482
|
path: input.path,
|
|
@@ -9488,7 +9489,7 @@ function verifyStoredArtifact(input) {
|
|
|
9488
9489
|
message: "stored artifact content is missing"
|
|
9489
9490
|
};
|
|
9490
9491
|
}
|
|
9491
|
-
const buffer =
|
|
9492
|
+
const buffer = readFileSync3(storedPath);
|
|
9492
9493
|
const actualSha = sha256(buffer);
|
|
9493
9494
|
const actualSize = buffer.length;
|
|
9494
9495
|
const ok = actualSha === store.sha256 && actualSize === store.size_bytes;
|
|
@@ -9508,7 +9509,7 @@ function exportStoredArtifactContent(input) {
|
|
|
9508
9509
|
const report = verifyStoredArtifact(input);
|
|
9509
9510
|
if (report.status !== "ok" || !report.relative_path || !report.actual_sha256 || report.actual_size_bytes === null)
|
|
9510
9511
|
return null;
|
|
9511
|
-
const content =
|
|
9512
|
+
const content = readFileSync3(artifactStorePath(report.relative_path));
|
|
9512
9513
|
return {
|
|
9513
9514
|
artifact_id: input.id,
|
|
9514
9515
|
sha256: report.actual_sha256,
|
|
@@ -9534,7 +9535,7 @@ function importStoredArtifactContent(content) {
|
|
|
9534
9535
|
};
|
|
9535
9536
|
}
|
|
9536
9537
|
const destination = artifactStorePath(content.relative_path);
|
|
9537
|
-
mkdirSync4(
|
|
9538
|
+
mkdirSync4(dirname4(destination), { recursive: true });
|
|
9538
9539
|
writeFileSync2(destination, buffer);
|
|
9539
9540
|
return {
|
|
9540
9541
|
id: content.artifact_id,
|
|
@@ -9555,29 +9556,29 @@ function getArtifactStoreRoot(dbPath) {
|
|
|
9555
9556
|
return resolve7(process.env["TODOS_ARTIFACTS_DIR"]);
|
|
9556
9557
|
const path = dbPath ?? getDatabasePath();
|
|
9557
9558
|
if (isInMemoryDb2(path))
|
|
9558
|
-
return
|
|
9559
|
-
return
|
|
9559
|
+
return join5(tmpdir2(), "hasna-todos-artifacts");
|
|
9560
|
+
return join5(dirname4(resolve7(path)), "artifacts");
|
|
9560
9561
|
}
|
|
9561
9562
|
function computeContentHash(path) {
|
|
9562
|
-
return sha256(
|
|
9563
|
+
return sha256(readFileSync3(resolve7(path)));
|
|
9563
9564
|
}
|
|
9564
9565
|
function storeArtifactFile(input) {
|
|
9565
9566
|
const sourcePath = resolve7(input.sourcePath);
|
|
9566
|
-
if (!
|
|
9567
|
+
if (!existsSync7(sourcePath)) {
|
|
9567
9568
|
throw new Error(`Source file not found: ${input.sourcePath}`);
|
|
9568
9569
|
}
|
|
9569
9570
|
if (!statSync2(sourcePath).isFile()) {
|
|
9570
9571
|
throw new Error(`Source path is not a file: ${input.sourcePath}`);
|
|
9571
9572
|
}
|
|
9572
|
-
const buffer =
|
|
9573
|
+
const buffer = readFileSync3(sourcePath);
|
|
9573
9574
|
const contentHash = sha256(buffer);
|
|
9574
9575
|
const mimeType = mediaTypeFor(sourcePath, isTextLike(buffer, sourcePath));
|
|
9575
9576
|
const storageMode = input.storageMode ?? "copy";
|
|
9576
9577
|
let localPath = sourcePath;
|
|
9577
9578
|
if (storageMode === "copy") {
|
|
9578
9579
|
const fileName = input.name && input.name.trim().length > 0 ? basename(input.name) : basename(sourcePath);
|
|
9579
|
-
const destination =
|
|
9580
|
-
mkdirSync4(
|
|
9580
|
+
const destination = join5(getArtifactStoreRoot(input.dbPath), input.artifactId, fileName);
|
|
9581
|
+
mkdirSync4(dirname4(destination), { recursive: true });
|
|
9581
9582
|
writeFileSync2(destination, buffer);
|
|
9582
9583
|
localPath = destination;
|
|
9583
9584
|
}
|
|
@@ -9586,11 +9587,11 @@ function storeArtifactFile(input) {
|
|
|
9586
9587
|
function deleteStoredArtifactFile(localPath, storageMode, _dbPath2) {
|
|
9587
9588
|
if (storageMode === "reference")
|
|
9588
9589
|
return false;
|
|
9589
|
-
if (!localPath || !
|
|
9590
|
+
if (!localPath || !existsSync7(localPath))
|
|
9590
9591
|
return false;
|
|
9591
9592
|
rmSync(localPath, { force: true });
|
|
9592
9593
|
try {
|
|
9593
|
-
rmSync(
|
|
9594
|
+
rmSync(dirname4(localPath), { recursive: false });
|
|
9594
9595
|
} catch {}
|
|
9595
9596
|
return true;
|
|
9596
9597
|
}
|
|
@@ -9612,7 +9613,7 @@ function buildArtifactExportManifest(artifacts, dbPath) {
|
|
|
9612
9613
|
}
|
|
9613
9614
|
function writeArtifactExportManifest(manifest, outputPath) {
|
|
9614
9615
|
const destination = resolve7(outputPath);
|
|
9615
|
-
mkdirSync4(
|
|
9616
|
+
mkdirSync4(dirname4(destination), { recursive: true });
|
|
9616
9617
|
writeFileSync2(destination, `${JSON.stringify(manifest, null, 2)}
|
|
9617
9618
|
`);
|
|
9618
9619
|
return destination;
|
|
@@ -10752,28 +10753,126 @@ var init_tasks = __esm(() => {
|
|
|
10752
10753
|
init_boards();
|
|
10753
10754
|
init_calendar();
|
|
10754
10755
|
});
|
|
10755
|
-
|
|
10756
|
-
|
|
10757
|
-
|
|
10758
|
-
|
|
10759
|
-
|
|
10760
|
-
|
|
10761
|
-
|
|
10762
|
-
|
|
10763
|
-
|
|
10764
|
-
|
|
10765
|
-
|
|
10766
|
-
|
|
10767
|
-
|
|
10768
|
-
|
|
10769
|
-
|
|
10770
|
-
|
|
10771
|
-
|
|
10756
|
+
// package.json
|
|
10757
|
+
var package_default = {
|
|
10758
|
+
name: "@hasna/todos",
|
|
10759
|
+
version: "0.11.93",
|
|
10760
|
+
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
10761
|
+
type: "module",
|
|
10762
|
+
main: "dist/index.js",
|
|
10763
|
+
types: "dist/index.d.ts",
|
|
10764
|
+
bin: {
|
|
10765
|
+
todos: "dist/cli/index.js",
|
|
10766
|
+
"todos-mcp": "dist/mcp/index.js",
|
|
10767
|
+
"todos-serve": "dist/server/index.js"
|
|
10768
|
+
},
|
|
10769
|
+
exports: {
|
|
10770
|
+
".": {
|
|
10771
|
+
types: "./dist/index.d.ts",
|
|
10772
|
+
import: "./dist/index.js"
|
|
10773
|
+
},
|
|
10774
|
+
"./sdk": {
|
|
10775
|
+
types: "./dist/sdk/index.d.ts",
|
|
10776
|
+
import: "./dist/sdk/index.js"
|
|
10777
|
+
},
|
|
10778
|
+
"./mcp": {
|
|
10779
|
+
types: "./dist/mcp.d.ts",
|
|
10780
|
+
import: "./dist/mcp.js"
|
|
10781
|
+
},
|
|
10782
|
+
"./registry": {
|
|
10783
|
+
types: "./dist/registry.d.ts",
|
|
10784
|
+
import: "./dist/registry.js"
|
|
10785
|
+
},
|
|
10786
|
+
"./contracts": {
|
|
10787
|
+
types: "./dist/contracts.d.ts",
|
|
10788
|
+
import: "./dist/contracts.js"
|
|
10789
|
+
},
|
|
10790
|
+
"./storage": {
|
|
10791
|
+
types: "./dist/storage.d.ts",
|
|
10792
|
+
import: "./dist/storage.js"
|
|
10772
10793
|
}
|
|
10773
|
-
}
|
|
10774
|
-
|
|
10794
|
+
},
|
|
10795
|
+
workspaces: [
|
|
10796
|
+
"dashboard"
|
|
10797
|
+
],
|
|
10798
|
+
files: [
|
|
10799
|
+
"dist",
|
|
10800
|
+
"dashboard/dist",
|
|
10801
|
+
"LICENSE",
|
|
10802
|
+
"README.md"
|
|
10803
|
+
],
|
|
10804
|
+
scripts: {
|
|
10805
|
+
build: "rm -rf dist dashboard/dist && cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && tsc --emitDeclarationOnly --outDir dist",
|
|
10806
|
+
"build:server": "rm -rf dist && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*'",
|
|
10807
|
+
migrate: "bun run src/server/index.ts migrate",
|
|
10808
|
+
"backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
|
|
10809
|
+
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
10810
|
+
"build:dashboard": "cd dashboard && bun install --frozen-lockfile && bun run build",
|
|
10811
|
+
typecheck: "tsc --noEmit",
|
|
10812
|
+
test: "bun test",
|
|
10813
|
+
"test:no-cloud": "bun test src/no-cloud-boundary.test.ts src/local-first.test.ts src/lib/public-release-gate.test.ts",
|
|
10814
|
+
"dev:cli": "bun run src/cli/index.tsx",
|
|
10815
|
+
"dev:mcp": "bun run src/mcp/index.ts",
|
|
10816
|
+
"dev:serve": "bun run src/server/index.ts",
|
|
10817
|
+
"verify:release": "bun run scripts/verify-public-release.ts --mode=review",
|
|
10818
|
+
prepublishOnly: "bun run scripts/verify-public-release.ts --mode=publish",
|
|
10819
|
+
postinstall: "mkdir -p $HOME/.hasna/todos $HOME/.hasna/todos/training 2>/dev/null || true"
|
|
10820
|
+
},
|
|
10821
|
+
keywords: [
|
|
10822
|
+
"todos",
|
|
10823
|
+
"tasks",
|
|
10824
|
+
"mcp",
|
|
10825
|
+
"ai",
|
|
10826
|
+
"coding-agent",
|
|
10827
|
+
"claude",
|
|
10828
|
+
"codex",
|
|
10829
|
+
"gemini",
|
|
10830
|
+
"tui",
|
|
10831
|
+
"cli",
|
|
10832
|
+
"dashboard"
|
|
10833
|
+
],
|
|
10834
|
+
publishConfig: {
|
|
10835
|
+
registry: "https://registry.npmjs.org",
|
|
10836
|
+
access: "public"
|
|
10837
|
+
},
|
|
10838
|
+
repository: {
|
|
10839
|
+
type: "git",
|
|
10840
|
+
url: "https://github.com/hasna/todos.git"
|
|
10841
|
+
},
|
|
10842
|
+
homepage: "https://github.com/hasna/todos",
|
|
10843
|
+
bugs: {
|
|
10844
|
+
url: "https://github.com/hasna/todos/issues"
|
|
10845
|
+
},
|
|
10846
|
+
engines: {
|
|
10847
|
+
bun: ">=1.0.0"
|
|
10848
|
+
},
|
|
10849
|
+
packageManager: "bun@1.3.14",
|
|
10850
|
+
author: "Andrei Hasna <andrei@hasna.com>",
|
|
10851
|
+
license: "Apache-2.0",
|
|
10852
|
+
dependencies: {
|
|
10853
|
+
"@hasna/contracts": "0.5.2",
|
|
10854
|
+
"@hasna/events": "^0.1.11",
|
|
10855
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
10856
|
+
chalk: "^5.4.1",
|
|
10857
|
+
commander: "^13.1.0",
|
|
10858
|
+
ink: "^5.2.0",
|
|
10859
|
+
react: "^18.3.1",
|
|
10860
|
+
zod: "^3.24.2"
|
|
10861
|
+
},
|
|
10862
|
+
overrides: {
|
|
10863
|
+
"fast-uri": "3.1.2"
|
|
10864
|
+
},
|
|
10865
|
+
devDependencies: {
|
|
10866
|
+
"@types/bun": "^1.2.4",
|
|
10867
|
+
"@types/react": "^18.3.18",
|
|
10868
|
+
"bun-types": "1.3.9",
|
|
10869
|
+
typescript: "^5.7.3"
|
|
10775
10870
|
}
|
|
10776
|
-
|
|
10871
|
+
};
|
|
10872
|
+
|
|
10873
|
+
// src/lib/package-version.ts
|
|
10874
|
+
function getPackageVersion(_fromUrl = import.meta.url) {
|
|
10875
|
+
return package_default.version || "0.0.0";
|
|
10777
10876
|
}
|
|
10778
10877
|
|
|
10779
10878
|
// src/mcp/token-utils.ts
|
|
@@ -13360,7 +13459,7 @@ var TODOS_JSON_CONTRACTS_MANIFEST = createJsonContractsManifest({
|
|
|
13360
13459
|
});
|
|
13361
13460
|
// src/lib/onboarding-fixtures.ts
|
|
13362
13461
|
import { mkdirSync as mkdirSync5, writeFileSync as writeFileSync3 } from "fs";
|
|
13363
|
-
import { join as
|
|
13462
|
+
import { join as join6 } from "path";
|
|
13364
13463
|
|
|
13365
13464
|
// src/lib/local-bridge.ts
|
|
13366
13465
|
init_database();
|
|
@@ -14267,7 +14366,7 @@ function writeOnboardingFixtureFiles(directory) {
|
|
|
14267
14366
|
mkdirSync5(directory, { recursive: true });
|
|
14268
14367
|
const files = [];
|
|
14269
14368
|
for (const fixture of allFixtures()) {
|
|
14270
|
-
const path =
|
|
14369
|
+
const path = join6(directory, `${fixture.summary.name}.bridge.json`);
|
|
14271
14370
|
writeFileSync3(path, `${JSON.stringify(fixture.bundle, null, 2)}
|
|
14272
14371
|
`, "utf-8");
|
|
14273
14372
|
files.push(path);
|
|
@@ -14284,8 +14383,8 @@ function importOnboardingFixture(options = {}) {
|
|
|
14284
14383
|
// src/lib/local-backups.ts
|
|
14285
14384
|
init_database();
|
|
14286
14385
|
import { createHash as createHash3 } from "crypto";
|
|
14287
|
-
import { readFileSync as
|
|
14288
|
-
import { dirname as
|
|
14386
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
14387
|
+
import { dirname as dirname5, resolve as resolve8 } from "path";
|
|
14289
14388
|
import { mkdirSync as mkdirSync6 } from "fs";
|
|
14290
14389
|
var TODOS_LOCAL_BACKUP_KIND = "hasna.todos.local-backup";
|
|
14291
14390
|
var TODOS_LOCAL_BACKUP_SCHEMA_VERSION = 1;
|
|
@@ -14393,13 +14492,13 @@ function createLocalBackup(options = {}, db) {
|
|
|
14393
14492
|
}
|
|
14394
14493
|
function writeLocalBackupFile(backup, outputPath) {
|
|
14395
14494
|
const path = resolve8(outputPath);
|
|
14396
|
-
mkdirSync6(
|
|
14495
|
+
mkdirSync6(dirname5(path), { recursive: true });
|
|
14397
14496
|
writeFileSync4(path, `${JSON.stringify(backup, null, 2)}
|
|
14398
14497
|
`);
|
|
14399
14498
|
return path;
|
|
14400
14499
|
}
|
|
14401
14500
|
function readLocalBackupFile(path) {
|
|
14402
|
-
return JSON.parse(
|
|
14501
|
+
return JSON.parse(readFileSync4(resolve8(path), "utf-8"));
|
|
14403
14502
|
}
|
|
14404
14503
|
function verifyLocalBackup(value, options = {}, db) {
|
|
14405
14504
|
const verifiedAt = options.verified_at ?? now();
|
|
@@ -15093,7 +15192,7 @@ function renderLocalSnapshotMarkdown(snapshot) {
|
|
|
15093
15192
|
}
|
|
15094
15193
|
// src/lib/sdk-integration-fixtures.ts
|
|
15095
15194
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync5 } from "fs";
|
|
15096
|
-
import { join as
|
|
15195
|
+
import { join as join7 } from "path";
|
|
15097
15196
|
|
|
15098
15197
|
// src/cli-mcp-parity.ts
|
|
15099
15198
|
function source4(version) {
|
|
@@ -17049,7 +17148,7 @@ function writeSdkIntegrationFixtures(directory, options = {}) {
|
|
|
17049
17148
|
];
|
|
17050
17149
|
const written = [];
|
|
17051
17150
|
for (const [name, payload] of files) {
|
|
17052
|
-
const file =
|
|
17151
|
+
const file = join7(directory, name);
|
|
17053
17152
|
writeFileSync5(file, `${JSON.stringify(payload, null, 2)}
|
|
17054
17153
|
`, "utf-8");
|
|
17055
17154
|
written.push(file);
|
|
@@ -18331,8 +18430,8 @@ function renderLocalAuditLedgerMarkdown(ledger) {
|
|
|
18331
18430
|
// src/lib/release-compatibility.ts
|
|
18332
18431
|
init_migrations();
|
|
18333
18432
|
init_schema();
|
|
18334
|
-
import { readFileSync as
|
|
18335
|
-
import { join as
|
|
18433
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
18434
|
+
import { join as join8, resolve as resolve9 } from "path";
|
|
18336
18435
|
import { Database as Database2 } from "bun:sqlite";
|
|
18337
18436
|
var LOCAL_RELEASE_COMPATIBILITY_SCHEMA_VERSION = 1;
|
|
18338
18437
|
var EXPECTED_PACKAGE_NAME = "@hasna/todos";
|
|
@@ -18378,7 +18477,7 @@ function warn(id, message, details) {
|
|
|
18378
18477
|
return { id, status: "warning", message, details };
|
|
18379
18478
|
}
|
|
18380
18479
|
function readPackageJson(root) {
|
|
18381
|
-
return JSON.parse(
|
|
18480
|
+
return JSON.parse(readFileSync5(join8(root, "package.json"), "utf8"));
|
|
18382
18481
|
}
|
|
18383
18482
|
function sortedKeys(value) {
|
|
18384
18483
|
return Object.keys(value ?? {}).sort((left, right) => left.localeCompare(right));
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "@hasna/todos",
|
|
3
|
-
"packageVersion": "0.11.
|
|
3
|
+
"packageVersion": "0.11.93",
|
|
4
4
|
"repository": "https://github.com/hasna/todos.git",
|
|
5
|
-
"gitCommit": "
|
|
6
|
-
"
|
|
5
|
+
"gitCommit": "587429d21e17aa8aef579f268aeb21d936cbd318",
|
|
6
|
+
"gitTree": "66ffc2eae17dcdb8234c9c4f6196eb5a944c4d7e",
|
|
7
|
+
"sourceTreeSha256": "349ea2e0ea68b5176cfbd1b6e1c7f3f9d79706c1bf6cdd17d1436a6a622f26ed",
|
|
8
|
+
"generatedAt": "2026-07-20T06:14:03.000Z"
|
|
7
9
|
}
|