kanbo-cli 0.2.1 → 0.4.0

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.
Files changed (88) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/README.md +17 -46
  3. package/dist/{better-sqlite3-fU3G4xnX.cjs → better-sqlite3-DPdSZ6sH.cjs} +244 -247
  4. package/dist/cli-main.cjs +51690 -0
  5. package/dist/cli.cjs +32 -45216
  6. package/dist/dist-IHRTF-b5.cjs +2552 -0
  7. package/dist/lib/{tool-names-WfH4IURz.d.cts → approval-BsBk2xVr.d.cts} +72 -3
  8. package/dist/lib/{tool-names-3q_GEZej.d.mts → approval-LRZ6ontC.d.mts} +72 -3
  9. package/dist/lib/{board-store-BvWn9xTB.d.mts → board-store-D_Mpfb84.d.mts} +75 -2
  10. package/dist/lib/{board-store-BfszzAJB.d.cts → board-store-Dx-mw2I6.d.cts} +75 -2
  11. package/dist/lib/index.cjs +8 -2
  12. package/dist/lib/index.d.cts +202 -91
  13. package/dist/lib/index.d.mts +202 -91
  14. package/dist/lib/index.mjs +3 -3
  15. package/dist/lib/{manifest-D9nCRtXM.cjs → manifest-DcIMYvWk.cjs} +7363 -1556
  16. package/dist/lib/manifest-Dmo6IlWk.mjs +14654 -0
  17. package/dist/lib/mcp/index.cjs +166 -22
  18. package/dist/lib/mcp/index.d.cts +144 -5
  19. package/dist/lib/mcp/index.d.mts +144 -5
  20. package/dist/lib/mcp/index.mjs +162 -23
  21. package/dist/lib/{migrate-DnMjTCvu.cjs → migrate-Dca5WdYd.cjs} +144 -14
  22. package/dist/lib/{migrate-BhYi9cXw.mjs → migrate-DtBeW3Fs.mjs} +134 -16
  23. package/dist/lib/{migrations-path-Ciwan537.mjs → migrations-path-ClaYRNwk.mjs} +5 -7
  24. package/dist/lib/{migrations-path-CZxVOgeD.cjs → migrations-path-DBCE17dT.cjs} +5 -7
  25. package/dist/lib/postgres/index.cjs +2 -4
  26. package/dist/lib/postgres/index.d.cts +2 -3
  27. package/dist/lib/postgres/index.d.mts +2 -3
  28. package/dist/lib/postgres/index.mjs +2 -4
  29. package/dist/lib/{roles.sql-CvyCGt38.mjs → roles.sql-BoOZSkBp.mjs} +96 -5
  30. package/dist/lib/{roles.sql-B9rt-x4o.cjs → roles.sql-E58x7mLS.cjs} +95 -4
  31. package/dist/lib/schema-D0MyXcej.d.cts +1 -2
  32. package/dist/lib/schema-D0MyXcej.d.mts +1 -2
  33. package/dist/lib/schema-epoch-ZyumVL_A.d.cts +1 -2
  34. package/dist/lib/schema-epoch-ZyumVL_A.d.mts +1 -2
  35. package/dist/lib/sqlite/index.cjs +2 -2
  36. package/dist/lib/sqlite/index.d.cts +3 -4
  37. package/dist/lib/sqlite/index.d.mts +3 -4
  38. package/dist/lib/sqlite/index.mjs +2 -2
  39. package/dist/lib/sqlite/schema.cjs +0 -2
  40. package/dist/lib/sqlite/schema.mjs +0 -2
  41. package/dist/page/board.css +1622 -327
  42. package/dist/page/board.js +2 -2
  43. package/package.json +13 -10
  44. package/dist/better-sqlite3-fU3G4xnX.cjs.map +0 -1
  45. package/dist/cli.cjs.map +0 -1
  46. package/dist/dist-BsCwQFEl.cjs +0 -989
  47. package/dist/dist-BsCwQFEl.cjs.map +0 -1
  48. package/dist/lib/manifest-D9nCRtXM.cjs.map +0 -1
  49. package/dist/lib/manifest-DHV2fRdO.mjs +0 -8933
  50. package/dist/lib/manifest-DHV2fRdO.mjs.map +0 -1
  51. package/dist/lib/mcp/index.cjs.map +0 -1
  52. package/dist/lib/mcp/index.mjs.map +0 -1
  53. package/dist/lib/migrate-BhYi9cXw.mjs.map +0 -1
  54. package/dist/lib/migrate-DnMjTCvu.cjs.map +0 -1
  55. package/dist/lib/migrations-path-CZxVOgeD.cjs.map +0 -1
  56. package/dist/lib/migrations-path-Ciwan537.mjs.map +0 -1
  57. package/dist/lib/postgres/index.cjs.map +0 -1
  58. package/dist/lib/postgres/index.mjs.map +0 -1
  59. package/dist/lib/roles.sql-B9rt-x4o.cjs.map +0 -1
  60. package/dist/lib/roles.sql-CvyCGt38.mjs.map +0 -1
  61. package/dist/lib/sqlite/schema.cjs.map +0 -1
  62. package/dist/lib/sqlite/schema.mjs.map +0 -1
  63. package/drizzle-postgres/0000_board.sql +0 -135
  64. package/drizzle-postgres/0001_history_order.sql +0 -2
  65. package/drizzle-postgres/0002_issue_pull_requests.sql +0 -16
  66. package/drizzle-postgres/0003_milestone_start_date.sql +0 -1
  67. package/drizzle-postgres/0004_status_entry_rules.sql +0 -1
  68. package/drizzle-postgres/0005_run_external_session_ref.sql +0 -1
  69. package/drizzle-postgres/README.md +0 -61
  70. package/drizzle-postgres/meta/0000_snapshot.json +0 -1078
  71. package/drizzle-postgres/meta/0001_snapshot.json +0 -1090
  72. package/drizzle-postgres/meta/0002_snapshot.json +0 -1239
  73. package/drizzle-postgres/meta/0003_snapshot.json +0 -1245
  74. package/drizzle-postgres/meta/0004_snapshot.json +0 -1251
  75. package/drizzle-postgres/meta/0005_snapshot.json +0 -1257
  76. package/drizzle-postgres/meta/_journal.json +0 -48
  77. package/drizzle-sqlite/0000_board.sql +0 -133
  78. package/drizzle-sqlite/0001_issue_pull_requests.sql +0 -15
  79. package/drizzle-sqlite/0002_milestone_start_date.sql +0 -1
  80. package/drizzle-sqlite/0003_status_entry_rules.sql +0 -1
  81. package/drizzle-sqlite/0004_run_external_session_ref.sql +0 -1
  82. package/drizzle-sqlite/README.md +0 -67
  83. package/drizzle-sqlite/meta/0000_snapshot.json +0 -946
  84. package/drizzle-sqlite/meta/0001_snapshot.json +0 -1054
  85. package/drizzle-sqlite/meta/0002_snapshot.json +0 -1061
  86. package/drizzle-sqlite/meta/0003_snapshot.json +0 -1068
  87. package/drizzle-sqlite/meta/0004_snapshot.json +0 -1075
  88. package/drizzle-sqlite/meta/_journal.json +0 -41
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_manifest = require("../manifest-D9nCRtXM.cjs");
3
- const require_migrations_path = require("../migrations-path-CZxVOgeD.cjs");
2
+ const require_manifest = require("../manifest-DcIMYvWk.cjs");
3
+ const require_migrations_path = require("../migrations-path-DBCE17dT.cjs");
4
4
  let zod = require("zod");
