codiedev 0.7.10 → 0.7.11

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
@@ -26,6 +26,12 @@ const note_1 = require("./commands/note");
26
26
  const promote_1 = require("./commands/promote");
27
27
  const reverseTicket_1 = require("./commands/reverseTicket");
28
28
  const doctor_1 = require("./commands/doctor");
29
+ const search_1 = require("./commands/search");
30
+ const library_1 = require("./commands/library");
31
+ const post_1 = require("./commands/post");
32
+ const share_1 = require("./commands/share");
33
+ const send_1 = require("./commands/send");
34
+ const react_1 = require("./commands/react");
29
35
  const HELP = `
30
36
  CodieDev CLI
31
37
 
@@ -60,9 +66,25 @@ Artifacts:
60
66
  Messaging:
61
67
  codiedev ping <user> "<msg>" [--with <key>]
62
68
  Send a message to a teammate
69
+ codiedev send <key> <user> ["<msg>"] Share an artifact + ping in one step
70
+ codiedev share <key> <user> [--role read|edit]
71
+ Silently grant access (no notification)
63
72
  codiedev inbox [--unread] [--limit N] Show messages
64
73
  codiedev read <ping-id> Mark read + show full message
65
74
 
75
+ Discovery:
76
+ codiedev search "<query>" Semantic search across the team's
77
+ captured sessions and artifacts
78
+ codiedev library [--scope mine|shared|all] [--kind doc|skill]
79
+ [--type T] [--tag X] [--limit N]
80
+ List artifacts in your workspace
81
+
82
+ Feed:
83
+ codiedev post --title "<t>" --body "<b>" [--intent share|request_review|
84
+ request_expertise|link_share|rfc] [--filename <key>]
85
+ [--mention <name>]... Publish to the team feed
86
+ codiedev react <postId> <emoji> Toggle a reaction on a feed post
87
+
66
88
  Capture:
67
89
  codiedev note "<text>" Capture a passing thought
68
90
 
@@ -90,7 +112,7 @@ Examples:
90
112
  codiedev push spec-cart-clear.md # the typical case
91
113
  codiedev push portal-design.md # with name:/description: → skill
92
114
  codiedev pull spec-cart-clear.md
93
- codiedev ping maya "thoughts?" --with spec-cart-clear.md
115
+ codiedev ping <teammate> "thoughts?" --with spec-cart-clear.md
94
116
  codiedev inbox --unread
95
117
  codiedev note "idempotency key is worth a follow-up"
96
118
 
@@ -162,8 +184,8 @@ codiedev ping — send a teammate a message, optionally attached to an artifact
162
184
  Teammates are notified by email and can reply from their own agent.
163
185
 
164
186
  Examples:
165
- codiedev ping maya "thoughts on batch vs parallel?" --with spec-cart-clear.md
166
- codiedev ping nic@signalandcode.co "can you take this one?"
187
+ codiedev ping <teammate> "thoughts on batch vs parallel?" --with spec-cart-clear.md
188
+ codiedev ping <teammate>@example.com "can you take this one?"
167
189
  `.trim(),
