@gobi-ai/cli 2.0.4 → 2.0.6
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +56 -42
- package/commands/space-share.md +1 -1
- package/dist/commands/auth.js +38 -9
- package/dist/commands/draft.js +9 -13
- package/dist/commands/global.js +90 -24
- package/dist/commands/init.js +36 -35
- package/dist/commands/media.js +39 -39
- package/dist/commands/saved.js +31 -41
- package/dist/commands/sense.js +4 -4
- package/dist/commands/sessions.js +6 -6
- package/dist/commands/space.js +188 -68
- package/dist/commands/utils.js +7 -2
- package/dist/commands/vault.js +40 -4
- package/dist/main.js +37 -13
- package/package.json +1 -1
- package/skills/gobi-core/SKILL.md +38 -42
- package/skills/gobi-core/references/session.md +10 -10
- package/skills/gobi-core/references/space.md +6 -6
- package/skills/gobi-draft/SKILL.md +4 -4
- package/skills/gobi-draft/references/draft.md +9 -8
- package/skills/gobi-media/SKILL.md +37 -38
- package/skills/gobi-media/references/media.md +59 -59
- package/skills/gobi-saved/SKILL.md +27 -26
- package/skills/gobi-saved/references/saved.md +108 -26
- package/skills/gobi-sense/SKILL.md +8 -8
- package/skills/gobi-sense/references/sense.md +10 -10
- package/skills/gobi-space/SKILL.md +28 -10
- package/skills/gobi-space/references/global.md +21 -15
- package/skills/gobi-space/references/space.md +54 -35
- package/skills/gobi-vault/SKILL.md +12 -5
- package/skills/gobi-vault/references/vault.md +25 -1
- package/skills/gobi-core/references/init.md +0 -10
package/dist/commands/init.js
CHANGED
|
@@ -3,8 +3,6 @@ import { join } from "path";
|
|
|
3
3
|
import inquirer from "inquirer";
|
|
4
4
|
import yaml from "js-yaml";
|
|
5
5
|
import { apiGet, apiPost } from "../client.js";
|
|
6
|
-
import { isAuthenticated } from "../auth/manager.js";
|
|
7
|
-
import { runLoginFlow } from "./auth.js";
|
|
8
6
|
const SETTINGS_DIR = ".gobi";
|
|
9
7
|
const SETTINGS_FILE = "settings.yaml";
|
|
10
8
|
function settingsPath() {
|
|
@@ -21,7 +19,7 @@ export function getSpaceSlug() {
|
|
|
21
19
|
const settings = readSettings();
|
|
22
20
|
const slug = settings?.selectedSpaceSlug;
|
|
23
21
|
if (!slug) {
|
|
24
|
-
throw new Error("Space not set. Run 'gobi space warp'
|
|
22
|
+
throw new Error("Space not set. Run 'gobi space warp' to select a space, or pass --space-slug.");
|
|
25
23
|
}
|
|
26
24
|
return slug;
|
|
27
25
|
}
|
|
@@ -29,27 +27,44 @@ export function getVaultSlug() {
|
|
|
29
27
|
const settings = readSettings();
|
|
30
28
|
const vault = settings?.vaultSlug;
|
|
31
29
|
if (!vault) {
|
|
32
|
-
throw new Error("
|
|
30
|
+
throw new Error("Vault not set. Run 'gobi vault init' first.");
|
|
33
31
|
}
|
|
34
32
|
return vault;
|
|
35
33
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
34
|
+
// Per-command requirement markers. Tri-state: true / false override / inherit
|
|
35
|
+
// from parent. The pre-action warning uses these to decide whether to remind
|
|
36
|
+
// the user to run `gobi vault init` / `gobi space warp`.
|
|
37
|
+
const REQUIRES_VAULT = Symbol.for("gobi.requiresVault");
|
|
38
|
+
const REQUIRES_SPACE = Symbol.for("gobi.requiresSpace");
|
|
39
|
+
export function setVaultRequirement(cmd, value) {
|
|
40
|
+
cmd[REQUIRES_VAULT] = value;
|
|
41
|
+
return cmd;
|
|
42
|
+
}
|
|
43
|
+
export function setSpaceRequirement(cmd, value) {
|
|
44
|
+
cmd[REQUIRES_SPACE] = value;
|
|
45
|
+
return cmd;
|
|
46
|
+
}
|
|
47
|
+
export function requireVault(cmd) {
|
|
48
|
+
return setVaultRequirement(cmd, true);
|
|
49
|
+
}
|
|
50
|
+
export function requireSpace(cmd) {
|
|
51
|
+
return setSpaceRequirement(cmd, true);
|
|
52
|
+
}
|
|
53
|
+
function resolveRequirement(cmd, key) {
|
|
54
|
+
let cur = cmd;
|
|
55
|
+
while (cur) {
|
|
56
|
+
const v = cur[key];
|
|
57
|
+
if (v !== undefined)
|
|
58
|
+
return v;
|
|
59
|
+
cur = cur.parent;
|
|
51
60
|
}
|
|
52
|
-
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
export function commandRequiresVault(cmd) {
|
|
64
|
+
return resolveRequirement(cmd, REQUIRES_VAULT);
|
|
65
|
+
}
|
|
66
|
+
export function commandRequiresSpace(cmd) {
|
|
67
|
+
return resolveRequirement(cmd, REQUIRES_SPACE);
|
|
53
68
|
}
|
|
54
69
|
function ensureSettingsDir() {
|
|
55
70
|
const dir = join(process.cwd(), SETTINGS_DIR);
|
|
@@ -171,13 +186,7 @@ async function createNewVault() {
|
|
|
171
186
|
console.log(`Created vault "${vault.name}" (${vault.vaultId})`);
|
|
172
187
|
return { vaultId: vault.vaultId, name: vault.name };
|
|
173
188
|
}
|
|
174
|
-
export async function
|
|
175
|
-
if (!isAuthenticated()) {
|
|
176
|
-
console.log("Not logged in. Starting login flow...\n");
|
|
177
|
-
await runLoginFlow();
|
|
178
|
-
console.log("");
|
|
179
|
-
}
|
|
180
|
-
// Select or create vault
|
|
189
|
+
export async function runVaultInitFlow() {
|
|
181
190
|
let vaultId;
|
|
182
191
|
let vaultName;
|
|
183
192
|
while (true) {
|
|
@@ -216,11 +225,3 @@ export async function runInitFlow() {
|
|
|
216
225
|
console.log("Created PUBLISH.md");
|
|
217
226
|
}
|
|
218
227
|
}
|
|
219
|
-
export function registerInitCommand(program) {
|
|
220
|
-
program
|
|
221
|
-
.command("init")
|
|
222
|
-
.description("Log in (if needed) and select or create the vault for the current directory.")
|
|
223
|
-
.action(async () => {
|
|
224
|
-
await runInitFlow();
|
|
225
|
-
});
|
|
226
|
-
}
|
package/dist/commands/media.js
CHANGED
|
@@ -127,7 +127,7 @@ export function registerMediaCommand(program) {
|
|
|
127
127
|
// Avatars & Voices
|
|
128
128
|
// ════════════════════════════════════════════════════════════════════
|
|
129
129
|
media
|
|
130
|
-
.command("avatars")
|
|
130
|
+
.command("list-avatars")
|
|
131
131
|
.description("List available avatars.")
|
|
132
132
|
.action(async () => {
|
|
133
133
|
const resp = (await apiGet("/media-gen/avatars"));
|
|
@@ -146,7 +146,7 @@ export function registerMediaCommand(program) {
|
|
|
146
146
|
}
|
|
147
147
|
});
|
|
148
148
|
media
|
|
149
|
-
.command("voices")
|
|
149
|
+
.command("list-voices")
|
|
150
150
|
.description("List available voices.")
|
|
151
151
|
.action(async () => {
|
|
152
152
|
const resp = (await apiGet("/media-gen/voices"));
|
|
@@ -168,7 +168,7 @@ export function registerMediaCommand(program) {
|
|
|
168
168
|
// Videos
|
|
169
169
|
// ════════════════════════════════════════════════════════════════════
|
|
170
170
|
media
|
|
171
|
-
.command("video
|
|
171
|
+
.command("create-video")
|
|
172
172
|
.description("Create an avatar video generation job.")
|
|
173
173
|
.option("--name <name>", "Name for the video (auto-generated if omitted)")
|
|
174
174
|
.requiredOption("--avatar-id <avatarId>", "Avatar to use")
|
|
@@ -220,7 +220,7 @@ export function registerMediaCommand(program) {
|
|
|
220
220
|
}
|
|
221
221
|
});
|
|
222
222
|
media
|
|
223
|
-
.command("
|
|
223
|
+
.command("list-videos")
|
|
224
224
|
.description("List all videos.")
|
|
225
225
|
.action(async () => {
|
|
226
226
|
const resp = (await apiGet("/media-gen/videos"));
|
|
@@ -239,65 +239,65 @@ export function registerMediaCommand(program) {
|
|
|
239
239
|
}
|
|
240
240
|
});
|
|
241
241
|
media
|
|
242
|
-
.command("video
|
|
242
|
+
.command("get-video <videoId>")
|
|
243
243
|
.description("Get video metadata.")
|
|
244
|
-
.action(async (
|
|
245
|
-
const resp = (await apiGet(`/media-gen/videos/${
|
|
244
|
+
.action(async (videoId) => {
|
|
245
|
+
const resp = (await apiGet(`/media-gen/videos/${videoId}`));
|
|
246
246
|
const data = unwrapResp(resp);
|
|
247
247
|
if (isJsonMode(media)) {
|
|
248
248
|
jsonOut(data);
|
|
249
249
|
return;
|
|
250
250
|
}
|
|
251
|
-
console.log(`Video ${
|
|
251
|
+
console.log(`Video ${videoId}:`);
|
|
252
252
|
for (const [k, v] of Object.entries(data)) {
|
|
253
253
|
console.log(` ${k}: ${typeof v === "object" ? JSON.stringify(v) : v}`);
|
|
254
254
|
}
|
|
255
255
|
});
|
|
256
256
|
media
|
|
257
|
-
.command("video-status <
|
|
258
|
-
.description("
|
|
257
|
+
.command("get-video-status <videoId>")
|
|
258
|
+
.description("Get video generation status.")
|
|
259
259
|
.option("--wait", "Poll until a terminal state is reached")
|
|
260
260
|
.option("-o, --output <path>", "Download video to this path when complete (implies --wait)")
|
|
261
|
-
.action(async (
|
|
261
|
+
.action(async (videoId, opts) => {
|
|
262
262
|
const shouldWait = opts.wait || !!opts.output;
|
|
263
263
|
if (shouldWait) {
|
|
264
|
-
const data = await pollStatus(`/media-gen/videos/${
|
|
264
|
+
const data = await pollStatus(`/media-gen/videos/${videoId}/status`, ["inference_complete", "inference_failed"]);
|
|
265
265
|
// Download if -o specified and completed
|
|
266
266
|
if (opts.output && data.status === "inference_complete") {
|
|
267
|
-
const dlId = (data.videoId || data.id ||
|
|
267
|
+
const dlId = (data.videoId || data.id || videoId);
|
|
268
268
|
const { contentType, size } = await downloadVideoToFile(dlId, opts.output);
|
|
269
269
|
if (isJsonMode(media)) {
|
|
270
270
|
jsonOut({ ...data, filename: opts.output, contentType, size });
|
|
271
271
|
return;
|
|
272
272
|
}
|
|
273
|
-
console.log(`Video ${
|
|
273
|
+
console.log(`Video ${videoId} — ${data.status}\nSaved to ${opts.output} (${size} bytes)`);
|
|
274
274
|
return;
|
|
275
275
|
}
|
|
276
276
|
if (isJsonMode(media)) {
|
|
277
277
|
jsonOut(data);
|
|
278
278
|
return;
|
|
279
279
|
}
|
|
280
|
-
console.log(`Video ${
|
|
280
|
+
console.log(`Video ${videoId} — status: ${data.status}`);
|
|
281
281
|
return;
|
|
282
282
|
}
|
|
283
|
-
const resp = (await apiGet(`/media-gen/videos/${
|
|
283
|
+
const resp = (await apiGet(`/media-gen/videos/${videoId}/status`));
|
|
284
284
|
const data = unwrapResp(resp);
|
|
285
285
|
if (isJsonMode(media)) {
|
|
286
286
|
jsonOut(data);
|
|
287
287
|
return;
|
|
288
288
|
}
|
|
289
|
-
console.log(`Video ${
|
|
289
|
+
console.log(`Video ${videoId} — status: ${data.status || "unknown"}`);
|
|
290
290
|
});
|
|
291
291
|
media
|
|
292
|
-
.command("video
|
|
292
|
+
.command("download-video <videoId>")
|
|
293
293
|
.description("Download a completed video (or get its URL).")
|
|
294
294
|
.option("-o, --output <path>", "Save video to this file path")
|
|
295
|
-
.action(async (
|
|
295
|
+
.action(async (videoId, opts) => {
|
|
296
296
|
const token = await getValidToken();
|
|
297
|
-
const url = `${BASE_URL}/media-gen/videos/${
|
|
297
|
+
const url = `${BASE_URL}/media-gen/videos/${videoId}/download`;
|
|
298
298
|
// If -o specified, download directly to file
|
|
299
299
|
if (opts.output) {
|
|
300
|
-
const { contentType, size } = await downloadVideoToFile(
|
|
300
|
+
const { contentType, size } = await downloadVideoToFile(videoId, opts.output);
|
|
301
301
|
if (isJsonMode(media)) {
|
|
302
302
|
jsonOut({ filename: opts.output, contentType, size });
|
|
303
303
|
return;
|
|
@@ -317,12 +317,12 @@ export function registerMediaCommand(program) {
|
|
|
317
317
|
jsonOut({ downloadUrl: location });
|
|
318
318
|
return;
|
|
319
319
|
}
|
|
320
|
-
console.log(`Download URL for video ${
|
|
320
|
+
console.log(`Download URL for video ${videoId}:\n ${location}`);
|
|
321
321
|
return;
|
|
322
322
|
}
|
|
323
323
|
if (!res.ok) {
|
|
324
324
|
const text = (await res.text()) || "(no body)";
|
|
325
|
-
throw new ApiError(res.status, `/media-gen/videos/${
|
|
325
|
+
throw new ApiError(res.status, `/media-gen/videos/${videoId}/download`, text);
|
|
326
326
|
}
|
|
327
327
|
// If it returns JSON instead of a redirect
|
|
328
328
|
const resp = (await res.json());
|
|
@@ -331,13 +331,13 @@ export function registerMediaCommand(program) {
|
|
|
331
331
|
jsonOut(data);
|
|
332
332
|
return;
|
|
333
333
|
}
|
|
334
|
-
console.log(`Download URL for video ${
|
|
334
|
+
console.log(`Download URL for video ${videoId}:\n ${data.url || data.downloadUrl || JSON.stringify(data)}`);
|
|
335
335
|
});
|
|
336
336
|
// ════════════════════════════════════════════════════════════════════
|
|
337
337
|
// Cinematic Video
|
|
338
338
|
// ════════════════════════════════════════════════════════════════════
|
|
339
339
|
media
|
|
340
|
-
.command("cinematic
|
|
340
|
+
.command("create-cinematic")
|
|
341
341
|
.description("Create a cinematic video from a text prompt.")
|
|
342
342
|
.requiredOption("--prompt <prompt>", "Text prompt describing the video")
|
|
343
343
|
.option("--name <name>", "Name for the video (auto-generated if omitted)")
|
|
@@ -425,7 +425,7 @@ export function registerMediaCommand(program) {
|
|
|
425
425
|
// Custom Avatars
|
|
426
426
|
// ════════════════════════════════════════════════════════════════════
|
|
427
427
|
media
|
|
428
|
-
.command("avatar
|
|
428
|
+
.command("design-avatar")
|
|
429
429
|
.description("Start a design-your-avatar job.")
|
|
430
430
|
.option("--name <name>", "Name for the avatar (auto-generated if omitted)")
|
|
431
431
|
.requiredOption("--gender <gender>", "Gender for the avatar design")
|
|
@@ -464,13 +464,13 @@ export function registerMediaCommand(program) {
|
|
|
464
464
|
` Job ID: ${jobId}\n` +
|
|
465
465
|
` Status: ${status}`);
|
|
466
466
|
if (status === "variants_ready") {
|
|
467
|
-
console.log(` Confirm: gobi media avatar
|
|
467
|
+
console.log(` Confirm: gobi media confirm-avatar --job-id ${jobId}`);
|
|
468
468
|
}
|
|
469
469
|
});
|
|
470
470
|
media
|
|
471
|
-
.command("avatar
|
|
471
|
+
.command("confirm-avatar")
|
|
472
472
|
.description("Confirm avatar variant(s) after design.")
|
|
473
|
-
.requiredOption("--job-id <jobId>", "Job ID from avatar
|
|
473
|
+
.requiredOption("--job-id <jobId>", "Job ID from design-avatar")
|
|
474
474
|
.option("--variant <variant>", "Variant to confirm (1 or 2); omit to confirm both")
|
|
475
475
|
.action(async (opts) => {
|
|
476
476
|
const body = { jobId: opts.jobId };
|
|
@@ -491,8 +491,8 @@ export function registerMediaCommand(program) {
|
|
|
491
491
|
` Avatar ID: ${avatarId || JSON.stringify(data)}`);
|
|
492
492
|
});
|
|
493
493
|
media
|
|
494
|
-
.command("avatar-from-selfie")
|
|
495
|
-
.description("
|
|
494
|
+
.command("design-avatar-from-selfie")
|
|
495
|
+
.description("Design an avatar from a selfie (instant or enhanced with prompt).")
|
|
496
496
|
.option("--name <name>", "Name for the avatar (auto-generated if omitted)")
|
|
497
497
|
.requiredOption("--photo <file>", "Selfie photo file (auto-uploaded)")
|
|
498
498
|
.option("--prompt <prompt>", "Enhancement prompt (triggers async enhance flow)")
|
|
@@ -532,8 +532,8 @@ export function registerMediaCommand(program) {
|
|
|
532
532
|
}
|
|
533
533
|
});
|
|
534
534
|
media
|
|
535
|
-
.command("avatar-job-status <jobId>")
|
|
536
|
-
.description("
|
|
535
|
+
.command("get-avatar-job-status <jobId>")
|
|
536
|
+
.description("Get avatar job status.")
|
|
537
537
|
.option("--wait", "Poll until a terminal state is reached")
|
|
538
538
|
.action(async (jobId, opts) => {
|
|
539
539
|
let data;
|
|
@@ -554,7 +554,7 @@ export function registerMediaCommand(program) {
|
|
|
554
554
|
// Images
|
|
555
555
|
// ════════════════════════════════════════════════════════════════════
|
|
556
556
|
media
|
|
557
|
-
.command("image
|
|
557
|
+
.command("generate-image")
|
|
558
558
|
.description("Generate an image from a text prompt. Types: image (default), thumbnail (YouTube-optimized), asset (logo/product). Aspect ratios: 1:1, 16:9, 9:16, 4:3, 3:4")
|
|
559
559
|
.requiredOption("--prompt <prompt>", "Text prompt for image generation")
|
|
560
560
|
.option("--name <name>", "Name for the generated image (auto-generated from prompt if omitted)")
|
|
@@ -636,7 +636,7 @@ export function registerMediaCommand(program) {
|
|
|
636
636
|
}
|
|
637
637
|
});
|
|
638
638
|
media
|
|
639
|
-
.command("image
|
|
639
|
+
.command("edit-image")
|
|
640
640
|
.description("Edit an existing image with a prompt (image-to-image).")
|
|
641
641
|
.requiredOption("--image <file>", "Source image file (auto-uploaded)")
|
|
642
642
|
.requiredOption("--prompt <prompt>", "Edit instruction")
|
|
@@ -699,7 +699,7 @@ export function registerMediaCommand(program) {
|
|
|
699
699
|
}
|
|
700
700
|
});
|
|
701
701
|
media
|
|
702
|
-
.command("image
|
|
702
|
+
.command("inpaint-image")
|
|
703
703
|
.description("Inpaint an image region using a mask.")
|
|
704
704
|
.requiredOption("--image <file>", "Source image file (auto-uploaded)")
|
|
705
705
|
.requiredOption("--mask <file>", "Mask image file (auto-uploaded)")
|
|
@@ -766,8 +766,8 @@ export function registerMediaCommand(program) {
|
|
|
766
766
|
}
|
|
767
767
|
});
|
|
768
768
|
media
|
|
769
|
-
.command("image-status <jobId>")
|
|
770
|
-
.description("
|
|
769
|
+
.command("get-image-status <jobId>")
|
|
770
|
+
.description("Get image generation job status.")
|
|
771
771
|
.option("--wait", "Poll until a terminal state is reached")
|
|
772
772
|
.action(async (jobId, opts) => {
|
|
773
773
|
let data;
|
|
@@ -794,7 +794,7 @@ export function registerMediaCommand(program) {
|
|
|
794
794
|
}
|
|
795
795
|
});
|
|
796
796
|
media
|
|
797
|
-
.command("image
|
|
797
|
+
.command("download-image <jobId>")
|
|
798
798
|
.description("Download a generated image.")
|
|
799
799
|
.option("--wait", "Poll until generation completes before downloading")
|
|
800
800
|
.option("--type <type>", "Image type (image, thumbnail, asset)")
|
package/dist/commands/saved.js
CHANGED
|
@@ -24,16 +24,17 @@ function formatSavedPostLine(item) {
|
|
|
24
24
|
const space = item.spaceSlug ? `, space: ${item.spaceSlug}` : "";
|
|
25
25
|
return `- [${item.postId}] "${snippet.replace(/\n/g, " ")}" by ${author ?? "?"}${space} (saved ${item.savedAt})`;
|
|
26
26
|
}
|
|
27
|
-
function
|
|
28
|
-
const
|
|
29
|
-
.command("
|
|
30
|
-
.description("
|
|
31
|
-
|
|
32
|
-
|
|
27
|
+
export function registerSavedCommand(program) {
|
|
28
|
+
const saved = program
|
|
29
|
+
.command("saved")
|
|
30
|
+
.description("Saved-knowledge commands (notes and bookmarked posts).");
|
|
31
|
+
// ── Notes ──
|
|
32
|
+
saved
|
|
33
|
+
.command("list-notes")
|
|
33
34
|
.description("List your notes. Without --date, returns recent notes via cursor pagination. With --date, returns all notes for that day.")
|
|
34
35
|
.option("--date <date>", "Filter to a single day (YYYY-MM-DD)")
|
|
35
36
|
.option("--timezone <tz>", "IANA timezone name (default: system timezone)")
|
|
36
|
-
.option("--limit <number>", "Items per page
|
|
37
|
+
.option("--limit <number>", "Items per page", "20")
|
|
37
38
|
.option("--cursor <string>", "Pagination cursor from previous response")
|
|
38
39
|
.action(async (opts) => {
|
|
39
40
|
const params = {
|
|
@@ -61,8 +62,8 @@ function registerNoteCommands(saved) {
|
|
|
61
62
|
: "";
|
|
62
63
|
console.log(`Notes (${items.length} items):\n` + lines.join("\n") + footer);
|
|
63
64
|
});
|
|
64
|
-
|
|
65
|
-
.command("get <noteId>")
|
|
65
|
+
saved
|
|
66
|
+
.command("get-note <noteId>")
|
|
66
67
|
.description("Get a single note by id.")
|
|
67
68
|
.action(async (noteId) => {
|
|
68
69
|
const resp = (await apiGet(`/app/notes/${noteId}`));
|
|
@@ -90,8 +91,8 @@ function registerNoteCommands(saved) {
|
|
|
90
91
|
.trimEnd();
|
|
91
92
|
console.log(output);
|
|
92
93
|
});
|
|
93
|
-
|
|
94
|
-
.command("create")
|
|
94
|
+
saved
|
|
95
|
+
.command("create-note")
|
|
95
96
|
.description("Create a note. Provide --content (use '-' for stdin) and/or attachments.")
|
|
96
97
|
.option("--content <content>", 'Note content (markdown supported, use "-" for stdin)')
|
|
97
98
|
.option("--timezone <tz>", "IANA timezone name (default: system timezone)")
|
|
@@ -115,8 +116,8 @@ function registerNoteCommands(saved) {
|
|
|
115
116
|
}
|
|
116
117
|
console.log(`Note created!\n ID: ${note.id}\n Date: ${note.eventDate}\n Created: ${note.createdAt}`);
|
|
117
118
|
});
|
|
118
|
-
|
|
119
|
-
.command("edit <noteId>")
|
|
119
|
+
saved
|
|
120
|
+
.command("edit-note <noteId>")
|
|
120
121
|
.description("Edit a note. Provide --content and/or --agent-id.")
|
|
121
122
|
.option("--content <content>", 'New note content (markdown supported, use "-" for stdin)')
|
|
122
123
|
.option("--agent-id <number>", 'New agent id, or "null" to clear the association')
|
|
@@ -140,8 +141,8 @@ function registerNoteCommands(saved) {
|
|
|
140
141
|
}
|
|
141
142
|
console.log(`Note edited!\n ID: ${note.id}\n Updated: ${note.updatedAt}`);
|
|
142
143
|
});
|
|
143
|
-
|
|
144
|
-
.command("delete <noteId>")
|
|
144
|
+
saved
|
|
145
|
+
.command("delete-note <noteId>")
|
|
145
146
|
.description("Delete a note you authored.")
|
|
146
147
|
.action(async (noteId) => {
|
|
147
148
|
await apiDelete(`/app/notes/${noteId}`);
|
|
@@ -151,16 +152,12 @@ function registerNoteCommands(saved) {
|
|
|
151
152
|
}
|
|
152
153
|
console.log(`Note ${noteId} deleted.`);
|
|
153
154
|
});
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
.
|
|
158
|
-
.description("Saved posts (snapshots of posts and replies you bookmark).");
|
|
159
|
-
post
|
|
160
|
-
.command("list")
|
|
161
|
-
.description("List posts you have saved.")
|
|
155
|
+
// ── Saved posts (bookmarks) ──
|
|
156
|
+
saved
|
|
157
|
+
.command("list-posts")
|
|
158
|
+
.description("List posts you have bookmarked (paginated).")
|
|
162
159
|
.option("--type <type>", "Filter by type: all|article|space-post", "all")
|
|
163
|
-
.option("--limit <number>", "Items per page
|
|
160
|
+
.option("--limit <number>", "Items per page", "20")
|
|
164
161
|
.option("--cursor <string>", "Pagination cursor from previous response")
|
|
165
162
|
.action(async (opts) => {
|
|
166
163
|
const params = {
|
|
@@ -184,8 +181,8 @@ function registerPostCommands(saved) {
|
|
|
184
181
|
const footer = pagination.hasMore ? `\n Next cursor: ${pagination.nextCursor}` : "";
|
|
185
182
|
console.log(`Saved posts (${items.length} items):\n` + lines.join("\n") + footer);
|
|
186
183
|
});
|
|
187
|
-
|
|
188
|
-
.command("get <postId>")
|
|
184
|
+
saved
|
|
185
|
+
.command("get-post <postId>")
|
|
189
186
|
.description("Get a saved post snapshot by post id.")
|
|
190
187
|
.action(async (postId) => {
|
|
191
188
|
const resp = (await apiGet(`/feed/${postId}`));
|
|
@@ -205,10 +202,10 @@ function registerPostCommands(saved) {
|
|
|
205
202
|
post.content || "",
|
|
206
203
|
].join("\n"));
|
|
207
204
|
});
|
|
208
|
-
|
|
209
|
-
.command("create")
|
|
210
|
-
.description("
|
|
211
|
-
.requiredOption("--source <id>", "Source post or reply id to
|
|
205
|
+
saved
|
|
206
|
+
.command("create-post")
|
|
207
|
+
.description("Bookmark a post or reply by id. Records a snapshot in your saved-posts collection.")
|
|
208
|
+
.requiredOption("--source <id>", "Source post or reply id to bookmark (numeric)")
|
|
212
209
|
.action(async (opts) => {
|
|
213
210
|
const sourceId = parseInt(opts.source, 10);
|
|
214
211
|
if (!Number.isFinite(sourceId)) {
|
|
@@ -219,27 +216,20 @@ function registerPostCommands(saved) {
|
|
|
219
216
|
}));
|
|
220
217
|
const data = unwrapResp(resp);
|
|
221
218
|
if (isJsonMode(saved)) {
|
|
222
|
-
jsonOut({
|
|
219
|
+
jsonOut({ id: sourceId, ...data });
|
|
223
220
|
return;
|
|
224
221
|
}
|
|
225
222
|
console.log(`Saved post ${sourceId}.`);
|
|
226
223
|
});
|
|
227
|
-
|
|
228
|
-
.command("delete <postId>")
|
|
224
|
+
saved
|
|
225
|
+
.command("delete-post <postId>")
|
|
229
226
|
.description("Remove a post from your saved-posts collection.")
|
|
230
227
|
.action(async (postId) => {
|
|
231
228
|
await apiDelete(`/reactions/posts/${postId}/save`);
|
|
232
229
|
if (isJsonMode(saved)) {
|
|
233
|
-
jsonOut({ postId });
|
|
230
|
+
jsonOut({ id: postId });
|
|
234
231
|
return;
|
|
235
232
|
}
|
|
236
233
|
console.log(`Removed post ${postId} from saved.`);
|
|
237
234
|
});
|
|
238
235
|
}
|
|
239
|
-
export function registerSavedCommand(program) {
|
|
240
|
-
const saved = program
|
|
241
|
-
.command("saved")
|
|
242
|
-
.description("Saved-knowledge commands (notes and posts).");
|
|
243
|
-
registerNoteCommands(saved);
|
|
244
|
-
registerPostCommands(saved);
|
|
245
|
-
}
|
package/dist/commands/sense.js
CHANGED
|
@@ -6,8 +6,8 @@ export function registerSenseCommand(program) {
|
|
|
6
6
|
.description("Sense commands (activities, transcriptions).");
|
|
7
7
|
// ── Activities ──
|
|
8
8
|
sense
|
|
9
|
-
.command("activities")
|
|
10
|
-
.description("
|
|
9
|
+
.command("list-activities")
|
|
10
|
+
.description("List activity records within a time range.")
|
|
11
11
|
.requiredOption("--start-time <iso>", "Start of time range (ISO 8601 UTC, e.g. 2026-03-20T00:00:00Z)")
|
|
12
12
|
.requiredOption("--end-time <iso>", "End of time range (ISO 8601 UTC, e.g. 2026-03-20T23:59:59Z)")
|
|
13
13
|
.action(async (opts) => {
|
|
@@ -55,8 +55,8 @@ export function registerSenseCommand(program) {
|
|
|
55
55
|
});
|
|
56
56
|
// ── Transcriptions ──
|
|
57
57
|
sense
|
|
58
|
-
.command("transcriptions")
|
|
59
|
-
.description("
|
|
58
|
+
.command("list-transcriptions")
|
|
59
|
+
.description("List transcription records within a time range.")
|
|
60
60
|
.requiredOption("--start-time <iso>", "Start of time range (ISO 8601 UTC, e.g. 2026-03-20T00:00:00Z)")
|
|
61
61
|
.requiredOption("--end-time <iso>", "End of time range (ISO 8601 UTC, e.g. 2026-03-20T23:59:59Z)")
|
|
62
62
|
.action(async (opts) => {
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { apiGet, apiPost } from "../client.js";
|
|
2
|
-
import { isJsonMode, jsonOut, unwrapResp } from "./utils.js";
|
|
2
|
+
import { isJsonMode, jsonOut, readStdin, unwrapResp } from "./utils.js";
|
|
3
3
|
export function registerSessionsCommand(program) {
|
|
4
4
|
const sessions = program
|
|
5
5
|
.command("session")
|
|
6
|
-
.description("Session commands (get, list, reply).");
|
|
6
|
+
.description("Session commands (get, list, create-reply).");
|
|
7
7
|
// ── Get ──
|
|
8
8
|
sessions
|
|
9
9
|
.command("get <sessionId>")
|
|
10
10
|
.description("Get a session and its messages (paginated).")
|
|
11
|
-
.option("--limit <number>", "
|
|
11
|
+
.option("--limit <number>", "Items per page", "20")
|
|
12
12
|
.option("--cursor <string>", "Pagination cursor from previous response")
|
|
13
13
|
.action(async (sessionId, opts) => {
|
|
14
14
|
const params = {
|
|
@@ -85,9 +85,9 @@ export function registerSessionsCommand(program) {
|
|
|
85
85
|
});
|
|
86
86
|
// ── Reply ──
|
|
87
87
|
sessions
|
|
88
|
-
.command("reply <sessionId>")
|
|
88
|
+
.command("create-reply <sessionId>")
|
|
89
89
|
.description("Send a human reply to a session you are a member of.")
|
|
90
|
-
.option("--content <content>", "Reply content (markdown supported)")
|
|
90
|
+
.option("--content <content>", "Reply content (markdown supported, use \"-\" for stdin)")
|
|
91
91
|
.option("--rich-text <richText>", "Rich-text JSON array (e.g. [{\"type\":\"text\",\"text\":\"hello\"}])")
|
|
92
92
|
.action(async (sessionId, opts) => {
|
|
93
93
|
if (!opts.content && !opts.richText) {
|
|
@@ -108,7 +108,7 @@ export function registerSessionsCommand(program) {
|
|
|
108
108
|
body.richText = parsed;
|
|
109
109
|
}
|
|
110
110
|
else {
|
|
111
|
-
body.content = opts.content;
|
|
111
|
+
body.content = opts.content === "-" ? readStdin() : opts.content;
|
|
112
112
|
}
|
|
113
113
|
const resp = (await apiPost(`/chat/${sessionId}/reply`, body));
|
|
114
114
|
const msg = unwrapResp(resp);
|