@hasna/todos 0.15.15 → 0.15.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/cloud-router.d.ts +8 -1
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/commands/mcp-hooks-commands.d.ts.map +1 -1
- package/dist/cli/commands/query-commands.d.ts.map +1 -1
- package/dist/cli/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +508 -43
- package/dist/contracts.js +4 -3
- package/dist/db/task-lifecycle.d.ts.map +1 -1
- package/dist/index.js +93 -16
- package/dist/lib/agent-adapter-docs.d.ts +10 -0
- package/dist/lib/agent-adapter-docs.d.ts.map +1 -1
- package/dist/mcp/index.js +233 -27
- package/dist/mcp.js +1 -1
- package/dist/project-registration.js +4 -3
- package/dist/registry.js +4 -3
- package/dist/release-provenance.json +5 -5
- package/dist/sdk/index.d.ts +1 -1
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +7 -0
- package/dist/sdk/v1.generated.d.ts +20 -6
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/index.js +233 -27
- package/dist/server/openapi.d.ts +80 -0
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage.js +3 -2
- package/dist/task-manifest/authority.d.ts.map +1 -1
- package/dist/task-manifest/index.d.ts +1 -1
- package/dist/task-manifest/index.d.ts.map +1 -1
- package/dist/task-manifest/postgres.d.ts.map +1 -1
- package/dist/task-manifest/sqlite.d.ts.map +1 -1
- package/dist/task-manifest/types.d.ts +2 -0
- package/dist/task-manifest/types.d.ts.map +1 -1
- package/dist/task-manifest.js +89 -13
- package/package.json +1 -1
package/dist/mcp/index.js
CHANGED
|
@@ -13596,8 +13596,8 @@ function failTask(id, agentId, reason, options, db) {
|
|
|
13596
13596
|
const safeMeta = sanitizePreWriteValue(meta, "task.failure.metadata");
|
|
13597
13597
|
const timestamp2 = now();
|
|
13598
13598
|
const failTx = d.transaction(() => {
|
|
13599
|
-
const res = d.run(`UPDATE tasks SET status = 'failed', locked_by = NULL, locked_at = NULL, metadata = ?, version = version + 1, updated_at = ?
|
|
13600
|
-
WHERE id = ? AND version = ?`, [JSON.stringify(safeMeta), timestamp2, id, task.version]);
|
|
13599
|
+
const res = d.run(`UPDATE tasks SET status = 'failed', reason = ?, locked_by = NULL, locked_at = NULL, metadata = ?, version = version + 1, updated_at = ?
|
|
13600
|
+
WHERE id = ? AND version = ?`, [safeReason, JSON.stringify(safeMeta), timestamp2, id, task.version]);
|
|
13601
13601
|
if (res.changes === 0) {
|
|
13602
13602
|
const current = getTask(id, d);
|
|
13603
13603
|
throw new VersionConflictError(id, task.version, current?.version ?? -1);
|
|
@@ -13609,6 +13609,7 @@ function failTask(id, agentId, reason, options, db) {
|
|
|
13609
13609
|
status: "failed",
|
|
13610
13610
|
locked_by: null,
|
|
13611
13611
|
locked_at: null,
|
|
13612
|
+
reason: safeReason,
|
|
13612
13613
|
metadata: safeMeta,
|
|
13613
13614
|
version: task.version + 1,
|
|
13614
13615
|
updated_at: timestamp2
|
|
@@ -21041,10 +21042,72 @@ async function requireTagsFilterCapability(client) {
|
|
|
21041
21042
|
throw new Error(`REMOTE_TAGS_FILTER_UNSUPPORTED: configured Todos authority ${authority} does not advertise the tags ` + "query param on GET /v1/tasks; deploy the current @hasna/todos /v1 server to filter by tag; " + "no unfiltered task read was issued");
|
|
21042
21043
|
}
|
|
21043
21044
|
}
|
|
21044
|
-
|
|
21045
|
+
function parseCloudTaskTotal(raw) {
|
|
21046
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
21047
|
+
return;
|
|
21048
|
+
const total = raw.total;
|
|
21049
|
+
return typeof total === "number" && Number.isSafeInteger(total) && total >= 0 ? total : undefined;
|
|
21050
|
+
}
|
|
21051
|
+
async function requestRawCloudTaskPage(client, filter) {
|
|
21045
21052
|
const res = await requiredRemoteRoute(client, "/v1/tasks", () => client.list("tasks", { query: toListQuery(filter) }));
|
|
21046
21053
|
const envelope = res.raw;
|
|
21047
|
-
return
|
|
21054
|
+
return {
|
|
21055
|
+
tasks: Array.isArray(envelope?.tasks) ? envelope.tasks : res.items,
|
|
21056
|
+
total: parseCloudTaskTotal(res.raw)
|
|
21057
|
+
};
|
|
21058
|
+
}
|
|
21059
|
+
function cloudTaskListFilterError(code, taskListId, detail) {
|
|
21060
|
+
return new Error(`${code}: hosted authority returned rows outside requested task_list_id ${taskListId}; ${detail}; refusing an incomplete exact-list result`);
|
|
21061
|
+
}
|
|
21062
|
+
async function requestCloudTaskPage(client, filter) {
|
|
21063
|
+
const firstPage = await requestRawCloudTaskPage(client, filter);
|
|
21064
|
+
const tasks = firstPage.tasks;
|
|
21065
|
+
if (filter.task_list_id === undefined)
|
|
21066
|
+
return tasks;
|
|
21067
|
+
const taskListId = filter.task_list_id;
|
|
21068
|
+
if (tasks.every((task) => task.task_list_id === taskListId))
|
|
21069
|
+
return tasks;
|
|
21070
|
+
const scanLimit = filter.limit;
|
|
21071
|
+
const startOffset = filter.offset ?? 0;
|
|
21072
|
+
if (startOffset !== 0 || scanLimit === undefined || !Number.isSafeInteger(scanLimit) || scanLimit <= 0 || firstPage.total === undefined) {
|
|
21073
|
+
throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, "the response does not provide complete bounded total/offset pagination evidence");
|
|
21074
|
+
}
|
|
21075
|
+
const total = firstPage.total;
|
|
21076
|
+
if (total > scanLimit) {
|
|
21077
|
+
throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_INCOMPLETE", taskListId, `reported total ${total} exceeds bounded scan limit ${scanLimit}`);
|
|
21078
|
+
}
|
|
21079
|
+
if (tasks.length > total) {
|
|
21080
|
+
throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `the first page contains ${tasks.length} rows but reports total ${total}`);
|
|
21081
|
+
}
|
|
21082
|
+
const seenTaskIds = new Set;
|
|
21083
|
+
for (const task of tasks) {
|
|
21084
|
+
if (seenTaskIds.has(task.id)) {
|
|
21085
|
+
throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `the first page repeats task id ${task.id}`);
|
|
21086
|
+
}
|
|
21087
|
+
seenTaskIds.add(task.id);
|
|
21088
|
+
}
|
|
21089
|
+
while (tasks.length < total) {
|
|
21090
|
+
const remaining = total - tasks.length;
|
|
21091
|
+
const page = await requestRawCloudTaskPage(client, {
|
|
21092
|
+
...filter,
|
|
21093
|
+
offset: tasks.length,
|
|
21094
|
+
limit: Math.min(scanLimit - tasks.length, remaining)
|
|
21095
|
+
});
|
|
21096
|
+
if (page.total !== total) {
|
|
21097
|
+
throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `pagination total changed from ${total} to ${String(page.total)}`);
|
|
21098
|
+
}
|
|
21099
|
+
if (page.tasks.length === 0 || tasks.length + page.tasks.length > total) {
|
|
21100
|
+
throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, "pagination did not make bounded progress toward the reported total");
|
|
21101
|
+
}
|
|
21102
|
+
for (const task of page.tasks) {
|
|
21103
|
+
if (seenTaskIds.has(task.id)) {
|
|
21104
|
+
throw cloudTaskListFilterError("REMOTE_TASK_LIST_FILTER_UNSUPPORTED", taskListId, `pagination repeats task id ${task.id}`);
|
|
21105
|
+
}
|
|
21106
|
+
seenTaskIds.add(task.id);
|
|
21107
|
+
}
|
|
21108
|
+
tasks.push(...page.tasks);
|
|
21109
|
+
}
|
|
21110
|
+
return tasks.filter((task) => task.task_list_id === taskListId);
|
|
21048
21111
|
}
|
|
21049
21112
|
async function cloudListTasks(client, filter = {}) {
|
|
21050
21113
|
if (filter.tags?.length)
|
|
@@ -21083,12 +21146,10 @@ async function cloudGetTask(client, id) {
|
|
|
21083
21146
|
}
|
|
21084
21147
|
async function cloudCreateTask(client, input) {
|
|
21085
21148
|
const expectedParentId = typeof input["parent_id"] === "string" ? input["parent_id"] : null;
|
|
21086
|
-
const created = unwrapTask(await requiredRemoteRoute(client, "/v1/tasks", () =>
|
|
21149
|
+
const created = unwrapTask(await requiredRemoteRoute(client, "/v1/tasks", () => client.create("tasks", input, { retry: false }), ["PARENT_TASK_NOT_FOUND"]));
|
|
21087
21150
|
if (!created || typeof created.id !== "string" || !created.id.trim()) {
|
|
21088
21151
|
throw new Error(`REMOTE_API_INCOMPATIBLE: configured Todos authority ${remoteAuthorityBase(client)} returned a task create ` + "response without a stored task id; no success row or local SQLite fallback is permitted");
|
|
21089
21152
|
}
|
|
21090
|
-
if (expectedParentId === null)
|
|
21091
|
-
return created;
|
|
21092
21153
|
const persisted = await cloudGetTask(client, created.id);
|
|
21093
21154
|
if (!persisted || persisted.id !== created.id || (persisted.parent_id ?? null) !== expectedParentId) {
|
|
21094
21155
|
throw new Error(`TASK_CREATE_PERSISTENCE_UNVERIFIED: configured Todos authority ${remoteAuthorityBase(client)} accepted ` + `POST /v1/tasks but authoritative GET /v1/tasks/${encodeURIComponent(created.id)} did not return the same ` + "stored task id and parent_id; no success row or local SQLite fallback is permitted");
|
|
@@ -35415,7 +35476,7 @@ var package_default;
|
|
|
35415
35476
|
var init_package = __esm(() => {
|
|
35416
35477
|
package_default = {
|
|
35417
35478
|
name: "@hasna/todos",
|
|
35418
|
-
version: "0.15.
|
|
35479
|
+
version: "0.15.17",
|
|
35419
35480
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
35420
35481
|
type: "module",
|
|
35421
35482
|
main: "dist/index.js",
|
|
@@ -51606,6 +51667,22 @@ class PostgresTodosTaskManifestBackend {
|
|
|
51606
51667
|
async markOutboxDelivered(outboxId, deliveredAt) {
|
|
51607
51668
|
await this.ensureSchema();
|
|
51608
51669
|
await this.client.transaction(async (tx) => {
|
|
51670
|
+
const owned = await tx.query(`SELECT r.operation_id
|
|
51671
|
+
FROM todos_task_manifest_outbox o
|
|
51672
|
+
JOIN todos_task_manifest_receipts r
|
|
51673
|
+
ON r.receipt_id = o.apply_receipt_id
|
|
51674
|
+
WHERE r.tenant_id = $1
|
|
51675
|
+
AND r.authority = 'todos'
|
|
51676
|
+
AND r.route = 'todos.task-manifest.v1'
|
|
51677
|
+
AND r.schema_version = 1
|
|
51678
|
+
AND r.kind = 'apply'
|
|
51679
|
+
AND o.id = $2
|
|
51680
|
+
LIMIT 1`, [this.tenantId, outboxId]);
|
|
51681
|
+
const operationId = owned.rows[0]?.operation_id;
|
|
51682
|
+
if (operationId == null) {
|
|
51683
|
+
throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
|
|
51684
|
+
}
|
|
51685
|
+
await tx.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [`${this.service}\x1F${String(operationId)}`]);
|
|
51609
51686
|
const result = await tx.query(`UPDATE todos_task_manifest_outbox
|
|
51610
51687
|
SET status = 'delivered', delivered_at = $1, attempts = attempts + 1
|
|
51611
51688
|
WHERE id = $2 AND status = 'pending'
|
|
@@ -51613,10 +51690,28 @@ class PostgresTodosTaskManifestBackend {
|
|
|
51613
51690
|
SELECT 1 FROM todos_task_manifest_receipts r
|
|
51614
51691
|
WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
|
|
51615
51692
|
AND r.tenant_id = $3
|
|
51693
|
+
AND r.authority = 'todos'
|
|
51694
|
+
AND r.route = 'todos.task-manifest.v1'
|
|
51695
|
+
AND r.schema_version = 1
|
|
51696
|
+
AND r.kind = 'apply'
|
|
51616
51697
|
)
|
|
51617
51698
|
RETURNING id`, [deliveredAt, outboxId, this.tenantId]);
|
|
51618
|
-
if (
|
|
51619
|
-
|
|
51699
|
+
if (result.rows[0])
|
|
51700
|
+
return;
|
|
51701
|
+
const existing = await tx.query(`SELECT o.status
|
|
51702
|
+
FROM todos_task_manifest_outbox o
|
|
51703
|
+
JOIN todos_task_manifest_receipts r
|
|
51704
|
+
ON r.receipt_id = o.apply_receipt_id
|
|
51705
|
+
WHERE r.tenant_id = $1
|
|
51706
|
+
AND r.authority = 'todos'
|
|
51707
|
+
AND r.route = 'todos.task-manifest.v1'
|
|
51708
|
+
AND r.schema_version = 1
|
|
51709
|
+
AND r.kind = 'apply'
|
|
51710
|
+
AND o.id = $2
|
|
51711
|
+
LIMIT 1`, [this.tenantId, outboxId]);
|
|
51712
|
+
if (existing.rows[0]?.status === "delivered")
|
|
51713
|
+
return;
|
|
51714
|
+
throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_GRAPH_CONFLICT", `Pending outbox row not found: ${outboxId}`);
|
|
51620
51715
|
});
|
|
51621
51716
|
}
|
|
51622
51717
|
async compensate(input, receipt, compensationReceiptId, requestDigest, now4) {
|
|
@@ -51648,7 +51743,13 @@ class PostgresTodosTaskManifestBackend {
|
|
|
51648
51743
|
throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Graph is not applied");
|
|
51649
51744
|
const delivered = await tx.query(`SELECT o.id FROM todos_task_manifest_outbox o
|
|
51650
51745
|
JOIN todos_task_manifest_receipts r ON r.receipt_id = o.apply_receipt_id
|
|
51651
|
-
WHERE r.tenant_id = $1
|
|
51746
|
+
WHERE r.tenant_id = $1
|
|
51747
|
+
AND r.authority = 'todos'
|
|
51748
|
+
AND r.route = 'todos.task-manifest.v1'
|
|
51749
|
+
AND r.schema_version = 1
|
|
51750
|
+
AND r.kind = 'apply'
|
|
51751
|
+
AND o.apply_receipt_id = $2
|
|
51752
|
+
AND o.status = 'delivered'
|
|
51652
51753
|
LIMIT 1`, [this.tenantId, input.receipt_id]);
|
|
51653
51754
|
if (delivered.rows[0])
|
|
51654
51755
|
throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: delivered outbox row exists");
|
|
@@ -51661,15 +51762,20 @@ class PostgresTodosTaskManifestBackend {
|
|
|
51661
51762
|
},
|
|
51662
51763
|
...(manifest.effects ?? []).map((effect2) => ({ topic: effect2.topic, payload: effect2.payload }))
|
|
51663
51764
|
];
|
|
51664
|
-
const outboxRows = await tx.query(`SELECT id, topic, payload, payload_digest, status, attempts, delivered_at
|
|
51665
|
-
FROM todos_task_manifest_outbox
|
|
51666
|
-
WHERE apply_receipt_id = $1
|
|
51765
|
+
const outboxRows = await tx.query(`SELECT o.id, o.topic, o.payload, o.payload_digest, o.status, o.attempts, o.delivered_at
|
|
51766
|
+
FROM todos_task_manifest_outbox o
|
|
51767
|
+
WHERE o.apply_receipt_id = $1
|
|
51667
51768
|
AND EXISTS (
|
|
51668
51769
|
SELECT 1 FROM todos_task_manifest_receipts r
|
|
51669
|
-
WHERE r.receipt_id =
|
|
51770
|
+
WHERE r.receipt_id = o.apply_receipt_id
|
|
51670
51771
|
AND r.tenant_id = $2
|
|
51772
|
+
AND r.authority = 'todos'
|
|
51773
|
+
AND r.route = 'todos.task-manifest.v1'
|
|
51774
|
+
AND r.schema_version = 1
|
|
51775
|
+
AND r.kind = 'apply'
|
|
51671
51776
|
)
|
|
51672
|
-
ORDER BY id
|
|
51777
|
+
ORDER BY o.id
|
|
51778
|
+
FOR UPDATE OF o`, [input.receipt_id, this.tenantId]);
|
|
51673
51779
|
if (outboxRows.rows.length !== expectedEffects.length) {
|
|
51674
51780
|
throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: outbox changed since apply");
|
|
51675
51781
|
}
|
|
@@ -51769,14 +51875,23 @@ class PostgresTodosTaskManifestBackend {
|
|
|
51769
51875
|
}
|
|
51770
51876
|
if (stored.rows.length !== managedIds.length)
|
|
51771
51877
|
throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: managed graph is incomplete");
|
|
51772
|
-
await tx.query(`UPDATE todos_task_manifest_outbox
|
|
51878
|
+
const cancelled = await tx.query(`UPDATE todos_task_manifest_outbox
|
|
51773
51879
|
SET status = 'cancelled'
|
|
51774
51880
|
WHERE apply_receipt_id = $1 AND status = 'pending'
|
|
51775
51881
|
AND EXISTS (
|
|
51776
51882
|
SELECT 1 FROM todos_task_manifest_receipts r
|
|
51777
51883
|
WHERE r.receipt_id = todos_task_manifest_outbox.apply_receipt_id
|
|
51778
51884
|
AND r.tenant_id = $2
|
|
51779
|
-
|
|
51885
|
+
AND r.authority = 'todos'
|
|
51886
|
+
AND r.route = 'todos.task-manifest.v1'
|
|
51887
|
+
AND r.schema_version = 1
|
|
51888
|
+
AND r.kind = 'apply'
|
|
51889
|
+
)
|
|
51890
|
+
RETURNING id`, [input.receipt_id, this.tenantId]);
|
|
51891
|
+
const cancelledIds = new Set(cancelled.rows.map((row) => String(row.id)));
|
|
51892
|
+
if (cancelledIds.size !== applyResult.outbox_ids.length || applyResult.outbox_ids.some((id) => !cancelledIds.has(id))) {
|
|
51893
|
+
throw new TodosTaskManifestError("TODOS_TASK_MANIFEST_COMPENSATION_REFUSED", "Compensation refused: failed to cancel every expected outbox row");
|
|
51894
|
+
}
|
|
51780
51895
|
const typedIds = [
|
|
51781
51896
|
["dependencies", applyResult.graph.dependency_ids],
|
|
51782
51897
|
["comments", applyResult.graph.comment_ids],
|
|
@@ -51959,6 +52074,7 @@ class PackageOwnedTodosTaskManifestAuthority {
|
|
|
51959
52074
|
deterministic_ids: true,
|
|
51960
52075
|
immutable_receipts: true,
|
|
51961
52076
|
transactional_outbox: true,
|
|
52077
|
+
idempotent_outbox_delivery: true,
|
|
51962
52078
|
exact_bounded_readback: true,
|
|
51963
52079
|
conditional_compensation: true,
|
|
51964
52080
|
transcript_safe: false,
|
|
@@ -53715,8 +53831,8 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
53715
53831
|
properties: {
|
|
53716
53832
|
title: { type: "string" },
|
|
53717
53833
|
description: { type: "string", nullable: true },
|
|
53718
|
-
status: { type: "string" },
|
|
53719
|
-
priority: { type: "string" },
|
|
53834
|
+
status: { type: "string", enum: [...TASK_STATUSES] },
|
|
53835
|
+
priority: { type: "string", enum: [...TASK_PRIORITIES] },
|
|
53720
53836
|
project_id: { type: "string" },
|
|
53721
53837
|
parent_id: { type: "string" },
|
|
53722
53838
|
plan_id: { type: "string" },
|
|
@@ -53730,8 +53846,8 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
53730
53846
|
properties: {
|
|
53731
53847
|
title: { type: "string" },
|
|
53732
53848
|
description: { type: "string" },
|
|
53733
|
-
status: { type: "string" },
|
|
53734
|
-
priority: { type: "string" },
|
|
53849
|
+
status: { type: "string", enum: [...TASK_STATUSES] },
|
|
53850
|
+
priority: { type: "string", enum: [...TASK_PRIORITIES] },
|
|
53735
53851
|
assigned_to: { type: "string" },
|
|
53736
53852
|
project_id: { type: "string", nullable: true },
|
|
53737
53853
|
plan_id: { type: "string", nullable: true },
|
|
@@ -53752,6 +53868,24 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
53752
53868
|
confidence: { type: "number", minimum: 0, maximum: 1 }
|
|
53753
53869
|
}
|
|
53754
53870
|
},
|
|
53871
|
+
FailTaskInput: {
|
|
53872
|
+
type: "object",
|
|
53873
|
+
additionalProperties: false,
|
|
53874
|
+
properties: {
|
|
53875
|
+
agent_id: { type: "string", minLength: 1 },
|
|
53876
|
+
reason: { type: "string" },
|
|
53877
|
+
retry: { type: "boolean" }
|
|
53878
|
+
}
|
|
53879
|
+
},
|
|
53880
|
+
TaskFailureResult: {
|
|
53881
|
+
type: "object",
|
|
53882
|
+
additionalProperties: false,
|
|
53883
|
+
required: ["task"],
|
|
53884
|
+
properties: {
|
|
53885
|
+
task: { $ref: "#/components/schemas/Task" },
|
|
53886
|
+
retryTask: { $ref: "#/components/schemas/Task" }
|
|
53887
|
+
}
|
|
53888
|
+
},
|
|
53755
53889
|
CreateProjectInput: {
|
|
53756
53890
|
type: "object",
|
|
53757
53891
|
additionalProperties: false,
|
|
@@ -54995,6 +55129,30 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
54995
55129
|
responses: { "200": { content: { "application/json": { schema: { type: "object", properties: { task: { $ref: "#/components/schemas/Task" } } } } } } }
|
|
54996
55130
|
}
|
|
54997
55131
|
},
|
|
55132
|
+
"/v1/tasks/{id}/fail": {
|
|
55133
|
+
post: {
|
|
55134
|
+
operationId: "failTask",
|
|
55135
|
+
summary: "Fail a task with an optional reason and retry copy",
|
|
55136
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" } }],
|
|
55137
|
+
requestBody: {
|
|
55138
|
+
required: false,
|
|
55139
|
+
content: { "application/json": { schema: { $ref: "#/components/schemas/FailTaskInput" } } }
|
|
55140
|
+
},
|
|
55141
|
+
responses: {
|
|
55142
|
+
"200": {
|
|
55143
|
+
content: {
|
|
55144
|
+
"application/json": {
|
|
55145
|
+
schema: {
|
|
55146
|
+
type: "object",
|
|
55147
|
+
required: ["result"],
|
|
55148
|
+
properties: { result: { $ref: "#/components/schemas/TaskFailureResult" } }
|
|
55149
|
+
}
|
|
55150
|
+
}
|
|
55151
|
+
}
|
|
55152
|
+
}
|
|
55153
|
+
}
|
|
55154
|
+
}
|
|
55155
|
+
},
|
|
54998
55156
|
"/v1/projects": {
|
|
54999
55157
|
get: {
|
|
55000
55158
|
operationId: "listProjects",
|
|
@@ -55436,12 +55594,13 @@ var init_openapi = __esm(() => {
|
|
|
55436
55594
|
id: { type: "string" },
|
|
55437
55595
|
title: { type: "string" },
|
|
55438
55596
|
description: { type: "string" },
|
|
55439
|
-
status: { type: "string" },
|
|
55440
|
-
priority: { type: "string" },
|
|
55597
|
+
status: { type: "string", enum: [...TASK_STATUSES] },
|
|
55598
|
+
priority: { type: "string", enum: [...TASK_PRIORITIES] },
|
|
55441
55599
|
project_id: { type: "string", nullable: true },
|
|
55442
55600
|
parent_id: { type: "string", nullable: true },
|
|
55443
55601
|
assigned_to: { type: "string", nullable: true },
|
|
55444
55602
|
agent_id: { type: "string", nullable: true },
|
|
55603
|
+
reason: { type: "string", nullable: true },
|
|
55445
55604
|
tags: { type: "array", items: { type: "string" } },
|
|
55446
55605
|
version: { type: "number" },
|
|
55447
55606
|
created_at: { type: "string" },
|
|
@@ -56321,6 +56480,44 @@ function validateTaskCompletion(value) {
|
|
|
56321
56480
|
}
|
|
56322
56481
|
};
|
|
56323
56482
|
}
|
|
56483
|
+
function validateTaskFailure(value) {
|
|
56484
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
56485
|
+
return { ok: false, message: "failure body must be an object" };
|
|
56486
|
+
const body2 = value;
|
|
56487
|
+
const allowed = new Set(["agent_id", "reason", "retry"]);
|
|
56488
|
+
const unknown = Object.keys(body2).find((key2) => !allowed.has(key2));
|
|
56489
|
+
if (unknown)
|
|
56490
|
+
return { ok: false, message: `unknown failure field: ${unknown}` };
|
|
56491
|
+
if (body2.agent_id !== undefined && (typeof body2.agent_id !== "string" || !body2.agent_id.trim())) {
|
|
56492
|
+
return { ok: false, message: "agent_id must be a non-empty string" };
|
|
56493
|
+
}
|
|
56494
|
+
if (body2.reason !== undefined && typeof body2.reason !== "string")
|
|
56495
|
+
return { ok: false, message: "reason must be a string" };
|
|
56496
|
+
if (body2.retry !== undefined && typeof body2.retry !== "boolean")
|
|
56497
|
+
return { ok: false, message: "retry must be a boolean" };
|
|
56498
|
+
return {
|
|
56499
|
+
ok: true,
|
|
56500
|
+
...typeof body2.agent_id === "string" ? { agentId: body2.agent_id } : {},
|
|
56501
|
+
reason: typeof body2.reason === "string" && body2.reason ? body2.reason : "Unknown failure",
|
|
56502
|
+
retry: body2.retry === true
|
|
56503
|
+
};
|
|
56504
|
+
}
|
|
56505
|
+
function validateTaskPatchVocabulary(value) {
|
|
56506
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
56507
|
+
return { ok: false, message: "task patch must be an object" };
|
|
56508
|
+
const body2 = value;
|
|
56509
|
+
for (const [name, vocabulary] of [["status", TASK_STATUSES], ["priority", TASK_PRIORITIES]]) {
|
|
56510
|
+
const raw = body2[name];
|
|
56511
|
+
if (raw === undefined)
|
|
56512
|
+
continue;
|
|
56513
|
+
if (typeof raw !== "string")
|
|
56514
|
+
return { ok: false, message: `${name} must be a string. Allowed values: ${vocabulary.join(", ")}.` };
|
|
56515
|
+
const parsed = resolveEnumVocabulary(raw, { name, vocabulary, allowList: false });
|
|
56516
|
+
if (!parsed.ok)
|
|
56517
|
+
return { ok: false, message: parsed.message };
|
|
56518
|
+
}
|
|
56519
|
+
return { ok: true, patch: body2 };
|
|
56520
|
+
}
|
|
56324
56521
|
function validateProjectPatch(value) {
|
|
56325
56522
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
56326
56523
|
return { ok: false, message: "project patch must be an object" };
|
|
@@ -57001,7 +57198,12 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
57001
57198
|
});
|
|
57002
57199
|
}
|
|
57003
57200
|
if (action === "fail" && method === "POST") {
|
|
57004
|
-
|
|
57201
|
+
const parsed = validateTaskFailure(actionJson.value);
|
|
57202
|
+
if (!parsed.ok)
|
|
57203
|
+
return error(400, parsed.message);
|
|
57204
|
+
return json5({
|
|
57205
|
+
result: await store.tasks.fail(id, parsed.agentId || principal.agent || "todos-serve", parsed.reason, { retry: parsed.retry }, contextFromPrincipal(principal, body2))
|
|
57206
|
+
});
|
|
57005
57207
|
}
|
|
57006
57208
|
if (action === "claim" && method === "POST") {
|
|
57007
57209
|
return json5({ task: await store.tasks.claimNext(agentId, {}) });
|
|
@@ -57030,9 +57232,13 @@ async function handleV1Request(req, url, dependencies = {}) {
|
|
|
57030
57232
|
return task3 ? json5({ task: task3 }) : error(404, "task not found");
|
|
57031
57233
|
}
|
|
57032
57234
|
if (method === "PATCH" || method === "PUT") {
|
|
57033
|
-
const
|
|
57034
|
-
if (!
|
|
57235
|
+
const rawBody = await readJson3(req);
|
|
57236
|
+
if (!rawBody)
|
|
57035
57237
|
return error(400, "invalid JSON body");
|
|
57238
|
+
const validated = validateTaskPatchVocabulary(rawBody);
|
|
57239
|
+
if (!validated.ok)
|
|
57240
|
+
return error(400, validated.message);
|
|
57241
|
+
const body2 = validated.patch;
|
|
57036
57242
|
const current = await store.tasks.get(id);
|
|
57037
57243
|
if (!current)
|
|
57038
57244
|
return error(404, "task not found");
|
package/dist/mcp.js
CHANGED
|
@@ -41,7 +41,7 @@ var __require = import.meta.require;
|
|
|
41
41
|
// package.json
|
|
42
42
|
var package_default = {
|
|
43
43
|
name: "@hasna/todos",
|
|
44
|
-
version: "0.15.
|
|
44
|
+
version: "0.15.17",
|
|
45
45
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
46
46
|
type: "module",
|
|
47
47
|
main: "dist/index.js",
|
|
@@ -8949,8 +8949,8 @@ function failTask2(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 failTask2(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
|
|
@@ -12382,7 +12383,7 @@ import { createHash as createHash5 } from "crypto";
|
|
|
12382
12383
|
// package.json
|
|
12383
12384
|
var package_default = {
|
|
12384
12385
|
name: "@hasna/todos",
|
|
12385
|
-
version: "0.15.
|
|
12386
|
+
version: "0.15.17",
|
|
12386
12387
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12387
12388
|
type: "module",
|
|
12388
12389
|
main: "dist/index.js",
|
package/dist/registry.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
|
|
@@ -12379,7 +12380,7 @@ var init_tasks = __esm(() => {
|
|
|
12379
12380
|
// package.json
|
|
12380
12381
|
var package_default = {
|
|
12381
12382
|
name: "@hasna/todos",
|
|
12382
|
-
version: "0.15.
|
|
12383
|
+
version: "0.15.17",
|
|
12383
12384
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12384
12385
|
type: "module",
|
|
12385
12386
|
main: "dist/index.js",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "@hasna/todos",
|
|
3
|
-
"packageVersion": "0.15.
|
|
3
|
+
"packageVersion": "0.15.17",
|
|
4
4
|
"repository": "https://github.com/hasna/todos.git",
|
|
5
|
-
"gitCommit": "
|
|
6
|
-
"gitTree": "
|
|
7
|
-
"sourceTreeSha256": "
|
|
8
|
-
"generatedAt": "2026-08-
|
|
5
|
+
"gitCommit": "f5ad4d8f466d76f7b213b4285cb7eb8be1d65057",
|
|
6
|
+
"gitTree": "5a91a08de2e8af7d18d37de3dfa5956b141a62ac",
|
|
7
|
+
"sourceTreeSha256": "798227cadfbde7ad824600dd06968ca9b7c01f4f8a967f9f6e149b75de6dae93",
|
|
8
|
+
"generatedAt": "2026-08-09T03:22:03.000Z"
|
|
9
9
|
}
|
package/dist/sdk/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
export { TodosClient, createClient } from "./client.js";
|
|
11
11
|
export type { TodosClientOptions } from "./client.js";
|
|
12
12
|
export { TodosV1Client, ApiError as TodosV1ApiError } from "./v1.generated.js";
|
|
13
|
-
export type { TodosV1ClientOptions, Task as TodosV1Task, Project as TodosV1Project, TaskManifestBindingLookupRequest as TodosV1TaskManifestBindingLookupRequest, TaskManifestBindingLookupResult as TodosV1TaskManifestBindingLookupResult, TaskManifestBindingLookupResponse as TodosV1TaskManifestBindingLookupResponse, TaskComment as TodosV1TaskComment, CreateTaskInput as TodosV1CreateTaskInput, UpdateTaskInput as TodosV1UpdateTaskInput, CreateProjectInput as TodosV1CreateProjectInput, ProjectTaskListEnsureApplyInput as TodosV1ProjectTaskListEnsureApplyInput, ProjectTaskListRollbackInput as TodosV1ProjectTaskListRollbackInput, ProjectTaskListEnsureReceipt as TodosV1ProjectTaskListEnsureReceipt, ProjectTaskListEnsureResult as TodosV1ProjectTaskListEnsureResult, ProjectTaskListRollbackResult as TodosV1ProjectTaskListRollbackResult, CreateTaskCommentInput as TodosV1CreateTaskCommentInput, AdmitPrGroupInput as TodosV1AdmitPrGroupInput, RecoverPrGroupInput as TodosV1RecoverPrGroupInput, AppendPrGroupEventInput as TodosV1AppendPrGroupEventInput, PrGroupCiProof as TodosV1PrGroupCiProof, PrGroupCleanupProof as TodosV1PrGroupCleanupProof, PrGroupRecord as TodosV1PrGroupRecord, PrGroupAttemptRecord as TodosV1PrGroupAttemptRecord, PrGroupEventRecord as TodosV1PrGroupEventRecord, PrGroupStateView as TodosV1PrGroupStateView, PrGroupEventPage as TodosV1PrGroupEventPage, PrGroupMutationResult as TodosV1PrGroupMutationResult, } from "./v1.generated.js";
|
|
13
|
+
export type { TodosV1ClientOptions, Task as TodosV1Task, Project as TodosV1Project, TaskManifestBindingLookupRequest as TodosV1TaskManifestBindingLookupRequest, TaskManifestBindingLookupResult as TodosV1TaskManifestBindingLookupResult, TaskManifestBindingLookupResponse as TodosV1TaskManifestBindingLookupResponse, TaskComment as TodosV1TaskComment, CreateTaskInput as TodosV1CreateTaskInput, UpdateTaskInput as TodosV1UpdateTaskInput, FailTaskInput as TodosV1FailTaskInput, TaskFailureResult as TodosV1TaskFailureResult, CreateProjectInput as TodosV1CreateProjectInput, ProjectTaskListEnsureApplyInput as TodosV1ProjectTaskListEnsureApplyInput, ProjectTaskListRollbackInput as TodosV1ProjectTaskListRollbackInput, ProjectTaskListEnsureReceipt as TodosV1ProjectTaskListEnsureReceipt, ProjectTaskListEnsureResult as TodosV1ProjectTaskListEnsureResult, ProjectTaskListRollbackResult as TodosV1ProjectTaskListRollbackResult, CreateTaskCommentInput as TodosV1CreateTaskCommentInput, AdmitPrGroupInput as TodosV1AdmitPrGroupInput, RecoverPrGroupInput as TodosV1RecoverPrGroupInput, AppendPrGroupEventInput as TodosV1AppendPrGroupEventInput, PrGroupCiProof as TodosV1PrGroupCiProof, PrGroupCleanupProof as TodosV1PrGroupCleanupProof, PrGroupRecord as TodosV1PrGroupRecord, PrGroupAttemptRecord as TodosV1PrGroupAttemptRecord, PrGroupEventRecord as TodosV1PrGroupEventRecord, PrGroupStateView as TodosV1PrGroupStateView, PrGroupEventPage as TodosV1PrGroupEventPage, PrGroupMutationResult as TodosV1PrGroupMutationResult, } from "./v1.generated.js";
|
|
14
14
|
export type { AdmitPrGroupInput, AppendPrGroupEventInput, PrGroupAdapterViews, PrGroupAttemptRecord, PrGroupCiProof, PrGroupCleanupProof, PrGroupDecisionEnvelopeAdapter, PrGroupEventListOptions, PrGroupEventPage, PrGroupEventRecord, PrGroupEvidenceRefAdapter, PrGroupMutationResult, PrGroupProofBundleAdapter, PrGroupRecord, PrGroupStateView, PrGroupWorkRunAdapter, RecoverPrGroupInput, } from "../pr-groups/types.js";
|
|
15
15
|
export { TodosAPIError, TodosNotFoundError, TodosConflictError, TodosUnauthorizedError, TodosRateLimitError, TodosTimeoutError, } from "./types.js";
|
|
16
16
|
export type { SSEEvent, CursorPage, ListOptions, TaskListResponse, TaskStatusResponse, TaskNextResponse, TaskActiveResponse, TaskStaleResponse, TaskChangedResponse, TaskContextResponse, TaskProgressResponse, TaskAttachmentsResponse, TaskFailResponse, TaskBulkResponse, AgentMeResponse, AgentQueueResponse, OrgNode, PlanWithTasks, ReportResponse, DoctorResponse, DoctorIssue, } from "./types.js";
|
package/dist/sdk/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItD,OAAO,EAAE,aAAa,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/E,YAAY,EACV,oBAAoB,EACpB,IAAI,IAAI,WAAW,EACnB,OAAO,IAAI,cAAc,EACzB,gCAAgC,IAAI,uCAAuC,EAC3E,+BAA+B,IAAI,sCAAsC,EACzE,iCAAiC,IAAI,wCAAwC,EAC7E,WAAW,IAAI,kBAAkB,EACjC,eAAe,IAAI,sBAAsB,EACzC,eAAe,IAAI,sBAAsB,EACzC,kBAAkB,IAAI,yBAAyB,EAC/C,+BAA+B,IAAI,sCAAsC,EACzE,4BAA4B,IAAI,mCAAmC,EACnE,4BAA4B,IAAI,mCAAmC,EACnE,2BAA2B,IAAI,kCAAkC,EACjE,6BAA6B,IAAI,oCAAoC,EACrE,sBAAsB,IAAI,6BAA6B,EACvD,iBAAiB,IAAI,wBAAwB,EAC7C,mBAAmB,IAAI,0BAA0B,EACjD,uBAAuB,IAAI,8BAA8B,EACzD,cAAc,IAAI,qBAAqB,EACvC,mBAAmB,IAAI,0BAA0B,EACjD,aAAa,IAAI,oBAAoB,EACrC,oBAAoB,IAAI,2BAA2B,EACnD,kBAAkB,IAAI,yBAAyB,EAC/C,gBAAgB,IAAI,uBAAuB,EAC3C,gBAAgB,IAAI,uBAAuB,EAC3C,qBAAqB,IAAI,4BAA4B,GACtD,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,8BAA8B,EAC9B,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,cAAc,EACd,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sdk/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAItD,OAAO,EAAE,aAAa,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC/E,YAAY,EACV,oBAAoB,EACpB,IAAI,IAAI,WAAW,EACnB,OAAO,IAAI,cAAc,EACzB,gCAAgC,IAAI,uCAAuC,EAC3E,+BAA+B,IAAI,sCAAsC,EACzE,iCAAiC,IAAI,wCAAwC,EAC7E,WAAW,IAAI,kBAAkB,EACjC,eAAe,IAAI,sBAAsB,EACzC,eAAe,IAAI,sBAAsB,EACzC,aAAa,IAAI,oBAAoB,EACrC,iBAAiB,IAAI,wBAAwB,EAC7C,kBAAkB,IAAI,yBAAyB,EAC/C,+BAA+B,IAAI,sCAAsC,EACzE,4BAA4B,IAAI,mCAAmC,EACnE,4BAA4B,IAAI,mCAAmC,EACnE,2BAA2B,IAAI,kCAAkC,EACjE,6BAA6B,IAAI,oCAAoC,EACrE,sBAAsB,IAAI,6BAA6B,EACvD,iBAAiB,IAAI,wBAAwB,EAC7C,mBAAmB,IAAI,0BAA0B,EACjD,uBAAuB,IAAI,8BAA8B,EACzD,cAAc,IAAI,qBAAqB,EACvC,mBAAmB,IAAI,0BAA0B,EACjD,aAAa,IAAI,oBAAoB,EACrC,oBAAoB,IAAI,2BAA2B,EACnD,kBAAkB,IAAI,yBAAyB,EAC/C,gBAAgB,IAAI,uBAAuB,EAC3C,gBAAgB,IAAI,uBAAuB,EAC3C,qBAAqB,IAAI,4BAA4B,GACtD,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,iBAAiB,EACjB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,8BAA8B,EAC9B,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,qBAAqB,EACrB,yBAAyB,EACzB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,QAAQ,EACR,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,OAAO,EACP,aAAa,EACb,cAAc,EACd,cAAc,EACd,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
package/dist/sdk/index.js
CHANGED
|
@@ -980,6 +980,13 @@ class TodosV1Client {
|
|
|
980
980
|
init
|
|
981
981
|
});
|
|
982
982
|
}
|
|
983
|
+
async failTask(id, body, init) {
|
|
984
|
+
return this.request("POST", `/v1/tasks/${encodeURIComponent(String(id))}/fail`, {
|
|
985
|
+
body,
|
|
986
|
+
query: undefined,
|
|
987
|
+
init
|
|
988
|
+
});
|
|
989
|
+
}
|
|
983
990
|
async listTaskGitRefs(id, init) {
|
|
984
991
|
return this.request("GET", `/v1/tasks/${encodeURIComponent(String(id))}/refs`, {
|
|
985
992
|
body: undefined,
|
|
@@ -2,12 +2,13 @@ export interface Task {
|
|
|
2
2
|
"id"?: string;
|
|
3
3
|
"title"?: string;
|
|
4
4
|
"description"?: string;
|
|
5
|
-
"status"?:
|
|
6
|
-
"priority"?:
|
|
5
|
+
"status"?: "pending" | "in_progress" | "completed" | "failed" | "cancelled";
|
|
6
|
+
"priority"?: "low" | "medium" | "high" | "critical";
|
|
7
7
|
"project_id"?: string | null;
|
|
8
8
|
"parent_id"?: string | null;
|
|
9
9
|
"assigned_to"?: string | null;
|
|
10
10
|
"agent_id"?: string | null;
|
|
11
|
+
"reason"?: string | null;
|
|
11
12
|
"tags"?: Array<string>;
|
|
12
13
|
"version"?: number;
|
|
13
14
|
"created_at"?: string;
|
|
@@ -206,8 +207,8 @@ export interface CreateTemplateTaskInput {
|
|
|
206
207
|
export interface CreateTaskInput {
|
|
207
208
|
"title": string;
|
|
208
209
|
"description"?: string | null;
|
|
209
|
-
"status"?:
|
|
210
|
-
"priority"?:
|
|
210
|
+
"status"?: "pending" | "in_progress" | "completed" | "failed" | "cancelled";
|
|
211
|
+
"priority"?: "low" | "medium" | "high" | "critical";
|
|
211
212
|
"project_id"?: string;
|
|
212
213
|
"parent_id"?: string;
|
|
213
214
|
"plan_id"?: string;
|
|
@@ -218,8 +219,8 @@ export interface CreateTaskInput {
|
|
|
218
219
|
export interface UpdateTaskInput {
|
|
219
220
|
"title"?: string;
|
|
220
221
|
"description"?: string;
|
|
221
|
-
"status"?:
|
|
222
|
-
"priority"?:
|
|
222
|
+
"status"?: "pending" | "in_progress" | "completed" | "failed" | "cancelled";
|
|
223
|
+
"priority"?: "low" | "medium" | "high" | "critical";
|
|
223
224
|
"assigned_to"?: string;
|
|
224
225
|
"project_id"?: string | null;
|
|
225
226
|
"plan_id"?: string | null;
|
|
@@ -235,6 +236,15 @@ export interface CompleteTaskInput {
|
|
|
235
236
|
"notes"?: string;
|
|
236
237
|
"confidence"?: number;
|
|
237
238
|
}
|
|
239
|
+
export interface FailTaskInput {
|
|
240
|
+
"agent_id"?: string;
|
|
241
|
+
"reason"?: string;
|
|
242
|
+
"retry"?: boolean;
|
|
243
|
+
}
|
|
244
|
+
export interface TaskFailureResult {
|
|
245
|
+
"task": Task;
|
|
246
|
+
"retryTask"?: Task;
|
|
247
|
+
}
|
|
238
248
|
export interface CreateProjectInput {
|
|
239
249
|
"name": string;
|
|
240
250
|
"path": string;
|
|
@@ -822,6 +832,10 @@ export declare class TodosV1Client {
|
|
|
822
832
|
completeTask(id: string, body?: CompleteTaskInput, init?: RequestInit): Promise<{
|
|
823
833
|
"task"?: Task;
|
|
824
834
|
}>;
|
|
835
|
+
/** Fail a task with an optional reason and retry copy */
|
|
836
|
+
failTask(id: string, body?: FailTaskInput, init?: RequestInit): Promise<{
|
|
837
|
+
"result": TaskFailureResult;
|
|
838
|
+
}>;
|
|
825
839
|
/** List git branch and pull-request refs linked to a task */
|
|
826
840
|
listTaskGitRefs(id: string, init?: RequestInit): Promise<{
|
|
827
841
|
"refs": Array<TaskGitRef>;
|