168
190
  inbox: `
169
191
  codiedev inbox — show messages from teammates
@@ -242,7 +264,7 @@ specs, reviews, decisions, proposals, and captured thoughts — so:
242
264
 
243
265
  2. Your teammate gets pinged (either directly by you, or because
244
266
  they asked to be kept in the loop on that key):
245
- codiedev ping maya "thoughts?" --with spec-cart-clear.md
267
+ codiedev ping <teammate> "thoughts?" --with spec-cart-clear.md
246
268
 
247
269
  3. They check their inbox:
248
270
  codiedev inbox
@@ -305,9 +327,9 @@ If you use Claude Code or Codex, the agent already knows the commands —
305
327
  'codiedev connect' installs instructions into your user-level config.
306
328
  Just say things like:
307
329
 
308
- "push this spec and ping Nic"
330
+ "push this spec and ping a teammate"
309
331
  "any messages?"
310
- "pull Maya's latest spec"
332
+ "pull a teammate's latest spec"
311
333
 
312
334
  The agent will run the right command via Bash.
313
335
 
@@ -408,6 +430,25 @@ async function main() {
408
430
  case "reverseTicket":
409
431
  await (0, reverseTicket_1.runReverseTicket)(rest);
410
432
  return;
433
+ case "search":
434
+ await (0, search_1.runSearch)(rest);
435
+ return;
436
+ case "library":
437
+ case "ls":
438
+ await (0, library_1.runLibrary)(rest);
439
+ return;
440
+ case "post":
441
+ await (0, post_1.runPost)(rest);
442
+ return;
443
+ case "share":
444
+ await (0, share_1.runShare)(rest);
445
+ return;
446
+ case "send":
447
+ await (0, send_1.runSend)(rest);
448
+ return;
449
+ case "react":
450
+ await (0, react_1.runReact)(rest);
451
+ return;
411
452
  default:
412
453
  console.error(`Unknown command: ${command}`);
413
454
  console.error(HELP);
@@ -20,11 +20,17 @@ function parseArgs(args) {
20
20
  async function runAsk(args) {
21
21
  const { question } = parseArgs(args);
22
22
  const config = (0, shared_1.requireConfig)();
23
+ const start = Date.now();
23
24
  try {
24
25
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/ask", {
25
26
  config,
26
27
  body: { question },
27
28
  });
29
+ (0, shared_1.recordAgentEvent)(config, {
30
+ tool: "codiedev_ask",
31
+ ok: true,
32
+ latencyMs: Date.now() - start,
33
+ });
28
34
  console.log("");
29
35
  console.log(res.answer);
30
36
  if (res.citations.length > 0) {
@@ -40,6 +46,12 @@ async function runAsk(args) {
40
46
  console.log("");
41
47
  }
42
48
  catch (err) {
49
+ (0, shared_1.recordAgentEvent)(config, {
50
+ tool: "codiedev_ask",
51
+ ok: false,
52
+ latencyMs: Date.now() - start,
53
+ error: err.message,
54
+ });
43
55
  console.error(`Ask failed: ${err.message}`);
44
56
  process.exit(1);
45
57
  }
@@ -75,11 +75,17 @@ async function runDelete(args) {
75
75
  return;
76
76
  }
77
77
  }
78
+ const start = Date.now();
78
79
  try {
79
80
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/delete", {
80
81
  config,
81
82
  body: { key },
82
83
  });
84
+ (0, shared_1.recordAgentEvent)(config, {
85
+ tool: "codiedev_delete",
86
+ ok: true,
87
+ latencyMs: Date.now() - start,
88
+ });
83
89
  if (res.deleted === 0) {
84
90
  console.log(`No artifact found with key '${key}'. Nothing to delete.`);
85
91
  return;
@@ -90,6 +96,12 @@ async function runDelete(args) {
90
96
  console.log(`✓ Deleted ${res.deleted} version${res.deleted === 1 ? "" : "s"}${cascaded} of '${res.key}'.`);
91
97
  }
92
98
  catch (err) {
99
+ (0, shared_1.recordAgentEvent)(config, {
100
+ tool: "codiedev_delete",
101
+ ok: false,
102
+ latencyMs: Date.now() - start,
103
+ error: err.message,
104
+ });
93
105
  console.error(`Delete failed: ${err.message}`);
94
106
  process.exit(1);
95
107
  }
@@ -40,6 +40,7 @@ const os = __importStar(require("os"));
40
40
  const child_process_1 = require("child_process");
41
41
  const shared_1 = require("./shared");
42
42
  const utils_1 = require("../utils");
43
+ const detection_1 = require("../detection");
43
44
  const version_1 = require("../version");
44
45
  const upgradeNudge_1 = require("../upgradeNudge");
45
46
  const CLAUDE_SETTINGS_PATH = path.join(os.homedir(), ".claude", "settings.json");
@@ -48,7 +49,6 @@ const CODEX_HOOKS_PATH = path.join(os.homedir(), ".codex", "hooks.json");
48
49
  const CODEX_INSTRUCTIONS_PATH = path.join(os.homedir(), ".codex", "AGENTS.md");
49
50
  const CURSOR_HOOKS_PATH = path.join(os.homedir(), ".cursor", "hooks.json");
50
51
  const CURSOR_INSTRUCTIONS_PATH = path.join(os.homedir(), ".cursor", "rules", "codiedev.mdc");
51
- const CURSOR_MCP_PATH = path.join(os.homedir(), ".cursor", "mcp.json");
52
52
  function symbol(status) {
53
53
  if (status === "pass")
54
54
  return "✓";
@@ -62,27 +62,9 @@ function codexInstalled() {
62
62
  function cursorInstalled() {
63
63
  return fs.existsSync(path.join(os.homedir(), ".cursor"));
64
64
  }
65
- function hasCursorMcpEntry() {
66
- try {
67
- if (!fs.existsSync(CURSOR_MCP_PATH))
68
- return false;
69
- const raw = fs.readFileSync(CURSOR_MCP_PATH, "utf8");
70
- const parsed = JSON.parse(raw);
71
- const servers = parsed.mcpServers;
72
- return !!servers && "codiedev" in servers;
73
- }
74
- catch {
75
- return false;
76
- }
77
- }
78
- // Match both legacy `npx codiedev-hook ...` and absolute-path forms
79
- // `<node> <.../codiedev/dist/hook.js> ...` — installer switched to absolute
80
- // paths in 0.6.1 to work in GUI-launched contexts where shell PATH is missing.
81
- function isCodiedevHookCommand(cmd) {
82
- if (!cmd)
83
- return false;
84
- return cmd.includes("codiedev-hook") || /codiedev[\\/]dist[\\/]hook/.test(cmd);
85
- }
65
+ // `isCodiedevHookCommand` lives in ../detection alongside detectClaudeCode
66
+ // so utils.ts and doctor.ts share one definition (they used to drift —
67
+ // each had its own copy).
86
68
  // Cursor's hooks.json schema is { hooks: { sessionEnd: [{ command, ... }] } }
87
69
  // — flat array of objects with `command`, not the Claude/Codex nested
88
70
  // `{ hooks: [{ command }] }` wrapper.
@@ -95,7 +77,7 @@ function hasCursorHook() {
95
77
  const arr = parsed.hooks?.sessionEnd;
96
78
  if (!Array.isArray(arr))
97
79
  return false;
98
- return arr.some((h) => isCodiedevHookCommand(h.command));
80
+ return arr.some((h) => (0, detection_1.isCodiedevHookCommand)(h.command));
99
81
  }
100
82
  catch {
101
83
  return false;
@@ -114,7 +96,7 @@ function hasCodiedevHook(settingsPath, hookKey) {
114
96
  const inner = h.hooks;
115
97
  if (!Array.isArray(inner))
116
98
  return false;
117
- return inner.some((x) => isCodiedevHookCommand(x.command));
99
+ return inner.some((x) => (0, detection_1.isCodiedevHookCommand)(x.command));
118
100
  });
119
101
  }
120
102
  catch {
@@ -307,13 +289,6 @@ async function runDoctor(_args) {
307
289
  ? "~/.cursor/rules/codiedev.mdc"
308
290
  : "missing — re-run `codiedev connect`",
309
291
  });
310
- checks.push({
311
- name: "Cursor MCP server",
312
- status: hasCursorMcpEntry() ? "pass" : "fail",
313
- detail: hasCursorMcpEntry()
314
- ? "~/.cursor/mcp.json"
315
- : "missing — re-run `codiedev connect`",
316
- });
317
292
  }
318
293
  else {
319
294
  checks.push({
@@ -26,6 +26,7 @@ function parseInboxArgs(args) {
26
26
  async function runInbox(args) {
27
27
  const { unreadOnly, limit } = parseInboxArgs(args);
28
28
  const config = (0, shared_1.requireConfig)();
29
+ const start = Date.now();
29
30
  try {
30
31
  const res = await (0, shared_1.apiRequest)("GET", "/api/cli/inbox", {
31
32
  config,
@@ -34,6 +35,11 @@ async function runInbox(args) {
34
35
  limit,
35
36
  },
36
37
  });
38
+ (0, shared_1.recordAgentEvent)(config, {
39
+ tool: "codiedev_inbox",
40
+ ok: true,
41
+ latencyMs: Date.now() - start,
42
+ });
37
43
  const pings = res.pings;
38
44
  const unreadCount = pings.filter((p) => !p.readAt).length;
39
45
  if (pings.length === 0) {
@@ -56,6 +62,12 @@ async function runInbox(args) {
56
62
  console.log(`Mark read: codiedev read <ping-id>`);
57
63
  }
58
64
  catch (err) {
65
+ (0, shared_1.recordAgentEvent)(config, {
66
+ tool: "codiedev_inbox",
67
+ ok: false,
68
+ latencyMs: Date.now() - start,
69
+ error: err.message,
70
+ });
59
71
  console.error(`Inbox failed: ${err.message}`);
60
72
  process.exit(1);
61
73
  }
@@ -67,6 +79,7 @@ async function runRead(args) {
67
79
  process.exit(1);
68
80
  }
69
81
  const config = (0, shared_1.requireConfig)();
82
+ const start = Date.now();
70
83
  try {
71
84
  // First, fetch inbox so we can show the full body (markRead endpoint
72
85
  // doesn't return content).
@@ -76,6 +89,12 @@ async function runRead(args) {
76
89
  });
77
90
  const ping = listRes.pings.find((p) => p.pingId === pingId);
78
91
  if (!ping) {
92
+ (0, shared_1.recordAgentEvent)(config, {
93
+ tool: "codiedev_read",
94
+ ok: false,
95
+ latencyMs: Date.now() - start,
96
+ error: "ping not found",
97
+ });
79
98
  console.error(`Ping not found: ${pingId}`);
80
99
  process.exit(1);
81
100
  }
@@ -83,6 +102,11 @@ async function runRead(args) {
83
102
  config,
84
103
  body: { pingId },
85
104
  });
105
+ (0, shared_1.recordAgentEvent)(config, {
106
+ tool: "codiedev_read",
107
+ ok: true,
108
+ latencyMs: Date.now() - start,
109
+ });
86
110
  const from = ping.from?.name ?? "unknown";
87
111
  const when = (0, shared_1.timeAgo)(ping.createdAt);
88
112
  const where = ping.subjectKey ? ` · on ${ping.subjectKey}` : "";
@@ -100,6 +124,12 @@ async function runRead(args) {
100
124
  }
101
125
  }
102
126
  catch (err) {
127
+ (0, shared_1.recordAgentEvent)(config, {
128
+ tool: "codiedev_read",
129
+ ok: false,
130
+ latencyMs: Date.now() - start,
131
+ error: err.message,
132
+ });
103
133
  console.error(`Read failed: ${err.message}`);
104
134
  process.exit(1);
105
135
  }
@@ -0,0 +1,2 @@
1
+ import type { CodiedevConfig } from "../utils";
2
+ export declare function runLibrary(args: string[], configOverride?: CodiedevConfig): Promise<void>;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ // `codiedev library [--scope mine|shared|all] [--kind doc|skill] [--tag X]
3
+ // [--type spec|...] [--limit N]` — list artifacts in your CodieDev workspace.
4
+ // Server applies companyId scoping; --scope filters within that.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runLibrary = runLibrary;
7
+ const shared_1 = require("./shared");
8
+ const VALID_SCOPES = new Set(["mine", "shared", "all"]);
9
+ const VALID_KINDS = new Set(["doc", "skill"]);
10
+ const VALID_TYPES = new Set([
11
+ "spec",
12
+ "bugfix",
13
+ "decision",
14
+ "proposal",
15
+ "review",
16
+ "message",
17
+ "note",
18
+ ]);
19
+ function readFlag(args, i, flag) {
20
+ const a = args[i];
21
+ if (a === flag && i + 1 < args.length)
22
+ return { value: args[i + 1], next: i + 2 };
23
+ if (a.startsWith(flag + "="))
24
+ return { value: a.slice(flag.length + 1), next: i + 1 };
25
+ return { value: undefined, next: i + 1 };
26
+ }
27
+ function parseArgs(args) {
28
+ const out = {};
29
+ let i = 0;
30
+ while (i < args.length) {
31
+ const a = args[i];
32
+ let consumed = 1;
33
+ for (const flag of ["--scope", "--kind", "--tag", "--type", "--limit"]) {
34
+ const { value, next } = readFlag(args, i, flag);
35
+ if (value !== undefined) {
36
+ const key = flag.slice(2);
37
+ if (key === "limit") {
38
+ const n = Number(value);
39
+ if (Number.isInteger(n) && n > 0)
40
+ out.limit = n;
41
+ }
42
+ else {
43
+ out[key] = value;
44
+ }
45
+ consumed = next - i;
46
+ break;
47
+ }
48
+ }
49
+ i += consumed;
50
+ }
51
+ if (out.scope && !VALID_SCOPES.has(out.scope)) {
52
+ console.error(`Invalid --scope. Valid: ${[...VALID_SCOPES].join(", ")}`);
53
+ process.exit(1);
54
+ }
55
+ if (out.kind && !VALID_KINDS.has(out.kind)) {
56
+ console.error(`Invalid --kind. Valid: ${[...VALID_KINDS].join(", ")}`);
57
+ process.exit(1);
58
+ }
59
+ if (out.type && !VALID_TYPES.has(out.type)) {
60
+ console.error(`Invalid --type. Valid: ${[...VALID_TYPES].join(", ")}`);
61
+ process.exit(1);
62
+ }
63
+ return out;
64
+ }
65
+ async function runLibrary(args, configOverride) {
66
+ const parsed = parseArgs(args);
67
+ const config = configOverride ?? (0, shared_1.requireConfig)();
68
+ const start = Date.now();
69
+ try {
70
+ const res = await (0, shared_1.apiRequest)("GET", "/api/cli/library", {
71
+ config,
72
+ query: {
73
+ scope: parsed.scope,
74
+ kind: parsed.kind,
75
+ tag: parsed.tag,
76
+ type: parsed.type,
77
+ limit: parsed.limit,
78
+ },
79
+ });
80
+ (0, shared_1.recordAgentEvent)(config, {
81
+ tool: "codiedev_get_library",
82
+ ok: true,
83
+ latencyMs: Date.now() - start,
84
+ });
85
+ if (!res.artifacts || res.artifacts.length === 0) {
86
+ console.log("No artifacts found.");
87
+ return;
88
+ }
89
+ for (const a of res.artifacts) {
90
+ const tagStr = a.tags.length > 0 ? ` [${a.tags.join(", ")}]` : "";
91
+ console.log(` ${a.kind === "skill" ? "/" : "•"} ${a.title} (${a.type})${tagStr}`);
92
+ console.log(` ${a.key} · v${a.version} · ${(0, shared_1.timeAgo)(a.updatedAt)}`);
93
+ }
94
+ }
95
+ catch (err) {
96
+ (0, shared_1.recordAgentEvent)(config, {
97
+ tool: "codiedev_get_library",
98
+ ok: false,
99
+ latencyMs: Date.now() - start,
100
+ error: err.message,
101
+ });
102
+ console.error(`Library listing failed: ${err.message}`);
103
+ process.exit(1);
104
+ }
105
+ }
@@ -14,14 +14,26 @@ async function runNote(args) {
14
14
  process.exit(1);
15
15
  }