5
5
  //#region src/mcp/http-transport.ts
6
6
  const IssueSchema = zod.z.object({
@@ -88,6 +88,32 @@ const SprintSchema = zod.z.object({
88
88
  })
89
89
  });
90
90
  const PrimeSchema = zod.z.object({ text: zod.z.string() });
91
+ const ACTOR_KINDS = [
92
+ "user",
93
+ "agent",
94
+ "provider-target",
95
+ "system"
96
+ ];
97
+ /** A comment as the server lists it; who wrote it by the stored kind, `system.*` markers included. */
98
+ const CardCommentSchema = zod.z.object({
99
+ id: zod.z.string(),
100
+ authorKind: zod.z.string(),
101
+ authorId: zod.z.string().nullish(),
102
+ sourceChatSessionId: zod.z.string().nullish(),
103
+ content: zod.z.string(),
104
+ createdAt: zod.z.number()
105
+ }).transform((row) => ({
106
+ ...row,
107
+ authorId: row.authorId ?? null,
108
+ sourceChatSessionId: row.sourceChatSessionId ?? null
109
+ }));
110
+ const FieldChangeSchema = zod.z.object({
111
+ field: zod.z.string(),
112
+ fromValue: zod.z.string().nullable(),
113
+ toValue: zod.z.string().nullable(),
114
+ actorKind: zod.z.enum(ACTOR_KINDS),
115
+ createdAt: zod.z.number()
116
+ });
91
117
  function createHttpTransport(input) {
92
118
  const { request } = input;
93
119
  async function readColumns() {
@@ -111,36 +137,135 @@ function createHttpTransport(input) {
111
137
  });
112
138
  return column;
113
139
  }
