@hasna/todos 0.13.8 → 0.13.10
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/claim-guard.d.ts.map +1 -1
- package/dist/cli/cloud-router.d.ts +2 -0
- package/dist/cli/cloud-router.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/components/TaskDetail.d.ts.map +1 -1
- package/dist/cli/components/TaskList.d.ts.map +1 -1
- package/dist/cli/helpers.d.ts.map +1 -1
- package/dist/cli/index.js +222 -48
- package/dist/cli/stage-a.d.ts.map +1 -1
- package/dist/contracts.js +46 -10
- package/dist/db/task-crud.d.ts.map +1 -1
- package/dist/db/task-lifecycle.d.ts.map +1 -1
- package/dist/index.js +106 -21
- package/dist/lib/lock-display.d.ts +52 -0
- package/dist/lib/lock-display.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +5 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +159 -28
- package/dist/mcp.js +3 -3
- package/dist/registry.js +46 -10
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +14016 -1227
- package/dist/server/routes.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/postgres-adapter.d.ts.map +1 -1
- package/dist/storage.js +103 -18
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -3
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.10",
|
|
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",
|
|
@@ -2173,8 +2173,8 @@ var init_package = __esm(() => {
|
|
|
2173
2173
|
"README.md"
|
|
2174
2174
|
],
|
|
2175
2175
|
scripts: {
|
|
2176
|
-
build: "rm -rf dist dashboard/dist && cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun
|
|
2177
|
-
"build:server": "rm -rf dist && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun
|
|
2176
|
+
build: "rm -rf dist dashboard/dist && cd dashboard && bun install --frozen-lockfile && bun run build && cd .. && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts src/testing.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && tsc --emitDeclarationOnly --outDir dist",
|
|
2177
|
+
"build:server": "rm -rf dist && bun build src/cli/index.tsx --outdir dist/cli --target bun --external ink --external react --external chalk --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/mcp/index.ts --outdir dist/mcp --target bun --external @modelcontextprotocol/sdk --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/server/index.ts --outdir dist/server --target bun && bun build src/sdk/index.ts --outdir dist/sdk --target bun --external '@hasna/contracts' --external '@hasna/contracts/*' && bun build src/index.ts src/mcp.ts src/registry.ts src/contracts.ts src/storage.ts src/testing.ts --outdir dist --target bun --external '@hasna/contracts' --external '@hasna/contracts/*'",
|
|
2178
2178
|
migrate: "bun run src/server/index.ts migrate",
|
|
2179
2179
|
"backfill:comment-redaction": "bun run src/server/index.ts redact-comments",
|
|
2180
2180
|
"generate:sdk": "bun run scripts/generate-sdk.ts",
|
|
@@ -2258,7 +2258,7 @@ var init_package_version = __esm(() => {
|
|
|
2258
2258
|
function isBlockingDependencyStatus(status) {
|
|
2259
2259
|
return status !== "completed" && status !== "cancelled";
|
|
2260
2260
|
}
|
|
2261
|
-
var TASK_STATUSES, TASK_PRIORITIES, VersionConflictError, TaskNotFoundError, TaskReferenceAmbiguousError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DispatchNotFoundError;
|
|
2261
|
+
var TASK_STATUSES, TASK_PRIORITIES, VersionConflictError, TaskNotFoundError, TaskNotStartableError, TaskReferenceAmbiguousError, ProjectNotFoundError, ResourceConflictError, PlanNotFoundError, LockError, AgentNotFoundError, IdentityAliasAmbiguousError, IdentityIdImmutableError, TaskListNotFoundError, DependencyCycleError, CompletionGuardError, DispatchNotFoundError;
|
|
2262
2262
|
var init_types = __esm(() => {
|
|
2263
2263
|
TASK_STATUSES = [
|
|
2264
2264
|
"pending",
|
|
@@ -2297,6 +2297,20 @@ var init_types = __esm(() => {
|
|
|
2297
2297
|
this.name = "TaskNotFoundError";
|
|
2298
2298
|
}
|
|
2299
2299
|
};
|
|
2300
|
+
TaskNotStartableError = class TaskNotStartableError extends Error {
|
|
2301
|
+
taskId;
|
|
2302
|
+
status;
|
|
2303
|
+
agentId;
|
|
2304
|
+
static code = "TASK_NOT_STARTABLE";
|
|
2305
|
+
static suggestion = "Reset the task status to pending before starting it again.";
|
|
2306
|
+
constructor(taskId, status, agentId) {
|
|
2307
|
+
super(`Task ${taskId} is ${status} and cannot be started by ${agentId}; ` + "reset the task status to pending before starting it again");
|
|
2308
|
+
this.taskId = taskId;
|
|
2309
|
+
this.status = status;
|
|
2310
|
+
this.agentId = agentId;
|
|
2311
|
+
this.name = "TaskNotStartableError";
|
|
2312
|
+
}
|
|
2313
|
+
};
|
|
2300
2314
|
TaskReferenceAmbiguousError = class TaskReferenceAmbiguousError extends Error {
|
|
2301
2315
|
reference;
|
|
2302
2316
|
static code = "TASK_REFERENCE_AMBIGUOUS";
|
|
@@ -5174,6 +5188,16 @@ function classifyRemoteRequestError(baseUrl, route, error) {
|
|
|
5174
5188
|
if (status === 403) {
|
|
5175
5189
|
throw new Error(`REMOTE_API_FORBIDDEN: configured Todos authority ${baseUrl} denied ${route}; local SQLite fallback is disabled`, { cause: error });
|
|
5176
5190
|
}
|
|
5191
|
+
if (status === 409) {
|
|
5192
|
+
const body = error && typeof error === "object" ? error.body : undefined;
|
|
5193
|
+
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
5194
|
+
const remoteError = body;
|
|
5195
|
+
if (remoteError.code === "TASK_NOT_STARTABLE" && typeof remoteError.error === "string" && remoteError.error.length > 0) {
|
|
5196
|
+
throw new Error(`${remoteError.code}: ${remoteError.error}`, { cause: error });
|
|
5197
|
+
}
|
|
5198
|
+
}
|
|
5199
|
+
throw error;
|
|
5200
|
+
}
|
|
5177
5201
|
if (typeof status === "number" && status >= 300 && status < 400) {
|
|
5178
5202
|
throw new Error(`REMOTE_API_REDIRECT_REJECTED: configured Todos authority ${baseUrl} redirected ${route}; ` + "authenticated redirects are disabled to prevent credential leakage", { cause: error });
|
|
5179
5203
|
}
|
|
@@ -5608,7 +5632,10 @@ function resolveCloudProjectRef(projects, ref) {
|
|
|
5608
5632
|
if (matches.length > 1)
|
|
5609
5633
|
throw new Error(`Project reference is ambiguous: "${input}"`);
|
|
5610
5634
|
}
|
|
5611
|
-
|
|
5635
|
+
if (UUID_RE.test(input) || /^[0-9a-f]{4,}$/i.test(input)) {
|
|
5636
|
+
throw new Error(`Project not found: "${input}"`);
|
|
5637
|
+
}
|
|
5638
|
+
throw new Error(`Project not found: "${input}" \u2014 no project in todos's own project registry matches this ` + `name, path, or slug. This does not know about projects registered elsewhere (for example ` + `a Hasna Projects CLI workspace) \u2014 resolve it there first (e.g. "projects show ${input} ` + `--json") and pass the resulting id or task-list slug, or run "todos projects create" to ` + `register it here. Do not assume "${input}" has never been created.`);
|
|
5612
5639
|
}
|
|
5613
5640
|
async function cloudResolveProjectRef(client, ref) {
|
|
5614
5641
|
return resolveCloudProjectRef(await cloudListProjects(client), ref);
|
|
@@ -5625,6 +5652,16 @@ async function cloudUpdateProject(client, id, patch) {
|
|
|
5625
5652
|
}
|
|
5626
5653
|
return raw;
|
|
5627
5654
|
}
|
|
5655
|
+
async function cloudDeleteProject(client, id) {
|
|
5656
|
+
try {
|
|
5657
|
+
await client.transport.del(`/projects/${encodeURIComponent(id)}`);
|
|
5658
|
+
} catch (error) {
|
|
5659
|
+
if (error && typeof error === "object" && error.status === 404)
|
|
5660
|
+
return false;
|
|
5661
|
+
throw error;
|
|
5662
|
+
}
|
|
5663
|
+
return true;
|
|
5664
|
+
}
|
|
5628
5665
|
async function cloudListPlans(client, projectId) {
|
|
5629
5666
|
const query = projectId ? { project_id: projectId } : {};
|
|
5630
5667
|
const res = await requiredRemoteRoute(client, "/v1/plans", () => client.list("plans", { query }));
|
|
@@ -6412,7 +6449,9 @@ function disqualifyingArgument(invocation) {
|
|
|
6412
6449
|
return dropIt("the `routing` subcommand");
|
|
6413
6450
|
return firstPresentOption(args, ["--apply", "--fix"]);
|
|
6414
6451
|
case "projects":
|
|
6415
|
-
|
|
6452
|
+
if (hasOption(args, "--deregister"))
|
|
6453
|
+
return null;
|
|
6454
|
+
return firstPresentOption(args, ["--path-prefix", "--dry-run"]);
|
|
6416
6455
|
case "plans":
|
|
6417
6456
|
return firstPresentOption(args, ["--artifact", "--write-artifacts"]);
|
|
6418
6457
|
case "list":
|
|
@@ -11363,6 +11402,24 @@ var init_projects = __esm(() => {
|
|
|
11363
11402
|
init_storage_tombstones();
|
|
11364
11403
|
});
|
|
11365
11404
|
|
|
11405
|
+
// src/lib/lock-display.ts
|
|
11406
|
+
function lockDisplayState(lockedBy, lockedAt, nowMs = Date.now()) {
|
|
11407
|
+
const holder = lockedBy ?? null;
|
|
11408
|
+
const at = lockedAt ?? null;
|
|
11409
|
+
if (!holder) {
|
|
11410
|
+
return { present: false, held: false, expired: false, holder: null, lockedAt: at };
|
|
11411
|
+
}
|
|
11412
|
+
const expired = isLockExpired(at, nowMs);
|
|
11413
|
+
return { present: true, held: !expired, expired, holder, lockedAt: at };
|
|
11414
|
+
}
|
|
11415
|
+
function formatExpiredLock(state) {
|
|
11416
|
+
const at = state.lockedAt ? ` at ${state.lockedAt}` : "";
|
|
11417
|
+
return `expired (last held by ${state.holder}${at})`;
|
|
11418
|
+
}
|
|
11419
|
+
var init_lock_display = __esm(() => {
|
|
11420
|
+
init_database();
|
|
11421
|
+
});
|
|
11422
|
+
|
|
11366
11423
|
// src/cli/helpers.ts
|
|
11367
11424
|
var exports_helpers = {};
|
|
11368
11425
|
__export(exports_helpers, {
|
|
@@ -11628,7 +11685,8 @@ function output(data, jsonMode) {
|
|
|
11628
11685
|
function formatTaskLine(t) {
|
|
11629
11686
|
const statusFn = statusColors[t.status] || chalk.white;
|
|
11630
11687
|
const priorityFn = priorityColors[t.priority] || chalk.white;
|
|
11631
|
-
const
|
|
11688
|
+
const lockState = lockDisplayState(t.locked_by, t.locked_at);
|
|
11689
|
+
const lock = lockState.held ? chalk.magenta(` [locked:${lockState.holder}]`) : "";
|
|
11632
11690
|
const assigned = t.assigned_to ? chalk.cyan(` -> ${t.assigned_to}`) : "";
|
|
11633
11691
|
const tags = t.tags.length > 0 ? chalk.dim(` [${t.tags.join(",")}]`) : "";
|
|
11634
11692
|
const plan = t.plan_id ? chalk.magenta(` [plan:${t.plan_id.slice(0, 8)}]`) : "";
|
|
@@ -11639,6 +11697,7 @@ var init_helpers = __esm(() => {
|
|
|
11639
11697
|
init_cloud_router();
|
|
11640
11698
|
init_database();
|
|
11641
11699
|
init_projects();
|
|
11700
|
+
init_lock_display();
|
|
11642
11701
|
init_package_version();
|
|
11643
11702
|
stdoutRetryBuffer = new SharedArrayBuffer(4);
|
|
11644
11703
|
stdoutRetrySignal = new Int32Array(stdoutRetryBuffer);
|
|
@@ -14865,7 +14924,7 @@ function assertStartable(task, agentId) {
|
|
|
14865
14924
|
return;
|
|
14866
14925
|
if (task.status === "in_progress")
|
|
14867
14926
|
return;
|
|
14868
|
-
throw new
|
|
14927
|
+
throw new TaskNotStartableError(task.id, task.status, agentId);
|
|
14869
14928
|
}
|
|
14870
14929
|
function getBlockingDeps(id, db) {
|
|
14871
14930
|
const d = db || getDatabase();
|
|
@@ -14936,7 +14995,7 @@ function completeTask(id, agentId, db, options) {
|
|
|
14936
14995
|
if (task.status === "cancelled") {
|
|
14937
14996
|
throw new Error(`Task ${id} is cancelled and cannot be completed`);
|
|
14938
14997
|
}
|
|
14939
|
-
if (
|
|
14998
|
+
if (task.locked_by && !sameHolder(task.locked_by, agentId) && !isLockExpired(task.locked_at)) {
|
|
14940
14999
|
throw new LockError(id, task.locked_by);
|
|
14941
15000
|
}
|
|
14942
15001
|
checkCompletionGuard(task, agentId || null, d);
|
|
@@ -15571,6 +15630,30 @@ function getTaskWithRelations(id, db) {
|
|
|
15571
15630
|
checklist
|
|
15572
15631
|
};
|
|
15573
15632
|
}
|
|
15633
|
+
function resolveAssignedToAliases(db, ref) {
|
|
15634
|
+
const aliases = new Set([ref]);
|
|
15635
|
+
let agentId;
|
|
15636
|
+
try {
|
|
15637
|
+
agentId = resolvePartialId(db, "agents", ref);
|
|
15638
|
+
} catch (err) {
|
|
15639
|
+
if (!(err instanceof IdentityAliasAmbiguousError))
|
|
15640
|
+
throw err;
|
|
15641
|
+
agentId = null;
|
|
15642
|
+
}
|
|
15643
|
+
if (agentId) {
|
|
15644
|
+
aliases.add(agentId);
|
|
15645
|
+
const row = db.query("SELECT name FROM agents WHERE id = ?").get(agentId);
|
|
15646
|
+
if (row?.name)
|
|
15647
|
+
aliases.add(row.name);
|
|
15648
|
+
}
|
|
15649
|
+
return [...aliases];
|
|
15650
|
+
}
|
|
15651
|
+
function lowerInClause(column, values, params) {
|
|
15652
|
+
if (values.length === 0)
|
|
15653
|
+
return "1=0";
|
|
15654
|
+
params.push(...values.map((v) => v.toLowerCase()));
|
|
15655
|
+
return `LOWER(${column}) IN (${values.map(() => "?").join(",")})`;
|
|
15656
|
+
}
|
|
15574
15657
|
function listTasks(filter = {}, db) {
|
|
15575
15658
|
const d = db || getDatabase();
|
|
15576
15659
|
const { clearExpiredLocks: clearExpiredLocks2 } = (init_database(), __toCommonJS(exports_database));
|
|
@@ -15612,8 +15695,7 @@ function listTasks(filter = {}, db) {
|
|
|
15612
15695
|
}
|
|
15613
15696
|
}
|
|
15614
15697
|
if (filter.assigned_to) {
|
|
15615
|
-
conditions.push("assigned_to
|
|
15616
|
-
params.push(filter.assigned_to);
|
|
15698
|
+
conditions.push(lowerInClause("assigned_to", resolveAssignedToAliases(d, filter.assigned_to), params));
|
|
15617
15699
|
}
|
|
15618
15700
|
if (filter.agent_id) {
|
|
15619
15701
|
conditions.push("agent_id = ?");
|
|
@@ -15773,8 +15855,7 @@ function countTasks(filter = {}, db) {
|
|
|
15773
15855
|
}
|
|
15774
15856
|
}
|
|
15775
15857
|
if (filter.assigned_to) {
|
|
15776
|
-
conditions.push("assigned_to
|
|
15777
|
-
params.push(filter.assigned_to);
|
|
15858
|
+
conditions.push(lowerInClause("assigned_to", resolveAssignedToAliases(d, filter.assigned_to), params));
|
|
15778
15859
|
}
|
|
15779
15860
|
if (filter.agent_id) {
|
|
15780
15861
|
conditions.push("agent_id = ?");
|
|
@@ -18956,7 +19037,7 @@ var init_tasks = __esm(() => {
|
|
|
18956
19037
|
function resolveClaimIdentity(verb, explicit) {
|
|
18957
19038
|
const resolved = resolveWritableIdentity(explicit);
|
|
18958
19039
|
if (!resolved.agent_id) {
|
|
18959
|
-
handleError(new Error(`Cannot ${verb} a task without an agent identity: a
|
|
19040
|
+
handleError(new Error(`Cannot ${verb} a task without an agent identity: this operation changes a task lock, and a lock with no distinct caller is not a lock. ` + `Set TODOS_AGENT_ID=<name> for this session, or pass --agent <name>. ` + `An identity persisted by 'todos init' is deliberately not used here \u2014 it is keyed on $HOME and names the station, not this session.`));
|
|
18960
19041
|
}
|
|
18961
19042
|
return resolved.agent_id;
|
|
18962
19043
|
}
|
|
@@ -20736,8 +20817,11 @@ function registerTaskCommands(program2) {
|
|
|
20736
20817
|
console.log(` ${chalk3.dim("Agent:")} ${task2.agent_id}`);
|
|
20737
20818
|
if (task2.session_id)
|
|
20738
20819
|
console.log(` ${chalk3.dim("Session:")} ${task2.session_id}`);
|
|
20739
|
-
|
|
20740
|
-
|
|
20820
|
+
const showLock = lockDisplayState(task2.locked_by, task2.locked_at);
|
|
20821
|
+
if (showLock.held)
|
|
20822
|
+
console.log(` ${chalk3.dim("Locked:")} ${showLock.holder} (at ${showLock.lockedAt})`);
|
|
20823
|
+
else if (showLock.expired)
|
|
20824
|
+
console.log(` ${chalk3.dim("Lock:")} ${chalk3.dim(formatExpiredLock(showLock))}`);
|
|
20741
20825
|
if (task2.requires_approval) {
|
|
20742
20826
|
const approvalStatus = task2.approved_by ? chalk3.green(`approved by ${task2.approved_by}`) : chalk3.yellow("pending approval");
|
|
20743
20827
|
console.log(` ${chalk3.dim("Approval:")} ${approvalStatus}`);
|
|
@@ -20880,8 +20964,11 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
|
|
|
20880
20964
|
}
|
|
20881
20965
|
if (task2.assigned_to)
|
|
20882
20966
|
console.log(` ${chalk3.dim("Assigned:")} ${task2.assigned_to}`);
|
|
20883
|
-
|
|
20884
|
-
|
|
20967
|
+
const inspectLock = lockDisplayState(task2.locked_by, task2.locked_at);
|
|
20968
|
+
if (inspectLock.held)
|
|
20969
|
+
console.log(` ${chalk3.dim("Locked by:")} ${inspectLock.holder}`);
|
|
20970
|
+
else if (inspectLock.expired)
|
|
20971
|
+
console.log(` ${chalk3.dim("Lock:")} ${chalk3.dim(formatExpiredLock(inspectLock))}`);
|
|
20885
20972
|
if (task2.project_id)
|
|
20886
20973
|
console.log(` ${chalk3.dim("Project:")} ${task2.project_id}`);
|
|
20887
20974
|
if (task2.plan_id)
|
|
@@ -21189,10 +21276,12 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
|
|
|
21189
21276
|
};
|
|
21190
21277
|
const cloud = getTodosCloudClient();
|
|
21191
21278
|
if (cloud) {
|
|
21279
|
+
const resolvedId2 = await resolveTaskIdForCommand(id, cloud);
|
|
21280
|
+
const agentId2 = resolveClaimIdentity("complete", globalOpts.agent);
|
|
21192
21281
|
let task3;
|
|
21193
21282
|
try {
|
|
21194
|
-
task3 = await cloudCompleteTask(cloud,
|
|
21195
|
-
|
|
21283
|
+
task3 = await cloudCompleteTask(cloud, resolvedId2, {
|
|
21284
|
+
agent_id: agentId2,
|
|
21196
21285
|
...completionOptions
|
|
21197
21286
|
});
|
|
21198
21287
|
} catch (e) {
|
|
@@ -21207,9 +21296,10 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
|
|
|
21207
21296
|
return;
|
|
21208
21297
|
}
|
|
21209
21298
|
const resolvedId = resolveTaskId(id);
|
|
21299
|
+
const agentId = resolveClaimIdentity("complete", globalOpts.agent);
|
|
21210
21300
|
let task2;
|
|
21211
21301
|
try {
|
|
21212
|
-
task2 = completeTask(resolvedId,
|
|
21302
|
+
task2 = completeTask(resolvedId, agentId, undefined, completionOptions);
|
|
21213
21303
|
} catch (e) {
|
|
21214
21304
|
handleError(e);
|
|
21215
21305
|
}
|
|
@@ -21329,11 +21419,12 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
|
|
|
21329
21419
|
const globalOpts = program2.opts();
|
|
21330
21420
|
const cloud = getTodosCloudClient();
|
|
21331
21421
|
const resolvedId = cloud ? await resolveTaskIdForCommand(id, cloud) : resolveTaskId(id);
|
|
21422
|
+
const agentId = resolveClaimIdentity("unlock", globalOpts.agent);
|
|
21332
21423
|
try {
|
|
21333
21424
|
if (cloud)
|
|
21334
|
-
await cloudUnlockTask(cloud, resolvedId,
|
|
21425
|
+
await cloudUnlockTask(cloud, resolvedId, agentId);
|
|
21335
21426
|
else
|
|
21336
|
-
unlockTask(resolvedId,
|
|
21427
|
+
unlockTask(resolvedId, agentId);
|
|
21337
21428
|
} catch (e) {
|
|
21338
21429
|
handleError(e);
|
|
21339
21430
|
}
|
|
@@ -21491,6 +21582,7 @@ var init_task_commands = __esm(() => {
|
|
|
21491
21582
|
init_task_lists();
|
|
21492
21583
|
init_cloud_router();
|
|
21493
21584
|
init_creator_identity();
|
|
21585
|
+
init_lock_display();
|
|
21494
21586
|
init_claim_guard();
|
|
21495
21587
|
init_assignee_guard();
|
|
21496
21588
|
init_helpers();
|
|
@@ -26175,6 +26267,12 @@ function countProjectTasks(projectId) {
|
|
|
26175
26267
|
FROM tasks
|
|
26176
26268
|
WHERE project_id = ?`).get(projectId);
|
|
26177
26269
|
}
|
|
26270
|
+
function countTasksForDeregistration(tasks) {
|
|
26271
|
+
return {
|
|
26272
|
+
total: tasks.length,
|
|
26273
|
+
incomplete: tasks.filter((task) => task.status !== "completed" && task.status !== "cancelled").length
|
|
26274
|
+
};
|
|
26275
|
+
}
|
|
26178
26276
|
function pathIsWithinPrefix(projectPath, prefix) {
|
|
26179
26277
|
const normalizedPath = resolve13(projectPath);
|
|
26180
26278
|
const normalizedPrefix = resolve13(prefix);
|
|
@@ -26650,11 +26748,8 @@ function registerProjectCommands(program2) {
|
|
|
26650
26748
|
return;
|
|
26651
26749
|
}
|
|
26652
26750
|
if (opts.deregister) {
|
|
26653
|
-
|
|
26654
|
-
|
|
26655
|
-
}
|
|
26656
|
-
const project = resolveExplicitProject(opts.deregister);
|
|
26657
|
-
const counts = countProjectTasks(project.id);
|
|
26751
|
+
const project = cloud ? await cloudResolveProject(cloud, opts.deregister) : resolveExplicitProject(opts.deregister);
|
|
26752
|
+
const counts = cloud ? countTasksForDeregistration(await cloudListTasks(cloud, { project_id: project.id, include_subtasks: true })) : countProjectTasks(project.id);
|
|
26658
26753
|
if (opts.pathPrefix && !pathIsWithinPrefix(project.path, opts.pathPrefix)) {
|
|
26659
26754
|
handleError(new Error(`Refusing to deregister ${project.name}: path ${project.path} is not within ${opts.pathPrefix}`));
|
|
26660
26755
|
}
|
|
@@ -26671,7 +26766,10 @@ function registerProjectCommands(program2) {
|
|
|
26671
26766
|
tasks_preserved: true
|
|
26672
26767
|
};
|
|
26673
26768
|
if (!opts.dryRun) {
|
|
26674
|
-
|
|
26769
|
+
if (cloud)
|
|
26770
|
+
await cloudDeleteProject(cloud, project.id);
|
|
26771
|
+
else
|
|
26772
|
+
deleteProject(project.id);
|
|
26675
26773
|
}
|
|
26676
26774
|
if (globalOpts.json) {
|
|
26677
26775
|
output(result, true);
|
|
@@ -31437,7 +31535,16 @@ class PostgresJsonRecordStore {
|
|
|
31437
31535
|
updatedAt: stringValue2(row.updated_at) ?? new Date().toISOString()
|
|
31438
31536
|
}));
|
|
31439
31537
|
}
|
|
31440
|
-
|
|
31538
|
+
async resolveAssignedToAliases(ref) {
|
|
31539
|
+
const agent = await resolveAgentForAssignedFilter(ref, this);
|
|
31540
|
+
const aliases = new Set([ref]);
|
|
31541
|
+
if (agent) {
|
|
31542
|
+
aliases.add(agent.id);
|
|
31543
|
+
aliases.add(agent.name);
|
|
31544
|
+
}
|
|
31545
|
+
return [...aliases];
|
|
31546
|
+
}
|
|
31547
|
+
async buildTaskFilterSql(filter) {
|
|
31441
31548
|
const params = [this.service, "tasks"];
|
|
31442
31549
|
const conds = ["service = $1", "object_type = $2", "deleted_at IS NULL"];
|
|
31443
31550
|
const p = (value) => {
|
|
@@ -31463,8 +31570,10 @@ class PostgresJsonRecordStore {
|
|
|
31463
31570
|
conds.push(inClause("payload->>'status'", toFilterArray(filter.status)));
|
|
31464
31571
|
if (filter.priority !== undefined)
|
|
31465
31572
|
conds.push(inClause("payload->>'priority'", toFilterArray(filter.priority)));
|
|
31466
|
-
if (filter.assigned_to !== undefined)
|
|
31467
|
-
|
|
31573
|
+
if (filter.assigned_to !== undefined) {
|
|
31574
|
+
const aliases = [...new Set((await this.resolveAssignedToAliases(filter.assigned_to)).map((a) => a.toLowerCase()))];
|
|
31575
|
+
conds.push(inClause("LOWER(payload->>'assigned_to')", aliases));
|
|
31576
|
+
}
|
|
31468
31577
|
if (filter.agent_id !== undefined)
|
|
31469
31578
|
conds.push(`payload->>'agent_id' = ${p(filter.agent_id)}`);
|
|
31470
31579
|
if (filter.created_by !== undefined)
|
|
@@ -31498,7 +31607,7 @@ class PostgresJsonRecordStore {
|
|
|
31498
31607
|
}
|
|
31499
31608
|
async listTasks(filter) {
|
|
31500
31609
|
await this.ensureSchema();
|
|
31501
|
-
const { where, params, queryRef } = this.buildTaskFilterSql(filter);
|
|
31610
|
+
const { where, params, queryRef } = await this.buildTaskFilterSql(filter);
|
|
31502
31611
|
const orderBy = queryRef ? `ORDER BY ts_rank_cd(task_search_tsv, websearch_to_tsquery('simple', todos_immutable_unaccent(${queryRef}))) DESC, ${TASK_ORDER_TIEBREAK}` : TASK_ORDER_BY;
|
|
31503
31612
|
let sql = `/* todos:list-tasks */ SELECT payload FROM ${this.tableName} WHERE ${where} ${orderBy}`;
|
|
31504
31613
|
if (filter.limit !== undefined) {
|
|
@@ -31558,7 +31667,7 @@ class PostgresJsonRecordStore {
|
|
|
31558
31667
|
}
|
|
31559
31668
|
async countTasks(filter) {
|
|
31560
31669
|
await this.ensureSchema();
|
|
31561
|
-
const { where, params } = this.buildTaskFilterSql(filter);
|
|
31670
|
+
const { where, params } = await this.buildTaskFilterSql(filter);
|
|
31562
31671
|
const sql = `/* todos:count-tasks */ SELECT COUNT(*)::int AS count FROM ${this.tableName} WHERE ${where}`;
|
|
31563
31672
|
const result = await this.options.client.query(sql, params);
|
|
31564
31673
|
return Number(result.rows[0]?.count ?? 0);
|
|
@@ -31719,9 +31828,13 @@ class PostgresJsonRecordStore {
|
|
|
31719
31828
|
} : {};
|
|
31720
31829
|
const hasEvidence = Object.keys(evidence).length > 0;
|
|
31721
31830
|
const hasConfidence = options?.confidence !== undefined;
|
|
31722
|
-
const
|
|
31831
|
+
const lockExpiryCutoff2 = new Date(new Date(operationTimestamp).getTime() - CLOUD_LOCK_EXPIRY_MINUTES * 60 * 1000).toISOString();
|
|
31832
|
+
const result = await this.options.client.query(`/* todos:complete-task-atomic todos:complete-task-lock-guard todos:complete-task-clears-lock */
|
|
31833
|
+
UPDATE ${this.tableName}
|
|
31723
31834
|
SET payload = payload || jsonb_build_object(
|
|
31724
31835
|
'status', 'completed',
|
|
31836
|
+
'locked_by', 'null'::jsonb,
|
|
31837
|
+
'locked_at', 'null'::jsonb,
|
|
31725
31838
|
'assigned_to', CASE
|
|
31726
31839
|
WHEN jsonb_typeof(payload->'assigned_to') = 'string' THEN payload->'assigned_to'
|
|
31727
31840
|
ELSE COALESCE(to_jsonb($3::text), 'null'::jsonb)
|
|
@@ -31749,6 +31862,16 @@ class PostgresJsonRecordStore {
|
|
|
31749
31862
|
updated_at = $9::timestamptz,
|
|
31750
31863
|
version = COALESCE(version, 0) + 1
|
|
31751
31864
|
WHERE service = $1 AND object_type = 'tasks' AND object_id = $2 AND deleted_at IS NULL
|
|
31865
|
+
AND (
|
|
31866
|
+
payload->>'locked_by' IS NULL
|
|
31867
|
+
OR BTRIM(payload->>'locked_by') = ''
|
|
31868
|
+
OR payload->>'locked_at' IS NULL
|
|
31869
|
+
OR payload->>'locked_at' < $10::text
|
|
31870
|
+
OR (
|
|
31871
|
+
$3::text IS NOT NULL
|
|
31872
|
+
AND LOWER(BTRIM(payload->>'locked_by')) = LOWER(BTRIM($3::text))
|
|
31873
|
+
)
|
|
31874
|
+
)
|
|
31752
31875
|
RETURNING payload`, [
|
|
31753
31876
|
this.service,
|
|
31754
31877
|
id,
|
|
@@ -31758,7 +31881,8 @@ class PostgresJsonRecordStore {
|
|
|
31758
31881
|
jsonbParam(evidence),
|
|
31759
31882
|
hasConfidence,
|
|
31760
31883
|
options?.confidence ?? null,
|
|
31761
|
-
operationTimestamp
|
|
31884
|
+
operationTimestamp,
|
|
31885
|
+
lockExpiryCutoff2
|
|
31762
31886
|
]);
|
|
31763
31887
|
return result.rows[0] ? payloadRecord2(result.rows[0].payload) : null;
|
|
31764
31888
|
}
|
|
@@ -32039,6 +32163,7 @@ async function updateTask2(id, input, store) {
|
|
|
32039
32163
|
if (existing.version !== input.version) {
|
|
32040
32164
|
throw new Error(`Task ${id} version conflict: expected ${existing.version}, got ${input.version}`);
|
|
32041
32165
|
}
|
|
32166
|
+
const reopened = existing.status === "completed" && input.status !== undefined && input.status !== "completed" && input.completed_at === undefined;
|
|
32042
32167
|
const task = {
|
|
32043
32168
|
...existing,
|
|
32044
32169
|
...definedPatch(input),
|
|
@@ -32048,7 +32173,8 @@ async function updateTask2(id, input, store) {
|
|
|
32048
32173
|
metadata: input.metadata ?? existing.metadata,
|
|
32049
32174
|
requires_approval: input.requires_approval ?? existing.requires_approval,
|
|
32050
32175
|
task_list_id: input.task_list_id !== undefined ? input.task_list_id : existing.task_list_id,
|
|
32051
|
-
created_by: existing.created_by
|
|
32176
|
+
created_by: existing.created_by,
|
|
32177
|
+
completed_at: reopened ? null : input.completed_at !== undefined ? input.completed_at : existing.completed_at
|
|
32052
32178
|
};
|
|
32053
32179
|
await store.upsert("tasks", task);
|
|
32054
32180
|
return task;
|
|
@@ -32056,11 +32182,11 @@ async function updateTask2(id, input, store) {
|
|
|
32056
32182
|
async function startTask2(id, agentId, store) {
|
|
32057
32183
|
const task = await requireRecord("tasks", id, store);
|
|
32058
32184
|
if (task.status !== "pending" && task.status !== "in_progress") {
|
|
32059
|
-
throw new
|
|
32185
|
+
throw new TaskNotStartableError(task.id, task.status, agentId);
|
|
32060
32186
|
}
|
|
32061
32187
|
const started = await patchTask(task, {
|
|
32062
32188
|
status: "in_progress",
|
|
32063
|
-
assigned_to: task.assigned_to
|
|
32189
|
+
assigned_to: task.assigned_to || agentId,
|
|
32064
32190
|
agent_id: task.agent_id ?? agentId,
|
|
32065
32191
|
locked_by: agentId,
|
|
32066
32192
|
locked_at: new Date().toISOString(),
|
|
@@ -32071,8 +32197,13 @@ async function startTask2(id, agentId, store) {
|
|
|
32071
32197
|
}
|
|
32072
32198
|
async function completeTask2(id, agentId, options, store) {
|
|
32073
32199
|
const task = await store.completeTask(id, agentId, options);
|
|
32074
|
-
if (!task)
|
|
32200
|
+
if (!task) {
|
|
32201
|
+
const current = await store.get("tasks", id);
|
|
32202
|
+
if (current?.locked_by && !cloudLockExpired(current.locked_at) && !sameCloudLockHolder(current.locked_by, agentId)) {
|
|
32203
|
+
throw new LockError(id, current.locked_by);
|
|
32204
|
+
}
|
|
32075
32205
|
throw new Error(`tasks record not found: ${id}`);
|
|
32206
|
+
}
|
|
32076
32207
|
return task;
|
|
32077
32208
|
}
|
|
32078
32209
|
async function failTask2(id, agentId, reason, options, store) {
|
|
@@ -32113,6 +32244,11 @@ async function patchTask(task, patch, store) {
|
|
|
32113
32244
|
await store.upsert("tasks", updated);
|
|
32114
32245
|
return updated;
|
|
32115
32246
|
}
|
|
32247
|
+
function sameCloudLockHolder(stored, incoming) {
|
|
32248
|
+
if (!stored || !incoming)
|
|
32249
|
+
return false;
|
|
32250
|
+
return canonicalAgentRef(stored) === canonicalAgentRef(incoming);
|
|
32251
|
+
}
|
|
32116
32252
|
function cloudLockExpired(lockedAt) {
|
|
32117
32253
|
if (!lockedAt)
|
|
32118
32254
|
return true;
|
|
@@ -32430,6 +32566,16 @@ async function resolveAgent(idOrName, store) {
|
|
|
32430
32566
|
return byId;
|
|
32431
32567
|
return matchAgentByName(await store.list("agents"), idOrName);
|
|
32432
32568
|
}
|
|
32569
|
+
async function resolveAgentForAssignedFilter(idOrName, store) {
|
|
32570
|
+
const byId = await store.get("agents", idOrName);
|
|
32571
|
+
if (byId)
|
|
32572
|
+
return byId;
|
|
32573
|
+
const target = normalizeAgentNameInput(idOrName);
|
|
32574
|
+
if (!target)
|
|
32575
|
+
return null;
|
|
32576
|
+
const matches = (await store.list("agents")).filter((agent) => normalizeAgentNameInput(agent.name) === target);
|
|
32577
|
+
return matches.length === 1 ? matches[0] : null;
|
|
32578
|
+
}
|
|
32433
32579
|
async function heartbeatAgent(idOrName, store, context) {
|
|
32434
32580
|
const agent = await resolveAgent(idOrName, store);
|
|
32435
32581
|
if (!agent)
|
|
@@ -32745,6 +32891,7 @@ function postgresConstraintName(error) {
|
|
|
32745
32891
|
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;
|
|
32746
32892
|
var init_postgres_adapter = __esm(() => {
|
|
32747
32893
|
init_types();
|
|
32894
|
+
init_creator_identity();
|
|
32748
32895
|
init_postgres_sync();
|
|
32749
32896
|
init_integrity();
|
|
32750
32897
|
init_redaction();
|
|
@@ -34234,7 +34381,10 @@ function mapTaskError(e, json2) {
|
|
|
34234
34381
|
retry_after: e.retryAfterSeconds ?? null
|
|
34235
34382
|
}, 409);
|
|
34236
34383
|
}
|
|
34237
|
-
if (e instanceof
|
|
34384
|
+
if (e instanceof TaskNotStartableError) {
|
|
34385
|
+
return json2({ error: e.message, code: TaskNotStartableError.code }, 409);
|
|
34386
|
+
}
|
|
34387
|
+
if (e instanceof Error && / is blocked by /.test(e.message)) {
|
|
34238
34388
|
return json2({ error: e.message, code: "TASK_NOT_STARTABLE" }, 409);
|
|
34239
34389
|
}
|
|
34240
34390
|
return null;
|
|
@@ -38228,10 +38378,10 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
38228
38378
|
const released2 = await store.tasks.unlock(id);
|
|
38229
38379
|
return json3({ success: released2 });
|
|
38230
38380
|
}
|
|
38231
|
-
if (body2.agent_id &&
|
|
38381
|
+
if (body2.agent_id && body2.agent_id !== principal.agent && !principal.scopes.includes("todos:*")) {
|
|
38232
38382
|
return error(403, "unlock agent_id must match the authenticated agent");
|
|
38233
38383
|
}
|
|
38234
|
-
const agentId2 =
|
|
38384
|
+
const agentId2 = body2.agent_id || principal.agent;
|
|
38235
38385
|
if (!agentId2)
|
|
38236
38386
|
return error(403, "unlock requires an agent-bound key or force=true");
|
|
38237
38387
|
const released = await store.tasks.unlock(id, agentId2);
|
|
@@ -38799,6 +38949,9 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
38799
38949
|
}
|
|
38800
38950
|
if (e instanceof LockError)
|
|
38801
38951
|
return error(409, e.message, { code: LockError.code });
|
|
38952
|
+
if (e instanceof TaskNotStartableError) {
|
|
38953
|
+
return error(409, e.message, { code: TaskNotStartableError.code });
|
|
38954
|
+
}
|
|
38802
38955
|
if (e instanceof ResourceConflictError)
|
|
38803
38956
|
return error(409, e.message, { code: e.code, conflict: true });
|
|
38804
38957
|
if (e instanceof ProjectNotFoundError)
|
|
@@ -62407,6 +62560,8 @@ var init_workflow_prompts2 = __esm(() => {
|
|
|
62407
62560
|
// src/mcp/index.ts
|
|
62408
62561
|
var exports_mcp = {};
|
|
62409
62562
|
__export(exports_mcp, {
|
|
62563
|
+
formatTaskDetail: () => formatTaskDetail,
|
|
62564
|
+
formatTask: () => formatTask,
|
|
62410
62565
|
buildServer: () => buildServer,
|
|
62411
62566
|
applyFocus: () => applyFocus
|
|
62412
62567
|
});
|
|
@@ -62555,7 +62710,8 @@ function resolveId(partialId, table = "tasks") {
|
|
|
62555
62710
|
function formatTask(task2) {
|
|
62556
62711
|
const id = task2.short_id || task2.id.slice(0, 8);
|
|
62557
62712
|
const assigned = task2.assigned_to ? ` -> ${task2.assigned_to}` : "";
|
|
62558
|
-
const
|
|
62713
|
+
const lockState = lockDisplayState(task2.locked_by, task2.locked_at);
|
|
62714
|
+
const lock = lockState.held ? ` [locked:${lockState.holder}]` : "";
|
|
62559
62715
|
const recur = task2.recurrence_rule ? ` [\u21BB]` : "";
|
|
62560
62716
|
return `${id} ${task2.status.padEnd(11)} ${task2.priority.padEnd(8)} ${task2.title}${assigned}${lock}${recur}`;
|
|
62561
62717
|
}
|
|
@@ -62574,8 +62730,11 @@ function formatTaskDetail(task2, maxDescriptionChars) {
|
|
|
62574
62730
|
parts.push(`Assigned to: ${task2.assigned_to}`);
|
|
62575
62731
|
if (task2.agent_id)
|
|
62576
62732
|
parts.push(`Agent: ${task2.agent_id}`);
|
|
62577
|
-
|
|
62578
|
-
|
|
62733
|
+
const detailLock = lockDisplayState(task2.locked_by, task2.locked_at);
|
|
62734
|
+
if (detailLock.held)
|
|
62735
|
+
parts.push(`Locked by: ${detailLock.holder}`);
|
|
62736
|
+
else if (detailLock.expired)
|
|
62737
|
+
parts.push(`Lock: ${formatExpiredLock(detailLock)}`);
|
|
62579
62738
|
if (task2.parent_id)
|
|
62580
62739
|
parts.push(`Parent: ${task2.parent_id}`);
|
|
62581
62740
|
if (task2.project_id)
|
|
@@ -62659,6 +62818,7 @@ var agentFocusMap, isDirectRun;
|
|
|
62659
62818
|
var init_mcp2 = __esm(() => {
|
|
62660
62819
|
init_agents();
|
|
62661
62820
|
init_database();
|
|
62821
|
+
init_lock_display();
|
|
62662
62822
|
init_types();
|
|
62663
62823
|
init_dispatch2();
|
|
62664
62824
|
init_task_crud2();
|
|
@@ -63704,7 +63864,7 @@ function TaskList({ tasks, selectedIndex }) {
|
|
|
63704
63864
|
task2.assigned_to
|
|
63705
63865
|
]
|
|
63706
63866
|
}, undefined, true, undefined, this),
|
|
63707
|
-
task2.locked_by && /* @__PURE__ */ jsxDEV2(Text2, {
|
|
63867
|
+
lockDisplayState(task2.locked_by, task2.locked_at).held && /* @__PURE__ */ jsxDEV2(Text2, {
|
|
63708
63868
|
color: "magenta",
|
|
63709
63869
|
children: [
|
|
63710
63870
|
" \uD83D\uDD12",
|
|
@@ -63726,6 +63886,7 @@ function TaskList({ tasks, selectedIndex }) {
|
|
|
63726
63886
|
}
|
|
63727
63887
|
var statusIcons, statusColors2, priorityLabels, priorityColors2;
|
|
63728
63888
|
var init_TaskList = __esm(() => {
|
|
63889
|
+
init_lock_display();
|
|
63729
63890
|
statusIcons = {
|
|
63730
63891
|
pending: "\u25CB",
|
|
63731
63892
|
in_progress: "\u25D0",
|
|
@@ -63888,7 +64049,7 @@ function TaskDetail({ task: task2 }) {
|
|
|
63888
64049
|
}, undefined, false, undefined, this)
|
|
63889
64050
|
]
|
|
63890
64051
|
}, undefined, true, undefined, this),
|
|
63891
|
-
task2.locked_by && /* @__PURE__ */ jsxDEV3(Box3, {
|
|
64052
|
+
lockDisplayState(task2.locked_by, task2.locked_at).held && /* @__PURE__ */ jsxDEV3(Box3, {
|
|
63892
64053
|
children: [
|
|
63893
64054
|
/* @__PURE__ */ jsxDEV3(Text3, {
|
|
63894
64055
|
dimColor: true,
|
|
@@ -63905,6 +64066,18 @@ function TaskDetail({ task: task2 }) {
|
|
|
63905
64066
|
}, undefined, true, undefined, this)
|
|
63906
64067
|
]
|
|
63907
64068
|
}, undefined, true, undefined, this),
|
|
64069
|
+
lockDisplayState(task2.locked_by, task2.locked_at).expired && /* @__PURE__ */ jsxDEV3(Box3, {
|
|
64070
|
+
children: [
|
|
64071
|
+
/* @__PURE__ */ jsxDEV3(Text3, {
|
|
64072
|
+
dimColor: true,
|
|
64073
|
+
children: "Lock: "
|
|
64074
|
+
}, undefined, false, undefined, this),
|
|
64075
|
+
/* @__PURE__ */ jsxDEV3(Text3, {
|
|
64076
|
+
dimColor: true,
|
|
64077
|
+
children: formatExpiredLock(lockDisplayState(task2.locked_by, task2.locked_at))
|
|
64078
|
+
}, undefined, false, undefined, this)
|
|
64079
|
+
]
|
|
64080
|
+
}, undefined, true, undefined, this),
|
|
63908
64081
|
task2.tags.length > 0 && /* @__PURE__ */ jsxDEV3(Box3, {
|
|
63909
64082
|
children: [
|
|
63910
64083
|
/* @__PURE__ */ jsxDEV3(Text3, {
|
|
@@ -64107,6 +64280,7 @@ function TaskDetail({ task: task2 }) {
|
|
|
64107
64280
|
}
|
|
64108
64281
|
var statusColors3;
|
|
64109
64282
|
var init_TaskDetail = __esm(() => {
|
|
64283
|
+
init_lock_display();
|
|
64110
64284
|
statusColors3 = {
|
|
64111
64285
|
pending: "yellow",
|
|
64112
64286
|
in_progress: "blue",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAO1C,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,MAAM,+BAA+B,GACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,IAAI,CAAA;CAAE,GACrC;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;AAyB/E,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;CA8BgB,CAAC;AAsBvD,wBAAgB,kCAAkC,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAC9C,OAAO,CAKT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAAG,IAAI,CASnH;
|
|
1
|
+
{"version":3,"file":"stage-a.d.ts","sourceRoot":"","sources":["../../src/cli/stage-a.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAQ,MAAM,WAAW,CAAC;AAO1C,KAAK,GAAG,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAE9C,MAAM,MAAM,+BAA+B,GACvC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,IAAI,CAAA;CAAE,GACrC;IAAE,KAAK,EAAE,mBAAmB,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,oBAAoB,GAAG,YAAY,GAAG,aAAa,GAAG,YAAY,CAAC;AAyB/E,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;CA8BgB,CAAC;AAsBvD,wBAAgB,kCAAkC,IAAI,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAE9F;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAC9C,OAAO,CAKT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,+BAA+B,CAAC,OAAO,CAAC,GAAG,IAAI,CASnH;AAkTD;;;;GAIG;AACH,wBAAgB,2BAA2B,CACzC,IAAI,GAAE,MAAM,EAA0B,EACtC,GAAG,GAAE,GAAwB,GAC5B,+BAA+B,CAgBjC"}
|