@omnicoreos/planka-mcp 0.2.0 → 0.3.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 (195) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.claude-plugin/marketplace.json +26 -0
  3. package/.claude-plugin/plugin.json +45 -0
  4. package/.codex-plugin/mcp.json +16 -0
  5. package/.codex-plugin/plugin.json +27 -0
  6. package/.mcp.json +17 -0
  7. package/CHANGELOG.md +510 -0
  8. package/README.es.md +294 -55
  9. package/README.md +293 -55
  10. package/dist/cli/init.d.ts +101 -0
  11. package/dist/cli/init.d.ts.map +1 -0
  12. package/dist/cli/init.js +481 -0
  13. package/dist/cli/init.js.map +1 -0
  14. package/dist/client.d.ts +32 -4
  15. package/dist/client.d.ts.map +1 -1
  16. package/dist/client.js +106 -32
  17. package/dist/client.js.map +1 -1
  18. package/dist/config/policy.d.ts +82 -0
  19. package/dist/config/policy.d.ts.map +1 -0
  20. package/dist/config/policy.js +226 -0
  21. package/dist/config/policy.js.map +1 -0
  22. package/dist/errors.d.ts +5 -1
  23. package/dist/errors.d.ts.map +1 -1
  24. package/dist/errors.js +62 -5
  25. package/dist/errors.js.map +1 -1
  26. package/dist/identity.generated.d.ts +2 -1
  27. package/dist/identity.generated.d.ts.map +1 -1
  28. package/dist/identity.generated.js +2 -1
  29. package/dist/identity.generated.js.map +1 -1
  30. package/dist/index.js +85 -10
  31. package/dist/index.js.map +1 -1
  32. package/dist/instructions.d.ts +21 -0
  33. package/dist/instructions.d.ts.map +1 -0
  34. package/dist/instructions.js +37 -0
  35. package/dist/instructions.js.map +1 -0
  36. package/dist/operations/actions.d.ts +654 -0
  37. package/dist/operations/actions.d.ts.map +1 -0
  38. package/dist/operations/actions.js +154 -0
  39. package/dist/operations/actions.js.map +1 -0
  40. package/dist/operations/archive.d.ts +28 -0
  41. package/dist/operations/archive.d.ts.map +1 -0
  42. package/dist/operations/archive.js +74 -0
  43. package/dist/operations/archive.js.map +1 -0
  44. package/dist/operations/attachments.d.ts +1 -1
  45. package/dist/operations/attachments.d.ts.map +1 -1
  46. package/dist/operations/attachments.js +3 -1
  47. package/dist/operations/attachments.js.map +1 -1
  48. package/dist/operations/board-id.d.ts +1 -1
  49. package/dist/operations/board-id.d.ts.map +1 -1
  50. package/dist/operations/board-id.js +13 -7
  51. package/dist/operations/board-id.js.map +1 -1
  52. package/dist/operations/boards.d.ts +96 -19
  53. package/dist/operations/boards.d.ts.map +1 -1
  54. package/dist/operations/boards.js +377 -93
  55. package/dist/operations/boards.js.map +1 -1
  56. package/dist/operations/card-brief.d.ts +91 -0
  57. package/dist/operations/card-brief.d.ts.map +1 -0
  58. package/dist/operations/card-brief.js +79 -0
  59. package/dist/operations/card-brief.js.map +1 -0
  60. package/dist/operations/cards.d.ts +34 -9
  61. package/dist/operations/cards.d.ts.map +1 -1
  62. package/dist/operations/cards.js +60 -14
  63. package/dist/operations/cards.js.map +1 -1
  64. package/dist/operations/comments.d.ts +61 -4
  65. package/dist/operations/comments.d.ts.map +1 -1
  66. package/dist/operations/comments.js +91 -8
  67. package/dist/operations/comments.js.map +1 -1
  68. package/dist/operations/duplicate.d.ts +16 -0
  69. package/dist/operations/duplicate.d.ts.map +1 -0
  70. package/dist/operations/duplicate.js +43 -0
  71. package/dist/operations/duplicate.js.map +1 -0
  72. package/dist/operations/labels.d.ts +1 -1
  73. package/dist/operations/labels.d.ts.map +1 -1
  74. package/dist/operations/labels.js +7 -4
  75. package/dist/operations/labels.js.map +1 -1
  76. package/dist/operations/lists.d.ts +63 -1
  77. package/dist/operations/lists.d.ts.map +1 -1
  78. package/dist/operations/lists.js +97 -2
  79. package/dist/operations/lists.js.map +1 -1
  80. package/dist/operations/members.d.ts +39 -0
  81. package/dist/operations/members.d.ts.map +1 -0
  82. package/dist/operations/members.js +107 -0
  83. package/dist/operations/members.js.map +1 -0
  84. package/dist/operations/projects.d.ts +16 -0
  85. package/dist/operations/projects.d.ts.map +1 -1
  86. package/dist/operations/projects.js +54 -9
  87. package/dist/operations/projects.js.map +1 -1
  88. package/dist/operations/tasks.d.ts +1 -1
  89. package/dist/operations/tasks.d.ts.map +1 -1
  90. package/dist/operations/tasks.js +5 -3
  91. package/dist/operations/tasks.js.map +1 -1
  92. package/dist/operations/users.d.ts +123 -0
  93. package/dist/operations/users.d.ts.map +1 -0
  94. package/dist/operations/users.js +180 -0
  95. package/dist/operations/users.js.map +1 -0
  96. package/dist/operations/verify.d.ts +84 -0
  97. package/dist/operations/verify.d.ts.map +1 -0
  98. package/dist/operations/verify.js +124 -0
  99. package/dist/operations/verify.js.map +1 -0
  100. package/dist/prompts.d.ts +48 -0
  101. package/dist/prompts.d.ts.map +1 -0
  102. package/dist/prompts.js +155 -0
  103. package/dist/prompts.js.map +1 -0
  104. package/dist/resources.d.ts +38 -0
  105. package/dist/resources.d.ts.map +1 -0
  106. package/dist/resources.js +127 -0
  107. package/dist/resources.js.map +1 -0
  108. package/dist/schemas/entities.d.ts +115 -24
  109. package/dist/schemas/entities.d.ts.map +1 -1
  110. package/dist/schemas/entities.js +48 -0
  111. package/dist/schemas/entities.js.map +1 -1
  112. package/dist/schemas/requests.d.ts +121 -46
  113. package/dist/schemas/requests.d.ts.map +1 -1
  114. package/dist/schemas/requests.js +57 -12
  115. package/dist/schemas/requests.js.map +1 -1
  116. package/dist/schemas/responses.d.ts +541 -186
  117. package/dist/schemas/responses.d.ts.map +1 -1
  118. package/dist/schemas/responses.js +13 -2
  119. package/dist/schemas/responses.js.map +1 -1
  120. package/dist/tools/activity.d.ts +150 -0
  121. package/dist/tools/activity.d.ts.map +1 -0
  122. package/dist/tools/activity.js +198 -0
  123. package/dist/tools/activity.js.map +1 -0
  124. package/dist/tools/annotations.d.ts +52 -0
  125. package/dist/tools/annotations.d.ts.map +1 -0
  126. package/dist/tools/annotations.js +214 -0
  127. package/dist/tools/annotations.js.map +1 -0
  128. package/dist/tools/attachments.d.ts +28 -4
  129. package/dist/tools/attachments.d.ts.map +1 -1
  130. package/dist/tools/attachments.js +53 -34
  131. package/dist/tools/attachments.js.map +1 -1
  132. package/dist/tools/card-ops.d.ts +232 -0
  133. package/dist/tools/card-ops.d.ts.map +1 -0
  134. package/dist/tools/card-ops.js +333 -0
  135. package/dist/tools/card-ops.js.map +1 -0
  136. package/dist/tools/cards.d.ts +90 -8
  137. package/dist/tools/cards.d.ts.map +1 -1
  138. package/dist/tools/cards.js +411 -128
  139. package/dist/tools/cards.js.map +1 -1
  140. package/dist/tools/comments.d.ts +226 -22
  141. package/dist/tools/comments.d.ts.map +1 -1
  142. package/dist/tools/comments.js +163 -134
  143. package/dist/tools/comments.js.map +1 -1
  144. package/dist/tools/dispatch.d.ts +47 -0
  145. package/dist/tools/dispatch.d.ts.map +1 -0
  146. package/dist/tools/dispatch.js +63 -0
  147. package/dist/tools/dispatch.js.map +1 -0
  148. package/dist/tools/guard.d.ts +9 -0
  149. package/dist/tools/guard.d.ts.map +1 -0
  150. package/dist/tools/guard.js +20 -0
  151. package/dist/tools/guard.js.map +1 -0
  152. package/dist/tools/index.d.ts +748 -450
  153. package/dist/tools/index.d.ts.map +1 -1
  154. package/dist/tools/index.js +136 -17
  155. package/dist/tools/index.js.map +1 -1
  156. package/dist/tools/labels.d.ts +213 -18
  157. package/dist/tools/labels.d.ts.map +1 -1
  158. package/dist/tools/labels.js +218 -203
  159. package/dist/tools/labels.js.map +1 -1
  160. package/dist/tools/lists.d.ts +222 -15
  161. package/dist/tools/lists.d.ts.map +1 -1
  162. package/dist/tools/lists.js +175 -156
  163. package/dist/tools/lists.js.map +1 -1
  164. package/dist/tools/members.d.ts +128 -0
  165. package/dist/tools/members.d.ts.map +1 -0
  166. package/dist/tools/members.js +150 -0
  167. package/dist/tools/members.js.map +1 -0
  168. package/dist/tools/navigation.d.ts +22 -2
  169. package/dist/tools/navigation.d.ts.map +1 -1
  170. package/dist/tools/navigation.js +60 -15
  171. package/dist/tools/navigation.js.map +1 -1
  172. package/dist/tools/queries.d.ts +196 -166
  173. package/dist/tools/queries.d.ts.map +1 -1
  174. package/dist/tools/queries.js +125 -155
  175. package/dist/tools/queries.js.map +1 -1
  176. package/dist/tools/tasks.d.ts +26 -6
  177. package/dist/tools/tasks.d.ts.map +1 -1
  178. package/dist/tools/tasks.js +110 -55
  179. package/dist/tools/tasks.js.map +1 -1
  180. package/dist/tools/users.d.ts +130 -0
  181. package/dist/tools/users.d.ts.map +1 -0
  182. package/dist/tools/users.js +165 -0
  183. package/dist/tools/users.js.map +1 -0
  184. package/docs/planka-2x-gotchas.md +121 -5
  185. package/docs/tools.md +771 -187
  186. package/docs/troubleshooting.md +137 -5
  187. package/hooks/hooks.json +15 -0
  188. package/hooks/preflight.mjs +100 -0
  189. package/package.json +6 -1
  190. package/scripts/setup.sh +8 -26
  191. package/scripts/sync-identity.mjs +55 -1
  192. package/server.json +87 -6
  193. package/tests/smoke/planka-smoke.mjs +512 -72
  194. package/workflow/skills/planka-close-card/SKILL.md +18 -5
  195. package/workflow/skills/planka-orchestrator/SKILL.md +36 -7
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Tool: planka_duplicate_card
3
+ */
4
+ export declare const duplicateCardTool: {
5
+ name: string;
6
+ description: string;
7
+ inputSchema: {
8
+ type: "object";
9
+ properties: {
10
+ cardId: {
11
+ type: string;
12
+ description: string;
13
+ };
14
+ listId: {
15
+ type: string;
16
+ description: string;
17
+ };
18
+ boardId: {
19
+ type: string;
20
+ description: string;
21
+ };
22
+ name: {
23
+ type: string;
24
+ description: string;
25
+ };
26
+ position: {
27
+ type: string;
28
+ description: string;
29
+ };
30
+ };
31
+ required: string[];
32
+ };
33
+ handler: (params: {
34
+ cardId: string;
35
+ listId?: string;
36
+ boardId?: string;
37
+ name?: string;
38
+ position?: number;
39
+ }) => Promise<{
40
+ isError?: true | undefined;
41
+ content: {
42
+ type: "text";
43
+ text: string;
44
+ }[];
45
+ }>;
46
+ };
47
+ /**
48
+ * Tool: planka_archive_card
49
+ */
50
+ export declare const archiveCardTool: {
51
+ name: string;
52
+ description: string;
53
+ inputSchema: {
54
+ type: "object";
55
+ properties: {
56
+ cardId: {
57
+ type: string;
58
+ description: string;
59
+ };
60
+ restoreToListId: {
61
+ type: string;
62
+ description: string;
63
+ };
64
+ position: {
65
+ type: string;
66
+ description: string;
67
+ };
68
+ };
69
+ required: string[];
70
+ };
71
+ handler: (params: {
72
+ cardId: string;
73
+ restoreToListId?: string;
74
+ position?: number;
75
+ }) => Promise<{
76
+ isError?: true | undefined;
77
+ content: {
78
+ type: "text";
79
+ text: string;
80
+ }[];
81
+ }>;
82
+ };
83
+ /**
84
+ * Tool: planka_move_list_cards
85
+ *
86
+ * Planka's own bulk endpoint looks like the implementation of this tool and is
87
+ * not: it only archives a whole `closed` column, and answers 403 "Not enough
88
+ * rights" for anything else (see `bulkMoveClosedListToArchive`). So the tool
89
+ * uses it where it applies and moves card by card everywhere else — the
90
+ * promise to the caller is the same either way, and `strategy` says which ran.
91
+ */
92
+ export declare const moveListCardsTool: {
93
+ name: string;
94
+ description: string;
95
+ inputSchema: {
96
+ type: "object";
97
+ properties: {
98
+ fromListId: {
99
+ type: string;
100
+ description: string;
101
+ };
102
+ toListId: {
103
+ type: string;
104
+ description: string;
105
+ };
106
+ boardId: {
107
+ type: string;
108
+ description: string;
109
+ };
110
+ };
111
+ required: string[];
112
+ };
113
+ handler: (params: {
114
+ fromListId: string;
115
+ toListId: string;
116
+ boardId?: string;
117
+ }) => Promise<{
118
+ isError?: true | undefined;
119
+ content: {
120
+ type: "text";
121
+ text: string;
122
+ }[];
123
+ }>;
124
+ };
125
+ export declare const cardOpsTools: ({
126
+ name: string;
127
+ description: string;
128
+ inputSchema: {
129
+ type: "object";
130
+ properties: {
131
+ cardId: {
132
+ type: string;
133
+ description: string;
134
+ };
135
+ listId: {
136
+ type: string;
137
+ description: string;
138
+ };
139
+ boardId: {
140
+ type: string;
141
+ description: string;
142
+ };
143
+ name: {
144
+ type: string;
145
+ description: string;
146
+ };
147
+ position: {
148
+ type: string;
149
+ description: string;
150
+ };
151
+ };
152
+ required: string[];
153
+ };
154
+ handler: (params: {
155
+ cardId: string;
156
+ listId?: string;
157
+ boardId?: string;
158
+ name?: string;
159
+ position?: number;
160
+ }) => Promise<{
161
+ isError?: true | undefined;
162
+ content: {
163
+ type: "text";
164
+ text: string;
165
+ }[];
166
+ }>;
167
+ } | {
168
+ name: string;
169
+ description: string;
170
+ inputSchema: {
171
+ type: "object";
172
+ properties: {
173
+ cardId: {
174
+ type: string;
175
+ description: string;
176
+ };
177
+ restoreToListId: {
178
+ type: string;
179
+ description: string;
180
+ };
181
+ position: {
182
+ type: string;
183
+ description: string;
184
+ };
185
+ };
186
+ required: string[];
187
+ };
188
+ handler: (params: {
189
+ cardId: string;
190
+ restoreToListId?: string;
191
+ position?: number;
192
+ }) => Promise<{
193
+ isError?: true | undefined;
194
+ content: {
195
+ type: "text";
196
+ text: string;
197
+ }[];
198
+ }>;
199
+ } | {
200
+ name: string;
201
+ description: string;
202
+ inputSchema: {
203
+ type: "object";
204
+ properties: {
205
+ fromListId: {
206
+ type: string;
207
+ description: string;
208
+ };
209
+ toListId: {
210
+ type: string;
211
+ description: string;
212
+ };
213
+ boardId: {
214
+ type: string;
215
+ description: string;
216
+ };
217
+ };
218
+ required: string[];
219
+ };
220
+ handler: (params: {
221
+ fromListId: string;
222
+ toListId: string;
223
+ boardId?: string;
224
+ }) => Promise<{
225
+ isError?: true | undefined;
226
+ content: {
227
+ type: "text";
228
+ text: string;
229
+ }[];
230
+ }>;
231
+ })[];
232
+ //# sourceMappingURL=card-ops.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-ops.d.ts","sourceRoot":"","sources":["../../src/tools/card-ops.ts"],"names":[],"mappings":"AAmCA;;GAEG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA0BJ;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;;;;;;;CA0CF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;sBAqBF;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;;;;;;;CA4GF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;sBAiBJ;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;;;;;;;CA8GF,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA1UC;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAoEuB;QACtB,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBAwIuB;QACtB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;;;;;;;IAgHgF,CAAC"}
@@ -0,0 +1,333 @@
1
+ /**
2
+ * Card operations Planka has that this server did not expose: duplicating a
3
+ * card, archiving one, and emptying a column into another.
4
+ *
5
+ * All three are verified the same way the rest of the server is: the write is
6
+ * sent, the entity is read back, and the report describes the re-read.
7
+ */
8
+ import { duplicateCard } from "../operations/duplicate.js";
9
+ import { getCardBrief } from "../operations/card-brief.js";
10
+ import { getBoardSystemLists, moveCardToList, noArchiveList, } from "../operations/archive.js";
11
+ import { bulkMoveClosedListToArchive, moveCardsOneByOne, readListState, } from "../operations/lists.js";
12
+ import { verifiedWrite, writeResult } from "../operations/verify.js";
13
+ import { assertBoardAllowed, assertListWritable } from "../config/policy.js";
14
+ import { PlankaError } from "../errors.js";
15
+ function errorResult(message) {
16
+ return {
17
+ content: [{ type: "text", text: `Error: ${message}` }],
18
+ isError: true,
19
+ };
20
+ }
21
+ function catchPlanka(error) {
22
+ if (error instanceof PlankaError)
23
+ return errorResult(error.message);
24
+ throw error;
25
+ }
26
+ /**
27
+ * Tool: planka_duplicate_card
28
+ */
29
+ export const duplicateCardTool = {
30
+ name: "planka_duplicate_card",
31
+ description: "Copy a card with its tasks, labels and members (attachments are not copied). Lands in the " +
32
+ "same column unless listId says otherwise. Re-reads the copy and reports what it carries.",
33
+ inputSchema: {
34
+ type: "object",
35
+ properties: {
36
+ cardId: { type: "string", description: "The card to copy" },
37
+ listId: {
38
+ type: "string",
39
+ description: "Column for the copy. Defaults to the original's column.",
40
+ },
41
+ boardId: {
42
+ type: "string",
43
+ description: "Board for the copy, when copying across boards. Requires listId.",
44
+ },
45
+ name: {
46
+ type: "string",
47
+ description: "Name for the copy. Without it Planka appends its own suffix to the original name.",
48
+ },
49
+ position: { type: "number", description: "Position in the target column" },
50
+ },
51
+ required: ["cardId"],
52
+ },
53
+ handler: async (params) => {
54
+ try {
55
+ if (params.boardId && !params.listId) {
56
+ return errorResult("boardId without listId: a copy sent to another board needs the column it lands in.");
57
+ }
58
+ const written = await verifiedWrite({
59
+ write: () => duplicateCard(params),
60
+ reread: (copy) => getCardBrief({ cardId: copy.id }),
61
+ landed: (after, copy) => {
62
+ if (after.card.id !== copy.id)
63
+ return false;
64
+ if (params.listId && after.card.listId !== params.listId)
65
+ return false;
66
+ if (params.name !== undefined && after.card.name !== params.name)
67
+ return false;
68
+ return true;
69
+ },
70
+ });
71
+ const after = written.after;
72
+ return writeResult({
73
+ card: {
74
+ id: written.result.id,
75
+ name: after?.card.name ?? written.result.name,
76
+ listId: after?.card.listId ?? written.result.listId,
77
+ boardId: after?.card.boardId ?? written.result.boardId,
78
+ },
79
+ sourceCardId: params.cardId,
80
+ copied: {
81
+ tasks: after?.counts.tasks ?? 0,
82
+ labels: after?.counts.labels ?? 0,
83
+ members: after?.counts.members ?? 0,
84
+ attachments: after?.counts.attachments ?? 0,
85
+ },
86
+ }, written);
87
+ }
88
+ catch (error) {
89
+ return catchPlanka(error);
90
+ }
91
+ },
92
+ };
93
+ /**
94
+ * Tool: planka_archive_card
95
+ */
96
+ export const archiveCardTool = {
97
+ name: "planka_archive_card",
98
+ description: "Archive a card (Planka's hidden archive column) or bring it back with restoreToListId. " +
99
+ "Archiving hides the card from the board without deleting it; verified by re-reading its column.",
100
+ inputSchema: {
101
+ type: "object",
102
+ properties: {
103
+ cardId: { type: "string", description: "The card ID" },
104
+ restoreToListId: {
105
+ type: "string",
106
+ description: "Un-archive instead: move the card into this column. The card's previous column is reported when archiving.",
107
+ },
108
+ position: {
109
+ type: "number",
110
+ description: "Position in the column when restoring. Defaults to the end.",
111
+ },
112
+ },
113
+ required: ["cardId"],
114
+ },
115
+ handler: async (params) => {
116
+ try {
117
+ const before = await getCardBrief({ cardId: params.cardId });
118
+ const boardId = before.card.boardId;
119
+ // --- restore ---------------------------------------------------------
120
+ if (params.restoreToListId) {
121
+ assertListWritable(params.restoreToListId, undefined, "restore cards into");
122
+ const written = await verifiedWrite({
123
+ write: () => moveCardToList({
124
+ cardId: params.cardId,
125
+ listId: params.restoreToListId,
126
+ // An archived card has position null and Planka refuses a PATCH
127
+ // without one, so a restore always carries a position.
128
+ position: params.position ?? 65536,
129
+ }),
130
+ reread: () => getCardBrief({ cardId: params.cardId }),
131
+ landed: (after) => after.card.listId === params.restoreToListId,
132
+ });
133
+ return writeResult({
134
+ card: {
135
+ id: params.cardId,
136
+ name: written.after?.card.name ?? before.card.name,
137
+ listId: written.after?.card.listId ?? before.card.listId,
138
+ },
139
+ archived: false,
140
+ restoredTo: params.restoreToListId,
141
+ previousListId: before.card.listId,
142
+ }, written);
143
+ }
144
+ // --- archive ---------------------------------------------------------
145
+ // Archiving takes the card OUT of its column, so the origin is checked
146
+ // too — otherwise a protected column can be emptied one archive at a time.
147
+ assertListWritable(before.card.listId, undefined, "archive cards out of");
148
+ const system = await getBoardSystemLists(boardId);
149
+ if (!system.archiveListId)
150
+ throw noArchiveList(boardId);
151
+ assertListWritable(system.archiveListId, undefined, "archive cards into");
152
+ if (before.card.listId === system.archiveListId) {
153
+ return {
154
+ content: [
155
+ {
156
+ type: "text",
157
+ text: JSON.stringify({
158
+ success: true,
159
+ // Derived from the read above, not asserted: `before` IS the
160
+ // re-read, and it already says the card sits in the archive.
161
+ verified: true,
162
+ verifiedBy: "the card was read before the write and is already archived; nothing was written",
163
+ card: {
164
+ id: before.card.id,
165
+ name: before.card.name,
166
+ listId: before.card.listId,
167
+ },
168
+ archived: true,
169
+ alreadyArchived: true,
170
+ archiveListId: system.archiveListId,
171
+ previousListId: before.card.prevListId ?? null,
172
+ message: "The card was already in the archive. Pass restoreToListId to bring it back" +
173
+ (before.card.prevListId
174
+ ? ` (it came from list ${before.card.prevListId}).`
175
+ : "."),
176
+ }),
177
+ },
178
+ ],
179
+ };
180
+ }
181
+ const written = await verifiedWrite({
182
+ write: () => moveCardToList({ cardId: params.cardId, listId: system.archiveListId }),
183
+ reread: () => getCardBrief({ cardId: params.cardId }),
184
+ // isClosed does NOT flip on archive (verified on 2.2.1), so the column
185
+ // is the only honest proof.
186
+ landed: (after) => after.card.listId === system.archiveListId &&
187
+ after.card.listId !== before.card.listId,
188
+ });
189
+ return writeResult({
190
+ card: {
191
+ id: before.card.id,
192
+ name: written.after?.card.name ?? before.card.name,
193
+ listId: written.after?.card.listId ?? system.archiveListId,
194
+ },
195
+ archived: written.verified,
196
+ archiveListId: system.archiveListId,
197
+ previousListId: before.card.listId,
198
+ message: written.verified
199
+ ? `Card archived. Restore it with restoreToListId: "${before.card.listId}".`
200
+ : "The card does not read as archived.",
201
+ }, written);
202
+ }
203
+ catch (error) {
204
+ return catchPlanka(error);
205
+ }
206
+ },
207
+ };
208
+ /**
209
+ * Tool: planka_move_list_cards
210
+ *
211
+ * Planka's own bulk endpoint looks like the implementation of this tool and is
212
+ * not: it only archives a whole `closed` column, and answers 403 "Not enough
213
+ * rights" for anything else (see `bulkMoveClosedListToArchive`). So the tool
214
+ * uses it where it applies and moves card by card everywhere else — the
215
+ * promise to the caller is the same either way, and `strategy` says which ran.
216
+ */
217
+ export const moveListCardsTool = {
218
+ name: "planka_move_list_cards",
219
+ description: "Move EVERY card of one column into another. Counts both columns before and after; verified " +
220
+ "is false when the numbers do not add up. Reports partial moves rather than a smaller success.",
221
+ inputSchema: {
222
+ type: "object",
223
+ properties: {
224
+ fromListId: { type: "string", description: "Column to empty" },
225
+ toListId: { type: "string", description: "Column that receives the cards" },
226
+ boardId: {
227
+ type: "string",
228
+ description: "Board both columns belong to. Checked against the allowlist when given.",
229
+ },
230
+ },
231
+ required: ["fromListId", "toListId"],
232
+ },
233
+ handler: async (params) => {
234
+ try {
235
+ if (params.fromListId === params.toListId) {
236
+ return errorResult("fromListId and toListId are the same column: nothing would move.");
237
+ }
238
+ if (params.boardId)
239
+ assertBoardAllowed(params.boardId);
240
+ assertListWritable(params.toListId, undefined, "move cards into");
241
+ assertListWritable(params.fromListId, undefined, "move cards out of");
242
+ const from = await readListState(params.fromListId);
243
+ if (!from) {
244
+ return errorResult(`List ${params.fromListId} cannot be read. Planka's hidden archive and trash lists ` +
245
+ `answer 404 here, and so does a list id that does not exist.`);
246
+ }
247
+ // The destination may legitimately be unreadable: the archive list is.
248
+ const to = await readListState(params.toListId);
249
+ const toBefore = to?.count ?? null;
250
+ if (from.count === 0) {
251
+ return {
252
+ content: [
253
+ {
254
+ type: "text",
255
+ text: JSON.stringify({
256
+ success: true,
257
+ // `from.count === 0` comes from readListState, a real read of
258
+ // the column: the desired state already holds, nothing written.
259
+ verified: true,
260
+ verifiedBy: "the source column was read and is already empty; nothing was written",
261
+ moved: 0,
262
+ fromRemaining: 0,
263
+ toTotal: toBefore,
264
+ message: `List ${params.fromListId} is already empty; nothing was moved.`,
265
+ }),
266
+ },
267
+ ],
268
+ };
269
+ }
270
+ // Planka's bulk call only accepts closed -> archive. Everywhere else it
271
+ // answers 403, so it is not even attempted. The board show that resolves
272
+ // the archive id is expensive, so it is only read when the destination
273
+ // could BE the archive — an unreadable list — and the source is closed.
274
+ let canBulk = false;
275
+ if (from.type === "closed" && to === null && from.boardId) {
276
+ const { archiveListId } = await getBoardSystemLists(from.boardId);
277
+ canBulk = archiveListId === params.toListId;
278
+ }
279
+ const cards = from.cardIds.map((id) => ({
280
+ id,
281
+ position: from.positions.get(id) ?? null,
282
+ }));
283
+ let failed = [];
284
+ const written = await verifiedWrite({
285
+ write: async () => {
286
+ if (canBulk) {
287
+ await bulkMoveClosedListToArchive({
288
+ fromListId: params.fromListId,
289
+ toListId: params.toListId,
290
+ });
291
+ return "bulk";
292
+ }
293
+ failed = await moveCardsOneByOne({ cards, toListId: params.toListId });
294
+ return "perCard";
295
+ },
296
+ reread: async () => ({
297
+ from: (await readListState(params.fromListId))?.count ?? null,
298
+ to: (await readListState(params.toListId))?.count ?? null,
299
+ }),
300
+ landed: (after) => {
301
+ if (after.from !== 0)
302
+ return false;
303
+ // An unreadable destination (the archive) cannot be counted; an empty
304
+ // source plus no failed PATCH is the whole proof available.
305
+ if (after.to === null || toBefore === null)
306
+ return failed.length === 0;
307
+ return after.to === toBefore + from.count;
308
+ },
309
+ });
310
+ const fromAfter = written.after?.from ?? from.count;
311
+ const toAfter = written.after?.to ?? toBefore;
312
+ return writeResult({
313
+ fromListId: params.fromListId,
314
+ toListId: params.toListId,
315
+ strategy: written.result,
316
+ moved: from.count - (fromAfter ?? from.count),
317
+ fromRemaining: fromAfter,
318
+ toTotal: toAfter,
319
+ ...(toBefore === null
320
+ ? {
321
+ toCountUnavailable: "the destination list cannot be read (Planka hides archive and trash), so only the source was counted",
322
+ }
323
+ : { expectedTotal: toBefore + from.count }),
324
+ ...(failed.length ? { failed } : {}),
325
+ }, written);
326
+ }
327
+ catch (error) {
328
+ return catchPlanka(error);
329
+ }
330
+ },
331
+ };
332
+ export const cardOpsTools = [duplicateCardTool, archiveCardTool, moveListCardsTool];
333
+ //# sourceMappingURL=card-ops.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"card-ops.js","sourceRoot":"","sources":["../../src/tools/card-ops.ts"],"names":[],"mappings":"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"}