140
+ async function listCards(filters) {
141
+ const query = new URLSearchParams({
142
+ workspaceId: input.workspaceId(),
143
+ ...filters
144
+ });
145
+ return zod.z.array(IssueSchema).parse(await request("GET", `/issues/?${query.toString()}`));
146
+ }
147
+ /**
148
+ * The cards a query picks. A server of the `/issues` routes filters on one
149
+ * column and on a parent, and no more; the rest of the query is applied here,
150
+ * to the cards it answered with, so the answer is the one the board file gives.
151
+ *
152
+ * The server filters on a parent's id only, and an agent may name the parent
153
+ * the way it names any card — `WOR-001`, `WOR-1`, `1`. The id is asked first;
154
+ * when no card answers it, the board is read whole to learn which card the
155
+ * reference names, and a reference that names none is refused as `issue_not_found`.
156
+ */
157
+ async function cardPage(cardQuery) {
158
+ const columns = await readColumns();
159
+ const statusIds = cardQuery.columns === void 0 ? null : new Set(cardQuery.columns.map((column) => requireColumn(columns, column).id));
160
+ const filters = statusIds?.size === 1 ? { statusId: [...statusIds][0] } : {};
161
+ let parent = cardQuery.parent;
162
+ let rows = await listCards(parent === void 0 ? filters : {
163
+ ...filters,
164
+ parentIssueId: parent
165
+ });
166
+ if (parent !== void 0 && rows.length === 0) {
167
+ const board = await listCards({});
168
+ const named = findCardRow(board, parent);
169
+ if (!named) throw new require_migrations_path.BoardError("issue_not_found", { issueId: parent });
170
+ parent = named.id;
171
+ rows = board;
172
+ }
173
+ const matched = rows.filter((row) => require_manifest.matchesKanboCardQuery(row, {
174
+ ...cardQuery,
175
+ parent,
176
+ returned: void 0
177
+ }, statusIds));
178
+ const picked = cardQuery.returned === void 0 ? matched : (await withAttention(matched)).filter((row) => require_manifest.matchesKanboCardQuery(row, cardQuery, null));
179
+ const offset = cardQuery.offset ?? 0;
180
+ return {
181
+ cards: (await withAttention(picked.slice(offset, cardQuery.limit === void 0 ? void 0 : offset + cardQuery.limit))).map((row) => require_manifest.projectKanboCard(row, columns)),
182
+ total: picked.length,
183
+ offset
184
+ };
185
+ }
186
+ /**
187
+ * The cards with what a list says beside the ones a person has to look at or
188
+ * sent back — their comments read one card at a time, since the route lists
189
+ * none, and only for cards that are waiting, or neither waiting nor running.
190
+ */
191
+ async function withAttention(rows) {
192
+ return await Promise.all(rows.map(async (row) => {
193
+ if (row.attention || row.waitingFor !== "human" && row.activeRun !== null) return row;
194
+ const comments = zod.z.array(CardCommentSchema).parse(await request("GET", `/issues/${encodeURIComponent(row.id)}/comments`));
195
+ const decision = comments.filter((comment) => comment.authorKind === "system.approved" || comment.authorKind === "system.returned").at(-1);
196
+ const returned = row.waitingFor !== "human" && decision?.authorKind === "system.returned";
197
+ const latest = comments.filter((comment) => comment.authorKind !== "system.run").at(-1);
198
+ const lastComment = (row.waitingFor === "human" || returned) && latest ? require_manifest.previewComment({
199
+ ...latest,
200
+ authorKind: latest.authorKind
201
+ }) : null;
202
+ return {
203
+ ...row,
204
+ attention: {
205
+ returned,
206
+ lastComment
207
+ }
208
+ };
209
+ }));
210
+ }
211
+ /** The ready cards, a page of them; the server answers the whole queue. */
212
+ async function readyPage({ returnedLimit, ...page }) {
213
+ const query = new URLSearchParams({ workspaceId: input.workspaceId() });
214
+ const cards = zod.z.array(IssueSchema).parse(await request("GET", `/issues/ready?${query.toString()}`));
215
+ const columns = await readColumns();
216
+ const offset = page.offset ?? 0;
217
+ const ready = {
218
+ cards: cards.slice(offset, page.limit === void 0 ? void 0 : offset + page.limit).map((row) => require_manifest.projectKanboCard(row, columns)),
219
+ total: cards.length,
220
+ offset
221
+ };
222
+ return returnedLimit === void 0 ? ready : {
223
+ ...ready,
224
+ returned: await cardPage({
225
+ returned: true,
226
+ limit: returnedLimit
227
+ })
228
+ };
229
+ }
114
230
  return {
115
231
  prime: async () => PrimeSchema.parse(await request("GET", `/issues/prime?workspaceId=${encodeURIComponent(input.workspaceId())}`)),
116
- ready: async ({ limit }) => {
117
- const query = new URLSearchParams({ workspaceId: input.workspaceId() });
118
- if (limit !== void 0) query.set("limit", String(limit));
119
- const cards = zod.z.array(IssueSchema).parse(await request("GET", `/issues/ready?${query.toString()}`));
120
- const columns = await readColumns();
121
- return cards.map((row) => require_manifest.projectKanboCard(row, columns));
122
- },
232
+ ready: async ({ limit }) => (await readyPage({ limit })).cards,
233
+ readyPage,
123
234
  columns: readColumns,
124
235
  sprints: async () => zod.z.array(SprintSchema).parse(await request("GET", `/issues/sprints?workspaceId=${encodeURIComponent(input.workspaceId())}`)).map(require_manifest.projectKanboSprint),
125
- cardGet: async ({ card }) => {
236
+ cardGet: async ({ card, include = require_manifest.DEFAULT_KANBO_CARD_INCLUDES, commentLimit = 10 }) => {
126
237
  const found = IssueSchema.parse(await request("GET", `/issues/${encodeURIComponent(card)}`));
127
- const columns = await readColumns();
238
+ const wants = new Set(include);
239
+ const path = `/issues/${encodeURIComponent(found.id)}`;
128
240
  const query = new URLSearchParams({
129
241
  workspaceId: input.workspaceId(),
130
242
  parentIssueId: found.id
131
243
  });
132
- const subCards = zod.z.array(IssueSchema).parse(await request("GET", `/issues/?${query.toString()}`));
244
+ const [columns, subCards, comments, runs, history, pullRequests] = await Promise.all([
245
+ readColumns(),
246
+ wants.has("subCards") ? request("GET", `/issues/?${query.toString()}`).then((rows) => zod.z.array(IssueSchema).parse(rows)) : null,
247
+ wants.has("comments") ? request("GET", `${path}/comments`).then((rows) => zod.z.array(CardCommentSchema).parse(rows)) : null,
248
+ wants.has("runs") ? request("GET", `${path}/runs`).then((rows) => zod.z.array(RunSchema).parse(rows)) : null,
249
+ wants.has("history") ? request("GET", `${path}/field-changes`).then((rows) => zod.z.array(FieldChangeSchema).parse(rows)) : null,
250
+ wants.has("prs") ? request("GET", `${path}/pull-requests`).then((rows) => zod.z.array(PullRequestSchema).parse(rows)) : null
251
+ ]);
133
252
  return {
134
253
  ...require_manifest.projectKanboCard(found, columns),
135
- subCards: subCards.map((row) => require_manifest.projectKanboSubCard(row, columns))
254
+ ...subCards ? { subCards: subCards.map((row) => require_manifest.projectKanboSubCard(row, columns)) } : {},
255
+ ...comments ? {
256
+ comments: comments.slice(-commentLimit).map(require_manifest.projectKanboCardComment),
257
+ commentCount: comments.length
258
+ } : {},
259
+ ...runs ? { runs: runs.map(require_manifest.projectKanboRun) } : {},
260
+ ...history ? { history: history.map(require_manifest.projectKanboFieldChange) } : {},
261
+ ...pullRequests ? { pullRequests: pullRequests.map(require_manifest.projectKanboPullRequest) } : {}
136
262
  };
137
263
  },
138
- cardList: async ({ column, limit }) => {
139
- const columns = await readColumns();
140
- const query = new URLSearchParams({ workspaceId: input.workspaceId() });
141
- if (column) query.set("statusId", requireColumn(columns, column).id);
142
- return zod.z.array(IssueSchema).parse(await request("GET", `/issues/?${query.toString()}`)).slice(0, limit ?? Number.POSITIVE_INFINITY).map((row) => require_manifest.projectKanboCard(row, columns));
143
- },
264
+ cardList: async ({ column, limit }) => (await cardPage({
265
+ columns: column ? [column] : void 0,
266
+ limit
267
+ })).cards,
268
+ cardPage,
144
269
  cardCreate: async ({ title, description, column, parent, executionMode }) => await projectOne(await request("POST", "/issues/", {
145
270
  workspaceId: input.workspaceId(),
146
271
  ...title !== void 0 ? { title } : {},
@@ -149,7 +274,10 @@ function createHttpTransport(input) {
149
274
  ...parent !== void 0 ? { parentIssueId: parent } : {},
150
275
  ...executionMode !== void 0 ? { executionMode } : {}
151
276
  })),
152
- cardUpdate: async ({ card, ...patch }) => await projectOne(await request("PATCH", `/issues/${encodeURIComponent(card)}`, patch)),
277
+ cardUpdate: async ({ card, parent, ...patch }) => await projectOne(await request("PATCH", `/issues/${encodeURIComponent(card)}`, {
278
+ ...patch,
279
+ ...parent !== void 0 ? { parentIssueId: parent } : {}
280
+ })),
153
281
  cardMove: async ({ card, column }) => await projectOne(await request("PATCH", `/issues/${encodeURIComponent(card)}/status/${encodeURIComponent(column)}`)),
154
282
  cardComment: async ({ card, content }) => CommentSchema.parse(await request("POST", `/issues/${encodeURIComponent(card)}/comments`, { content })),
155
283
  cardLinkPullRequest: async ({ card, url }) => require_manifest.projectKanboPullRequest(PullRequestSchema.parse(await request("POST", `/issues/${encodeURIComponent(card)}/pull-requests`, { url }))),
@@ -168,9 +296,25 @@ function createHttpTransport(input) {
168
296
  })))
