codiedev 0.9.83 → 0.9.85

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.
@@ -5,7 +5,7 @@ exports.teamSkillSessionOutput = teamSkillSessionOutput;
5
5
  /** Session-start context uses each client's supported output contract. */
6
6
  exports.TEAM_SKILL_CONTEXT = `This machine is connected to Codiedev, the team's artifact and skill library.
7
7
  Before a substantial coding task, run codiedev search "<brief task description>" and reuse a relevant team skill by running codiedev pull <exact-key> and following its instructions. If no skill fits, continue the task.
8
- Use codiedev push <file.md> to share an artifact when asked, codiedev ask "<question>" for team knowledge, and codiedev inbox to check messages. Use codiedev --help for other commands. If codiedev is unavailable, use npx codiedev@latest.`;
8
+ Use codiedev push <file.md> to share an artifact when asked, and codiedev inbox to check messages. Use codiedev --help for other commands. If codiedev is unavailable, use npx codiedev@latest.`;
9
9
  function teamSkillSessionOutput(source, context = exports.TEAM_SKILL_CONTEXT) {
10
10
  return source === "cursor" ? { additional_context: context } : { additionalContext: context };
11
11
  }
@@ -0,0 +1,22 @@
1
+ export interface UnreadPings {
2
+ count: number;
3
+ newestPingId: string | null;
4
+ from: string[];
5
+ senderCount?: number;
6
+ }
7
+ /** Repeat an unchanged notice at most this often. A new ping always shows. */
8
+ export declare const UNREAD_NOTICE_INTERVAL_MS: number;
9
+ export declare function parseUnreadPings(value: unknown): UnreadPings | null;
10
+ /** The line added to the session's context. Written for the agent: it says
11
+ * what is waiting and what to do about it. */
12
+ export declare function unreadNoticeLine(u: UnreadPings): string;
13
+ /**
14
+ * Returns the notice to print, or null. Shown when the newest unread ping is
15
+ * one we haven't announced, or the same pile is still there a day later.
16
+ * Records that it spoke; any failure is silent — never slow or break a
17
+ * session start over a reminder.
18
+ */
19
+ export declare function takeUnreadNotice(value: unknown, options?: {
20
+ dir?: string;
21
+ now?: number;
22
+ }): string | null;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.UNREAD_NOTICE_INTERVAL_MS = void 0;
7
+ exports.parseUnreadPings = parseUnreadPings;
8
+ exports.unreadNoticeLine = unreadNoticeLine;
9
+ exports.takeUnreadNotice = takeUnreadNotice;
10
+ const fs_1 = __importDefault(require("fs"));
11
+ const path_1 = __importDefault(require("path"));
12
+ const configDir_1 = require("./configDir");
13
+ /** Repeat an unchanged notice at most this often. A new ping always shows. */
14
+ exports.UNREAD_NOTICE_INTERVAL_MS = 20 * 60 * 60 * 1000;
15
+ const STATE_FILE = "unread-notice.json";
16
+ function parseUnreadPings(value) {
17
+ if (!value || typeof value !== "object")
18
+ return null;
19
+ const v = value;
20
+ if (typeof v.count !== "number" || !Number.isFinite(v.count) || v.count <= 0)
21
+ return null;
22
+ return {
23
+ count: Math.floor(v.count),
24
+ newestPingId: typeof v.newestPingId === "string" ? v.newestPingId : null,
25
+ from: Array.isArray(v.from) ? v.from.filter((n) => typeof n === "string" && n.trim() !== "") : [],
26
+ senderCount: typeof v.senderCount === "number" ? v.senderCount : undefined,
27
+ };
28
+ }
29
+ function nameList(from, senderCount) {
30
+ if (from.length === 0)
31
+ return "";
32
+ const others = Math.max(0, senderCount - from.length);
33
+ const names = others > 0 ? [...from, `${others} other${others === 1 ? "" : "s"}`] : from;
34
+ if (names.length === 1)
35
+ return ` from ${names[0]}`;
36
+ return ` from ${names.slice(0, -1).join(", ")} and ${names[names.length - 1]}`;
37
+ }
38
+ /** The line added to the session's context. Written for the agent: it says
39
+ * what is waiting and what to do about it. */
40
+ function unreadNoticeLine(u) {
41
+ const who = nameList(u.from, u.senderCount ?? u.from.length);
42
+ return (`Codiedev: ${u.count} unread message${u.count === 1 ? "" : "s"}${who}. ` +
43
+ "Tell the user at the start of your first reply, and offer to show them with `codiedev inbox --unread`. " +
44
+ 'Answer one with `codiedev reply <ping-id> "<message>"`.');
45
+ }
46
+ function readState(dir) {
47
+ try {
48
+ const raw = JSON.parse(fs_1.default.readFileSync(path_1.default.join(dir, STATE_FILE), "utf8"));
49
+ if (typeof raw?.at !== "number")
50
+ return null;
51
+ return { newestPingId: typeof raw.newestPingId === "string" ? raw.newestPingId : null, at: raw.at };
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ /**
58
+ * Returns the notice to print, or null. Shown when the newest unread ping is
59
+ * one we haven't announced, or the same pile is still there a day later.
60
+ * Records that it spoke; any failure is silent — never slow or break a
61
+ * session start over a reminder.
62
+ */
63
+ function takeUnreadNotice(value, options = {}) {
64
+ try {
65
+ const unread = parseUnreadPings(value);
66
+ if (!unread)
67
+ return null;
68
+ const dir = options.dir ?? (0, configDir_1.codiedevStateDir)();
69
+ const now = options.now ?? Date.now();
70
+ const last = readState(dir);
71
+ const sameNewest = !!last && last.newestPingId === unread.newestPingId;
72
+ if (sameNewest && last.at <= now && now - last.at < exports.UNREAD_NOTICE_INTERVAL_MS)
73
+ return null;
74
+ fs_1.default.mkdirSync(dir, { recursive: true });
75
+ fs_1.default.writeFileSync(path_1.default.join(dir, STATE_FILE), JSON.stringify({ newestPingId: unread.newestPingId, at: now }));
76
+ return unreadNoticeLine(unread);
77
+ }
78
+ catch {
79
+ return null;
80
+ }
81
+ }
package/dist/utils.js CHANGED
@@ -1673,14 +1673,14 @@ thought, use the \`codiedev\` CLI via Bash:**
1673
1673
  | "push this spec" / "save this as a skill" | \`codiedev push <file.md>\` |
1674
1674
  | "pull X" / "grab the latest spec-X" / "what did a teammate push?" | \`codiedev pull <key>\` |
1675
1675
  | "delete X" / "remove that test push" / "rm spec-old" | \`codiedev delete <key>\` (always confirm with the user first) |
1676
- | "ping a teammate about this" / "ask someone for their take" | \`codiedev ping <name> "<msg>" [--with <key>]\` |
1676
+ | "ping a teammate about this" / "ask someone for their take" / "send them this file" | \`codiedev ping <name> "<msg>" [--with <key>] [--file <path>]\` |
1677
1677
  | "any messages?" / "check my inbox" / "what did a teammate say?" | \`codiedev inbox\` |
1678
1678
  | "read that reply" / "mark that ping read" | \`codiedev read <ping-id>\` |
1679
+ | "reply to that" / "tell them X" (answering a message from \`codiedev inbox\`) | \`codiedev reply <ping-id> "<msg>" [--file <path>]\` (not a new ping: this threads it and marks theirs answered) |
1679
1680
  | "note that X is a follow-up" / "remember X" | \`codiedev note "<text>"\` |
1680
1681
  | "share with a teammate" / "give someone access" (no notification) | \`codiedev share <key> <name> [--role read\\|edit]\` |
1681
1682
  | "send this to a teammate" / "ask someone to look at this" | \`codiedev send <key> <name> ["<msg>"]\` |
1682
1683
  | "find something about X" / "has anyone solved Y?" | \`codiedev search "<query>" [--limit N]\` |
1683
- | "why did we…?" / "what does the team know about X?" | \`codiedev ask "<question>"\` (synthesized answer + citations) |
1684
1684
  | "show my library" / "what artifacts exist?" | \`codiedev library [--scope mine\\|shared\\|all] [--kind doc\\|skill]\` |
1685
1685
  | "run my agent's test cases" / "check the dataset on model Y" / "run v2 of the dataset" | \`codiedev traces cases <agent> [--dataset <name> [--version <n>]] [--model <id>]\` (writes cases + RUN_CASES.md + results.json; follow it, then \`codiedev traces report <results.json>\`) |
1686
1686
  | "how are my agents doing?" / "what's failing this week?" / "show the booking agent's failed runs" / "why did run X fail?" | \`codiedev traces overview\`; \`codiedev traces runs <agent> [--failed] [--flag <issue>] [--days n]\`; \`codiedev traces run <run> --agent <name>\` (add \`--json\` to read the data yourself) |
@@ -1695,9 +1695,10 @@ thought, use the \`codiedev\` CLI via Bash:**
1695
1695
  is classified into one of two kinds at upload time:
1696
1696
 
1697
1697
  - **skill** — the file has SKILL.md frontmatter (\`name:\` + \`description:\`
1698
- inside a \`---\` block). Lands under \`Artifacts → Skills tab\` and is
1698
+ inside a \`---\` block). Shows on the Skills page in the portal and is
1699
1699
  invokable as a slash command (\`/<name>\`).
1700
- - **doc** — everything else. Lands under \`Artifacts → My artifacts\`.
1700
+ - **doc** — everything else. Lives in the library: list it with
1701
+ \`codiedev library\`, fetch it with \`codiedev pull <key>\`.
1701
1702
 
1702
1703
  Detection is content-based, not filename-based. The filename prefix
1703
1704
  (\`spec-\` / \`decision-\` / \`proposal-\` / \`bugfix-\` / \`review-\` /
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codiedev",
3
- "version": "0.9.83",
3
+ "version": "0.9.85",
4
4
  "description": "Connect Claude Code, Codex, Cursor, OpenCode, or VS Code Copilot to Codiedev for team session capture and artifact collaboration — and run the governed Codie harness",
5
5
  "bin": {
6
6
  "codiedev": "dist/cli.js",
@@ -1 +0,0 @@
1
- export declare function runAsk(args: string[]): Promise<void>;
@@ -1,58 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runAsk = runAsk;
4
- const shared_1 = require("./shared");
5
- function parseArgs(args) {
6
- // Everything after the command, joined back into a question string. Allows
7
- // both quoted and unquoted forms: `codiedev ask "why pg-bouncer?"` or
8
- // `codiedev ask why did we drop pg-bouncer`.
9
- const question = args
10
- .filter((a) => !a.startsWith("--"))
11
- .join(" ")
12
- .trim();
13
- if (!question) {
14
- console.error('Usage: codiedev ask "<question>"');
15
- console.error('Example: codiedev ask "why did we drop pg-bouncer?"');
16
- process.exit(1);
17
- }
18
- return { question };
19
- }
20
- async function runAsk(args) {
21
- const { question } = parseArgs(args);
22
- const config = (0, shared_1.requireConfig)();
23
- const start = Date.now();
24
- try {
25
- const res = await (0, shared_1.apiRequest)("POST", "/api/cli/ask", {
26
- config,
27
- body: { question },
28
- });
29
- (0, shared_1.recordAgentEvent)(config, {
30
- tool: "codiedev_ask",
31
- ok: true,
32
- latencyMs: Date.now() - start,
33
- });
34
- console.log("");
35
- console.log(res.answer);
36
- if (res.citations.length > 0) {
37
- console.log("");
38
- console.log("Sources:");
39
- for (const c of res.citations) {
40
- const label = c.kind === "artifact"
41
- ? `[${c.type}] ${c.title}`
42
- : `[session] ${c.title}`;
43
- console.log(` • ${label}`);
44
- }
45
- }
46
- console.log("");
47
- }
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
- });
55
- console.error(`Ask failed: ${err.message}`);
56
- process.exit(1);
57
- }
58
- }