@gobi-ai/cli 1.3.2 → 1.3.3

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.
@@ -4,12 +4,12 @@
4
4
  "name": "gobi-ai"
5
5
  },
6
6
  "description": "Claude Code plugin for the Gobi collaborative knowledge platform CLI",
7
- "version": "1.3.2",
7
+ "version": "1.3.3",
8
8
  "plugins": [
9
9
  {
10
10
  "name": "gobi",
11
11
  "description": "Manage the Gobi collaborative knowledge platform from the command line. Search and ask brains, publish brain documents, create threads, manage sessions, generate images and videos.",
12
- "version": "1.3.2",
12
+ "version": "1.3.3",
13
13
  "author": {
14
14
  "name": "gobi-ai"
15
15
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "gobi",
3
3
  "description": "Manage the Gobi collaborative knowledge platform from the command line",
4
- "version": "1.3.2",
4
+ "version": "1.3.3",
5
5
  "author": {
6
6
  "name": "gobi-ai"
7
7
  },
@@ -0,0 +1,158 @@
1
+ import { readFileSync } from "fs";
2
+ import { apiDelete, apiGet, apiPatch, apiPost } from "../client.js";
3
+ import { isJsonMode, jsonOut, unwrapResp } from "./utils.js";
4
+ function readContent(value) {
5
+ if (value === "-")
6
+ return readFileSync("/dev/stdin", "utf8");
7
+ return value;
8
+ }
9
+ function snippet(content, max = 80) {
10
+ const single = content.replace(/\s+/g, " ");
11
+ return single.length > max ? `${single.slice(0, max)}…` : single;
12
+ }
13
+ function formatProposalLine(p) {
14
+ const status = p.status === "pending" ? "·" : p.status === "accepted" ? "✓" : "✗";
15
+ return `- [${status}] p${p.priority} rev${p.revision} ${p.proposalId.slice(0, 8)} ${snippet(p.content)}`;
16
+ }
17
+ export function registerProposalCommand(program) {
18
+ const proposal = program
19
+ .command("proposal")
20
+ .description("Proposals authored by your agent during chat. Top-5 feed the system prompt; accept/reject/revise post into the originating chat session.");
21
+ // ── List ──
22
+ proposal
23
+ .command("list")
24
+ .description("List proposals (priority ASC, then newest first).")
25
+ .option("--limit <number>", "Max proposals to return (1-200)", "50")
26
+ .action(async (opts) => {
27
+ const params = { limit: parseInt(opts.limit, 10) };
28
+ const resp = (await apiGet("/app/proposals", params));
29
+ const items = (resp.data || []);
30
+ if (isJsonMode(proposal)) {
31
+ jsonOut(items);
32
+ return;
33
+ }
34
+ if (!items.length) {
35
+ console.log("No proposals.");
36
+ return;
37
+ }
38
+ console.log(`Proposals (${items.length}):`);
39
+ for (const p of items)
40
+ console.log(formatProposalLine(p));
41
+ });
42
+ // ── Get ──
43
+ proposal
44
+ .command("get <proposalId>")
45
+ .description("Show one proposal with its history.")
46
+ .action(async (proposalId) => {
47
+ const resp = (await apiGet(`/app/proposals/${proposalId}`));
48
+ const p = unwrapResp(resp);
49
+ if (isJsonMode(proposal)) {
50
+ jsonOut(p);
51
+ return;
52
+ }
53
+ console.log(`Proposal ${p.proposalId}`);
54
+ console.log(` status: ${p.status}`);
55
+ console.log(` priority: ${p.priority}`);
56
+ console.log(` revision: ${p.revision}`);
57
+ console.log(` session: ${p.sessionId ?? "(none)"}`);
58
+ console.log(` created: ${p.createdAt}`);
59
+ console.log("");
60
+ console.log("Content:");
61
+ console.log(p.content);
62
+ if (p.history.length) {
63
+ console.log("");
64
+ console.log("History:");
65
+ for (const h of p.history) {
66
+ const detail = h.type === "revise_requested"
67
+ ? `: ${h.comment}`
68
+ : h.type === "prioritized"
69
+ ? `: priority=${h.priority}`
70
+ : "";
71
+ console.log(` ${h.createdAt} rev${h.revision} ${h.type}${detail}`);
72
+ }
73
+ }
74
+ });
75
+ // ── Edit content ──
76
+ proposal
77
+ .command("edit <proposalId> <content>")
78
+ .description("Replace proposal content (bumps revision). Pass '-' for stdin.")
79
+ .action(async (proposalId, content) => {
80
+ const resp = (await apiPatch(`/app/proposals/${proposalId}`, {
81
+ content: readContent(content),
82
+ }));
83
+ const p = unwrapResp(resp);
84
+ if (isJsonMode(proposal)) {
85
+ jsonOut(p);
86
+ return;
87
+ }
88
+ console.log(`Updated ${p.proposalId} → rev${p.revision}.`);
89
+ });
90
+ // ── Delete ──
91
+ proposal
92
+ .command("delete <proposalId>")
93
+ .description("Delete a proposal.")
94
+ .action(async (proposalId) => {
95
+ await apiDelete(`/app/proposals/${proposalId}`);
96
+ if (isJsonMode(proposal)) {
97
+ jsonOut({ deleted: proposalId });
98
+ return;
99
+ }
100
+ console.log(`Deleted ${proposalId}.`);
101
+ });
102
+ // ── Prioritize ──
103
+ proposal
104
+ .command("prioritize <proposalId> <priority>")
105
+ .description("Set priority (lower = higher). Top 5 feed the system prompt.")
106
+ .action(async (proposalId, priority) => {
107
+ const resp = (await apiPatch(`/app/proposals/${proposalId}/priority`, {
108
+ priority: parseInt(priority, 10),
109
+ }));
110
+ const p = unwrapResp(resp);
111
+ if (isJsonMode(proposal)) {
112
+ jsonOut(p);
113
+ return;
114
+ }
115
+ console.log(`Set ${p.proposalId} priority to ${p.priority}.`);
116
+ });
117
+ // ── Accept ──
118
+ proposal
119
+ .command("accept <proposalId>")
120
+ .description('Accept — posts "Accept your proposal X" into the originating chat session.')
121
+ .action(async (proposalId) => {
122
+ const resp = (await apiPost(`/app/proposals/${proposalId}/accept`));
123
+ const p = unwrapResp(resp);
124
+ if (isJsonMode(proposal)) {
125
+ jsonOut(p);
126
+ return;
127
+ }
128
+ console.log(`Accepted ${p.proposalId}.`);
129
+ });
130
+ // ── Reject ──
131
+ proposal
132
+ .command("reject <proposalId>")
133
+ .description('Reject — posts "Reject your proposal X" into the originating chat session.')
134
+ .action(async (proposalId) => {
135
+ const resp = (await apiPost(`/app/proposals/${proposalId}/reject`));
136
+ const p = unwrapResp(resp);
137
+ if (isJsonMode(proposal)) {
138
+ jsonOut(p);
139
+ return;
140
+ }
141
+ console.log(`Rejected ${p.proposalId}.`);
142
+ });
143
+ // ── Revise ──
144
+ proposal
145
+ .command("revise <proposalId> <comment>")
146
+ .description('Ask the agent to revise — posts "Update your proposal X. Here\'s my comment. {comment}" into the chat session.')
147
+ .action(async (proposalId, comment) => {
148
+ const resp = (await apiPost(`/app/proposals/${proposalId}/revise`, {
149
+ comment: readContent(comment),
150
+ }));
151
+ const p = unwrapResp(resp);
152
+ if (isJsonMode(proposal)) {
153
+ jsonOut(p);
154
+ return;
155
+ }
156
+ console.log(`Revision requested on ${p.proposalId}.`);
157
+ });
158
+ }
package/dist/main.js CHANGED
@@ -13,6 +13,7 @@ import { registerSenseCommand } from "./commands/sense.js";
13
13
  import { registerSyncCommand } from "./commands/sync.js";
14
14
  import { registerUpdateCommand } from "./commands/update.js";
15
15
  import { registerMediaCommand } from "./commands/media.js";
16
+ import { registerProposalCommand } from "./commands/proposal.js";
16
17
  const require = createRequire(import.meta.url);
17
18
  const { version } = require("../package.json");
18
19
  const SKIP_BANNER_COMMANDS = new Set(["auth", "init", "update"]);
@@ -42,6 +43,7 @@ export async function cli() {
42
43
  registerSyncCommand(program);
43
44
  registerUpdateCommand(program);
44
45
  registerMediaCommand(program);
46
+ registerProposalCommand(program);
45
47
  // Propagate helpWidth to all subcommands
46
48
  const helpWidth = process.stdout.columns || 200;
47
49
  for (const cmd of program.commands) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobi-ai/cli",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "CLI client for the Gobi collaborative knowledge platform",
5
5
  "license": "MIT",
6
6
  "type": "module",