169
297
  };
170
298
  }
299
+ /**
300
+ * The card a reference names among cards already read, the way the board file
301
+ * resolves one: its id, its number, or its key without the padding (`WOR-1`).
302
+ */
303
+ function findCardRow(rows, reference) {
304
+ const trimmed = reference.trim();
305
+ const byId = rows.find((row) => row.id === trimmed);
306
+ if (byId) return byId;
307
+ const key = /^(?:(.+)-)?(\d+)$/.exec(trimmed);
308
+ if (!key) return;
309
+ const [, prefix, digits] = key;
310
+ return rows.find((row) => row.number === Number(digits) && (prefix === void 0 || row.id.slice(0, row.id.lastIndexOf("-")).toUpperCase() === prefix.toUpperCase()));
311
+ }
171
312
  //#endregion
313
+ exports.DEFAULT_KANBO_CARD_INCLUDES = require_manifest.DEFAULT_KANBO_CARD_INCLUDES;
314
+ exports.DEFAULT_KANBO_COMMENT_LIMIT = require_manifest.DEFAULT_KANBO_COMMENT_LIMIT;
172
315
  exports.KANBO_CAPABILITIES_MARKDOWN_RESOURCE_URI = require_manifest.KANBO_CAPABILITIES_MARKDOWN_RESOURCE_URI;
173
316
  exports.KANBO_CAPABILITIES_RESOURCE_URI = require_manifest.KANBO_CAPABILITIES_RESOURCE_URI;
317
+ exports.KANBO_CARD_INCLUDES = require_manifest.KANBO_CARD_INCLUDES;
174
318
  exports.KANBO_MCP_INSTRUCTIONS = require_manifest.KANBO_MCP_INSTRUCTIONS;
175
319
  exports.KANBO_MCP_SERVER_NAME = require_manifest.KANBO_MCP_SERVER_NAME;
176
320
  exports.KANBO_TOOLS = require_manifest.KANBO_TOOLS;
@@ -179,7 +323,7 @@ exports.KANBO_TOOL_NAMES = require_manifest.KANBO_TOOL_NAMES;
179
323
  exports.buildKanboTools = require_manifest.buildKanboTools;
180
324
  exports.createHttpTransport = createHttpTransport;
181
325
  exports.createKanboMcpServer = require_manifest.createKanboMcpServer;
326
+ exports.matchesKanboCardQuery = require_manifest.matchesKanboCardQuery;
327
+ exports.pageOf = require_manifest.pageOf;
182
328
  exports.registerKanboCapabilitiesResources = require_manifest.registerKanboCapabilitiesResources;
183
329
  exports.registerKanboTools = require_manifest.registerKanboTools;
184
-
185
- //# sourceMappingURL=index.cjs.map
@@ -1,5 +1,5 @@
1
1
  import { s as IssueRun, t as Issue } from "../schema-D0MyXcej.cjs";
2
- import { i as KanboToolName, n as KANBO_TOOL_NAMES, r as KanboToolCliEquivalent, s as EntryRule, t as KANBO_TOOL_CLI_EQUIVALENTS } from "../tool-names-WfH4IURz.cjs";
2
+ import { _ as EntryRule, d as KANBO_TOOL_CLI_EQUIVALENTS, f as KANBO_TOOL_NAMES, i as IssueActorKind, m as KanboToolName, p as KanboToolCliEquivalent, r as CardLastComment } from "../approval-BsBk2xVr.cjs";
3
3
  import { z } from "zod";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
@@ -40,13 +40,88 @@ interface KanboCardResult {
40
40
  /** The run going on right now, `null` when nobody is working on the card. */
41
41
  activeRun: KanboActiveRunResult | null;
42
42
  updatedAt: number;
43
+ /** Present on a list's card a person sent back that nobody has picked up again. */
44
+ returned?: true;
45
+ /** On a list's card waiting for a person or returned: its latest comment, cut short. */
46
+ lastComment?: CardLastComment;
43
47
  }
