codiedev 0.5.2 → 0.5.4

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.js CHANGED
@@ -17,6 +17,7 @@
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  const connect_1 = require("./connect");
19
19
  const push_1 = require("./commands/push");
20
+ const delete_1 = require("./commands/delete");
20
21
  const pull_1 = require("./commands/pull");
21
22
  const ping_1 = require("./commands/ping");
22
23
  const inbox_1 = require("./commands/inbox");
@@ -39,6 +40,9 @@ Artifacts:
39
40
  codiedev push <file.md> Author or update an artifact
40
41
  codiedev pull <key> [--version N] [--out path]
41
42
  Fetch an artifact (stdout by default)
43
+ codiedev delete <key> [-y] Delete every version of an artifact you
44
+ authored (clean up bad/test pushes).
45
+ Asks for confirmation; -y to skip.
42
46
  codiedev promote <artifact-id> Promote an auto-extracted artifact
43
47
  to an authored one
44
48
  codiedev reverse-ticket [<pr-url>] Generate a Jira ticket draft.
@@ -363,6 +367,10 @@ async function main() {
363
367
  case "push":
364
368
  await (0, push_1.runPush)(rest);
365
369
  return;
370
+ case "delete":
371
+ case "rm":
372
+ await (0, delete_1.runDelete)(rest);
373
+ return;
366
374
  case "pull":
367
375
  await (0, pull_1.runPull)(rest);
368
376
  return;
@@ -0,0 +1 @@
1
+ export declare function runDelete(args: string[]): Promise<void>;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.runDelete = runDelete;
37
+ const readline = __importStar(require("readline"));
38
+ const shared_1 = require("./shared");
39
+ function parseArgs(args) {
40
+ let key;
41
+ let yes = false;
42
+ for (const a of args) {
43
+ if (a === "-y" || a === "--yes") {
44
+ yes = true;
45
+ }
46
+ else if (!a.startsWith("--") && !key) {
47
+ key = a;
48
+ }
49
+ }
50
+ if (!key) {
51
+ console.error("Usage: codiedev delete <key> [-y]");
52
+ console.error("Example: codiedev delete spec-old.md");
53
+ process.exit(1);
54
+ }
55
+ return { key, yes };
56
+ }
57
+ async function confirm(prompt) {
58
+ const rl = readline.createInterface({
59
+ input: process.stdin,
60
+ output: process.stdout,
61
+ });
62
+ const answer = await new Promise((resolve) => {
63
+ rl.question(prompt, (ans) => resolve(ans));
64
+ });
65
+ rl.close();
66
+ return /^y(es)?$/i.test(answer.trim());
67
+ }
68
+ async function runDelete(args) {
69
+ const { key, yes } = parseArgs(args);
70
+ const config = (0, shared_1.requireConfig)();
71
+ if (!yes) {
72
+ const ok = await confirm(`Delete every version of '${key}' (and its replies)? This cannot be undone. [y/N] `);
73
+ if (!ok) {
74
+ console.log("Cancelled.");
75
+ return;
76
+ }
77
+ }
78
+ try {
79
+ const res = await (0, shared_1.apiRequest)("POST", "/api/cli/delete", {
80
+ config,
81
+ body: { key },
82
+ });
83
+ if (res.deleted === 0) {
84
+ console.log(`No artifact found with key '${key}'. Nothing to delete.`);
85
+ return;
86
+ }
87
+ const cascaded = res.cascadedMessages > 0
88
+ ? ` + ${res.cascadedMessages} reply${res.cascadedMessages === 1 ? "" : "ies"}`
89
+ : "";
90
+ console.log(`✓ Deleted ${res.deleted} version${res.deleted === 1 ? "" : "s"}${cascaded} of '${res.key}'.`);
91
+ }
92
+ catch (err) {
93
+ console.error(`Delete failed: ${err.message}`);
94
+ process.exit(1);
95
+ }
96
+ }
package/dist/mcp.js CHANGED
@@ -117,11 +117,13 @@ const TOOLS = [
117
117
  },
118
118
  {
119
119
  name: "codiedev_pull",
120
- description: "Fetch an artifact (spec, review, decision, proposal, bugfix, or " +
121
- "note) from the team's CodieDev artifact layer. Use when the user " +
122
- "asks to pull, grab, fetch, or resume work on a named artifact, or " +
123
- "when they want to see what a teammate pushed. Returns the full " +
124
- "markdown content.",
120
+ description: "Fetch any artifact (doc or skill) from the team's CodieDev artifact " +
121
+ "layer. Works for specs, decisions, proposals, bugfixes, reviews, " +
122
+ "notes, AND skills (SKILL.md frontmatter files surfaced as slash " +
123
+ "commands). Use when the user asks to pull, grab, fetch, or resume " +
124
+ "work on a named artifact, when they want to load a skill into " +
125
+ "their session (e.g. 'pull the writing-emails skill'), or when they " +
126
+ "want to see what a teammate pushed. Returns the full markdown.",
125
127
  inputSchema: {
126
128
  type: "object",
127
129
  properties: {
@@ -137,6 +139,26 @@ const TOOLS = [
137
139
  required: ["key"],
138
140
  },
139
141
  },
142
+ {
143
+ name: "codiedev_delete",
144
+ description: "Delete every version of an artifact (and its replies) by key. Use " +
145
+ "when the user asks to delete, remove, undo, throw away, or clean up " +
146
+ "an artifact (e.g., 'delete that test push', 'remove the duplicate', " +
147
+ "'rm spec-old'). Authorship is enforced server-side: you can only " +
148
+ "delete artifacts you authored. Always confirm with the user before " +
149
+ "calling — deletions cannot be undone.",
150
+ inputSchema: {
151
+ type: "object",
152
+ properties: {
153
+ key: {
154
+ type: "string",
155
+ description: "Filename key of the artifact to delete, e.g. 'spec-214.md'. " +
156
+ "Every version of this key is removed.",
157
+ },
158
+ },
159
+ required: ["key"],
160
+ },
161
+ },
140
162
  {
141
163
  name: "codiedev_ping",
142
164
  description: "Send a message to a teammate on CodieDev, optionally attached to a " +
@@ -374,10 +396,13 @@ const TOOLS = [
374
396
  },
375
397
  {
376
398
  name: "codiedev_get_library",
377
- description: "List artifacts in the team library, scoped to what the current " +
378
- "user authored, what's been shared with them, or everything in the " +
379
- "company. Use when the user asks 'show me my artifacts', 'what did " +
380
- "I push?', 'what has Greg shared with me?', or 'browse the library'.",
399
+ description: "List artifacts in the team library both docs (spec / decision / " +
400
+ "proposal / bugfix / review / note) and skills (SKILL.md frontmatter " +
401
+ "files surfaced as slash commands). Each row reports its `kind` " +
402
+ "(doc | skill) and `tags`. Use when the user asks 'show me my " +
403
+ "artifacts', 'what skills do we have?', 'what did I push?', 'what " +
404
+ "has Greg shared with me?', or 'browse the library'. Filter by " +
405
+ "`kind` to narrow to docs-only or skills-only.",
381
406
  inputSchema: {
382
407
  type: "object",
383
408
  properties: {
@@ -387,10 +412,24 @@ const TOOLS = [
387
412
  description: "'mine' = artifacts I authored (default). 'shared' = artifacts " +
388
413
  "explicitly shared with me. 'all' = everything in the company.",
389
414
  },
415
+ kind: {
416
+ type: "string",
417
+ enum: ["doc", "skill"],
418
+ description: "Filter to one kind. `skill` = files with SKILL.md frontmatter " +
419
+ "(slash commands). `doc` = everything else (specs, decisions, " +
420
+ "etc.). Omit to return both.",
421
+ },
422
+ tag: {
423
+ type: "string",
424
+ description: "Filter to one tag (e.g. 'spec', 'decision', 'auth'). The " +
425
+ "legacy doc-shape (spec/decision/...) is automatically " +
426
+ "available as a tag, plus anything the author added.",
427
+ },
390
428
  type: {
391
429
  type: "string",
392
430
  enum: ["spec", "bugfix", "decision", "proposal", "review", "note"],
393
- description: "Filter to one artifact type.",
431
+ description: "Legacy doc-shape filter kept for back-compat. Prefer `kind` " +
432
+ "or `tag` for new code.",
394
433
  },
395
434
  folderPath: { type: "string", description: "Filter to one folder path." },
396
435
  limit: { type: "integer", description: "Max rows. Default 50." },
@@ -514,6 +553,8 @@ async function dispatchTool(name, args, config) {
514
553
  return await handlePush(args, config);
515
554
  case "codiedev_pull":
516
555
  return await handlePull(args, config);
556
+ case "codiedev_delete":
557
+ return await handleDelete(args, config);
517
558
  case "codiedev_ping":
518
559
  return await handlePing(args, config);
519
560
  case "codiedev_inbox":
@@ -587,6 +628,33 @@ async function handlePull(args, config) {
587
628
  content: [{ type: "text", text: header + a.markdown }],
588
629
  };
589
630
  }
631
+ async function handleDelete(args, config) {
632
+ const key = asString(args.key);
633
+ if (!key)
634
+ throw new Error("key required");
635
+ const res = await (0, shared_1.apiRequest)("POST", "/api/cli/delete", { config, body: { key } });
636
+ if (res.deleted === 0) {
637
+ return {
638
+ content: [
639
+ {
640
+ type: "text",
641
+ text: `No artifact found with key '${key}'. Nothing to delete.`,
642
+ },
643
+ ],
644
+ };
645
+ }
646
+ const cascaded = res.cascadedMessages > 0
647
+ ? ` + ${res.cascadedMessages} reply${res.cascadedMessages === 1 ? "" : "ies"}`
648
+ : "";
649
+ return {
650
+ content: [
651
+ {
652
+ type: "text",
653
+ text: `✓ Deleted ${res.deleted} version${res.deleted === 1 ? "" : "s"}${cascaded} of '${res.key}'.`,
654
+ },
655
+ ],
656
+ };
657
+ }
590
658
  async function handlePing(args, config) {
591
659
  const to = asString(args.to);
592
660
  const body = asString(args.body);
@@ -726,16 +794,48 @@ async function handleShareWith(args, config) {
726
794
  config,
727
795
  body: { filename, to, role },
728
796
  });
729
- const verb = res.action === "added"
730
- ? "Shared"
731
- : res.action === "updated"
732
- ? "Updated share for"
733
- : "Already shared with";
797
+ const target = `${res.recipient.name} <${res.recipient.email}>`;
798
+ if (res.added) {
799
+ return {
800
+ content: [
801
+ {
802
+ type: "text",
803
+ text: `✓ Shared ${target} on ${filename} (role=${role ?? "read"}).`,
804
+ },
805
+ ],
806
+ };
807
+ }
808
+ if (res.updated) {
809
+ return {
810
+ content: [
811
+ {
812
+ type: "text",
813
+ text: `✓ Updated share for ${target} on ${filename} (role=${role ?? "read"}).`,
814
+ },
815
+ ],
816
+ };
817
+ }
818
+ // noop / duplicate path — surface where the existing grant came from so
819
+ // the user knows whether to expect it next time.
820
+ const e = res.existing;
821
+ let why = "";
822
+ if (e) {
823
+ const when = e.grantedAt ? ` ${(0, shared_1.timeAgo)(e.grantedAt)}` : "";
824
+ if (e.source === "self") {
825
+ why = ` — you already shared it with them${when} (role=${e.role}).`;
826
+ }
827
+ else if (e.source === "auto") {
828
+ why = ` — granted automatically${when} (role=${e.role}). No action needed next time.`;
829
+ }
830
+ else {
831
+ why = ` — ${e.granterLabel} shared it${when} (role=${e.role}).`;
832
+ }
833
+ }
734
834
  return {
735
835
  content: [
736
836
  {
737
837
  type: "text",
738
- text: `✓ ${verb} ${res.recipient.name} <${res.recipient.email}> on ${filename} (role=${role ?? "read"}).`,
838
+ text: `✓ Already shared with ${target} on ${filename}${why}`,
739
839
  },
740
840
  ],
741
841
  };
@@ -818,6 +918,8 @@ async function handleSearch(args, config) {
818
918
  async function handleGetLibrary(args, config) {
819
919
  const scope = asStringOrUndefined(args.scope);
820
920
  const type = asStringOrUndefined(args.type);
921
+ const kind = asStringOrUndefined(args.kind);
922
+ const tag = asStringOrUndefined(args.tag);
821
923
  const folderPath = asStringOrUndefined(args.folderPath);
822
924
  const limit = asIntOrUndefined(args.limit);
823
925
  const res = await (0, shared_1.apiRequest)("GET", "/api/cli/library", {
@@ -825,6 +927,8 @@ async function handleGetLibrary(args, config) {
825
927
  query: {
826
928
  scope,
827
929
  type,
930
+ kind,
931
+ tag,
828
932
  folderPath,
829
933
  limit: limit?.toString(),
830
934
  },
@@ -840,7 +944,7 @@ async function handleGetLibrary(args, config) {
840
944
  };
841
945
  }
842
946
  const lines = [
843
- `Library · scope=${scope ?? "mine"} · ${res.artifacts.length} item${res.artifacts.length === 1 ? "" : "s"}`,
947
+ `Library · scope=${scope ?? "mine"}${kind ? ` · kind=${kind}` : ""} · ${res.artifacts.length} item${res.artifacts.length === 1 ? "" : "s"}`,
844
948
  "",
845
949
  ];
846
950
  for (const a of res.artifacts) {
@@ -848,7 +952,12 @@ async function handleGetLibrary(args, config) {
848
952
  const v = a.version ? ` v${a.version}` : "";
849
953
  const life = a.lifecycle ? ` · ${a.lifecycle}` : "";
850
954
  const when = a.updatedAt ? ` · ${(0, shared_1.timeAgo)(a.updatedAt)}` : "";
851
- lines.push(`[${a.type}] ${loc}${a.key ?? a.title}${v}${life}${when}`);
955
+ // Lead with the canonical kind (doc | skill). Tags carry the legacy
956
+ // doc-shape (spec/decision/...) plus any author-added labels — surface
957
+ // them after the kind so the row is self-describing.
958
+ const k = a.kind ?? (a.type === "note" ? "doc" : "doc");
959
+ const tagList = (a.tags ?? []).length > 0 ? ` [${a.tags.join(", ")}]` : "";
960
+ lines.push(`[${k}]${tagList} ${loc}${a.key ?? a.title}${v}${life}${when}`);
852
961
  lines.push(` ${a.title}`);
853
962
  lines.push("");
854
963
  }
package/dist/utils.js CHANGED
@@ -208,6 +208,7 @@ thought, use the \`codiedev\` CLI via Bash:**
208
208
  |---|---|
209
209
  | "push this spec" / "save this as a skill" | \`codiedev push <file.md>\` |
210
210
  | "pull X" / "grab the latest spec-X" / "what did Maya push?" | \`codiedev pull <key>\` |
211
+ | "delete X" / "remove that test push" / "rm spec-old" | \`codiedev delete <key>\` (always confirm with the user first) |
211
212
  | "ping Nic about this" / "ask Maya for her take" | \`codiedev ping <name> "<msg>" [--with <key>]\` |
212
213
  | "any messages?" / "check my inbox" / "what did Nic say?" | \`codiedev inbox\` |
213
214
  | "read Nic's reply" / "mark that ping read" | \`codiedev read <ping-id>\` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codiedev",
3
- "version": "0.5.2",
3
+ "version": "0.5.4",
4
4
  "description": "Connect Claude Code or Codex to CodieDev for org-wide session capture and artifact collaboration",
5
5
  "bin": {
6
6
  "codiedev": "./dist/cli.js",