16
16
  const config = (0, shared_1.requireConfig)();
17
+ const start = Date.now();
17
18
  try {
18
19
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/note", {
19
20
  config,
20
21
  body: { body },
21
22
  });
23
+ (0, shared_1.recordAgentEvent)(config, {
24
+ tool: "codiedev_note",
25
+ ok: true,
26
+ latencyMs: Date.now() - start,
27
+ });
22
28
  console.log(`✓ Noted (${res.key})`);
23
29
  }
24
30
  catch (err) {
31
+ (0, shared_1.recordAgentEvent)(config, {
32
+ tool: "codiedev_note",
33
+ ok: false,
34
+ latencyMs: Date.now() - start,
35
+ error: err.message,
36
+ });
25
37
  console.error(`Note failed: ${err.message}`);
26
38
  process.exit(1);
27
39
  }
@@ -31,15 +31,27 @@ function parseArgs(args) {
31
31
  async function runPing(args) {
32
32
  const { to, body, subjectKey } = parseArgs(args);
33
33
  const config = (0, shared_1.requireConfig)();
34
+ const start = Date.now();
34
35
  try {
35
36
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/ping", {
36
37
  config,
37
38
  body: { to, body, subjectKey },
38
39
  });
40
+ (0, shared_1.recordAgentEvent)(config, {
41
+ tool: "codiedev_ping",
42
+ ok: true,
43
+ latencyMs: Date.now() - start,
44
+ });
39
45
  console.log(`✓ Pinged ${res.recipient.name} <${res.recipient.email}>${subjectKey ? ` on ${subjectKey}` : ""}`);
40
46
  }
