@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/index.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 = ?");
|
|
@@ -12922,7 +12922,7 @@ var init_dispatches = __esm(() => {
|
|
|
12922
12922
|
// package.json
|
|
12923
12923
|
var package_default = {
|
|
12924
12924
|
name: "@hasna/todos",
|
|
12925
|
-
version: "0.15.
|
|
12925
|
+
version: "0.15.46",
|
|
12926
12926
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12927
12927
|
type: "module",
|
|
12928
12928
|
main: "dist/index.js",
|
|
@@ -13040,7 +13040,7 @@ var package_default = {
|
|
|
13040
13040
|
author: "Andrei Hasna <andrei@hasna.com>",
|
|
13041
13041
|
license: "Apache-2.0",
|
|
13042
13042
|
dependencies: {
|
|
13043
|
-
"@hasna/contracts": "0.13.
|
|
13043
|
+
"@hasna/contracts": "0.13.4",
|
|
13044
13044
|
"@hasna/events": "^0.1.11",
|
|
13045
13045
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
13046
13046
|
chalk: "^5.4.1",
|
|
@@ -27150,7 +27150,7 @@ function matchesExtraFilters(task2, filter) {
|
|
|
27150
27150
|
}
|
|
27151
27151
|
if (filter.tags?.length) {
|
|
27152
27152
|
const taskTags2 = new Set(task2.tags ?? []);
|
|
27153
|
-
if (!filter.tags.
|
|
27153
|
+
if (!filter.tags.some((tag) => taskTags2.has(tag)))
|
|
27154
27154
|
return false;
|
|
27155
27155
|
}
|
|
27156
27156
|
if (filter.include_subtasks !== true && filter.parent_id === undefined && task2.parent_id)
|
|
@@ -27314,6 +27314,59 @@ function createLocalSqliteTodosStorageAdapter(options = {}) {
|
|
|
27314
27314
|
init_types();
|
|
27315
27315
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
27316
27316
|
init_creator_identity();
|
|
27317
|
+
|
|
27318
|
+
// src/lib/instant-compare.ts
|
|
27319
|
+
var SQLITE_STAMP = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?(?:Z|([+-])(\d{2}):(\d{2}))?)?$/;
|
|
27320
|
+
var DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
27321
|
+
function isLeapYear(year) {
|
|
27322
|
+
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
27323
|
+
}
|
|
27324
|
+
function sqliteJulianDay(value) {
|
|
27325
|
+
const m = SQLITE_STAMP.exec(value);
|
|
27326
|
+
if (!m)
|
|
27327
|
+
return null;
|
|
27328
|
+
const year = Number(m[1]);
|
|
27329
|
+
const month = Number(m[2]);
|
|
27330
|
+
const day = Number(m[3]);
|
|
27331
|
+
const hour = m[4] === undefined ? 0 : Number(m[4]);
|
|
27332
|
+
const minute = m[5] === undefined ? 0 : Number(m[5]);
|
|
27333
|
+
const second = m[6] === undefined ? 0 : Number(m[6]);
|
|
27334
|
+
const frac = m[7];
|
|
27335
|
+
const sign = m[8];
|
|
27336
|
+
const offsetHour = m[9];
|
|
27337
|
+
const offsetMinute = m[10];
|
|
27338
|
+
if (month < 1 || month > 12)
|
|
27339
|
+
return null;
|
|
27340
|
+
if (hour > 23 || minute > 59 || second > 59)
|
|
27341
|
+
return null;
|
|
27342
|
+
const maxDay = (DAYS_IN_MONTH[month - 1] ?? 0) + (month === 2 && isLeapYear(year) ? 1 : 0);
|
|
27343
|
+
if (day < 1 || day > maxDay)
|
|
27344
|
+
return null;
|
|
27345
|
+
let offsetMinutes = 0;
|
|
27346
|
+
if (sign !== undefined) {
|
|
27347
|
+
const oh = Number(offsetHour ?? "0");
|
|
27348
|
+
const om = Number(offsetMinute ?? "0");
|
|
27349
|
+
if (oh > 23 || om > 59)
|
|
27350
|
+
return null;
|
|
27351
|
+
offsetMinutes = oh * 60 + om;
|
|
27352
|
+
if (sign === "-")
|
|
27353
|
+
offsetMinutes = -offsetMinutes;
|
|
27354
|
+
}
|
|
27355
|
+
const micros = frac === undefined ? 0 : Number((frac + "000000").slice(0, 6));
|
|
27356
|
+
const ms = Date.UTC(year, month - 1, day, hour, minute, second);
|
|
27357
|
+
return (ms + micros / 1000) / 86400000 + 2440587.5 - offsetMinutes / 1440;
|
|
27358
|
+
}
|
|
27359
|
+
function changedSinceStampNewer(stamp, since) {
|
|
27360
|
+
const stampJd = sqliteJulianDay(stamp);
|
|
27361
|
+
if (stampJd === null)
|
|
27362
|
+
return true;
|
|
27363
|
+
const sinceJd = sqliteJulianDay(since);
|
|
27364
|
+
if (sinceJd === null)
|
|
27365
|
+
return false;
|
|
27366
|
+
return stampJd > sinceJd;
|
|
27367
|
+
}
|
|
27368
|
+
|
|
27369
|
+
// src/storage/postgres-adapter.ts
|
|
27317
27370
|
init_stale_lock_handoff();
|
|
27318
27371
|
|
|
27319
27372
|
// src/storage/postgres-sync.ts
|
|
@@ -27928,11 +27981,16 @@ class PostgresJsonRecordStore {
|
|
|
27928
27981
|
return context?.requestId ?? this.sourceMachineId ?? null;
|
|
27929
27982
|
}
|
|
27930
27983
|
async ensureSchema() {
|
|
27931
|
-
this.schemaReady
|
|
27932
|
-
|
|
27933
|
-
|
|
27934
|
-
|
|
27935
|
-
|
|
27984
|
+
if (!this.schemaReady) {
|
|
27985
|
+
this.schemaReady = (async () => {
|
|
27986
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName, this.cursorTableName)) {
|
|
27987
|
+
await this.options.client.query(sql);
|
|
27988
|
+
}
|
|
27989
|
+
})().catch((error) => {
|
|
27990
|
+
this.schemaReady = null;
|
|
27991
|
+
throw error;
|
|
27992
|
+
});
|
|
27993
|
+
}
|
|
27936
27994
|
await this.schemaReady;
|
|
27937
27995
|
}
|
|
27938
27996
|
async get(type, id) {
|
|
@@ -29697,7 +29755,7 @@ async function getActiveWork2(filters, store) {
|
|
|
29697
29755
|
}));
|
|
29698
29756
|
}
|
|
29699
29757
|
async function getChangedSince(since, filters, store) {
|
|
29700
|
-
return (await listTasks2(filters ?? {}, store)).filter((task2) => task2.updated_at
|
|
29758
|
+
return (await listTasks2(filters ?? {}, store)).filter((task2) => changedSinceStampNewer(task2.updated_at ?? "", since));
|
|
29701
29759
|
}
|
|
29702
29760
|
async function createProject2(input, store, context) {
|
|
29703
29761
|
const timestamp3 = new Date().toISOString();
|
|
@@ -35052,14 +35110,23 @@ class PostgresTodosProjectRegistrationBackend {
|
|
|
35052
35110
|
this.cursorTableName = safeIdentifier(options.cursorTableName ?? "todos_sync_cursors", "cursorTableName");
|
|
35053
35111
|
}
|
|
35054
35112
|
async ensureSchema() {
|
|
35055
|
-
this.schemaReady
|
|
35056
|
-
|
|
35057
|
-
|
|
35058
|
-
|
|
35059
|
-
|
|
35060
|
-
|
|
35113
|
+
if (this.schemaReady === null) {
|
|
35114
|
+
const attempt = (async () => {
|
|
35115
|
+
for (const statement of postgresTodosSyncSchemaSql(this.tableName, this.cursorTableName)) {
|
|
35116
|
+
await this.client.query(statement);
|
|
35117
|
+
}
|
|
35118
|
+
for (const statement of postgresTodosProjectRegistrationSchemaSql()) {
|
|
35119
|
+
await this.client.query(statement);
|
|
35120
|
+
}
|
|
35121
|
+
})();
|
|
35122
|
+
this.schemaReady = attempt;
|
|
35123
|
+
try {
|
|
35124
|
+
await attempt;
|
|
35125
|
+
} catch (error) {
|
|
35126
|
+
this.schemaReady = null;
|
|
35127
|
+
throw error;
|
|
35061
35128
|
}
|
|
35062
|
-
}
|
|
35129
|
+
}
|
|
35063
35130
|
await this.schemaReady;
|
|
35064
35131
|
}
|
|
35065
35132
|
async transaction(fn) {
|
|
@@ -42717,12 +42784,21 @@ class PostgresTodosTaskManifestBackend {
|
|
|
42717
42784
|
this.tenantId = options.tenantId ?? "default";
|
|
42718
42785
|
}
|
|
42719
42786
|
async ensureSchema() {
|
|
42720
|
-
this.schemaReady
|
|
42721
|
-
|
|
42722
|
-
|
|
42723
|
-
|
|
42724
|
-
|
|
42725
|
-
|
|
42787
|
+
if (this.schemaReady === null) {
|
|
42788
|
+
const attempt = (async () => {
|
|
42789
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName))
|
|
42790
|
+
await this.client.query(sql);
|
|
42791
|
+
for (const sql of postgresTodosTaskManifestSchemaSql(this.tenantId))
|
|
42792
|
+
await this.client.query(sql);
|
|
42793
|
+
})();
|
|
42794
|
+
this.schemaReady = attempt;
|
|
42795
|
+
try {
|
|
42796
|
+
await attempt;
|
|
42797
|
+
} catch (error) {
|
|
42798
|
+
this.schemaReady = null;
|
|
42799
|
+
throw error;
|
|
42800
|
+
}
|
|
42801
|
+
}
|
|
42726
42802
|
await this.schemaReady;
|
|
42727
42803
|
}
|
|
42728
42804
|
async insertSync(tx, objectType2, objectId, payload, now4) {
|
|
@@ -44072,12 +44148,21 @@ class PostgresTodosTaskSubtreeTransferBackend {
|
|
|
44072
44148
|
this.tenantId = options.tenantId ?? "default";
|
|
44073
44149
|
}
|
|
44074
44150
|
async ensureSchema() {
|
|
44075
|
-
this.schemaReady
|
|
44076
|
-
|
|
44077
|
-
|
|
44078
|
-
|
|
44079
|
-
|
|
44080
|
-
|
|
44151
|
+
if (this.schemaReady === null) {
|
|
44152
|
+
const attempt = (async () => {
|
|
44153
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName))
|
|
44154
|
+
await this.client.query(sql);
|
|
44155
|
+
for (const sql of postgresTodosTaskSubtreeTransferSchemaSql())
|
|
44156
|
+
await this.client.query(sql);
|
|
44157
|
+
})();
|
|
44158
|
+
this.schemaReady = attempt;
|
|
44159
|
+
try {
|
|
44160
|
+
await attempt;
|
|
44161
|
+
} catch (error) {
|
|
44162
|
+
this.schemaReady = null;
|
|
44163
|
+
throw error;
|
|
44164
|
+
}
|
|
44165
|
+
}
|
|
44081
44166
|
await this.schemaReady;
|
|
44082
44167
|
}
|
|
44083
44168
|
async snapshot(client, input, forUpdate = false) {
|
|
@@ -48928,7 +49013,7 @@ function scoreHealth(scope, scopeId, db) {
|
|
|
48928
49013
|
const blockers = d.query(`SELECT dep.id, dep.short_id, dep.title, dep.status
|
|
48929
49014
|
FROM task_dependencies td
|
|
48930
49015
|
JOIN tasks dep ON dep.id = td.depends_on
|
|
48931
|
-
WHERE td.task_id = ? AND dep.status
|
|
49016
|
+
WHERE td.task_id = ? AND dep.status NOT IN ('completed', 'cancelled')`).all(task3.id);
|
|
48932
49017
|
return { id: task3.id, short_id: task3.short_id, title: redactEvidenceText(task3.title), blockers };
|
|
48933
49018
|
}).filter((entry2) => entry2.blockers.length > 0);
|
|
48934
49019
|
const overdue = tasks.filter((task3) => activeTaskIds.has(task3.id) && Boolean(task3.due_at && task3.due_at < generatedAt)).map((task3) => ({ id: task3.id, short_id: task3.short_id, title: redactEvidenceText(task3.title), due_at: task3.due_at }));
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Since-cursor comparison for changed-since feeds.
|
|
3
|
+
*
|
|
4
|
+
* Stored `updated_at` stamps mix ISO ("2026-08-05T18:54:55.814Z") with
|
|
5
|
+
* space-form ("2026-06-10 11:24:47" — the DDL default `datetime('now')`, plus
|
|
6
|
+
* snapshot import/sync). As TEXT, space (0x20) sorts before 'T' (0x54), so a
|
|
7
|
+
* raw `updated_at > since` comparison silently excludes space-form rows that
|
|
8
|
+
* are genuinely NEWER than an ISO cursor. This compares the stamps as
|
|
9
|
+
* INSTANTS, mirroring the SQL `julianday()` predicate used by the
|
|
10
|
+
* SQLite/Postgres updated_after paths (task-crud.ts), including its
|
|
11
|
+
* keep-unparseable semantics: a stamp julianday() cannot parse yields NULL
|
|
12
|
+
* and the row is KEPT, because "cannot read the row's timestamp" is not
|
|
13
|
+
* "older than the cursor".
|
|
14
|
+
*
|
|
15
|
+
* The parser is deliberately SQLite-faithful rather than `Date.parse`-based,
|
|
16
|
+
* because the two disagree in ways that change the comparison:
|
|
17
|
+
*
|
|
18
|
+
* - SQLite accepts ONLY an uppercase 'T' (or space) separator and an
|
|
19
|
+
* uppercase 'Z' (or `±HH:MM`) offset; `Date.parse` also accepts lowercase
|
|
20
|
+
* 't'/'z', so a row SQLite would read as NULL (and KEEP) would otherwise be
|
|
21
|
+
* excluded.
|
|
22
|
+
* - SQLite parses the fractional seconds to microsecond precision;
|
|
23
|
+
* `Date.parse` truncates to milliseconds, so stamps that differ only in the
|
|
24
|
+
* sub-millisecond digits would compare equal (and be excluded) instead of
|
|
25
|
+
* newer.
|
|
26
|
+
* - SQLite rejects out-of-range calendar fields (month 13, day 32, hour 25,
|
|
27
|
+
* second 61); `Date.UTC` normalizes them, which would silently accept a
|
|
28
|
+
* stamp SQLite treats as unreadable.
|
|
29
|
+
*
|
|
30
|
+
* Naive (no-offset) stamps are read as UTC, matching SQLite julianday().
|
|
31
|
+
* Offsets are applied by subtraction, matching julianday('...+02:00') ==
|
|
32
|
+
* UTC minus two hours.
|
|
33
|
+
*/
|
|
34
|
+
export declare function changedSinceStampNewer(stamp: string, since: string): boolean;
|
|
35
|
+
//# sourceMappingURL=instant-compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instant-compare.d.ts","sourceRoot":"","sources":["../../src/lib/instant-compare.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAqDH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAM5E"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -13289,7 +13289,7 @@ function getTaskGraph(taskId, direction = "both", db) {
|
|
|
13289
13289
|
const deps = getTaskDependencies(t.id, d);
|
|
13290
13290
|
const hasUnfinishedDeps = deps.some((dep) => {
|
|
13291
13291
|
const depTask = getTask(dep.depends_on, d);
|
|
13292
|
-
return depTask && depTask.status
|
|
13292
|
+
return depTask && isBlockingDependencyStatus(depTask.status);
|
|
13293
13293
|
});
|
|
13294
13294
|
return { id: t.id, short_id: t.short_id, title: t.title, status: t.status, priority: t.priority, is_blocked: hasUnfinishedDeps };
|
|
13295
13295
|
}
|
|
@@ -13549,7 +13549,7 @@ function getBlockingDeps(id, db) {
|
|
|
13549
13549
|
const blocking = [];
|
|
13550
13550
|
for (const dep of deps) {
|
|
13551
13551
|
const task = getTask(dep.depends_on, d);
|
|
13552
|
-
if (task && task.status
|
|
13552
|
+
if (task && isBlockingDependencyStatus(task.status))
|
|
13553
13553
|
blocking.push(task);
|
|
13554
13554
|
}
|
|
13555
13555
|
return blocking;
|
|
@@ -13873,7 +13873,7 @@ function getNextTask(agentId, filters, db) {
|
|
|
13873
13873
|
conditions.push(`id IN (SELECT task_id FROM task_tags WHERE tag IN (${placeholders}))`);
|
|
13874
13874
|
params.push(...filters.tags);
|
|
13875
13875
|
}
|
|
13876
|
-
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
|
|
13876
|
+
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'))");
|
|
13877
13877
|
const where = conditions.join(" AND ");
|
|
13878
13878
|
let recentProjectIds = [];
|
|
13879
13879
|
const assignedAliasParams = [];
|
|
@@ -13917,7 +13917,7 @@ function getActiveWork(filters, db) {
|
|
|
13917
13917
|
}
|
|
13918
13918
|
function getTasksChangedSince(since, filters, db) {
|
|
13919
13919
|
const d = db || getDatabase();
|
|
13920
|
-
const conditions = ["updated_at > ?"];
|
|
13920
|
+
const conditions = ["(julianday(updated_at) IS NULL OR julianday(updated_at) > julianday(?))"];
|
|
13921
13921
|
const params = [since];
|
|
13922
13922
|
if (filters?.project_id) {
|
|
13923
13923
|
conditions.push("project_id = ?");
|
|
@@ -18867,6 +18867,60 @@ var init_assignee_context = __esm(() => {
|
|
|
18867
18867
|
init_assignee_validation();
|
|
18868
18868
|
});
|
|
18869
18869
|
|
|
18870
|
+
// src/lib/instant-compare.ts
|
|
18871
|
+
function isLeapYear(year) {
|
|
18872
|
+
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
|
|
18873
|
+
}
|
|
18874
|
+
function sqliteJulianDay(value) {
|
|
18875
|
+
const m = SQLITE_STAMP.exec(value);
|
|
18876
|
+
if (!m)
|
|
18877
|
+
return null;
|
|
18878
|
+
const year = Number(m[1]);
|
|
18879
|
+
const month = Number(m[2]);
|
|
18880
|
+
const day = Number(m[3]);
|
|
18881
|
+
const hour = m[4] === undefined ? 0 : Number(m[4]);
|
|
18882
|
+
const minute = m[5] === undefined ? 0 : Number(m[5]);
|
|
18883
|
+
const second = m[6] === undefined ? 0 : Number(m[6]);
|
|
18884
|
+
const frac = m[7];
|
|
18885
|
+
const sign = m[8];
|
|
18886
|
+
const offsetHour = m[9];
|
|
18887
|
+
const offsetMinute = m[10];
|
|
18888
|
+
if (month < 1 || month > 12)
|
|
18889
|
+
return null;
|
|
18890
|
+
if (hour > 23 || minute > 59 || second > 59)
|
|
18891
|
+
return null;
|
|
18892
|
+
const maxDay = (DAYS_IN_MONTH[month - 1] ?? 0) + (month === 2 && isLeapYear(year) ? 1 : 0);
|
|
18893
|
+
if (day < 1 || day > maxDay)
|
|
18894
|
+
return null;
|
|
18895
|
+
let offsetMinutes = 0;
|
|
18896
|
+
if (sign !== undefined) {
|
|
18897
|
+
const oh = Number(offsetHour ?? "0");
|
|
18898
|
+
const om = Number(offsetMinute ?? "0");
|
|
18899
|
+
if (oh > 23 || om > 59)
|
|
18900
|
+
return null;
|
|
18901
|
+
offsetMinutes = oh * 60 + om;
|
|
18902
|
+
if (sign === "-")
|
|
18903
|
+
offsetMinutes = -offsetMinutes;
|
|
18904
|
+
}
|
|
18905
|
+
const micros = frac === undefined ? 0 : Number((frac + "000000").slice(0, 6));
|
|
18906
|
+
const ms = Date.UTC(year, month - 1, day, hour, minute, second);
|
|
18907
|
+
return (ms + micros / 1000) / 86400000 + 2440587.5 - offsetMinutes / 1440;
|
|
18908
|
+
}
|
|
18909
|
+
function changedSinceStampNewer(stamp, since) {
|
|
18910
|
+
const stampJd = sqliteJulianDay(stamp);
|
|
18911
|
+
if (stampJd === null)
|
|
18912
|
+
return true;
|
|
18913
|
+
const sinceJd = sqliteJulianDay(since);
|
|
18914
|
+
if (sinceJd === null)
|
|
18915
|
+
return false;
|
|
18916
|
+
return stampJd > sinceJd;
|
|
18917
|
+
}
|
|
18918
|
+
var SQLITE_STAMP, DAYS_IN_MONTH;
|
|
18919
|
+
var init_instant_compare = __esm(() => {
|
|
18920
|
+
SQLITE_STAMP = /^(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?(?:Z|([+-])(\d{2}):(\d{2}))?)?$/;
|
|
18921
|
+
DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
18922
|
+
});
|
|
18923
|
+
|
|
18870
18924
|
// src/lib/plan-project-link-contract.ts
|
|
18871
18925
|
import { createHash as createHash3 } from "crypto";
|
|
18872
18926
|
function canonicalPlanProjectLinkJson(value) {
|
|
@@ -21920,6 +21974,7 @@ var UUID_RE, completionCapabilityCache, retryCapabilityCache, taskCreatorCapabil
|
|
|
21920
21974
|
var init_cloud_router = __esm(() => {
|
|
21921
21975
|
init_types();
|
|
21922
21976
|
init_redaction();
|
|
21977
|
+
init_instant_compare();
|
|
21923
21978
|
init_plan_project_link_contract();
|
|
21924
21979
|
init_http_client();
|
|
21925
21980
|
init_adoption_validation();
|
|
@@ -34724,7 +34779,7 @@ function scoreHealth(scope, scopeId, db) {
|
|
|
34724
34779
|
const blockers = d.query(`SELECT dep.id, dep.short_id, dep.title, dep.status
|
|
34725
34780
|
FROM task_dependencies td
|
|
34726
34781
|
JOIN tasks dep ON dep.id = td.depends_on
|
|
34727
|
-
WHERE td.task_id = ? AND dep.status
|
|
34782
|
+
WHERE td.task_id = ? AND dep.status NOT IN ('completed', 'cancelled')`).all(task.id);
|
|
34728
34783
|
return { id: task.id, short_id: task.short_id, title: redactEvidenceText(task.title), blockers };
|
|
34729
34784
|
}).filter((entry) => entry.blockers.length > 0);
|
|
34730
34785
|
const overdue = tasks.filter((task) => activeTaskIds.has(task.id) && Boolean(task.due_at && task.due_at < generatedAt)).map((task) => ({ id: task.id, short_id: task.short_id, title: redactEvidenceText(task.title), due_at: task.due_at }));
|
|
@@ -36047,7 +36102,7 @@ var package_default;
|
|
|
36047
36102
|
var init_package = __esm(() => {
|
|
36048
36103
|
package_default = {
|
|
36049
36104
|
name: "@hasna/todos",
|
|
36050
|
-
version: "0.15.
|
|
36105
|
+
version: "0.15.46",
|
|
36051
36106
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
36052
36107
|
type: "module",
|
|
36053
36108
|
main: "dist/index.js",
|
|
@@ -36165,7 +36220,7 @@ var init_package = __esm(() => {
|
|
|
36165
36220
|
author: "Andrei Hasna <andrei@hasna.com>",
|
|
36166
36221
|
license: "Apache-2.0",
|
|
36167
36222
|
dependencies: {
|
|
36168
|
-
"@hasna/contracts": "0.13.
|
|
36223
|
+
"@hasna/contracts": "0.13.4",
|
|
36169
36224
|
"@hasna/events": "^0.1.11",
|
|
36170
36225
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
36171
36226
|
chalk: "^5.4.1",
|
|
@@ -46241,7 +46296,7 @@ function matchesExtraFilters(task2, filter) {
|
|
|
46241
46296
|
}
|
|
46242
46297
|
if (filter.tags?.length) {
|
|
46243
46298
|
const taskTags = new Set(task2.tags ?? []);
|
|
46244
|
-
if (!filter.tags.
|
|
46299
|
+
if (!filter.tags.some((tag) => taskTags.has(tag)))
|
|
46245
46300
|
return false;
|
|
46246
46301
|
}
|
|
46247
46302
|
if (filter.include_subtasks !== true && filter.parent_id === undefined && task2.parent_id)
|
|
@@ -47433,11 +47488,16 @@ class PostgresJsonRecordStore {
|
|
|
47433
47488
|
return context?.requestId ?? this.sourceMachineId ?? null;
|
|
47434
47489
|
}
|
|
47435
47490
|
async ensureSchema() {
|
|
47436
|
-
this.schemaReady
|
|
47437
|
-
|
|
47438
|
-
|
|
47439
|
-
|
|
47440
|
-
|
|
47491
|
+
if (!this.schemaReady) {
|
|
47492
|
+
this.schemaReady = (async () => {
|
|
47493
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName, this.cursorTableName)) {
|
|
47494
|
+
await this.options.client.query(sql);
|
|
47495
|
+
}
|
|
47496
|
+
})().catch((error) => {
|
|
47497
|
+
this.schemaReady = null;
|
|
47498
|
+
throw error;
|
|
47499
|
+
});
|
|
47500
|
+
}
|
|
47441
47501
|
await this.schemaReady;
|
|
47442
47502
|
}
|
|
47443
47503
|
async get(type, id) {
|
|
@@ -49199,7 +49259,7 @@ async function getActiveWork2(filters, store) {
|
|
|
49199
49259
|
}));
|
|
49200
49260
|
}
|
|
49201
49261
|
async function getChangedSince(since, filters, store) {
|
|
49202
|
-
return (await listTasks3(filters ?? {}, store)).filter((task2) => task2.updated_at
|
|
49262
|
+
return (await listTasks3(filters ?? {}, store)).filter((task2) => changedSinceStampNewer(task2.updated_at ?? "", since));
|
|
49203
49263
|
}
|
|
49204
49264
|
async function createProject2(input, store, context) {
|
|
49205
49265
|
const timestamp4 = new Date().toISOString();
|
|
@@ -49758,6 +49818,7 @@ var CLOUD_LOCK_EXPIRY_MINUTES = 30, TASK_ORDER_TIEBREAK = "CASE payload->>'prior
|
|
|
49758
49818
|
var init_postgres_adapter = __esm(() => {
|
|
49759
49819
|
init_types();
|
|
49760
49820
|
init_creator_identity();
|
|
49821
|
+
init_instant_compare();
|
|
49761
49822
|
init_plan_project_link_contract();
|
|
49762
49823
|
init_stale_lock_handoff();
|
|
49763
49824
|
init_postgres_sync();
|
|
@@ -50188,10 +50249,19 @@ class PostgresPrGroupLedgerPersistence {
|
|
|
50188
50249
|
this.client = client;
|
|
50189
50250
|
}
|
|
50190
50251
|
async ensureSchema() {
|
|
50191
|
-
this.schemaReady
|
|
50192
|
-
|
|
50193
|
-
|
|
50194
|
-
|
|
50252
|
+
if (this.schemaReady === null) {
|
|
50253
|
+
const attempt = (async () => {
|
|
50254
|
+
for (const statement of postgresPrGroupSchemaSql())
|
|
50255
|
+
await this.client.query(statement);
|
|
50256
|
+
})();
|
|
50257
|
+
this.schemaReady = attempt;
|
|
50258
|
+
try {
|
|
50259
|
+
await attempt;
|
|
50260
|
+
} catch (error) {
|
|
50261
|
+
this.schemaReady = null;
|
|
50262
|
+
throw error;
|
|
50263
|
+
}
|
|
50264
|
+
}
|
|
50195
50265
|
return this.schemaReady;
|
|
50196
50266
|
}
|
|
50197
50267
|
async transaction(fn) {
|
|
@@ -50609,14 +50679,23 @@ class PostgresTodosProjectRegistrationBackend {
|
|
|
50609
50679
|
this.cursorTableName = safeIdentifier(options.cursorTableName ?? "todos_sync_cursors", "cursorTableName");
|
|
50610
50680
|
}
|
|
50611
50681
|
async ensureSchema() {
|
|
50612
|
-
this.schemaReady
|
|
50613
|
-
|
|
50614
|
-
|
|
50615
|
-
|
|
50616
|
-
|
|
50617
|
-
|
|
50682
|
+
if (this.schemaReady === null) {
|
|
50683
|
+
const attempt = (async () => {
|
|
50684
|
+
for (const statement of postgresTodosSyncSchemaSql(this.tableName, this.cursorTableName)) {
|
|
50685
|
+
await this.client.query(statement);
|
|
50686
|
+
}
|
|
50687
|
+
for (const statement of postgresTodosProjectRegistrationSchemaSql()) {
|
|
50688
|
+
await this.client.query(statement);
|
|
50689
|
+
}
|
|
50690
|
+
})();
|
|
50691
|
+
this.schemaReady = attempt;
|
|
50692
|
+
try {
|
|
50693
|
+
await attempt;
|
|
50694
|
+
} catch (error) {
|
|
50695
|
+
this.schemaReady = null;
|
|
50696
|
+
throw error;
|
|
50618
50697
|
}
|
|
50619
|
-
}
|
|
50698
|
+
}
|
|
50620
50699
|
await this.schemaReady;
|
|
50621
50700
|
}
|
|
50622
50701
|
async transaction(fn) {
|
|
@@ -53326,12 +53405,21 @@ class PostgresTodosTaskManifestBackend {
|
|
|
53326
53405
|
this.tenantId = options.tenantId ?? "default";
|
|
53327
53406
|
}
|
|
53328
53407
|
async ensureSchema() {
|
|
53329
|
-
this.schemaReady
|
|
53330
|
-
|
|
53331
|
-
|
|
53332
|
-
|
|
53333
|
-
|
|
53334
|
-
|
|
53408
|
+
if (this.schemaReady === null) {
|
|
53409
|
+
const attempt = (async () => {
|
|
53410
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName))
|
|
53411
|
+
await this.client.query(sql);
|
|
53412
|
+
for (const sql of postgresTodosTaskManifestSchemaSql(this.tenantId))
|
|
53413
|
+
await this.client.query(sql);
|
|
53414
|
+
})();
|
|
53415
|
+
this.schemaReady = attempt;
|
|
53416
|
+
try {
|
|
53417
|
+
await attempt;
|
|
53418
|
+
} catch (error) {
|
|
53419
|
+
this.schemaReady = null;
|
|
53420
|
+
throw error;
|
|
53421
|
+
}
|
|
53422
|
+
}
|
|
53335
53423
|
await this.schemaReady;
|
|
53336
53424
|
}
|
|
53337
53425
|
async insertSync(tx, objectType2, objectId, payload, now4) {
|
|
@@ -54631,12 +54719,21 @@ class PostgresTodosTaskSubtreeTransferBackend {
|
|
|
54631
54719
|
this.tenantId = options.tenantId ?? "default";
|
|
54632
54720
|
}
|
|
54633
54721
|
async ensureSchema() {
|
|
54634
|
-
this.schemaReady
|
|
54635
|
-
|
|
54636
|
-
|
|
54637
|
-
|
|
54638
|
-
|
|
54639
|
-
|
|
54722
|
+
if (this.schemaReady === null) {
|
|
54723
|
+
const attempt = (async () => {
|
|
54724
|
+
for (const sql of postgresTodosSyncSchemaSql(this.tableName))
|
|
54725
|
+
await this.client.query(sql);
|
|
54726
|
+
for (const sql of postgresTodosTaskSubtreeTransferSchemaSql())
|
|
54727
|
+
await this.client.query(sql);
|
|
54728
|
+
})();
|
|
54729
|
+
this.schemaReady = attempt;
|
|
54730
|
+
try {
|
|
54731
|
+
await attempt;
|
|
54732
|
+
} catch (error) {
|
|
54733
|
+
this.schemaReady = null;
|
|
54734
|
+
throw error;
|
|
54735
|
+
}
|
|
54736
|
+
}
|
|
54640
54737
|
await this.schemaReady;
|
|
54641
54738
|
}
|
|
54642
54739
|
async snapshot(client, input, forUpdate = false) {
|
|
@@ -55723,7 +55820,10 @@ async function ensureCloudSchema() {
|
|
|
55723
55820
|
await client.query(sql);
|
|
55724
55821
|
}
|
|
55725
55822
|
await getApiKeyStore().ensureSchema();
|
|
55726
|
-
})()
|
|
55823
|
+
})().catch((error) => {
|
|
55824
|
+
schemaEnsured = null;
|
|
55825
|
+
throw error;
|
|
55826
|
+
});
|
|
55727
55827
|
return schemaEnsured;
|
|
55728
55828
|
}
|
|
55729
55829
|
async function ensureCloudCommentCursorIndex() {
|
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.46",
|
|
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",
|
|
@@ -159,7 +159,7 @@ var package_default = {
|
|
|
159
159
|
author: "Andrei Hasna <andrei@hasna.com>",
|
|
160
160
|
license: "Apache-2.0",
|
|
161
161
|
dependencies: {
|
|
162
|
-
"@hasna/contracts": "0.13.
|
|
162
|
+
"@hasna/contracts": "0.13.4",
|
|
163
163
|
"@hasna/events": "^0.1.11",
|
|
164
164
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
165
165
|
chalk: "^5.4.1",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/pr-groups/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA2B,SAAQ,wBAAwB;IAC1E,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAClF;AAED,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAyInD;AAgPD,qBAAa,gCAAiC,YAAW,wBAAwB;IAInE,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,QAAQ,CAAC,SAAS,EAAG,QAAQ,CAAU;IACvC,OAAO,CAAC,WAAW,CAA8B;gBAEpB,MAAM,EAAE,0BAA0B;IAEzD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/pr-groups/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,aAAa,EACnB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA2B,SAAQ,wBAAwB;IAC1E,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAClF;AAED,wBAAgB,wBAAwB,IAAI,MAAM,EAAE,CAyInD;AAgPD,qBAAa,gCAAiC,YAAW,wBAAwB;IAInE,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,QAAQ,CAAC,SAAS,EAAG,QAAQ,CAAU;IACvC,OAAO,CAAC,WAAW,CAA8B;gBAEpB,MAAM,EAAE,0BAA0B;IAEzD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB7B,WAAW,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,wBAAwB,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IA2B5E,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAKnD,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAK9D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAK7F,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAYhF,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAS7C,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC;CAQ1E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/project-registration/postgres.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EACV,+BAA+B,EAC/B,0CAA0C,EAC1C,sCAAsC,EACtC,kCAAkC,EAClC,oCAAoC,EACpC,kCAAkC,EAElC,6BAA6B,EAC7B,0BAA0B,EAC3B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAEL,KAAK,oCAAoC,EAC1C,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,sCACjB,SAAQ,wBAAwB;IAC9B,WAAW,CAAC,CAAC,EACX,EAAE,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,OAAO,CAAC,CAAC,CAAC,GACnD,OAAO,CAAC,CAAC,CAAC,CAAC;CACf;AAED,MAAM,WAAW,8CAA8C;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAuaD,qBAAa,uCACb,YAAW,+BAA+B;IAQtC,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,eAAe,CAAS;IACzC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,sCAAsC,EAC/D,OAAO,GAAE,8CAAmD;IAUxD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/project-registration/postgres.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,EACV,+BAA+B,EAC/B,0CAA0C,EAC1C,sCAAsC,EACtC,kCAAkC,EAClC,oCAAoC,EACpC,kCAAkC,EAElC,6BAA6B,EAC7B,0BAA0B,EAC3B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAEL,KAAK,oCAAoC,EAC1C,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,sCACjB,SAAQ,wBAAwB;IAC9B,WAAW,CAAC,CAAC,EACX,EAAE,EAAE,CAAC,MAAM,EAAE,wBAAwB,KAAK,OAAO,CAAC,CAAC,CAAC,GACnD,OAAO,CAAC,CAAC,CAAC,CAAC;CACf;AAED,MAAM,WAAW,8CAA8C;IAC7D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAuaD,qBAAa,uCACb,YAAW,+BAA+B;IAQtC,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,eAAe,CAAS;IACzC,OAAO,CAAC,WAAW,CAA8B;gBAG9B,MAAM,EAAE,sCAAsC,EAC/D,OAAO,GAAE,8CAAmD;IAUxD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA4B7B,WAAW,CAAC,CAAC,EACjB,EAAE,EAAE,CAAC,WAAW,EAAE,0CAA0C,KAAK,OAAO,CAAC,CAAC,CAAC,GAC1E,OAAO,CAAC,CAAC,CAAC;YAkBC,MAAM;IAUd,mBAAmB,CACvB,QAAQ,EAAE,oCAAoC,GAC7C,OAAO,CAAC,kCAAkC,GAAG,IAAI,CAAC;IAI/C,cAAc,CAClB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,kCAAkC,GAAG,IAAI,CAAC;IAI/C,UAAU,CACd,KAAK,EAAE,sCAAsC,EAC7C,YAAY,EAAE,oCAAoC,EAClD,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,kCAAkC,GAAG,IAAI,CAAC;IAI/C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAI/C,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC;IAIjD,oCAAoC,CAAC,KAAK,EAAE;QAChD,gBAAgB,EAAE,MAAM,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,OAAO,CAAC;KAC1B,GAAG,OAAO,CAAC,MAAM,CAAC;IA8Cb,6BAA6B,CAAC,KAAK,EAAE;QACzC,gBAAgB,EAAE,MAAM,CAAC;QACzB,YAAY,EAAE,MAAM,CAAC;QACrB,eAAe,EAAE,OAAO,CAAC;QACzB,KAAK,EAAE,0BAA0B,GAAG,IAAI,CAAC;QACzC,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,6BAA6B,EAAE,CAAC;CAgD7C"}
|