@hasna/todos 0.15.5 → 0.15.6
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/commands/task-commands.d.ts.map +1 -1
- package/dist/cli/index.js +96 -28
- package/dist/contracts.js +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/comment-cursor.d.ts +40 -0
- package/dist/lib/comment-cursor.d.ts.map +1 -0
- package/dist/mcp/index.js +24 -21
- package/dist/mcp.js +1 -1
- package/dist/registry.js +1 -1
- package/dist/release-provenance.json +5 -5
- package/dist/server/index.js +24 -21
- package/dist/server/v1.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/task-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"task-commands.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/task-commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiEzC,oFAAoF;AACpF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQ5D;AA2ZD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,QAwzDpD"}
|
package/dist/cli/index.js
CHANGED
|
@@ -2123,7 +2123,7 @@ var package_default;
|
|
|
2123
2123
|
var init_package = __esm(() => {
|
|
2124
2124
|
package_default = {
|
|
2125
2125
|
name: "@hasna/todos",
|
|
2126
|
-
version: "0.15.
|
|
2126
|
+
version: "0.15.6",
|
|
2127
2127
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
2128
2128
|
type: "module",
|
|
2129
2129
|
main: "dist/index.js",
|
|
@@ -19331,6 +19331,45 @@ var init_tasks = __esm(() => {
|
|
|
19331
19331
|
init_calendar();
|
|
19332
19332
|
});
|
|
19333
19333
|
|
|
19334
|
+
// src/lib/comment-cursor.ts
|
|
19335
|
+
function encodeCommentCursor(comment) {
|
|
19336
|
+
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
19337
|
+
}
|
|
19338
|
+
function decodeCommentCursor(value) {
|
|
19339
|
+
if (value.length > MAX_COMMENT_CURSOR_LENGTH)
|
|
19340
|
+
throw new Error("invalid comment cursor");
|
|
19341
|
+
let parsed;
|
|
19342
|
+
try {
|
|
19343
|
+
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
19344
|
+
} catch {
|
|
19345
|
+
throw new Error("invalid comment cursor");
|
|
19346
|
+
}
|
|
19347
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
19348
|
+
throw new Error("invalid comment cursor");
|
|
19349
|
+
const cursor = parsed;
|
|
19350
|
+
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
19351
|
+
throw new Error("invalid comment cursor");
|
|
19352
|
+
}
|
|
19353
|
+
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
19354
|
+
}
|
|
19355
|
+
function isStrictlyOlder(comment, before) {
|
|
19356
|
+
return comment.created_at < before.created_at || comment.created_at === before.created_at && comment.id < before.id;
|
|
19357
|
+
}
|
|
19358
|
+
function pageComments(all, options) {
|
|
19359
|
+
const ascending = [...all].sort((left, right) => left.created_at.localeCompare(right.created_at) || left.id.localeCompare(right.id));
|
|
19360
|
+
const scoped = options.before ? ascending.filter((comment) => isStrictlyOlder(comment, options.before)) : ascending;
|
|
19361
|
+
const comments = scoped.slice(-options.limit);
|
|
19362
|
+
const hasMore = scoped.length > comments.length;
|
|
19363
|
+
return {
|
|
19364
|
+
comments,
|
|
19365
|
+
count: comments.length,
|
|
19366
|
+
has_more: hasMore,
|
|
19367
|
+
next_cursor: hasMore && comments[0] ? encodeCommentCursor(comments[0]) : null,
|
|
19368
|
+
limit: options.limit
|
|
19369
|
+
};
|
|
19370
|
+
}
|
|
19371
|
+
var MAX_COMMENT_CURSOR_LENGTH = 1024;
|
|
19372
|
+
|
|
19334
19373
|
// src/lib/bulk-tags.ts
|
|
19335
19374
|
function parseTagList(raw) {
|
|
19336
19375
|
if (!raw)
|
|
@@ -20565,6 +20604,53 @@ function parseIntOption(value, flag) {
|
|
|
20565
20604
|
}
|
|
20566
20605
|
return n;
|
|
20567
20606
|
}
|
|
20607
|
+
function commentPageOptions(opts) {
|
|
20608
|
+
const requested = opts.commentsLimit !== undefined || opts.commentsCursor !== undefined;
|
|
20609
|
+
let limit = DEFAULT_CLI_COMMENT_PAGE;
|
|
20610
|
+
if (opts.commentsLimit !== undefined) {
|
|
20611
|
+
const parsed = Number(opts.commentsLimit);
|
|
20612
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > MAX_CLI_COMMENT_PAGE) {
|
|
20613
|
+
handleError(new Error(`--comments-limit must be an integer between 1 and ${MAX_CLI_COMMENT_PAGE}`));
|
|
20614
|
+
}
|
|
20615
|
+
limit = parsed;
|
|
20616
|
+
}
|
|
20617
|
+
let before;
|
|
20618
|
+
if (opts.commentsCursor !== undefined) {
|
|
20619
|
+
try {
|
|
20620
|
+
before = decodeCommentCursor(opts.commentsCursor);
|
|
20621
|
+
} catch {
|
|
20622
|
+
handleError(new Error("--comments-cursor is not a valid comment cursor; pass the value from comments_page.next_cursor"));
|
|
20623
|
+
}
|
|
20624
|
+
}
|
|
20625
|
+
return {
|
|
20626
|
+
request: {
|
|
20627
|
+
...opts.commentsLimit !== undefined ? { limit } : {},
|
|
20628
|
+
...opts.commentsCursor !== undefined ? { cursor: opts.commentsCursor } : {}
|
|
20629
|
+
},
|
|
20630
|
+
requested,
|
|
20631
|
+
limit,
|
|
20632
|
+
...before ? { before } : {}
|
|
20633
|
+
};
|
|
20634
|
+
}
|
|
20635
|
+
function applyLocalCommentPage(task, page) {
|
|
20636
|
+
if (!task || !page.requested)
|
|
20637
|
+
return task;
|
|
20638
|
+
const paged = pageComments(task.comments, {
|
|
20639
|
+
limit: page.limit,
|
|
20640
|
+
...page.before ? { before: page.before } : {}
|
|
20641
|
+
});
|
|
20642
|
+
return {
|
|
20643
|
+
...task,
|
|
20644
|
+
comments: paged.comments,
|
|
20645
|
+
comments_page: {
|
|
20646
|
+
count: paged.count,
|
|
20647
|
+
limit: paged.limit,
|
|
20648
|
+
has_more: paged.has_more,
|
|
20649
|
+
next_cursor: paged.next_cursor,
|
|
20650
|
+
pagination_supported: true
|
|
20651
|
+
}
|
|
20652
|
+
};
|
|
20653
|
+
}
|
|
20568
20654
|
function isPathLike(input) {
|
|
20569
20655
|
return input.startsWith(".") || input.includes("/") || input.includes("\\");
|
|
20570
20656
|
}
|
|
@@ -21161,13 +21247,14 @@ function registerTaskCommands(program2) {
|
|
|
21161
21247
|
console.log(parts.join(" "));
|
|
21162
21248
|
}
|
|
21163
21249
|
});
|
|
21164
|
-
program2.command("show <id>").description("Show full task details").action(async (id) => {
|
|
21250
|
+
program2.command("show <id>").description("Show full task details").option("--comments-limit <n>", `Comments per page, 1-${MAX_CLI_COMMENT_PAGE} (default ${DEFAULT_CLI_COMMENT_PAGE})`).option("--comments-cursor <cursor>", "Read the next OLDER page; pass comments_page.next_cursor").action(async (id, opts) => {
|
|
21165
21251
|
const globalOpts = program2.opts();
|
|
21252
|
+
const page = commentPageOptions(opts);
|
|
21166
21253
|
const cloud = getTodosCloudClient();
|
|
21167
21254
|
let task2;
|
|
21168
21255
|
if (cloud) {
|
|
21169
21256
|
const remote = await cloudGetTask(cloud, await resolveTaskIdForCommand(id, cloud));
|
|
21170
|
-
const commentPage = remote ? await cloudListComments(cloud, remote.id) : null;
|
|
21257
|
+
const commentPage = remote ? await cloudListComments(cloud, remote.id, page.request) : null;
|
|
21171
21258
|
const relations = remote ? await cloudDetailRelations(cloud, remote.id) : null;
|
|
21172
21259
|
task2 = remote ? {
|
|
21173
21260
|
subtasks: [],
|
|
@@ -21187,7 +21274,7 @@ function registerTaskCommands(program2) {
|
|
|
21187
21274
|
} : null;
|
|
21188
21275
|
} else {
|
|
21189
21276
|
const resolvedId = resolveTaskId(id);
|
|
21190
|
-
task2 = getTaskWithRelations(resolvedId);
|
|
21277
|
+
task2 = applyLocalCommentPage(getTaskWithRelations(resolvedId), page);
|
|
21191
21278
|
}
|
|
21192
21279
|
if (!task2) {
|
|
21193
21280
|
handleError(new Error(`Task not found: ${id}`));
|
|
@@ -21278,8 +21365,9 @@ function registerTaskCommands(program2) {
|
|
|
21278
21365
|
}
|
|
21279
21366
|
}
|
|
21280
21367
|
});
|
|
21281
|
-
program2.command("inspect [id]").description("Full orientation for a task \u2014 details, description, dependencies, blocker, files, commits, comments. If no ID given, shows current in-progress task for --agent.").action(async (id) => {
|
|
21368
|
+
program2.command("inspect [id]").description("Full orientation for a task \u2014 details, description, dependencies, blocker, files, commits, comments. If no ID given, shows current in-progress task for --agent.").option("--comments-limit <n>", `Comments per page, 1-${MAX_CLI_COMMENT_PAGE} (default ${DEFAULT_CLI_COMMENT_PAGE})`).option("--comments-cursor <cursor>", "Read the next OLDER page; pass comments_page.next_cursor").action(async (id, opts) => {
|
|
21282
21369
|
const globalOpts = program2.opts();
|
|
21370
|
+
const page = commentPageOptions(opts);
|
|
21283
21371
|
const cloud = getTodosCloudClient();
|
|
21284
21372
|
let resolvedId = id ? await resolveTaskIdForCommand(id, cloud) : null;
|
|
21285
21373
|
if (!resolvedId && globalOpts.agent && !cloud) {
|
|
@@ -21299,7 +21387,7 @@ function registerTaskCommands(program2) {
|
|
|
21299
21387
|
let task2;
|
|
21300
21388
|
if (cloud) {
|
|
21301
21389
|
const remote = await cloudGetTask(cloud, resolvedId);
|
|
21302
|
-
const commentPage = remote ? await cloudListComments(cloud, remote.id) : null;
|
|
21390
|
+
const commentPage = remote ? await cloudListComments(cloud, remote.id, page.request) : null;
|
|
21303
21391
|
const relations = remote ? await cloudDetailRelations(cloud, remote.id) : null;
|
|
21304
21392
|
task2 = remote ? {
|
|
21305
21393
|
subtasks: [],
|
|
@@ -21319,7 +21407,7 @@ function registerTaskCommands(program2) {
|
|
|
21319
21407
|
}
|
|
21320
21408
|
} : null;
|
|
21321
21409
|
} else {
|
|
21322
|
-
task2 = getTaskWithRelations(resolvedId);
|
|
21410
|
+
task2 = applyLocalCommentPage(getTaskWithRelations(resolvedId), page);
|
|
21323
21411
|
}
|
|
21324
21412
|
if (!task2) {
|
|
21325
21413
|
handleError(new Error(`Task not found: ${id || resolvedId}`));
|
|
@@ -21995,7 +22083,7 @@ ${chalk3.cyan(sid)} ${statusColor(task2.status)} ${prioColor(task2.priority)} ${
|
|
|
21995
22083
|
}
|
|
21996
22084
|
});
|
|
21997
22085
|
}
|
|
21998
|
-
var DEFAULT_LIST_SCAN_LIMIT = 1e4;
|
|
22086
|
+
var DEFAULT_LIST_SCAN_LIMIT = 1e4, DEFAULT_CLI_COMMENT_PAGE = 100, MAX_CLI_COMMENT_PAGE = 500;
|
|
21999
22087
|
var init_task_commands = __esm(() => {
|
|
22000
22088
|
init_database();
|
|
22001
22089
|
init_projects();
|
|
@@ -38626,26 +38714,6 @@ function contextFromPrincipal(principal, body) {
|
|
|
38626
38714
|
function redactComment3(comment) {
|
|
38627
38715
|
return { ...comment, content: redactEvidenceText(comment.content) };
|
|
38628
38716
|
}
|
|
38629
|
-
function encodeCommentCursor(comment) {
|
|
38630
|
-
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
38631
|
-
}
|
|
38632
|
-
function decodeCommentCursor(value) {
|
|
38633
|
-
if (value.length > 1024)
|
|
38634
|
-
throw new Error("invalid comment cursor");
|
|
38635
|
-
let parsed;
|
|
38636
|
-
try {
|
|
38637
|
-
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
38638
|
-
} catch {
|
|
38639
|
-
throw new Error("invalid comment cursor");
|
|
38640
|
-
}
|
|
38641
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
38642
|
-
throw new Error("invalid comment cursor");
|
|
38643
|
-
const cursor = parsed;
|
|
38644
|
-
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
38645
|
-
throw new Error("invalid comment cursor");
|
|
38646
|
-
}
|
|
38647
|
-
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
38648
|
-
}
|
|
38649
38717
|
function normalizeImportSnapshot(raw) {
|
|
38650
38718
|
const body = raw && typeof raw === "object" ? raw : {};
|
|
38651
38719
|
const arr = (v) => Array.isArray(v) ? v : [];
|
package/dist/contracts.js
CHANGED
|
@@ -12044,7 +12044,7 @@ var init_tasks = __esm(() => {
|
|
|
12044
12044
|
// package.json
|
|
12045
12045
|
var package_default = {
|
|
12046
12046
|
name: "@hasna/todos",
|
|
12047
|
-
version: "0.15.
|
|
12047
|
+
version: "0.15.6",
|
|
12048
12048
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12049
12049
|
type: "module",
|
|
12050
12050
|
main: "dist/index.js",
|
package/dist/index.js
CHANGED
|
@@ -12157,7 +12157,7 @@ var init_dispatches = __esm(() => {
|
|
|
12157
12157
|
// package.json
|
|
12158
12158
|
var package_default = {
|
|
12159
12159
|
name: "@hasna/todos",
|
|
12160
|
-
version: "0.15.
|
|
12160
|
+
version: "0.15.6",
|
|
12161
12161
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12162
12162
|
type: "module",
|
|
12163
12163
|
main: "dist/index.js",
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { TaskComment } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Keyset cursor for the task-comment read model, and the pure pager that walks
|
|
4
|
+
* it. Both the `/v1` server and the CLI encode and decode the same cursor, so
|
|
5
|
+
* the codec lives here rather than beside either consumer — a second copy of
|
|
6
|
+
* this keyset logic is exactly how the two ends drift into disagreeing about
|
|
7
|
+
* what a cursor means.
|
|
8
|
+
*
|
|
9
|
+
* ORDERING CONTRACT, measured against the live deployment rather than assumed:
|
|
10
|
+
* a page carries the NEWEST `limit` comments in ASCENDING display order, so the
|
|
11
|
+
* newest comment is the LAST element. `next_cursor` encodes the FIRST (oldest)
|
|
12
|
+
* element of the page, and walking it moves toward OLDER history.
|
|
13
|
+
*/
|
|
14
|
+
export interface CommentCursor {
|
|
15
|
+
created_at: string;
|
|
16
|
+
id: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const MAX_COMMENT_CURSOR_LENGTH = 1024;
|
|
19
|
+
export declare function encodeCommentCursor(comment: Pick<TaskComment, "created_at" | "id">): string;
|
|
20
|
+
export declare function decodeCommentCursor(value: string): CommentCursor;
|
|
21
|
+
/** True when `comment` sorts strictly before `before` on the `(created_at, id)` keyset. */
|
|
22
|
+
export declare function isStrictlyOlder(comment: Pick<TaskComment, "created_at" | "id">, before: CommentCursor): boolean;
|
|
23
|
+
export interface CommentPageResult<T> {
|
|
24
|
+
comments: T[];
|
|
25
|
+
count: number;
|
|
26
|
+
has_more: boolean;
|
|
27
|
+
next_cursor: string | null;
|
|
28
|
+
limit: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Page an already-materialised, ascending comment list. Used by the local
|
|
32
|
+
* (SQLite) read path, where the whole history is in hand; the cloud path gets
|
|
33
|
+
* the identical shape from the server, which applies the same rule against the
|
|
34
|
+
* database.
|
|
35
|
+
*/
|
|
36
|
+
export declare function pageComments<T extends Pick<TaskComment, "created_at" | "id">>(all: readonly T[], options: {
|
|
37
|
+
limit: number;
|
|
38
|
+
before?: CommentCursor;
|
|
39
|
+
}): CommentPageResult<T>;
|
|
40
|
+
//# sourceMappingURL=comment-cursor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comment-cursor.d.ts","sourceRoot":"","sources":["../../src/lib/comment-cursor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,eAAO,MAAM,yBAAyB,OAAQ,CAAC;AAE/C,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,YAAY,GAAG,IAAI,CAAC,GAAG,MAAM,CAG3F;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAgBhE;AAED,2FAA2F;AAC3F,wBAAgB,eAAe,CAC7B,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,YAAY,GAAG,IAAI,CAAC,EAC/C,MAAM,EAAE,aAAa,GACpB,OAAO,CAGT;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,QAAQ,EAAE,CAAC,EAAE,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,IAAI,CAAC,WAAW,EAAE,YAAY,GAAG,IAAI,CAAC,EAC3E,GAAG,EAAE,SAAS,CAAC,EAAE,EACjB,OAAO,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAE,GACjD,iBAAiB,CAAC,CAAC,CAAC,CAetB"}
|
package/dist/mcp/index.js
CHANGED
|
@@ -34926,7 +34926,7 @@ var package_default;
|
|
|
34926
34926
|
var init_package = __esm(() => {
|
|
34927
34927
|
package_default = {
|
|
34928
34928
|
name: "@hasna/todos",
|
|
34929
|
-
version: "0.15.
|
|
34929
|
+
version: "0.15.6",
|
|
34930
34930
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
34931
34931
|
type: "module",
|
|
34932
34932
|
main: "dist/index.js",
|
|
@@ -50912,6 +50912,29 @@ var init_pr_groups = __esm(() => {
|
|
|
50912
50912
|
JSON_HEADERS = { "Content-Type": "application/json" };
|
|
50913
50913
|
});
|
|
50914
50914
|
|
|
50915
|
+
// src/lib/comment-cursor.ts
|
|
50916
|
+
function encodeCommentCursor(comment) {
|
|
50917
|
+
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
50918
|
+
}
|
|
50919
|
+
function decodeCommentCursor(value) {
|
|
50920
|
+
if (value.length > MAX_COMMENT_CURSOR_LENGTH)
|
|
50921
|
+
throw new Error("invalid comment cursor");
|
|
50922
|
+
let parsed;
|
|
50923
|
+
try {
|
|
50924
|
+
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
50925
|
+
} catch {
|
|
50926
|
+
throw new Error("invalid comment cursor");
|
|
50927
|
+
}
|
|
50928
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
50929
|
+
throw new Error("invalid comment cursor");
|
|
50930
|
+
const cursor = parsed;
|
|
50931
|
+
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
50932
|
+
throw new Error("invalid comment cursor");
|
|
50933
|
+
}
|
|
50934
|
+
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
50935
|
+
}
|
|
50936
|
+
var MAX_COMMENT_CURSOR_LENGTH = 1024;
|
|
50937
|
+
|
|
50915
50938
|
// src/server/v1.ts
|
|
50916
50939
|
var exports_v1 = {};
|
|
50917
50940
|
__export(exports_v1, {
|
|
@@ -51201,26 +51224,6 @@ function contextFromPrincipal(principal, body) {
|
|
|
51201
51224
|
function redactComment3(comment) {
|
|
51202
51225
|
return { ...comment, content: redactEvidenceText(comment.content) };
|
|
51203
51226
|
}
|
|
51204
|
-
function encodeCommentCursor(comment) {
|
|
51205
|
-
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
51206
|
-
}
|
|
51207
|
-
function decodeCommentCursor(value) {
|
|
51208
|
-
if (value.length > 1024)
|
|
51209
|
-
throw new Error("invalid comment cursor");
|
|
51210
|
-
let parsed;
|
|
51211
|
-
try {
|
|
51212
|
-
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
51213
|
-
} catch {
|
|
51214
|
-
throw new Error("invalid comment cursor");
|
|
51215
|
-
}
|
|
51216
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
51217
|
-
throw new Error("invalid comment cursor");
|
|
51218
|
-
const cursor = parsed;
|
|
51219
|
-
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
51220
|
-
throw new Error("invalid comment cursor");
|
|
51221
|
-
}
|
|
51222
|
-
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
51223
|
-
}
|
|
51224
51227
|
function normalizeImportSnapshot(raw) {
|
|
51225
51228
|
const body = raw && typeof raw === "object" ? raw : {};
|
|
51226
51229
|
const arr = (v) => Array.isArray(v) ? v : [];
|
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.6",
|
|
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",
|
package/dist/registry.js
CHANGED
|
@@ -12044,7 +12044,7 @@ var init_tasks = __esm(() => {
|
|
|
12044
12044
|
// package.json
|
|
12045
12045
|
var package_default = {
|
|
12046
12046
|
name: "@hasna/todos",
|
|
12047
|
-
version: "0.15.
|
|
12047
|
+
version: "0.15.6",
|
|
12048
12048
|
description: "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
12049
12049
|
type: "module",
|
|
12050
12050
|
main: "dist/index.js",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "@hasna/todos",
|
|
3
|
-
"packageVersion": "0.15.
|
|
3
|
+
"packageVersion": "0.15.6",
|
|
4
4
|
"repository": "https://github.com/hasna/todos.git",
|
|
5
|
-
"gitCommit": "
|
|
6
|
-
"gitTree": "
|
|
7
|
-
"sourceTreeSha256": "
|
|
8
|
-
"generatedAt": "2026-08-
|
|
5
|
+
"gitCommit": "912706df4217032e0fa328b8e63c631cbd2dbaaa",
|
|
6
|
+
"gitTree": "55ffcbf22946c2823608bf05b7db8c77c3d1837f",
|
|
7
|
+
"sourceTreeSha256": "6d97deaa19cf1aca86ae5d2ac810239a96079987884dffad727762b91dbbe660",
|
|
8
|
+
"generatedAt": "2026-08-06T09:35:27.000Z"
|
|
9
9
|
}
|
package/dist/server/index.js
CHANGED
|
@@ -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.
|
|
73
|
+
version: "0.15.6",
|
|
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",
|
|
@@ -22312,6 +22312,29 @@ var init_pr_groups = __esm(() => {
|
|
|
22312
22312
|
JSON_HEADERS = { "Content-Type": "application/json" };
|
|
22313
22313
|
});
|
|
22314
22314
|
|
|
22315
|
+
// src/lib/comment-cursor.ts
|
|
22316
|
+
function encodeCommentCursor(comment) {
|
|
22317
|
+
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
22318
|
+
}
|
|
22319
|
+
function decodeCommentCursor(value) {
|
|
22320
|
+
if (value.length > MAX_COMMENT_CURSOR_LENGTH)
|
|
22321
|
+
throw new Error("invalid comment cursor");
|
|
22322
|
+
let parsed;
|
|
22323
|
+
try {
|
|
22324
|
+
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
22325
|
+
} catch {
|
|
22326
|
+
throw new Error("invalid comment cursor");
|
|
22327
|
+
}
|
|
22328
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
22329
|
+
throw new Error("invalid comment cursor");
|
|
22330
|
+
const cursor = parsed;
|
|
22331
|
+
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
22332
|
+
throw new Error("invalid comment cursor");
|
|
22333
|
+
}
|
|
22334
|
+
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
22335
|
+
}
|
|
22336
|
+
var MAX_COMMENT_CURSOR_LENGTH = 1024;
|
|
22337
|
+
|
|
22315
22338
|
// src/server/v1.ts
|
|
22316
22339
|
var exports_v1 = {};
|
|
22317
22340
|
__export(exports_v1, {
|
|
@@ -22601,26 +22624,6 @@ function contextFromPrincipal(principal, body) {
|
|
|
22601
22624
|
function redactComment2(comment) {
|
|
22602
22625
|
return { ...comment, content: redactEvidenceText(comment.content) };
|
|
22603
22626
|
}
|
|
22604
|
-
function encodeCommentCursor(comment) {
|
|
22605
|
-
return Buffer.from(JSON.stringify({ created_at: comment.created_at, id: comment.id }), "utf8").toString("base64url");
|
|
22606
|
-
}
|
|
22607
|
-
function decodeCommentCursor(value) {
|
|
22608
|
-
if (value.length > 1024)
|
|
22609
|
-
throw new Error("invalid comment cursor");
|
|
22610
|
-
let parsed;
|
|
22611
|
-
try {
|
|
22612
|
-
parsed = JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
22613
|
-
} catch {
|
|
22614
|
-
throw new Error("invalid comment cursor");
|
|
22615
|
-
}
|
|
22616
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
22617
|
-
throw new Error("invalid comment cursor");
|
|
22618
|
-
const cursor = parsed;
|
|
22619
|
-
if (typeof cursor["created_at"] !== "string" || cursor["created_at"].length > 64 || !Number.isFinite(Date.parse(cursor["created_at"])) || typeof cursor["id"] !== "string" || !cursor["id"] || cursor["id"].length > 256) {
|
|
22620
|
-
throw new Error("invalid comment cursor");
|
|
22621
|
-
}
|
|
22622
|
-
return { created_at: cursor["created_at"], id: cursor["id"] };
|
|
22623
|
-
}
|
|
22624
22627
|
function normalizeImportSnapshot(raw) {
|
|
22625
22628
|
const body = raw && typeof raw === "object" ? raw : {};
|
|
22626
22629
|
const arr = (v) => Array.isArray(v) ? v : [];
|
package/dist/server/v1.d.ts.map
CHANGED
|
@@ -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,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;
|
|
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,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMhH,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;CACjD;AAuSD;;;;;;;;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,CAu6B1B"}
|