@hasna/todos 0.15.16 → 0.15.18

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.
@@ -70,7 +70,7 @@ var package_default;
70
70
  var init_package = __esm(() => {
71
71
  package_default = {
72
72
  name: "@hasna/todos",
73
- version: "0.15.16",
73
+ version: "0.15.18",
74
74
  description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
75
75
  type: "module",
76
76
  main: "dist/index.js",
@@ -14537,8 +14537,8 @@ function failTask2(id, agentId, reason, options, db) {
14537
14537
  const safeMeta = sanitizePreWriteValue(meta, "task.failure.metadata");
14538
14538
  const timestamp2 = now();
14539
14539
  const failTx = d.transaction(() => {
14540
- const res = d.run(`UPDATE tasks SET status = 'failed', locked_by = NULL, locked_at = NULL, metadata = ?, version = version + 1, updated_at = ?
14541
- WHERE id = ? AND version = ?`, [JSON.stringify(safeMeta), timestamp2, id, task.version]);
14540
+ const res = d.run(`UPDATE tasks SET status = 'failed', reason = ?, locked_by = NULL, locked_at = NULL, metadata = ?, version = version + 1, updated_at = ?
14541
+ WHERE id = ? AND version = ?`, [safeReason, JSON.stringify(safeMeta), timestamp2, id, task.version]);
14542
14542
  if (res.changes === 0) {
14543
14543
  const current = getTask(id, d);
14544
14544
  throw new VersionConflictError(id, task.version, current?.version ?? -1);
@@ -14550,6 +14550,7 @@ function failTask2(id, agentId, reason, options, db) {
14550
14550
  status: "failed",
14551
14551
  locked_by: null,
14552
14552
  locked_at: null,
14553
+ reason: safeReason,
14553
14554
  metadata: safeMeta,
14554
14555
  version: task.version + 1,
14555
14556
  updated_at: timestamp2
@@ -29039,8 +29040,8 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
29039
29040
  properties: {
29040
29041
  title: { type: "string" },
29041
29042
  description: { type: "string", nullable: true },
29042
- status: { type: "string" },
29043
- priority: { type: "string" },
29043
+ status: { type: "string", enum: [...TASK_STATUSES] },
29044
+ priority: { type: "string", enum: [...TASK_PRIORITIES] },
29044
29045
  project_id: { type: "string" },
29045
29046
  parent_id: { type: "string" },
29046
29047
  plan_id: { type: "string" },
@@ -29054,8 +29055,8 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
29054
29055
  properties: {
29055
29056
  title: { type: "string" },
29056
29057
  description: { type: "string" },
29057
- status: { type: "string" },
29058
- priority: { type: "string" },
29058
+ status: { type: "string", enum: [...TASK_STATUSES] },
29059
+ priority: { type: "string", enum: [...TASK_PRIORITIES] },
29059
29060
  assigned_to: { type: "string" },
29060
29061
  project_id: { type: "string", nullable: true },
29061
29062
  plan_id: { type: "string", nullable: true },
@@ -29076,6 +29077,24 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
29076
29077
  confidence: { type: "number", minimum: 0, maximum: 1 }
29077
29078
  }
29078
29079
  },
29080
+ FailTaskInput: {
29081
+ type: "object",
29082
+ additionalProperties: false,
29083
+ properties: {
29084
+ agent_id: { type: "string", minLength: 1 },
29085
+ reason: { type: "string" },
29086
+ retry: { type: "boolean" }
29087
+ }
29088
+ },
29089
+ TaskFailureResult: {
29090
+ type: "object",
29091
+ additionalProperties: false,
29092
+ required: ["task"],
29093
+ properties: {
29094
+ task: { $ref: "#/components/schemas/Task" },
29095
+ retryTask: { $ref: "#/components/schemas/Task" }
29096
+ }
29097
+ },
29079
29098
  CreateProjectInput: {
29080
29099
  type: "object",
29081
29100
  additionalProperties: false,
@@ -30319,6 +30338,30 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
30319
30338
  responses: { "200": { content: { "application/json": { schema: { type: "object", properties: { task: { $ref: "#/components/schemas/Task" } } } } } } }
30320
30339
  }
30321
30340
  },
30341
+ "/v1/tasks/{id}/fail": {
30342
+ post: {
30343
+ operationId: "failTask",
30344
+ summary: "Fail a task with an optional reason and retry copy",
30345
+ parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" } }],
30346
+ requestBody: {
30347
+ required: false,
30348
+ content: { "application/json": { schema: { $ref: "#/components/schemas/FailTaskInput" } } }
30349
+ },
30350
+ responses: {
30351
+ "200": {
30352
+ content: {
30353
+ "application/json": {
30354
+ schema: {
30355
+ type: "object",
30356
+ required: ["result"],
30357
+ properties: { result: { $ref: "#/components/schemas/TaskFailureResult" } }
30358
+ }
30359
+ }
30360
+ }
30361
+ }
30362
+ }
30363
+ }
30364
+ },
30322
30365
  "/v1/projects": {
30323
30366
  get: {
30324
30367
  operationId: "listProjects",
@@ -30760,12 +30803,13 @@ var init_openapi = __esm(() => {
30760
30803
  id: { type: "string" },
30761
30804
  title: { type: "string" },
30762
30805
  description: { type: "string" },
30763
- status: { type: "string" },
30764
- priority: { type: "string" },
30806
+ status: { type: "string", enum: [...TASK_STATUSES] },
30807
+ priority: { type: "string", enum: [...TASK_PRIORITIES] },
30765
30808
  project_id: { type: "string", nullable: true },
30766
30809
  parent_id: { type: "string", nullable: true },
30767
30810
  assigned_to: { type: "string", nullable: true },
30768
30811
  agent_id: { type: "string", nullable: true },
30812
+ reason: { type: "string", nullable: true },
30769
30813
  tags: { type: "array", items: { type: "string" } },
30770
30814
  version: { type: "number" },
30771
30815
  created_at: { type: "string" },
@@ -31645,6 +31689,44 @@ function validateTaskCompletion(value) {
31645
31689
  }
31646
31690
  };
31647
31691
  }
31692
+ function validateTaskFailure(value) {
31693
+ if (!value || typeof value !== "object" || Array.isArray(value))
31694
+ return { ok: false, message: "failure body must be an object" };
31695
+ const body2 = value;
31696
+ const allowed = new Set(["agent_id", "reason", "retry"]);
31697
+ const unknown = Object.keys(body2).find((key2) => !allowed.has(key2));
31698
+ if (unknown)
31699
+ return { ok: false, message: `unknown failure field: ${unknown}` };
31700
+ if (body2.agent_id !== undefined && (typeof body2.agent_id !== "string" || !body2.agent_id.trim())) {
31701
+ return { ok: false, message: "agent_id must be a non-empty string" };
31702
+ }
31703
+ if (body2.reason !== undefined && typeof body2.reason !== "string")
31704
+ return { ok: false, message: "reason must be a string" };
31705
+ if (body2.retry !== undefined && typeof body2.retry !== "boolean")
31706
+ return { ok: false, message: "retry must be a boolean" };
31707
+ return {
31708
+ ok: true,
31709
+ ...typeof body2.agent_id === "string" ? { agentId: body2.agent_id } : {},
31710
+ reason: typeof body2.reason === "string" && body2.reason ? body2.reason : "Unknown failure",
31711
+ retry: body2.retry === true
31712
+ };
31713
+ }
31714
+ function validateTaskPatchVocabulary(value) {
31715
+ if (!value || typeof value !== "object" || Array.isArray(value))
31716
+ return { ok: false, message: "task patch must be an object" };
31717
+ const body2 = value;
31718
+ for (const [name, vocabulary] of [["status", TASK_STATUSES], ["priority", TASK_PRIORITIES]]) {
31719
+ const raw = body2[name];
31720
+ if (raw === undefined)
31721
+ continue;
31722
+ if (typeof raw !== "string")
31723
+ return { ok: false, message: `${name} must be a string. Allowed values: ${vocabulary.join(", ")}.` };
31724
+ const parsed = resolveEnumVocabulary(raw, { name, vocabulary, allowList: false });
31725
+ if (!parsed.ok)
31726
+ return { ok: false, message: parsed.message };
31727
+ }
31728
+ return { ok: true, patch: body2 };
31729
+ }
31648
31730
  function validateProjectPatch(value) {
31649
31731
  if (!value || typeof value !== "object" || Array.isArray(value))
31650
31732
  return { ok: false, message: "project patch must be an object" };
@@ -32325,7 +32407,12 @@ async function handleV1Request(req, url, dependencies = {}) {
32325
32407
  });
32326
32408
  }
32327
32409
  if (action === "fail" && method === "POST") {
32328
- return json5({ result: await store.tasks.fail(id, agentId, typeof body2.reason === "string" ? body2.reason : "failed", {}) });
32410
+ const parsed = validateTaskFailure(actionJson.value);
32411
+ if (!parsed.ok)
32412
+ return error(400, parsed.message);
32413
+ return json5({
32414
+ result: await store.tasks.fail(id, parsed.agentId || principal.agent || "todos-serve", parsed.reason, { retry: parsed.retry }, contextFromPrincipal(principal, body2))
32415
+ });
32329
32416
  }
32330
32417
  if (action === "claim" && method === "POST") {
32331
32418
  return json5({ task: await store.tasks.claimNext(agentId, {}) });
@@ -32354,9 +32441,13 @@ async function handleV1Request(req, url, dependencies = {}) {
32354
32441
  return task2 ? json5({ task: task2 }) : error(404, "task not found");
32355
32442
  }
32356
32443
  if (method === "PATCH" || method === "PUT") {
32357
- const body2 = await readJson3(req);
32358
- if (!body2)
32444
+ const rawBody = await readJson3(req);
32445
+ if (!rawBody)
32359
32446
  return error(400, "invalid JSON body");
32447
+ const validated = validateTaskPatchVocabulary(rawBody);
32448
+ if (!validated.ok)
32449
+ return error(400, validated.message);
32450
+ const body2 = validated.patch;
32360
32451
  const current = await store.tasks.get(id);
32361
32452
  if (!current)
32362
32453
  return error(404, "task not found");
@@ -64213,7 +64304,7 @@ function resolveTaskListFromCandidates(lists, input) {
64213
64304
  ];
64214
64305
  for (const matches of matchGroups) {
64215
64306
  if (matches.length === 1)
64216
- return matches[0].id;
64307
+ return matches[0];
64217
64308
  if (matches.length > 1) {
64218
64309
  throw new Error(`Task list reference is ambiguous: "${input}"`);
64219
64310
  }
@@ -64226,27 +64317,26 @@ async function legacyProjectTaskLists(client, projectId) {
64226
64317
  return [];
64227
64318
  return (await cloudListTaskLists(client)).filter((list) => list.project_id == null && list.slug === project.task_list_id);
64228
64319
  }
64229
- async function cloudResolveTaskListRef(client, ref, projectId) {
64320
+ async function cloudResolveTaskList(client, ref, projectId) {
64230
64321
  const input = ref.trim();
64231
64322
  const normalizedIdRef = input.toLowerCase();
64232
- if (UUID_RE.test(input) && !projectId)
64233
- return normalizedIdRef;
64234
- if (UUID_RE.test(input) && projectId) {
64323
+ if (UUID_RE.test(input)) {
64235
64324
  const direct = await cloudGetTaskList(client, normalizedIdRef);
64236
64325
  if (direct?.id?.toLowerCase() === normalizedIdRef) {
64237
- if (direct.project_id === projectId)
64238
- return direct.id;
64326
+ if (!projectId || direct.project_id === projectId)
64327
+ return direct;
64239
64328
  if (direct.project_id == null) {
64240
64329
  const project = await cloudGetProjectById(client, projectId);
64241
64330
  if (project?.task_list_id === direct.slug)
64242
- return direct.id;
64331
+ return direct;
64243
64332
  }
64244
64333
  throw new Error(`Task list not found: "${input}"`);
64245
64334
  }
64246
64335
  }
64247
64336
  const scopedMatch = resolveTaskListFromCandidates(await cloudListTaskLists(client, projectId), input);
64248
- if (scopedMatch)
64337
+ if (scopedMatch && (!projectId || scopedMatch.project_id === projectId)) {
64249
64338
  return scopedMatch;
64339
+ }
64250
64340
  if (projectId) {
64251
64341
  const legacyMatch = resolveTaskListFromCandidates(await legacyProjectTaskLists(client, projectId), input);
64252
64342
  if (legacyMatch)
@@ -64254,6 +64344,12 @@ async function cloudResolveTaskListRef(client, ref, projectId) {
64254
64344
  }
64255
64345
  throw new Error(`Task list not found: "${input}"`);
64256
64346
  }
64347
+ async function cloudResolveTaskListRef(client, ref, projectId) {
64348
+ const input = ref.trim();
64349
+ if (UUID_RE.test(input) && !projectId)
64350
+ return input.toLowerCase();
64351
+ return (await cloudResolveTaskList(client, ref, projectId)).id;
64352
+ }
64257
64353
  var UUID_RE, TRANSPORT_TOKENS, completionCapabilityCache, gitRefCapabilityCache, SERVER_MODE_CANDIDATES, cachedServerMode = null, PRIORITY_RANK, listTagsCapabilityCache;
64258
64354
  var init_cloud_router = __esm(() => {
64259
64355
  init_storage();
@@ -31,9 +31,11 @@ export declare function buildV1OpenApiDocument(version?: string): {
31
31
  };
32
32
  readonly status: {
33
33
  readonly type: "string";
34
+ readonly enum: readonly ["pending", "in_progress", "completed", "failed", "cancelled"];
34
35
  };
35
36
  readonly priority: {
36
37
  readonly type: "string";
38
+ readonly enum: readonly ["low", "medium", "high", "critical"];
37
39
  };
38
40
  readonly project_id: {
39
41
  readonly type: "string";
@@ -51,6 +53,10 @@ export declare function buildV1OpenApiDocument(version?: string): {
51
53
  readonly type: "string";
52
54
  readonly nullable: true;
53
55
  };
56
+ readonly reason: {
57
+ readonly type: "string";
58
+ readonly nullable: true;
59
+ };
54
60
  readonly tags: {
55
61
  readonly type: "array";
56
62
  readonly items: {
@@ -794,9 +800,11 @@ export declare function buildV1OpenApiDocument(version?: string): {
794
800
  };
795
801
  status: {
796
802
  type: string;
803
+ enum: ("pending" | "in_progress" | "completed" | "failed" | "cancelled")[];
797
804
  };
798
805
  priority: {
799
806
  type: string;
807
+ enum: ("low" | "medium" | "high" | "critical")[];
800
808
  };
801
809
  project_id: {
802
810
  type: string;
@@ -832,9 +840,11 @@ export declare function buildV1OpenApiDocument(version?: string): {
832
840
  };
833
841
  status: {
834
842
  type: string;
843
+ enum: ("pending" | "in_progress" | "completed" | "failed" | "cancelled")[];
835
844
  };
836
845
  priority: {
837
846
  type: string;
847
+ enum: ("low" | "medium" | "high" | "critical")[];
838
848
  };
839
849
  assigned_to: {
840
850
  type: string;
@@ -894,6 +904,35 @@ export declare function buildV1OpenApiDocument(version?: string): {
894
904
  };
895
905
  };
896
906
  };
907
+ FailTaskInput: {
908
+ type: string;
909
+ additionalProperties: boolean;
910
+ properties: {
911
+ agent_id: {
912
+ type: string;
913
+ minLength: number;
914
+ };
915
+ reason: {
916
+ type: string;
917
+ };
918
+ retry: {
919
+ type: string;
920
+ };
921
+ };
922
+ };
923
+ TaskFailureResult: {
924
+ type: string;
925
+ additionalProperties: boolean;
926
+ required: string[];
927
+ properties: {
928
+ task: {
929
+ $ref: string;
930
+ };
931
+ retryTask: {
932
+ $ref: string;
933
+ };
934
+ };
935
+ };
897
936
  CreateProjectInput: {
898
937
  type: string;
899
938
  additionalProperties: boolean;
@@ -2994,6 +3033,47 @@ export declare function buildV1OpenApiDocument(version?: string): {
2994
3033
  };
2995
3034
  };
2996
3035
  };
3036
+ "/v1/tasks/{id}/fail": {
3037
+ post: {
3038
+ operationId: string;
3039
+ summary: string;
3040
+ parameters: {
3041
+ name: string;
3042
+ in: string;
3043
+ required: boolean;
3044
+ schema: {
3045
+ type: string;
3046
+ };
3047
+ }[];
3048
+ requestBody: {
3049
+ required: boolean;
3050
+ content: {
3051
+ "application/json": {
3052
+ schema: {
3053
+ $ref: string;
3054
+ };
3055
+ };
3056
+ };
3057
+ };
3058
+ responses: {
3059
+ "200": {
3060
+ content: {
3061
+ "application/json": {
3062
+ schema: {
3063
+ type: string;
3064
+ required: string[];
3065
+ properties: {
3066
+ result: {
3067
+ $ref: string;
3068
+ };
3069
+ };
3070
+ };
3071
+ };
3072
+ };
3073
+ };
3074
+ };
3075
+ };
3076
+ };
2997
3077
  "/v1/projects": {
2998
3078
  get: {
2999
3079
  operationId: string;
@@ -1 +1 @@
1
- {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/server/openapi.ts"],"names":[],"mappings":"AA+WA,wBAAgB,sBAAsB,CAAC,OAAO,SAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsgDnE"}
1
+ {"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/server/openapi.ts"],"names":[],"mappings":"AAgXA,wBAAgB,sBAAsB,CAAC,OAAO,SAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgjDnE"}
@@ -1 +1 @@
1
- {"version":3,"file":"v1.d.ts","sourceRoot":"","sources":["../../src/server/v1.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAuB,oBAAoB,EAAmD,MAAM,0BAA0B,CAAC;AAC3I,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oCAAoC,EACpC,sBAAsB,EACtB,6BAA6B,EAC7B,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAoBpB,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,OAAO,gBAAgB,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,iBAAiB,CAAC;IACxC,iBAAiB,CAAC,EAAE,OAAO,sBAAsB,CAAC;IAClD,gBAAgB,CAAC,EAAE,OAAO,qBAAqB,CAAC;IAChD,+BAA+B,CAAC,EAAE,OAAO,oCAAoC,CAAC;IAC9E,wBAAwB,CAAC,EAAE,OAAO,6BAA6B,CAAC;CACjE;AAwVD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB,CAiB1E;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAapE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,YAAY,GAAE,qBAA0B,GACvC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA8kC1B"}
1
+ {"version":3,"file":"v1.d.ts","sourceRoot":"","sources":["../../src/server/v1.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAuB,oBAAoB,EAAmD,MAAM,0BAA0B,CAAC;AAC3I,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,oCAAoC,EACpC,sBAAsB,EACtB,6BAA6B,EAC7B,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAoBpB,MAAM,WAAW,qBAAqB;IACpC,WAAW,CAAC,EAAE,OAAO,gBAAgB,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,iBAAiB,CAAC;IACxC,iBAAiB,CAAC,EAAE,OAAO,sBAAsB,CAAC;IAClD,gBAAgB,CAAC,EAAE,OAAO,qBAAqB,CAAC;IAChD,+BAA+B,CAAC,EAAE,OAAO,oCAAoC,CAAC;IAC9E,wBAAwB,CAAC,EAAE,OAAO,6BAA6B,CAAC;CACjE;AA4XD;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,oBAAoB,CAiB1E;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,oBAAoB,GAAG,MAAM,CAapE;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,GAAG,EACR,YAAY,GAAE,qBAA0B,GACvC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA2lC1B"}
package/dist/storage.js CHANGED
@@ -8949,8 +8949,8 @@ function failTask(id, agentId, reason, options, db) {
8949
8949
  const safeMeta = sanitizePreWriteValue(meta, "task.failure.metadata");
8950
8950
  const timestamp2 = now();
8951
8951
  const failTx = d.transaction(() => {
8952
- const res = d.run(`UPDATE tasks SET status = 'failed', locked_by = NULL, locked_at = NULL, metadata = ?, version = version + 1, updated_at = ?
8953
- WHERE id = ? AND version = ?`, [JSON.stringify(safeMeta), timestamp2, id, task.version]);
8952
+ const res = d.run(`UPDATE tasks SET status = 'failed', reason = ?, locked_by = NULL, locked_at = NULL, metadata = ?, version = version + 1, updated_at = ?
8953
+ WHERE id = ? AND version = ?`, [safeReason, JSON.stringify(safeMeta), timestamp2, id, task.version]);
8954
8954
  if (res.changes === 0) {
8955
8955
  const current = getTask(id, d);
8956
8956
  throw new VersionConflictError(id, task.version, current?.version ?? -1);
@@ -8962,6 +8962,7 @@ function failTask(id, agentId, reason, options, db) {
8962
8962
  status: "failed",
8963
8963
  locked_by: null,
8964
8964
  locked_at: null,
8965
+ reason: safeReason,
8965
8966
  metadata: safeMeta,
8966
8967
  version: task.version + 1,
8967
8968
  updated_at: timestamp2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/todos",
3
- "version": "0.15.16",
3
+ "version": "0.15.18",
4
4
  "description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",