smashspace 0.5.0 → 0.8.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.
- package/dist/smash.mjs +50 -5
- package/dist/smashspace-mcp.mjs +74 -7
- package/package.json +1 -1
package/dist/smash.mjs
CHANGED
|
@@ -4128,7 +4128,7 @@ ${detail.card.description}`);
|
|
|
4128
4128
|
}
|
|
4129
4129
|
}
|
|
4130
4130
|
});
|
|
4131
|
-
cardCmd.command("update <cardId>").description("Update card fields (title, description, due date, cover, checklist title)").option("--title <title>", "New title").option("-d, --description <description>", "New description (markdown)").option("--desc <description>", "alias for --description").option("--desc-file <path>", "read description from a file (or - for stdin)").option("--due <iso>", "Due date as ISO string, or empty string to clear").option("--cover <attachmentId>", "Cover attachment ID, or empty string to clear").option("--checklist-title <title>", "Custom checklist section title, or empty string to clear").action(
|
|
4131
|
+
cardCmd.command("update <cardId>").description("Update card fields (title, description, due date, cover, checklist title)").option("--title <title>", "New title").option("-d, --description <description>", "New description (markdown)").option("--desc <description>", "alias for --description").option("--desc-file <path>", "read description from a file (or - for stdin)").option("--due <iso>", "Due date as ISO string, or empty string to clear").option("--cover <attachmentId>", "Cover attachment ID, or empty string to clear").option("--checklist-title <title>", "Custom checklist section title, or empty string to clear").option("--comment <body>", "Add a comment in the same call").option("--comment-author <name>", "Author name for --comment").option("--to <id>", "Address the comment to an assignee id (repeatable)", collectRepeated, []).option("--list <name>", "Move the card to this list (name or id) in the same call").option("--done", "Move the card to the board's done list (wins over --list)").action(
|
|
4132
4132
|
async (cardId, opts) => {
|
|
4133
4133
|
const patch = {};
|
|
4134
4134
|
if (opts.title !== void 0)
|
|
@@ -4144,15 +4144,35 @@ cardCmd.command("update <cardId>").description("Update card fields (title, descr
|
|
|
4144
4144
|
patch.coverAttachmentId = opts.cover === "" ? null : opts.cover;
|
|
4145
4145
|
if (opts.checklistTitle !== void 0)
|
|
4146
4146
|
patch.checklistTitle = opts.checklistTitle === "" ? null : opts.checklistTitle;
|
|
4147
|
+
if (opts.comment !== void 0) {
|
|
4148
|
+
patch.comment = {
|
|
4149
|
+
body: opts.comment,
|
|
4150
|
+
...opts.commentAuthor ? { authorName: opts.commentAuthor } : {},
|
|
4151
|
+
...opts.to.length > 0 ? { recipients: opts.to } : {}
|
|
4152
|
+
};
|
|
4153
|
+
}
|
|
4154
|
+
if (opts.done)
|
|
4155
|
+
patch.complete = true;
|
|
4156
|
+
else if (opts.list !== void 0)
|
|
4157
|
+
patch.list = opts.list;
|
|
4147
4158
|
if (Object.keys(patch).length === 0) {
|
|
4148
|
-
console.error(
|
|
4159
|
+
console.error(
|
|
4160
|
+
"Provide at least one of: --title, --description, --desc-file, --due, --cover, --checklist-title, --comment, --list, --done"
|
|
4161
|
+
);
|
|
4149
4162
|
process.exit(1);
|
|
4150
4163
|
}
|
|
4151
4164
|
const card = await api(`/api/cards/${cardId}`, {
|
|
4152
4165
|
method: "PATCH",
|
|
4153
4166
|
body: JSON.stringify(patch)
|
|
4154
4167
|
});
|
|
4155
|
-
|
|
4168
|
+
const done = [];
|
|
4169
|
+
if (opts.comment !== void 0)
|
|
4170
|
+
done.push("commented");
|
|
4171
|
+
if (opts.done)
|
|
4172
|
+
done.push("completed");
|
|
4173
|
+
else if (opts.list !== void 0)
|
|
4174
|
+
done.push(`moved to ${opts.list}`);
|
|
4175
|
+
show(card, [`\u2713 card ${card.id} updated${done.length ? ` (${done.join(", ")})` : ""}`]);
|
|
4156
4176
|
}
|
|
4157
4177
|
);
|
|
4158
4178
|
cardCmd.command("move <cardId>").description("Move a card to a list (and optionally a position)").requiredOption("--list <listId>", "Destination list ID").option("--position <n>", "Target index (0-based)", "0").action(
|
|
@@ -4259,18 +4279,34 @@ cardCmd.command("comment <cardId> <body>").description("Add a comment to a card"
|
|
|
4259
4279
|
function collectRepeated(value, previous) {
|
|
4260
4280
|
return [...previous, value];
|
|
4261
4281
|
}
|
|
4282
|
+
program2.command("done <cardId>").description(
|
|
4283
|
+
"Mark a card done \u2014 moves it to the board's done list (it stays on the board). Not the same as `smash archive`, which takes it off."
|
|
4284
|
+
).action(async (cardId) => {
|
|
4285
|
+
const result = await api(`/api/cards/${cardId}/complete`, {
|
|
4286
|
+
method: "POST"
|
|
4287
|
+
});
|
|
4288
|
+
show(result.card, [`\u2713 card ${result.card.id} \u2192 ${result.listTitle}`]);
|
|
4289
|
+
});
|
|
4262
4290
|
program2.command("cards").description(
|
|
4263
4291
|
"List cards on the resolved board \u2014 light by default (no description). Filter by list/assignee, pick columns with --fields."
|
|
4264
|
-
).option("-b, --board <label>", "board label from config").option("--board-id <id>", "explicit board id (bypass config)").option("-l, --list <name>", "only cards in this list (name or id)").option("--assignee <idOrName>", "only cards assigned to this id or display name").option(
|
|
4292
|
+
).option("-b, --board <label>", "board label from config").option("--board-id <id>", "explicit board id (bypass config)").option("-l, --list <name>", "only cards in this list (name or id)").option("--assignee <idOrName>", "only cards assigned to this id or display name").option("--status <status>", "open (skip cards in lists marked done) | done | all (default)").option("--stale <days>", "only cards untouched for N days, oldest first (adds lastActivityAt)").option(
|
|
4265
4293
|
"--fields <list>",
|
|
4266
4294
|
"comma-separated columns (default: id,title,listId,listTitle,updatedAt). Add description only when you need bodies."
|
|
4267
4295
|
).option("--limit <n>", "max cards per page (default 100, max 500)").option("--cursor <cursor>", "continue from a previous response's cursor").action(async (opts) => {
|
|
4296
|
+
if (opts.status && !["open", "done", "all"].includes(opts.status)) {
|
|
4297
|
+
console.error("--status must be one of: open, done, all");
|
|
4298
|
+
process.exit(1);
|
|
4299
|
+
}
|
|
4268
4300
|
const ctx = resolveContext(opts);
|
|
4269
4301
|
const params = new URLSearchParams();
|
|
4270
4302
|
if (opts.list)
|
|
4271
4303
|
params.set("list", opts.list);
|
|
4272
4304
|
if (opts.assignee)
|
|
4273
4305
|
params.set("assignee", opts.assignee);
|
|
4306
|
+
if (opts.status)
|
|
4307
|
+
params.set("status", opts.status);
|
|
4308
|
+
if (opts.stale)
|
|
4309
|
+
params.set("staleDays", opts.stale);
|
|
4274
4310
|
if (opts.fields)
|
|
4275
4311
|
params.set("fields", opts.fields);
|
|
4276
4312
|
if (opts.limit)
|
|
@@ -4289,7 +4325,9 @@ program2.command("cards").description(
|
|
|
4289
4325
|
}
|
|
4290
4326
|
for (const card of result.cards) {
|
|
4291
4327
|
const listTitle = typeof card.listTitle === "string" ? `[${card.listTitle}] ` : "";
|
|
4292
|
-
|
|
4328
|
+
const last = typeof card.lastActivityAt === "string" ? card.lastActivityAt : null;
|
|
4329
|
+
const age = last ? ` ${last.slice(0, 10)} (${Math.floor((Date.now() - Date.parse(last)) / 864e5)}\u65E5\u524D)` : "";
|
|
4330
|
+
console.log(`${listTitle}${String(card.title ?? "")} (${String(card.id ?? "")})${age}`);
|
|
4293
4331
|
}
|
|
4294
4332
|
console.log(
|
|
4295
4333
|
`
|
|
@@ -4564,6 +4602,13 @@ tokenCmd.command("revoke <boardId> <tokenId>").description("Revoke a write token
|
|
|
4564
4602
|
);
|
|
4565
4603
|
show(revoked, [`\u2713 token ${revoked.id} revoked at ${revoked.revokedAt}`]);
|
|
4566
4604
|
});
|
|
4605
|
+
listCmd.command("done <listId>").description("Mark a list as done (cards in it are excluded by `smash cards --status open`)").option("--no-done", "unmark it instead").action(async (listId, opts) => {
|
|
4606
|
+
const list = await api(`/api/lists/${listId}`, {
|
|
4607
|
+
method: "PATCH",
|
|
4608
|
+
body: JSON.stringify({ isDone: opts.done })
|
|
4609
|
+
});
|
|
4610
|
+
show(list, [`\u2713 list ${list.id} (${list.title}) isDone=${list.isDone}`]);
|
|
4611
|
+
});
|
|
4567
4612
|
var labelCmd = program2.command("label").description("Labels");
|
|
4568
4613
|
labelCmd.command("create <boardId> <name>").description("Create a board label").option(
|
|
4569
4614
|
"--color <color>",
|
package/dist/smashspace-mcp.mjs
CHANGED
|
@@ -15553,18 +15553,25 @@ var tools = [
|
|
|
15553
15553
|
},
|
|
15554
15554
|
{
|
|
15555
15555
|
name: "smash_rename_list",
|
|
15556
|
-
description: "Rename a list.",
|
|
15556
|
+
description: "Rename a list, and/or mark it as a done list. Cards in a list with isDone=true are excluded by smash_list_cards({status: 'open'}), so an agent can ask for open work without knowing the board's list names.",
|
|
15557
15557
|
inputSchema: {
|
|
15558
15558
|
type: "object",
|
|
15559
15559
|
properties: {
|
|
15560
15560
|
listId: { type: "string" },
|
|
15561
|
-
title: { type: "string" }
|
|
15561
|
+
title: { type: "string" },
|
|
15562
|
+
isDone: {
|
|
15563
|
+
type: "boolean",
|
|
15564
|
+
description: "Treat cards in this list as done"
|
|
15565
|
+
}
|
|
15562
15566
|
},
|
|
15563
|
-
required: ["listId"
|
|
15567
|
+
required: ["listId"]
|
|
15564
15568
|
},
|
|
15565
15569
|
handler: async (args) => api(`/api/lists/${args.listId}`, {
|
|
15566
15570
|
method: "PATCH",
|
|
15567
|
-
body: JSON.stringify({
|
|
15571
|
+
body: JSON.stringify({
|
|
15572
|
+
...typeof args.title === "string" ? { title: args.title } : {},
|
|
15573
|
+
...typeof args.isDone === "boolean" ? { isDone: args.isDone } : {}
|
|
15574
|
+
})
|
|
15568
15575
|
})
|
|
15569
15576
|
},
|
|
15570
15577
|
{
|
|
@@ -15608,7 +15615,7 @@ var tools = [
|
|
|
15608
15615
|
},
|
|
15609
15616
|
{
|
|
15610
15617
|
name: "smash_update_card",
|
|
15611
|
-
description: "Update a card'
|
|
15618
|
+
description: "Update a card, and optionally comment on it and move it IN THE SAME CALL. Advancing a card is usually 'write what happened, then move it' \u2014 pass `comment` plus `list` (or `complete: true`) instead of making three calls. All fields except cardId are optional. Pass null to clear dueAt / coverAttachmentId / checklistTitle / description.",
|
|
15612
15619
|
inputSchema: {
|
|
15613
15620
|
type: "object",
|
|
15614
15621
|
properties: {
|
|
@@ -15629,6 +15636,33 @@ var tools = [
|
|
|
15629
15636
|
checklistTitle: {
|
|
15630
15637
|
type: ["string", "null"],
|
|
15631
15638
|
description: "Custom title for the checklist section, or null to reset to default"
|
|
15639
|
+
},
|
|
15640
|
+
comment: {
|
|
15641
|
+
type: "object",
|
|
15642
|
+
description: "Add one comment in the same call",
|
|
15643
|
+
properties: {
|
|
15644
|
+
body: { type: "string" },
|
|
15645
|
+
authorName: { type: "string" },
|
|
15646
|
+
recipients: {
|
|
15647
|
+
type: "array",
|
|
15648
|
+
items: { type: "string" },
|
|
15649
|
+
description: "Assignee ids this comment is addressed to"
|
|
15650
|
+
}
|
|
15651
|
+
},
|
|
15652
|
+
required: ["body"]
|
|
15653
|
+
},
|
|
15654
|
+
list: {
|
|
15655
|
+
type: "string",
|
|
15656
|
+
description: "Move the card to this list (name, case-insensitive, or id)"
|
|
15657
|
+
},
|
|
15658
|
+
position: { type: "number", description: "Position within the destination list" },
|
|
15659
|
+
complete: {
|
|
15660
|
+
type: "boolean",
|
|
15661
|
+
description: "Move the card to the board's done list (wins over `list`). Fails with 409 when no list is marked done."
|
|
15662
|
+
},
|
|
15663
|
+
assignees: {
|
|
15664
|
+
type: ["array", "null"],
|
|
15665
|
+
description: "Replace the card's assignees (same shape as smash_set_assignees)"
|
|
15632
15666
|
}
|
|
15633
15667
|
},
|
|
15634
15668
|
required: ["cardId"]
|
|
@@ -15645,6 +15679,16 @@ var tools = [
|
|
|
15645
15679
|
patch.coverAttachmentId = args.coverAttachmentId;
|
|
15646
15680
|
if (args.checklistTitle !== void 0)
|
|
15647
15681
|
patch.checklistTitle = args.checklistTitle;
|
|
15682
|
+
if (args.comment !== void 0)
|
|
15683
|
+
patch.comment = args.comment;
|
|
15684
|
+
if (typeof args.list === "string")
|
|
15685
|
+
patch.list = args.list;
|
|
15686
|
+
if (typeof args.position === "number")
|
|
15687
|
+
patch.position = args.position;
|
|
15688
|
+
if (args.complete === true)
|
|
15689
|
+
patch.complete = true;
|
|
15690
|
+
if (args.assignees !== void 0)
|
|
15691
|
+
patch.assignees = args.assignees;
|
|
15648
15692
|
return api(`/api/cards/${args.cardId}`, {
|
|
15649
15693
|
method: "PATCH",
|
|
15650
15694
|
body: JSON.stringify(patch)
|
|
@@ -15710,10 +15754,19 @@ var tools = [
|
|
|
15710
15754
|
boardId: { type: "string" },
|
|
15711
15755
|
list: { type: "string", description: "List name (case-insensitive) or list id" },
|
|
15712
15756
|
assignee: { type: "string", description: "Assignee id or display name" },
|
|
15757
|
+
status: {
|
|
15758
|
+
type: "string",
|
|
15759
|
+
enum: ["open", "done", "all"],
|
|
15760
|
+
description: "open skips cards sitting in a list marked done (a flag on the list, not a name match); done keeps only those. Default all."
|
|
15761
|
+
},
|
|
15762
|
+
staleDays: {
|
|
15763
|
+
type: "number",
|
|
15764
|
+
description: "Only cards untouched for this many days, oldest first. Each row gets lastActivityAt, so you can tell a two-week stall from a three-month one. Use it to find work that stopped without anyone noticing."
|
|
15765
|
+
},
|
|
15713
15766
|
fields: {
|
|
15714
15767
|
type: "array",
|
|
15715
15768
|
items: { type: "string" },
|
|
15716
|
-
description: "Columns to return: id, boardId, title, description, listId, listTitle, position, dueAt, labelIds, checklistTitle, agentMeta, externalRefs, assignees, customData, createdAt, updatedAt"
|
|
15769
|
+
description: "Columns to return: id, boardId, title, description, listId, listTitle, position, dueAt, labelIds, checklistTitle, agentMeta, externalRefs, assignees, customData, source, createdAt, updatedAt, lastActivityAt"
|
|
15717
15770
|
},
|
|
15718
15771
|
limit: { type: "number", description: "Max cards per page (default 100, max 500)" },
|
|
15719
15772
|
cursor: { type: "string", description: "Cursor from a previous response" }
|
|
@@ -15726,6 +15779,10 @@ var tools = [
|
|
|
15726
15779
|
params.set("list", args.list);
|
|
15727
15780
|
if (typeof args.assignee === "string" && args.assignee)
|
|
15728
15781
|
params.set("assignee", args.assignee);
|
|
15782
|
+
if (typeof args.status === "string" && args.status)
|
|
15783
|
+
params.set("status", args.status);
|
|
15784
|
+
if (typeof args.staleDays === "number")
|
|
15785
|
+
params.set("staleDays", String(args.staleDays));
|
|
15729
15786
|
if (Array.isArray(args.fields) && args.fields.length > 0)
|
|
15730
15787
|
params.set("fields", args.fields.join(","));
|
|
15731
15788
|
if (typeof args.limit === "number")
|
|
@@ -15786,9 +15843,19 @@ var tools = [
|
|
|
15786
15843
|
})
|
|
15787
15844
|
})
|
|
15788
15845
|
},
|
|
15846
|
+
{
|
|
15847
|
+
name: "smash_complete_card",
|
|
15848
|
+
description: "Mark a card done: it moves to the list flagged as done on its board and STAYS on the board, where people can see it. Use this when work finished. smash_delete_card is different \u2014 that archives the card off the board. Fails with a message when no list is marked done yet (mark one with smash_rename_list({listId, isDone: true})).",
|
|
15849
|
+
inputSchema: {
|
|
15850
|
+
type: "object",
|
|
15851
|
+
properties: { cardId: { type: "string" } },
|
|
15852
|
+
required: ["cardId"]
|
|
15853
|
+
},
|
|
15854
|
+
handler: async (args) => api(`/api/cards/${args.cardId}/complete`, { method: "POST" })
|
|
15855
|
+
},
|
|
15789
15856
|
{
|
|
15790
15857
|
name: "smash_delete_card",
|
|
15791
|
-
description: "Archive a card (soft delete). It leaves the board but is kept: it shows up in the space's archived column and smash_restore_card puts it back. Nothing is destroyed here \u2014 smash_permanently_delete_card is the irreversible one.",
|
|
15858
|
+
description: "Archive a card (soft delete) \u2014 NOT the same as marking it done. It leaves the board but is kept: it shows up in the space's archived column and smash_restore_card puts it back. Nothing is destroyed here \u2014 smash_permanently_delete_card is the irreversible one.",
|
|
15792
15859
|
inputSchema: {
|
|
15793
15860
|
type: "object",
|
|
15794
15861
|
properties: { cardId: { type: "string" } },
|