@supacortex/cli 0.1.3 → 0.2.0
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/index.js +248 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -188,11 +188,12 @@ var registerWhoamiCommand = (program2) => {
|
|
|
188
188
|
// src/commands/bookmarks.ts
|
|
189
189
|
var registerBookmarksCommand = (program2) => {
|
|
190
190
|
const bookmarks = program2.command("bookmarks");
|
|
191
|
-
bookmarks.command("list").option("-l, --limit <number>", "Max results", "20").option("-o, --offset <number>", "Skip results").option("-s, --search <string>", "Search bookmarks").option("-j, --json", "Output raw JSON").description("List all bookmarks").action(async (option) => {
|
|
191
|
+
bookmarks.command("list").option("-l, --limit <number>", "Max results", "20").option("-o, --offset <number>", "Skip results").option("-s, --search <string>", "Search bookmarks").option("-t, --type <string>", "Filter by type (tweet, link, youtube)").option("-j, --json", "Output raw JSON").description("List all bookmarks").action(async (option) => {
|
|
192
192
|
const searchParams = new URLSearchParams();
|
|
193
193
|
if (option.limit) searchParams.append("limit", String(parseInt(option.limit, 10)));
|
|
194
194
|
if (option.offset) searchParams.append("offset", String(parseInt(option.offset, 10)));
|
|
195
195
|
if (option.search) searchParams.append("search", option.search);
|
|
196
|
+
if (option.type) searchParams.append("type", option.type);
|
|
196
197
|
const result = await apiRequest(
|
|
197
198
|
`bookmarks?${searchParams.toString()}`,
|
|
198
199
|
"GET"
|
|
@@ -220,6 +221,20 @@ var registerBookmarksCommand = (program2) => {
|
|
|
220
221
|
}
|
|
221
222
|
console.log(`Bookmark added: ${result.title || result.url}`);
|
|
222
223
|
});
|
|
224
|
+
bookmarks.command("get").description("Get a bookmark by ID").argument("<id>", "Bookmark ID").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
225
|
+
const data = await apiRequest(`bookmarks/${id}`, "GET");
|
|
226
|
+
if (option.json) {
|
|
227
|
+
console.log(JSON.stringify(data, null, 2));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
console.log(`ID: ${data.id}`);
|
|
231
|
+
console.log(`Type: ${data.type}`);
|
|
232
|
+
console.log(`Title: ${data.title || "(none)"}`);
|
|
233
|
+
console.log(`URL: ${data.url}`);
|
|
234
|
+
if (data.author) console.log(`Author: ${data.author}`);
|
|
235
|
+
if (data.content) console.log(`Content: ${data.content.slice(0, 200)}${data.content.length > 200 ? "\u2026" : ""}`);
|
|
236
|
+
console.log(`Created: ${data.createdAt}`);
|
|
237
|
+
});
|
|
223
238
|
bookmarks.command("delete").description("Delete a bookmark").argument("<id>", "Bookmark ID to delete").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
224
239
|
const result = await apiRequest(`bookmarks/${id}`, "DELETE");
|
|
225
240
|
if (option.json) {
|
|
@@ -341,6 +356,236 @@ var registerUpdateCommand = (program2, version) => {
|
|
|
341
356
|
});
|
|
342
357
|
};
|
|
343
358
|
|
|
359
|
+
// src/commands/conversation.ts
|
|
360
|
+
var TIERS = ["brief", "summary", "detailed"];
|
|
361
|
+
var tierType = (tier) => `conversation_${tier}`;
|
|
362
|
+
var registerConversationCommand = (program2) => {
|
|
363
|
+
const convo = program2.command("conversation").description("Manage conversation memories \u2014 summaries of AI chat sessions");
|
|
364
|
+
convo.command("list").option("-s, --search <string>", "Search conversations").option("--tier <tier>", "Filter by tier (brief, summary, detailed)").option("-l, --limit <number>", "Max results", "20").option("-o, --offset <number>", "Skip results").option("-j, --json", "Output raw JSON").description("List saved conversations").action(async (option) => {
|
|
365
|
+
const searchParams = new URLSearchParams();
|
|
366
|
+
if (option.limit) searchParams.append("limit", String(parseInt(option.limit, 10)));
|
|
367
|
+
if (option.offset) searchParams.append("offset", String(parseInt(option.offset, 10)));
|
|
368
|
+
if (option.search) searchParams.append("search", option.search);
|
|
369
|
+
if (option.tier) {
|
|
370
|
+
if (!TIERS.includes(option.tier)) {
|
|
371
|
+
console.error(`Error: --tier must be one of: ${TIERS.join(", ")}`);
|
|
372
|
+
process.exit(1);
|
|
373
|
+
}
|
|
374
|
+
searchParams.append("type", tierType(option.tier));
|
|
375
|
+
} else {
|
|
376
|
+
searchParams.append("type", "conversation_brief");
|
|
377
|
+
searchParams.delete("type");
|
|
378
|
+
}
|
|
379
|
+
const result = await apiRequest(`memory?${searchParams.toString()}`, "GET");
|
|
380
|
+
if (option.json) {
|
|
381
|
+
console.log(JSON.stringify(result, null, 2));
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const { data } = result;
|
|
385
|
+
const conversations = option.tier ? data : data.filter((m) => String(m.type).startsWith("conversation_"));
|
|
386
|
+
if (conversations.length === 0) {
|
|
387
|
+
console.log("No conversations found.");
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
for (const m of conversations) {
|
|
391
|
+
const title = m.title || m.content?.slice(0, 80) || "Untitled";
|
|
392
|
+
const truncated = title.length > 80 ? title.slice(0, 80) + "..." : title;
|
|
393
|
+
const tier = String(m.type).replace("conversation_", "");
|
|
394
|
+
const date = m.createdAt ? new Date(m.createdAt).toISOString().slice(0, 10) : "";
|
|
395
|
+
console.log(` ${truncated}`);
|
|
396
|
+
console.log(` ${tier} \xB7 ${date}`);
|
|
397
|
+
console.log();
|
|
398
|
+
}
|
|
399
|
+
console.log(`Showing ${conversations.length} conversations`);
|
|
400
|
+
});
|
|
401
|
+
convo.command("add").description("Save a conversation summary").argument("<content>", "Conversation summary text").requiredOption("--tier <tier>", "Tier: brief (1 sentence), summary (bullet points), detailed (full document)").option("-t, --title <string>", "Title for the conversation").option("-m, --metadata <json>", "Metadata as JSON (e.g. source, sessionId, tags)").option("-j, --json", "Output raw JSON").action(async (content, option) => {
|
|
402
|
+
if (!TIERS.includes(option.tier)) {
|
|
403
|
+
console.error(`Error: --tier must be one of: ${TIERS.join(", ")}`);
|
|
404
|
+
process.exit(1);
|
|
405
|
+
}
|
|
406
|
+
const body = {
|
|
407
|
+
type: tierType(option.tier),
|
|
408
|
+
content
|
|
409
|
+
};
|
|
410
|
+
if (option.title) body.title = option.title;
|
|
411
|
+
if (option.metadata) {
|
|
412
|
+
try {
|
|
413
|
+
body.metadata = JSON.parse(option.metadata);
|
|
414
|
+
} catch {
|
|
415
|
+
console.error("Error: --metadata must be valid JSON");
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
const result = await apiRequest("memory", "POST", body);
|
|
420
|
+
if (option.json) {
|
|
421
|
+
console.log(JSON.stringify(result, null, 2));
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
console.log(`Conversation saved: ${result.title || result.content?.slice(0, 60) || result.id}`);
|
|
425
|
+
});
|
|
426
|
+
convo.command("get").description("Get a conversation by ID").argument("<id>", "Conversation ID").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
427
|
+
const data = await apiRequest(`memory/${id}`, "GET");
|
|
428
|
+
if (option.json) {
|
|
429
|
+
console.log(JSON.stringify(data, null, 2));
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const tier = String(data.type).replace("conversation_", "");
|
|
433
|
+
console.log(`ID: ${data.id}`);
|
|
434
|
+
console.log(`Tier: ${tier}`);
|
|
435
|
+
console.log(`Title: ${data.title || "(none)"}`);
|
|
436
|
+
console.log(`Content: ${data.content?.slice(0, 500)}${data.content?.length > 500 ? "\u2026" : ""}`);
|
|
437
|
+
if (data.metadata) console.log(`Metadata: ${JSON.stringify(data.metadata)}`);
|
|
438
|
+
console.log(`Created: ${data.createdAt}`);
|
|
439
|
+
if (data.updatedAt) console.log(`Updated: ${data.updatedAt}`);
|
|
440
|
+
});
|
|
441
|
+
convo.command("update").description("Update a saved conversation").argument("<id>", "Conversation ID").option("-t, --title <string>", "New title").option("-c, --content <string>", "New content").option("--tier <tier>", "Change tier (brief, summary, detailed)").option("-m, --metadata <json>", "New metadata as JSON").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
442
|
+
const body = {};
|
|
443
|
+
if (option.title) body.title = option.title;
|
|
444
|
+
if (option.content) body.content = option.content;
|
|
445
|
+
if (option.tier) {
|
|
446
|
+
if (!TIERS.includes(option.tier)) {
|
|
447
|
+
console.error(`Error: --tier must be one of: ${TIERS.join(", ")}`);
|
|
448
|
+
process.exit(1);
|
|
449
|
+
}
|
|
450
|
+
body.type = tierType(option.tier);
|
|
451
|
+
}
|
|
452
|
+
if (option.metadata) {
|
|
453
|
+
try {
|
|
454
|
+
body.metadata = JSON.parse(option.metadata);
|
|
455
|
+
} catch {
|
|
456
|
+
console.error("Error: --metadata must be valid JSON");
|
|
457
|
+
process.exit(1);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (Object.keys(body).length === 0) {
|
|
461
|
+
console.error("Error: provide at least one field to update (--title, --content, --tier, --metadata)");
|
|
462
|
+
process.exit(1);
|
|
463
|
+
}
|
|
464
|
+
const result = await apiRequest(`memory/${id}`, "PATCH", body);
|
|
465
|
+
if (option.json) {
|
|
466
|
+
console.log(JSON.stringify(result, null, 2));
|
|
467
|
+
return;
|
|
468
|
+
}
|
|
469
|
+
console.log(`Conversation updated: ${result.title || result.id}`);
|
|
470
|
+
});
|
|
471
|
+
convo.command("delete").description("Delete a saved conversation").argument("<id>", "Conversation ID").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
472
|
+
const result = await apiRequest(`memory/${id}`, "DELETE");
|
|
473
|
+
if (option.json) {
|
|
474
|
+
console.log(JSON.stringify(result, null, 2));
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
console.log("Conversation deleted.");
|
|
478
|
+
});
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// src/commands/identity.ts
|
|
482
|
+
var CATEGORIES = ["core", "goals", "preferences", "interests"];
|
|
483
|
+
var registerIdentityCommand = (program2) => {
|
|
484
|
+
const identity = program2.command("identity").description("Manage identity \u2014 persistent context about the user (name, goals, preferences, interests)");
|
|
485
|
+
identity.command("list").option("-s, --search <string>", "Search identity entries").option("--category <category>", "Filter by category (core, goals, preferences, interests)").option("-l, --limit <number>", "Max results", "20").option("-o, --offset <number>", "Skip results").option("-j, --json", "Output raw JSON").description("List identity entries").action(async (option) => {
|
|
486
|
+
const searchParams = new URLSearchParams();
|
|
487
|
+
searchParams.append("type", "identity");
|
|
488
|
+
if (option.limit) searchParams.append("limit", String(parseInt(option.limit, 10)));
|
|
489
|
+
if (option.offset) searchParams.append("offset", String(parseInt(option.offset, 10)));
|
|
490
|
+
if (option.search) searchParams.append("search", option.search);
|
|
491
|
+
const result = await apiRequest(`memory?${searchParams.toString()}`, "GET");
|
|
492
|
+
if (option.json) {
|
|
493
|
+
console.log(JSON.stringify(result, null, 2));
|
|
494
|
+
return;
|
|
495
|
+
}
|
|
496
|
+
let { data } = result;
|
|
497
|
+
if (option.category) {
|
|
498
|
+
data = data.filter(
|
|
499
|
+
(m) => m.metadata?.category === option.category
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
if (data.length === 0) {
|
|
503
|
+
console.log("No identity entries found.");
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
for (const m of data) {
|
|
507
|
+
const category = m.metadata?.category || "uncategorized";
|
|
508
|
+
const title = m.title || m.content?.slice(0, 80) || "Untitled";
|
|
509
|
+
const truncated = title.length > 80 ? title.slice(0, 80) + "..." : title;
|
|
510
|
+
console.log(` ${truncated}`);
|
|
511
|
+
console.log(` ${category}`);
|
|
512
|
+
console.log();
|
|
513
|
+
}
|
|
514
|
+
console.log(`Showing ${data.length} entries`);
|
|
515
|
+
});
|
|
516
|
+
identity.command("add").description("Add an identity entry").argument("<content>", 'Identity content (e.g. "Solo founder based in Nepal, building Supacortex")').option("-t, --title <string>", 'Title (e.g. "Core profile", "Tech preferences")').option("--category <category>", "Category: core, goals, preferences, interests").option("-m, --metadata <json>", "Additional metadata as JSON").option("-j, --json", "Output raw JSON").action(async (content, option) => {
|
|
517
|
+
const metadata = option.metadata ? JSON.parse(option.metadata) : {};
|
|
518
|
+
if (option.category) {
|
|
519
|
+
if (!CATEGORIES.includes(option.category)) {
|
|
520
|
+
console.error(`Error: --category must be one of: ${CATEGORIES.join(", ")}`);
|
|
521
|
+
process.exit(1);
|
|
522
|
+
}
|
|
523
|
+
metadata.category = option.category;
|
|
524
|
+
}
|
|
525
|
+
const body = {
|
|
526
|
+
type: "identity",
|
|
527
|
+
content,
|
|
528
|
+
metadata: Object.keys(metadata).length > 0 ? metadata : void 0
|
|
529
|
+
};
|
|
530
|
+
if (option.title) body.title = option.title;
|
|
531
|
+
const result = await apiRequest("memory", "POST", body);
|
|
532
|
+
if (option.json) {
|
|
533
|
+
console.log(JSON.stringify(result, null, 2));
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
console.log(`Identity added: ${result.title || result.content?.slice(0, 60) || result.id}`);
|
|
537
|
+
});
|
|
538
|
+
identity.command("get").description("Get an identity entry by ID").argument("<id>", "Identity entry ID").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
539
|
+
const data = await apiRequest(`memory/${id}`, "GET");
|
|
540
|
+
if (option.json) {
|
|
541
|
+
console.log(JSON.stringify(data, null, 2));
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
const category = data.metadata?.category || "uncategorized";
|
|
545
|
+
console.log(`ID: ${data.id}`);
|
|
546
|
+
console.log(`Category: ${category}`);
|
|
547
|
+
console.log(`Title: ${data.title || "(none)"}`);
|
|
548
|
+
console.log(`Content: ${data.content}`);
|
|
549
|
+
if (data.metadata) console.log(`Metadata: ${JSON.stringify(data.metadata)}`);
|
|
550
|
+
console.log(`Created: ${data.createdAt}`);
|
|
551
|
+
if (data.updatedAt) console.log(`Updated: ${data.updatedAt}`);
|
|
552
|
+
});
|
|
553
|
+
identity.command("update").description("Update an identity entry").argument("<id>", "Identity entry ID").option("-t, --title <string>", "New title").option("-c, --content <string>", "New content").option("--category <category>", "Change category (core, goals, preferences, interests)").option("-m, --metadata <json>", "New metadata as JSON").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
554
|
+
const body = {};
|
|
555
|
+
if (option.title) body.title = option.title;
|
|
556
|
+
if (option.content) body.content = option.content;
|
|
557
|
+
if (option.category || option.metadata) {
|
|
558
|
+
const metadata = option.metadata ? JSON.parse(option.metadata) : {};
|
|
559
|
+
if (option.category) {
|
|
560
|
+
if (!CATEGORIES.includes(option.category)) {
|
|
561
|
+
console.error(`Error: --category must be one of: ${CATEGORIES.join(", ")}`);
|
|
562
|
+
process.exit(1);
|
|
563
|
+
}
|
|
564
|
+
metadata.category = option.category;
|
|
565
|
+
}
|
|
566
|
+
body.metadata = metadata;
|
|
567
|
+
}
|
|
568
|
+
if (Object.keys(body).length === 0) {
|
|
569
|
+
console.error("Error: provide at least one field to update (--title, --content, --category, --metadata)");
|
|
570
|
+
process.exit(1);
|
|
571
|
+
}
|
|
572
|
+
const result = await apiRequest(`memory/${id}`, "PATCH", body);
|
|
573
|
+
if (option.json) {
|
|
574
|
+
console.log(JSON.stringify(result, null, 2));
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
console.log(`Identity updated: ${result.title || result.id}`);
|
|
578
|
+
});
|
|
579
|
+
identity.command("delete").description("Delete an identity entry").argument("<id>", "Identity entry ID").option("-j, --json", "Output raw JSON").action(async (id, option) => {
|
|
580
|
+
const result = await apiRequest(`memory/${id}`, "DELETE");
|
|
581
|
+
if (option.json) {
|
|
582
|
+
console.log(JSON.stringify(result, null, 2));
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
console.log("Identity entry deleted.");
|
|
586
|
+
});
|
|
587
|
+
};
|
|
588
|
+
|
|
344
589
|
// src/lib/update-notifier.ts
|
|
345
590
|
var NPM_REGISTRY_URL2 = "https://registry.npmjs.org/@supacortex/cli/latest";
|
|
346
591
|
var CHECK_INTERVAL = 24 * 60 * 60 * 1e3;
|
|
@@ -391,6 +636,8 @@ registerWhoamiCommand(program);
|
|
|
391
636
|
registerBookmarksCommand(program);
|
|
392
637
|
registerGroupsCommand(program);
|
|
393
638
|
registerSyncCommand(program);
|
|
639
|
+
registerConversationCommand(program);
|
|
640
|
+
registerIdentityCommand(program);
|
|
394
641
|
registerUpdateCommand(program, pkg.version);
|
|
395
642
|
checkForUpdates(pkg.version);
|
|
396
643
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supacortex/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Supacortex CLI — your second brain from the terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
],
|
|
22
22
|
"repository": {
|
|
23
23
|
"type": "git",
|
|
24
|
-
"url": "https://github.com/monorepo-labs/supacortex"
|
|
24
|
+
"url": "git+https://github.com/monorepo-labs/supacortex.git"
|
|
25
25
|
},
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"dependencies": {
|