41
47
  catch (err) {
42
48
  const e = err;
49
+ (0, shared_1.recordAgentEvent)(config, {
50
+ tool: "codiedev_ping",
51
+ ok: false,
52
+ latencyMs: Date.now() - start,
53
+ error: e.message,
54
+ });
43
55
  if (e.status === 409 && e.body?.candidates?.length) {
44
56
  console.error(`${e.message}: multiple matches for "${to}":`);
45
57
  for (const c of e.body.candidates) {
@@ -0,0 +1,2 @@
1
+ import type { CodiedevConfig } from "../utils";
2
+ export declare function runPost(args: string[], configOverride?: CodiedevConfig): Promise<void>;
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ // `codiedev post --title ... --body ... [--intent share|...] [--filename ...]
3
+ // [--mention NAME ...] [--tag X ...]` — publish to the team feed. Intended
4
+ // for broad-team reach: announcing a skill, asking who knows about X,
5
+ // proposing a change. Use `codiedev send` to address a single teammate.
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.runPost = runPost;
8
+ const shared_1 = require("./shared");
9
+ const VALID_INTENTS = new Set([
10
+ "share",
11
+ "request_review",
12
+ "request_expertise",
13
+ "link_share",
14
+ "rfc",
15
+ ]);
16
+ const VALID_FORMATS = new Set(["article", "quick", "workflow", "review"]);
17
+ function parseArgs(args) {
18
+ let title;
19
+ let body;
20
+ let intent;
21
+ let filename;
22
+ let format;
23
+ const mentions = [];
24
+ const tags = [];
25
+ for (let i = 0; i < args.length; i++) {
26
+ const a = args[i];
27
+ const next = (k) => a === k && i + 1 < args.length ? args[++i] : a.startsWith(k + "=") ? a.slice(k.length + 1) : undefined;
28
+ let v;
29
+ if ((v = next("--title")) !== undefined)
30
+ title = v;
31
+ else if ((v = next("--body")) !== undefined)
32
+ body = v;
33
+ else if ((v = next("--intent")) !== undefined)
34
+ intent = v;
35
+ else if ((v = next("--filename")) !== undefined)
36
+ filename = v;
37
+ else if ((v = next("--format")) !== undefined)
38
+ format = v;
39
+ else if ((v = next("--mention")) !== undefined)
40
+ mentions.push(v);
41
+ else if ((v = next("--tag")) !== undefined)
42
+ tags.push(v);
43
+ }
44
+ if (!title || !title.trim()) {
45
+ console.error('Usage: codiedev post --title "<title>" --body "<body>" [--intent share|request_review|request_expertise|link_share|rfc] [--filename <key>] [--mention <name>]...');
46
+ process.exit(1);
47
+ }
48
+ if (!body || !body.trim()) {
49
+ console.error("--body required");
50
+ process.exit(1);
51
+ }
52
+ if (intent && !VALID_INTENTS.has(intent)) {
53
+ console.error(`Invalid --intent. Valid: ${[...VALID_INTENTS].join(", ")}`);
54
+ process.exit(1);
55
+ }
56
+ if (format && !VALID_FORMATS.has(format)) {
57
+ console.error(`Invalid --format. Valid: ${[...VALID_FORMATS].join(", ")}`);
58
+ process.exit(1);
59
+ }
60
+ return { title, body, intent, filename, format, mentions, tags };
61
+ }
62
+ async function runPost(args, configOverride) {
63
+ const parsed = parseArgs(args);
64
+ const config = configOverride ?? (0, shared_1.requireConfig)();
65
+ const start = Date.now();
66
+ try {
67
+ const res = await (0, shared_1.apiRequest)("POST", "/api/cli/post-to-feed", {
68
+ config,
69
+ body: {
70
+ title: parsed.title,
71
+ body: parsed.body,
72
+ intent: parsed.intent,
73
+ filename: parsed.filename,
74
+ format: parsed.format,
75
+ mentions: parsed.mentions.length > 0 ? parsed.mentions : undefined,
76
+ tags: parsed.tags.length > 0 ? parsed.tags : undefined,
77
+ },
78
+ });
79
+ (0, shared_1.recordAgentEvent)(config, {
80
+ tool: "codiedev_post_to_feed",
81
+ ok: true,
82
+ latencyMs: Date.now() - start,
83
+ });
84
+ console.log(`Posted to the team feed${res.postId ? ` (id: ${res.postId})` : ""}.`);
85
+ }
86
+ catch (err) {
87
+ (0, shared_1.recordAgentEvent)(config, {
88
+ tool: "codiedev_post_to_feed",
89
+ ok: false,
90
+ latencyMs: Date.now() - start,
91
+ error: err.message,
92
+ });
93
+ console.error(`Post failed: ${err.message}`);
94
+ process.exit(1);
95
+ }
96
+ }
@@ -26,15 +26,27 @@ function parseArgs(args) {
26
26
  async function runPromote(args) {
27
27
  const { artifactId, keyOverride } = parseArgs(args);
28
28
  const config = (0, shared_1.requireConfig)();
29
+ const start = Date.now();
29
30
  try {
30
31
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/promote", {
31
32
  config,
32
33
  body: { artifactId, keyOverride },
33
34
  });
35
+ (0, shared_1.recordAgentEvent)(config, {
36
+ tool: "codiedev_promote",
37
+ ok: true,
38
+ latencyMs: Date.now() - start,
39
+ });
34
40
  console.log(`✓ Promoted to authored artifact ${res.key}`);
35
41
  console.log(` id: ${res.artifactId}`);
36
42
  }
37
43
  catch (err) {
44
+ (0, shared_1.recordAgentEvent)(config, {
45
+ tool: "codiedev_promote",
46
+ ok: false,
47
+ latencyMs: Date.now() - start,
48
+ error: err.message,
49
+ });
38
50
  console.error(`Promote failed: ${err.message}`);
39
51
  process.exit(1);
40
52
  }
@@ -72,11 +72,17 @@ function parseArgs(args) {
72
72
  async function runPull(args) {
73
73
  const { key, version, out } = parseArgs(args);
74
74
  const config = (0, shared_1.requireConfig)();
75
+ const start = Date.now();
75
76
  try {
76
77
  const res = await (0, shared_1.apiRequest)("GET", "/api/cli/pull", {
77
78
  config,
78
79
  query: { key, version },
79
80
  });
81
+ (0, shared_1.recordAgentEvent)(config, {
82
+ tool: "codiedev_pull",
83
+ ok: true,
84
+ latencyMs: Date.now() - start,
85
+ });
80
86
  const a = res.artifact;
81
87
  if (out) {
82
88
  const absolute = path.isAbsolute(out) ? out : path.resolve(process.cwd(), out);
@@ -95,6 +101,12 @@ async function runPull(args) {
95
101
  }
96
102
  catch (err) {
97
103
  const e = err;
104
+ (0, shared_1.recordAgentEvent)(config, {
105
+ tool: "codiedev_pull",
106
+ ok: false,
107
+ latencyMs: Date.now() - start,
108
+ error: e.message,
109
+ });
98
110
  if (e.status === 404) {
99
111
  console.error(`Not found: ${key}${version ? ` v${version}` : ""}`);
100
112
  }
@@ -113,6 +113,7 @@ async function runPush(args) {
113
113
  }
114
114
  const filename = path.basename(absolute);
115
115
  const gitRemoteUrl = (0, utils_1.getGitRemoteUrl)(process.cwd()) ?? undefined;
116
+ const start = Date.now();
116
117
  try {
117
118
  const res = await (0, shared_1.apiRequest)("POST", "/api/cli/push", {
118
119
  config,
@@ -126,6 +127,11 @@ async function runPush(args) {
126
127
  gitRemoteUrl,
127
128
  },
128
129
  });
130
+ (0, shared_1.recordAgentEvent)(config, {
131
+ tool: "codiedev_push",
132
+ ok: true,
133
+ latencyMs: Date.now() - start,
134
+ });
129
135
  (0, scope_1.printScope)({ workspaceName: res.workspaceName, matchedRepo: res.matchedRepo });
130
136
  const tagSummary = res.tags && res.tags.length > 0 ? ` tags=[${res.tags.join(", ")}]` : "";
131
137
  console.log(`✓ Pushed ${filename} (kind=${res.kind}${tagSummary}).`);
@@ -133,6 +139,12 @@ async function runPush(args) {
133
139
  console.log(` Pull with: codiedev pull ${filename}`);
134
140
  }
135
141
  catch (err) {
142
+ (0, shared_1.recordAgentEvent)(config, {
143
+ tool: "codiedev_push",
144
+ ok: false,
145
+ latencyMs: Date.now() - start,
146
+ error: err.message,
147
+ });
136
148
  console.error(`Push failed: ${err.message}`);
137
149
  process.exit(1);
138
150
  }