@hasna/todos 0.13.0 → 0.13.2
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 +10 -0
- package/dist/cli/cloud-router.d.ts +21 -5
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/config-serve-commands.d.ts.map +1 -1
- package/dist/cli/commands/project-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +468 -238
- package/dist/contracts.js +20 -10
- package/dist/db/database.d.ts.map +1 -1
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -13
- package/dist/lib/dependency-graph.d.ts +108 -0
- package/dist/lib/dependency-graph.d.ts.map +1 -1
- package/dist/lib/redaction.d.ts.map +1 -1
- package/dist/mcp/index.js +28 -13
- package/dist/mcp.js +2 -2
- package/dist/registry.js +20 -10
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +65 -30
- package/dist/server/port.d.ts +52 -0
- package/dist/server/port.d.ts.map +1 -0
- package/dist/server/serve.d.ts.map +1 -1
- package/dist/storage/interfaces.d.ts +14 -0
- package/dist/storage/interfaces.d.ts.map +1 -1
- package/dist/storage.js +21 -9
- package/dist/types/index.d.ts +15 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -2123,7 +2123,7 @@ var package_default;
|
|
|
2123
2123
|
var init_package = __esm(() => {
|
|
2124
2124
|
package_default = {
|
|
2125
2125
|
name: "@hasna/todos",
|
|
2126
|
-
version: "0.13.
|
|
2126
|
+
version: "0.13.2",
|
|
2127
2127
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
2128
2128
|
type: "module",
|
|
2129
2129
|
main: "dist/index.js",
|
|
@@ -2175,7 +2175,7 @@ var init_package = __esm(() => {
|
|
|
2175
2175
|
"backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
|
|
2176
2176
|
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
2177
2177
|
"build:dashboard": "cd dashboard && bun install --frozen-lockfile && bun run build",
|
|
2178
|
-
typecheck: "tsc --noEmit",
|
|
2178
|
+
typecheck: "tsc --noEmit -p tsconfig.typecheck.json",
|
|
2179
2179
|
test: "bun test",
|
|
2180
2180
|
"test:no-cloud": "bun test src/no-cloud-boundary.test.ts src/local-first.test.ts src/lib/public-release-gate.test.ts",
|
|
2181
2181
|
"dev:cli": "bun run src/cli/index.tsx",
|
|
@@ -2250,6 +2250,161 @@ var init_package_version = __esm(() => {
|
|
|
2250
2250
|
init_package();
|
|
2251
2251
|
});
|
|
2252
2252
|
|
|
2253
|
+
// src/types/index.ts
|
|
2254
|
+
function isBlockingDependencyStatus(status) {
|
|
2255
|
+
return status !== "completed" && status !== "cancelled";
|
|
2256
|
+
}
|
|
2257
|
+
var TASK_STATUSES, TASK_PRIORITIES, VersionConflictError, TaskNotFoundError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DispatchNotFoundError;
|
|
2258
|
+
var init_types = __esm(() => {
|
|
2259
|
+
TASK_STATUSES = [
|
|
2260
|
+
"pending",
|
|
2261
|
+
"in_progress",
|
|
2262
|
+
"completed",
|
|
2263
|
+
"failed",
|
|
2264
|
+
"cancelled"
|
|
2265
|
+
];
|
|
2266
|
+
TASK_PRIORITIES = [
|
|
2267
|
+
"low",
|
|
2268
|
+
"medium",
|
|
2269
|
+
"high",
|
|
2270
|
+
"critical"
|
|
2271
|
+
];
|
|
2272
|
+
VersionConflictError = class VersionConflictError extends Error {
|
|
2273
|
+
taskId;
|
|
2274
|
+
expectedVersion;
|
|
2275
|
+
actualVersion;
|
|
2276
|
+
static code = "VERSION_CONFLICT";
|
|
2277
|
+
static suggestion = "Fetch the task with get_task to get the current version before updating.";
|
|
2278
|
+
constructor(taskId, expectedVersion, actualVersion) {
|
|
2279
|
+
super(`Version conflict for task ${taskId}: expected ${expectedVersion}, got ${actualVersion}`);
|
|
2280
|
+
this.taskId = taskId;
|
|
2281
|
+
this.expectedVersion = expectedVersion;
|
|
2282
|
+
this.actualVersion = actualVersion;
|
|
2283
|
+
this.name = "VersionConflictError";
|
|
2284
|
+
}
|
|
2285
|
+
};
|
|
2286
|
+
TaskNotFoundError = class TaskNotFoundError extends Error {
|
|
2287
|
+
taskId;
|
|
2288
|
+
static code = "TASK_NOT_FOUND";
|
|
2289
|
+
static suggestion = "Verify the task ID. Use list_tasks or search_tasks to find the correct ID.";
|
|
2290
|
+
constructor(taskId) {
|
|
2291
|
+
super(`Task not found: ${taskId}`);
|
|
2292
|
+
this.taskId = taskId;
|
|
2293
|
+
this.name = "TaskNotFoundError";
|
|
2294
|
+
}
|
|
2295
|
+
};
|
|
2296
|
+
ProjectNotFoundError = class ProjectNotFoundError extends Error {
|
|
2297
|
+
projectId;
|
|
2298
|
+
static code = "PROJECT_NOT_FOUND";
|
|
2299
|
+
static suggestion = "Use list_projects to see available projects.";
|
|
2300
|
+
constructor(projectId) {
|
|
2301
|
+
super(`Project not found: ${projectId}`);
|
|
2302
|
+
this.projectId = projectId;
|
|
2303
|
+
this.name = "ProjectNotFoundError";
|
|
2304
|
+
}
|
|
2305
|
+
};
|
|
2306
|
+
ResourceConflictError = class ResourceConflictError extends Error {
|
|
2307
|
+
code;
|
|
2308
|
+
constructor(code, message) {
|
|
2309
|
+
super(message);
|
|
2310
|
+
this.code = code;
|
|
2311
|
+
this.name = "ResourceConflictError";
|
|
2312
|
+
}
|
|
2313
|
+
};
|
|
2314
|
+
PlanNotFoundError = class PlanNotFoundError extends Error {
|
|
2315
|
+
planId;
|
|
2316
|
+
static code = "PLAN_NOT_FOUND";
|
|
2317
|
+
static suggestion = "Use list_plans to see available plans.";
|
|
2318
|
+
constructor(planId) {
|
|
2319
|
+
super(`Plan not found: ${planId}`);
|
|
2320
|
+
this.planId = planId;
|
|
2321
|
+
this.name = "PlanNotFoundError";
|
|
2322
|
+
}
|
|
2323
|
+
};
|
|
2324
|
+
LockError = class LockError extends Error {
|
|
2325
|
+
taskId;
|
|
2326
|
+
lockedBy;
|
|
2327
|
+
static code = "LOCK_ERROR";
|
|
2328
|
+
static suggestion = "Wait for the lock to expire (30 min) or contact the lock holder.";
|
|
2329
|
+
constructor(taskId, lockedBy) {
|
|
2330
|
+
super(`Task ${taskId} is locked by ${lockedBy}`);
|
|
2331
|
+
this.taskId = taskId;
|
|
2332
|
+
this.lockedBy = lockedBy;
|
|
2333
|
+
this.name = "LockError";
|
|
2334
|
+
}
|
|
2335
|
+
};
|
|
2336
|
+
AgentNotFoundError = class AgentNotFoundError extends Error {
|
|
2337
|
+
agentId;
|
|
2338
|
+
static code = "AGENT_NOT_FOUND";
|
|
2339
|
+
static suggestion = "Use register_agent to create the agent first, or list_agents to find existing ones.";
|
|
2340
|
+
constructor(agentId) {
|
|
2341
|
+
super(`Agent not found: ${agentId}`);
|
|
2342
|
+
this.agentId = agentId;
|
|
2343
|
+
this.name = "AgentNotFoundError";
|
|
2344
|
+
}
|
|
2345
|
+
};
|
|
2346
|
+
IdentityAliasAmbiguousError = class IdentityAliasAmbiguousError extends Error {
|
|
2347
|
+
code = "IDENTITY_ALIAS_AMBIGUOUS";
|
|
2348
|
+
candidates;
|
|
2349
|
+
constructor(subject, candidates = []) {
|
|
2350
|
+
super(`Identity alias or source is ambiguous: ${subject}`);
|
|
2351
|
+
this.name = "IdentityAliasAmbiguousError";
|
|
2352
|
+
this.candidates = [...new Set(candidates)].sort();
|
|
2353
|
+
}
|
|
2354
|
+
};
|
|
2355
|
+
IdentityIdImmutableError = class IdentityIdImmutableError extends Error {
|
|
2356
|
+
code = "IDENTITY_ID_IMMUTABLE";
|
|
2357
|
+
constructor(agentId) {
|
|
2358
|
+
super(`IDENTITY_ID_IMMUTABLE: canonical identity for agent ${agentId} cannot be replaced`);
|
|
2359
|
+
this.name = "IdentityIdImmutableError";
|
|
2360
|
+
}
|
|
2361
|
+
};
|
|
2362
|
+
TaskListNotFoundError = class TaskListNotFoundError extends Error {
|
|
2363
|
+
taskListId;
|
|
2364
|
+
static code = "TASK_LIST_NOT_FOUND";
|
|
2365
|
+
static suggestion = "Use list_task_lists to see available lists.";
|
|
2366
|
+
constructor(taskListId) {
|
|
2367
|
+
super(`Task list not found: ${taskListId}`);
|
|
2368
|
+
this.taskListId = taskListId;
|
|
2369
|
+
this.name = "TaskListNotFoundError";
|
|
2370
|
+
}
|
|
2371
|
+
};
|
|
2372
|
+
DependencyCycleError = class DependencyCycleError extends Error {
|
|
2373
|
+
taskId;
|
|
2374
|
+
dependsOn;
|
|
2375
|
+
static code = "DEPENDENCY_CYCLE";
|
|
2376
|
+
static suggestion = "Check the dependency chain with get_task to avoid circular references.";
|
|
2377
|
+
constructor(taskId, dependsOn) {
|
|
2378
|
+
super(`Adding dependency ${taskId} -> ${dependsOn} would create a cycle`);
|
|
2379
|
+
this.taskId = taskId;
|
|
2380
|
+
this.dependsOn = dependsOn;
|
|
2381
|
+
this.name = "DependencyCycleError";
|
|
2382
|
+
}
|
|
2383
|
+
};
|
|
2384
|
+
CompletionGuardError = class CompletionGuardError extends Error {
|
|
2385
|
+
reason;
|
|
2386
|
+
retryAfterSeconds;
|
|
2387
|
+
static code = "COMPLETION_BLOCKED";
|
|
2388
|
+
static suggestion = "Wait for the cooldown period, then retry.";
|
|
2389
|
+
constructor(reason, retryAfterSeconds) {
|
|
2390
|
+
super(reason);
|
|
2391
|
+
this.reason = reason;
|
|
2392
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
2393
|
+
this.name = "CompletionGuardError";
|
|
2394
|
+
}
|
|
2395
|
+
};
|
|
2396
|
+
DispatchNotFoundError = class DispatchNotFoundError extends Error {
|
|
2397
|
+
dispatchId;
|
|
2398
|
+
static code = "DISPATCH_NOT_FOUND";
|
|
2399
|
+
static suggestion = "Check the dispatch ID with list_dispatches.";
|
|
2400
|
+
constructor(dispatchId) {
|
|
2401
|
+
super(`Dispatch not found: ${dispatchId}`);
|
|
2402
|
+
this.dispatchId = dispatchId;
|
|
2403
|
+
this.name = "DispatchNotFoundError";
|
|
2404
|
+
}
|
|
2405
|
+
};
|
|
2406
|
+
});
|
|
2407
|
+
|
|
2253
2408
|
// src/lib/sync-utils.ts
|
|
2254
2409
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
2255
2410
|
import { join } from "path";
|
|
@@ -2472,11 +2627,15 @@ function secretPatterns() {
|
|
|
2472
2627
|
return [...customPatterns(), ...DEFAULT_SECRET_PATTERNS];
|
|
2473
2628
|
}
|
|
2474
2629
|
function isRedactionPlaceholderMatch(match) {
|
|
2475
|
-
const placeholder = String.raw`\[REDACTED(?:_[A-Z_]+)?\]`;
|
|
2476
2630
|
const trimmed = match.trim();
|
|
2477
|
-
return new RegExp(`^${
|
|
2631
|
+
return new RegExp(`^${REDACTION_PLACEHOLDER}$`).test(trimmed) || new RegExp(`=\\s*['"]?${REDACTION_PLACEHOLDER}['"]?$`).test(trimmed);
|
|
2632
|
+
}
|
|
2633
|
+
function isRedactionPlaceholderKey(key) {
|
|
2634
|
+
return new RegExp(`^${REDACTION_PLACEHOLDER}$`).test(key.trim());
|
|
2478
2635
|
}
|
|
2479
2636
|
function isSecretKey(key) {
|
|
2637
|
+
if (isRedactionPlaceholderKey(key))
|
|
2638
|
+
return false;
|
|
2480
2639
|
if (NON_SECRET_USAGE_KEYS.has(key.toLowerCase()))
|
|
2481
2640
|
return false;
|
|
2482
2641
|
if (DEFAULT_SECRET_KEY_PATTERN.test(key))
|
|
@@ -2537,7 +2696,7 @@ function upsertSecretSafetyConfig(input) {
|
|
|
2537
2696
|
saveConfig({ ...config, secret_safety: next });
|
|
2538
2697
|
return next;
|
|
2539
2698
|
}
|
|
2540
|
-
var DEFAULT_SECRET_PATTERNS, DEFAULT_SECRET_KEY_PATTERN, NON_SECRET_USAGE_KEYS;
|
|
2699
|
+
var DEFAULT_SECRET_PATTERNS, DEFAULT_SECRET_KEY_PATTERN, NON_SECRET_USAGE_KEYS, REDACTION_PLACEHOLDER;
|
|
2541
2700
|
var init_redaction = __esm(() => {
|
|
2542
2701
|
init_config();
|
|
2543
2702
|
DEFAULT_SECRET_PATTERNS = [
|
|
@@ -2561,11 +2720,12 @@ var init_redaction = __esm(() => {
|
|
|
2561
2720
|
"completion_tokens",
|
|
2562
2721
|
"cost_tokens"
|
|
2563
2722
|
]);
|
|
2723
|
+
REDACTION_PLACEHOLDER = String.raw`\[REDACTED(?:_[A-Z_]+)?\]`;
|
|
2564
2724
|
});
|
|
2565
2725
|
|
|
2566
2726
|
// src/pr-groups/types.ts
|
|
2567
2727
|
var PR_GROUP_LEDGER_SCHEMA_VERSION = 1, PR_GROUP_REPAIR_CYCLE_LIMIT = 2, PrGroupLedgerError;
|
|
2568
|
-
var
|
|
2728
|
+
var init_types2 = __esm(() => {
|
|
2569
2729
|
PrGroupLedgerError = class PrGroupLedgerError extends Error {
|
|
2570
2730
|
code;
|
|
2571
2731
|
details;
|
|
@@ -3920,7 +4080,7 @@ class PrGroupLedger {
|
|
|
3920
4080
|
}
|
|
3921
4081
|
var SHA_PATTERN, SAFE_REFERENCE_PATTERN, SAFE_PROFILE_PATTERN, FORBIDDEN_METADATA_KEY, EMAIL_PATTERN, CREDENTIAL_PATTERN, AUTH_PATH_PATTERN, STATE_VIEW_ATTEMPT_LIMIT = 100, STATE_VIEW_EVENT_LIMIT = 500, PR_GROUP_WRITER_STALE_AFTER_MS = 30000, APPENDABLE_EVENT_TYPES, EVENT_OUTCOMES, RECEIPT_EVENT_TYPES;
|
|
3922
4082
|
var init_ledger = __esm(() => {
|
|
3923
|
-
|
|
4083
|
+
init_types2();
|
|
3924
4084
|
SHA_PATTERN = /^[0-9a-f]{40}$/;
|
|
3925
4085
|
SAFE_REFERENCE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$/;
|
|
3926
4086
|
SAFE_PROFILE_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
@@ -4722,7 +4882,7 @@ class PrGroupHttpClient {
|
|
|
4722
4882
|
var LEDGER_CODES, GROUP_STATES, ATTEMPT_STATES, EVENT_TYPES, EVENT_OUTCOMES2;
|
|
4723
4883
|
var init_http_client = __esm(() => {
|
|
4724
4884
|
init_ledger();
|
|
4725
|
-
|
|
4885
|
+
init_types2();
|
|
4726
4886
|
LEDGER_CODES = new Set([
|
|
4727
4887
|
"PR_GROUP_INVALID_INPUT",
|
|
4728
4888
|
"PR_GROUP_NOT_FOUND",
|
|
@@ -5539,7 +5699,7 @@ async function cloudUnlockTask(client, id, agentId, force = false) {
|
|
|
5539
5699
|
async function cloudGetDependencies(client, id) {
|
|
5540
5700
|
const raw = await client.transport.get(`/tasks/${encodeURIComponent(id)}/dependencies`);
|
|
5541
5701
|
const env = raw ?? {};
|
|
5542
|
-
return { dependencies: env.dependencies ?? [],
|
|
5702
|
+
return { dependencies: env.dependencies ?? [], blocks: env.blocks ?? env.blocked_by ?? [] };
|
|
5543
5703
|
}
|
|
5544
5704
|
function unresolvedRelatedTask(id) {
|
|
5545
5705
|
const now = new Date(0).toISOString();
|
|
@@ -5600,7 +5760,7 @@ function unresolvedRelatedTask(id) {
|
|
|
5600
5760
|
async function cloudGetTaskRelations(client, id) {
|
|
5601
5761
|
const edges = await cloudGetDependencies(client, id);
|
|
5602
5762
|
const upstream = dedupe(edges.dependencies.map((edge) => edge.depends_on));
|
|
5603
|
-
const downstream = dedupe(edges.
|
|
5763
|
+
const downstream = dedupe(edges.blocks.map((edge) => edge.task_id));
|
|
5604
5764
|
const wanted = dedupe([...upstream, ...downstream]).filter((ref) => ref !== id);
|
|
5605
5765
|
const rows = new Map;
|
|
5606
5766
|
let cursor = 0;
|
|
@@ -5616,7 +5776,9 @@ async function cloudGetTaskRelations(client, id) {
|
|
|
5616
5776
|
});
|
|
5617
5777
|
await Promise.all(workers);
|
|
5618
5778
|
const materialize = (ref) => rows.get(ref) ?? unresolvedRelatedTask(ref);
|
|
5619
|
-
|
|
5779
|
+
const dependencies = upstream.map(materialize);
|
|
5780
|
+
const blocked_by = dependencies.filter((dep) => isBlockingDependencyStatus(dep.status));
|
|
5781
|
+
return { dependencies, blocked_by, blocks: downstream.map(materialize) };
|
|
5620
5782
|
}
|
|
5621
5783
|
function dedupe(ids) {
|
|
5622
5784
|
const seen = new Set;
|
|
@@ -5938,6 +6100,7 @@ async function cloudTimeline(client, options = {}) {
|
|
|
5938
6100
|
}
|
|
5939
6101
|
var UUID_RE, CLOUD_MODES, VALID_STORAGE_MODES, COMPLETION_EVIDENCE_FIELDS, completionCapabilityCache, RELATION_HYDRATION_CONCURRENCY = 6, PRIORITY_RANK;
|
|
5940
6102
|
var init_cloud_router = __esm(() => {
|
|
6103
|
+
init_types();
|
|
5941
6104
|
init_redaction();
|
|
5942
6105
|
init_http_client();
|
|
5943
6106
|
UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
@@ -9769,158 +9932,6 @@ var init_machines = __esm(() => {
|
|
|
9769
9932
|
];
|
|
9770
9933
|
});
|
|
9771
9934
|
|
|
9772
|
-
// src/types/index.ts
|
|
9773
|
-
var TASK_STATUSES, TASK_PRIORITIES, VersionConflictError, TaskNotFoundError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DispatchNotFoundError;
|
|
9774
|
-
var init_types2 = __esm(() => {
|
|
9775
|
-
TASK_STATUSES = [
|
|
9776
|
-
"pending",
|
|
9777
|
-
"in_progress",
|
|
9778
|
-
"completed",
|
|
9779
|
-
"failed",
|
|
9780
|
-
"cancelled"
|
|
9781
|
-
];
|
|
9782
|
-
TASK_PRIORITIES = [
|
|
9783
|
-
"low",
|
|
9784
|
-
"medium",
|
|
9785
|
-
"high",
|
|
9786
|
-
"critical"
|
|
9787
|
-
];
|
|
9788
|
-
VersionConflictError = class VersionConflictError extends Error {
|
|
9789
|
-
taskId;
|
|
9790
|
-
expectedVersion;
|
|
9791
|
-
actualVersion;
|
|
9792
|
-
static code = "VERSION_CONFLICT";
|
|
9793
|
-
static suggestion = "Fetch the task with get_task to get the current version before updating.";
|
|
9794
|
-
constructor(taskId, expectedVersion, actualVersion) {
|
|
9795
|
-
super(`Version conflict for task ${taskId}: expected ${expectedVersion}, got ${actualVersion}`);
|
|
9796
|
-
this.taskId = taskId;
|
|
9797
|
-
this.expectedVersion = expectedVersion;
|
|
9798
|
-
this.actualVersion = actualVersion;
|
|
9799
|
-
this.name = "VersionConflictError";
|
|
9800
|
-
}
|
|
9801
|
-
};
|
|
9802
|
-
TaskNotFoundError = class TaskNotFoundError extends Error {
|
|
9803
|
-
taskId;
|
|
9804
|
-
static code = "TASK_NOT_FOUND";
|
|
9805
|
-
static suggestion = "Verify the task ID. Use list_tasks or search_tasks to find the correct ID.";
|
|
9806
|
-
constructor(taskId) {
|
|
9807
|
-
super(`Task not found: ${taskId}`);
|
|
9808
|
-
this.taskId = taskId;
|
|
9809
|
-
this.name = "TaskNotFoundError";
|
|
9810
|
-
}
|
|
9811
|
-
};
|
|
9812
|
-
ProjectNotFoundError = class ProjectNotFoundError extends Error {
|
|
9813
|
-
projectId;
|
|
9814
|
-
static code = "PROJECT_NOT_FOUND";
|
|
9815
|
-
static suggestion = "Use list_projects to see available projects.";
|
|
9816
|
-
constructor(projectId) {
|
|
9817
|
-
super(`Project not found: ${projectId}`);
|
|
9818
|
-
this.projectId = projectId;
|
|
9819
|
-
this.name = "ProjectNotFoundError";
|
|
9820
|
-
}
|
|
9821
|
-
};
|
|
9822
|
-
ResourceConflictError = class ResourceConflictError extends Error {
|
|
9823
|
-
code;
|
|
9824
|
-
constructor(code, message) {
|
|
9825
|
-
super(message);
|
|
9826
|
-
this.code = code;
|
|
9827
|
-
this.name = "ResourceConflictError";
|
|
9828
|
-
}
|
|
9829
|
-
};
|
|
9830
|
-
PlanNotFoundError = class PlanNotFoundError extends Error {
|
|
9831
|
-
planId;
|
|
9832
|
-
static code = "PLAN_NOT_FOUND";
|
|
9833
|
-
static suggestion = "Use list_plans to see available plans.";
|
|
9834
|
-
constructor(planId) {
|
|
9835
|
-
super(`Plan not found: ${planId}`);
|
|
9836
|
-
this.planId = planId;
|
|
9837
|
-
this.name = "PlanNotFoundError";
|
|
9838
|
-
}
|
|
9839
|
-
};
|
|
9840
|
-
LockError = class LockError extends Error {
|
|
9841
|
-
taskId;
|
|
9842
|
-
lockedBy;
|
|
9843
|
-
static code = "LOCK_ERROR";
|
|
9844
|
-
static suggestion = "Wait for the lock to expire (30 min) or contact the lock holder.";
|
|
9845
|
-
constructor(taskId, lockedBy) {
|
|
9846
|
-
super(`Task ${taskId} is locked by ${lockedBy}`);
|
|
9847
|
-
this.taskId = taskId;
|
|
9848
|
-
this.lockedBy = lockedBy;
|
|
9849
|
-
this.name = "LockError";
|
|
9850
|
-
}
|
|
9851
|
-
};
|
|
9852
|
-
AgentNotFoundError = class AgentNotFoundError extends Error {
|
|
9853
|
-
agentId;
|
|
9854
|
-
static code = "AGENT_NOT_FOUND";
|
|
9855
|
-
static suggestion = "Use register_agent to create the agent first, or list_agents to find existing ones.";
|
|
9856
|
-
constructor(agentId) {
|
|
9857
|
-
super(`Agent not found: ${agentId}`);
|
|
9858
|
-
this.agentId = agentId;
|
|
9859
|
-
this.name = "AgentNotFoundError";
|
|
9860
|
-
}
|
|
9861
|
-
};
|
|
9862
|
-
IdentityAliasAmbiguousError = class IdentityAliasAmbiguousError extends Error {
|
|
9863
|
-
code = "IDENTITY_ALIAS_AMBIGUOUS";
|
|
9864
|
-
candidates;
|
|
9865
|
-
constructor(subject, candidates = []) {
|
|
9866
|
-
super(`Identity alias or source is ambiguous: ${subject}`);
|
|
9867
|
-
this.name = "IdentityAliasAmbiguousError";
|
|
9868
|
-
this.candidates = [...new Set(candidates)].sort();
|
|
9869
|
-
}
|
|
9870
|
-
};
|
|
9871
|
-
IdentityIdImmutableError = class IdentityIdImmutableError extends Error {
|
|
9872
|
-
code = "IDENTITY_ID_IMMUTABLE";
|
|
9873
|
-
constructor(agentId) {
|
|
9874
|
-
super(`IDENTITY_ID_IMMUTABLE: canonical identity for agent ${agentId} cannot be replaced`);
|
|
9875
|
-
this.name = "IdentityIdImmutableError";
|
|
9876
|
-
}
|
|
9877
|
-
};
|
|
9878
|
-
TaskListNotFoundError = class TaskListNotFoundError extends Error {
|
|
9879
|
-
taskListId;
|
|
9880
|
-
static code = "TASK_LIST_NOT_FOUND";
|
|
9881
|
-
static suggestion = "Use list_task_lists to see available lists.";
|
|
9882
|
-
constructor(taskListId) {
|
|
9883
|
-
super(`Task list not found: ${taskListId}`);
|
|
9884
|
-
this.taskListId = taskListId;
|
|
9885
|
-
this.name = "TaskListNotFoundError";
|
|
9886
|
-
}
|
|
9887
|
-
};
|
|
9888
|
-
DependencyCycleError = class DependencyCycleError extends Error {
|
|
9889
|
-
taskId;
|
|
9890
|
-
dependsOn;
|
|
9891
|
-
static code = "DEPENDENCY_CYCLE";
|
|
9892
|
-
static suggestion = "Check the dependency chain with get_task to avoid circular references.";
|
|
9893
|
-
constructor(taskId, dependsOn) {
|
|
9894
|
-
super(`Adding dependency ${taskId} -> ${dependsOn} would create a cycle`);
|
|
9895
|
-
this.taskId = taskId;
|
|
9896
|
-
this.dependsOn = dependsOn;
|
|
9897
|
-
this.name = "DependencyCycleError";
|
|
9898
|
-
}
|
|
9899
|
-
};
|
|
9900
|
-
CompletionGuardError = class CompletionGuardError extends Error {
|
|
9901
|
-
reason;
|
|
9902
|
-
retryAfterSeconds;
|
|
9903
|
-
static code = "COMPLETION_BLOCKED";
|
|
9904
|
-
static suggestion = "Wait for the cooldown period, then retry.";
|
|
9905
|
-
constructor(reason, retryAfterSeconds) {
|
|
9906
|
-
super(reason);
|
|
9907
|
-
this.reason = reason;
|
|
9908
|
-
this.retryAfterSeconds = retryAfterSeconds;
|
|
9909
|
-
this.name = "CompletionGuardError";
|
|
9910
|
-
}
|
|
9911
|
-
};
|
|
9912
|
-
DispatchNotFoundError = class DispatchNotFoundError extends Error {
|
|
9913
|
-
dispatchId;
|
|
9914
|
-
static code = "DISPATCH_NOT_FOUND";
|
|
9915
|
-
static suggestion = "Check the dispatch ID with list_dispatches.";
|
|
9916
|
-
constructor(dispatchId) {
|
|
9917
|
-
super(`Dispatch not found: ${dispatchId}`);
|
|
9918
|
-
this.dispatchId = dispatchId;
|
|
9919
|
-
this.name = "DispatchNotFoundError";
|
|
9920
|
-
}
|
|
9921
|
-
};
|
|
9922
|
-
});
|
|
9923
|
-
|
|
9924
9935
|
// src/db/identity-mapping.ts
|
|
9925
9936
|
function timestamp() {
|
|
9926
9937
|
return new Date().toISOString();
|
|
@@ -10075,8 +10086,8 @@ function recordAgentAlias(agentId, label, db) {
|
|
|
10075
10086
|
}
|
|
10076
10087
|
var IDENTITY_PROJECTION_CONTRACT, IDENTITY_MIGRATION_ID = 65;
|
|
10077
10088
|
var init_identity_mapping = __esm(() => {
|
|
10078
|
-
|
|
10079
|
-
|
|
10089
|
+
init_types();
|
|
10090
|
+
init_types();
|
|
10080
10091
|
IDENTITY_PROJECTION_CONTRACT = Object.freeze({
|
|
10081
10092
|
name: "hasna.todos.agent-identity-projection/v1",
|
|
10082
10093
|
version: 1,
|
|
@@ -10467,8 +10478,8 @@ function ensureDir2(filePath) {
|
|
|
10467
10478
|
function openDatabase(path) {
|
|
10468
10479
|
ensureDir2(path);
|
|
10469
10480
|
const db = new Database(path);
|
|
10470
|
-
db.run("PRAGMA journal_mode = WAL");
|
|
10471
10481
|
db.run("PRAGMA busy_timeout = 5000");
|
|
10482
|
+
db.run("PRAGMA journal_mode = WAL");
|
|
10472
10483
|
db.run("PRAGMA foreign_keys = ON");
|
|
10473
10484
|
runMigrations(db);
|
|
10474
10485
|
ensureAgentIdentitySchema(db);
|
|
@@ -10601,7 +10612,7 @@ var init_database = __esm(() => {
|
|
|
10601
10612
|
init_schema();
|
|
10602
10613
|
init_machines();
|
|
10603
10614
|
init_identity_mapping();
|
|
10604
|
-
|
|
10615
|
+
init_types();
|
|
10605
10616
|
ALLOWED_TABLES = new Set(["tasks", "projects", "agents", "plans", "task_lists", "task_templates", "project_knowledge_records", "project_risks", "local_retrospectives"]);
|
|
10606
10617
|
});
|
|
10607
10618
|
|
|
@@ -11042,7 +11053,7 @@ function removeMachineLocalPath(projectId, machineId, db) {
|
|
|
11042
11053
|
return result.changes > 0;
|
|
11043
11054
|
}
|
|
11044
11055
|
var init_projects = __esm(() => {
|
|
11045
|
-
|
|
11056
|
+
init_types();
|
|
11046
11057
|
init_database();
|
|
11047
11058
|
init_machines();
|
|
11048
11059
|
init_storage_tombstones();
|
|
@@ -11387,7 +11398,7 @@ function checkCompletionGuard(task, agentId, db, configOverride) {
|
|
|
11387
11398
|
}
|
|
11388
11399
|
}
|
|
11389
11400
|
var init_completion_guard = __esm(() => {
|
|
11390
|
-
|
|
11401
|
+
init_types();
|
|
11391
11402
|
init_config();
|
|
11392
11403
|
init_projects();
|
|
11393
11404
|
});
|
|
@@ -12811,7 +12822,7 @@ function ensureTaskList(name, slug, projectId, db) {
|
|
|
12811
12822
|
return createTaskList({ name, slug, project_id: projectId }, d);
|
|
12812
12823
|
}
|
|
12813
12824
|
var init_task_lists = __esm(() => {
|
|
12814
|
-
|
|
12825
|
+
init_types();
|
|
12815
12826
|
init_database();
|
|
12816
12827
|
init_projects();
|
|
12817
12828
|
init_storage_tombstones();
|
|
@@ -13101,7 +13112,7 @@ function scanTextForSecrets(text, options = {}) {
|
|
|
13101
13112
|
};
|
|
13102
13113
|
}
|
|
13103
13114
|
function redactText(text, options = {}) {
|
|
13104
|
-
const placeholder = options.placeholder ??
|
|
13115
|
+
const placeholder = options.placeholder ?? REDACTION_PLACEHOLDER2;
|
|
13105
13116
|
let out = text;
|
|
13106
13117
|
for (const { pattern, allowlist_ok } of DEFAULT_PATTERNS) {
|
|
13107
13118
|
out = out.replace(new RegExp(pattern.source, pattern.flags), (match) => {
|
|
@@ -13128,7 +13139,7 @@ function redactExportRecord(record) {
|
|
|
13128
13139
|
}
|
|
13129
13140
|
return base;
|
|
13130
13141
|
}
|
|
13131
|
-
var SECRET_REDACTION_SCHEMA,
|
|
13142
|
+
var SECRET_REDACTION_SCHEMA, REDACTION_PLACEHOLDER2 = "[REDACTED]", DEFAULT_PATTERNS, DEFAULT_ALLOWLIST, customRedactors;
|
|
13132
13143
|
var init_secret_redaction = __esm(() => {
|
|
13133
13144
|
init_redaction();
|
|
13134
13145
|
SECRET_REDACTION_SCHEMA = ["todos", "secret_redaction", "v1"].join(".");
|
|
@@ -14435,7 +14446,7 @@ function wouldCreateCycle(taskId, dependsOn, db) {
|
|
|
14435
14446
|
return false;
|
|
14436
14447
|
}
|
|
14437
14448
|
var init_task_graph = __esm(() => {
|
|
14438
|
-
|
|
14449
|
+
init_types();
|
|
14439
14450
|
init_database();
|
|
14440
14451
|
init_task_crud();
|
|
14441
14452
|
});
|
|
@@ -14994,7 +15005,7 @@ function spawnNextRecurrence(completedTask, db, completedAt) {
|
|
|
14994
15005
|
}
|
|
14995
15006
|
var MAX_SPAWN_DEPTH = 10;
|
|
14996
15007
|
var init_task_lifecycle = __esm(() => {
|
|
14997
|
-
|
|
15008
|
+
init_types();
|
|
14998
15009
|
init_database();
|
|
14999
15010
|
init_completion_guard();
|
|
15000
15011
|
init_event_emission_safety();
|
|
@@ -15153,10 +15164,11 @@ function getTaskWithRelations(id, db) {
|
|
|
15153
15164
|
JOIN task_dependencies td ON td.depends_on = t.id
|
|
15154
15165
|
WHERE td.task_id = ?`).all(id);
|
|
15155
15166
|
const dependencies = depRows.map(rowToTask);
|
|
15156
|
-
const
|
|
15167
|
+
const blocked_by = dependencies.filter((dep) => isBlockingDependencyStatus(dep.status));
|
|
15168
|
+
const blocksRows = d.query(`SELECT t.* FROM tasks t
|
|
15157
15169
|
JOIN task_dependencies td ON td.task_id = t.id
|
|
15158
15170
|
WHERE td.depends_on = ?`).all(id);
|
|
15159
|
-
const
|
|
15171
|
+
const blocks = blocksRows.map(rowToTask);
|
|
15160
15172
|
const comments = d.query("SELECT * FROM task_comments WHERE task_id = ? ORDER BY created_at").all(id);
|
|
15161
15173
|
const parent = task.parent_id ? getTask(task.parent_id, d) : null;
|
|
15162
15174
|
const checklist = getChecklist(id, d);
|
|
@@ -15165,6 +15177,7 @@ function getTaskWithRelations(id, db) {
|
|
|
15165
15177
|
subtasks,
|
|
15166
15178
|
dependencies,
|
|
15167
15179
|
blocked_by,
|
|
15180
|
+
blocks,
|
|
15168
15181
|
comments,
|
|
15169
15182
|
parent,
|
|
15170
15183
|
checklist
|
|
@@ -15622,7 +15635,7 @@ function deleteTask(id, db) {
|
|
|
15622
15635
|
return result.changes > 0;
|
|
15623
15636
|
}
|
|
15624
15637
|
var init_task_crud = __esm(() => {
|
|
15625
|
-
|
|
15638
|
+
init_types();
|
|
15626
15639
|
init_database();
|
|
15627
15640
|
init_completion_guard();
|
|
15628
15641
|
init_event_emission_safety();
|
|
@@ -15808,7 +15821,7 @@ function getTaskStats(filters, db) {
|
|
|
15808
15821
|
return { total: totalRow.count, by_status, by_priority, completion_rate, by_agent };
|
|
15809
15822
|
}
|
|
15810
15823
|
var init_task_status = __esm(() => {
|
|
15811
|
-
|
|
15824
|
+
init_types();
|
|
15812
15825
|
init_database();
|
|
15813
15826
|
init_task_crud();
|
|
15814
15827
|
init_task_graph();
|
|
@@ -16489,7 +16502,7 @@ function deletePlan(id, db) {
|
|
|
16489
16502
|
return result.changes > 0;
|
|
16490
16503
|
}
|
|
16491
16504
|
var init_plans = __esm(() => {
|
|
16492
|
-
|
|
16505
|
+
init_types();
|
|
16493
16506
|
init_event_emission_safety();
|
|
16494
16507
|
init_event_hooks();
|
|
16495
16508
|
init_database();
|
|
@@ -17176,7 +17189,7 @@ function deleteComment(id, db) {
|
|
|
17176
17189
|
return result.changes > 0;
|
|
17177
17190
|
}
|
|
17178
17191
|
var init_comments = __esm(() => {
|
|
17179
|
-
|
|
17192
|
+
init_types();
|
|
17180
17193
|
init_database();
|
|
17181
17194
|
init_tasks();
|
|
17182
17195
|
init_prewrite_secrets();
|
|
@@ -18055,7 +18068,7 @@ var init_task_runs = __esm(() => {
|
|
|
18055
18068
|
init_event_emission_safety();
|
|
18056
18069
|
init_event_hooks();
|
|
18057
18070
|
init_prewrite_secrets();
|
|
18058
|
-
|
|
18071
|
+
init_types();
|
|
18059
18072
|
init_comments();
|
|
18060
18073
|
init_database();
|
|
18061
18074
|
init_task_files();
|
|
@@ -18845,7 +18858,7 @@ async function cloudDetailRelations(cloud, id) {
|
|
|
18845
18858
|
if (status !== 404 && status !== 501) {
|
|
18846
18859
|
console.error(chalk2.dim(`Warning: could not load task dependencies: ${e instanceof Error ? e.message : String(e)}`));
|
|
18847
18860
|
}
|
|
18848
|
-
return { dependencies: [], blocked_by: [] };
|
|
18861
|
+
return { dependencies: [], blocked_by: [], blocks: [] };
|
|
18849
18862
|
}
|
|
18850
18863
|
}
|
|
18851
18864
|
function resolveProjectIdOrSlug(input) {
|
|
@@ -19422,6 +19435,7 @@ function registerTaskCommands(program2) {
|
|
|
19422
19435
|
tags: remote.tags ?? [],
|
|
19423
19436
|
dependencies: relations.dependencies,
|
|
19424
19437
|
blocked_by: relations.blocked_by,
|
|
19438
|
+
blocks: relations.blocks,
|
|
19425
19439
|
comments: commentPage.comments,
|
|
19426
19440
|
comments_page: {
|
|
19427
19441
|
count: commentPage.count,
|
|
@@ -19505,10 +19519,10 @@ function registerTaskCommands(program2) {
|
|
|
19505
19519
|
console.log(` ${formatTaskLine(dep)}`);
|
|
19506
19520
|
}
|
|
19507
19521
|
}
|
|
19508
|
-
if (task2.
|
|
19522
|
+
if (task2.blocks.length > 0) {
|
|
19509
19523
|
console.log(chalk2.bold(`
|
|
19510
|
-
Blocks (${task2.
|
|
19511
|
-
for (const b of task2.
|
|
19524
|
+
Blocks (${task2.blocks.length}):`));
|
|
19525
|
+
for (const b of task2.blocks) {
|
|
19512
19526
|
console.log(` ${formatTaskLine(b)}`);
|
|
19513
19527
|
}
|
|
19514
19528
|
}
|
|
@@ -19551,6 +19565,7 @@ function registerTaskCommands(program2) {
|
|
|
19551
19565
|
tags: remote.tags ?? [],
|
|
19552
19566
|
dependencies: relations.dependencies,
|
|
19553
19567
|
blocked_by: relations.blocked_by,
|
|
19568
|
+
blocks: relations.blocks,
|
|
19554
19569
|
comments: commentPage.comments,
|
|
19555
19570
|
comments_page: {
|
|
19556
19571
|
count: commentPage.count,
|
|
@@ -19632,10 +19647,10 @@ ${chalk2.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
|
|
|
19632
19647
|
console.log(chalk2.red(`
|
|
19633
19648
|
BLOCKED by ${unfinishedDeps.length} unfinished dep(s)`));
|
|
19634
19649
|
}
|
|
19635
|
-
if (task2.
|
|
19650
|
+
if (task2.blocks.length > 0) {
|
|
19636
19651
|
console.log(chalk2.bold(`
|
|
19637
|
-
Blocks (${task2.
|
|
19638
|
-
for (const b of task2.
|
|
19652
|
+
Blocks (${task2.blocks.length}):`));
|
|
19653
|
+
for (const b of task2.blocks)
|
|
19639
19654
|
console.log(` ${formatTaskLine(b)}`);
|
|
19640
19655
|
}
|
|
19641
19656
|
if (task2.subtasks.length > 0) {
|
|
@@ -20203,7 +20218,7 @@ var init_task_commands = __esm(() => {
|
|
|
20203
20218
|
init_cloud_router();
|
|
20204
20219
|
init_helpers();
|
|
20205
20220
|
init_output_redaction();
|
|
20206
|
-
|
|
20221
|
+
init_types();
|
|
20207
20222
|
});
|
|
20208
20223
|
|
|
20209
20224
|
// src/lib/plan-artifacts.ts
|
|
@@ -21666,6 +21681,111 @@ var init_plan_template_commands = __esm(() => {
|
|
|
21666
21681
|
init_cloud_router();
|
|
21667
21682
|
});
|
|
21668
21683
|
|
|
21684
|
+
// src/lib/dependency-graph.ts
|
|
21685
|
+
function toNode(task) {
|
|
21686
|
+
return {
|
|
21687
|
+
id: task.id,
|
|
21688
|
+
short_id: task.short_id,
|
|
21689
|
+
title: task.title,
|
|
21690
|
+
status: task.status,
|
|
21691
|
+
priority: task.priority,
|
|
21692
|
+
plan_id: task.plan_id,
|
|
21693
|
+
project_id: task.project_id
|
|
21694
|
+
};
|
|
21695
|
+
}
|
|
21696
|
+
function filterTasks(tasks, filter) {
|
|
21697
|
+
let out = tasks;
|
|
21698
|
+
if (filter.project_id)
|
|
21699
|
+
out = out.filter((t) => t.project_id === filter.project_id);
|
|
21700
|
+
if (filter.plan_id)
|
|
21701
|
+
out = out.filter((t) => t.plan_id === filter.plan_id);
|
|
21702
|
+
if (filter.status?.length)
|
|
21703
|
+
out = out.filter((t) => filter.status.includes(t.status));
|
|
21704
|
+
return out;
|
|
21705
|
+
}
|
|
21706
|
+
function detectCyclesFromEdges(edges) {
|
|
21707
|
+
const adj = new Map;
|
|
21708
|
+
const nodes = new Set;
|
|
21709
|
+
for (const e of edges) {
|
|
21710
|
+
nodes.add(e.task_id);
|
|
21711
|
+
nodes.add(e.depends_on);
|
|
21712
|
+
if (!adj.has(e.task_id))
|
|
21713
|
+
adj.set(e.task_id, []);
|
|
21714
|
+
adj.get(e.task_id).push(e.depends_on);
|
|
21715
|
+
}
|
|
21716
|
+
const cycles = [];
|
|
21717
|
+
const visited = new Set;
|
|
21718
|
+
const stack = new Set;
|
|
21719
|
+
const path = [];
|
|
21720
|
+
function dfs(node) {
|
|
21721
|
+
visited.add(node);
|
|
21722
|
+
stack.add(node);
|
|
21723
|
+
path.push(node);
|
|
21724
|
+
for (const next of adj.get(node) ?? []) {
|
|
21725
|
+
if (!visited.has(next))
|
|
21726
|
+
dfs(next);
|
|
21727
|
+
else if (stack.has(next)) {
|
|
21728
|
+
const idx = path.indexOf(next);
|
|
21729
|
+
if (idx >= 0)
|
|
21730
|
+
cycles.push([...path.slice(idx), next]);
|
|
21731
|
+
}
|
|
21732
|
+
}
|
|
21733
|
+
path.pop();
|
|
21734
|
+
stack.delete(node);
|
|
21735
|
+
}
|
|
21736
|
+
for (const node of nodes) {
|
|
21737
|
+
if (!visited.has(node))
|
|
21738
|
+
dfs(node);
|
|
21739
|
+
}
|
|
21740
|
+
return cycles;
|
|
21741
|
+
}
|
|
21742
|
+
function buildTaskDependencyEdges(task, dependencies, blocks) {
|
|
21743
|
+
return {
|
|
21744
|
+
schema_version: TASK_DEPENDENCY_EDGES_SCHEMA,
|
|
21745
|
+
task_id: task.id,
|
|
21746
|
+
short_id: task.short_id,
|
|
21747
|
+
dependencies: dependencies.map(toNode),
|
|
21748
|
+
blocked_by: dependencies.filter((dep) => isBlockingDependencyStatus(dep.status)).map(toNode),
|
|
21749
|
+
blocks: blocks.map(toNode)
|
|
21750
|
+
};
|
|
21751
|
+
}
|
|
21752
|
+
function getTaskDependencyEdges(taskId, db) {
|
|
21753
|
+
const d = db || getDatabase();
|
|
21754
|
+
const task = getTask(taskId, d);
|
|
21755
|
+
if (!task)
|
|
21756
|
+
return null;
|
|
21757
|
+
const dependencies = getTaskDependencies(taskId, d).map((edge) => getTask(edge.depends_on, d)).filter((t) => Boolean(t));
|
|
21758
|
+
const blocks = getTaskDependents(taskId, d).map((edge) => getTask(edge.task_id, d)).filter((t) => Boolean(t));
|
|
21759
|
+
return buildTaskDependencyEdges(task, dependencies, blocks);
|
|
21760
|
+
}
|
|
21761
|
+
function buildProjectDependencyGraph(projectId, tasks, edges, generatedAt = new Date().toISOString()) {
|
|
21762
|
+
const nodeIds = new Set(tasks.map((t) => t.id));
|
|
21763
|
+
const scoped = edges.filter((edge) => nodeIds.has(edge.task_id)).map((edge) => ({ task_id: edge.task_id, depends_on: edge.depends_on }));
|
|
21764
|
+
return {
|
|
21765
|
+
schema_version: PROJECT_DEPENDENCY_GRAPH_SCHEMA,
|
|
21766
|
+
generated_at: generatedAt,
|
|
21767
|
+
project_id: projectId,
|
|
21768
|
+
nodes: tasks.map(toNode),
|
|
21769
|
+
edges: scoped,
|
|
21770
|
+
cycles: detectCyclesFromEdges(scoped)
|
|
21771
|
+
};
|
|
21772
|
+
}
|
|
21773
|
+
function getProjectDependencyGraph(filter = {}, db) {
|
|
21774
|
+
const d = db || getDatabase();
|
|
21775
|
+
const tasks = filterTasks(listTasks({}, d), filter);
|
|
21776
|
+
const edges = d.query("SELECT task_id, depends_on FROM task_dependencies").all();
|
|
21777
|
+
return buildProjectDependencyGraph(filter.project_id ?? null, tasks, edges);
|
|
21778
|
+
}
|
|
21779
|
+
var TASK_DEPENDENCY_EDGES_SCHEMA = "todos.task_dependency_edges.v1", PROJECT_DEPENDENCY_GRAPH_SCHEMA = "todos.project_dependency_graph.v1";
|
|
21780
|
+
var init_dependency_graph = __esm(() => {
|
|
21781
|
+
init_database();
|
|
21782
|
+
init_tasks();
|
|
21783
|
+
init_task_graph();
|
|
21784
|
+
init_task_lifecycle();
|
|
21785
|
+
init_types();
|
|
21786
|
+
init_types();
|
|
21787
|
+
});
|
|
21788
|
+
|
|
21669
21789
|
// src/lib/local-fields.ts
|
|
21670
21790
|
function normalizeList(values) {
|
|
21671
21791
|
return [...new Set((values || []).map((value) => value.trim()).filter(Boolean))].sort((a, b) => a.localeCompare(b));
|
|
@@ -21758,7 +21878,7 @@ var LOCAL_FIELDS_KEY = "local_fields";
|
|
|
21758
21878
|
var init_local_fields = __esm(() => {
|
|
21759
21879
|
init_database();
|
|
21760
21880
|
init_tasks();
|
|
21761
|
-
|
|
21881
|
+
init_types();
|
|
21762
21882
|
init_redaction();
|
|
21763
21883
|
});
|
|
21764
21884
|
|
|
@@ -24709,6 +24829,46 @@ import { basename as basename5, resolve as resolve13, sep as sep3 } from "path";
|
|
|
24709
24829
|
function collectOption(value, previous = []) {
|
|
24710
24830
|
return [...previous, value];
|
|
24711
24831
|
}
|
|
24832
|
+
function isResolvedTask(task) {
|
|
24833
|
+
const metadata = task.metadata;
|
|
24834
|
+
return !(metadata && metadata["unresolved"] === true);
|
|
24835
|
+
}
|
|
24836
|
+
async function buildCloudProjectDependencyGraph(cloud, projectId) {
|
|
24837
|
+
const tasks = await cloudListTasks(cloud, projectId ? { project_id: projectId } : {});
|
|
24838
|
+
const edges = [];
|
|
24839
|
+
const seen = new Set;
|
|
24840
|
+
let cursor = 0;
|
|
24841
|
+
const workers = Array.from({ length: Math.min(CLOUD_GRAPH_EDGE_CONCURRENCY, tasks.length) }, async () => {
|
|
24842
|
+
for (let index = cursor++;index < tasks.length; index = cursor++) {
|
|
24843
|
+
const task = tasks[index];
|
|
24844
|
+
try {
|
|
24845
|
+
const deps = await cloudGetDependencies(cloud, task.id);
|
|
24846
|
+
for (const edge of deps.dependencies) {
|
|
24847
|
+
const key = `${edge.task_id}|${edge.depends_on}`;
|
|
24848
|
+
if (seen.has(key))
|
|
24849
|
+
continue;
|
|
24850
|
+
seen.add(key);
|
|
24851
|
+
edges.push({ task_id: edge.task_id, depends_on: edge.depends_on });
|
|
24852
|
+
}
|
|
24853
|
+
} catch {}
|
|
24854
|
+
}
|
|
24855
|
+
});
|
|
24856
|
+
await Promise.all(workers);
|
|
24857
|
+
return buildProjectDependencyGraph(projectId, tasks, edges);
|
|
24858
|
+
}
|
|
24859
|
+
function printProjectDependencyGraph(graph) {
|
|
24860
|
+
if (graph.nodes.length === 0) {
|
|
24861
|
+
console.log(chalk4.dim("No tasks in scope."));
|
|
24862
|
+
return;
|
|
24863
|
+
}
|
|
24864
|
+
console.log(chalk4.bold(`Dependency graph: ${graph.nodes.length} task(s), ${graph.edges.length} edge(s)`));
|
|
24865
|
+
if (graph.cycles.length > 0) {
|
|
24866
|
+
console.log(chalk4.red(` ${graph.cycles.length} cycle(s) detected`));
|
|
24867
|
+
}
|
|
24868
|
+
for (const edge of graph.edges) {
|
|
24869
|
+
console.log(` ${chalk4.cyan(edge.task_id.slice(0, 8))} depends on ${chalk4.cyan(edge.depends_on.slice(0, 8))}`);
|
|
24870
|
+
}
|
|
24871
|
+
}
|
|
24712
24872
|
function splitList(value) {
|
|
24713
24873
|
if (!value)
|
|
24714
24874
|
return;
|
|
@@ -25042,9 +25202,39 @@ function registerProjectCommands(program2) {
|
|
|
25042
25202
|
handleError(e);
|
|
25043
25203
|
}
|
|
25044
25204
|
});
|
|
25045
|
-
program2.command("deps
|
|
25205
|
+
program2.command("deps [id]").description("Read or manage task dependencies. With no id, --project reads the whole-project dependency graph").option("--needs <dep-id>", "Add dependency (this task needs dep-id)").option("--remove <dep-id>", "Remove dependency").option("--graph", "Show the dependency graph instead of direct edges").option("--direction <direction>", "Graph direction: up, down, or both", "both").option("--project <ref>", "With no id: read the whole-project graph (project id, slug, name, or path)").action(async (id, opts) => {
|
|
25046
25206
|
const globalOpts = program2.opts();
|
|
25047
25207
|
const cloud = getTodosCloudClient();
|
|
25208
|
+
if (!id) {
|
|
25209
|
+
if (opts.needs || opts.remove || opts.graph || opts.direction !== "both") {
|
|
25210
|
+
handleError(new Error("A task id is required with --needs, --remove, --graph, or --direction."));
|
|
25211
|
+
}
|
|
25212
|
+
const projectRef = opts.project ?? globalOpts.project;
|
|
25213
|
+
if (cloud) {
|
|
25214
|
+
if (!projectRef) {
|
|
25215
|
+
handleError(new Error("deps needs a task id, or --project <ref> to read a whole-project graph."));
|
|
25216
|
+
}
|
|
25217
|
+
const projectId = await cloudResolveProjectRef(cloud, projectRef);
|
|
25218
|
+
const graph2 = await buildCloudProjectDependencyGraph(cloud, projectId);
|
|
25219
|
+
if (globalOpts.json) {
|
|
25220
|
+
output(graph2, true);
|
|
25221
|
+
return;
|
|
25222
|
+
}
|
|
25223
|
+
printProjectDependencyGraph(graph2);
|
|
25224
|
+
return;
|
|
25225
|
+
}
|
|
25226
|
+
const resolvedProjectId = projectRef ? resolveExplicitProject(projectRef).id : autoProject(globalOpts);
|
|
25227
|
+
if (!resolvedProjectId) {
|
|
25228
|
+
handleError(new Error("deps needs a task id, or --project <ref> to read a whole-project graph."));
|
|
25229
|
+
}
|
|
25230
|
+
const graph = getProjectDependencyGraph({ project_id: resolvedProjectId });
|
|
25231
|
+
if (globalOpts.json) {
|
|
25232
|
+
output(graph, true);
|
|
25233
|
+
return;
|
|
25234
|
+
}
|
|
25235
|
+
printProjectDependencyGraph(graph);
|
|
25236
|
+
return;
|
|
25237
|
+
}
|
|
25048
25238
|
if (cloud) {
|
|
25049
25239
|
const cloudId = await resolveTaskIdForCommand(id, cloud);
|
|
25050
25240
|
if (opts.needs) {
|
|
@@ -25067,22 +25257,23 @@ function registerProjectCommands(program2) {
|
|
|
25067
25257
|
console.log(removed ? chalk4.green("Dependency removed.") : chalk4.red("Dependency not found."));
|
|
25068
25258
|
return;
|
|
25069
25259
|
}
|
|
25070
|
-
const edges = await cloudGetDependencies(cloud, cloudId);
|
|
25071
25260
|
if (globalOpts.json) {
|
|
25072
|
-
|
|
25261
|
+
const relations = await cloudGetTaskRelations(cloud, cloudId);
|
|
25262
|
+
output(buildTaskDependencyEdges({ id: cloudId, short_id: null }, relations.dependencies.filter(isResolvedTask), relations.blocks.filter(isResolvedTask)), true);
|
|
25073
25263
|
return;
|
|
25074
25264
|
}
|
|
25265
|
+
const edges = await cloudGetDependencies(cloud, cloudId);
|
|
25075
25266
|
if (edges.dependencies.length > 0) {
|
|
25076
25267
|
console.log(chalk4.bold("Depends on:"));
|
|
25077
25268
|
for (const dep of edges.dependencies)
|
|
25078
25269
|
console.log(` ${chalk4.cyan(dep.depends_on)}`);
|
|
25079
25270
|
}
|
|
25080
|
-
if (edges.
|
|
25271
|
+
if (edges.blocks.length > 0) {
|
|
25081
25272
|
console.log(chalk4.bold("Blocks:"));
|
|
25082
|
-
for (const b of edges.
|
|
25273
|
+
for (const b of edges.blocks)
|
|
25083
25274
|
console.log(` ${chalk4.cyan(b.task_id)}`);
|
|
25084
25275
|
}
|
|
25085
|
-
if (edges.dependencies.length === 0 && edges.
|
|
25276
|
+
if (edges.dependencies.length === 0 && edges.blocks.length === 0) {
|
|
25086
25277
|
console.log(chalk4.dim("No dependencies."));
|
|
25087
25278
|
}
|
|
25088
25279
|
return;
|
|
@@ -25127,28 +25318,30 @@ function registerProjectCommands(program2) {
|
|
|
25127
25318
|
printNode(dependent, depth + 1, "blocks");
|
|
25128
25319
|
};
|
|
25129
25320
|
printNode(graph, 0, "root");
|
|
25321
|
+
} else if (globalOpts.json) {
|
|
25322
|
+
const edges = getTaskDependencyEdges(resolvedId);
|
|
25323
|
+
if (!edges)
|
|
25324
|
+
handleError(new Error("Task not found."));
|
|
25325
|
+
output(edges, true);
|
|
25326
|
+
return;
|
|
25130
25327
|
} else {
|
|
25131
25328
|
const task = getTaskWithRelations2(resolvedId);
|
|
25132
25329
|
if (!task) {
|
|
25133
25330
|
handleError(new Error("Task not found."));
|
|
25134
25331
|
}
|
|
25135
|
-
if (globalOpts.json) {
|
|
25136
|
-
output({ dependencies: task.dependencies, blocked_by: task.blocked_by }, true);
|
|
25137
|
-
return;
|
|
25138
|
-
}
|
|
25139
25332
|
if (task.dependencies.length > 0) {
|
|
25140
25333
|
console.log(chalk4.bold("Depends on:"));
|
|
25141
25334
|
for (const dep of task.dependencies) {
|
|
25142
25335
|
console.log(` ${formatTaskLine(dep)}`);
|
|
25143
25336
|
}
|
|
25144
25337
|
}
|
|
25145
|
-
if (task.
|
|
25338
|
+
if (task.blocks.length > 0) {
|
|
25146
25339
|
console.log(chalk4.bold("Blocks:"));
|
|
25147
|
-
for (const b of task.
|
|
25340
|
+
for (const b of task.blocks) {
|
|
25148
25341
|
console.log(` ${formatTaskLine(b)}`);
|
|
25149
25342
|
}
|
|
25150
25343
|
}
|
|
25151
|
-
if (task.dependencies.length === 0 && task.
|
|
25344
|
+
if (task.dependencies.length === 0 && task.blocks.length === 0) {
|
|
25152
25345
|
console.log(chalk4.dim("No dependencies."));
|
|
25153
25346
|
}
|
|
25154
25347
|
}
|
|
@@ -25641,11 +25834,13 @@ function resolveTaskListId(partialId) {
|
|
|
25641
25834
|
}
|
|
25642
25835
|
return id;
|
|
25643
25836
|
}
|
|
25837
|
+
var CLOUD_GRAPH_EDGE_CONCURRENCY = 6;
|
|
25644
25838
|
var init_project_commands = __esm(() => {
|
|
25645
25839
|
init_database();
|
|
25646
25840
|
init_projects();
|
|
25647
25841
|
init_comments();
|
|
25648
25842
|
init_cloud_router();
|
|
25843
|
+
init_dependency_graph();
|
|
25649
25844
|
init_saved_search_views();
|
|
25650
25845
|
init_sync();
|
|
25651
25846
|
init_config();
|
|
@@ -26323,7 +26518,7 @@ function getCapableAgents(capabilities, opts, db) {
|
|
|
26323
26518
|
return opts?.limit ? scored.slice(0, opts.limit) : scored;
|
|
26324
26519
|
}
|
|
26325
26520
|
var init_agents = __esm(() => {
|
|
26326
|
-
|
|
26521
|
+
init_types();
|
|
26327
26522
|
init_database();
|
|
26328
26523
|
init_identity_mapping();
|
|
26329
26524
|
init_storage_tombstones();
|
|
@@ -26771,6 +26966,44 @@ var init_agent_commands = __esm(() => {
|
|
|
26771
26966
|
init_cloud_router();
|
|
26772
26967
|
});
|
|
26773
26968
|
|
|
26969
|
+
// src/server/port.ts
|
|
26970
|
+
var exports_port = {};
|
|
26971
|
+
__export(exports_port, {
|
|
26972
|
+
refuseInvalidPort: () => refuseInvalidPort,
|
|
26973
|
+
findFreePort: () => findFreePort,
|
|
26974
|
+
coercePort: () => coercePort,
|
|
26975
|
+
DEFAULT_PORT: () => DEFAULT_PORT
|
|
26976
|
+
});
|
|
26977
|
+
function coercePort(raw) {
|
|
26978
|
+
if (raw === undefined)
|
|
26979
|
+
return;
|
|
26980
|
+
const trimmed = raw.trim();
|
|
26981
|
+
if (!/^\d+$/.test(trimmed))
|
|
26982
|
+
return;
|
|
26983
|
+
if (trimmed.length > 1 && trimmed.startsWith("0"))
|
|
26984
|
+
return;
|
|
26985
|
+
const parsed = Number.parseInt(trimmed, 10);
|
|
26986
|
+
if (!Number.isInteger(parsed) || parsed > 65535)
|
|
26987
|
+
return;
|
|
26988
|
+
return parsed;
|
|
26989
|
+
}
|
|
26990
|
+
function refuseInvalidPort(source, raw) {
|
|
26991
|
+
console.error(`Invalid ${source}: ${JSON.stringify(raw)} is not a port.
|
|
26992
|
+
` + `Use an integer from 0 to 65535, where 0 asks the kernel for a free port.`);
|
|
26993
|
+
process.exit(1);
|
|
26994
|
+
}
|
|
26995
|
+
async function findFreePort(start) {
|
|
26996
|
+
for (let port = start;port < start + 100; port++) {
|
|
26997
|
+
try {
|
|
26998
|
+
const server = Bun.serve({ port, fetch: () => new Response("") });
|
|
26999
|
+
server.stop(true);
|
|
27000
|
+
return port;
|
|
27001
|
+
} catch {}
|
|
27002
|
+
}
|
|
27003
|
+
return start;
|
|
27004
|
+
}
|
|
27005
|
+
var DEFAULT_PORT = 19427;
|
|
27006
|
+
|
|
26774
27007
|
// src/lib/db-backup.ts
|
|
26775
27008
|
import { existsSync as existsSync14, copyFileSync, mkdirSync as mkdirSync8, readFileSync as readFileSync8, renameSync, statSync as statSync6, writeFileSync as writeFileSync7, unlinkSync } from "fs";
|
|
26776
27009
|
import { dirname as dirname7, join as join12, resolve as resolve14 } from "path";
|
|
@@ -29342,7 +29575,7 @@ var init_approval_gates = __esm(() => {
|
|
|
29342
29575
|
init_database();
|
|
29343
29576
|
init_task_runs();
|
|
29344
29577
|
init_tasks();
|
|
29345
|
-
|
|
29578
|
+
init_types();
|
|
29346
29579
|
init_event_emission_safety();
|
|
29347
29580
|
init_event_hooks();
|
|
29348
29581
|
});
|
|
@@ -31050,9 +31283,11 @@ async function removeDependency2(taskId, dependsOn, store) {
|
|
|
31050
31283
|
}
|
|
31051
31284
|
async function listDependencies(taskId, store) {
|
|
31052
31285
|
const edges = await store.list("dependencies");
|
|
31286
|
+
const incoming = edges.filter((edge) => edge.depends_on === taskId).map((edge) => ({ task_id: edge.task_id, depends_on: edge.depends_on }));
|
|
31053
31287
|
return {
|
|
31054
31288
|
dependencies: edges.filter((edge) => edge.task_id === taskId).map((edge) => ({ task_id: edge.task_id, depends_on: edge.depends_on })),
|
|
31055
|
-
|
|
31289
|
+
blocks: incoming,
|
|
31290
|
+
blocked_by: incoming
|
|
31056
31291
|
};
|
|
31057
31292
|
}
|
|
31058
31293
|
async function addVerification(input, store, context) {
|
|
@@ -31596,7 +31831,7 @@ function postgresConstraintName(error) {
|
|
|
31596
31831
|
}
|
|
31597
31832
|
var CLOUD_LOCK_EXPIRY_MINUTES = 30, TASK_ORDER_TIEBREAK = "CASE payload->>'priority' WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END ASC, payload->>'created_at' ASC, payload->>'id' ASC", TASK_ORDER_BY;
|
|
31598
31833
|
var init_postgres_adapter = __esm(() => {
|
|
31599
|
-
|
|
31834
|
+
init_types();
|
|
31600
31835
|
init_postgres_sync();
|
|
31601
31836
|
init_redaction();
|
|
31602
31837
|
TASK_ORDER_BY = `ORDER BY ${TASK_ORDER_TIEBREAK}`;
|
|
@@ -32079,7 +32314,7 @@ class PostgresPrGroupLedgerPersistence {
|
|
|
32079
32314
|
}
|
|
32080
32315
|
}
|
|
32081
32316
|
var init_postgres = __esm(() => {
|
|
32082
|
-
|
|
32317
|
+
init_types2();
|
|
32083
32318
|
});
|
|
32084
32319
|
|
|
32085
32320
|
// src/storage/comment-redaction-backfill.ts
|
|
@@ -33797,7 +34032,7 @@ function handleStaticFiles(path, method, ctx, json2, serveStaticFile2) {
|
|
|
33797
34032
|
var init_routes = __esm(() => {
|
|
33798
34033
|
init_tasks();
|
|
33799
34034
|
init_database();
|
|
33800
|
-
|
|
34035
|
+
init_types();
|
|
33801
34036
|
init_projects();
|
|
33802
34037
|
init_agents();
|
|
33803
34038
|
init_plans();
|
|
@@ -36435,7 +36670,7 @@ async function handlePrGroupHttpRequest(req, url, ledger, basePath, principal) {
|
|
|
36435
36670
|
}
|
|
36436
36671
|
var JSON_HEADERS;
|
|
36437
36672
|
var init_pr_groups = __esm(() => {
|
|
36438
|
-
|
|
36673
|
+
init_types2();
|
|
36439
36674
|
JSON_HEADERS = { "Content-Type": "application/json" };
|
|
36440
36675
|
});
|
|
36441
36676
|
|
|
@@ -37554,7 +37789,7 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
37554
37789
|
}
|
|
37555
37790
|
var JSON_HEADERS2, DEFAULT_COMMENT_PAGE_SIZE = 100, MAX_COMMENT_PAGE_SIZE = 500, LEGACY_COMMENT_RESPONSE_LIMIT = 500;
|
|
37556
37791
|
var init_v1 = __esm(() => {
|
|
37557
|
-
|
|
37792
|
+
init_types();
|
|
37558
37793
|
init_cloud();
|
|
37559
37794
|
init_pr_groups();
|
|
37560
37795
|
init_redaction();
|
|
@@ -41639,7 +41874,7 @@ function getDueDispatches(db) {
|
|
|
41639
41874
|
}
|
|
41640
41875
|
var init_dispatches = __esm(() => {
|
|
41641
41876
|
init_database();
|
|
41642
|
-
|
|
41877
|
+
init_types();
|
|
41643
41878
|
init_prewrite_secrets();
|
|
41644
41879
|
});
|
|
41645
41880
|
|
|
@@ -42418,7 +42653,7 @@ ${task.description}` : null
|
|
|
42418
42653
|
var init_task_crud2 = __esm(() => {
|
|
42419
42654
|
init_zod();
|
|
42420
42655
|
init_tasks();
|
|
42421
|
-
|
|
42656
|
+
init_types();
|
|
42422
42657
|
init_token_utils();
|
|
42423
42658
|
init_cloud_router();
|
|
42424
42659
|
});
|
|
@@ -43816,7 +44051,7 @@ function renderWorkflowStatesMarkdown(states = listWorkflowStates()) {
|
|
|
43816
44051
|
var LOCAL_FIELDS_KEY2 = "local_fields", WORKFLOW_STATE_KEY = "workflow_state", DEFAULT_WORKFLOW_STATES;
|
|
43817
44052
|
var init_workflow_states = __esm(() => {
|
|
43818
44053
|
init_tasks();
|
|
43819
|
-
|
|
44054
|
+
init_types();
|
|
43820
44055
|
init_database();
|
|
43821
44056
|
init_config();
|
|
43822
44057
|
init_local_fields();
|
|
@@ -48060,7 +48295,7 @@ var init_task_project_tools = __esm(() => {
|
|
|
48060
48295
|
init_capacity_forecasts();
|
|
48061
48296
|
init_audit_ledger();
|
|
48062
48297
|
init_release_compatibility();
|
|
48063
|
-
|
|
48298
|
+
init_types();
|
|
48064
48299
|
});
|
|
48065
48300
|
|
|
48066
48301
|
// src/db/handoffs.ts
|
|
@@ -48737,7 +48972,7 @@ function registerTaskWorkflowTools(server, ctx) {
|
|
|
48737
48972
|
}
|
|
48738
48973
|
var init_task_workflow_tools = __esm(() => {
|
|
48739
48974
|
init_zod();
|
|
48740
|
-
|
|
48975
|
+
init_types();
|
|
48741
48976
|
init_token_utils();
|
|
48742
48977
|
init_cloud_router();
|
|
48743
48978
|
});
|
|
@@ -49702,7 +49937,7 @@ var init_context_packs = __esm(() => {
|
|
|
49702
49937
|
init_task_graph();
|
|
49703
49938
|
init_task_runs();
|
|
49704
49939
|
init_tasks();
|
|
49705
|
-
|
|
49940
|
+
init_types();
|
|
49706
49941
|
init_redaction();
|
|
49707
49942
|
DEFAULT_LIMITS = {
|
|
49708
49943
|
comment_limit: 8,
|
|
@@ -51097,7 +51332,7 @@ function resolveMissingTaskFindings(input, db) {
|
|
|
51097
51332
|
var TASK_FINDING_SCHEMA_VERSION = "todos.task_finding.v1", TASK_FINDING_UPSERT_SCHEMA_VERSION = "todos.task_finding_upsert.v1", TASK_FINDING_RESOLVE_MISSING_SCHEMA_VERSION = "todos.task_finding_resolve_missing.v1", SEVERITIES, STATUSES;
|
|
51098
51333
|
var init_findings = __esm(() => {
|
|
51099
51334
|
init_redaction();
|
|
51100
|
-
|
|
51335
|
+
init_types();
|
|
51101
51336
|
init_database();
|
|
51102
51337
|
init_tasks();
|
|
51103
51338
|
init_task_runs();
|
|
@@ -56195,7 +56430,7 @@ function forceUnlockFile(path, db) {
|
|
|
56195
56430
|
var FILE_LOCK_DEFAULT_TTL_SECONDS;
|
|
56196
56431
|
var init_file_locks = __esm(() => {
|
|
56197
56432
|
init_database();
|
|
56198
|
-
|
|
56433
|
+
init_types();
|
|
56199
56434
|
FILE_LOCK_DEFAULT_TTL_SECONDS = 30 * 60;
|
|
56200
56435
|
});
|
|
56201
56436
|
|
|
@@ -61343,7 +61578,7 @@ var agentFocusMap, isDirectRun;
|
|
|
61343
61578
|
var init_mcp2 = __esm(() => {
|
|
61344
61579
|
init_agents();
|
|
61345
61580
|
init_database();
|
|
61346
|
-
|
|
61581
|
+
init_types();
|
|
61347
61582
|
init_dispatch2();
|
|
61348
61583
|
init_task_crud2();
|
|
61349
61584
|
init_task_project_tools();
|
|
@@ -61697,7 +61932,7 @@ var init_pr_groups2 = __esm(() => {
|
|
|
61697
61932
|
init_database();
|
|
61698
61933
|
init_ledger();
|
|
61699
61934
|
init_sqlite();
|
|
61700
|
-
|
|
61935
|
+
init_types2();
|
|
61701
61936
|
init_ledger();
|
|
61702
61937
|
init_sqlite();
|
|
61703
61938
|
init_http_client();
|
|
@@ -61935,7 +62170,7 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
61935
62170
|
const path = url.pathname;
|
|
61936
62171
|
const method = req.method;
|
|
61937
62172
|
const reqOrigin = req.headers.get("origin") || undefined;
|
|
61938
|
-
const corsHeaders = reqOrigin &&
|
|
62173
|
+
const corsHeaders = reqOrigin && reqOrigin === `http://localhost:${ctx.port}` ? {
|
|
61939
62174
|
"Access-Control-Allow-Origin": reqOrigin,
|
|
61940
62175
|
"Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE, OPTIONS",
|
|
61941
62176
|
"Access-Control-Allow-Headers": "Content-Type, X-API-Key, Authorization",
|
|
@@ -62223,7 +62458,9 @@ Dashboard not found at: ${dashboardDir}`);
|
|
|
62223
62458
|
};
|
|
62224
62459
|
process.on("SIGINT", shutdown);
|
|
62225
62460
|
process.on("SIGTERM", shutdown);
|
|
62226
|
-
const
|
|
62461
|
+
const boundPort = server.port ?? port;
|
|
62462
|
+
ctx.port = boundPort;
|
|
62463
|
+
const serverUrl = `http://localhost:${boundPort}`;
|
|
62227
62464
|
console.log(`Todos Dashboard running at ${serverUrl}`);
|
|
62228
62465
|
if (shouldOpen) {
|
|
62229
62466
|
try {
|
|
@@ -62705,7 +62942,7 @@ function TaskDetail({ task: task2 }) {
|
|
|
62705
62942
|
}, dep.id, true, undefined, this))
|
|
62706
62943
|
]
|
|
62707
62944
|
}, undefined, true, undefined, this),
|
|
62708
|
-
task2.
|
|
62945
|
+
task2.blocks.length > 0 && /* @__PURE__ */ jsxDEV3(Box3, {
|
|
62709
62946
|
flexDirection: "column",
|
|
62710
62947
|
marginBottom: 1,
|
|
62711
62948
|
children: [
|
|
@@ -62713,11 +62950,11 @@ function TaskDetail({ task: task2 }) {
|
|
|
62713
62950
|
bold: true,
|
|
62714
62951
|
children: [
|
|
62715
62952
|
"Blocks (",
|
|
62716
|
-
task2.
|
|
62953
|
+
task2.blocks.length,
|
|
62717
62954
|
"):"
|
|
62718
62955
|
]
|
|
62719
62956
|
}, undefined, true, undefined, this),
|
|
62720
|
-
task2.
|
|
62957
|
+
task2.blocks.map((b) => /* @__PURE__ */ jsxDEV3(Box3, {
|
|
62721
62958
|
marginLeft: 2,
|
|
62722
62959
|
children: [
|
|
62723
62960
|
/* @__PURE__ */ jsxDEV3(Text3, {
|
|
@@ -64701,18 +64938,11 @@ function registerConfigServeCommands(program2) {
|
|
|
64701
64938
|
console.log(renderTerminalNotification2(notification, rule?.format || "line"));
|
|
64702
64939
|
}
|
|
64703
64940
|
});
|
|
64704
|
-
program2.command("serve").description("Start the web dashboard").option("--port <port>", "Port number",
|
|
64941
|
+
program2.command("serve").description("Start the web dashboard").option("--port <port>", "Port number", String(DEFAULT_PORT)).option("--host <host>", "Host to bind (default: 127.0.0.1 localhost only, use 0.0.0.0 for all interfaces)").option("--api-key <key>", "Require this API key for /api/* requests").option("--allow-anonymous", "Local dev only: serve /api/* and /mcp without a credential (refused unless the bind host is loopback)").option("--no-open", "Don't open browser automatically").action(async (opts) => {
|
|
64705
64942
|
const { startServer: startServer2 } = await Promise.resolve().then(() => (init_serve(), exports_serve));
|
|
64706
|
-
const
|
|
64707
|
-
|
|
64708
|
-
|
|
64709
|
-
try {
|
|
64710
|
-
const s = Bun.serve({ port: p, fetch: () => new Response("") });
|
|
64711
|
-
s.stop(true);
|
|
64712
|
-
port = p;
|
|
64713
|
-
break;
|
|
64714
|
-
} catch {}
|
|
64715
|
-
}
|
|
64943
|
+
const { coercePort: coercePort2, findFreePort: findFreePort2, refuseInvalidPort: refuseInvalidPort2 } = await Promise.resolve().then(() => exports_port);
|
|
64944
|
+
const requestedPort = coercePort2(opts.port) ?? refuseInvalidPort2("--port", String(opts.port));
|
|
64945
|
+
const port = requestedPort === 0 ? requestedPort : await findFreePort2(requestedPort);
|
|
64716
64946
|
if (port !== requestedPort) {
|
|
64717
64947
|
console.log(`Port ${requestedPort} in use, using ${port}`);
|
|
64718
64948
|
}
|
|
@@ -69127,7 +69357,7 @@ var init_query_commands = __esm(() => {
|
|
|
69127
69357
|
init_local_reports();
|
|
69128
69358
|
init_helpers();
|
|
69129
69359
|
init_cloud_router();
|
|
69130
|
-
|
|
69360
|
+
init_types();
|
|
69131
69361
|
});
|
|
69132
69362
|
|
|
69133
69363
|
// src/cli/commands/mcp-hooks-commands.ts
|