@hasna/todos 0.13.5 → 0.13.7
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 +418 -177
- package/dist/contracts.js +29 -3
- package/dist/db/schema.d.ts.map +1 -1
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/index.js +43 -7
- package/dist/lib/creator-identity.d.ts +100 -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 +177 -75
- package/dist/mcp/tools/task-crud.d.ts.map +1 -1
- package/dist/mcp.js +1 -1
- package/dist/registry.js +29 -3
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +167 -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 +41 -6
- package/dist/types/index.d.ts +18 -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);
|
|
@@ -13777,6 +13798,10 @@ function updateTask(id, input, db) {
|
|
|
13777
13798
|
sets.push("description = ?");
|
|
13778
13799
|
params.push(input.description);
|
|
13779
13800
|
}
|
|
13801
|
+
if (input.agent_id !== undefined) {
|
|
13802
|
+
sets.push("agent_id = ?");
|
|
13803
|
+
params.push(input.agent_id);
|
|
13804
|
+
}
|
|
13780
13805
|
if (input.status !== undefined) {
|
|
13781
13806
|
if (input.status === "completed") {
|
|
13782
13807
|
checkCompletionGuard(task, task.assigned_to || task.agent_id || null, d);
|
|
@@ -17844,6 +17869,50 @@ var init_token_utils = __esm(() => {
|
|
|
17844
17869
|
};
|
|
17845
17870
|
});
|
|
17846
17871
|
|
|
17872
|
+
// src/lib/creator-identity.ts
|
|
17873
|
+
import { existsSync as existsSync7, rmSync as rmSync2 } from "fs";
|
|
17874
|
+
import { join as join6 } from "path";
|
|
17875
|
+
function identityFilePath() {
|
|
17876
|
+
return join6(getTodosGlobalDir(), "identity.json");
|
|
17877
|
+
}
|
|
17878
|
+
function readPersistedIdentity() {
|
|
17879
|
+
const path = identityFilePath();
|
|
17880
|
+
if (!existsSync7(path))
|
|
17881
|
+
return null;
|
|
17882
|
+
const parsed = readJsonFile(path);
|
|
17883
|
+
if (!parsed || typeof parsed.agent_id !== "string" || !parsed.agent_id.trim())
|
|
17884
|
+
return null;
|
|
17885
|
+
return parsed;
|
|
17886
|
+
}
|
|
17887
|
+
function canonicalAgentRef(value) {
|
|
17888
|
+
return value.trim().toLowerCase();
|
|
17889
|
+
}
|
|
17890
|
+
function isProcessBoundSource(source) {
|
|
17891
|
+
return source === "explicit" || source === "env";
|
|
17892
|
+
}
|
|
17893
|
+
function resolveWritableIdentity(explicit) {
|
|
17894
|
+
const resolved = resolveCreatorIdentity(explicit);
|
|
17895
|
+
if (!isProcessBoundSource(resolved.source))
|
|
17896
|
+
return { agent_id: null, source: "none" };
|
|
17897
|
+
return resolved;
|
|
17898
|
+
}
|
|
17899
|
+
function resolveCreatorIdentity(explicit) {
|
|
17900
|
+
const fromExplicit = explicit?.trim();
|
|
17901
|
+
if (fromExplicit)
|
|
17902
|
+
return { agent_id: canonicalAgentRef(fromExplicit), source: "explicit" };
|
|
17903
|
+
const fromEnv = (process.env["TODOS_AGENT_ID"] || process.env["HASNA_TODOS_AGENT_ID"] || "").trim();
|
|
17904
|
+
if (fromEnv)
|
|
17905
|
+
return { agent_id: canonicalAgentRef(fromEnv), source: "env" };
|
|
17906
|
+
const persisted = readPersistedIdentity();
|
|
17907
|
+
if (persisted) {
|
|
17908
|
+
return { agent_id: canonicalAgentRef(persisted.agent_name || persisted.agent_id), source: "persisted" };
|
|
17909
|
+
}
|
|
17910
|
+
return { agent_id: null, source: "none" };
|
|
17911
|
+
}
|
|
17912
|
+
var init_creator_identity = __esm(() => {
|
|
17913
|
+
init_sync_utils();
|
|
17914
|
+
});
|
|
17915
|
+
|
|
17847
17916
|
// src/pr-groups/types.ts
|
|
17848
17917
|
var PR_GROUP_LEDGER_SCHEMA_VERSION = 1, PR_GROUP_REPAIR_CYCLE_LIMIT = 2, PrGroupLedgerError;
|
|
17849
17918
|
var init_types3 = __esm(() => {
|
|
@@ -20594,6 +20663,8 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20594
20663
|
project_id: exports_external.string().optional().describe("Project ID"),
|
|
20595
20664
|
task_list_id: exports_external.string().optional().describe("Task list ID"),
|
|
20596
20665
|
assigned_to: exports_external.string().optional().describe("Agent ID or name to assign to"),
|
|
20666
|
+
created_by: exports_external.string().optional().describe("Agent who FILED this task. Defaults to the ambient agent identity (todos init / TODOS_AGENT_ID)."),
|
|
20667
|
+
unassigned: exports_external.boolean().optional().describe("Deliberately file with no assignee. Without it, the task defaults to the filer."),
|
|
20597
20668
|
depends_on: exports_external.array(exports_external.string()).optional().describe("Array of task IDs this task depends on"),
|
|
20598
20669
|
short_id: exports_external.string().nullable().optional().describe("Short ID (auto-generated if not provided, disabled if null)"),
|
|
20599
20670
|
tags: exports_external.array(exports_external.string()).optional().describe("Tags for the task"),
|
|
@@ -20604,12 +20675,19 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20604
20675
|
retry_count: exports_external.number().optional().describe("Max retry count for agent failures")
|
|
20605
20676
|
}, async (params) => {
|
|
20606
20677
|
try {
|
|
20607
|
-
const { depends_on, assigned_to, project_id, task_list_id, tags, estimate, confidence, retry_count, deadline, ...rest } = params;
|
|
20678
|
+
const { depends_on, assigned_to, project_id, task_list_id, tags, estimate, confidence, retry_count, deadline, created_by, unassigned, ...rest } = params;
|
|
20679
|
+
const creator = resolveCreatorIdentity(created_by);
|
|
20680
|
+
const router = resolveWritableIdentity(created_by);
|
|
20681
|
+
const assignee = assigned_to || (unassigned ? undefined : router.agent_id || undefined);
|
|
20608
20682
|
const cloud = getTodosCloudClient();
|
|
20609
20683
|
if (cloud) {
|
|
20610
20684
|
const payload = { ...rest };
|
|
20611
|
-
if (
|
|
20612
|
-
payload.
|
|
20685
|
+
if (creator.agent_id)
|
|
20686
|
+
payload.created_by = creator.agent_id;
|
|
20687
|
+
if (router.agent_id)
|
|
20688
|
+
payload.agent_id = payload.agent_id ?? router.agent_id;
|
|
20689
|
+
if (assignee)
|
|
20690
|
+
payload.assigned_to = assignee;
|
|
20613
20691
|
if (project_id)
|
|
20614
20692
|
payload.project_id = project_id;
|
|
20615
20693
|
if (task_list_id)
|
|
@@ -20630,8 +20708,12 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20630
20708
|
return { content: [{ type: "text", text: mutationTaskResponse(created) }] };
|
|
20631
20709
|
}
|
|
20632
20710
|
const resolved = { ...rest };
|
|
20633
|
-
if (
|
|
20634
|
-
resolved.
|
|
20711
|
+
if (creator.agent_id)
|
|
20712
|
+
resolved.created_by = creator.agent_id;
|
|
20713
|
+
if (router.agent_id)
|
|
20714
|
+
resolved.agent_id = resolved.agent_id ?? router.agent_id;
|
|
20715
|
+
if (assignee)
|
|
20716
|
+
resolved.assigned_to = resolveAssignee(assignee);
|
|
20635
20717
|
if (project_id)
|
|
20636
20718
|
resolved.project_id = resolveId(project_id, "projects");
|
|
20637
20719
|
if (task_list_id)
|
|
@@ -20717,6 +20799,8 @@ function registerTaskCrudTools(server, ctx) {
|
|
|
20717
20799
|
project_id: exports_external.string().optional().describe("Filter by project"),
|
|
20718
20800
|
task_list_id: exports_external.string().optional().describe("Filter by task list"),
|
|
20719
20801
|
assigned_to: exports_external.string().optional().describe("Filter by assignee (agent ID or name, empty string = unassigned)"),
|
|
20802
|
+
created_by: exports_external.string().optional().describe("Filter by the agent who FILED the task"),
|
|
20803
|
+
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
20804
|
tags: exports_external.array(exports_external.string()).optional().describe("Filter by tags (AND logic)"),
|
|
20721
20805
|
created_after: exports_external.string().optional().describe("ISO date \u2014 tasks created after this date"),
|
|
20722
20806
|
created_before: exports_external.string().optional().describe("ISO date \u2014 tasks created before this date"),
|
|
@@ -20909,11 +20993,12 @@ var init_task_crud2 = __esm(() => {
|
|
|
20909
20993
|
init_tasks();
|
|
20910
20994
|
init_types();
|
|
20911
20995
|
init_token_utils();
|
|
20996
|
+
init_creator_identity();
|
|
20912
20997
|
init_cloud_router();
|
|
20913
20998
|
});
|
|
20914
20999
|
|
|
20915
21000
|
// src/lib/project-bootstrap.ts
|
|
20916
|
-
import { existsSync as
|
|
21001
|
+
import { existsSync as existsSync8, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
|
|
20917
21002
|
import { basename as basename2, dirname as dirname5, resolve as resolve8 } from "path";
|
|
20918
21003
|
function safeStat(path) {
|
|
20919
21004
|
try {
|
|
@@ -20932,7 +21017,7 @@ function canonicalPath(input) {
|
|
|
20932
21017
|
function findUp(start, marker) {
|
|
20933
21018
|
let current = canonicalPath(start);
|
|
20934
21019
|
while (true) {
|
|
20935
|
-
if (
|
|
21020
|
+
if (existsSync8(resolve8(current, marker)))
|
|
20936
21021
|
return current;
|
|
20937
21022
|
const parent = dirname5(current);
|
|
20938
21023
|
if (parent === current)
|
|
@@ -20944,7 +21029,7 @@ function readPackageJson(path) {
|
|
|
20944
21029
|
if (!path)
|
|
20945
21030
|
return null;
|
|
20946
21031
|
const file = resolve8(path, "package.json");
|
|
20947
|
-
if (!
|
|
21032
|
+
if (!existsSync8(file))
|
|
20948
21033
|
return null;
|
|
20949
21034
|
try {
|
|
20950
21035
|
const parsed = JSON.parse(readFileSync3(file, "utf-8"));
|
|
@@ -20966,7 +21051,7 @@ function workspaceMarker(root, rootPackage) {
|
|
|
20966
21051
|
if (rootPackage?.workspaces)
|
|
20967
21052
|
markers.push("package.json#workspaces");
|
|
20968
21053
|
for (const marker of ["pnpm-workspace.yaml", "turbo.json", "nx.json", "lerna.json", "rush.json", "bun.lock", "bun.lockb"]) {
|
|
20969
|
-
if (
|
|
21054
|
+
if (existsSync8(resolve8(root, marker)))
|
|
20970
21055
|
markers.push(marker);
|
|
20971
21056
|
}
|
|
20972
21057
|
const kind = markers.find((marker) => marker !== "bun.lock" && marker !== "bun.lockb") ?? null;
|
|
@@ -21279,7 +21364,7 @@ var init_tags = __esm(() => {
|
|
|
21279
21364
|
});
|
|
21280
21365
|
|
|
21281
21366
|
// src/lib/retention-cleanup.ts
|
|
21282
|
-
import { existsSync as
|
|
21367
|
+
import { existsSync as existsSync9, unlinkSync } from "fs";
|
|
21283
21368
|
function normalizeScopes(scopes) {
|
|
21284
21369
|
if (!scopes || scopes.length === 0)
|
|
21285
21370
|
return [...ALL_SCOPES];
|
|
@@ -21482,7 +21567,7 @@ function applyRetentionCleanup(input, db) {
|
|
|
21482
21567
|
for (const artifact of report.candidates.artifact_files) {
|
|
21483
21568
|
try {
|
|
21484
21569
|
const path = artifactStorePath(artifact.relative_path);
|
|
21485
|
-
if (!
|
|
21570
|
+
if (!existsSync9(path)) {
|
|
21486
21571
|
report.warnings.push(`stored artifact already missing: ${artifact.relative_path}`);
|
|
21487
21572
|
continue;
|
|
21488
21573
|
}
|
|
@@ -21509,8 +21594,8 @@ var init_retention_cleanup = __esm(() => {
|
|
|
21509
21594
|
});
|
|
21510
21595
|
|
|
21511
21596
|
// src/lib/mention-resolver.ts
|
|
21512
|
-
import { existsSync as
|
|
21513
|
-
import { basename as basename3, isAbsolute, join as
|
|
21597
|
+
import { existsSync as existsSync10, readdirSync as readdirSync2, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
|
|
21598
|
+
import { basename as basename3, isAbsolute, join as join7, relative as relative3, resolve as resolve9, sep as sep2 } from "path";
|
|
21514
21599
|
function blankResolution(parsed) {
|
|
21515
21600
|
return {
|
|
21516
21601
|
input: parsed.input,
|
|
@@ -21608,7 +21693,7 @@ function resolveFile(parsed, workspace) {
|
|
|
21608
21693
|
return resolution;
|
|
21609
21694
|
}
|
|
21610
21695
|
resolution.path = relPath;
|
|
21611
|
-
if (!
|
|
21696
|
+
if (!existsSync10(absolutePath)) {
|
|
21612
21697
|
resolution.warnings.push("file does not exist in the local workspace");
|
|
21613
21698
|
return resolution;
|
|
21614
21699
|
}
|
|
@@ -21641,7 +21726,7 @@ function walkSourceFiles(root, current = root, files = []) {
|
|
|
21641
21726
|
if (SKIP_DIRS.has(entry.name))
|
|
21642
21727
|
continue;
|
|
21643
21728
|
}
|
|
21644
|
-
const absolutePath =
|
|
21729
|
+
const absolutePath = join7(current, entry.name);
|
|
21645
21730
|
if (entry.isDirectory()) {
|
|
21646
21731
|
if (!SKIP_DIRS.has(entry.name))
|
|
21647
21732
|
walkSourceFiles(root, absolutePath, files);
|
|
@@ -25333,7 +25418,7 @@ var init_audit_ledger = __esm(() => {
|
|
|
25333
25418
|
|
|
25334
25419
|
// src/lib/release-compatibility.ts
|
|
25335
25420
|
import { readFileSync as readFileSync5 } from "fs";
|
|
25336
|
-
import { join as
|
|
25421
|
+
import { join as join8, resolve as resolve11 } from "path";
|
|
25337
25422
|
import { Database as Database2 } from "bun:sqlite";
|
|
25338
25423
|
function pass(id, message, details) {
|
|
25339
25424
|
return { id, status: "passed", message, details };
|
|
@@ -25345,7 +25430,7 @@ function warn(id, message, details) {
|
|
|
25345
25430
|
return { id, status: "warning", message, details };
|
|
25346
25431
|
}
|
|
25347
25432
|
function readPackageJson2(root) {
|
|
25348
|
-
return JSON.parse(readFileSync5(
|
|
25433
|
+
return JSON.parse(readFileSync5(join8(root, "package.json"), "utf8"));
|
|
25349
25434
|
}
|
|
25350
25435
|
function sortedKeys(value) {
|
|
25351
25436
|
return Object.keys(value ?? {}).sort((left, right) => left.localeCompare(right));
|
|
@@ -29358,8 +29443,8 @@ var exports_doctor = {};
|
|
|
29358
29443
|
__export(exports_doctor, {
|
|
29359
29444
|
runTodosDoctor: () => runTodosDoctor
|
|
29360
29445
|
});
|
|
29361
|
-
import { chmodSync, copyFileSync, existsSync as
|
|
29362
|
-
import { basename as basename4, dirname as dirname6, join as
|
|
29446
|
+
import { chmodSync, copyFileSync, existsSync as existsSync11, mkdirSync as mkdirSync5, statSync as statSync5 } from "fs";
|
|
29447
|
+
import { basename as basename4, dirname as dirname6, join as join9 } from "path";
|
|
29363
29448
|
function tableExists2(db, table) {
|
|
29364
29449
|
return Boolean(db.query("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(table));
|
|
29365
29450
|
}
|
|
@@ -29453,7 +29538,7 @@ function findMissingProjectRoots(db) {
|
|
|
29453
29538
|
continue;
|
|
29454
29539
|
if (!row.path.startsWith("/"))
|
|
29455
29540
|
continue;
|
|
29456
|
-
if (!
|
|
29541
|
+
if (!existsSync11(row.path))
|
|
29457
29542
|
missing++;
|
|
29458
29543
|
}
|
|
29459
29544
|
return missing;
|
|
@@ -29513,16 +29598,16 @@ function databasePermissionsAreUnsafe(dbPath) {
|
|
|
29513
29598
|
function createBackup(dbPath) {
|
|
29514
29599
|
if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
|
|
29515
29600
|
return;
|
|
29516
|
-
if (!
|
|
29601
|
+
if (!existsSync11(dbPath))
|
|
29517
29602
|
return;
|
|
29518
29603
|
const stamp = now().replace(/[:.]/g, "-");
|
|
29519
|
-
const backupDir =
|
|
29604
|
+
const backupDir = join9(dirname6(dbPath), `${basename4(dbPath)}.backup-${stamp}`);
|
|
29520
29605
|
const files = [];
|
|
29521
29606
|
mkdirSync5(backupDir, { recursive: true });
|
|
29522
29607
|
for (const source of [dbPath, `${dbPath}-wal`, `${dbPath}-shm`]) {
|
|
29523
|
-
if (!
|
|
29608
|
+
if (!existsSync11(source))
|
|
29524
29609
|
continue;
|
|
29525
|
-
const target =
|
|
29610
|
+
const target = join9(backupDir, basename4(source));
|
|
29526
29611
|
copyFileSync(source, target);
|
|
29527
29612
|
files.push(target);
|
|
29528
29613
|
}
|
|
@@ -32258,7 +32343,7 @@ var init_agent_run_dispatcher = __esm(() => {
|
|
|
32258
32343
|
});
|
|
32259
32344
|
|
|
32260
32345
|
// src/lib/verification-providers.ts
|
|
32261
|
-
import { existsSync as
|
|
32346
|
+
import { existsSync as existsSync12, readFileSync as readFileSync6 } from "fs";
|
|
32262
32347
|
function normalizeName5(name) {
|
|
32263
32348
|
const normalized = name.trim().toLowerCase();
|
|
32264
32349
|
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(normalized)) {
|
|
@@ -32410,7 +32495,7 @@ Timed out after ${provider.timeout_ms}ms`);
|
|
|
32410
32495
|
};
|
|
32411
32496
|
}
|
|
32412
32497
|
function runCiLogProvider(input) {
|
|
32413
|
-
const text = input.log_text ?? (input.log_path &&
|
|
32498
|
+
const text = input.log_text ?? (input.log_path && existsSync12(input.log_path) ? readFileSync6(input.log_path, "utf-8") : "");
|
|
32414
32499
|
return {
|
|
32415
32500
|
status: classifyLog(text),
|
|
32416
32501
|
attempts: 1,
|
|
@@ -32422,7 +32507,7 @@ function runBrowserProvider(input) {
|
|
|
32422
32507
|
if (!input.artifact_path) {
|
|
32423
32508
|
return { status: "unknown", attempts: 1, exit_code: null, output_summary: "browser provider needs a screenshot or artifact path" };
|
|
32424
32509
|
}
|
|
32425
|
-
if (!
|
|
32510
|
+
if (!existsSync12(input.artifact_path)) {
|
|
32426
32511
|
return { status: "failed", attempts: 1, exit_code: null, output_summary: `artifact not found: ${input.artifact_path}` };
|
|
32427
32512
|
}
|
|
32428
32513
|
return {
|
|
@@ -34571,7 +34656,7 @@ var package_default;
|
|
|
34571
34656
|
var init_package = __esm(() => {
|
|
34572
34657
|
package_default = {
|
|
34573
34658
|
name: "@hasna/todos",
|
|
34574
|
-
version: "0.13.
|
|
34659
|
+
version: "0.13.7",
|
|
34575
34660
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
34576
34661
|
type: "module",
|
|
34577
34662
|
main: "dist/index.js",
|
|
@@ -35641,6 +35726,7 @@ function task(input) {
|
|
|
35641
35726
|
reason: "Bundled deterministic onboarding fixture",
|
|
35642
35727
|
spawned_from_session: null,
|
|
35643
35728
|
assigned_by: null,
|
|
35729
|
+
created_by: null,
|
|
35644
35730
|
assigned_from_project: null,
|
|
35645
35731
|
task_type: "onboarding",
|
|
35646
35732
|
cost_tokens: 0,
|
|
@@ -36838,8 +36924,8 @@ __export(exports_local_extensions, {
|
|
|
36838
36924
|
discoverLocalExtensions: () => discoverLocalExtensions
|
|
36839
36925
|
});
|
|
36840
36926
|
import { createHash as createHash9, createVerify } from "crypto";
|
|
36841
|
-
import { existsSync as
|
|
36842
|
-
import { basename as basename5, join as
|
|
36927
|
+
import { existsSync as existsSync13, readdirSync as readdirSync3, readFileSync as readFileSync8, statSync as statSync6 } from "fs";
|
|
36928
|
+
import { basename as basename5, join as join10, resolve as resolve13 } from "path";
|
|
36843
36929
|
function isObject2(value) {
|
|
36844
36930
|
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
36845
36931
|
}
|
|
@@ -37098,10 +37184,10 @@ function verifyExtensionSignature(input) {
|
|
|
37098
37184
|
}
|
|
37099
37185
|
function inspectExtensionSource(source3) {
|
|
37100
37186
|
const resolved = resolve13(source3);
|
|
37101
|
-
if (!
|
|
37187
|
+
if (!existsSync13(resolved))
|
|
37102
37188
|
throw new Error(`extension source not found: ${source3}`);
|
|
37103
37189
|
const stat = statSync6(resolved);
|
|
37104
|
-
const manifestPath = stat.isDirectory() ? [
|
|
37190
|
+
const manifestPath = stat.isDirectory() ? [join10(resolved, "todos.extension.json"), join10(resolved, "extension.json")].find(existsSync13) : resolved;
|
|
37105
37191
|
if (!manifestPath)
|
|
37106
37192
|
throw new Error(`extension directory ${source3} is missing todos.extension.json`);
|
|
37107
37193
|
const raw = readFileSync8(manifestPath);
|
|
@@ -37197,20 +37283,20 @@ function projectExtensionSources(projectPath) {
|
|
|
37197
37283
|
return [];
|
|
37198
37284
|
const root = resolve13(projectPath);
|
|
37199
37285
|
const candidates = [
|
|
37200
|
-
|
|
37201
|
-
|
|
37286
|
+
join10(root, "todos.extension.json"),
|
|
37287
|
+
join10(root, ".todos", "todos.extension.json")
|
|
37202
37288
|
];
|
|
37203
|
-
const extensionDir =
|
|
37204
|
-
if (
|
|
37289
|
+
const extensionDir = join10(root, ".todos", "extensions");
|
|
37290
|
+
if (existsSync13(extensionDir)) {
|
|
37205
37291
|
for (const entry of readdirSync3(extensionDir)) {
|
|
37206
37292
|
if (entry.startsWith("."))
|
|
37207
37293
|
continue;
|
|
37208
|
-
const full =
|
|
37294
|
+
const full = join10(extensionDir, entry);
|
|
37209
37295
|
if (statSync6(full).isDirectory() || entry.endsWith(".json"))
|
|
37210
37296
|
candidates.push(full);
|
|
37211
37297
|
}
|
|
37212
37298
|
}
|
|
37213
|
-
return candidates.filter(
|
|
37299
|
+
return candidates.filter(existsSync13);
|
|
37214
37300
|
}
|
|
37215
37301
|
function discoverLocalExtensions(options = {}) {
|
|
37216
37302
|
const config = loadConfig();
|
|
@@ -41617,9 +41703,9 @@ __export(exports_extract, {
|
|
|
41617
41703
|
buildCodebaseIndex: () => buildCodebaseIndex,
|
|
41618
41704
|
EXTRACT_TAGS: () => EXTRACT_TAGS
|
|
41619
41705
|
});
|
|
41620
|
-
import { existsSync as
|
|
41706
|
+
import { existsSync as existsSync14, readFileSync as readFileSync9, statSync as statSync7 } from "fs";
|
|
41621
41707
|
import { createHash as createHash11 } from "crypto";
|
|
41622
|
-
import { relative as relative5, resolve as resolve14, join as
|
|
41708
|
+
import { relative as relative5, resolve as resolve14, join as join11 } from "path";
|
|
41623
41709
|
function stableHash(value) {
|
|
41624
41710
|
return createHash11("sha256").update(value).digest("hex");
|
|
41625
41711
|
}
|
|
@@ -41628,8 +41714,8 @@ function normalizePathForMatch(value) {
|
|
|
41628
41714
|
}
|
|
41629
41715
|
function readGitignorePatterns(basePath) {
|
|
41630
41716
|
const root = statSync7(basePath).isFile() ? resolve14(basePath, "..") : basePath;
|
|
41631
|
-
const gitignorePath =
|
|
41632
|
-
if (!
|
|
41717
|
+
const gitignorePath = join11(root, ".gitignore");
|
|
41718
|
+
if (!existsSync14(gitignorePath))
|
|
41633
41719
|
return [];
|
|
41634
41720
|
try {
|
|
41635
41721
|
return readFileSync9(gitignorePath, "utf-8").split(`
|
|
@@ -41771,7 +41857,7 @@ function buildCodebaseIndex(options) {
|
|
|
41771
41857
|
const files = collectFiles(basePath, extensions, excludes, respectGitignore);
|
|
41772
41858
|
const indexed = [];
|
|
41773
41859
|
for (const file of files) {
|
|
41774
|
-
const fullPath = statSync7(basePath).isFile() ? basePath :
|
|
41860
|
+
const fullPath = statSync7(basePath).isFile() ? basePath : join11(basePath, file);
|
|
41775
41861
|
try {
|
|
41776
41862
|
const source3 = readFileSync9(fullPath, "utf-8");
|
|
41777
41863
|
const relPath = statSync7(basePath).isFile() ? relative5(resolve14(basePath, ".."), fullPath) : file;
|
|
@@ -41802,7 +41888,7 @@ function extractTodos(options, db) {
|
|
|
41802
41888
|
const files = collectFiles(basePath, extensions, excludes, respectGitignore);
|
|
41803
41889
|
const allComments = [];
|
|
41804
41890
|
for (const file of files) {
|
|
41805
|
-
const fullPath = statSync7(basePath).isFile() ? basePath :
|
|
41891
|
+
const fullPath = statSync7(basePath).isFile() ? basePath : join11(basePath, file);
|
|
41806
41892
|
try {
|
|
41807
41893
|
const source3 = readFileSync9(fullPath, "utf-8");
|
|
41808
41894
|
const relPath = statSync7(basePath).isFile() ? relative5(resolve14(basePath, ".."), fullPath) : file;
|
|
@@ -42753,7 +42839,7 @@ __export(exports_builtin_templates, {
|
|
|
42753
42839
|
BUILTIN_TEMPLATES: () => BUILTIN_TEMPLATES
|
|
42754
42840
|
});
|
|
42755
42841
|
import { mkdirSync as mkdirSync7, writeFileSync as writeFileSync4 } from "fs";
|
|
42756
|
-
import { join as
|
|
42842
|
+
import { join as join12 } from "path";
|
|
42757
42843
|
function templateMetadata(template) {
|
|
42758
42844
|
return {
|
|
42759
42845
|
source: BUILTIN_TEMPLATE_LIBRARY_SOURCE,
|
|
@@ -42812,7 +42898,7 @@ function writeBuiltinTemplateFiles(directory) {
|
|
|
42812
42898
|
mkdirSync7(directory, { recursive: true });
|
|
42813
42899
|
const files = [];
|
|
42814
42900
|
for (const entry of exportBuiltinTemplateFiles()) {
|
|
42815
|
-
const path =
|
|
42901
|
+
const path = join12(directory, entry.filename);
|
|
42816
42902
|
writeFileSync4(path, `${JSON.stringify(entry.template, null, 2)}
|
|
42817
42903
|
`, "utf-8");
|
|
42818
42904
|
files.push(path);
|
|
@@ -43338,16 +43424,16 @@ __export(exports_environment_snapshots, {
|
|
|
43338
43424
|
captureEnvironmentSnapshot: () => captureEnvironmentSnapshot
|
|
43339
43425
|
});
|
|
43340
43426
|
import { createHash as createHash12 } from "crypto";
|
|
43341
|
-
import { existsSync as
|
|
43427
|
+
import { existsSync as existsSync15, readFileSync as readFileSync10, statSync as statSync8 } from "fs";
|
|
43342
43428
|
import { hostname as hostname2, platform, arch } from "os";
|
|
43343
|
-
import { dirname as dirname8, join as
|
|
43429
|
+
import { dirname as dirname8, join as join13, resolve as resolve15 } from "path";
|
|
43344
43430
|
import { tmpdir as tmpdir3 } from "os";
|
|
43345
43431
|
function sha2567(value) {
|
|
43346
43432
|
return createHash12("sha256").update(value).digest("hex");
|
|
43347
43433
|
}
|
|
43348
43434
|
function fileRecord(root, relativePath) {
|
|
43349
|
-
const path =
|
|
43350
|
-
if (!
|
|
43435
|
+
const path = join13(root, relativePath);
|
|
43436
|
+
if (!existsSync15(path))
|
|
43351
43437
|
return null;
|
|
43352
43438
|
const stat = statSync8(path);
|
|
43353
43439
|
if (!stat.isFile())
|
|
@@ -43359,7 +43445,7 @@ function manifestRecord(root, relativePath) {
|
|
|
43359
43445
|
const base = fileRecord(root, relativePath);
|
|
43360
43446
|
if (!base)
|
|
43361
43447
|
return null;
|
|
43362
|
-
const parsed = readJsonFile(
|
|
43448
|
+
const parsed = readJsonFile(join13(root, relativePath));
|
|
43363
43449
|
if (!parsed)
|
|
43364
43450
|
return { ...base, redacted: {} };
|
|
43365
43451
|
const redacted = redactValue({
|
|
@@ -43454,8 +43540,8 @@ function commandEnv(env, includeValues) {
|
|
|
43454
43540
|
function defaultSnapshotDir() {
|
|
43455
43541
|
const dbPath = getDatabasePath();
|
|
43456
43542
|
if (dbPath === ":memory:" || dbPath.startsWith("file::memory:"))
|
|
43457
|
-
return
|
|
43458
|
-
return
|
|
43543
|
+
return join13(tmpdir3(), "hasna-todos", "environment-snapshots");
|
|
43544
|
+
return join13(dirname8(resolve15(dbPath)), "environment-snapshots");
|
|
43459
43545
|
}
|
|
43460
43546
|
function snapshotWithId(snapshot) {
|
|
43461
43547
|
const digest = sha2567(JSON.stringify(snapshot)).slice(0, 24);
|
|
@@ -43502,7 +43588,7 @@ function captureEnvironmentSnapshot(input = {}) {
|
|
|
43502
43588
|
});
|
|
43503
43589
|
}
|
|
43504
43590
|
function writeEnvironmentSnapshot(snapshot, outputPath) {
|
|
43505
|
-
const path = outputPath ? resolve15(outputPath) :
|
|
43591
|
+
const path = outputPath ? resolve15(outputPath) : join13(defaultSnapshotDir(), `${snapshot.id}.json`);
|
|
43506
43592
|
ensureDir2(dirname8(path));
|
|
43507
43593
|
writeJsonFile(path, snapshot);
|
|
43508
43594
|
return path;
|
|
@@ -44401,7 +44487,11 @@ function createLocalSqliteTodosStorageAdapter(options = {}) {
|
|
|
44401
44487
|
sync: true
|
|
44402
44488
|
},
|
|
44403
44489
|
tasks: {
|
|
44404
|
-
create: (input) => createTask(
|
|
44490
|
+
create: (input, context) => createTask({
|
|
44491
|
+
...input,
|
|
44492
|
+
agent_id: input.agent_id ?? context?.agentId,
|
|
44493
|
+
created_by: input.created_by ?? input.agent_id ?? context?.agentId
|
|
44494
|
+
}, database()),
|
|
44405
44495
|
get: (id) => getTask(id, database()),
|
|
44406
44496
|
resolveRef: (ref) => resolveTaskRefLocal(database(), ref),
|
|
44407
44497
|
list: (filter = {}) => listTasksMaybeSearch(filter, database()),
|
|
@@ -45540,6 +45630,10 @@ class PostgresJsonRecordStore {
|
|
|
45540
45630
|
conds.push(`payload->>'assigned_to' = ${p(filter.assigned_to)}`);
|
|
45541
45631
|
if (filter.agent_id !== undefined)
|
|
45542
45632
|
conds.push(`payload->>'agent_id' = ${p(filter.agent_id)}`);
|
|
45633
|
+
if (filter.created_by !== undefined)
|
|
45634
|
+
conds.push(`LOWER(payload->>'created_by') = LOWER(${p(filter.created_by)})`);
|
|
45635
|
+
if (filter.not_created_by !== undefined)
|
|
45636
|
+
conds.push(`(payload->>'created_by' IS NULL OR LOWER(payload->>'created_by') <> LOWER(${p(filter.not_created_by)}))`);
|
|
45543
45637
|
if (filter.session_id !== undefined)
|
|
45544
45638
|
conds.push(`payload->>'session_id' = ${p(filter.session_id)}`);
|
|
45545
45639
|
if (filter.tags?.length) {
|
|
@@ -46053,7 +46147,7 @@ async function createTask3(input, store, context) {
|
|
|
46053
46147
|
description: input.description ?? null,
|
|
46054
46148
|
status: input.status ?? "pending",
|
|
46055
46149
|
priority: input.priority ?? "medium",
|
|
46056
|
-
agent_id: input.agent_id ?? null,
|
|
46150
|
+
agent_id: input.agent_id ?? context?.agentId ?? null,
|
|
46057
46151
|
assigned_to: input.assigned_to ?? null,
|
|
46058
46152
|
session_id: input.session_id ?? context?.sessionId ?? null,
|
|
46059
46153
|
working_dir: input.working_dir ?? null,
|
|
@@ -46078,7 +46172,8 @@ async function createTask3(input, store, context) {
|
|
|
46078
46172
|
confidence: input.confidence ?? null,
|
|
46079
46173
|
reason: input.reason ?? null,
|
|
46080
46174
|
spawned_from_session: input.spawned_from_session ?? null,
|
|
46081
|
-
assigned_by: input.assigned_by ?? null,
|
|
46175
|
+
assigned_by: input.assigned_by ?? input.agent_id ?? context?.agentId ?? null,
|
|
46176
|
+
created_by: input.created_by ?? input.agent_id ?? context?.agentId ?? null,
|
|
46082
46177
|
assigned_from_project: input.assigned_from_project ?? null,
|
|
46083
46178
|
task_type: input.task_type ?? null,
|
|
46084
46179
|
cost_tokens: 0,
|
|
@@ -46115,7 +46210,8 @@ async function updateTask2(id, input, store) {
|
|
|
46115
46210
|
tags: input.tags ?? existing.tags,
|
|
46116
46211
|
metadata: input.metadata ?? existing.metadata,
|
|
46117
46212
|
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
|
|
46213
|
+
task_list_id: input.task_list_id !== undefined ? input.task_list_id : existing.task_list_id,
|
|
46214
|
+
created_by: existing.created_by
|
|
46119
46215
|
};
|
|
46120
46216
|
await store.upsert("tasks", task2);
|
|
46121
46217
|
return task2;
|
|
@@ -47798,7 +47894,7 @@ var init_headless_boundaries = __esm(() => {
|
|
|
47798
47894
|
});
|
|
47799
47895
|
|
|
47800
47896
|
// src/server/routes.ts
|
|
47801
|
-
import { join as
|
|
47897
|
+
import { join as join14, resolve as resolve16, sep as sep3 } from "path";
|
|
47802
47898
|
function parseFieldsParam(url) {
|
|
47803
47899
|
const fieldsParam = url.searchParams.get("fields");
|
|
47804
47900
|
return fieldsParam ? fieldsParam.split(",").map((f) => f.trim()).filter(Boolean) : undefined;
|
|
@@ -47979,11 +48075,15 @@ async function handleCreateTask(req, ctx, json2, taskToSummary2) {
|
|
|
47979
48075
|
const body = await req.json();
|
|
47980
48076
|
if (!body.title)
|
|
47981
48077
|
return json2({ error: "Missing 'title'" }, 400);
|
|
48078
|
+
const createdBy = body.created_by ?? body.agent_id ?? "dashboard";
|
|
47982
48079
|
const task2 = createTask({
|
|
47983
48080
|
title: body.title,
|
|
47984
48081
|
description: body.description,
|
|
47985
48082
|
priority: body.priority,
|
|
47986
|
-
project_id: body.project_id
|
|
48083
|
+
project_id: body.project_id,
|
|
48084
|
+
agent_id: body.agent_id ?? createdBy,
|
|
48085
|
+
created_by: createdBy,
|
|
48086
|
+
...body.assigned_to ? { assigned_to: body.assigned_to } : {}
|
|
47987
48087
|
});
|
|
47988
48088
|
ctx.broadcastEvent({ type: "task", task_id: task2.id, action: "created", agent_id: task2.agent_id, project_id: task2.project_id });
|
|
47989
48089
|
return json2(taskToSummary2(task2), 201);
|
|
@@ -48589,7 +48689,7 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
|
|
|
48589
48689
|
if (!ctx.dashboardExists || method !== "GET" && method !== "HEAD")
|
|
48590
48690
|
return null;
|
|
48591
48691
|
if (path !== "/") {
|
|
48592
|
-
const filePath =
|
|
48692
|
+
const filePath = join14(ctx.dashboardDir, path);
|
|
48593
48693
|
const resolvedFile = resolve16(filePath);
|
|
48594
48694
|
const resolvedBase = resolve16(ctx.dashboardDir);
|
|
48595
48695
|
if (!resolvedFile.startsWith(resolvedBase + sep3) && resolvedFile !== resolvedBase) {
|
|
@@ -48599,7 +48699,7 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
|
|
|
48599
48699
|
if (res2)
|
|
48600
48700
|
return res2;
|
|
48601
48701
|
}
|
|
48602
|
-
const indexPath =
|
|
48702
|
+
const indexPath = join14(ctx.dashboardDir, "index.html");
|
|
48603
48703
|
const res = serveStaticFile2(indexPath);
|
|
48604
48704
|
if (res)
|
|
48605
48705
|
return res;
|
|
@@ -50776,6 +50876,8 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
50776
50876
|
...url.searchParams.get("task_list_id") ? { task_list_id: url.searchParams.get("task_list_id") } : {},
|
|
50777
50877
|
...url.searchParams.get("assigned_to") ? { assigned_to: url.searchParams.get("assigned_to") } : {},
|
|
50778
50878
|
...url.searchParams.get("agent_id") ? { agent_id: url.searchParams.get("agent_id") } : {},
|
|
50879
|
+
...url.searchParams.get("created_by") ? { created_by: url.searchParams.get("created_by") } : {},
|
|
50880
|
+
...url.searchParams.get("not_created_by") ? { not_created_by: url.searchParams.get("not_created_by") } : {},
|
|
50779
50881
|
...url.searchParams.get("tags") ? {
|
|
50780
50882
|
tags: url.searchParams.get("tags").split(",").map((tag) => tag.trim()).filter(Boolean)
|
|
50781
50883
|
} : {},
|
|
@@ -51734,27 +51836,27 @@ __export(exports_serve, {
|
|
|
51734
51836
|
SECURITY_HEADERS: () => SECURITY_HEADERS,
|
|
51735
51837
|
MIME_TYPES: () => MIME_TYPES
|
|
51736
51838
|
});
|
|
51737
|
-
import { existsSync as
|
|
51738
|
-
import { join as
|
|
51839
|
+
import { existsSync as existsSync16 } from "fs";
|
|
51840
|
+
import { join as join15, dirname as dirname9, extname } from "path";
|
|
51739
51841
|
import { fileURLToPath } from "url";
|
|
51740
51842
|
function resolveDashboardDir() {
|
|
51741
51843
|
const candidates = [];
|
|
51742
51844
|
try {
|
|
51743
51845
|
const scriptDir = dirname9(fileURLToPath(import.meta.url));
|
|
51744
|
-
candidates.push(
|
|
51745
|
-
candidates.push(
|
|
51846
|
+
candidates.push(join15(scriptDir, "..", "dashboard", "dist"));
|
|
51847
|
+
candidates.push(join15(scriptDir, "..", "..", "dashboard", "dist"));
|
|
51746
51848
|
} catch {}
|
|
51747
51849
|
if (process.argv[1]) {
|
|
51748
51850
|
const mainDir = dirname9(process.argv[1]);
|
|
51749
|
-
candidates.push(
|
|
51750
|
-
candidates.push(
|
|
51851
|
+
candidates.push(join15(mainDir, "..", "dashboard", "dist"));
|
|
51852
|
+
candidates.push(join15(mainDir, "..", "..", "dashboard", "dist"));
|
|
51751
51853
|
}
|
|
51752
|
-
candidates.push(
|
|
51854
|
+
candidates.push(join15(process.cwd(), "dashboard", "dist"));
|
|
51753
51855
|
for (const candidate of candidates) {
|
|
51754
|
-
if (
|
|
51856
|
+
if (existsSync16(candidate))
|
|
51755
51857
|
return candidate;
|
|
51756
51858
|
}
|
|
51757
|
-
return
|
|
51859
|
+
return join15(process.cwd(), "dashboard", "dist");
|
|
51758
51860
|
}
|
|
51759
51861
|
function getProvidedApiKey(req) {
|
|
51760
51862
|
const headerKey = req.headers.get("x-api-key");
|
|
@@ -51826,7 +51928,7 @@ function json(data, status = 200, headers) {
|
|
|
51826
51928
|
});
|
|
51827
51929
|
}
|
|
51828
51930
|
function serveStaticFile(filePath) {
|
|
51829
|
-
if (!
|
|
51931
|
+
if (!existsSync16(filePath))
|
|
51830
51932
|
return null;
|
|
51831
51933
|
const ext = extname(filePath);
|
|
51832
51934
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
@@ -51927,7 +52029,7 @@ data: ${data}
|
|
|
51927
52029
|
filteredSseClients.delete(client);
|
|
51928
52030
|
}
|
|
51929
52031
|
const dashboardDir = resolveDashboardDir();
|
|
51930
|
-
const dashboardExists =
|
|
52032
|
+
const dashboardExists = existsSync16(dashboardDir);
|
|
51931
52033
|
if (!dashboardExists) {
|
|
51932
52034
|
console.error(`
|
|
51933
52035
|
Dashboard not found at: ${dashboardDir}`);
|