@hasna/todos 0.15.41 → 0.15.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/cloud-router.d.ts.map +1 -1
- package/dist/cli/index.js +139 -39
- package/dist/contracts.js +6 -6
- package/dist/db/task-graph.d.ts.map +1 -1
- package/dist/db/task-lifecycle.d.ts.map +1 -1
- package/dist/index.js +118 -33
- package/dist/lib/instant-compare.d.ts +35 -0
- package/dist/lib/instant-compare.d.ts.map +1 -0
- package/dist/mcp/index.js +138 -38
- package/dist/mcp.js +2 -2
- package/dist/pr-groups/postgres.d.ts.map +1 -1
- package/dist/project-registration/postgres.d.ts.map +1 -1
- package/dist/project-registration.js +85 -20
- package/dist/registry.js +6 -6
- package/dist/release-provenance.json +5 -5
- package/dist/server/cloud.d.ts.map +1 -1
- package/dist/server/index.js +142 -42
- package/dist/storage/local-sqlite.d.ts.map +1 -1
- package/dist/storage/postgres-adapter.d.ts.map +1 -1
- package/dist/storage.js +69 -11
- package/dist/task-manifest/postgres.d.ts.map +1 -1
- package/dist/task-manifest.js +15 -6
- package/dist/task-subtree-transfer/postgres.d.ts.map +1 -1
- package/dist/task-subtree-transfer.js +15 -6
- package/package.json +2 -2
package/dist/storage.js
CHANGED
|
@@ -8651,7 +8651,7 @@ function getTaskGraph(taskId, direction = "both", db) {
|
|
|
8651
8651
|
const deps = getTaskDependencies(t.id, d);
|
|
8652
8652
|
const hasUnfinishedDeps = deps.some((dep) => {
|
|
8653
8653
|
const depTask = getTask(dep.depends_on, d);
|
|
8654
|
-
return depTask && depTask.status
|
|
8654
|
+
return depTask && isBlockingDependencyStatus(depTask.status);
|
|
8655
8655
|
});
|
|
8656
8656
|
return { id: t.id, short_id: t.short_id, title: t.title, status: t.status, priority: t.priority, is_blocked: hasUnfinishedDeps };
|
|
8657
8657
|
}
|
|
@@ -8911,7 +8911,7 @@ function getBlockingDeps(id, db) {
|
|
|
8911
8911
|
const blocking = [];
|
|
8912
8912
|
for (const dep of deps) {
|
|
8913
8913
|
const task = getTask(dep.depends_on, d);
|
|
8914
|
-
if (task && task.status
|
|
8914
|
+
if (task && isBlockingDependencyStatus(task.status))
|
|
8915
8915
|
blocking.push(task);
|
|
8916
8916
|
}
|
|
8917
8917
|
return blocking;
|
|
@@ -9235,7 +9235,7 @@ function getNextTask(agentId, filters, db) {
|
|
|
9235
9235
|
conditions.push(`id IN (SELECT task_id FROM task_tags WHERE tag IN (${placeholders}))`);
|
|
9236
9236
|
params.push(...filters.tags);
|
|
9237
9237
|
}
|
|
9238
|
-
conditions.push("id NOT IN (SELECT td.task_id FROM task_dependencies td JOIN tasks dep ON dep.id = td.depends_on WHERE dep.status
|
|
9238
|
+
conditions.push("id NOT IN (SELECT td.task_id FROM task_dependencies td JOIN tasks dep ON dep.id = td.depends_on WHERE dep.status NOT IN ('completed', 'cancelled'))");
|
|
9239
9239
|
const where = conditions.join(" AND ");
|
|
9240
9240
|
let recentProjectIds = [];
|
|
9241
9241
|
const assignedAliasParams = [];
|
|
@@ -9279,7 +9279,7 @@ function getActiveWork(filters, db) {
|
|
|
9279
9279
|
}
|
|
9280
9280
|
function getTasksChangedSince(since, filters, db) {
|
|
9281
9281
|
const d = db || getDatabase();
|
|
9282
|
-
const conditions = ["updated_at > ?"];
|
|
9282
|
+
const conditions = ["(julianday(updated_at) IS NULL OR julianday(updated_at) > julianday(?))"];
|
|
9283
9283
|
const params = [since];
|
|
9284
9284
|
if (filters?.project_id) {
|
|
9285
9285
|
conditions.push("project_id = ?");
|
|
@@ -14696,7 +14696,7 @@ function matchesExtraFilters(task, filter) {
|
|
|
14696
14696
|
}
|
|
14697
14697
|
if (filter.tags?.length) {
|
|
14698
14698
|
const taskTags = new Set(task.tags ?? []);
|
|
14699
|
-
if (!filter.tags.
|
|
14699
|
+
if (!filter.tags.some((tag) => taskTags.has(tag)))
|
|
14700
14700
|
return false;
|
|
14701
14701
|
}
|
|
14702
14702
|
if (filter.include_subtasks !== true && filter.parent_id === undefined && task.parent_id)
|
|
@@ -14860,6 +14860,59 @@ function createLocalSqliteTodosStorageAdapter(options = {}) {
|
|
|
14860
14860
|
init_types();
|
|
14861
14861
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
14862
14862
|
init_creator_identity();
|
|
14863
|
+
|
|
14864
|
+
// src/lib/instant-compare.ts
|
|
14865
|
+
var SQLITE_STAMP = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?(?:Z|([+-])(\d{2}):(\d{2}))?)?$/;
|
|
14866
|
+
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
14867
|
+
function isLeapYear(year) {
|
|
14868
|
+
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
14869
|
+
}
|
|
14870
|
+
function sqliteJulianDay(value) {
|
|
14871
|
+
const m = SQLITE_STAMP.exec(value);
|
|
14872
|
+
if (!m)
|
|
14873
|
+
return null;
|
|
14874
|
+
const year = Number(m[1]);
|
|
14875
|
+
const month = Number(m[2]);
|
|
14876
|
+
const day = Number(m[3]);
|
|
14877
|
+
const hour = m[4] === undefined ? 0 : Number(m[4]);
|
|
14878
|
+
const minute = m[5] === undefined ? 0 : Number(m[5]);
|
|
14879
|
+
const second = m[6] === undefined ? 0 : Number(m[6]);
|
|
14880
|
+
const frac = m[7];
|
|
14881
|
+
const sign = m[8];
|
|
14882
|
+
const offsetHour = m[9];
|
|
14883
|
+
const offsetMinute = m[10];
|
|
14884
|
+
if (month < 1 || month > 12)
|
|
14885
|
+
return null;
|
|
14886
|
+
if (hour > 23 || minute > 59 || second > 59)
|
|
14887
|
+
return null;
|
|
14888
|
+
const maxDay = (DAYS_IN_MONTH[month - 1] ?? 0) + (month === 2 && isLeapYear(year) ? 1 : 0);
|
|
14889
|
+
if (day < 1 || day > maxDay)
|
|
14890
|
+
return null;
|
|
14891
|
+
let offsetMinutes = 0;
|
|
14892
|
+
if (sign !== undefined) {
|
|
14893
|
+
const oh = Number(offsetHour ?? "0");
|
|
14894
|
+
const om = Number(offsetMinute ?? "0");
|
|
14895
|
+
if (oh > 23 || om > 59)
|
|
14896
|
+
return null;
|
|
14897
|
+
offsetMinutes = oh * 60 + om;
|
|
14898
|
+
if (sign === "-")
|
|
14899
|
+
offsetMinutes = -offsetMinutes;
|
|
14900
|
+
}
|
|
14901
|
+
const micros = frac === undefined ? 0 : Number((frac + "000000").slice(0, 6));
|
|
14902
|
+
const ms = Date.UTC(year, month - 1, day, hour, minute, second);
|
|
14903
|
+
return (ms + micros / 1000) / 86400000 + 2440587.5 - offsetMinutes / 1440;
|
|
14904
|
+
}
|
|
14905
|
+
function changedSinceStampNewer(stamp, since) {
|
|
14906
|
+
const stampJd = sqliteJulianDay(stamp);
|
|
14907
|
+
if (stampJd === null)
|
|
14908
|
+
return true;
|
|
14909
|
+
const sinceJd = sqliteJulianDay(since);
|
|
14910
|
+
if (sinceJd === null)
|
|
14911
|
+
return false;
|
|
14912
|
+
return stampJd > sinceJd;
|
|
14913
|
+
}
|
|
14914
|
+
|
|
14915
|
+
// src/storage/postgres-adapter.ts
|
|
14863
14916
|
init_stale_lock_handoff();
|
|
14864
14917
|
|
|
14865
14918
|
// src/storage/postgres-sync.ts
|
|
@@ -15474,11 +15527,16 @@ class PostgresJsonRecordStore {
|
|
|
15474
15527
|
return context?.requestId ?? this.sourceMachineId ?? null;
|
|
15475
15528
|
}
|
|
15476
15529
|
async ensureSchema() {
|
|
15477
|
-
this.schemaReady
|
|
15478
|
-
|
|
15479
|
-
|
|
15480
|
-
|
|
15481
|
-
|
|
15530
|
+
if (!this.schemaReady) {
|
|
15531
|
+
this.schemaReady = (async () => {
|
|
15532
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName, this.cursorTableName)) {
|
|
15533
|
+
await this.options.client.query(sql);
|
|
15534
|
+
}
|
|
15535
|
+
})().catch((error) => {
|
|
15536
|
+
this.schemaReady = null;
|
|
15537
|
+
throw error;
|
|
15538
|
+
});
|
|
15539
|
+
}
|
|
15482
15540
|
await this.schemaReady;
|
|
15483
15541
|
}
|
|
15484
15542
|
async get(type, id) {
|
|
@@ -17243,7 +17301,7 @@ async function getActiveWork2(filters, store) {
|
|
|
17243
17301
|
}));
|
|
17244
17302
|
}
|
|
17245
17303
|
async function getChangedSince(since, filters, store) {
|
|
17246
|
-
return (await listTasks2(filters ?? {}, store)).filter((task) => task.updated_at
|
|
17304
|
+
return (await listTasks2(filters ?? {}, store)).filter((task) => changedSinceStampNewer(task.updated_at ?? "", since));
|
|
17247
17305
|
}
|
|
17248
17306
|
async function createProject2(input, store, context) {
|
|
17249
17307
|
const timestamp2 = new Date().toISOString();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/task-manifest/postgres.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAItB,OAAO,EAEL,KAAK,yCAAyC,EAE9C,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAE9B,MAAM,YAAY,CAAC;AAgKpB,qBAAa,gCAAiC,YAAW,wBAAwB;IAQ7E,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,+BAA+B,EACxD,OAAO,GAAE,yCAA8C;YAO3C,YAAY;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/task-manifest/postgres.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,0BAA0B,EAE/B,KAAK,wBAAwB,EAC9B,MAAM,cAAc,CAAC;AAItB,OAAO,EAEL,KAAK,yCAAyC,EAE9C,KAAK,4BAA4B,EACjC,KAAK,kCAAkC,EACvC,KAAK,mCAAmC,EAExC,KAAK,+BAA+B,EACpC,KAAK,wBAAwB,EAE9B,MAAM,YAAY,CAAC;AAgKpB,qBAAa,gCAAiC,YAAW,wBAAwB;IAQ7E,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,+BAA+B,EACxD,OAAO,GAAE,yCAA8C;YAO3C,YAAY;YAqBZ,UAAU;YAcV,eAAe;IAyCvB,KAAK,CAAC,KAAK,EAAE,sBAAsB,EAAE,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAwJ/G,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,4BAA4B,CAAC;IAenE,qBAAqB,CAAC,MAAM,EAAE,MAAM;IA8BpC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0DzE,UAAU,CACd,KAAK,EAAE,kCAAkC,EACzC,OAAO,EAAE,wBAAwB,EACjC,qBAAqB,EAAE,MAAM,EAC7B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,mCAAmC,CAAC;YAyPjC,QAAQ;CAcvB"}
|
package/dist/task-manifest.js
CHANGED
|
@@ -6613,12 +6613,21 @@ class PostgresTodosTaskManifestBackend {
|
|
|
6613
6613
|
this.tenantId = options.tenantId ?? "default";
|
|
6614
6614
|
}
|
|
6615
6615
|
async ensureSchema() {
|
|
6616
|
-
this.schemaReady
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6616
|
+
if (this.schemaReady === null) {
|
|
6617
|
+
const attempt = (async () => {
|
|
6618
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName))
|
|
6619
|
+
await this.client.query(sql);
|
|
6620
|
+
for (const sql of postgresTodosTaskManifestSchemaSql(this.tenantId))
|
|
6621
|
+
await this.client.query(sql);
|
|
6622
|
+
})();
|
|
6623
|
+
this.schemaReady = attempt;
|
|
6624
|
+
try {
|
|
6625
|
+
await attempt;
|
|
6626
|
+
} catch (error) {
|
|
6627
|
+
this.schemaReady = null;
|
|
6628
|
+
throw error;
|
|
6629
|
+
}
|
|
6630
|
+
}
|
|
6622
6631
|
await this.schemaReady;
|
|
6623
6632
|
}
|
|
6624
6633
|
async insertSync(tx, objectType2, objectId, payload, now) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/task-subtree-transfer/postgres.ts"],"names":[],"mappings":"AAcA,OAAO,EAGL,KAAK,gDAAgD,EACrD,KAAK,oCAAoC,EACzC,KAAK,wCAAwC,EAE7C,KAAK,sCAAsC,EAC3C,KAAK,kCAAkC,EAEvC,KAAK,8BAA8B,EACnC,KAAK,uCAAuC,EAC7C,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AA6CpE,qBAAa,uCAAwC,YAAW,+BAA+B;IAQ3F,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,OAAO,YAAY,EAAE,sCAAsC,EACpF,OAAO,GAAE,gDAAqD;YAOlD,YAAY;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/task-subtree-transfer/postgres.ts"],"names":[],"mappings":"AAcA,OAAO,EAGL,KAAK,gDAAgD,EACrD,KAAK,oCAAoC,EACzC,KAAK,wCAAwC,EAE7C,KAAK,sCAAsC,EAC3C,KAAK,kCAAkC,EAEvC,KAAK,8BAA8B,EACnC,KAAK,uCAAuC,EAC7C,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,+BAA+B,EAAE,MAAM,cAAc,CAAC;AA6CpE,qBAAa,uCAAwC,YAAW,+BAA+B;IAQ3F,OAAO,CAAC,QAAQ,CAAC,MAAM;IAPzB,QAAQ,CAAC,IAAI,EAAG,YAAY,CAAU;IACtC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,OAAO,YAAY,EAAE,sCAAsC,EACpF,OAAO,GAAE,gDAAqD;YAOlD,YAAY;YAqBZ,QAAQ;IAoDhB,OAAO,CAAC,KAAK,EAAE,sCAAsC,GAAG,OAAO,CAAC,kCAAkC,CAAC;YAK3F,aAAa;IAoCrB,KAAK,CAAC,KAAK,EAAE,oCAAoC,EAAE,OAAO,EAAE,wCAAwC,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAuH9I,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,8BAA8B,CAAC;IAUrE,QAAQ,CAAC,KAAK,EAAE,uCAAuC,EAAE,OAAO,EAAE,wCAAwC,GAAG,OAAO,CAAC,8BAA8B,CAAC;CAgH3J"}
|
|
@@ -835,12 +835,21 @@ class PostgresTodosTaskSubtreeTransferBackend {
|
|
|
835
835
|
this.tenantId = options.tenantId ?? "default";
|
|
836
836
|
}
|
|
837
837
|
async ensureSchema() {
|
|
838
|
-
this.schemaReady
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
838
|
+
if (this.schemaReady === null) {
|
|
839
|
+
const attempt = (async () => {
|
|
840
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName))
|
|
841
|
+
await this.client.query(sql);
|
|
842
|
+
for (const sql of postgresTodosTaskSubtreeTransferSchemaSql())
|
|
843
|
+
await this.client.query(sql);
|
|
844
|
+
})();
|
|
845
|
+
this.schemaReady = attempt;
|
|
846
|
+
try {
|
|
847
|
+
await attempt;
|
|
848
|
+
} catch (error) {
|
|
849
|
+
this.schemaReady = null;
|
|
850
|
+
throw error;
|
|
851
|
+
}
|
|
852
|
+
}
|
|
844
853
|
await this.schemaReady;
|
|
845
854
|
}
|
|
846
855
|
async snapshot(client, input, forUpdate = false) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/todos",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.46",
|
|
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",
|
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
"author": "Andrei Hasna <andrei@hasna.com>",
|
|
119
119
|
"license": "Apache-2.0",
|
|
120
120
|
"dependencies": {
|
|
121
|
-
"@hasna/contracts": "0.13.
|
|
121
|
+
"@hasna/contracts": "0.13.4",
|
|
122
122
|
"@hasna/events": "^0.1.11",
|
|
123
123
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
124
124
|
"chalk": "^5.4.1",
|