48
+ /** What `kanbo_card_get` may bring along with the card. */
49
+ export declare const KANBO_CARD_INCLUDES: readonly ['comments', 'subCards', 'runs', 'history', 'prs'];
50
+ type KanboCardInclude = typeof KANBO_CARD_INCLUDES[number];
51
+ /** What a card read brings along when the caller does not say: its latest comments and its sub-cards. */
52
+ export declare const DEFAULT_KANBO_CARD_INCLUDES: readonly KanboCardInclude[];
53
+ /** How many of its latest comments a card read brings along when the caller does not say. */
54
+ export declare const DEFAULT_KANBO_COMMENT_LIMIT = 10;
44
55
  /**
45
56
  * A card read on its own, as `kanbo_card_get` hands it to an agent: the card,
46
- * and the sub-cards under it in board order. Its parent is `parentIssueId`.
57
+ * and whatever the read was asked to bring along — the sub-cards under it in
58
+ * board order, its latest comments, its runs, its field history, the pull
59
+ * requests it names. Its parent is `parentIssueId`.
47
60
  */
48
61
  interface KanboCardDetailResult extends KanboCardResult {
49
- subCards: Pick<KanboCardResult, 'id' | 'title' | 'columnSlug'>[];
62
+ subCards?: Pick<KanboCardResult, 'id' | 'title' | 'columnSlug'>[];
63
+ /** The latest comments, oldest of them first; `commentCount` says how many the card has in all. */
64
+ comments?: KanboCardCommentResult[];
65
+ commentCount?: number;
66
+ /** Every run, first attempt first. */
67
+ runs?: KanboRunResult[];
68
+ /** Every tracked field change, oldest first. */
69
+ history?: KanboFieldChangeResult[];
70
+ pullRequests?: KanboPullRequestResult[];
71
+ }
72
+ /** A comment as a card read lists it: who wrote it — a person, an agent or the board — and what it says. */
73
+ interface KanboCardCommentResult {
74
+ id: string;
75
+ author: IssueActorKind;
76
+ /** The name behind it: a person's or an agent's id, an outside writer's name, `kanbo` for the board's own lines. */
77
+ by: string;
78
+ content: string;
79
+ createdAt: number;
80
+ }
81
+ /** One change to a tracked field of a card, and who made it. */
82
+ interface KanboFieldChangeResult {
83
+ field: string;
84
+ from: string | null;
85
+ to: string | null;
86
+ actor: IssueActorKind;
87
+ createdAt: number;
88
+ }
89
+ /**
90
+ * Which cards `kanbo_card_list` picks, and which page of them. Every filter is
91
+ * optional and they all apply together.
92
+ */
93
+ interface KanboCardQuery {
94
+ /** Cards in any of these columns, by slug or name. */
95
+ columns?: string[];
96
+ /** `true`: only cards waiting for a person; `false`: only cards waiting for no one. */
97
+ waitingForPerson?: boolean;
98
+ /** Only the sub-cards of this card, by its id. */
99
+ parent?: string;
100
+ /** `true`: only cards an agent is working on now; `false`: only cards nobody is. */
101
+ hasActiveRun?: boolean;
102
+ /** `true`: only cards a person sent back that nobody has picked up again; `false`: every other card. */
103
+ returned?: boolean;
104
+ /** Cards whose id, title or description contains this text, ignoring case. */
105
+ text?: string;
106
+ /** Cards changed at or after this moment, in unix seconds. */
107
+ updatedSince?: number;
108
+ /** Cards carrying every one of these labels. */
109
+ labels?: string[];
110
+ /** Cards of any of these priorities. */
111
+ priority?: Issue['priority'][];
112
+ offset?: number;
113
+ /** How many cards to return; every one picked when absent. */
114
+ limit?: number;
115
+ }
116
+ /** One page of cards, and how many the question picks in all. */
117
+ interface KanboCardPage {
118
+ cards: KanboCardResult[];
119
+ total: number;
120
+ offset: number;
121
+ }
122
+ /** The ready cards, with the returned ones when they were asked for. */
123
+ interface KanboReadyPage extends KanboCardPage {
124
+ returned?: KanboCardPage;
50
125
  }
51
126
  /** The run of a card that is going on right now. */
