@hasna/todos 0.13.4 → 0.13.6
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/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/agent-commands.d.ts.map +1 -1
- package/dist/cli/commands/mcp-hooks-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +483 -195
- package/dist/cli/stage-a.d.ts +2 -0
- package/dist/cli/stage-a.d.ts.map +1 -1
- package/dist/contracts.js +25 -3
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/index.js +39 -7
- package/dist/lib/creator-identity.d.ts +70 -0
- package/dist/lib/creator-identity.d.ts.map +1 -0
- package/dist/lib/onboarding-fixtures.d.ts.map +1 -1
- package/dist/mcp/index.js +163 -75
- package/dist/mcp/tools/task-crud.d.ts.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/registry.js +25 -3
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +153 -65
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/local-sqlite.d.ts.map +1 -1
- package/dist/storage.js +37 -6
- package/dist/types/index.d.ts +12 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -2497,6 +2497,7 @@ function ensureSchema(db) {
|
|
|
2497
2497
|
ensureColumn("tasks", "reason", "TEXT");
|
|
2498
2498
|
ensureColumn("tasks", "spawned_from_session", "TEXT");
|
|
2499
2499
|
ensureColumn("tasks", "assigned_by", "TEXT");
|
|
2500
|
+
ensureColumn("tasks", "created_by", "TEXT");
|
|
2500
2501
|
ensureColumn("tasks", "assigned_from_project", "TEXT");
|
|
2501
2502
|
ensureColumn("tasks", "started_at", "TEXT");
|
|
2502
2503
|
ensureColumn("tasks", "task_type", "TEXT");
|
|
@@ -2659,6 +2660,8 @@ function ensureSchema(db) {
|
|
|
2659
2660
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_sources_project ON project_sources(project_id)");
|
|
2660
2661
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_project_sources_type ON project_sources(type)");
|
|
2661
2662
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_assigned_by ON tasks(assigned_by)");
|
|
2663
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_created_by ON tasks(created_by)");
|
|
2664
|
+
ensureIndex("CREATE INDEX IF NOT EXISTS idx_tasks_assigned_created ON tasks(assigned_to, created_by)");
|
|
2662
2665
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_rel_source ON task_relationships(source_task_id)");
|
|
2663
2666
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_rel_target ON task_relationships(target_task_id)");
|
|
2664
2667
|
ensureIndex("CREATE INDEX IF NOT EXISTS idx_task_rel_type ON task_relationships(relationship_type)");
|
|
@@ -13413,13 +13416,14 @@ function createTask(input, db) {
|
|
|
13413
13416
|
const timestamp2 = now();
|
|
13414
13417
|
const tags = input.tags || [];
|
|
13415
13418
|
const machineId = currentStorageMachineId(d);
|
|
13419
|
+
const createdBy = input.created_by || input.agent_id || null;
|
|
13416
13420
|
const assignedBy = input.assigned_by || input.agent_id;
|
|
13417
13421
|
const assignedFromProject = input.assigned_from_project || null;
|
|
13418
13422
|
let id = uuid();
|
|
13419
13423
|
for (let attempt = 0;attempt < 3; attempt++) {
|
|
13420
13424
|
try {
|
|
13421
|
-
d.run(`INSERT INTO tasks (id, short_id, project_id, parent_id, plan_id, task_list_id, cycle_id, title, description, status, priority, agent_id, assigned_to, session_id, working_dir, tags, metadata, version, created_at, updated_at, due_at, estimated_minutes, sla_minutes, confidence, retry_count, max_retries, retry_after, requires_approval, approved_by, approved_at, recurrence_rule, recurrence_parent_id, spawns_template_id, reason, spawned_from_session, assigned_by, assigned_from_project, task_type, machine_id)
|
|
13422
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
13425
|
+
d.run(`INSERT INTO tasks (id, short_id, project_id, parent_id, plan_id, task_list_id, cycle_id, title, description, status, priority, agent_id, assigned_to, session_id, working_dir, tags, metadata, version, created_at, updated_at, due_at, estimated_minutes, sla_minutes, confidence, retry_count, max_retries, retry_after, requires_approval, approved_by, approved_at, recurrence_rule, recurrence_parent_id, spawns_template_id, reason, spawned_from_session, assigned_by, created_by, assigned_from_project, task_type, machine_id)
|
|
13426
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
13423
13427
|
id,
|
|
13424
13428
|
null,
|
|
13425
13429
|
input.project_id || null,
|
|
@@ -13455,6 +13459,7 @@ function createTask(input, db) {
|
|
|
13455
13459
|
input.reason || null,
|
|
13456
13460
|
input.spawned_from_session || null,
|
|
13457
13461
|
assignedBy || null,
|
|
13462
|
+
createdBy,
|
|
13458
13463
|
assignedFromProject || null,
|
|
13459
13464
|
input.task_type || null,
|
|
13460
13465
|
machineId
|
|
@@ -13564,6 +13569,14 @@ function listTasks(filter = {}, db) {
|
|
|
13564
13569
|
conditions.push("agent_id = ?");
|
|
13565
13570
|
params.push(filter.agent_id);
|
|
13566
13571
|
}
|
|
13572
|
+
if (filter.created_by) {
|
|
13573
|
+
conditions.push("LOWER(created_by) = LOWER(?)");
|
|
13574
|
+
params.push(filter.created_by);
|
|
13575
|
+
}
|
|
13576
|
+
if (filter.not_created_by) {
|
|
13577
|
+
conditions.push("(created_by IS NULL OR LOWER(created_by) != LOWER(?))");
|
|
13578
|
+
params.push(filter.not_created_by);
|
|
13579
|
+
}
|
|
13567
13580
|
if (filter.session_id) {
|
|
13568
13581
|
conditions.push("session_id = ?");
|
|
13569
13582
|
params.push(filter.session_id);
|
|
@@ -13717,6 +13730,14 @@ function countTasks(filter = {}, db) {
|
|
|
13717
13730
|
conditions.push("agent_id = ?");
|
|
13718
13731
|
params.push(filter.agent_id);
|
|
13719
13732
|
}
|
|
13733
|
+
if (filter.created_by) {
|
|
13734
|
+
conditions.push("LOWER(created_by) = LOWER(?)");
|
|
13735
|
+
params.push(filter.created_by);
|
|
13736
|
+
}
|
|
13737
|
+
if (filter.not_created_by) {
|
|
13738
|
+
conditions.push("(created_by IS NULL OR LOWER(created_by) != LOWER(?))");
|
|
13739
|
+
params.push(filter.not_created_by);
|
|
13740
|
+
}
|
|
13720
13741
|
if (filter.session_id) {
|
|
13721
13742
|
conditions.push("session_id = ?");
|
|
13722
13743
|
params.push(filter.session_id);
|
|
@@ -17844,6 +17865,41 @@ var init_token_utils = __esm(() => {
|
|
|
17844
17865
|
};
|
|
17845
17866
|
});
|
|
17846
17867
|
|
|
17868
|
+
// src/lib/creator-identity.ts
|
|
17869
|
+
import { existsSync as existsSync7, rmSync as rmSync2 } from "fs";
|
|
17870
|
+
import { join as join6 } from "path";
|
|
17871
|
+
function identityFilePath() {
|
|
17872
|
+
return join6(getTodosGlobalDir(), "identity.json");
|
|
17873
|
+
}
|
|
17874
|
+
function readPersistedIdentity() {
|
|
17875
|
+
const path = identityFilePath();
|
|
17876
|
+
if (!existsSync7(path))
|
|
17877
|
+
return null;
|
|
17878
|
+
const parsed = readJsonFile(path);
|
|
17879
|
+
if (!parsed || typeof parsed.agent_id !== "string" || !parsed.agent_id.trim())
|
|
17880
|
+
return null;
|
|
17881
|
+
return parsed;
|
|
17882
|
+
}
|
|
17883
|
+
function canonicalAgentRef(value) {
|
|
17884
|
+
return value.trim().toLowerCase();
|
|
17885
|
+
}
|
|
17886
|
+
function resolveCreatorIdentity(explicit) {
|
|
17887
|
+
const fromExplicit = explicit?.trim();
|
|
17888
|
+
if (fromExplicit)
|
|
17889
|
+
return { agent_id: canonicalAgentRef(fromExplicit), source: "explicit" };
|
|
17890
|
+
const fromEnv = (process.env["TODOS_AGENT_ID"] || process.env["HASNA_TODOS_AGENT_ID"] || "").trim();
|
|
17891
|
+
if (fromEnv)
|
|
17892
|
+
return { agent_id: canonicalAgentRef(fromEnv), source: "env" };
|
|
17893
|
+
const persisted = readPersistedIdentity();
|
|
17894
|
+
if (persisted) {
|
|
17895
|
+
return { agent_id: canonicalAgentRef(persisted.agent_name || persisted.agent_id), source: "persisted" };
|
|
17896
|
+
}
|
|
17897
|
+
return { agent_id: null, source: "none" };
|
|
17898
|
+
}
|
|
17899
|
+
var init_creator_identity = __esm(() => {
|
|
17900
|
+
init_sync_utils();
|
|
17901
|
+
});
|
|
17902
|
+
|
|
17847
17903
|
// src/pr-groups/types.ts
|
|
17848
17904
|
var PR_GROUP_LEDGER_SCHEMA_VERSION = 1, PR_GROUP_REPAIR_CYCLE_LIMIT = 2, PrGroupLedgerError;
|
|
17849
17905
|
var init_types3 = __esm(() => {
|
|
@@ -20594,6 +20650,8 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20594
20650
|
project_id: exports_external.string().optional().describe("Project ID"),
|
|
20595
20651
|
task_list_id: exports_external.string().optional().describe("Task list ID"),
|
|
20596
20652
|
assigned_to: exports_external.string().optional().describe("Agent ID or name to assign to"),
|
|
20653
|
+
created_by: exports_external.string().optional().describe("Agent who FILED this task. Defaults to the ambient agent identity (todos init / TODOS_AGENT_ID)."),
|
|
20654
|
+
unassigned: exports_external.boolean().optional().describe("Deliberately file with no assignee. Without it, the task defaults to the filer."),
|
|
20597
20655
|
depends_on: exports_external.array(exports_external.string()).optional().describe("Array of task IDs this task depends on"),
|
|
20598
20656
|
short_id: exports_external.string().nullable().optional().describe("Short ID (auto-generated if not provided, disabled if null)"),
|
|
20599
20657
|
tags: exports_external.array(exports_external.string()).optional().describe("Tags for the task"),
|
|
@@ -20604,12 +20662,18 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20604
20662
|
retry_count: exports_external.number().optional().describe("Max retry count for agent failures")
|
|
20605
20663
|
}, async (params) => {
|
|
20606
20664
|
try {
|
|
20607
|
-
const { depends_on, assigned_to, project_id, task_list_id, tags, estimate, confidence, retry_count, deadline, ...rest } = params;
|
|
20665
|
+
const { depends_on, assigned_to, project_id, task_list_id, tags, estimate, confidence, retry_count, deadline, created_by, unassigned, ...rest } = params;
|
|
20666
|
+
const creator = resolveCreatorIdentity(created_by);
|
|
20667
|
+
const assignee = assigned_to || (unassigned ? undefined : creator.agent_id || undefined);
|
|
20608
20668
|
const cloud = getTodosCloudClient();
|
|
20609
20669
|
if (cloud) {
|
|
20610
20670
|
const payload = { ...rest };
|
|
20611
|
-
if (
|
|
20612
|
-
payload.
|
|
20671
|
+
if (creator.agent_id) {
|
|
20672
|
+
payload.created_by = creator.agent_id;
|
|
20673
|
+
payload.agent_id = payload.agent_id ?? creator.agent_id;
|
|
20674
|
+
}
|
|
20675
|
+
if (assignee)
|
|
20676
|
+
payload.assigned_to = assignee;
|
|
20613
20677
|
if (project_id)
|
|
20614
20678
|
payload.project_id = project_id;
|
|
20615
20679
|
if (task_list_id)
|
|
@@ -20630,8 +20694,12 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20630
20694
|
return { content: [{ type: "text", text: mutationTaskResponse(created) }] };
|
|
20631
20695
|
}
|
|
20632
20696
|
const resolved = { ...rest };
|
|
20633
|
-
if (
|
|
20634
|
-
resolved.
|
|
20697
|
+
if (creator.agent_id) {
|
|
20698
|
+
resolved.created_by = creator.agent_id;
|
|
20699
|
+
resolved.agent_id = resolved.agent_id ?? creator.agent_id;
|
|
20700
|
+
}
|
|
20701
|
+
if (assignee)
|
|
20702
|
+
resolved.assigned_to = resolveAssignee(assignee);
|
|
20635
20703
|
if (project_id)
|
|
20636
20704
|
resolved.project_id = resolveId(project_id, "projects");
|
|
20637
20705
|
if (task_list_id)
|
|
@@ -20717,6 +20785,8 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20717
20785
|
project_id: exports_external.string().optional().describe("Filter by project"),
|
|
20718
20786
|
task_list_id: exports_external.string().optional().describe("Filter by task list"),
|
|
20719
20787
|
assigned_to: exports_external.string().optional().describe("Filter by assignee (agent ID or name, empty string = unassigned)"),
|
|
20788
|
+
created_by: exports_external.string().optional().describe("Filter by the agent who FILED the task"),
|
|
20789
|
+
not_created_by: exports_external.string().optional().describe('Exclude tasks filed by this agent. With assigned_to=<me> this is the "my inbox, minus my own filings" query.'),
|
|
20720
20790
|
tags: exports_external.array(exports_external.string()).optional().describe("Filter by tags (AND logic)"),
|
|
20721
20791
|
created_after: exports_external.string().optional().describe("ISO date \u2014 tasks created after this date"),
|
|
20722
20792
|
created_before: exports_external.string().optional().describe("ISO date \u2014 tasks created before this date"),
|
|
@@ -20909,11 +20979,12 @@ var init_task_crud2 = __esm(() => {
|
|
|
20909
20979
|
init_tasks();
|
|
20910
20980
|
init_types();
|
|
20911
20981
|
init_token_utils();
|
|
20982
|
+
init_creator_identity();
|
|
20912
20983
|
init_cloud_router();
|
|
20913
20984
|
});
|
|
20914
20985
|
|
|
20915
20986
|
// src/lib/project-bootstrap.ts
|
|
20916
|
-
import { existsSync as
|
|
20987
|
+
import { existsSync as existsSync8, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
|
|
20917
20988
|
import { basename as basename2, dirname as dirname5, resolve as resolve8 } from "path";
|
|
20918
20989
|
function safeStat(path) {
|
|
20919
20990
|
try {
|
|
@@ -20932,7 +21003,7 @@ function canonicalPath(input) {
|
|
|
20932
21003
|
function findUp(start, marker) {
|
|
20933
21004
|
let current = canonicalPath(start);
|
|
20934
21005
|
while (true) {
|
|
20935
|
-
if (
|
|
21006
|
+
if (existsSync8(resolve8(current, marker)))
|
|
20936
21007
|
return current;
|
|
20937
21008
|
const parent = dirname5(current);
|
|
20938
21009
|
if (parent === current)
|
|
@@ -20944,7 +21015,7 @@ function readPackageJson(path) {
|
|
|
20944
21015
|
if (!path)
|
|
20945
21016
|
return null;
|
|
20946
21017
|
const file = resolve8(path, "package.json");
|
|
20947
|
-
if (!
|
|
21018
|
+
if (!existsSync8(file))
|
|
20948
21019
|
return null;
|
|
20949
21020
|
try {
|
|
20950
21021
|
const parsed = JSON.parse(readFileSync3(file, "utf-8"));
|
|
@@ -20966,7 +21037,7 @@ function workspaceMarker(root, rootPackage) {
|
|
|
20966
21037
|
if (rootPackage?.workspaces)
|
|
20967
21038
|
markers.push("package.json#workspaces");
|
|
20968
21039
|
for (const marker of ["pnpm-workspace.yaml", "turbo.json", "nx.json", "lerna.json", "rush.json", "bun.lock", "bun.lockb"]) {
|
|
20969
|
-
if (
|
|
21040
|
+
if (existsSync8(resolve8(root, marker)))
|
|
20970
21041
|
markers.push(marker);
|
|
20971
21042
|
}
|
|
20972
21043
|
const kind = markers.find((marker) => marker !== "bun.lock" && marker !== "bun.lockb") ?? null;
|
|
@@ -21279,7 +21350,7 @@ var init_tags = __esm(() => {
|
|
|
21279
21350
|
});
|
|
21280
21351
|
|
|
21281
21352
|
// src/lib/retention-cleanup.ts
|
|
21282
|
-
import { existsSync as
|
|
21353
|
+
import { existsSync as existsSync9, unlinkSync } from "fs";
|
|
21283
21354
|
function normalizeScopes(scopes) {
|
|
21284
21355
|
if (!scopes || scopes.length === 0)
|
|
21285
21356
|
return [...ALL_SCOPES];
|
|
@@ -21482,7 +21553,7 @@ function applyRetentionCleanup(input, db) {
|
|
|
21482
21553
|
for (const artifact of report.candidates.artifact_files) {
|
|
21483
21554
|
try {
|
|
21484
21555
|
const path = artifactStorePath(artifact.relative_path);
|
|
21485
|
-
if (!
|
|
21556
|
+
if (!existsSync9(path)) {
|
|
21486
21557
|
report.warnings.push(`stored artifact already missing: ${artifact.relative_path}`);
|
|
21487
21558
|
continue;
|
|
21488
21559
|
}
|
|
@@ -21509,8 +21580,8 @@ var init_retention_cleanup = __esm(() => {
|
|
|
21509
21580
|
});
|
|
21510
21581
|
|
|
21511
21582
|
// src/lib/mention-resolver.ts
|
|
21512
|
-
import { existsSync as
|
|
21513
|
-
import { basename as basename3, isAbsolute, join as
|
|
21583
|
+
import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
21584
|
+
import { basename as basename3, isAbsolute, join as join7, relative as relative3, resolve as resolve9, sep as sep2 } from "path";
|
|
21514
21585
|
function blankResolution(parsed) {
|
|
21515
21586
|
return {
|
|
21516
21587
|
input: parsed.input,
|
|
@@ -21608,7 +21679,7 @@ function resolveFile(parsed, workspace) {
|
|
|
21608
21679
|
return resolution;
|
|
21609
21680
|
}
|
|
21610
21681
|
resolution.path = relPath;
|
|
21611
|
-
if (!
|
|
21682
|
+
if (!existsSync10(absolutePath)) {
|
|
21612
21683
|
resolution.warnings.push("file does not exist in the local workspace");
|
|
21613
21684
|
return resolution;
|
|
21614
21685
|
}
|
|
@@ -21641,7 +21712,7 @@ function walkSourceFiles(root, current = root, files = []) {
|
|
|
21641
21712
|
if (SKIP_DIRS.has(entry.name))
|
|
21642
21713
|
continue;
|
|
21643
21714
|
}
|
|
21644
|
-
const absolutePath =
|
|
21715
|
+
const absolutePath = join7(current, entry.name);
|
|
21645
21716
|
if (entry.isDirectory()) {
|
|
21646
21717
|
if (!SKIP_DIRS.has(entry.name))
|
|
21647
21718
|
walkSourceFiles(root, absolutePath, files);
|
|
@@ -25333,7 +25404,7 @@ var init_audit_ledger = __esm(() => {
|
|
|
25333
25404
|
|
|
25334
25405
|
// src/lib/release-compatibility.ts
|
|
25335
25406
|
import { readFileSync as readFileSync5 } from "fs";
|
|
25336
|
-
import { join as
|
|
25407
|
+
import { join as join8, resolve as resolve11 } from "path";
|
|
25337
25408
|
import { Database as Database2 } from "bun:sqlite";
|
|
25338
25409
|
function pass(id, message, details) {
|
|
25339
25410
|
return { id, status: "passed", message, details };
|
|
@@ -25345,7 +25416,7 @@ function warn(id, message, details) {
|
|
|
25345
25416
|
return { id, status: "warning", message, details };
|
|
25346
25417
|
}
|
|
25347
25418
|
function readPackageJson2(root) {
|
|
25348
|
-
return JSON.parse(readFileSync5(
|
|
25419
|
+
return JSON.parse(readFileSync5(join8(root, "package.json"), "utf8"));
|
|
25349
25420
|
}
|
|
25350
25421
|
function sortedKeys(value) {
|
|
25351
25422
|
return Object.keys(value ?? {}).sort((left, right) => left.localeCompare(right));
|
|
@@ -29358,8 +29429,8 @@ var exports_doctor = {};
|
|
|
29358
29429
|
__export(exports_doctor, {
|
|
29359
29430
|
runTodosDoctor: () => runTodosDoctor
|
|
29360
29431
|
});
|
|
29361
|
-
import { chmodSync, copyFileSync, existsSync as
|
|
29362
|
-
import { basename as basename4, dirname as dirname6, join as
|
|
29432
|
+
import { chmodSync, copyFileSync, existsSync as existsSync11, mkdirSync as mkdirSync5, statSync as statSync5 } from "fs";
|
|
29433
|
+
import { basename as basename4, dirname as dirname6, join as join9 } from "path";
|
|
29363
29434
|
function tableExists2(db, table) {
|
|
29364
29435
|
return Boolean(db.query("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(table));
|
|
29365
29436
|
}
|
|
@@ -29453,7 +29524,7 @@ function findMissingProjectRoots(db) {
|
|
|
29453
29524
|
continue;
|
|
29454
29525
|
if (!row.path.startsWith("/"))
|
|
29455
29526
|
continue;
|
|
29456
|
-
if (!
|
|
29527
|
+
if (!existsSync11(row.path))
|
|
29457
29528
|
missing++;
|
|
29458
29529
|
}
|
|
29459
29530
|
return missing;
|
|
@@ -29513,16 +29584,16 @@ function databasePermissionsAreUnsafe(dbPath) {
|
|
|
29513
29584
|
function createBackup(dbPath) {
|
|
29514
29585
|
if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
|
|
29515
29586
|
return;
|
|
29516
|
-
if (!
|
|
29587
|
+
if (!existsSync11(dbPath))
|
|
29517
29588
|
return;
|
|
29518
29589
|
const stamp = now().replace(/[:.]/g, "-");
|
|
29519
|
-
const backupDir =
|
|
29590
|
+
const backupDir = join9(dirname6(dbPath), `${basename4(dbPath)}.backup-${stamp}`);
|
|
29520
29591
|
const files = [];
|
|
29521
29592
|
mkdirSync5(backupDir, { recursive: true });
|
|
29522
29593
|
for (const source of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
|
|
29523
|
-
if (!
|
|
29594
|
+
if (!existsSync11(source))
|
|
29524
29595
|
continue;
|
|
29525
|
-
const target =
|
|
29596
|
+
const target = join9(backupDir, basename4(source));
|
|
29526
29597
|
copyFileSync(source, target);
|
|
29527
29598
|
files.push(target);
|
|
29528
29599
|
}
|
|
@@ -32258,7 +32329,7 @@ var init_agent_run_dispatcher = __esm(() => {
|
|
|
32258
32329
|
});
|
|
32259
32330
|
|
|
32260
32331
|
// src/lib/verification-providers.ts
|
|
32261
|
-
import { existsSync as
|
|
32332
|
+
import { existsSync as existsSync12, readFileSync as readFileSync6 } from "fs";
|
|
32262
32333
|
function normalizeName5(name) {
|
|
32263
32334
|
const normalized = name.trim().toLowerCase();
|
|
32264
32335
|
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(normalized)) {
|
|
@@ -32410,7 +32481,7 @@ Timed out after ${provider.timeout_ms}ms`);
|
|
|
32410
32481
|
};
|
|
32411
32482
|
}
|
|
32412
32483
|
function runCiLogProvider(input) {
|
|
32413
|
-
const text = input.log_text ?? (input.log_path &&
|
|
32484
|
+
const text = input.log_text ?? (input.log_path && existsSync12(input.log_path) ? readFileSync6(input.log_path, "utf-8") : "");
|
|
32414
32485
|
return {
|
|
32415
32486
|
status: classifyLog(text),
|
|
32416
32487
|
attempts: 1,
|
|
@@ -32422,7 +32493,7 @@ function runBrowserProvider(input) {
|
|
|
32422
32493
|
if (!input.artifact_path) {
|
|
32423
32494
|
return { status: "unknown", attempts: 1, exit_code: null, output_summary: "browser provider needs a screenshot or artifact path" };
|
|
32424
32495
|
}
|
|
32425
|
-
if (!
|
|
32496
|
+
if (!existsSync12(input.artifact_path)) {
|
|
32426
32497
|
return { status: "failed", attempts: 1, exit_code: null, output_summary: `artifact not found: ${input.artifact_path}` };
|
|
32427
32498
|
}
|
|
32428
32499
|
return {
|
|
@@ -34571,7 +34642,7 @@ var package_default;
|
|
|
34571
34642
|
var init_package = __esm(() => {
|
|
34572
34643
|
package_default = {
|
|
34573
34644
|
name: "@hasna/todos",
|
|
34574
|
-
version: "0.13.
|
|
34645
|
+
version: "0.13.6",
|
|
34575
34646
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
34576
34647
|
type: "module",
|
|
34577
34648
|
main: "dist/index.js",
|
|
@@ -35641,6 +35712,7 @@ function task(input) {
|
|
|
35641
35712
|
reason: "Bundled deterministic onboarding fixture",
|
|
35642
35713
|
spawned_from_session: null,
|
|
35643
35714
|
assigned_by: null,
|
|
35715
|
+
created_by: null,
|
|
35644
35716
|
assigned_from_project: null,
|
|
35645
35717
|
task_type: "onboarding",
|
|
35646
35718
|
cost_tokens: 0,
|
|
@@ -36838,8 +36910,8 @@ __export(exports_local_extensions, {
|
|
|
36838
36910
|
discoverLocalExtensions: () => discoverLocalExtensions
|
|
36839
36911
|
});
|
|
36840
36912
|
import { createHash as createHash9, createVerify } from "crypto";
|
|
36841
|
-
import { existsSync as
|
|
36842
|
-
import { basename as basename5, join as
|
|
36913
|
+
import { existsSync as existsSync13, readdirSync as readdirSync3, readFileSync as readFileSync8, statSync as statSync6 } from "fs";
|
|
36914
|
+
import { basename as basename5, join as join10, resolve as resolve13 } from "path";
|
|
36843
36915
|
function isObject2(value) {
|
|
36844
36916
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
36845
36917
|
}
|
|
@@ -37098,10 +37170,10 @@ function verifyExtensionSignature(input) {
|
|
|
37098
37170
|
}
|
|
37099
37171
|
function inspectExtensionSource(source3) {
|
|
37100
37172
|
const resolved = resolve13(source3);
|
|
37101
|
-
if (!
|
|
37173
|
+
if (!existsSync13(resolved))
|
|
37102
37174
|
throw new Error(`extension source not found: ${source3}`);
|
|
37103
37175
|
const stat = statSync6(resolved);
|
|
37104
|
-
const manifestPath = stat.isDirectory() ? [
|
|
37176
|
+
const manifestPath = stat.isDirectory() ? [join10(resolved, "todos.extension.json"), join10(resolved, "extension.json")].find(existsSync13) : resolved;
|
|
37105
37177
|
if (!manifestPath)
|
|
37106
37178
|
throw new Error(`extension directory ${source3} is missing todos.extension.json`);
|
|
37107
37179
|
const raw = readFileSync8(manifestPath);
|
|
@@ -37197,20 +37269,20 @@ function projectExtensionSources(projectPath) {
|
|
|
37197
37269
|
return [];
|
|
37198
37270
|
const root = resolve13(projectPath);
|
|
37199
37271
|
const candidates = [
|
|
37200
|
-
|
|
37201
|
-
|
|
37272
|
+
join10(root, "todos.extension.json"),
|
|
37273
|
+
join10(root, ".todos", "todos.extension.json")
|
|
37202
37274
|
];
|
|
37203
|
-
const extensionDir =
|
|
37204
|
-
if (
|
|
37275
|
+
const extensionDir = join10(root, ".todos", "extensions");
|
|
37276
|
+
if (existsSync13(extensionDir)) {
|
|
37205
37277
|
for (const entry of readdirSync3(extensionDir)) {
|
|
37206
37278
|
if (entry.startsWith("."))
|
|
37207
37279
|
continue;
|
|
37208
|
-
const full =
|
|
37280
|
+
const full = join10(extensionDir, entry);
|
|
37209
37281
|
if (statSync6(full).isDirectory() || entry.endsWith(".json"))
|
|
37210
37282
|
candidates.push(full);
|
|
37211
37283
|
}
|
|
37212
37284
|
}
|
|
37213
|
-
return candidates.filter(
|
|
37285
|
+
return candidates.filter(existsSync13);
|
|
37214
37286
|
}
|
|
37215
37287
|
function discoverLocalExtensions(options = {}) {
|
|
37216
37288
|
const config = loadConfig();
|
|
@@ -41617,9 +41689,9 @@ __export(exports_extract, {
|
|
|
41617
41689
|
buildCodebaseIndex: () => buildCodebaseIndex,
|
|
41618
41690
|
EXTRACT_TAGS: () => EXTRACT_TAGS
|
|
41619
41691
|
});
|
|
41620
|
-
import { existsSync as
|
|
41692
|
+
import { existsSync as existsSync14, readFileSync as readFileSync9, statSync as statSync7 } from "fs";
|
|
41621
41693
|
import { createHash as createHash11 } from "crypto";
|
|
41622
|
-
import { relative as relative5, resolve as resolve14, join as
|
|
41694
|
+
import { relative as relative5, resolve as resolve14, join as join11 } from "path";
|
|
41623
41695
|
function stableHash(value) {
|
|
41624
41696
|
return createHash11("sha256").update(value).digest("hex");
|
|
41625
41697
|
}
|
|
@@ -41628,8 +41700,8 @@ function normalizePathForMatch(value) {
|
|
|
41628
41700
|
}
|
|
41629
41701
|
function readGitignorePatterns(basePath) {
|
|
41630
41702
|
const root = statSync7(basePath).isFile() ? resolve14(basePath, "..") : basePath;
|
|
41631
|
-
const gitignorePath =
|
|
41632
|
-
if (!
|
|
41703
|
+
const gitignorePath = join11(root, ".gitignore");
|
|
41704
|
+
if (!existsSync14(gitignorePath))
|
|
41633
41705
|
return [];
|
|
41634
41706
|
try {
|
|
41635
41707
|
return readFileSync9(gitignorePath, "utf-8").split(`
|
|
@@ -41771,7 +41843,7 @@ function buildCodebaseIndex(options) {
|
|
|
41771
41843
|
const files = collectFiles(basePath, extensions, excludes, respectGitignore);
|
|
41772
41844
|
const indexed = [];
|
|
41773
41845
|
for (const file of files) {
|
|
41774
|
-
const fullPath = statSync7(basePath).isFile() ? basePath :
|
|
41846
|
+
const fullPath = statSync7(basePath).isFile() ? basePath : join11(basePath, file);
|
|
41775
41847
|
try {
|
|
41776
41848
|
const source3 = readFileSync9(fullPath, "utf-8");
|
|
41777
41849
|
const relPath = statSync7(basePath).isFile() ? relative5(resolve14(basePath, ".."), fullPath) : file;
|
|
@@ -41802,7 +41874,7 @@ function extractTodos(options, db) {
|
|
|
41802
41874
|
const files = collectFiles(basePath, extensions, excludes, respectGitignore);
|
|
41803
41875
|
const allComments = [];
|
|
41804
41876
|
for (const file of files) {
|
|
41805
|
-
const fullPath = statSync7(basePath).isFile() ? basePath :
|
|
41877
|
+
const fullPath = statSync7(basePath).isFile() ? basePath : join11(basePath, file);
|
|
41806
41878
|
try {
|
|
41807
41879
|
const source3 = readFileSync9(fullPath, "utf-8");
|
|
41808
41880
|
const relPath = statSync7(basePath).isFile() ? relative5(resolve14(basePath, ".."), fullPath) : file;
|
|
@@ -42753,7 +42825,7 @@ __export(exports_builtin_templates, {
|
|
|
42753
42825
|
BUILTIN_TEMPLATES: () => BUILTIN_TEMPLATES
|
|
42754
42826
|
});
|
|
42755
42827
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
42756
|
-
import { join as
|
|
42828
|
+
import { join as join12 } from "path";
|
|
42757
42829
|
function templateMetadata(template) {
|
|
42758
42830
|
return {
|
|
42759
42831
|
source: BUILTIN_TEMPLATE_LIBRARY_SOURCE,
|
|
@@ -42812,7 +42884,7 @@ function writeBuiltinTemplateFiles(directory) {
|
|
|
42812
42884
|
mkdirSync7(directory, { recursive: true });
|
|
42813
42885
|
const files = [];
|
|
42814
42886
|
for (const entry of exportBuiltinTemplateFiles()) {
|
|
42815
|
-
const path =
|
|
42887
|
+
const path = join12(directory, entry.filename);
|
|
42816
42888
|
writeFileSync4(path, `${JSON.stringify(entry.template, null, 2)}
|
|
42817
42889
|
`, "utf-8");
|
|
42818
42890
|
files.push(path);
|
|
@@ -43338,16 +43410,16 @@ __export(exports_environment_snapshots, {
|
|
|
43338
43410
|
captureEnvironmentSnapshot: () => captureEnvironmentSnapshot
|
|
43339
43411
|
});
|
|
43340
43412
|
import { createHash as createHash12 } from "crypto";
|
|
43341
|
-
import { existsSync as
|
|
43413
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, statSync as statSync8 } from "fs";
|
|
43342
43414
|
import { hostname as hostname2, platform, arch } from "os";
|
|
43343
|
-
import { dirname as dirname8, join as
|
|
43415
|
+
import { dirname as dirname8, join as join13, resolve as resolve15 } from "path";
|
|
43344
43416
|
import { tmpdir as tmpdir3 } from "os";
|
|
43345
43417
|
function sha2567(value) {
|
|
43346
43418
|
return createHash12("sha256").update(value).digest("hex");
|
|
43347
43419
|
}
|
|
43348
43420
|
function fileRecord(root, relativePath) {
|
|
43349
|
-
const path =
|
|
43350
|
-
if (!
|
|
43421
|
+
const path = join13(root, relativePath);
|
|
43422
|
+
if (!existsSync15(path))
|
|
43351
43423
|
return null;
|
|
43352
43424
|
const stat = statSync8(path);
|
|
43353
43425
|
if (!stat.isFile())
|
|
@@ -43359,7 +43431,7 @@ function manifestRecord(root, relativePath) {
|
|
|
43359
43431
|
const base = fileRecord(root, relativePath);
|
|
43360
43432
|
if (!base)
|
|
43361
43433
|
return null;
|
|
43362
|
-
const parsed = readJsonFile(
|
|
43434
|
+
const parsed = readJsonFile(join13(root, relativePath));
|
|
43363
43435
|
if (!parsed)
|
|
43364
43436
|
return { ...base, redacted: {} };
|
|
43365
43437
|
const redacted = redactValue({
|
|
@@ -43454,8 +43526,8 @@ function commandEnv(env, includeValues) {
|
|
|
43454
43526
|
function defaultSnapshotDir() {
|
|
43455
43527
|
const dbPath = getDatabasePath();
|
|
43456
43528
|
if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
|
|
43457
|
-
return
|
|
43458
|
-
return
|
|
43529
|
+
return join13(tmpdir3(), "hasna-todos", "environment-snapshots");
|
|
43530
|
+
return join13(dirname8(resolve15(dbPath)), "environment-snapshots");
|
|
43459
43531
|
}
|
|
43460
43532
|
function snapshotWithId(snapshot) {
|
|
43461
43533
|
const digest = sha2567(JSON.stringify(snapshot)).slice(0, 24);
|
|
@@ -43502,7 +43574,7 @@ function captureEnvironmentSnapshot(input = {}) {
|
|
|
43502
43574
|
});
|
|
43503
43575
|
}
|
|
43504
43576
|
function writeEnvironmentSnapshot(snapshot, outputPath) {
|
|
43505
|
-
const path = outputPath ? resolve15(outputPath) :
|
|
43577
|
+
const path = outputPath ? resolve15(outputPath) : join13(defaultSnapshotDir(), `${snapshot.id}.json`);
|
|
43506
43578
|
ensureDir2(dirname8(path));
|
|
43507
43579
|
writeJsonFile(path, snapshot);
|
|
43508
43580
|
return path;
|
|
@@ -44401,7 +44473,11 @@ function createLocalSqliteTodosStorageAdapter(options = {}) {
|
|
|
44401
44473
|
sync: true
|
|
44402
44474
|
},
|
|
44403
44475
|
tasks: {
|
|
44404
|
-
create: (input) => createTask(
|
|
44476
|
+
create: (input, context) => createTask({
|
|
44477
|
+
...input,
|
|
44478
|
+
agent_id: input.agent_id ?? context?.agentId,
|
|
44479
|
+
created_by: input.created_by ?? input.agent_id ?? context?.agentId
|
|
44480
|
+
}, database()),
|
|
44405
44481
|
get: (id) => getTask(id, database()),
|
|
44406
44482
|
resolveRef: (ref) => resolveTaskRefLocal(database(), ref),
|
|
44407
44483
|
list: (filter = {}) => listTasksMaybeSearch(filter, database()),
|
|
@@ -45540,6 +45616,10 @@ class PostgresJsonRecordStore {
|
|
|
45540
45616
|
conds.push(`payload->>'assigned_to' = ${p(filter.assigned_to)}`);
|
|
45541
45617
|
if (filter.agent_id !== undefined)
|
|
45542
45618
|
conds.push(`payload->>'agent_id' = ${p(filter.agent_id)}`);
|
|
45619
|
+
if (filter.created_by !== undefined)
|
|
45620
|
+
conds.push(`LOWER(payload->>'created_by') = LOWER(${p(filter.created_by)})`);
|
|
45621
|
+
if (filter.not_created_by !== undefined)
|
|
45622
|
+
conds.push(`(payload->>'created_by' IS NULL OR LOWER(payload->>'created_by') <> LOWER(${p(filter.not_created_by)}))`);
|
|
45543
45623
|
if (filter.session_id !== undefined)
|
|
45544
45624
|
conds.push(`payload->>'session_id' = ${p(filter.session_id)}`);
|
|
45545
45625
|
if (filter.tags?.length) {
|
|
@@ -46053,7 +46133,7 @@ async function createTask3(input, store, context) {
|
|
|
46053
46133
|
description: input.description ?? null,
|
|
46054
46134
|
status: input.status ?? "pending",
|
|
46055
46135
|
priority: input.priority ?? "medium",
|
|
46056
|
-
agent_id: input.agent_id ?? null,
|
|
46136
|
+
agent_id: input.agent_id ?? context?.agentId ?? null,
|
|
46057
46137
|
assigned_to: input.assigned_to ?? null,
|
|
46058
46138
|
session_id: input.session_id ?? context?.sessionId ?? null,
|
|
46059
46139
|
working_dir: input.working_dir ?? null,
|
|
@@ -46078,7 +46158,8 @@ async function createTask3(input, store, context) {
|
|
|
46078
46158
|
confidence: input.confidence ?? null,
|
|
46079
46159
|
reason: input.reason ?? null,
|
|
46080
46160
|
spawned_from_session: input.spawned_from_session ?? null,
|
|
46081
|
-
assigned_by: input.assigned_by ?? null,
|
|
46161
|
+
assigned_by: input.assigned_by ?? input.agent_id ?? context?.agentId ?? null,
|
|
46162
|
+
created_by: input.created_by ?? input.agent_id ?? context?.agentId ?? null,
|
|
46082
46163
|
assigned_from_project: input.assigned_from_project ?? null,
|
|
46083
46164
|
task_type: input.task_type ?? null,
|
|
46084
46165
|
cost_tokens: 0,
|
|
@@ -46115,7 +46196,8 @@ async function updateTask2(id, input, store) {
|
|
|
46115
46196
|
tags: input.tags ?? existing.tags,
|
|
46116
46197
|
metadata: input.metadata ?? existing.metadata,
|
|
46117
46198
|
requires_approval: input.requires_approval ?? existing.requires_approval,
|
|
46118
|
-
task_list_id: input.task_list_id !== undefined ? input.task_list_id : existing.task_list_id
|
|
46199
|
+
task_list_id: input.task_list_id !== undefined ? input.task_list_id : existing.task_list_id,
|
|
46200
|
+
created_by: existing.created_by
|
|
46119
46201
|
};
|
|
46120
46202
|
await store.upsert("tasks", task2);
|
|
46121
46203
|
return task2;
|
|
@@ -47798,7 +47880,7 @@ var init_headless_boundaries = __esm(() => {
|
|
|
47798
47880
|
});
|
|
47799
47881
|
|
|
47800
47882
|
// src/server/routes.ts
|
|
47801
|
-
import { join as
|
|
47883
|
+
import { join as join14, resolve as resolve16, sep as sep3 } from "path";
|
|
47802
47884
|
function parseFieldsParam(url) {
|
|
47803
47885
|
const fieldsParam = url.searchParams.get("fields");
|
|
47804
47886
|
return fieldsParam ? fieldsParam.split(",").map((f) => f.trim()).filter(Boolean) : undefined;
|
|
@@ -47979,11 +48061,15 @@ async function handleCreateTask(req, ctx, json2, taskToSummary2) {
|
|
|
47979
48061
|
const body = await req.json();
|
|
47980
48062
|
if (!body.title)
|
|
47981
48063
|
return json2({ error: "Missing 'title'" }, 400);
|
|
48064
|
+
const createdBy = body.created_by ?? body.agent_id ?? "dashboard";
|
|
47982
48065
|
const task2 = createTask({
|
|
47983
48066
|
title: body.title,
|
|
47984
48067
|
description: body.description,
|
|
47985
48068
|
priority: body.priority,
|
|
47986
|
-
project_id: body.project_id
|
|
48069
|
+
project_id: body.project_id,
|
|
48070
|
+
agent_id: body.agent_id ?? createdBy,
|
|
48071
|
+
created_by: createdBy,
|
|
48072
|
+
...body.assigned_to ? { assigned_to: body.assigned_to } : {}
|
|
47987
48073
|
});
|
|
47988
48074
|
ctx.broadcastEvent({ type: "task", task_id: task2.id, action: "created", agent_id: task2.agent_id, project_id: task2.project_id });
|
|
47989
48075
|
return json2(taskToSummary2(task2), 201);
|
|
@@ -48589,7 +48675,7 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
|
|
|
48589
48675
|
if (!ctx.dashboardExists || method !== "GET" && method !== "HEAD")
|
|
48590
48676
|
return null;
|
|
48591
48677
|
if (path !== "/") {
|
|
48592
|
-
const filePath =
|
|
48678
|
+
const filePath = join14(ctx.dashboardDir, path);
|
|
48593
48679
|
const resolvedFile = resolve16(filePath);
|
|
48594
48680
|
const resolvedBase = resolve16(ctx.dashboardDir);
|
|
48595
48681
|
if (!resolvedFile.startsWith(resolvedBase + sep3) && resolvedFile !== resolvedBase) {
|
|
@@ -48599,7 +48685,7 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
|
|
|
48599
48685
|
if (res2)
|
|
48600
48686
|
return res2;
|
|
48601
48687
|
}
|
|
48602
|
-
const indexPath =
|
|
48688
|
+
const indexPath = join14(ctx.dashboardDir, "index.html");
|
|
48603
48689
|
const res = serveStaticFile2(indexPath);
|
|
48604
48690
|
if (res)
|
|
48605
48691
|
return res;
|
|
@@ -50776,6 +50862,8 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
50776
50862
|
...url.searchParams.get("task_list_id") ? { task_list_id: url.searchParams.get("task_list_id") } : {},
|
|
50777
50863
|
...url.searchParams.get("assigned_to") ? { assigned_to: url.searchParams.get("assigned_to") } : {},
|
|
50778
50864
|
...url.searchParams.get("agent_id") ? { agent_id: url.searchParams.get("agent_id") } : {},
|
|
50865
|
+
...url.searchParams.get("created_by") ? { created_by: url.searchParams.get("created_by") } : {},
|
|
50866
|
+
...url.searchParams.get("not_created_by") ? { not_created_by: url.searchParams.get("not_created_by") } : {},
|
|
50779
50867
|
...url.searchParams.get("tags") ? {
|
|
50780
50868
|
tags: url.searchParams.get("tags").split(",").map((tag) => tag.trim()).filter(Boolean)
|
|
50781
50869
|
} : {},
|
|
@@ -51734,27 +51822,27 @@ __export(exports_serve, {
|
|
|
51734
51822
|
SECURITY_HEADERS: () => SECURITY_HEADERS,
|
|
51735
51823
|
MIME_TYPES: () => MIME_TYPES
|
|
51736
51824
|
});
|
|
51737
|
-
import { existsSync as
|
|
51738
|
-
import { join as
|
|
51825
|
+
import { existsSync as existsSync16 } from "fs";
|
|
51826
|
+
import { join as join15, dirname as dirname9, extname } from "path";
|
|
51739
51827
|
import { fileURLToPath } from "url";
|
|
51740
51828
|
function resolveDashboardDir() {
|
|
51741
51829
|
const candidates = [];
|
|
51742
51830
|
try {
|
|
51743
51831
|
const scriptDir = dirname9(fileURLToPath(import.meta.url));
|
|
51744
|
-
candidates.push(
|
|
51745
|
-
candidates.push(
|
|
51832
|
+
candidates.push(join15(scriptDir, "..", "dashboard", "dist"));
|
|
51833
|
+
candidates.push(join15(scriptDir, "..", "..", "dashboard", "dist"));
|
|
51746
51834
|
} catch {}
|
|
51747
51835
|
if (process.argv[1]) {
|
|
51748
51836
|
const mainDir = dirname9(process.argv[1]);
|
|
51749
|
-
candidates.push(
|
|
51750
|
-
candidates.push(
|
|
51837
|
+
candidates.push(join15(mainDir, "..", "dashboard", "dist"));
|
|
51838
|
+
candidates.push(join15(mainDir, "..", "..", "dashboard", "dist"));
|
|
51751
51839
|
}
|
|
51752
|
-
candidates.push(
|
|
51840
|
+
candidates.push(join15(process.cwd(), "dashboard", "dist"));
|
|
51753
51841
|
for (const candidate of candidates) {
|
|
51754
|
-
if (
|
|
51842
|
+
if (existsSync16(candidate))
|
|
51755
51843
|
return candidate;
|
|
51756
51844
|
}
|
|
51757
|
-
return
|
|
51845
|
+
return join15(process.cwd(), "dashboard", "dist");
|
|
51758
51846
|
}
|
|
51759
51847
|
function getProvidedApiKey(req) {
|
|
51760
51848
|
const headerKey = req.headers.get("x-api-key");
|
|
@@ -51826,7 +51914,7 @@ function json(data, status = 200, headers) {
|
|
|
51826
51914
|
});
|
|
51827
51915
|
}
|
|
51828
51916
|
function serveStaticFile(filePath) {
|
|
51829
|
-
if (!
|
|
51917
|
+
if (!existsSync16(filePath))
|
|
51830
51918
|
return null;
|
|
51831
51919
|
const ext = extname(filePath);
|
|
51832
51920
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
@@ -51927,7 +52015,7 @@ data: ${data}
|
|
|
51927
52015
|
filteredSseClients.delete(client);
|
|
51928
52016
|
}
|
|
51929
52017
|
const dashboardDir = resolveDashboardDir();
|
|
51930
|
-
const dashboardExists =
|
|
52018
|
+
const dashboardExists = existsSync16(dashboardDir);
|
|
51931
52019
|
if (!dashboardExists) {
|
|
51932
52020
|
console.error(`
|
|
51933
52021
|
Dashboard not found at: ${dashboardDir}`);
|