52
127
  interface KanboActiveRunResult {
@@ -143,6 +218,8 @@ interface KanboCardUpdateInput {
143
218
  priority?: Issue['priority'];
144
219
  labels?: string[];
145
220
  executionMode?: Issue['executionMode'];
221
+ /** The card to put this one under; `null` makes it a top-level card, and absent leaves it where it is. */
222
+ parent?: string | null;
146
223
  }
147
224
  /** What `kanbo_run_start` records about a launch. */
148
225
  interface KanboRunStartInput {
@@ -167,15 +244,30 @@ interface KanboToolTransport {
167
244
  ready: (input: {
168
245
  limit?: number;
169
246
  }) => Promise<KanboCardResult[]>;
247
+ /**
248
+ * One page of the ready cards, and how many are ready in all — and, when
249
+ * `returnedLimit` is given, up to that many cards a person sent back
250
+ * (`KanboCardQuery.returned`), which an agent continues before anything new.
251
+ */
252
+ readyPage: (input: {
253
+ limit?: number;
254
+ offset?: number;
255
+ returnedLimit?: number;
256
+ }) => Promise<KanboReadyPage>;
170
257
  columns: () => Promise<KanboColumnResult[]>;
171
258
  sprints: () => Promise<KanboSprintResult[]>;
259
+ /** The card, with what `include` names — `DEFAULT_KANBO_CARD_INCLUDES` when absent. */
172
260
  cardGet: (input: {
173
261
  card: string;
262
+ include?: readonly KanboCardInclude[];
263
+ commentLimit?: number;
174
264
  }) => Promise<KanboCardDetailResult>;
175
265
  cardList: (input: {
176
266
  column?: string;
177
267
  limit?: number;
178
268
  }) => Promise<KanboCardResult[]>;
269
+ /** One page of the cards a query picks, and how many it picks in all. */
270
+ cardPage: (input: KanboCardQuery) => Promise<KanboCardPage>;
179
271
  cardCreate: (input: KanboCardCreateInput) => Promise<KanboCardResult>;
180
272
  cardUpdate: (input: KanboCardUpdateInput) => Promise<KanboCardResult>;
181
273
  cardMove: (input: {
@@ -204,6 +296,44 @@ interface KanboToolTransport {
204
296
  runStart: (input: KanboRunStartInput) => Promise<KanboRunResult>;
205
297
  runFinish: (input: KanboRunFinishInput) => Promise<KanboRunResult>;
206
298
  }
299
+ /**
300
+ * A card as either transport already has it: the row's own fields with the
301
+ * labels decoded, plus what the run registry says about it.
302
+ */
303
+ interface KanboCardFacts {
304
+ id: string;
305
+ number: number;
306
+ title: string;
307
+ description: string | null;
308
+ statusId: string | null;
309
+ statusLine: string | null;
310
+ waitingFor: 'human' | null;
311
+ priority: Issue['priority'];
312
+ labels: string[];
313
+ executionMode: Issue['executionMode'];
314
+ parentIssueId: string | null;
315
+ updatedAt: number;
316
+ attemptCount: number;
317
+ activeRun: KanboActiveRunResult | null;
318
+ /** What a list says beside a card a person has to look at, or sent back; absent where nobody asked. */
319
+ attention?: {
320
+ returned: boolean;
321
+ lastComment: CardLastComment | null;
322
+ };
323
+ }
324
+ /**
325
+ * Does the card answer the query? The filters of `KanboCardQuery`, applied to
326
+ * a card already read — for a transport whose server filters on less than the
327
+ * query names. `statusIds` are the query's columns, already resolved.
328
+ */
329
+ export declare function matchesKanboCardQuery(card: KanboCardFacts & {
330
+ description: string | null;
331
+ }, query: KanboCardQuery, statusIds: ReadonlySet<string> | null): boolean;
332
+ /** A page cut out of cards already picked, in the order they were picked. */
333
+ export declare function pageOf(cards: KanboCardResult[], input: {
334
+ offset?: number;
335
+ limit?: number;
336
+ }): KanboCardPage;
207
337
  //#endregion
208
338
  //#region src/mcp/http-transport.d.ts
209
339
  /**
@@ -299,7 +429,17 @@ interface KanboTool {
299
429
  name: KanboToolName;
300
430
  title: string;
301
431
  description: string;
432
+ /** The arguments under their canonical names — what the tool publishes and the manifest lists. */
302
433
  inputSchema: KanboToolShape;
434
+ /**
435
+ * What the MCP server registers: the same JSON Schema as `inputSchema`, but
436
+ * accepting anything, so a call with a wrong or aliased argument reaches
437
+ * `run` — which answers it in a sentence — instead of the server's own
438
+ * validation dump.
439
+ */
440
+ registrationSchema: z.ZodType;
441
+ /** Other names each argument is accepted under, canonical name first. */
442
+ aliases: Readonly<Record<string, readonly string[]>>;
303
443
  run: (transport: KanboToolTransport, input: unknown) => Promise<KanboToolResult>;
304
444
  }
305
445
  //#endregion
@@ -359,5 +499,4 @@ export declare function registerKanboTools(server: McpServer, transport: KanboTo
359
499
  */
360
500
  export declare function createKanboMcpServer(transport: KanboToolTransport, options: KanboToolOptions): McpServer;
361
501
  //#endregion
362
- export { KANBO_TOOL_CLI_EQUIVALENTS, KANBO_TOOL_NAMES, type KanboActiveRunResult, type KanboCardResult, type KanboColumnResult, type KanboCommentResult, type KanboHttpRequest, type KanboHttpTransportInput, type KanboPullRequestResult, type KanboRunResult, type KanboTool, type KanboToolCliEquivalent, type KanboToolName, type KanboToolOptions, type KanboToolRegistration, type KanboToolResult, type KanboToolTransport };
363
- //# sourceMappingURL=index.d.cts.map
502
+ export { KANBO_TOOL_CLI_EQUIVALENTS, KANBO_TOOL_NAMES, type KanboActiveRunResult, type KanboCardCommentResult, type KanboCardCreateInput, type KanboCardDetailResult, type KanboCardFacts, type KanboCardInclude, type KanboCardPage, type KanboCardQuery, type KanboCardResult, type KanboCardUpdateInput, type KanboColumnResult, type KanboCommentResult, type KanboFieldChangeResult, type KanboHttpRequest, type KanboHttpTransportInput, type KanboPullRequestResult, type KanboReadyPage, type KanboRunFinishInput, type KanboRunResult, type KanboRunStartInput, type KanboSprintResult, type KanboTool, type KanboToolCliEquivalent, type KanboToolName, type KanboToolOptions, type KanboToolRegistration, type KanboToolResult, type KanboToolTransport };
@@ -1,5 +1,5 @@
1
1
  import { s as IssueRun, t as Issue } from "../schema-D0MyXcej.mjs";
2
- import { i as KanboToolName, n as KANBO_TOOL_NAMES, r as KanboToolCliEquivalent, s as EntryRule, t as KANBO_TOOL_CLI_EQUIVALENTS } from "../tool-names-3q_GEZej.mjs";
2
+ import { _ as EntryRule, d as KANBO_TOOL_CLI_EQUIVALENTS, f as KANBO_TOOL_NAMES, i as IssueActorKind, m as KanboToolName, p as KanboToolCliEquivalent, r as CardLastComment } from "../approval-LRZ6ontC.mjs";
3
3
  import { z } from "zod";
4
4
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
5
5
  import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
@@ -40,13 +40,88 @@ interface KanboCardResult {
40
40
  /** The run going on right now, `null` when nobody is working on the card. */
41
41
  activeRun: KanboActiveRunResult | null;
42
42
  updatedAt: number;
43
+ /** Present on a list's card a person sent back that nobody has picked up again. */
44
+ returned?: true;
45
+ /** On a list's card waiting for a person or returned: its latest comment, cut short. */
46
+ lastComment?: CardLastComment;
43
47
  }
48
+ /** What `kanbo_card_get` may bring along with the card. */
49
+ export declare const KANBO_CARD_INCLUDES: readonly ['comments', 'subCards', 'runs', 'history', 'prs'];
50
+ type KanboCardInclude = typeof KANBO_CARD_INCLUDES[number];
51
+ /** What a card read brings along when the caller does not say: its latest comments and its sub-cards. */
52
+ export declare const DEFAULT_KANBO_CARD_INCLUDES: readonly KanboCardInclude[];
53
+ /** How many of its latest comments a card read brings along when the caller does not say. */
54
+ export declare const DEFAULT_KANBO_COMMENT_LIMIT = 10;
44
55
  /**
45
56
  * A card read on its own, as `kanbo_card_get` hands it to an agent: the card,
46
- * and the sub-cards under it in board order. Its parent is `parentIssueId`.
57
+ * and whatever the read was asked to bring along — the sub-cards under it in
58
+ * board order, its latest comments, its runs, its field history, the pull
59
+ * requests it names. Its parent is `parentIssueId`.
47
60
  */
48
61
  interface KanboCardDetailResult extends KanboCardResult {
49
- subCards: Pick<KanboCardResult, 'id' | 'title' | 'columnSlug'>[];
62
+ subCards?: Pick<KanboCardResult, 'id' | 'title' | 'columnSlug'>[];
63
+ /** The latest comments, oldest of them first; `commentCount` says how many the card has in all. */
64
+ comments?: KanboCardCommentResult[];
65
+ commentCount?: number;
66
+ /** Every run, first attempt first. */
67
+ runs?: KanboRunResult[];
68
+ /** Every tracked field change, oldest first. */
69
+ history?: KanboFieldChangeResult[];
70
+ pullRequests?: KanboPullRequestResult[];
71
+ }
72
+ /** A comment as a card read lists it: who wrote it — a person, an agent or the board — and what it says. */
73
+ interface KanboCardCommentResult {
74
+ id: string;
75
+ author: IssueActorKind;
76
+ /** The name behind it: a person's or an agent's id, an outside writer's name, `kanbo` for the board's own lines. */
77
+ by: string;
78
+ content: string;
79
+ createdAt: number;
80
+ }
81
+ /** One change to a tracked field of a card, and who made it. */
82
+ interface KanboFieldChangeResult {
83
+ field: string;
84
+ from: string | null;
85
+ to: string | null;
86
+ actor: IssueActorKind;
87
+ createdAt: number;
88
+ }
89
+ /**
90
+ * Which cards `kanbo_card_list` picks, and which page of them. Every filter is
91
+ * optional and they all apply together.
92
+ */
93
+ interface KanboCardQuery {
94
+ /** Cards in any of these columns, by slug or name. */
95
+ columns?: string[];
96
+ /** `true`: only cards waiting for a person; `false`: only cards waiting for no one. */
97
+ waitingForPerson?: boolean;
98
+ /** Only the sub-cards of this card, by its id. */
99
+ parent?: string;
100
+ /** `true`: only cards an agent is working on now; `false`: only cards nobody is. */
101
+ hasActiveRun?: boolean;
102
+ /** `true`: only cards a person sent back that nobody has picked up again; `false`: every other card. */
103
+ returned?: boolean;
104
+ /** Cards whose id, title or description contains this text, ignoring case. */
105
+ text?: string;
106
+ /** Cards changed at or after this moment, in unix seconds. */
107
+ updatedSince?: number;
108
+ /** Cards carrying every one of these labels. */
109
+ labels?: string[];
110
+ /** Cards of any of these priorities. */
111
+ priority?: Issue['priority'][];
112
+ offset?: number;
113
+ /** How many cards to return; every one picked when absent. */
114
+ limit?: number;
115
+ }
116
+ /** One page of cards, and how many the question picks in all. */
117
+ interface KanboCardPage {
118
+ cards: KanboCardResult[];
119
+ total: number;
120
+ offset: number;
121
+ }
122
+ /** The ready cards, with the returned ones when they were asked for. */
123
+ interface KanboReadyPage extends KanboCardPage {
124
+ returned?: KanboCardPage;
50
125
  }
51
126
  /** The run of a card that is going on right now. */
52
127
  interface KanboActiveRunResult {
@@ -143,6 +218,8 @@ interface KanboCardUpdateInput {
143
218
  priority?: Issue['priority'];
144
219
  labels?: string[];
145
220
  executionMode?: Issue['executionMode'];
221
+ /** The card to put this one under; `null` makes it a top-level card, and absent leaves it where it is. */
222
+ parent?: string | null;
146
223
  }
147
224
  /** What `kanbo_run_start` records about a launch. */
148
225
  interface KanboRunStartInput {
@@ -167,15 +244,30 @@ interface KanboToolTransport {
167
244
  ready: (input: {
168
245
  limit?: number;
169
246
  }) => Promise<KanboCardResult[]>;
247
+ /**
248
+ * One page of the ready cards, and how many are ready in all — and, when
249
+ * `returnedLimit` is given, up to that many cards a person sent back
250
+ * (`KanboCardQuery.returned`), which an agent continues before anything new.
251
+ */
252
+ readyPage: (input: {
253
+ limit?: number;
254
+ offset?: number;
255
+ returnedLimit?: number;
256
+ }) => Promise<KanboReadyPage>;
170
257
  columns: () => Promise<KanboColumnResult[]>;
171
258
  sprints: () => Promise<KanboSprintResult[]>;
259
+ /** The card, with what `include` names — `DEFAULT_KANBO_CARD_INCLUDES` when absent. */
172
260
  cardGet: (input: {
173
261
  card: string;
262
+ include?: readonly KanboCardInclude[];
263
+ commentLimit?: number;
174
264
  }) => Promise<KanboCardDetailResult>;
175
265
  cardList: (input: {
176
266
  column?: string;
177
267
  limit?: number;
178
268
  }) => Promise<KanboCardResult[]>;
269
+ /** One page of the cards a query picks, and how many it picks in all. */
270
+ cardPage: (input: KanboCardQuery) => Promise<KanboCardPage>;
179
271
  cardCreate: (input: KanboCardCreateInput) => Promise<KanboCardResult>;
180
272
  cardUpdate: (input: KanboCardUpdateInput) => Promise<KanboCardResult>;
181
273
  cardMove: (input: {
@@ -204,6 +296,44 @@ interface KanboToolTransport {
204
296
  runStart: (input: KanboRunStartInput) => Promise<KanboRunResult>;
205
297
  runFinish: (input: KanboRunFinishInput) => Promise<KanboRunResult>;
206
298
  }
299
+ /**
300
+ * A card as either transport already has it: the row's own fields with the
301
+ * labels decoded, plus what the run registry says about it.
302
+ */
303
+ interface KanboCardFacts {
304
+ id: string;
305
+ number: number;
306
+ title: string;
307
+ description: string | null;
308
+ statusId: string | null;
309
+ statusLine: string | null;
310
+ waitingFor: 'human' | null;
311
+ priority: Issue['priority'];
312
+ labels: string[];
313
+ executionMode: Issue['executionMode'];
314
+ parentIssueId: string | null;
315
+ updatedAt: number;
316
+ attemptCount: number;
317
+ activeRun: KanboActiveRunResult | null;
318
+ /** What a list says beside a card a person has to look at, or sent back; absent where nobody asked. */
319
+ attention?: {
320
+ returned: boolean;
321
+ lastComment: CardLastComment | null;
322
+ };
323
+ }
324
+ /**
325
+ * Does the card answer the query? The filters of `KanboCardQuery`, applied to
326
+ * a card already read — for a transport whose server filters on less than the
327
+ * query names. `statusIds` are the query's columns, already resolved.
328
+ */
329
+ export declare function matchesKanboCardQuery(card: KanboCardFacts & {
330
+ description: string | null;
331
+ }, query: KanboCardQuery, statusIds: ReadonlySet<string> | null): boolean;
332
+ /** A page cut out of cards already picked, in the order they were picked. */
333
+ export declare function pageOf(cards: KanboCardResult[], input: {
334
+ offset?: number;
335
+ limit?: number;
336
+ }): KanboCardPage;
207
337
  //#endregion
208
338
  //#region src/mcp/http-transport.d.ts
209
339
  /**
@@ -299,7 +429,17 @@ interface KanboTool {
299
429
  name: KanboToolName;
300
430
  title: string;
301
431
  description: string;
432
+ /** The arguments under their canonical names — what the tool publishes and the manifest lists. */
302
433
  inputSchema: KanboToolShape;
434
+ /**
435
+ * What the MCP server registers: the same JSON Schema as `inputSchema`, but
436
+ * accepting anything, so a call with a wrong or aliased argument reaches
437
+ * `run` — which answers it in a sentence — instead of the server's own
438
+ * validation dump.
439
+ */
440
+ registrationSchema: z.ZodType;
441
+ /** Other names each argument is accepted under, canonical name first. */
442
+ aliases: Readonly<Record<string, readonly string[]>>;
303
443
  run: (transport: KanboToolTransport, input: unknown) => Promise<KanboToolResult>;
304
444
  }
305
445
  //#endregion
@@ -359,5 +499,4 @@ export declare function registerKanboTools(server: McpServer, transport: KanboTo
359
499
  */
360
500
  export declare function createKanboMcpServer(transport: KanboToolTransport, options: KanboToolOptions): McpServer;
361
501
  //#endregion
362
- export { KANBO_TOOL_CLI_EQUIVALENTS, KANBO_TOOL_NAMES, type KanboActiveRunResult, type KanboCardResult, type KanboColumnResult, type KanboCommentResult, type KanboHttpRequest, type KanboHttpTransportInput, type KanboPullRequestResult, type KanboRunResult, type KanboTool, type KanboToolCliEquivalent, type KanboToolName, type KanboToolOptions, type KanboToolRegistration, type KanboToolResult, type KanboToolTransport };
363
- //# sourceMappingURL=index.d.mts.map
502
+ export { KANBO_TOOL_CLI_EQUIVALENTS, KANBO_TOOL_NAMES, type KanboActiveRunResult, type KanboCardCommentResult, type KanboCardCreateInput, type KanboCardDetailResult, type KanboCardFacts, type KanboCardInclude, type KanboCardPage, type KanboCardQuery, type KanboCardResult, type KanboCardUpdateInput, type KanboColumnResult, type KanboCommentResult, type KanboFieldChangeResult, type KanboHttpRequest, type KanboHttpTransportInput, type KanboPullRequestResult, type KanboReadyPage, type KanboRunFinishInput, type KanboRunResult, type KanboRunStartInput, type KanboSprintResult, type KanboTool, type KanboToolCliEquivalent, type KanboToolName, type KanboToolOptions, type KanboToolRegistration, type KanboToolResult, type KanboToolTransport };