@prismer/sdk 1.7.1 → 1.7.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.
package/dist/cli.js CHANGED
@@ -6,6 +6,10 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __export = (target, all) => {
10
+ for (var name in all)
11
+ __defProp(target, name, { get: all[name], enumerable: true });
12
+ };
9
13
  var __copyProps = (to, from, except, desc) => {
10
14
  if (from && typeof from === "object" || typeof from === "function") {
11
15
  for (let key of __getOwnPropNames(from))
@@ -22,8 +26,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
26
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
27
  mod
24
28
  ));
29
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
30
 
26
31
  // src/cli.ts
32
+ var cli_exports = {};
33
+ __export(cli_exports, {
34
+ getAPIClient: () => getAPIClient,
35
+ getIMClient: () => getIMClient
36
+ });
37
+ module.exports = __toCommonJS(cli_exports);
27
38
  var import_commander = require("commander");
28
39
  var fs = __toESM(require("fs"));
29
40
  var path = __toESM(require("path"));
@@ -224,10 +235,11 @@ var RealtimeWSClient = class extends TypedEmitter {
224
235
  joinConversation(conversationId) {
225
236
  this.sendRaw({ type: "conversation.join", payload: { conversationId } });
226
237
  }
227
- sendMessage(conversationId, content, type = "text") {
238
+ sendMessage(conversationId, content, options) {
239
+ const opts = typeof options === "string" ? { type: options } : options;
228
240
  this.sendRaw({
229
241
  type: "message.send",
230
- payload: { conversationId, content, type },
242
+ payload: { conversationId, content, type: opts?.type ?? "text", ...opts?.metadata ? { metadata: opts.metadata } : {}, ...opts?.parentId ? { parentId: opts.parentId } : {} },
231
243
  requestId: `msg-${++this.pingCounter}`
232
244
  });
233
245
  }
@@ -947,8 +959,8 @@ var OfflineManager = class extends OfflineEmitter {
947
959
  // ── Read cache ────────────────────────────────────────────
948
960
  async readFromCache(path2, query) {
949
961
  if (/\/api\/im\/conversations$/.test(path2)) {
950
- const convos2 = await this.storage.getConversations({ limit: 50 });
951
- if (convos2.length > 0) return { ok: true, data: convos2 };
962
+ const convos = await this.storage.getConversations({ limit: 50 });
963
+ if (convos.length > 0) return { ok: true, data: convos };
952
964
  }
953
965
  const msgMatch = path2.match(/\/api\/im\/messages\/([^/]+)$/);
954
966
  if (msgMatch) {
@@ -967,7 +979,7 @@ var OfflineManager = class extends OfflineEmitter {
967
979
  if (!result?.ok || !result?.data) return;
968
980
  try {
969
981
  if (/\/api\/im\/conversations$/.test(path2) && Array.isArray(result.data)) {
970
- const convos2 = result.data.map((c) => ({
982
+ const convos = result.data.map((c) => ({
971
983
  id: c.id,
972
984
  type: c.type ?? "direct",
973
985
  title: c.title,
@@ -978,7 +990,7 @@ var OfflineManager = class extends OfflineEmitter {
978
990
  metadata: c.metadata,
979
991
  updatedAt: c.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
980
992
  }));
981
- await this.storage.putConversations(convos2);
993
+ await this.storage.putConversations(convos);
982
994
  }
983
995
  const msgMatch = path2.match(/\/api\/im\/messages\/([^/]+)$/);
984
996
  if (msgMatch && Array.isArray(result.data)) {
@@ -1238,8 +1250,8 @@ var MessagesClient = class {
1238
1250
  return this._r("GET", `/api/im/messages/${conversationId}`, void 0, query);
1239
1251
  }
1240
1252
  /** Edit a message */
1241
- async edit(conversationId, messageId, content) {
1242
- return this._r("PATCH", `/api/im/messages/${conversationId}/${messageId}`, { content });
1253
+ async edit(conversationId, messageId, content, options) {
1254
+ return this._r("PATCH", `/api/im/messages/${conversationId}/${messageId}`, { content, ...options?.metadata ? { metadata: options.metadata } : {} });
1243
1255
  }
1244
1256
  /** Delete a message */
1245
1257
  async delete(conversationId, messageId) {
@@ -1326,6 +1338,549 @@ var WorkspaceClient = class {
1326
1338
  return this._r("GET", "/api/im/workspace/mentions/autocomplete", void 0, q);
1327
1339
  }
1328
1340
  };
1341
+ var TasksClient = class {
1342
+ constructor(_r) {
1343
+ this._r = _r;
1344
+ }
1345
+ /** Create a new task */
1346
+ async create(options) {
1347
+ return this._r("POST", "/api/im/tasks", options);
1348
+ }
1349
+ /** List tasks with optional filters */
1350
+ async list(options) {
1351
+ const query = {};
1352
+ if (options?.status) query.status = options.status;
1353
+ if (options?.capability) query.capability = options.capability;
1354
+ if (options?.assigneeId) query.assigneeId = options.assigneeId;
1355
+ if (options?.creatorId) query.creatorId = options.creatorId;
1356
+ if (options?.scheduleType) query.scheduleType = options.scheduleType;
1357
+ if (options?.limit != null) query.limit = String(options.limit);
1358
+ if (options?.cursor) query.cursor = options.cursor;
1359
+ return this._r("GET", "/api/im/tasks", void 0, query);
1360
+ }
1361
+ /** Get task details with logs */
1362
+ async get(taskId) {
1363
+ return this._r("GET", `/api/im/tasks/${taskId}`);
1364
+ }
1365
+ /** Update a task */
1366
+ async update(taskId, options) {
1367
+ return this._r("PATCH", `/api/im/tasks/${taskId}`, options);
1368
+ }
1369
+ /** Claim a pending task */
1370
+ async claim(taskId) {
1371
+ return this._r("POST", `/api/im/tasks/${taskId}/claim`);
1372
+ }
1373
+ /** Report progress on a task */
1374
+ async progress(taskId, options) {
1375
+ return this._r("POST", `/api/im/tasks/${taskId}/progress`, options);
1376
+ }
1377
+ /** Complete a task with result */
1378
+ async complete(taskId, options) {
1379
+ return this._r("POST", `/api/im/tasks/${taskId}/complete`, options);
1380
+ }
1381
+ /** Fail a task with error */
1382
+ async fail(taskId, error, metadata) {
1383
+ return this._r("POST", `/api/im/tasks/${taskId}/fail`, { error, metadata });
1384
+ }
1385
+ };
1386
+ var MemoryClient = class {
1387
+ constructor(_r) {
1388
+ this._r = _r;
1389
+ }
1390
+ /** Create a memory file */
1391
+ async createFile(options) {
1392
+ return this._r("POST", "/api/im/memory/files", options);
1393
+ }
1394
+ /** List memory files */
1395
+ async listFiles(options) {
1396
+ const query = {};
1397
+ if (options?.scope) query.scope = options.scope;
1398
+ if (options?.path) query.path = options.path;
1399
+ return this._r("GET", "/api/im/memory/files", void 0, query);
1400
+ }
1401
+ /** Get a memory file by ID */
1402
+ async getFile(fileId) {
1403
+ return this._r("GET", `/api/im/memory/files/${fileId}`);
1404
+ }
1405
+ /** Update a memory file (append, replace, or replace_section) */
1406
+ async updateFile(fileId, options) {
1407
+ return this._r("PATCH", `/api/im/memory/files/${fileId}`, options);
1408
+ }
1409
+ /** Delete a memory file */
1410
+ async deleteFile(fileId) {
1411
+ return this._r("DELETE", `/api/im/memory/files/${fileId}`);
1412
+ }
1413
+ /** Compact conversation messages into a summary */
1414
+ async compact(options) {
1415
+ return this._r("POST", "/api/im/memory/compact", options);
1416
+ }
1417
+ /** Get compaction summaries for a conversation */
1418
+ async getCompaction(conversationId) {
1419
+ return this._r("GET", `/api/im/memory/compact/${conversationId}`);
1420
+ }
1421
+ /** Load memory for session context */
1422
+ async load(scope) {
1423
+ const query = {};
1424
+ if (scope) query.scope = scope;
1425
+ return this._r("GET", "/api/im/memory/load", void 0, query);
1426
+ }
1427
+ };
1428
+ var IdentityClient = class {
1429
+ constructor(_r) {
1430
+ this._r = _r;
1431
+ }
1432
+ /** Get server public key */
1433
+ async getServerKey() {
1434
+ return this._r("GET", "/api/im/keys/server");
1435
+ }
1436
+ /** Register or rotate an identity key */
1437
+ async registerKey(options) {
1438
+ return this._r("PUT", "/api/im/keys/identity", options);
1439
+ }
1440
+ /** Get a user's identity key */
1441
+ async getKey(userId) {
1442
+ return this._r("GET", `/api/im/keys/identity/${userId}`);
1443
+ }
1444
+ /** Revoke own identity key */
1445
+ async revokeKey() {
1446
+ return this._r("POST", "/api/im/keys/identity/revoke");
1447
+ }
1448
+ /** Get key audit log for a user */
1449
+ async getAuditLog(userId) {
1450
+ return this._r("GET", `/api/im/keys/audit/${userId}`);
1451
+ }
1452
+ /** Verify key audit log integrity */
1453
+ async verifyAuditLog(userId) {
1454
+ return this._r("GET", `/api/im/keys/audit/${userId}/verify`);
1455
+ }
1456
+ };
1457
+ var SecurityClient = class {
1458
+ constructor(_r) {
1459
+ this._r = _r;
1460
+ }
1461
+ /** Get conversation security settings */
1462
+ async getConversationSecurity(conversationId) {
1463
+ return this._r("GET", `/api/im/conversations/${conversationId}/security`);
1464
+ }
1465
+ /** Update conversation security settings */
1466
+ async setConversationSecurity(conversationId, options) {
1467
+ return this._r("PATCH", `/api/im/conversations/${conversationId}/security`, options);
1468
+ }
1469
+ /** Upload a public key for a conversation */
1470
+ async uploadKey(conversationId, publicKey, algorithm) {
1471
+ const body = { publicKey };
1472
+ if (algorithm) body.algorithm = algorithm;
1473
+ return this._r("POST", `/api/im/conversations/${conversationId}/keys`, body);
1474
+ }
1475
+ /** Get keys for a conversation */
1476
+ async getKeys(conversationId) {
1477
+ return this._r("GET", `/api/im/conversations/${conversationId}/keys`);
1478
+ }
1479
+ /** Revoke a key for a specific user in a conversation */
1480
+ async revokeKey(conversationId, keyUserId) {
1481
+ return this._r("DELETE", `/api/im/conversations/${conversationId}/keys/${keyUserId}`);
1482
+ }
1483
+ };
1484
+ var EvolutionClient = class {
1485
+ constructor(_r) {
1486
+ this._r = _r;
1487
+ }
1488
+ // ── Public endpoints (no auth required) ──
1489
+ /** Get evolution stats */
1490
+ async getStats() {
1491
+ return this._r("GET", "/api/im/evolution/public/stats");
1492
+ }
1493
+ /** Get hot/trending genes */
1494
+ async getHotGenes(limit) {
1495
+ const query = {};
1496
+ if (limit != null) query.limit = String(limit);
1497
+ return this._r("GET", "/api/im/evolution/public/hot", void 0, query);
1498
+ }
1499
+ /** Browse published genes */
1500
+ async browseGenes(options) {
1501
+ const query = {};
1502
+ if (options?.category) query.category = options.category;
1503
+ if (options?.search) query.search = options.search;
1504
+ if (options?.sort) query.sort = options.sort;
1505
+ if (options?.page != null) query.page = String(options.page);
1506
+ if (options?.limit != null) query.limit = String(options.limit);
1507
+ return this._r("GET", "/api/im/evolution/public/genes", void 0, query);
1508
+ }
1509
+ /** Get a public gene by ID */
1510
+ async getPublicGene(geneId) {
1511
+ return this._r("GET", `/api/im/evolution/public/genes/${geneId}`);
1512
+ }
1513
+ /** Get capsules for a public gene */
1514
+ async getGeneCapsules(geneId, limit) {
1515
+ const query = {};
1516
+ if (limit != null) query.limit = String(limit);
1517
+ return this._r("GET", `/api/im/evolution/public/genes/${geneId}/capsules`, void 0, query);
1518
+ }
1519
+ /** Get gene lineage (parent + children) */
1520
+ async getGeneLineage(geneId) {
1521
+ return this._r("GET", `/api/im/evolution/public/genes/${geneId}/lineage`);
1522
+ }
1523
+ /** Get public evolution feed */
1524
+ async getFeed(limit) {
1525
+ const query = {};
1526
+ if (limit != null) query.limit = String(limit);
1527
+ return this._r("GET", "/api/im/evolution/public/feed", void 0, query);
1528
+ }
1529
+ // ── Authenticated endpoints ──
1530
+ /** Analyze signals and get gene recommendation */
1531
+ async analyze(options) {
1532
+ const { scope, ...body } = options;
1533
+ const q = {};
1534
+ if (scope) q.scope = scope;
1535
+ return this._r("POST", "/api/im/evolution/analyze", body, q);
1536
+ }
1537
+ /** Record an outcome (success/failure) for a gene */
1538
+ async record(options) {
1539
+ const { scope, ...body } = options;
1540
+ const q = {};
1541
+ if (scope) q.scope = scope;
1542
+ return this._r("POST", "/api/im/evolution/record", body, q);
1543
+ }
1544
+ /**
1545
+ * One-step evolution: analyze context → get gene recommendation → auto-record outcome.
1546
+ * Combines analyze() + record() into a single call for the common case.
1547
+ *
1548
+ * Usage:
1549
+ * const result = await client.evolution.evolve({
1550
+ * error: 'Connection timeout after 10s',
1551
+ * outcome: 'success',
1552
+ * score: 0.85,
1553
+ * summary: 'Fixed with exponential backoff',
1554
+ * });
1555
+ */
1556
+ async evolve(options) {
1557
+ const { outcome, score, summary, strategy_used, scope, ...analyzeOpts } = options;
1558
+ const analysis = await this.analyze({ ...analyzeOpts, ...scope ? { scope } : {} });
1559
+ if (!analysis.ok || !analysis.data) {
1560
+ return { ok: false, error: analysis.error };
1561
+ }
1562
+ const data = analysis.data;
1563
+ const geneId = data.gene_id;
1564
+ if (geneId && (data.action === "apply_gene" || data.action === "explore")) {
1565
+ const recordResult = await this.record({
1566
+ gene_id: geneId,
1567
+ signals: data.signals || analyzeOpts.signals || [],
1568
+ outcome,
1569
+ score: score ?? (outcome === "success" ? 0.8 : 0.2),
1570
+ summary: summary || `${outcome === "success" ? "Resolved" : "Failed to resolve"} using ${geneId}`,
1571
+ strategy_used,
1572
+ ...scope ? { scope } : {}
1573
+ });
1574
+ return {
1575
+ ok: true,
1576
+ data: {
1577
+ analysis: data,
1578
+ recorded: true,
1579
+ edge_updated: recordResult.data?.edge_updated
1580
+ }
1581
+ };
1582
+ }
1583
+ return {
1584
+ ok: true,
1585
+ data: { analysis: data, recorded: false }
1586
+ };
1587
+ }
1588
+ /** Trigger gene distillation */
1589
+ async distill(dryRun) {
1590
+ const query = {};
1591
+ if (dryRun) query.dry_run = "true";
1592
+ return this._r("POST", "/api/im/evolution/distill", void 0, query);
1593
+ }
1594
+ /** List own genes */
1595
+ async listGenes(signals, scope) {
1596
+ const query = {};
1597
+ if (signals) query.signals = signals;
1598
+ if (scope) query.scope = scope;
1599
+ return this._r("GET", "/api/im/evolution/genes", void 0, query);
1600
+ }
1601
+ /** Create a new gene */
1602
+ async createGene(options) {
1603
+ const { scope, ...body } = options;
1604
+ const q = {};
1605
+ if (scope) q.scope = scope;
1606
+ return this._r("POST", "/api/im/evolution/genes", body, q);
1607
+ }
1608
+ /** Delete a gene */
1609
+ async deleteGene(geneId) {
1610
+ return this._r("DELETE", `/api/im/evolution/genes/${geneId}`);
1611
+ }
1612
+ /** Publish a gene. Pass skipCanary=true to bypass canary validation (MVP/admin). */
1613
+ async publishGene(geneId, options) {
1614
+ return this._r("POST", `/api/im/evolution/genes/${geneId}/publish`, options?.skipCanary ? { skipCanary: true } : void 0);
1615
+ }
1616
+ /** Import a published gene */
1617
+ async importGene(geneId) {
1618
+ return this._r("POST", "/api/im/evolution/genes/import", { gene_id: geneId });
1619
+ }
1620
+ /** Fork a gene with modifications */
1621
+ async forkGene(options) {
1622
+ return this._r("POST", "/api/im/evolution/genes/fork", options);
1623
+ }
1624
+ /** Get signal-gene edges */
1625
+ async getEdges(options) {
1626
+ const query = {};
1627
+ if (options?.signalKey) query.signal_key = options.signalKey;
1628
+ if (options?.geneId) query.gene_id = options.geneId;
1629
+ if (options?.limit != null) query.limit = String(options.limit);
1630
+ if (options?.scope) query.scope = options.scope;
1631
+ return this._r("GET", "/api/im/evolution/edges", void 0, query);
1632
+ }
1633
+ /** Get agent personality profile */
1634
+ async getPersonality(agentId) {
1635
+ return this._r("GET", `/api/im/evolution/personality/${agentId}`);
1636
+ }
1637
+ /** Get own capsule history */
1638
+ async getCapsules(options) {
1639
+ const query = {};
1640
+ if (options?.page != null) query.page = String(options.page);
1641
+ if (options?.limit != null) query.limit = String(options.limit);
1642
+ if (options?.scope) query.scope = options.scope;
1643
+ return this._r("GET", "/api/im/evolution/capsules", void 0, query);
1644
+ }
1645
+ /** Get evolution report */
1646
+ async getReport(agentId, scope) {
1647
+ const query = {};
1648
+ if (agentId) query.agent_id = agentId;
1649
+ if (scope) query.scope = scope;
1650
+ return this._r("GET", "/api/im/evolution/report", void 0, query);
1651
+ }
1652
+ /** List available evolution scopes */
1653
+ async listScopes() {
1654
+ return this._r("GET", "/api/im/evolution/scopes");
1655
+ }
1656
+ // ─── v0.3.1: Stories, Metrics, Skills ──────────────
1657
+ /** Get recent evolution stories (for L1 narrative embedding) */
1658
+ async getStories(options) {
1659
+ const query = {};
1660
+ if (options?.limit != null) query.limit = String(options.limit);
1661
+ if (options?.since != null) query.since = String(options.since);
1662
+ return this._r("GET", "/api/im/evolution/stories", void 0, query);
1663
+ }
1664
+ /** Get north-star metrics comparison (standard vs hypergraph) */
1665
+ async getMetrics() {
1666
+ return this._r("GET", "/api/im/evolution/metrics");
1667
+ }
1668
+ /** Trigger metrics collection snapshot */
1669
+ async collectMetrics(windowHours) {
1670
+ return this._r("POST", "/api/im/evolution/metrics/collect", { window_hours: windowHours ?? 1 });
1671
+ }
1672
+ /** Search skills catalog */
1673
+ async searchSkills(options) {
1674
+ const q = {};
1675
+ if (options?.query) q.query = options.query;
1676
+ if (options?.category) q.category = options.category;
1677
+ if (options?.limit != null) q.limit = String(options.limit);
1678
+ return this._r("GET", "/api/im/skills/search", void 0, q);
1679
+ }
1680
+ /** Get skill catalog stats */
1681
+ async getSkillStats() {
1682
+ return this._r("GET", "/api/im/skills/stats");
1683
+ }
1684
+ /** Install a skill — creates Gene + returns content + install guide */
1685
+ async installSkill(slugOrId) {
1686
+ return this._r("POST", `/api/im/skills/${encodeURIComponent(slugOrId)}/install`);
1687
+ }
1688
+ /** Uninstall a skill */
1689
+ async uninstallSkill(slugOrId) {
1690
+ return this._r("DELETE", `/api/im/skills/${encodeURIComponent(slugOrId)}/install`);
1691
+ }
1692
+ /** List installed skills for this agent */
1693
+ async installedSkills() {
1694
+ return this._r("GET", "/api/im/skills/installed");
1695
+ }
1696
+ /** Get full skill content (SKILL.md + package info) */
1697
+ async getSkillContent(slugOrId) {
1698
+ return this._r("GET", `/api/im/skills/${encodeURIComponent(slugOrId)}/content`);
1699
+ }
1700
+ /**
1701
+ * Install a skill and write SKILL.md to local filesystem.
1702
+ * Combines cloud install + local file sync for Claude Code / OpenClaw / OpenCode.
1703
+ * @param slugOrId - Skill slug or ID
1704
+ * @param options - Local install options
1705
+ */
1706
+ async installSkillLocal(slugOrId, options) {
1707
+ const result = await this.installSkill(slugOrId);
1708
+ if (!result.ok || !result.data) return result;
1709
+ let content = result.data.skill?.content || "";
1710
+ if (!content) {
1711
+ const contentResult = await this.getSkillContent(slugOrId);
1712
+ content = contentResult.data?.content || "";
1713
+ }
1714
+ if (!content) {
1715
+ return { ...result, data: { ...result.data, localPaths: [] } };
1716
+ }
1717
+ const rawSlug = result.data.skill?.slug || slugOrId;
1718
+ const slug = rawSlug.replace(/[\/\\]/g, "").replace(/\.\./g, "");
1719
+ if (!slug) {
1720
+ return { ...result, data: { ...result.data, localPaths: [] } };
1721
+ }
1722
+ const localPaths = [];
1723
+ try {
1724
+ const fs2 = await import("fs");
1725
+ const path2 = await import("path");
1726
+ const os2 = await import("os");
1727
+ const home = os2.homedir();
1728
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path2.join(home, ".claude", "plugins", "prismer");
1729
+ const platformPaths = options?.project ? {
1730
+ "claude-code": path2.join(options.projectRoot || ".", ".claude", "skills", slug),
1731
+ "openclaw": path2.join(options.projectRoot || ".", "skills", slug),
1732
+ "opencode": path2.join(options.projectRoot || ".", ".opencode", "skills", slug),
1733
+ "plugin": path2.join(options.projectRoot || ".", ".claude", "plugins", "prismer", "skills", slug)
1734
+ } : {
1735
+ "claude-code": path2.join(home, ".claude", "skills", slug),
1736
+ "openclaw": path2.join(home, ".openclaw", "skills", slug),
1737
+ "opencode": path2.join(home, ".config", "opencode", "skills", slug),
1738
+ "plugin": path2.join(pluginBase, "skills", slug)
1739
+ };
1740
+ const targets = options?.platforms || Object.keys(platformPaths);
1741
+ for (const platform of targets) {
1742
+ const dir = platformPaths[platform];
1743
+ if (!dir) continue;
1744
+ try {
1745
+ fs2.mkdirSync(dir, { recursive: true });
1746
+ const filePath = path2.join(dir, "SKILL.md");
1747
+ fs2.writeFileSync(filePath, content, "utf-8");
1748
+ localPaths.push(filePath);
1749
+ } catch {
1750
+ }
1751
+ }
1752
+ } catch {
1753
+ }
1754
+ return { ...result, data: { ...result.data, localPaths } };
1755
+ }
1756
+ /**
1757
+ * Uninstall a skill and remove local SKILL.md files.
1758
+ */
1759
+ async uninstallSkillLocal(slugOrId) {
1760
+ const result = await this.uninstallSkill(slugOrId);
1761
+ const removedPaths = [];
1762
+ const safeSlug = slugOrId.replace(/[\/\\]/g, "").replace(/\.\./g, "");
1763
+ if (!safeSlug) return { ...result, data: { uninstalled: result.data?.uninstalled ?? false, removedPaths } };
1764
+ try {
1765
+ const fs2 = await import("fs");
1766
+ const path2 = await import("path");
1767
+ const os2 = await import("os");
1768
+ const home = os2.homedir();
1769
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path2.join(home, ".claude", "plugins", "prismer");
1770
+ const dirs = [
1771
+ path2.join(home, ".claude", "skills", safeSlug),
1772
+ path2.join(home, ".openclaw", "skills", safeSlug),
1773
+ path2.join(home, ".config", "opencode", "skills", safeSlug),
1774
+ path2.join(pluginBase, "skills", safeSlug)
1775
+ ];
1776
+ for (const dir of dirs) {
1777
+ try {
1778
+ if (fs2.existsSync(dir)) {
1779
+ fs2.rmSync(dir, { recursive: true });
1780
+ removedPaths.push(dir);
1781
+ }
1782
+ } catch {
1783
+ }
1784
+ }
1785
+ } catch {
1786
+ }
1787
+ return { ...result, data: { uninstalled: result.data?.uninstalled ?? false, removedPaths } };
1788
+ }
1789
+ /**
1790
+ * Sync all installed skills to local filesystem.
1791
+ */
1792
+ async syncSkillsLocal(options) {
1793
+ const installed = await this.installedSkills();
1794
+ if (!installed.ok || !installed.data) return { synced: 0, failed: 0, paths: [] };
1795
+ let synced = 0;
1796
+ let failed = 0;
1797
+ const paths = [];
1798
+ for (const record of installed.data) {
1799
+ const rawSlug = record.skill?.slug;
1800
+ if (!rawSlug) {
1801
+ failed++;
1802
+ continue;
1803
+ }
1804
+ const slug = rawSlug.replace(/[\/\\]/g, "").replace(/\.\./g, "");
1805
+ if (!slug) {
1806
+ failed++;
1807
+ continue;
1808
+ }
1809
+ try {
1810
+ const contentResult = await this.getSkillContent(slug);
1811
+ const content = contentResult.data?.content;
1812
+ if (!content) {
1813
+ failed++;
1814
+ continue;
1815
+ }
1816
+ const fs2 = await import("fs");
1817
+ const path2 = await import("path");
1818
+ const os2 = await import("os");
1819
+ const home = os2.homedir();
1820
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path2.join(home, ".claude", "plugins", "prismer");
1821
+ const platformPaths = {
1822
+ "claude-code": path2.join(home, ".claude", "skills", slug),
1823
+ "openclaw": path2.join(home, ".openclaw", "skills", slug),
1824
+ "opencode": path2.join(home, ".config", "opencode", "skills", slug),
1825
+ "plugin": path2.join(pluginBase, "skills", slug)
1826
+ };
1827
+ const targets = options?.platforms || Object.keys(platformPaths);
1828
+ for (const platform of targets) {
1829
+ const dir = platformPaths[platform];
1830
+ if (!dir) continue;
1831
+ try {
1832
+ fs2.mkdirSync(dir, { recursive: true });
1833
+ const filePath = path2.join(dir, "SKILL.md");
1834
+ fs2.writeFileSync(filePath, content, "utf-8");
1835
+ paths.push(filePath);
1836
+ } catch {
1837
+ }
1838
+ }
1839
+ synced++;
1840
+ } catch {
1841
+ failed++;
1842
+ }
1843
+ }
1844
+ return { synced, failed, paths };
1845
+ }
1846
+ /** Export a Gene as a Skill */
1847
+ async exportAsSkill(geneId, options) {
1848
+ return this._r("POST", `/api/im/evolution/genes/${geneId}/export-skill`, options);
1849
+ }
1850
+ // ─── P0: Report, Achievements, Sync ──────────────
1851
+ /** Submit a raw-context evolution report (auto-creates signals + gene match) */
1852
+ async submitReport(options) {
1853
+ return this._r("POST", "/api/im/evolution/report", {
1854
+ raw_context: options.rawContext,
1855
+ outcome: options.outcome,
1856
+ task_context: options.taskContext,
1857
+ task_error: options.taskError,
1858
+ task_id: options.taskId,
1859
+ metadata: options.metadata
1860
+ });
1861
+ }
1862
+ /** Get status of a submitted report by traceId */
1863
+ async getReportStatus(traceId) {
1864
+ return this._r("GET", `/api/im/evolution/report/${traceId}`);
1865
+ }
1866
+ /** Get evolution achievements for the current agent */
1867
+ async getAchievements() {
1868
+ return this._r("GET", "/api/im/evolution/achievements");
1869
+ }
1870
+ /** Get a sync snapshot (global gene/edge state since a sequence number) */
1871
+ async getSyncSnapshot(since) {
1872
+ const query = { scope: "global" };
1873
+ if (since != null) query.since = String(since);
1874
+ return this._r("GET", "/api/im/evolution/sync/snapshot", void 0, query);
1875
+ }
1876
+ /** Bidirectional sync: push local outcomes and pull remote updates */
1877
+ async sync(options) {
1878
+ const body = {};
1879
+ if (options?.pushOutcomes) body.push = { outcomes: options.pushOutcomes };
1880
+ if (options?.pullSince != null) body.pull = { since: options.pullSince };
1881
+ return this._r("POST", "/api/im/evolution/sync", body);
1882
+ }
1883
+ };
1329
1884
  function guessMimeType(fileName) {
1330
1885
  const ext = fileName.split(".").pop()?.toLowerCase() || "";
1331
1886
  const map = {
@@ -1564,6 +2119,11 @@ var IMClient = class {
1564
2119
  this.bindings = new BindingsClient(request);
1565
2120
  this.credits = new CreditsClient(request);
1566
2121
  this.workspace = new WorkspaceClient(request);
2122
+ this.tasks = new TasksClient(request);
2123
+ this.memory = new MemoryClient(request);
2124
+ this.identity = new IdentityClient(request);
2125
+ this.security = new SecurityClient(request);
2126
+ this.evolution = new EvolutionClient(request);
1567
2127
  this.files = new FilesClient(request, wsBase, fetchFn, getAuthHeaders);
1568
2128
  this.realtime = new IMRealtimeClient(wsBase);
1569
2129
  this.offline = offlineManager ?? null;
@@ -1733,121 +2293,2410 @@ var PrismerClient = class {
1733
2293
  }
1734
2294
  };
1735
2295
 
1736
- // src/cli.ts
1737
- var cliVersion = "1.3.3";
1738
- try {
1739
- const pkgPath = path.join(__dirname, "..", "package.json");
1740
- const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
1741
- cliVersion = pkg.version || cliVersion;
1742
- } catch {
1743
- }
1744
- var CONFIG_DIR = path.join(os.homedir(), ".prismer");
1745
- var CONFIG_PATH = path.join(CONFIG_DIR, "config.toml");
1746
- function ensureConfigDir() {
1747
- if (!fs.existsSync(CONFIG_DIR)) {
1748
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
1749
- }
1750
- }
1751
- function readConfig() {
1752
- if (!fs.existsSync(CONFIG_PATH)) {
1753
- return {};
1754
- }
1755
- const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
1756
- return TOML.parse(raw);
1757
- }
1758
- function writeConfig(config) {
1759
- ensureConfigDir();
1760
- const content = TOML.stringify(config);
1761
- fs.writeFileSync(CONFIG_PATH, content, "utf-8");
1762
- }
1763
- function setNestedValue(obj, dotPath, value) {
1764
- const parts = dotPath.split(".");
1765
- let current = obj;
1766
- for (let i = 0; i < parts.length - 1; i++) {
1767
- const key = parts[i];
1768
- if (current[key] === void 0 || typeof current[key] !== "object") {
1769
- current[key] = {};
2296
+ // src/commands/im.ts
2297
+ function register(parent, getIMClient2, _getAPIClient) {
2298
+ const im = parent.command("im").description("IM messaging, groups, conversations, and credits");
2299
+ im.command("send <user-id> <message>").description("Send a direct message to a user").option("-t, --type <type>", "Message type: text, markdown, code, file, etc.", "text").option("--reply-to <msg-id>", "Reply to a specific message ID (parentId)").option("--json", "Output raw JSON response").action(async (userId, message, opts) => {
2300
+ const client = getIMClient2();
2301
+ try {
2302
+ const sendOpts = {
2303
+ type: opts.type
2304
+ };
2305
+ if (opts.replyTo) sendOpts.parentId = opts.replyTo;
2306
+ const res = await client.im.direct.send(userId, message, sendOpts);
2307
+ if (!res.ok) {
2308
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2309
+ `);
2310
+ process.exit(1);
2311
+ }
2312
+ if (opts.json) {
2313
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
2314
+ return;
2315
+ }
2316
+ process.stdout.write(`Message sent (conversationId: ${res.data?.conversationId})
2317
+ `);
2318
+ } catch (err) {
2319
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2320
+ `);
2321
+ process.exit(1);
1770
2322
  }
1771
- current = current[key];
1772
- }
1773
- current[parts[parts.length - 1]] = value;
1774
- }
1775
- function getIMClient() {
1776
- const cfg = readConfig();
1777
- const token = cfg?.auth?.im_token;
1778
- if (!token) {
1779
- console.error('No IM token. Run "prismer register" first.');
1780
- process.exit(1);
1781
- }
1782
- const env = cfg?.default?.environment || "production";
1783
- const baseUrl = cfg?.default?.base_url || "";
1784
- return new PrismerClient({ apiKey: token, environment: env, ...baseUrl ? { baseUrl } : {} });
1785
- }
1786
- function getAPIClient() {
1787
- const cfg = readConfig();
1788
- const apiKey = cfg?.default?.api_key;
1789
- if (!apiKey) {
1790
- console.error('No API key. Run "prismer init <api-key>" first.');
1791
- process.exit(1);
1792
- }
1793
- const env = cfg?.default?.environment || "production";
1794
- const baseUrl = cfg?.default?.base_url || "";
1795
- return new PrismerClient({ apiKey, environment: env, ...baseUrl ? { baseUrl } : {} });
1796
- }
1797
- var program = new import_commander.Command();
1798
- program.name("prismer").description("Prismer Cloud SDK CLI").version(cliVersion);
1799
- program.command("init <api-key>").description("Store API key in ~/.prismer/config.toml").action((apiKey) => {
1800
- const config = readConfig();
1801
- if (!config.default) {
1802
- config.default = {};
1803
- }
1804
- config.default.api_key = apiKey;
1805
- if (!config.default.environment) {
1806
- config.default.environment = "production";
1807
- }
1808
- if (config.default.base_url === void 0) {
1809
- config.default.base_url = "";
1810
- }
1811
- writeConfig(config);
1812
- console.log("API key saved to ~/.prismer/config.toml");
1813
- });
1814
- program.command("register <username>").description("Register an IM agent and store the token").option("--type <type>", "Identity type: agent or human", "agent").option("--display-name <name>", "Display name for the agent").option("--agent-type <agentType>", "Agent type: assistant, specialist, orchestrator, tool, or bot").option("--capabilities <caps>", "Comma-separated list of capabilities").action(async (username, opts) => {
1815
- const config = readConfig();
1816
- const apiKey = config.default?.api_key;
1817
- if (!apiKey) {
1818
- console.error('Error: No API key configured. Run "prismer init <api-key>" first.');
1819
- process.exit(1);
1820
- }
1821
- const client = new PrismerClient({
1822
- apiKey,
1823
- environment: config.default?.environment || "production",
1824
- baseUrl: config.default?.base_url || void 0
1825
2323
  });
1826
- const registerOpts = {
1827
- type: opts.type,
1828
- username,
1829
- displayName: opts.displayName || username
1830
- };
1831
- if (opts.agentType) {
1832
- registerOpts.agentType = opts.agentType;
1833
- }
1834
- if (opts.capabilities) {
1835
- registerOpts.capabilities = opts.capabilities.split(",").map((c) => c.trim());
1836
- }
1837
- try {
1838
- const result = await client.im.account.register(registerOpts);
1839
- if (!result.ok || !result.data) {
1840
- console.error("Registration failed:", result.error?.message || "Unknown error");
2324
+ im.command("messages <user-id>").description("View direct message history with a user").option("-n, --limit <n>", "Max number of messages to fetch", "20").option("--json", "Output raw JSON response").action(async (userId, opts) => {
2325
+ const client = getIMClient2();
2326
+ try {
2327
+ const res = await client.im.direct.getMessages(userId, { limit: parseInt(opts.limit, 10) });
2328
+ if (!res.ok) {
2329
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2330
+ `);
2331
+ process.exit(1);
2332
+ }
2333
+ const msgs = res.data || [];
2334
+ if (opts.json) {
2335
+ process.stdout.write(JSON.stringify(msgs, null, 2) + "\n");
2336
+ return;
2337
+ }
2338
+ if (msgs.length === 0) {
2339
+ process.stdout.write("No messages.\n");
2340
+ return;
2341
+ }
2342
+ for (const m of msgs) {
2343
+ const ts = m.createdAt ? new Date(m.createdAt).toLocaleString() : "";
2344
+ process.stdout.write(`[${ts}] ${m.senderId || "?"}: ${m.content}
2345
+ `);
2346
+ }
2347
+ } catch (err) {
2348
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2349
+ `);
1841
2350
  process.exit(1);
1842
2351
  }
1843
- const data = result.data;
1844
- if (!config.auth) {
1845
- config.auth = {};
1846
- }
1847
- config.auth.im_token = data.token;
1848
- config.auth.im_user_id = data.imUserId;
1849
- config.auth.im_username = data.username;
1850
- config.auth.im_token_expires = data.expiresIn;
2352
+ });
2353
+ im.command("edit <conversation-id> <message-id> <content>").description("Edit an existing message").option("--json", "Output raw JSON response").action(async (convId, msgId, content, opts) => {
2354
+ const client = getIMClient2();
2355
+ try {
2356
+ const res = await client.im.messages.edit(convId, msgId, content);
2357
+ if (!res.ok) {
2358
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2359
+ `);
2360
+ process.exit(1);
2361
+ }
2362
+ if (opts.json) {
2363
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
2364
+ return;
2365
+ }
2366
+ process.stdout.write(`Message ${msgId} updated.
2367
+ `);
2368
+ } catch (err) {
2369
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2370
+ `);
2371
+ process.exit(1);
2372
+ }
2373
+ });
2374
+ im.command("delete <conversation-id> <message-id>").description("Delete a message").option("--json", "Output raw JSON response").action(async (convId, msgId, opts) => {
2375
+ const client = getIMClient2();
2376
+ try {
2377
+ const res = await client.im.messages.delete(convId, msgId);
2378
+ if (!res.ok) {
2379
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2380
+ `);
2381
+ process.exit(1);
2382
+ }
2383
+ if (opts.json) {
2384
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
2385
+ return;
2386
+ }
2387
+ process.stdout.write(`Message ${msgId} deleted.
2388
+ `);
2389
+ } catch (err) {
2390
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2391
+ `);
2392
+ process.exit(1);
2393
+ }
2394
+ });
2395
+ im.command("discover").description("Discover available agents").option("--type <type>", "Filter by agent type").option("--capability <cap>", "Filter by capability").option("--json", "Output raw JSON response").action(async (opts) => {
2396
+ const client = getIMClient2();
2397
+ try {
2398
+ const discoverOpts = {};
2399
+ if (opts.type) discoverOpts.type = opts.type;
2400
+ if (opts.capability) discoverOpts.capability = opts.capability;
2401
+ const res = await client.im.contacts.discover(Object.keys(discoverOpts).length ? discoverOpts : void 0);
2402
+ if (!res.ok) {
2403
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2404
+ `);
2405
+ process.exit(1);
2406
+ }
2407
+ const agents = res.data || [];
2408
+ if (opts.json) {
2409
+ process.stdout.write(JSON.stringify(agents, null, 2) + "\n");
2410
+ return;
2411
+ }
2412
+ if (agents.length === 0) {
2413
+ process.stdout.write("No agents found.\n");
2414
+ return;
2415
+ }
2416
+ process.stdout.write(
2417
+ "Username".padEnd(20) + "Type".padEnd(14) + "Status".padEnd(10) + "Display Name\n"
2418
+ );
2419
+ for (const a of agents) {
2420
+ process.stdout.write(
2421
+ `${(a.username || "").padEnd(20)}${(a.agentType || "").padEnd(14)}${(a.status || "").padEnd(10)}${a.displayName || ""}
2422
+ `
2423
+ );
2424
+ }
2425
+ } catch (err) {
2426
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2427
+ `);
2428
+ process.exit(1);
2429
+ }
2430
+ });
2431
+ im.command("contacts").description("List contacts").option("--json", "Output raw JSON response").action(async (opts) => {
2432
+ const client = getIMClient2();
2433
+ try {
2434
+ const res = await client.im.contacts.list();
2435
+ if (!res.ok) {
2436
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2437
+ `);
2438
+ process.exit(1);
2439
+ }
2440
+ const contacts = res.data || [];
2441
+ if (opts.json) {
2442
+ process.stdout.write(JSON.stringify(contacts, null, 2) + "\n");
2443
+ return;
2444
+ }
2445
+ if (contacts.length === 0) {
2446
+ process.stdout.write("No contacts.\n");
2447
+ return;
2448
+ }
2449
+ process.stdout.write(
2450
+ "Username".padEnd(20) + "Role".padEnd(10) + "Unread".padEnd(8) + "Display Name\n"
2451
+ );
2452
+ for (const c of contacts) {
2453
+ process.stdout.write(
2454
+ `${(c.username || "").padEnd(20)}${(c.role || "").padEnd(10)}${String(c.unreadCount ?? 0).padEnd(8)}${c.displayName || ""}
2455
+ `
2456
+ );
2457
+ }
2458
+ } catch (err) {
2459
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2460
+ `);
2461
+ process.exit(1);
2462
+ }
2463
+ });
2464
+ im.command("conversations").description("List conversations").option("--unread", "Show only conversations with unread messages").option("--json", "Output raw JSON response").action(async (opts) => {
2465
+ const client = getIMClient2();
2466
+ try {
2467
+ const listOpts = {};
2468
+ if (opts.unread) {
2469
+ listOpts.withUnread = true;
2470
+ listOpts.unreadOnly = true;
2471
+ }
2472
+ const res = await client.im.conversations.list(listOpts);
2473
+ if (!res.ok) {
2474
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2475
+ `);
2476
+ process.exit(1);
2477
+ }
2478
+ const list = res.data || [];
2479
+ if (opts.json) {
2480
+ process.stdout.write(JSON.stringify(list, null, 2) + "\n");
2481
+ return;
2482
+ }
2483
+ if (list.length === 0) {
2484
+ process.stdout.write("No conversations.\n");
2485
+ return;
2486
+ }
2487
+ for (const c of list) {
2488
+ const unread = c.unreadCount ? ` (${c.unreadCount} unread)` : "";
2489
+ process.stdout.write(`${c.id || ""} ${c.type || ""} ${c.title || ""}${unread}
2490
+ `);
2491
+ }
2492
+ } catch (err) {
2493
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2494
+ `);
2495
+ process.exit(1);
2496
+ }
2497
+ });
2498
+ im.command("read <conversation-id>").description("Mark a conversation as read").action(async (convId) => {
2499
+ const client = getIMClient2();
2500
+ try {
2501
+ const res = await client.im.conversations.markAsRead(convId);
2502
+ if (!res.ok) {
2503
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2504
+ `);
2505
+ process.exit(1);
2506
+ }
2507
+ process.stdout.write("Marked as read.\n");
2508
+ } catch (err) {
2509
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2510
+ `);
2511
+ process.exit(1);
2512
+ }
2513
+ });
2514
+ const groups = im.command("groups").description("Group chat management");
2515
+ groups.command("create <title>").description("Create a new group").option("-m, --members <ids>", "Comma-separated member user IDs to add").option("--json", "Output raw JSON response").action(async (title, opts) => {
2516
+ const client = getIMClient2();
2517
+ try {
2518
+ const members = opts.members ? opts.members.split(",").map((s) => s.trim()) : [];
2519
+ const res = await client.im.groups.create({ title, members });
2520
+ if (!res.ok) {
2521
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2522
+ `);
2523
+ process.exit(1);
2524
+ }
2525
+ if (opts.json) {
2526
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
2527
+ return;
2528
+ }
2529
+ process.stdout.write(`Group created (groupId: ${res.data?.groupId})
2530
+ `);
2531
+ } catch (err) {
2532
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2533
+ `);
2534
+ process.exit(1);
2535
+ }
2536
+ });
2537
+ groups.command("list").description("List groups you belong to").option("--json", "Output raw JSON response").action(async (opts) => {
2538
+ const client = getIMClient2();
2539
+ try {
2540
+ const res = await client.im.groups.list();
2541
+ if (!res.ok) {
2542
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2543
+ `);
2544
+ process.exit(1);
2545
+ }
2546
+ const list = res.data || [];
2547
+ if (opts.json) {
2548
+ process.stdout.write(JSON.stringify(list, null, 2) + "\n");
2549
+ return;
2550
+ }
2551
+ if (list.length === 0) {
2552
+ process.stdout.write("No groups.\n");
2553
+ return;
2554
+ }
2555
+ for (const g of list) {
2556
+ process.stdout.write(`${g.groupId || ""} ${g.title || ""} (${g.members?.length || "?"} members)
2557
+ `);
2558
+ }
2559
+ } catch (err) {
2560
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2561
+ `);
2562
+ process.exit(1);
2563
+ }
2564
+ });
2565
+ groups.command("send <group-id> <message>").description("Send a message to a group").option("--json", "Output raw JSON response").action(async (groupId, message, opts) => {
2566
+ const client = getIMClient2();
2567
+ try {
2568
+ const res = await client.im.groups.send(groupId, message);
2569
+ if (!res.ok) {
2570
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2571
+ `);
2572
+ process.exit(1);
2573
+ }
2574
+ if (opts.json) {
2575
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
2576
+ return;
2577
+ }
2578
+ process.stdout.write("Message sent to group.\n");
2579
+ } catch (err) {
2580
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2581
+ `);
2582
+ process.exit(1);
2583
+ }
2584
+ });
2585
+ groups.command("messages <group-id>").description("View group message history").option("-n, --limit <n>", "Max number of messages to fetch", "20").option("--json", "Output raw JSON response").action(async (groupId, opts) => {
2586
+ const client = getIMClient2();
2587
+ try {
2588
+ const res = await client.im.groups.getMessages(groupId, { limit: parseInt(opts.limit, 10) });
2589
+ if (!res.ok) {
2590
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2591
+ `);
2592
+ process.exit(1);
2593
+ }
2594
+ const msgs = res.data || [];
2595
+ if (opts.json) {
2596
+ process.stdout.write(JSON.stringify(msgs, null, 2) + "\n");
2597
+ return;
2598
+ }
2599
+ if (msgs.length === 0) {
2600
+ process.stdout.write("No messages.\n");
2601
+ return;
2602
+ }
2603
+ for (const m of msgs) {
2604
+ const ts = m.createdAt ? new Date(m.createdAt).toLocaleString() : "";
2605
+ process.stdout.write(`[${ts}] ${m.senderId || "?"}: ${m.content}
2606
+ `);
2607
+ }
2608
+ } catch (err) {
2609
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2610
+ `);
2611
+ process.exit(1);
2612
+ }
2613
+ });
2614
+ im.command("me").description("Show current identity, agent card, credits, and stats").option("--json", "Output raw JSON response").action(async (opts) => {
2615
+ const client = getIMClient2();
2616
+ try {
2617
+ const res = await client.im.account.me();
2618
+ if (!res.ok) {
2619
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2620
+ `);
2621
+ process.exit(1);
2622
+ }
2623
+ const d = res.data;
2624
+ if (opts.json) {
2625
+ process.stdout.write(JSON.stringify(d, null, 2) + "\n");
2626
+ return;
2627
+ }
2628
+ process.stdout.write(`Display Name: ${d?.user?.displayName || "-"}
2629
+ `);
2630
+ process.stdout.write(`Username: ${d?.user?.username || "-"}
2631
+ `);
2632
+ process.stdout.write(`Role: ${d?.user?.role || "-"}
2633
+ `);
2634
+ process.stdout.write(`Agent Type: ${d?.agentCard?.agentType || "-"}
2635
+ `);
2636
+ process.stdout.write(`Credits: ${d?.credits?.balance ?? "-"}
2637
+ `);
2638
+ process.stdout.write(`Messages: ${d?.stats?.messagesSent ?? "-"}
2639
+ `);
2640
+ process.stdout.write(`Unread: ${d?.stats?.unreadCount ?? "-"}
2641
+ `);
2642
+ } catch (err) {
2643
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2644
+ `);
2645
+ process.exit(1);
2646
+ }
2647
+ });
2648
+ im.command("credits").description("Show credits balance").option("--json", "Output raw JSON response").action(async (opts) => {
2649
+ const client = getIMClient2();
2650
+ try {
2651
+ const res = await client.im.credits.get();
2652
+ if (!res.ok) {
2653
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2654
+ `);
2655
+ process.exit(1);
2656
+ }
2657
+ if (opts.json) {
2658
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
2659
+ return;
2660
+ }
2661
+ process.stdout.write(`Balance: ${res.data?.balance ?? "-"}
2662
+ `);
2663
+ } catch (err) {
2664
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2665
+ `);
2666
+ process.exit(1);
2667
+ }
2668
+ });
2669
+ im.command("transactions").description("Show credit transaction history").option("-n, --limit <n>", "Max number of transactions to fetch", "20").option("--json", "Output raw JSON response").action(async (opts) => {
2670
+ const client = getIMClient2();
2671
+ try {
2672
+ const res = await client.im.credits.transactions({ limit: parseInt(opts.limit, 10) });
2673
+ if (!res.ok) {
2674
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2675
+ `);
2676
+ process.exit(1);
2677
+ }
2678
+ const txns = res.data || [];
2679
+ if (opts.json) {
2680
+ process.stdout.write(JSON.stringify(txns, null, 2) + "\n");
2681
+ return;
2682
+ }
2683
+ if (txns.length === 0) {
2684
+ process.stdout.write("No transactions.\n");
2685
+ return;
2686
+ }
2687
+ process.stdout.write(
2688
+ "Date".padEnd(24) + "Type".padEnd(20) + "Amount".padEnd(12) + "Description\n"
2689
+ );
2690
+ for (const t of txns) {
2691
+ const date = t.createdAt ? new Date(t.createdAt).toLocaleString() : "";
2692
+ process.stdout.write(
2693
+ `${date.padEnd(24)}${(t.type || "").padEnd(20)}${String(t.amount ?? "").padEnd(12)}${t.description || ""}
2694
+ `
2695
+ );
2696
+ }
2697
+ } catch (err) {
2698
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2699
+ `);
2700
+ process.exit(1);
2701
+ }
2702
+ });
2703
+ im.command("heartbeat").description("Send agent heartbeat (online/busy/offline) with optional load").option("--status <status>", "Presence status: online, busy, or offline", "online").option("--load <n>", "Current load factor (0.0 to 1.0)").option("--json", "Output raw JSON response").action(async (opts) => {
2704
+ const client = getIMClient2();
2705
+ try {
2706
+ const body = { status: opts.status };
2707
+ if (opts.load !== void 0) {
2708
+ const load = parseFloat(opts.load);
2709
+ if (!isNaN(load)) body.load = load;
2710
+ }
2711
+ const res = await client.im.account._r("POST", "/api/im/agents/heartbeat", body);
2712
+ if (!res.ok) {
2713
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
2714
+ `);
2715
+ process.exit(1);
2716
+ }
2717
+ if (opts.json) {
2718
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
2719
+ return;
2720
+ }
2721
+ process.stdout.write(`Heartbeat sent (status: ${opts.status}${opts.load !== void 0 ? `, load: ${opts.load}` : ""}).
2722
+ `);
2723
+ } catch (err) {
2724
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2725
+ `);
2726
+ process.exit(1);
2727
+ }
2728
+ });
2729
+ im.command("health").description("Check IM service health").action(async () => {
2730
+ const client = getIMClient2();
2731
+ try {
2732
+ const res = await client.im.health();
2733
+ if (!res.ok) {
2734
+ process.stderr.write(`IM Service: ERROR
2735
+ `);
2736
+ process.stderr.write(`${JSON.stringify(res.error)}
2737
+ `);
2738
+ process.exit(1);
2739
+ }
2740
+ process.stdout.write("IM Service: OK\n");
2741
+ } catch (err) {
2742
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
2743
+ `);
2744
+ process.exit(1);
2745
+ }
2746
+ });
2747
+ }
2748
+
2749
+ // src/commands/context.ts
2750
+ function register2(parent, _getIMClient, getAPIClient2) {
2751
+ const ctx = parent.command("context").description("Context loading, searching, and caching");
2752
+ ctx.command("load <urls...>").description("Load one or more URLs into context").option("-f, --format <fmt>", "output format: hqcc, raw, or both", "hqcc").option("--json", "output raw JSON response").action(async (urls, opts) => {
2753
+ const client = getAPIClient2();
2754
+ try {
2755
+ const input = urls.length === 1 ? urls[0] : urls;
2756
+ const format = opts.format;
2757
+ const res = await client.load(input, {
2758
+ return: { format }
2759
+ });
2760
+ if (opts.json) {
2761
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
2762
+ return;
2763
+ }
2764
+ if (!res.success) {
2765
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
2766
+ `);
2767
+ process.exit(1);
2768
+ }
2769
+ const results = res.results ?? (res.result ? [res.result] : []);
2770
+ if (results.length === 0) {
2771
+ process.stdout.write("No results returned.\n");
2772
+ return;
2773
+ }
2774
+ for (const item of results) {
2775
+ process.stdout.write(`
2776
+ --- ${item.url ?? item.input ?? "result"} ---
2777
+ `);
2778
+ const hqcc = item.hqcc ?? item.content ?? "";
2779
+ if (hqcc) {
2780
+ const truncated = hqcc.length > 2e3 ? hqcc.slice(0, 2e3) + "... [truncated]" : hqcc;
2781
+ process.stdout.write(truncated + "\n");
2782
+ }
2783
+ if (item.cached !== void 0) {
2784
+ process.stdout.write(`[cached: ${item.cached}]
2785
+ `);
2786
+ }
2787
+ }
2788
+ } catch (err) {
2789
+ const message = err instanceof Error ? err.message : String(err);
2790
+ process.stderr.write(`Error: ${message}
2791
+ `);
2792
+ process.exit(1);
2793
+ }
2794
+ });
2795
+ ctx.command("search <query>").description("Search for content using a natural language query").option("-k, --top-k <n>", "number of results to return", "5").option("--json", "output raw JSON response").action(async (query, opts) => {
2796
+ const client = getAPIClient2();
2797
+ try {
2798
+ const topK = parseInt(opts.topK, 10);
2799
+ const res = await client.search(query, { topK });
2800
+ if (opts.json) {
2801
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
2802
+ return;
2803
+ }
2804
+ if (!res.success) {
2805
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
2806
+ `);
2807
+ process.exit(1);
2808
+ }
2809
+ const results = res.results ?? (res.result ? [res.result] : []);
2810
+ if (results.length === 0) {
2811
+ process.stdout.write("No results found.\n");
2812
+ return;
2813
+ }
2814
+ process.stdout.write(`Search results for: "${query}"
2815
+
2816
+ `);
2817
+ results.forEach((item, i) => {
2818
+ process.stdout.write(`[${i + 1}] ${item.url ?? item.input ?? "result"}
2819
+ `);
2820
+ const hqcc = item.hqcc ?? item.content ?? "";
2821
+ if (hqcc) {
2822
+ const truncated = hqcc.length > 2e3 ? hqcc.slice(0, 2e3) + "... [truncated]" : hqcc;
2823
+ process.stdout.write(truncated + "\n");
2824
+ }
2825
+ process.stdout.write("\n");
2826
+ });
2827
+ } catch (err) {
2828
+ const message = err instanceof Error ? err.message : String(err);
2829
+ process.stderr.write(`Error: ${message}
2830
+ `);
2831
+ process.exit(1);
2832
+ }
2833
+ });
2834
+ ctx.command("save <url> <hqcc>").description("Save a URL and its HQCC content to the context cache").option("--json", "output raw JSON response").action(async (url, hqcc, opts) => {
2835
+ const client = getAPIClient2();
2836
+ try {
2837
+ const res = await client.save({ url, hqcc });
2838
+ if (opts.json) {
2839
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
2840
+ return;
2841
+ }
2842
+ if (!res.success) {
2843
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
2844
+ `);
2845
+ process.exit(1);
2846
+ }
2847
+ process.stdout.write(`Saved: ${url}
2848
+ `);
2849
+ } catch (err) {
2850
+ const message = err instanceof Error ? err.message : String(err);
2851
+ process.stderr.write(`Error: ${message}
2852
+ `);
2853
+ process.exit(1);
2854
+ }
2855
+ });
2856
+ }
2857
+
2858
+ // src/commands/evolve.ts
2859
+ function parseSignals(raw) {
2860
+ if (!raw) return void 0;
2861
+ const trimmed = raw.trim();
2862
+ if (trimmed.startsWith("[")) {
2863
+ try {
2864
+ const parsed = JSON.parse(trimmed);
2865
+ if (Array.isArray(parsed)) return parsed.map(String);
2866
+ } catch {
2867
+ }
2868
+ }
2869
+ return trimmed.split(",").map((s) => s.trim()).filter(Boolean);
2870
+ }
2871
+ function handleError(err) {
2872
+ const message = err instanceof Error ? err.message : String(err);
2873
+ process.stderr.write(`Error: ${message}
2874
+ `);
2875
+ process.exit(1);
2876
+ }
2877
+ function printResult(res, label) {
2878
+ if (!res.ok) {
2879
+ const errMsg = res.error && typeof res.error === "object" && "message" in res.error ? res.error.message : JSON.stringify(res.error);
2880
+ process.stderr.write(`Error: ${errMsg || "Unknown error"}
2881
+ `);
2882
+ process.exit(1);
2883
+ }
2884
+ if (label) {
2885
+ process.stdout.write(`${label}
2886
+ `);
2887
+ }
2888
+ }
2889
+ function register3(parent, getIMClient2, _getAPIClient) {
2890
+ const evolve = parent.command("evolve").description("Evolution engine \u2014 analyze signals, manage genes, track learning");
2891
+ evolve.command("analyze").description("Analyze signals to find matching evolution strategies").option("-e, --error <msg>", "error message to analyze").option("-s, --signals <signals>", "signals as JSON array or comma-separated list").option("--task-status <status>", "task status (e.g. failed, timeout)").option("--provider <name>", "provider name (e.g. openai, exa)").option("--stage <stage>", "pipeline stage").option("--severity <level>", "severity level (low, medium, high, critical)").option("--tags <tags>", "comma-separated tags").option("--scope <scope>", "evolution scope (default: global)").option("--json", "output raw JSON response").action(async (opts) => {
2892
+ const client = getIMClient2();
2893
+ try {
2894
+ const signals = parseSignals(opts.signals);
2895
+ const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
2896
+ const res = await client.im.evolution.analyze({
2897
+ signals,
2898
+ error: opts.error,
2899
+ task_status: opts.taskStatus,
2900
+ provider: opts.provider,
2901
+ stage: opts.stage,
2902
+ severity: opts.severity,
2903
+ tags,
2904
+ scope: opts.scope
2905
+ });
2906
+ if (opts.json) {
2907
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
2908
+ return;
2909
+ }
2910
+ printResult(res);
2911
+ const data = res.data;
2912
+ if (data) {
2913
+ const matches = data.matches;
2914
+ const count = matches?.length ?? 0;
2915
+ process.stdout.write(`Matched ${count} gene(s)
2916
+ `);
2917
+ if (matches && count > 0) {
2918
+ for (const m of matches) {
2919
+ const id = m.gene_id ?? m.id ?? "?";
2920
+ const title = m.title ?? m.name ?? "";
2921
+ const score = m.score !== void 0 ? ` (score: ${m.score})` : "";
2922
+ process.stdout.write(` \u2022 ${id}${title ? ` \u2014 ${title}` : ""}${score}
2923
+ `);
2924
+ }
2925
+ }
2926
+ }
2927
+ } catch (err) {
2928
+ handleError(err);
2929
+ }
2930
+ });
2931
+ evolve.command("record").description("Record an outcome against an evolution gene").requiredOption("-g, --gene <id>", "gene ID to record against").requiredOption("-o, --outcome <outcome>", "outcome: success, failure, partial").option("-s, --signals <signals>", "signals as JSON array or comma-separated list").option("--score <n>", "outcome score (0-1)").option("--summary <text>", "brief summary of the outcome").option("--scope <scope>", "evolution scope (default: global)").option("--json", "output raw JSON response").action(async (opts) => {
2932
+ const client = getIMClient2();
2933
+ try {
2934
+ const signals = parseSignals(opts.signals);
2935
+ const score = opts.score !== void 0 ? parseFloat(opts.score) : void 0;
2936
+ const res = await client.im.evolution.record({
2937
+ gene_id: opts.gene,
2938
+ signals,
2939
+ outcome: opts.outcome,
2940
+ score,
2941
+ summary: opts.summary,
2942
+ scope: opts.scope
2943
+ });
2944
+ if (opts.json) {
2945
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
2946
+ return;
2947
+ }
2948
+ printResult(res, `Recorded outcome "${opts.outcome}" for gene ${opts.gene}`);
2949
+ } catch (err) {
2950
+ handleError(err);
2951
+ }
2952
+ });
2953
+ evolve.command("report").description("Submit a full evolution report (error + status context)").requiredOption("-e, --error <msg>", "raw error message or context").requiredOption("--status <outcome>", "final task outcome (success, failure, partial)").option("--task <context>", "task context description").option("--wait", "poll for report completion (max 60s)").option("--json", "output raw JSON response").action(async (opts) => {
2954
+ const client = getIMClient2();
2955
+ try {
2956
+ const res = await client.im.evolution.submitReport({
2957
+ rawContext: opts.error,
2958
+ outcome: opts.status,
2959
+ taskContext: opts.task
2960
+ });
2961
+ if (opts.json && !opts.wait) {
2962
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
2963
+ return;
2964
+ }
2965
+ if (!res.ok) {
2966
+ const errMsg = res.error && typeof res.error === "object" && "message" in res.error ? res.error.message : JSON.stringify(res.error);
2967
+ process.stderr.write(`Error: ${errMsg || "Unknown error"}
2968
+ `);
2969
+ process.exit(1);
2970
+ }
2971
+ const submitData = res.data;
2972
+ const traceId = submitData?.trace_id;
2973
+ if (!opts.wait || !traceId) {
2974
+ if (opts.json) {
2975
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
2976
+ } else {
2977
+ process.stdout.write(`Report submitted. trace_id: ${traceId ?? "unknown"}
2978
+ `);
2979
+ if (submitData?.fast_signals) {
2980
+ process.stdout.write(`Fast signals: ${JSON.stringify(submitData.fast_signals)}
2981
+ `);
2982
+ }
2983
+ }
2984
+ return;
2985
+ }
2986
+ if (!opts.json) {
2987
+ process.stdout.write(`Waiting for report ${traceId} `);
2988
+ }
2989
+ const maxIterations = 30;
2990
+ let lastStatus;
2991
+ for (let i = 0; i < maxIterations; i++) {
2992
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
2993
+ if (!opts.json) process.stdout.write(".");
2994
+ const statusRes = await client.im.evolution.getReportStatus(traceId);
2995
+ if (!statusRes.ok) break;
2996
+ const statusData = statusRes.data;
2997
+ lastStatus = statusData;
2998
+ if (statusData?.status === "done" || statusData?.status === "complete" || statusData?.status === "completed") {
2999
+ if (!opts.json) {
3000
+ process.stdout.write("\n");
3001
+ process.stdout.write(`Status: ${statusData.status}
3002
+ `);
3003
+ if (statusData.root_cause) process.stdout.write(`Root cause: ${statusData.root_cause}
3004
+ `);
3005
+ if (statusData.extracted_signals) process.stdout.write(`Extracted signals: ${JSON.stringify(statusData.extracted_signals)}
3006
+ `);
3007
+ } else {
3008
+ process.stdout.write(JSON.stringify({ trace_id: traceId, ...statusData }, null, 2) + "\n");
3009
+ }
3010
+ return;
3011
+ }
3012
+ }
3013
+ if (!opts.json) {
3014
+ process.stdout.write("\n");
3015
+ process.stdout.write(`Timed out waiting for report. Last status: ${JSON.stringify(lastStatus)}
3016
+ `);
3017
+ } else {
3018
+ process.stdout.write(JSON.stringify({ trace_id: traceId, status: "timeout", last: lastStatus }, null, 2) + "\n");
3019
+ }
3020
+ process.exit(1);
3021
+ } catch (err) {
3022
+ handleError(err);
3023
+ }
3024
+ });
3025
+ evolve.command("report-status <trace-id>").description("Check the status of a submitted evolution report").option("--json", "output raw JSON response").action(async (traceId, opts) => {
3026
+ const client = getIMClient2();
3027
+ try {
3028
+ const res = await client.im.evolution.getReportStatus(traceId);
3029
+ if (opts.json) {
3030
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3031
+ return;
3032
+ }
3033
+ printResult(res);
3034
+ const data = res.data;
3035
+ process.stdout.write(`trace_id: ${traceId}
3036
+ `);
3037
+ process.stdout.write(`status: ${data?.status ?? "unknown"}
3038
+ `);
3039
+ if (data?.root_cause) process.stdout.write(`root_cause: ${data.root_cause}
3040
+ `);
3041
+ if (data?.extracted_signals) process.stdout.write(`extracted_signals: ${JSON.stringify(data.extracted_signals)}
3042
+ `);
3043
+ } catch (err) {
3044
+ handleError(err);
3045
+ }
3046
+ });
3047
+ evolve.command("create").description("Create a new evolution gene").requiredOption("-c, --category <cat>", "gene category").requiredOption("-s, --signals <signals>", "trigger signals as JSON array or comma-separated list").requiredOption("--strategy <steps...>", "strategy steps (variadic)").option("-n, --name <title>", "gene title / display name").option("--scope <scope>", "evolution scope (default: global)").option("--json", "output raw JSON response").action(async (opts) => {
3048
+ const client = getIMClient2();
3049
+ try {
3050
+ const signals_match = parseSignals(opts.signals) ?? [];
3051
+ const res = await client.im.evolution.createGene({
3052
+ category: opts.category,
3053
+ signals_match,
3054
+ strategy: opts.strategy,
3055
+ title: opts.name,
3056
+ scope: opts.scope
3057
+ });
3058
+ if (opts.json) {
3059
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3060
+ return;
3061
+ }
3062
+ printResult(res);
3063
+ const data = res.data;
3064
+ const id = data?.gene_id ?? data?.id ?? "unknown";
3065
+ process.stdout.write(`Gene created: ${id}
3066
+ `);
3067
+ if (opts.name) process.stdout.write(`Title: ${opts.name}
3068
+ `);
3069
+ process.stdout.write(`Category: ${opts.category}
3070
+ `);
3071
+ } catch (err) {
3072
+ handleError(err);
3073
+ }
3074
+ });
3075
+ evolve.command("genes").description("List your own evolution genes").option("--scope <scope>", "filter by evolution scope").option("--json", "output raw JSON response").action(async (opts) => {
3076
+ const client = getIMClient2();
3077
+ try {
3078
+ const res = await client.im.evolution.listGenes(void 0, opts.scope);
3079
+ if (opts.json) {
3080
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3081
+ return;
3082
+ }
3083
+ printResult(res);
3084
+ const data = res.data;
3085
+ const genes = Array.isArray(data) ? data : data?.genes ?? data?.items ?? [];
3086
+ if (genes.length === 0) {
3087
+ process.stdout.write("No genes found.\n");
3088
+ return;
3089
+ }
3090
+ process.stdout.write(`${genes.length} gene(s):
3091
+ `);
3092
+ for (const g of genes) {
3093
+ const id = g.gene_id ?? g.id ?? "?";
3094
+ const title = g.title ?? g.name ?? "";
3095
+ const category = g.category ? ` [${g.category}]` : "";
3096
+ const scope = g.scope ? ` (${g.scope})` : "";
3097
+ process.stdout.write(` \u2022 ${id}${title ? ` \u2014 ${title}` : ""}${category}${scope}
3098
+ `);
3099
+ }
3100
+ } catch (err) {
3101
+ handleError(err);
3102
+ }
3103
+ });
3104
+ evolve.command("stats").description("Show public evolution statistics").option("--json", "output raw JSON response").action(async (opts) => {
3105
+ const client = getIMClient2();
3106
+ try {
3107
+ const res = await client.im.evolution.getStats();
3108
+ if (opts.json) {
3109
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3110
+ return;
3111
+ }
3112
+ printResult(res);
3113
+ const data = res.data;
3114
+ if (data) {
3115
+ for (const [key, val] of Object.entries(data)) {
3116
+ process.stdout.write(`${key}: ${JSON.stringify(val)}
3117
+ `);
3118
+ }
3119
+ }
3120
+ } catch (err) {
3121
+ handleError(err);
3122
+ }
3123
+ });
3124
+ evolve.command("metrics").description("Show A/B experiment metrics").option("--json", "output raw JSON response").action(async (opts) => {
3125
+ const client = getIMClient2();
3126
+ try {
3127
+ const res = await client.im.evolution.getMetrics();
3128
+ if (opts.json) {
3129
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3130
+ return;
3131
+ }
3132
+ printResult(res);
3133
+ const data = res.data;
3134
+ if (data) {
3135
+ for (const [key, val] of Object.entries(data)) {
3136
+ process.stdout.write(`${key}: ${JSON.stringify(val)}
3137
+ `);
3138
+ }
3139
+ }
3140
+ } catch (err) {
3141
+ handleError(err);
3142
+ }
3143
+ });
3144
+ evolve.command("achievements").description("Show your evolution achievements").option("--json", "output raw JSON response").action(async (opts) => {
3145
+ const client = getIMClient2();
3146
+ try {
3147
+ const res = await client.im.evolution.getAchievements();
3148
+ if (opts.json) {
3149
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3150
+ return;
3151
+ }
3152
+ printResult(res);
3153
+ const data = res.data;
3154
+ const achievements = Array.isArray(data) ? data : data?.achievements ?? data?.items ?? [];
3155
+ if (achievements.length === 0) {
3156
+ process.stdout.write("No achievements yet.\n");
3157
+ return;
3158
+ }
3159
+ process.stdout.write(`${achievements.length} achievement(s):
3160
+ `);
3161
+ for (const a of achievements) {
3162
+ const id = a.id ?? "?";
3163
+ const title = a.title ?? a.name ?? "";
3164
+ const desc = a.description ? ` \u2014 ${a.description}` : "";
3165
+ process.stdout.write(` \u2022 ${id}${title ? ` ${title}` : ""}${desc}
3166
+ `);
3167
+ }
3168
+ } catch (err) {
3169
+ handleError(err);
3170
+ }
3171
+ });
3172
+ evolve.command("sync").description("Get a sync snapshot of recent evolution data").option("--json", "output raw JSON response").action(async (opts) => {
3173
+ const client = getIMClient2();
3174
+ try {
3175
+ const res = await client.im.evolution.getSyncSnapshot();
3176
+ if (opts.json) {
3177
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3178
+ return;
3179
+ }
3180
+ printResult(res);
3181
+ const data = res.data;
3182
+ if (data) {
3183
+ const since = data.since ?? data.timestamp ?? data.generated_at;
3184
+ if (since) process.stdout.write(`Snapshot since: ${since}
3185
+ `);
3186
+ const genes = data.genes;
3187
+ const signals = data.signals;
3188
+ if (genes !== void 0) process.stdout.write(`Genes: ${genes.length}
3189
+ `);
3190
+ if (signals !== void 0) process.stdout.write(`Signals: ${signals.length}
3191
+ `);
3192
+ }
3193
+ } catch (err) {
3194
+ handleError(err);
3195
+ }
3196
+ });
3197
+ evolve.command("export-skill <gene-id>").description("Export a gene as a reusable skill").option("--slug <slug>", "skill slug identifier").option("--name <displayName>", "skill display name").option("--json", "output raw JSON response").action(async (geneId, opts) => {
3198
+ const client = getIMClient2();
3199
+ try {
3200
+ const res = await client.im.evolution.exportAsSkill(geneId, {
3201
+ slug: opts.slug,
3202
+ displayName: opts.name
3203
+ });
3204
+ if (opts.json) {
3205
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3206
+ return;
3207
+ }
3208
+ printResult(res);
3209
+ const data = res.data;
3210
+ process.stdout.write(`Skill exported from gene: ${geneId}
3211
+ `);
3212
+ if (data?.skill_id) process.stdout.write(`skill_id: ${data.skill_id}
3213
+ `);
3214
+ if (data?.slug) process.stdout.write(`slug: ${data.slug}
3215
+ `);
3216
+ if (data?.display_name) process.stdout.write(`display_name: ${data.display_name}
3217
+ `);
3218
+ } catch (err) {
3219
+ handleError(err);
3220
+ }
3221
+ });
3222
+ evolve.command("scopes").description("List available evolution scopes").option("--json", "output raw JSON response").action(async (opts) => {
3223
+ const client = getIMClient2();
3224
+ try {
3225
+ const res = await client.im.evolution.listScopes();
3226
+ if (opts.json) {
3227
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3228
+ return;
3229
+ }
3230
+ printResult(res);
3231
+ const data = res.data;
3232
+ const scopes = Array.isArray(data) ? data : data?.scopes ?? data?.items ?? [];
3233
+ if (scopes.length === 0) {
3234
+ process.stdout.write("No scopes found.\n");
3235
+ return;
3236
+ }
3237
+ process.stdout.write(`${scopes.length} scope(s):
3238
+ `);
3239
+ for (const s of scopes) {
3240
+ if (typeof s === "string") {
3241
+ process.stdout.write(` \u2022 ${s}
3242
+ `);
3243
+ } else {
3244
+ const name = s.name ?? s.scope ?? s.id ?? JSON.stringify(s);
3245
+ process.stdout.write(` \u2022 ${name}
3246
+ `);
3247
+ }
3248
+ }
3249
+ } catch (err) {
3250
+ handleError(err);
3251
+ }
3252
+ });
3253
+ evolve.command("browse").description("Browse published evolution genes").option("-c, --category <cat>", "filter by category").option("--search <query>", "full-text search query").option("--sort <field>", "sort field (e.g. score, created_at)").option("-n, --limit <n>", "max results to return", "20").option("--json", "output raw JSON response").action(async (opts) => {
3254
+ const client = getIMClient2();
3255
+ try {
3256
+ const limit = parseInt(opts.limit ?? "20", 10);
3257
+ const res = await client.im.evolution.browseGenes({
3258
+ category: opts.category,
3259
+ search: opts.search,
3260
+ sort: opts.sort,
3261
+ limit
3262
+ });
3263
+ if (opts.json) {
3264
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3265
+ return;
3266
+ }
3267
+ printResult(res);
3268
+ const data = res.data;
3269
+ const genes = Array.isArray(data) ? data : data?.genes ?? data?.items ?? data?.results ?? [];
3270
+ if (genes.length === 0) {
3271
+ process.stdout.write("No genes found.\n");
3272
+ return;
3273
+ }
3274
+ process.stdout.write(`${genes.length} gene(s):
3275
+ `);
3276
+ for (const g of genes) {
3277
+ const id = g.gene_id ?? g.id ?? "?";
3278
+ const title = g.title ?? g.name ?? "";
3279
+ const category = g.category ? ` [${g.category}]` : "";
3280
+ const score = g.score !== void 0 ? ` score=${g.score}` : "";
3281
+ process.stdout.write(` \u2022 ${id}${title ? ` \u2014 ${title}` : ""}${category}${score}
3282
+ `);
3283
+ }
3284
+ } catch (err) {
3285
+ handleError(err);
3286
+ }
3287
+ });
3288
+ evolve.command("import <gene-id>").description("Import a published gene into your collection").option("--json", "output raw JSON response").action(async (geneId, opts) => {
3289
+ const client = getIMClient2();
3290
+ try {
3291
+ const res = await client.im.evolution.importGene(geneId);
3292
+ if (opts.json) {
3293
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3294
+ return;
3295
+ }
3296
+ printResult(res, `Gene imported: ${geneId}`);
3297
+ } catch (err) {
3298
+ handleError(err);
3299
+ }
3300
+ });
3301
+ evolve.command("distill").description("Trigger gene distillation (consolidate learnings)").option("--dry-run", "preview distillation without applying changes").option("--json", "output raw JSON response").action(async (opts) => {
3302
+ const client = getIMClient2();
3303
+ try {
3304
+ const res = await client.im.evolution.distill(opts.dryRun);
3305
+ if (opts.json) {
3306
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3307
+ return;
3308
+ }
3309
+ printResult(res);
3310
+ const data = res.data;
3311
+ if (opts.dryRun) {
3312
+ process.stdout.write("Dry-run distillation preview:\n");
3313
+ } else {
3314
+ process.stdout.write("Distillation triggered.\n");
3315
+ }
3316
+ if (data) {
3317
+ for (const [key, val] of Object.entries(data)) {
3318
+ process.stdout.write(` ${key}: ${JSON.stringify(val)}
3319
+ `);
3320
+ }
3321
+ }
3322
+ } catch (err) {
3323
+ handleError(err);
3324
+ }
3325
+ });
3326
+ }
3327
+
3328
+ // src/commands/task.ts
3329
+ function register4(parent, getIMClient2, _getAPIClient) {
3330
+ const task = parent.command("task").description("Manage tasks in the task marketplace");
3331
+ task.command("create").description("Create a new task").requiredOption("--title <title>", "task title").option("--description <description>", "task description").option("--priority <priority>", "priority: low, normal, high, urgent").option("--capability <capability>", "required agent capability").option("--budget <budget>", "budget in credits", parseFloat).option("--json", "output raw JSON response").action(async (opts) => {
3332
+ const client = getIMClient2();
3333
+ try {
3334
+ const res = await client.im.tasks.create({
3335
+ title: opts.title,
3336
+ description: opts.description,
3337
+ priority: opts.priority,
3338
+ requiredCapability: opts.capability,
3339
+ budget: opts.budget
3340
+ });
3341
+ if (opts.json) {
3342
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3343
+ return;
3344
+ }
3345
+ if (!res.ok) {
3346
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3347
+ `);
3348
+ process.exit(1);
3349
+ }
3350
+ const t = res.data;
3351
+ process.stdout.write(`Task created successfully
3352
+
3353
+ `);
3354
+ process.stdout.write(`ID: ${t.id}
3355
+ `);
3356
+ process.stdout.write(`Title: ${t.title}
3357
+ `);
3358
+ process.stdout.write(`Status: ${t.status}
3359
+ `);
3360
+ process.stdout.write(`Priority: ${t.priority}
3361
+ `);
3362
+ if (t.description) process.stdout.write(`Description: ${t.description}
3363
+ `);
3364
+ if (t.requiredCapability) process.stdout.write(`Capability: ${t.requiredCapability}
3365
+ `);
3366
+ if (t.budget !== void 0) process.stdout.write(`Budget: ${t.budget}
3367
+ `);
3368
+ } catch (err) {
3369
+ const message = err instanceof Error ? err.message : String(err);
3370
+ process.stderr.write(`Error: ${message}
3371
+ `);
3372
+ process.exit(1);
3373
+ }
3374
+ });
3375
+ task.command("list").description("List tasks").option("--status <status>", "filter by status").option("--capability <capability>", "filter by required capability").option("-n, --limit <n>", "maximum number of tasks to return", "20").option("--json", "output raw JSON response").action(async (opts) => {
3376
+ const client = getIMClient2();
3377
+ try {
3378
+ const res = await client.im.tasks.list({
3379
+ status: opts.status,
3380
+ capability: opts.capability,
3381
+ limit: parseInt(opts.limit, 10)
3382
+ });
3383
+ if (opts.json) {
3384
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3385
+ return;
3386
+ }
3387
+ if (!res.ok) {
3388
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3389
+ `);
3390
+ process.exit(1);
3391
+ }
3392
+ const tasks = res.data;
3393
+ if (!tasks || tasks.length === 0) {
3394
+ process.stdout.write("No tasks found.\n");
3395
+ return;
3396
+ }
3397
+ const idW = 24;
3398
+ const statusW = 10;
3399
+ const priorityW = 10;
3400
+ const titleW = 40;
3401
+ const header = "ID".padEnd(idW) + "STATUS".padEnd(statusW) + "PRIORITY".padEnd(priorityW) + "TITLE";
3402
+ const sep = "-".repeat(idW + statusW + priorityW + titleW);
3403
+ process.stdout.write(header + "\n");
3404
+ process.stdout.write(sep + "\n");
3405
+ for (const t of tasks) {
3406
+ const title = t.title.length > titleW ? t.title.slice(0, titleW - 3) + "..." : t.title;
3407
+ process.stdout.write(
3408
+ String(t.id).padEnd(idW) + String(t.status).padEnd(statusW) + String(t.priority).padEnd(priorityW) + title + "\n"
3409
+ );
3410
+ }
3411
+ process.stdout.write(`
3412
+ ${tasks.length} task(s) listed.
3413
+ `);
3414
+ } catch (err) {
3415
+ const message = err instanceof Error ? err.message : String(err);
3416
+ process.stderr.write(`Error: ${message}
3417
+ `);
3418
+ process.exit(1);
3419
+ }
3420
+ });
3421
+ task.command("get <task-id>").description("Get task details and logs").option("--json", "output raw JSON response").action(async (taskId, opts) => {
3422
+ const client = getIMClient2();
3423
+ try {
3424
+ const res = await client.im.tasks.get(taskId);
3425
+ if (opts.json) {
3426
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3427
+ return;
3428
+ }
3429
+ if (!res.ok) {
3430
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3431
+ `);
3432
+ process.exit(1);
3433
+ }
3434
+ const t = res.data;
3435
+ process.stdout.write(`ID: ${t.id}
3436
+ `);
3437
+ process.stdout.write(`Title: ${t.title}
3438
+ `);
3439
+ process.stdout.write(`Status: ${t.status}
3440
+ `);
3441
+ process.stdout.write(`Priority: ${t.priority}
3442
+ `);
3443
+ if (t.description) process.stdout.write(`Description: ${t.description}
3444
+ `);
3445
+ if (t.requiredCapability) process.stdout.write(`Capability: ${t.requiredCapability}
3446
+ `);
3447
+ if (t.budget !== void 0) process.stdout.write(`Budget: ${t.budget}
3448
+ `);
3449
+ if (t.creatorId) process.stdout.write(`Creator: ${t.creatorId}
3450
+ `);
3451
+ if (t.assigneeId) process.stdout.write(`Assignee: ${t.assigneeId}
3452
+ `);
3453
+ if (t.createdAt) process.stdout.write(`Created: ${t.createdAt}
3454
+ `);
3455
+ if (t.updatedAt) process.stdout.write(`Updated: ${t.updatedAt}
3456
+ `);
3457
+ if (t.result) process.stdout.write(`Result: ${t.result}
3458
+ `);
3459
+ if (t.error) process.stdout.write(`Error: ${t.error}
3460
+ `);
3461
+ const logs = t.logs ?? t.taskLogs ?? [];
3462
+ if (logs.length > 0) {
3463
+ process.stdout.write(`
3464
+ Logs (${logs.length}):
3465
+ `);
3466
+ for (const log of logs) {
3467
+ const ts = log.createdAt ?? log.timestamp ?? "";
3468
+ const msg = log.message ?? log.content ?? JSON.stringify(log);
3469
+ process.stdout.write(` [${ts}] ${msg}
3470
+ `);
3471
+ }
3472
+ }
3473
+ } catch (err) {
3474
+ const message = err instanceof Error ? err.message : String(err);
3475
+ process.stderr.write(`Error: ${message}
3476
+ `);
3477
+ process.exit(1);
3478
+ }
3479
+ });
3480
+ task.command("claim <task-id>").description("Claim a pending task").option("--json", "output raw JSON response").action(async (taskId, opts) => {
3481
+ const client = getIMClient2();
3482
+ try {
3483
+ const res = await client.im.tasks.claim(taskId);
3484
+ if (opts.json) {
3485
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3486
+ return;
3487
+ }
3488
+ if (!res.ok) {
3489
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3490
+ `);
3491
+ process.exit(1);
3492
+ }
3493
+ const t = res.data;
3494
+ process.stdout.write(`Task claimed successfully
3495
+
3496
+ `);
3497
+ process.stdout.write(`ID: ${t.id}
3498
+ `);
3499
+ process.stdout.write(`Title: ${t.title}
3500
+ `);
3501
+ process.stdout.write(`Status: ${t.status}
3502
+ `);
3503
+ process.stdout.write(`Priority: ${t.priority}
3504
+ `);
3505
+ } catch (err) {
3506
+ const message = err instanceof Error ? err.message : String(err);
3507
+ process.stderr.write(`Error: ${message}
3508
+ `);
3509
+ process.exit(1);
3510
+ }
3511
+ });
3512
+ task.command("update <task-id>").description("Update a task").option("--title <title>", "new title").option("--description <description>", "new description").option("--priority <priority>", "new priority: low, normal, high, urgent").option("--json", "output raw JSON response").action(async (taskId, opts) => {
3513
+ const client = getIMClient2();
3514
+ try {
3515
+ const res = await client.im.tasks.update(taskId, {
3516
+ title: opts.title,
3517
+ description: opts.description,
3518
+ priority: opts.priority
3519
+ });
3520
+ if (opts.json) {
3521
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3522
+ return;
3523
+ }
3524
+ if (!res.ok) {
3525
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3526
+ `);
3527
+ process.exit(1);
3528
+ }
3529
+ const t = res.data;
3530
+ process.stdout.write(`Task updated successfully
3531
+
3532
+ `);
3533
+ process.stdout.write(`ID: ${t.id}
3534
+ `);
3535
+ process.stdout.write(`Title: ${t.title}
3536
+ `);
3537
+ process.stdout.write(`Status: ${t.status}
3538
+ `);
3539
+ process.stdout.write(`Priority: ${t.priority}
3540
+ `);
3541
+ } catch (err) {
3542
+ const message = err instanceof Error ? err.message : String(err);
3543
+ process.stderr.write(`Error: ${message}
3544
+ `);
3545
+ process.exit(1);
3546
+ }
3547
+ });
3548
+ task.command("complete <task-id>").description("Mark a task as complete").option("--result <result>", "result or output of the task").option("--json", "output raw JSON response").action(async (taskId, opts) => {
3549
+ const client = getIMClient2();
3550
+ try {
3551
+ const res = await client.im.tasks.complete(taskId, {
3552
+ result: opts.result
3553
+ });
3554
+ if (opts.json) {
3555
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3556
+ return;
3557
+ }
3558
+ if (!res.ok) {
3559
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3560
+ `);
3561
+ process.exit(1);
3562
+ }
3563
+ const t = res.data;
3564
+ process.stdout.write(`Task completed successfully
3565
+
3566
+ `);
3567
+ process.stdout.write(`ID: ${t.id}
3568
+ `);
3569
+ process.stdout.write(`Title: ${t.title}
3570
+ `);
3571
+ process.stdout.write(`Status: ${t.status}
3572
+ `);
3573
+ if (t.result) process.stdout.write(`Result: ${t.result}
3574
+ `);
3575
+ } catch (err) {
3576
+ const message = err instanceof Error ? err.message : String(err);
3577
+ process.stderr.write(`Error: ${message}
3578
+ `);
3579
+ process.exit(1);
3580
+ }
3581
+ });
3582
+ task.command("fail <task-id>").description("Mark a task as failed").requiredOption("--error <error>", "error message describing why the task failed").option("--json", "output raw JSON response").action(async (taskId, opts) => {
3583
+ const client = getIMClient2();
3584
+ try {
3585
+ const res = await client.im.tasks.fail(taskId, opts.error);
3586
+ if (opts.json) {
3587
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3588
+ return;
3589
+ }
3590
+ if (!res.ok) {
3591
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3592
+ `);
3593
+ process.exit(1);
3594
+ }
3595
+ const t = res.data;
3596
+ process.stdout.write(`Task marked as failed
3597
+
3598
+ `);
3599
+ process.stdout.write(`ID: ${t.id}
3600
+ `);
3601
+ process.stdout.write(`Title: ${t.title}
3602
+ `);
3603
+ process.stdout.write(`Status: ${t.status}
3604
+ `);
3605
+ if (t.error) process.stdout.write(`Error: ${t.error}
3606
+ `);
3607
+ } catch (err) {
3608
+ const message = err instanceof Error ? err.message : String(err);
3609
+ process.stderr.write(`Error: ${message}
3610
+ `);
3611
+ process.exit(1);
3612
+ }
3613
+ });
3614
+ }
3615
+
3616
+ // src/commands/memory.ts
3617
+ function register5(parent, getIMClient2, _getAPIClient) {
3618
+ const mem = parent.command("memory").description("Agent memory file management");
3619
+ mem.command("write").description("Write a memory file").requiredOption("-s, --scope <scope>", "memory scope").requiredOption("-p, --path <path>", "file path within scope").requiredOption("-c, --content <content>", "file content").option("--json", "output raw JSON response").action(async (opts) => {
3620
+ const client = getIMClient2();
3621
+ try {
3622
+ const res = await client.im.memory.createFile({
3623
+ scope: opts.scope,
3624
+ path: opts.path,
3625
+ content: opts.content
3626
+ });
3627
+ if (opts.json) {
3628
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3629
+ return;
3630
+ }
3631
+ if (!res.ok) {
3632
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3633
+ `);
3634
+ process.exit(1);
3635
+ }
3636
+ const file = res.data;
3637
+ process.stdout.write(`Memory file created
3638
+ `);
3639
+ process.stdout.write(` ID: ${file.id}
3640
+ `);
3641
+ process.stdout.write(` Scope: ${file.scope}
3642
+ `);
3643
+ process.stdout.write(` Path: ${file.path}
3644
+ `);
3645
+ } catch (err) {
3646
+ const message = err instanceof Error ? err.message : String(err);
3647
+ process.stderr.write(`Error: ${message}
3648
+ `);
3649
+ process.exit(1);
3650
+ }
3651
+ });
3652
+ mem.command("read [file-id]").description("Read a memory file by ID, or filter by scope/path").option("-s, --scope <scope>", "filter by scope (used when no file-id given)").option("-p, --path <path>", "filter by path (used when no file-id given)").option("--json", "output raw JSON response").action(async (fileId, opts) => {
3653
+ const client = getIMClient2();
3654
+ try {
3655
+ if (fileId) {
3656
+ const res = await client.im.memory.getFile(fileId);
3657
+ if (opts.json) {
3658
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3659
+ return;
3660
+ }
3661
+ if (!res.ok) {
3662
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3663
+ `);
3664
+ process.exit(1);
3665
+ }
3666
+ const file = res.data;
3667
+ process.stdout.write(`ID: ${file.id}
3668
+ `);
3669
+ process.stdout.write(`Scope: ${file.scope}
3670
+ `);
3671
+ process.stdout.write(`Path: ${file.path}
3672
+ `);
3673
+ process.stdout.write(`
3674
+ ${file.content ?? ""}
3675
+ `);
3676
+ return;
3677
+ }
3678
+ const listRes = await client.im.memory.listFiles({
3679
+ scope: opts.scope,
3680
+ path: opts.path
3681
+ });
3682
+ if (opts.json) {
3683
+ if (listRes.ok && Array.isArray(listRes.data) && listRes.data.length === 1) {
3684
+ const detailRes = await client.im.memory.getFile(listRes.data[0].id);
3685
+ process.stdout.write(JSON.stringify(detailRes, null, 2) + "\n");
3686
+ } else {
3687
+ process.stdout.write(JSON.stringify(listRes, null, 2) + "\n");
3688
+ }
3689
+ return;
3690
+ }
3691
+ if (!listRes.ok) {
3692
+ process.stderr.write(`Error: ${listRes.error?.message || "Unknown error"}
3693
+ `);
3694
+ process.exit(1);
3695
+ }
3696
+ const files = listRes.data;
3697
+ if (files.length === 0) {
3698
+ process.stdout.write("No memory files found.\n");
3699
+ return;
3700
+ }
3701
+ if (files.length === 1) {
3702
+ const detailRes = await client.im.memory.getFile(files[0].id);
3703
+ if (!detailRes.ok) {
3704
+ process.stderr.write(`Error: ${detailRes.error?.message || "Unknown error"}
3705
+ `);
3706
+ process.exit(1);
3707
+ }
3708
+ const file = detailRes.data;
3709
+ process.stdout.write(`ID: ${file.id}
3710
+ `);
3711
+ process.stdout.write(`Scope: ${file.scope}
3712
+ `);
3713
+ process.stdout.write(`Path: ${file.path}
3714
+ `);
3715
+ process.stdout.write(`
3716
+ ${file.content ?? ""}
3717
+ `);
3718
+ return;
3719
+ }
3720
+ printFileTable(files);
3721
+ } catch (err) {
3722
+ const message = err instanceof Error ? err.message : String(err);
3723
+ process.stderr.write(`Error: ${message}
3724
+ `);
3725
+ process.exit(1);
3726
+ }
3727
+ });
3728
+ mem.command("list").description("List memory files").option("-s, --scope <scope>", "filter by scope").option("--json", "output raw JSON response").action(async (opts) => {
3729
+ const client = getIMClient2();
3730
+ try {
3731
+ const res = await client.im.memory.listFiles({ scope: opts.scope });
3732
+ if (opts.json) {
3733
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3734
+ return;
3735
+ }
3736
+ if (!res.ok) {
3737
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3738
+ `);
3739
+ process.exit(1);
3740
+ }
3741
+ const files = res.data;
3742
+ if (files.length === 0) {
3743
+ process.stdout.write("No memory files found.\n");
3744
+ return;
3745
+ }
3746
+ printFileTable(files);
3747
+ } catch (err) {
3748
+ const message = err instanceof Error ? err.message : String(err);
3749
+ process.stderr.write(`Error: ${message}
3750
+ `);
3751
+ process.exit(1);
3752
+ }
3753
+ });
3754
+ mem.command("delete <file-id>").description("Delete a memory file by ID").option("--json", "output raw JSON response").action(async (fileId, opts) => {
3755
+ const client = getIMClient2();
3756
+ try {
3757
+ const res = await client.im.memory.deleteFile(fileId);
3758
+ if (opts.json) {
3759
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3760
+ return;
3761
+ }
3762
+ if (!res.ok) {
3763
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3764
+ `);
3765
+ process.exit(1);
3766
+ }
3767
+ process.stdout.write(`Deleted memory file: ${fileId}
3768
+ `);
3769
+ } catch (err) {
3770
+ const message = err instanceof Error ? err.message : String(err);
3771
+ process.stderr.write(`Error: ${message}
3772
+ `);
3773
+ process.exit(1);
3774
+ }
3775
+ });
3776
+ mem.command("compact <conversation-id>").description("Create a compaction summary for a conversation").option("--json", "output raw JSON response").action(async (conversationId, opts) => {
3777
+ const client = getIMClient2();
3778
+ try {
3779
+ const res = await client.im.memory.compact({ conversationId });
3780
+ if (opts.json) {
3781
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3782
+ return;
3783
+ }
3784
+ if (!res.ok) {
3785
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3786
+ `);
3787
+ process.exit(1);
3788
+ }
3789
+ const summary = res.data;
3790
+ process.stdout.write(`Compaction complete
3791
+ `);
3792
+ if (summary?.id) {
3793
+ process.stdout.write(` Summary ID: ${summary.id}
3794
+ `);
3795
+ }
3796
+ if (summary?.conversationId) {
3797
+ process.stdout.write(` Conversation ID: ${summary.conversationId}
3798
+ `);
3799
+ }
3800
+ } catch (err) {
3801
+ const message = err instanceof Error ? err.message : String(err);
3802
+ process.stderr.write(`Error: ${message}
3803
+ `);
3804
+ process.exit(1);
3805
+ }
3806
+ });
3807
+ mem.command("load").description("Load session memory context").option("-s, --scope <scope>", "scope to load").option("--json", "output raw JSON response").action(async (opts) => {
3808
+ const client = getIMClient2();
3809
+ try {
3810
+ const res = await client.im.memory.load(opts.scope);
3811
+ if (opts.json) {
3812
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3813
+ return;
3814
+ }
3815
+ if (!res.ok) {
3816
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
3817
+ `);
3818
+ process.exit(1);
3819
+ }
3820
+ const context = res.data;
3821
+ if (!context || typeof context === "object" && Object.keys(context).length === 0) {
3822
+ process.stdout.write("No memory context available.\n");
3823
+ return;
3824
+ }
3825
+ process.stdout.write("Memory context loaded:\n\n");
3826
+ if (typeof context === "string") {
3827
+ process.stdout.write(context + "\n");
3828
+ } else {
3829
+ process.stdout.write(JSON.stringify(context, null, 2) + "\n");
3830
+ }
3831
+ } catch (err) {
3832
+ const message = err instanceof Error ? err.message : String(err);
3833
+ process.stderr.write(`Error: ${message}
3834
+ `);
3835
+ process.exit(1);
3836
+ }
3837
+ });
3838
+ }
3839
+ function printFileTable(files) {
3840
+ const idLen = Math.max(2, ...files.map((f) => f.id.length));
3841
+ const scopeLen = Math.max(5, ...files.map((f) => f.scope.length));
3842
+ const pathLen = Math.max(4, ...files.map((f) => f.path.length));
3843
+ const row = (id, scope, path2) => `${id.padEnd(idLen)} ${scope.padEnd(scopeLen)} ${path2.padEnd(pathLen)}`;
3844
+ process.stdout.write(row("ID", "SCOPE", "PATH") + "\n");
3845
+ process.stdout.write(`${"-".repeat(idLen)} ${"-".repeat(scopeLen)} ${"-".repeat(pathLen)}
3846
+ `);
3847
+ for (const f of files) {
3848
+ process.stdout.write(row(f.id, f.scope, f.path) + "\n");
3849
+ }
3850
+ }
3851
+
3852
+ // src/commands/skill.ts
3853
+ function padEnd(str, len) {
3854
+ if (str.length >= len) return str.slice(0, len);
3855
+ return str + " ".repeat(len - str.length);
3856
+ }
3857
+ function formatTable(rows) {
3858
+ if (rows.length === 0) return "";
3859
+ const cols = rows[0].length;
3860
+ const widths = Array(cols).fill(0);
3861
+ for (const row of rows) {
3862
+ for (let i = 0; i < cols; i++) {
3863
+ widths[i] = Math.max(widths[i], (row[i] ?? "").length);
3864
+ }
3865
+ }
3866
+ return rows.map((row) => row.map((cell, i) => padEnd(cell ?? "", widths[i])).join(" ")).join("\n");
3867
+ }
3868
+ function register6(parent, getIMClient2, _getAPIClient) {
3869
+ const skill = parent.command("skill").description("Browse, install, and manage skills");
3870
+ skill.command("find [query]").description("Search the skill marketplace").option("-c, --category <category>", "filter by category").option("-n, --limit <n>", "max results to return", "20").option("--json", "output raw JSON response").action(async (query, opts) => {
3871
+ const client = getIMClient2();
3872
+ try {
3873
+ const limit = parseInt(opts.limit, 10);
3874
+ const res = await client.im.evolution.searchSkills({
3875
+ query,
3876
+ category: opts.category,
3877
+ limit
3878
+ });
3879
+ if (opts.json) {
3880
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3881
+ return;
3882
+ }
3883
+ const skills = Array.isArray(res) ? res : res?.skills ?? [];
3884
+ if (skills.length === 0) {
3885
+ process.stdout.write("No skills found.\n");
3886
+ return;
3887
+ }
3888
+ const header = ["Slug", "Name", "Installs", "Category"];
3889
+ const rows = skills.map((s) => {
3890
+ const sk = s;
3891
+ return [
3892
+ String(sk.slug ?? sk.id ?? ""),
3893
+ String(sk.name ?? ""),
3894
+ String(sk.installCount ?? sk.installs ?? "0"),
3895
+ String(sk.category ?? "")
3896
+ ];
3897
+ });
3898
+ process.stdout.write(formatTable([header, ...rows]) + "\n");
3899
+ } catch (err) {
3900
+ const message = err instanceof Error ? err.message : String(err);
3901
+ process.stderr.write(`Error: ${message}
3902
+ `);
3903
+ process.exit(1);
3904
+ }
3905
+ });
3906
+ skill.command("install <slug>").description("Install a skill").option("--platform <platform>", "target platform: claude-code, openclaw, opencode, or all", "all").option("--project <path>", "project directory for local file writes").option("--no-local", "cloud-only install, do not write local files").option("--json", "output raw JSON response").action(async (slug, opts) => {
3907
+ const client = getIMClient2();
3908
+ try {
3909
+ let res;
3910
+ if (!opts.local) {
3911
+ res = await client.im.evolution.installSkill(slug);
3912
+ } else {
3913
+ const platforms = opts.platform === "all" ? void 0 : [opts.platform];
3914
+ res = await client.im.evolution.installSkillLocal(slug, {
3915
+ platforms,
3916
+ project: opts.project
3917
+ });
3918
+ }
3919
+ if (opts.json) {
3920
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3921
+ return;
3922
+ }
3923
+ const result = res;
3924
+ if (result?.ok === false) {
3925
+ process.stderr.write(`Install failed.
3926
+ `);
3927
+ process.exit(1);
3928
+ }
3929
+ const skillData = result?.data?.skill ?? {};
3930
+ const name = String(skillData.name ?? slug);
3931
+ process.stdout.write(`Installed: ${name}
3932
+ `);
3933
+ const localPaths = result?.data?.localPaths ?? [];
3934
+ if (localPaths.length > 0) {
3935
+ process.stdout.write("Local files written:\n");
3936
+ for (const p of localPaths) {
3937
+ process.stdout.write(` ${p}
3938
+ `);
3939
+ }
3940
+ } else if (!opts.local) {
3941
+ process.stdout.write("Cloud-only install complete (no local files written).\n");
3942
+ }
3943
+ } catch (err) {
3944
+ const message = err instanceof Error ? err.message : String(err);
3945
+ process.stderr.write(`Error: ${message}
3946
+ `);
3947
+ process.exit(1);
3948
+ }
3949
+ });
3950
+ skill.command("list").description("List installed skills").option("--json", "output raw JSON response").action(async (opts) => {
3951
+ const client = getIMClient2();
3952
+ try {
3953
+ const res = await client.im.evolution.installedSkills();
3954
+ if (opts.json) {
3955
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3956
+ return;
3957
+ }
3958
+ const records = Array.isArray(res) ? res : res?.skills ?? [];
3959
+ if (records.length === 0) {
3960
+ process.stdout.write("No skills installed.\n");
3961
+ return;
3962
+ }
3963
+ const header = ["Slug", "Name", "Installs", "Category"];
3964
+ const rows = records.map((r) => {
3965
+ const rec = r;
3966
+ const sk = rec.skill ?? rec;
3967
+ return [
3968
+ String(sk.slug ?? sk.id ?? ""),
3969
+ String(sk.name ?? ""),
3970
+ String(sk.installCount ?? sk.installs ?? "0"),
3971
+ String(sk.category ?? "")
3972
+ ];
3973
+ });
3974
+ process.stdout.write(formatTable([header, ...rows]) + "\n");
3975
+ } catch (err) {
3976
+ const message = err instanceof Error ? err.message : String(err);
3977
+ process.stderr.write(`Error: ${message}
3978
+ `);
3979
+ process.exit(1);
3980
+ }
3981
+ });
3982
+ skill.command("show <slug>").description("Show skill content and details").option("--json", "output raw JSON response").action(async (slug, opts) => {
3983
+ const client = getIMClient2();
3984
+ try {
3985
+ const res = await client.im.evolution.getSkillContent(slug);
3986
+ if (opts.json) {
3987
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
3988
+ return;
3989
+ }
3990
+ const result = res;
3991
+ if (result?.packageUrl) {
3992
+ process.stdout.write(`Package URL: ${result.packageUrl}
3993
+ `);
3994
+ }
3995
+ if (result?.checksum) {
3996
+ process.stdout.write(`Checksum: ${result.checksum}
3997
+ `);
3998
+ }
3999
+ if (result?.files && result.files.length > 0) {
4000
+ process.stdout.write(`Files:
4001
+ `);
4002
+ for (const f of result.files) {
4003
+ process.stdout.write(` ${f}
4004
+ `);
4005
+ }
4006
+ }
4007
+ if (result?.content) {
4008
+ process.stdout.write(`
4009
+ ${result.content}
4010
+ `);
4011
+ }
4012
+ } catch (err) {
4013
+ const message = err instanceof Error ? err.message : String(err);
4014
+ process.stderr.write(`Error: ${message}
4015
+ `);
4016
+ process.exit(1);
4017
+ }
4018
+ });
4019
+ skill.command("uninstall <slug>").description("Uninstall a skill").option("--no-local", "cloud-only uninstall, do not remove local files").option("--json", "output raw JSON response").action(async (slug, opts) => {
4020
+ const client = getIMClient2();
4021
+ try {
4022
+ let res;
4023
+ if (!opts.local) {
4024
+ res = await client.im.evolution.uninstallSkill(slug);
4025
+ } else {
4026
+ res = await client.im.evolution.uninstallSkillLocal(slug);
4027
+ }
4028
+ if (opts.json) {
4029
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
4030
+ return;
4031
+ }
4032
+ const result = res;
4033
+ if (result?.ok === false) {
4034
+ process.stderr.write(`Uninstall failed.
4035
+ `);
4036
+ process.exit(1);
4037
+ }
4038
+ process.stdout.write(`Uninstalled: ${slug}
4039
+ `);
4040
+ const removedPaths = result?.data?.removedPaths ?? [];
4041
+ if (removedPaths.length > 0) {
4042
+ process.stdout.write("Local files removed:\n");
4043
+ for (const p of removedPaths) {
4044
+ process.stdout.write(` ${p}
4045
+ `);
4046
+ }
4047
+ } else if (!opts.local) {
4048
+ process.stdout.write("Cloud-only uninstall complete (no local files removed).\n");
4049
+ }
4050
+ } catch (err) {
4051
+ const message = err instanceof Error ? err.message : String(err);
4052
+ process.stderr.write(`Error: ${message}
4053
+ `);
4054
+ process.exit(1);
4055
+ }
4056
+ });
4057
+ skill.command("sync").description("Re-sync all installed skills to local filesystem").option("--platform <platform>", "target platform: claude-code, openclaw, opencode, or all", "all").option("--json", "output raw JSON response").action(async (opts) => {
4058
+ const client = getIMClient2();
4059
+ try {
4060
+ const platforms = opts.platform === "all" ? void 0 : [opts.platform];
4061
+ const res = await client.im.evolution.syncSkillsLocal({ platforms });
4062
+ if (opts.json) {
4063
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
4064
+ return;
4065
+ }
4066
+ const result = res;
4067
+ const synced = result?.synced ?? 0;
4068
+ const failed = result?.failed ?? 0;
4069
+ process.stdout.write(`Synced: ${synced} skill(s)`);
4070
+ if (failed > 0) {
4071
+ process.stdout.write(`, failed: ${failed}`);
4072
+ }
4073
+ process.stdout.write("\n");
4074
+ const paths = result?.paths ?? [];
4075
+ if (paths.length > 0) {
4076
+ process.stdout.write("Files written:\n");
4077
+ for (const p of paths) {
4078
+ process.stdout.write(` ${p}
4079
+ `);
4080
+ }
4081
+ }
4082
+ } catch (err) {
4083
+ const message = err instanceof Error ? err.message : String(err);
4084
+ process.stderr.write(`Error: ${message}
4085
+ `);
4086
+ process.exit(1);
4087
+ }
4088
+ });
4089
+ }
4090
+
4091
+ // src/commands/files.ts
4092
+ function register7(parent, getIMClient2, _getAPIClient) {
4093
+ const file = parent.command("file").description("File upload, transfer, quota, and type management");
4094
+ file.command("upload <path>").description("Upload a file and get its upload ID and CDN URL").option("--mime <type>", "Override MIME type (e.g. image/png)").option("--json", "Output raw JSON response").action(async (filePath, opts) => {
4095
+ const client = getIMClient2();
4096
+ try {
4097
+ const uploadOpts = {};
4098
+ if (opts.mime) uploadOpts.mimeType = opts.mime;
4099
+ const res = await client.im.files.upload(filePath, Object.keys(uploadOpts).length ? uploadOpts : void 0);
4100
+ if (opts.json) {
4101
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
4102
+ return;
4103
+ }
4104
+ process.stdout.write(`Uploaded: ${res.fileName}
4105
+ `);
4106
+ process.stdout.write(`Upload ID: ${res.uploadId}
4107
+ `);
4108
+ process.stdout.write(`CDN URL: ${res.cdnUrl}
4109
+ `);
4110
+ process.stdout.write(`Size: ${res.fileSize} bytes
4111
+ `);
4112
+ process.stdout.write(`MIME: ${res.mimeType}
4113
+ `);
4114
+ } catch (err) {
4115
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4116
+ `);
4117
+ process.exit(1);
4118
+ }
4119
+ });
4120
+ file.command("send <conversation-id> <path>").description("Upload a file and send it as a message in a conversation").option("-c, --content <text>", "Optional text caption to accompany the file").option("--mime <type>", "Override MIME type").option("--json", "Output raw JSON response").action(async (conversationId, filePath, opts) => {
4121
+ const client = getIMClient2();
4122
+ try {
4123
+ const sendOpts = {};
4124
+ if (opts.content) sendOpts.content = opts.content;
4125
+ if (opts.mime) sendOpts.mimeType = opts.mime;
4126
+ const res = await client.im.files.sendFile(
4127
+ conversationId,
4128
+ filePath,
4129
+ Object.keys(sendOpts).length ? sendOpts : void 0
4130
+ );
4131
+ if (opts.json) {
4132
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
4133
+ return;
4134
+ }
4135
+ process.stdout.write(`File sent (messageId: ${res.message?.id || res.message?.messageId || "-"})
4136
+ `);
4137
+ process.stdout.write(`Upload ID: ${res.upload?.uploadId || "-"}
4138
+ `);
4139
+ process.stdout.write(`CDN URL: ${res.upload?.cdnUrl || "-"}
4140
+ `);
4141
+ } catch (err) {
4142
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4143
+ `);
4144
+ process.exit(1);
4145
+ }
4146
+ });
4147
+ file.command("quota").description("Show file storage quota and usage").option("--json", "Output raw JSON response").action(async (opts) => {
4148
+ const client = getIMClient2();
4149
+ const res = await client.im.files.quota();
4150
+ if (!res.ok) {
4151
+ process.stderr.write(`Error: ${JSON.stringify(res)}
4152
+ `);
4153
+ process.exit(1);
4154
+ }
4155
+ if (opts.json) {
4156
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4157
+ return;
4158
+ }
4159
+ const d = res.data;
4160
+ process.stdout.write(`Tier: ${d?.tier || "-"}
4161
+ `);
4162
+ process.stdout.write(`Used: ${d?.used ?? "-"} bytes
4163
+ `);
4164
+ process.stdout.write(`Limit: ${d?.limit ?? "-"} bytes
4165
+ `);
4166
+ process.stdout.write(`File Count: ${d?.fileCount ?? "-"}
4167
+ `);
4168
+ });
4169
+ file.command("delete <upload-id>").description("Delete an uploaded file by its upload ID").action(async (uploadId) => {
4170
+ const client = getIMClient2();
4171
+ const res = await client.im.files.delete(uploadId);
4172
+ if (!res.ok) {
4173
+ process.stderr.write(`Error: ${JSON.stringify(res)}
4174
+ `);
4175
+ process.exit(1);
4176
+ }
4177
+ process.stdout.write(`File ${uploadId} deleted.
4178
+ `);
4179
+ });
4180
+ file.command("types").description("List allowed MIME types for file uploads").option("--json", "Output raw JSON response").action(async (opts) => {
4181
+ const client = getIMClient2();
4182
+ const res = await client.im.files.types();
4183
+ if (!res.ok) {
4184
+ process.stderr.write(`Error: ${JSON.stringify(res)}
4185
+ `);
4186
+ process.exit(1);
4187
+ }
4188
+ if (opts.json) {
4189
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4190
+ return;
4191
+ }
4192
+ const types = res.data?.allowedMimeTypes || [];
4193
+ if (types.length === 0) {
4194
+ process.stdout.write("No allowed MIME types returned.\n");
4195
+ return;
4196
+ }
4197
+ process.stdout.write("Allowed MIME types:\n");
4198
+ for (const t of types) {
4199
+ process.stdout.write(` ${t}
4200
+ `);
4201
+ }
4202
+ });
4203
+ }
4204
+
4205
+ // src/commands/workspace.ts
4206
+ function register8(parent, getIMClient2, _getAPIClient) {
4207
+ const workspace = parent.command("workspace").description("Workspace management \u2014 init, groups, and agent assignment");
4208
+ workspace.command("init <name>").description("Initialize a workspace with a user and agent").requiredOption("--user-id <id>", "User ID").requiredOption("--user-name <name>", "User display name").requiredOption("--agent-id <id>", "Agent ID").requiredOption("--agent-name <name>", "Agent display name").option("--agent-type <type>", "Agent type", "assistant").option("--agent-capabilities <caps>", "Comma-separated list of agent capabilities").option("--json", "Output raw JSON response").action(async (name, opts) => {
4209
+ const client = getIMClient2();
4210
+ try {
4211
+ const capabilities = opts.agentCapabilities ? opts.agentCapabilities.split(",").map((s) => s.trim()) : void 0;
4212
+ const res = await client.im.workspace.init({
4213
+ name,
4214
+ userId: opts.userId,
4215
+ userName: opts.userName,
4216
+ agentId: opts.agentId,
4217
+ agentName: opts.agentName,
4218
+ agentType: opts.agentType,
4219
+ ...capabilities !== void 0 && { agentCapabilities: capabilities }
4220
+ });
4221
+ if (!res.ok) {
4222
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4223
+ `);
4224
+ process.exit(1);
4225
+ }
4226
+ if (opts.json) {
4227
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4228
+ return;
4229
+ }
4230
+ process.stdout.write(`Workspace initialized (workspaceId: ${res.data?.workspaceId})
4231
+ `);
4232
+ } catch (err) {
4233
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4234
+ `);
4235
+ process.exit(1);
4236
+ }
4237
+ });
4238
+ workspace.command("init-group <name>").description("Initialize a group workspace with a set of members").requiredOption("--members <json>", "JSON array of member objects").option("--json", "Output raw JSON response").action(async (name, opts) => {
4239
+ const client = getIMClient2();
4240
+ try {
4241
+ let members;
4242
+ try {
4243
+ members = JSON.parse(opts.members);
4244
+ } catch {
4245
+ process.stderr.write("Error: --members must be a valid JSON array\n");
4246
+ process.exit(1);
4247
+ }
4248
+ const res = await client.im.workspace.initGroup({ name, members });
4249
+ if (!res.ok) {
4250
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4251
+ `);
4252
+ process.exit(1);
4253
+ }
4254
+ if (opts.json) {
4255
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4256
+ return;
4257
+ }
4258
+ process.stdout.write(`Group workspace initialized (workspaceId: ${res.data?.workspaceId})
4259
+ `);
4260
+ } catch (err) {
4261
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4262
+ `);
4263
+ process.exit(1);
4264
+ }
4265
+ });
4266
+ workspace.command("add-agent <workspace-id> <agent-id>").description("Add an agent to a workspace").option("--json", "Output raw JSON response").action(async (workspaceId, agentId, opts) => {
4267
+ const client = getIMClient2();
4268
+ try {
4269
+ const res = await client.im.workspace.addAgent(workspaceId, agentId);
4270
+ if (!res.ok) {
4271
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4272
+ `);
4273
+ process.exit(1);
4274
+ }
4275
+ if (opts.json) {
4276
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4277
+ return;
4278
+ }
4279
+ process.stdout.write(`Agent ${agentId} added to workspace ${workspaceId}.
4280
+ `);
4281
+ } catch (err) {
4282
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4283
+ `);
4284
+ process.exit(1);
4285
+ }
4286
+ });
4287
+ workspace.command("agents <workspace-id>").description("List agents in a workspace").option("--json", "Output raw JSON response").action(async (workspaceId, opts) => {
4288
+ const client = getIMClient2();
4289
+ try {
4290
+ const res = await client.im.workspace.listAgents(workspaceId);
4291
+ if (!res.ok) {
4292
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4293
+ `);
4294
+ process.exit(1);
4295
+ }
4296
+ const agents = res.data || [];
4297
+ if (opts.json) {
4298
+ process.stdout.write(JSON.stringify(agents, null, 2) + "\n");
4299
+ return;
4300
+ }
4301
+ if (agents.length === 0) {
4302
+ process.stdout.write("No agents in this workspace.\n");
4303
+ return;
4304
+ }
4305
+ process.stdout.write("Agent ID".padEnd(36) + "Type".padEnd(14) + "Name\n");
4306
+ for (const a of agents) {
4307
+ process.stdout.write(
4308
+ `${(a.agentId || a.id || "").padEnd(36)}${(a.agentType || "").padEnd(14)}${a.name || a.displayName || ""}
4309
+ `
4310
+ );
4311
+ }
4312
+ } catch (err) {
4313
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4314
+ `);
4315
+ process.exit(1);
4316
+ }
4317
+ });
4318
+ }
4319
+
4320
+ // src/commands/security.ts
4321
+ function register9(parent, getIMClient2, _getAPIClient) {
4322
+ const security = parent.command("security").description("Per-conversation encryption and key management");
4323
+ security.command("get <conversation-id>").description("Get security settings for a conversation").option("--json", "Output raw JSON response").action(async (convId, opts) => {
4324
+ const client = getIMClient2();
4325
+ try {
4326
+ const res = await client.im.security.getConversationSecurity(convId);
4327
+ if (!res.ok) {
4328
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4329
+ `);
4330
+ process.exit(1);
4331
+ }
4332
+ if (opts.json) {
4333
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4334
+ return;
4335
+ }
4336
+ const d = res.data;
4337
+ process.stdout.write(`Encryption Mode: ${d?.encryptionMode ?? "-"}
4338
+ `);
4339
+ process.stdout.write(`Signing Policy: ${d?.signingPolicy ?? "-"}
4340
+ `);
4341
+ } catch (err) {
4342
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4343
+ `);
4344
+ process.exit(1);
4345
+ }
4346
+ });
4347
+ security.command("set <conversation-id>").description("Set encryption mode for a conversation").requiredOption("--mode <mode>", "Encryption mode: none, available, or required").option("--json", "Output raw JSON response").action(async (convId, opts) => {
4348
+ const client = getIMClient2();
4349
+ try {
4350
+ const res = await client.im.security.setConversationSecurity(convId, {
4351
+ encryptionMode: opts.mode
4352
+ });
4353
+ if (!res.ok) {
4354
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4355
+ `);
4356
+ process.exit(1);
4357
+ }
4358
+ if (opts.json) {
4359
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4360
+ return;
4361
+ }
4362
+ process.stdout.write(`Encryption mode set to: ${opts.mode}
4363
+ `);
4364
+ } catch (err) {
4365
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4366
+ `);
4367
+ process.exit(1);
4368
+ }
4369
+ });
4370
+ security.command("upload-key <conversation-id>").description("Upload an ECDH public key for a conversation").requiredOption("--key <base64>", "Base64-encoded public key").option("--algorithm <alg>", "Key algorithm", "ecdh-p256").option("--json", "Output raw JSON response").action(async (convId, opts) => {
4371
+ const client = getIMClient2();
4372
+ try {
4373
+ const res = await client.im.security.uploadKey(convId, opts.key, opts.algorithm);
4374
+ if (!res.ok) {
4375
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4376
+ `);
4377
+ process.exit(1);
4378
+ }
4379
+ if (opts.json) {
4380
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4381
+ return;
4382
+ }
4383
+ process.stdout.write(`Key uploaded (algorithm: ${opts.algorithm})
4384
+ `);
4385
+ } catch (err) {
4386
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4387
+ `);
4388
+ process.exit(1);
4389
+ }
4390
+ });
4391
+ security.command("keys <conversation-id>").description("List all member public keys for a conversation").option("--json", "Output raw JSON response").action(async (convId, opts) => {
4392
+ const client = getIMClient2();
4393
+ try {
4394
+ const res = await client.im.security.getKeys(convId);
4395
+ if (!res.ok) {
4396
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4397
+ `);
4398
+ process.exit(1);
4399
+ }
4400
+ const keys = res.data;
4401
+ if (opts.json) {
4402
+ process.stdout.write(JSON.stringify(keys, null, 2) + "\n");
4403
+ return;
4404
+ }
4405
+ if (!keys || Array.isArray(keys) && keys.length === 0) {
4406
+ process.stdout.write("No keys found.\n");
4407
+ return;
4408
+ }
4409
+ process.stdout.write("User ID".padEnd(36) + "Algorithm".padEnd(16) + "Public Key\n");
4410
+ for (const k of keys) {
4411
+ process.stdout.write(
4412
+ `${String(k.userId ?? "").padEnd(36)}${String(k.algorithm ?? "").padEnd(16)}${String(k.publicKey ?? "")}
4413
+ `
4414
+ );
4415
+ }
4416
+ } catch (err) {
4417
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4418
+ `);
4419
+ process.exit(1);
4420
+ }
4421
+ });
4422
+ security.command("revoke-key <conversation-id> <user-id>").description("Revoke a member key from a conversation").option("--json", "Output raw JSON response").action(async (convId, userId, opts) => {
4423
+ const client = getIMClient2();
4424
+ try {
4425
+ const res = await client.im.security.revokeKey(convId, userId);
4426
+ if (!res.ok) {
4427
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4428
+ `);
4429
+ process.exit(1);
4430
+ }
4431
+ if (opts.json) {
4432
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4433
+ return;
4434
+ }
4435
+ process.stdout.write(`Key revoked for user: ${userId}
4436
+ `);
4437
+ } catch (err) {
4438
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4439
+ `);
4440
+ process.exit(1);
4441
+ }
4442
+ });
4443
+ const identity = parent.command("identity").description("Identity key management and audit log verification");
4444
+ identity.command("server-key").description("Get the server's identity public key").option("--json", "Output raw JSON response").action(async (opts) => {
4445
+ const client = getIMClient2();
4446
+ try {
4447
+ const res = await client.im.identity.getServerKey();
4448
+ if (!res.ok) {
4449
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4450
+ `);
4451
+ process.exit(1);
4452
+ }
4453
+ if (opts.json) {
4454
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4455
+ return;
4456
+ }
4457
+ const d = res.data;
4458
+ process.stdout.write(`Server Public Key: ${d?.publicKey ?? "-"}
4459
+ `);
4460
+ } catch (err) {
4461
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4462
+ `);
4463
+ process.exit(1);
4464
+ }
4465
+ });
4466
+ identity.command("register-key").description("Register an identity public key").requiredOption("--algorithm <alg>", "Key algorithm (e.g. ed25519, ecdh-p256)").requiredOption("--public-key <base64>", "Base64-encoded public key").option("--json", "Output raw JSON response").action(async (opts) => {
4467
+ const client = getIMClient2();
4468
+ try {
4469
+ const res = await client.im.identity.registerKey({
4470
+ algorithm: opts.algorithm,
4471
+ publicKey: opts.publicKey
4472
+ });
4473
+ if (!res.ok) {
4474
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4475
+ `);
4476
+ process.exit(1);
4477
+ }
4478
+ if (opts.json) {
4479
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4480
+ return;
4481
+ }
4482
+ process.stdout.write(`Identity key registered (algorithm: ${opts.algorithm})
4483
+ `);
4484
+ } catch (err) {
4485
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4486
+ `);
4487
+ process.exit(1);
4488
+ }
4489
+ });
4490
+ identity.command("get-key <user-id>").description("Get a user's identity public key").option("--json", "Output raw JSON response").action(async (userId, opts) => {
4491
+ const client = getIMClient2();
4492
+ try {
4493
+ const res = await client.im.identity.getKey(userId);
4494
+ if (!res.ok) {
4495
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4496
+ `);
4497
+ process.exit(1);
4498
+ }
4499
+ if (opts.json) {
4500
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4501
+ return;
4502
+ }
4503
+ const d = res.data;
4504
+ process.stdout.write(`Algorithm: ${d?.algorithm ?? "-"}
4505
+ `);
4506
+ process.stdout.write(`Public Key: ${d?.publicKey ?? "-"}
4507
+ `);
4508
+ } catch (err) {
4509
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4510
+ `);
4511
+ process.exit(1);
4512
+ }
4513
+ });
4514
+ identity.command("revoke-key").description("Revoke your own identity key").option("--json", "Output raw JSON response").action(async (opts) => {
4515
+ const client = getIMClient2();
4516
+ try {
4517
+ const res = await client.im.identity.revokeKey();
4518
+ if (!res.ok) {
4519
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4520
+ `);
4521
+ process.exit(1);
4522
+ }
4523
+ if (opts.json) {
4524
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4525
+ return;
4526
+ }
4527
+ process.stdout.write("Identity key revoked.\n");
4528
+ } catch (err) {
4529
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4530
+ `);
4531
+ process.exit(1);
4532
+ }
4533
+ });
4534
+ identity.command("audit-log <user-id>").description("Get key audit log entries for a user").option("--json", "Output raw JSON response").action(async (userId, opts) => {
4535
+ const client = getIMClient2();
4536
+ try {
4537
+ const res = await client.im.identity.getAuditLog(userId);
4538
+ if (!res.ok) {
4539
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4540
+ `);
4541
+ process.exit(1);
4542
+ }
4543
+ const entries = res.data;
4544
+ if (opts.json) {
4545
+ process.stdout.write(JSON.stringify(entries, null, 2) + "\n");
4546
+ return;
4547
+ }
4548
+ if (!entries || Array.isArray(entries) && entries.length === 0) {
4549
+ process.stdout.write("No audit log entries.\n");
4550
+ return;
4551
+ }
4552
+ process.stdout.write("Date".padEnd(24) + "Action".padEnd(20) + "Details\n");
4553
+ for (const e of entries) {
4554
+ const date = e.createdAt ? new Date(String(e.createdAt)).toLocaleString() : "";
4555
+ process.stdout.write(
4556
+ `${date.padEnd(24)}${String(e.action ?? "").padEnd(20)}${e.details ? JSON.stringify(e.details) : ""}
4557
+ `
4558
+ );
4559
+ }
4560
+ } catch (err) {
4561
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4562
+ `);
4563
+ process.exit(1);
4564
+ }
4565
+ });
4566
+ identity.command("verify-audit <user-id>").description("Verify the integrity of the key audit log for a user").option("--json", "Output raw JSON response").action(async (userId, opts) => {
4567
+ const client = getIMClient2();
4568
+ try {
4569
+ const res = await client.im.identity.verifyAuditLog(userId);
4570
+ if (!res.ok) {
4571
+ process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
4572
+ `);
4573
+ process.exit(1);
4574
+ }
4575
+ if (opts.json) {
4576
+ process.stdout.write(JSON.stringify(res.data, null, 2) + "\n");
4577
+ return;
4578
+ }
4579
+ const d = res.data;
4580
+ if (d?.valid) {
4581
+ process.stdout.write("Audit log verified: VALID\n");
4582
+ } else {
4583
+ process.stdout.write("Audit log verified: INVALID\n");
4584
+ if (d?.errors && Array.isArray(d.errors) && d.errors.length > 0) {
4585
+ process.stdout.write("Errors:\n");
4586
+ for (const err of d.errors) {
4587
+ process.stdout.write(` - ${JSON.stringify(err)}
4588
+ `);
4589
+ }
4590
+ }
4591
+ }
4592
+ } catch (err) {
4593
+ process.stderr.write(`Error: ${err instanceof Error ? err.message : String(err)}
4594
+ `);
4595
+ process.exit(1);
4596
+ }
4597
+ });
4598
+ }
4599
+
4600
+ // src/cli.ts
4601
+ var cliVersion = "1.7.2";
4602
+ try {
4603
+ const pkgPath = path.join(__dirname, "..", "package.json");
4604
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
4605
+ cliVersion = pkg.version || cliVersion;
4606
+ } catch {
4607
+ }
4608
+ var CONFIG_DIR = path.join(os.homedir(), ".prismer");
4609
+ var CONFIG_PATH = path.join(CONFIG_DIR, "config.toml");
4610
+ function ensureConfigDir() {
4611
+ if (!fs.existsSync(CONFIG_DIR)) {
4612
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
4613
+ }
4614
+ }
4615
+ function readConfig() {
4616
+ if (!fs.existsSync(CONFIG_PATH)) return {};
4617
+ const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
4618
+ return TOML.parse(raw);
4619
+ }
4620
+ function writeConfig(config) {
4621
+ ensureConfigDir();
4622
+ fs.writeFileSync(CONFIG_PATH, TOML.stringify(config), "utf-8");
4623
+ }
4624
+ function setNestedValue(obj, dotPath, value) {
4625
+ const parts = dotPath.split(".");
4626
+ let current = obj;
4627
+ for (let i = 0; i < parts.length - 1; i++) {
4628
+ const key = parts[i];
4629
+ if (current[key] === void 0 || typeof current[key] !== "object") current[key] = {};
4630
+ current = current[key];
4631
+ }
4632
+ current[parts[parts.length - 1]] = value;
4633
+ }
4634
+ function getIMClient() {
4635
+ const cfg = readConfig();
4636
+ const token = cfg?.auth?.im_token;
4637
+ if (!token) {
4638
+ console.error('No IM token. Run "prismer register" first.');
4639
+ process.exit(1);
4640
+ }
4641
+ const env = cfg?.default?.environment || "production";
4642
+ const baseUrl = cfg?.default?.base_url || "";
4643
+ return new PrismerClient({ apiKey: token, environment: env, ...baseUrl ? { baseUrl } : {} });
4644
+ }
4645
+ function getAPIClient() {
4646
+ const cfg = readConfig();
4647
+ const apiKey = cfg?.default?.api_key;
4648
+ if (!apiKey) {
4649
+ console.error('No API key. Run "prismer init <api-key>" first.');
4650
+ process.exit(1);
4651
+ }
4652
+ const env = cfg?.default?.environment || "production";
4653
+ const baseUrl = cfg?.default?.base_url || "";
4654
+ return new PrismerClient({ apiKey, environment: env, ...baseUrl ? { baseUrl } : {} });
4655
+ }
4656
+ var program = new import_commander.Command();
4657
+ program.name("prismer").description("Prismer Cloud SDK CLI").version(cliVersion);
4658
+ program.command("init <api-key>").description("Store API key in ~/.prismer/config.toml").action((apiKey) => {
4659
+ const config = readConfig();
4660
+ if (!config.default) config.default = {};
4661
+ config.default.api_key = apiKey;
4662
+ if (!config.default.environment) config.default.environment = "production";
4663
+ if (config.default.base_url === void 0) config.default.base_url = "";
4664
+ writeConfig(config);
4665
+ console.log("API key saved to ~/.prismer/config.toml");
4666
+ });
4667
+ program.command("register <username>").description("Register an IM identity and store the token").option("--type <type>", "Identity type: agent or human", "agent").option("--display-name <name>", "Display name").option("--agent-type <agentType>", "Agent type: assistant, specialist, orchestrator, tool, bot").option("--capabilities <caps>", "Comma-separated capabilities").option("--endpoint <url>", "Webhook endpoint URL").option("--webhook-secret <secret>", "Webhook HMAC secret").action(async (username, opts) => {
4668
+ const config = readConfig();
4669
+ const apiKey = config.default?.api_key;
4670
+ if (!apiKey) {
4671
+ console.error('No API key. Run "prismer init <api-key>" first.');
4672
+ process.exit(1);
4673
+ }
4674
+ const client = new PrismerClient({
4675
+ apiKey,
4676
+ environment: config.default?.environment || "production",
4677
+ baseUrl: config.default?.base_url || void 0
4678
+ });
4679
+ const registerOpts = {
4680
+ type: opts.type,
4681
+ username,
4682
+ displayName: opts.displayName || username
4683
+ };
4684
+ if (opts.agentType) registerOpts.agentType = opts.agentType;
4685
+ if (opts.capabilities) registerOpts.capabilities = opts.capabilities.split(",").map((c) => c.trim());
4686
+ if (opts.endpoint) registerOpts.endpoint = opts.endpoint;
4687
+ if (opts.webhookSecret) registerOpts.webhookSecret = opts.webhookSecret;
4688
+ try {
4689
+ const result = await client.im.account.register(registerOpts);
4690
+ if (!result.ok || !result.data) {
4691
+ console.error("Registration failed:", result.error?.message || "Unknown error");
4692
+ process.exit(1);
4693
+ }
4694
+ const data = result.data;
4695
+ if (!config.auth) config.auth = {};
4696
+ config.auth.im_token = data.token;
4697
+ config.auth.im_user_id = data.imUserId;
4698
+ config.auth.im_username = data.username;
4699
+ config.auth.im_token_expires = data.expiresIn;
1851
4700
  writeConfig(config);
1852
4701
  console.log("Registration successful!");
1853
4702
  console.log(` User ID: ${data.imUserId}`);
@@ -1855,18 +4704,15 @@ program.command("register <username>").description("Register an IM agent and sto
1855
4704
  console.log(` Display: ${data.displayName}`);
1856
4705
  console.log(` Role: ${data.role}`);
1857
4706
  console.log(` New: ${data.isNew}`);
1858
- console.log(` Expires: ${data.expiresIn}`);
1859
- console.log("");
1860
4707
  console.log("Token stored in ~/.prismer/config.toml");
1861
4708
  } catch (err) {
1862
4709
  console.error("Registration failed:", err instanceof Error ? err.message : err);
1863
4710
  process.exit(1);
1864
4711
  }
1865
4712
  });
1866
- program.command("status").description("Show current config and token status").action(async () => {
4713
+ program.command("status").description("Show current config and live info").action(async () => {
1867
4714
  const config = readConfig();
1868
- console.log("=== Prismer Status ===");
1869
- console.log("");
4715
+ console.log("=== Prismer Status ===\n");
1870
4716
  const apiKey = config.default?.api_key;
1871
4717
  if (apiKey) {
1872
4718
  const masked = apiKey.length > 16 ? apiKey.slice(0, 12) + "..." + apiKey.slice(-4) : "***";
@@ -1875,8 +4721,8 @@ program.command("status").description("Show current config and token status").ac
1875
4721
  console.log("API Key: (not set)");
1876
4722
  }
1877
4723
  console.log(`Environment: ${config.default?.environment || "(not set)"}`);
1878
- console.log(`Base URL: ${config.default?.base_url || "(default)"}`);
1879
- console.log("");
4724
+ console.log(`Base URL: ${config.default?.base_url || "(default)"}
4725
+ `);
1880
4726
  const token = config.auth?.im_token;
1881
4727
  if (token) {
1882
4728
  console.log(`IM User ID: ${config.auth?.im_user_id || "(unknown)"}`);
@@ -1885,9 +4731,7 @@ program.command("status").description("Show current config and token status").ac
1885
4731
  if (expires) {
1886
4732
  const expiresDate = new Date(expires);
1887
4733
  if (!isNaN(expiresDate.getTime())) {
1888
- const now = /* @__PURE__ */ new Date();
1889
- const isExpired = expiresDate <= now;
1890
- const label = isExpired ? "EXPIRED" : "valid";
4734
+ const label = expiresDate <= /* @__PURE__ */ new Date() ? "EXPIRED" : "valid";
1891
4735
  console.log(`IM Token: ${label} (expires ${expiresDate.toISOString()})`);
1892
4736
  } else {
1893
4737
  console.log(`IM Token: set (expires in ${expires})`);
@@ -1895,12 +4739,7 @@ program.command("status").description("Show current config and token status").ac
1895
4739
  } else {
1896
4740
  console.log("IM Token: set (expiry unknown)");
1897
4741
  }
1898
- } else {
1899
- console.log("IM Token: (not registered)");
1900
- }
1901
- if (token) {
1902
- console.log("");
1903
- console.log("--- Live Info ---");
4742
+ console.log("\n--- Live Info ---");
1904
4743
  try {
1905
4744
  const client = new PrismerClient({
1906
4745
  apiKey: token,
@@ -1920,355 +4759,79 @@ program.command("status").description("Show current config and token status").ac
1920
4759
  } catch (err) {
1921
4760
  console.log(`Could not fetch live info: ${err instanceof Error ? err.message : err}`);
1922
4761
  }
4762
+ } else {
4763
+ console.log("IM Token: (not registered)");
1923
4764
  }
1924
4765
  });
1925
4766
  var configCmd = program.command("config").description("Manage config file");
1926
- configCmd.command("show").description("Print config file contents").action(() => {
4767
+ configCmd.command("show").description("Print config file").action(() => {
1927
4768
  if (!fs.existsSync(CONFIG_PATH)) {
1928
- console.log("No config file found at ~/.prismer/config.toml");
1929
- console.log('Run "prismer init <api-key>" to create one.');
4769
+ console.log('No config file. Run "prismer init <api-key>" to create one.');
1930
4770
  return;
1931
4771
  }
1932
- const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
1933
- console.log(raw);
4772
+ console.log(fs.readFileSync(CONFIG_PATH, "utf-8"));
1934
4773
  });
1935
- configCmd.command("set <key> <value>").description("Set a config value (e.g., prismer config set default.api_key sk-prismer-...)").action((key, value) => {
4774
+ configCmd.command("set <key> <value>").description("Set a config value (e.g. default.base_url)").action((key, value) => {
1936
4775
  const config = readConfig();
1937
4776
  setNestedValue(config, key, value);
1938
4777
  writeConfig(config);
1939
4778
  console.log(`Set ${key} = ${value}`);
1940
4779
  });
1941
- var im = program.command("im").description("IM messaging commands");
1942
- im.command("me").description("Show current identity and stats").option("--json", "JSON output").action(async (opts) => {
1943
- const client = getIMClient();
1944
- const res = await client.im.account.me();
1945
- if (!res.ok) {
1946
- console.error("Error:", res.error);
1947
- process.exit(1);
1948
- }
1949
- const d = res.data;
1950
- if (opts.json) {
1951
- console.log(JSON.stringify(d, null, 2));
1952
- return;
1953
- }
1954
- console.log(`Display Name: ${d?.user?.displayName || "-"}`);
1955
- console.log(`Username: ${d?.user?.username || "-"}`);
1956
- console.log(`Role: ${d?.user?.role || "-"}`);
1957
- console.log(`Agent Type: ${d?.agentCard?.agentType || "-"}`);
1958
- console.log(`Credits: ${d?.credits?.balance ?? "-"}`);
1959
- console.log(`Messages: ${d?.stats?.messagesSent ?? "-"}`);
1960
- console.log(`Unread: ${d?.stats?.unreadCount ?? "-"}`);
1961
- });
1962
- im.command("health").description("Check IM service health").action(async () => {
1963
- const client = getIMClient();
1964
- const res = await client.im.health();
1965
- console.log(`IM Service: ${res.ok ? "OK" : "ERROR"}`);
1966
- if (!res.ok) {
1967
- console.error(res.error);
1968
- process.exit(1);
1969
- }
1970
- });
1971
- im.command("send").description("Send a direct message").argument("<user-id>", "Target user ID").argument("<message>", "Message content").option("--json", "JSON output").action(async (userId, message, opts) => {
1972
- const client = getIMClient();
1973
- const res = await client.im.direct.send(userId, message);
1974
- if (!res.ok) {
1975
- console.error("Error:", res.error);
1976
- process.exit(1);
1977
- }
1978
- if (opts.json) {
1979
- console.log(JSON.stringify(res.data, null, 2));
1980
- return;
1981
- }
1982
- console.log(`Message sent (conversationId: ${res.data?.conversationId})`);
1983
- });
1984
- im.command("messages").description("View direct message history").argument("<user-id>", "Target user ID").option("-n, --limit <n>", "Max messages", "20").option("--json", "JSON output").action(async (userId, opts) => {
1985
- const client = getIMClient();
1986
- const res = await client.im.direct.getMessages(userId, { limit: parseInt(opts.limit) });
1987
- if (!res.ok) {
1988
- console.error("Error:", res.error);
1989
- process.exit(1);
1990
- }
1991
- const msgs = res.data || [];
1992
- if (opts.json) {
1993
- console.log(JSON.stringify(msgs, null, 2));
1994
- return;
1995
- }
1996
- if (msgs.length === 0) {
1997
- console.log("No messages.");
1998
- return;
1999
- }
2000
- for (const m of msgs) {
2001
- const ts = m.createdAt ? new Date(m.createdAt).toLocaleString() : "";
2002
- console.log(`[${ts}] ${m.senderId || "?"}: ${m.content}`);
2003
- }
2004
- });
2005
- im.command("discover").description("Discover available agents").option("--type <type>", "Filter by type").option("--capability <cap>", "Filter by capability").option("--json", "JSON output").action(async (opts) => {
2006
- const client = getIMClient();
2007
- const discoverOpts = {};
2008
- if (opts.type) discoverOpts.type = opts.type;
2009
- if (opts.capability) discoverOpts.capability = opts.capability;
2010
- const res = await client.im.contacts.discover(discoverOpts);
2011
- if (!res.ok) {
2012
- console.error("Error:", res.error);
2013
- process.exit(1);
2014
- }
2015
- const agents = res.data || [];
2016
- if (opts.json) {
2017
- console.log(JSON.stringify(agents, null, 2));
2018
- return;
2019
- }
2020
- if (agents.length === 0) {
2021
- console.log("No agents found.");
2022
- return;
2023
- }
2024
- console.log("Username".padEnd(20) + "Type".padEnd(14) + "Status".padEnd(10) + "Display Name");
2025
- for (const a of agents) {
2026
- console.log(`${(a.username || "").padEnd(20)}${(a.agentType || "").padEnd(14)}${(a.status || "").padEnd(10)}${a.displayName || ""}`);
2027
- }
2028
- });
2029
- im.command("contacts").description("List contacts").option("--json", "JSON output").action(async (opts) => {
2030
- const client = getIMClient();
2031
- const res = await client.im.contacts.list();
2032
- if (!res.ok) {
2033
- console.error("Error:", res.error);
2034
- process.exit(1);
2035
- }
2036
- const contacts = res.data || [];
2037
- if (opts.json) {
2038
- console.log(JSON.stringify(contacts, null, 2));
2039
- return;
2040
- }
2041
- if (contacts.length === 0) {
2042
- console.log("No contacts.");
2043
- return;
2044
- }
2045
- console.log("Username".padEnd(20) + "Role".padEnd(10) + "Unread".padEnd(8) + "Display Name");
2046
- for (const c of contacts) {
2047
- console.log(`${(c.username || "").padEnd(20)}${(c.role || "").padEnd(10)}${String(c.unreadCount ?? 0).padEnd(8)}${c.displayName || ""}`);
2048
- }
2049
- });
2050
- var groups = im.command("groups").description("Group management");
2051
- groups.command("list").description("List groups").option("--json", "JSON output").action(async (opts) => {
2052
- const client = getIMClient();
2053
- const res = await client.im.groups.list();
2054
- if (!res.ok) {
2055
- console.error("Error:", res.error);
2056
- process.exit(1);
2057
- }
2058
- const list = res.data || [];
2059
- if (opts.json) {
2060
- console.log(JSON.stringify(list, null, 2));
2061
- return;
2062
- }
2063
- if (list.length === 0) {
2064
- console.log("No groups.");
2065
- return;
2066
- }
2067
- for (const g of list) {
2068
- console.log(`${g.groupId || ""} ${g.title || ""} (${g.members?.length || "?"} members)`);
2069
- }
2070
- });
2071
- groups.command("create").description("Create a group").argument("<title>", "Group title").option("-m, --members <ids>", "Comma-separated member IDs").option("--json", "JSON output").action(async (title, opts) => {
2072
- const client = getIMClient();
2073
- const members = opts.members ? opts.members.split(",").map((s) => s.trim()) : [];
2074
- const res = await client.im.groups.create({ title, members });
2075
- if (!res.ok) {
2076
- console.error("Error:", res.error);
2077
- process.exit(1);
2078
- }
2079
- if (opts.json) {
2080
- console.log(JSON.stringify(res.data, null, 2));
2081
- return;
2082
- }
2083
- console.log(`Group created (groupId: ${res.data?.groupId})`);
2084
- });
2085
- groups.command("send").description("Send message to group").argument("<group-id>", "Group ID").argument("<message>", "Message content").option("--json", "JSON output").action(async (groupId, message, opts) => {
2086
- const client = getIMClient();
2087
- const res = await client.im.groups.send(groupId, message);
2088
- if (!res.ok) {
2089
- console.error("Error:", res.error);
2090
- process.exit(1);
2091
- }
2092
- if (opts.json) {
2093
- console.log(JSON.stringify(res.data, null, 2));
2094
- return;
2095
- }
2096
- console.log("Message sent to group.");
2097
- });
2098
- groups.command("messages").description("View group message history").argument("<group-id>", "Group ID").option("-n, --limit <n>", "Max messages", "20").option("--json", "JSON output").action(async (groupId, opts) => {
2099
- const client = getIMClient();
2100
- const res = await client.im.groups.getMessages(groupId, { limit: parseInt(opts.limit) });
2101
- if (!res.ok) {
2102
- console.error("Error:", res.error);
2103
- process.exit(1);
2104
- }
2105
- const msgs = res.data || [];
2106
- if (opts.json) {
2107
- console.log(JSON.stringify(msgs, null, 2));
2108
- return;
2109
- }
2110
- if (msgs.length === 0) {
2111
- console.log("No messages.");
2112
- return;
2113
- }
2114
- for (const m of msgs) {
2115
- const ts = m.createdAt ? new Date(m.createdAt).toLocaleString() : "";
2116
- console.log(`[${ts}] ${m.senderId || "?"}: ${m.content}`);
2117
- }
2118
- });
2119
- var convos = im.command("conversations").description("Conversation management");
2120
- convos.command("list").description("List conversations").option("--unread", "Show unread only").option("--json", "JSON output").action(async (opts) => {
2121
- const client = getIMClient();
2122
- const listOpts = {};
2123
- if (opts.unread) {
2124
- listOpts.withUnread = true;
2125
- listOpts.unreadOnly = true;
2126
- }
2127
- const res = await client.im.conversations.list(listOpts);
2128
- if (!res.ok) {
2129
- console.error("Error:", res.error);
2130
- process.exit(1);
2131
- }
2132
- const list = res.data || [];
2133
- if (opts.json) {
2134
- console.log(JSON.stringify(list, null, 2));
2135
- return;
2136
- }
2137
- if (list.length === 0) {
2138
- console.log("No conversations.");
2139
- return;
2140
- }
2141
- for (const c of list) {
2142
- const unread = c.unreadCount ? ` (${c.unreadCount} unread)` : "";
2143
- console.log(`${c.id || ""} ${c.type || ""} ${c.title || ""}${unread}`);
2144
- }
2145
- });
2146
- convos.command("read").description("Mark conversation as read").argument("<conversation-id>", "Conversation ID").action(async (convId) => {
2147
- const client = getIMClient();
2148
- const res = await client.im.conversations.markAsRead(convId);
2149
- if (!res.ok) {
2150
- console.error("Error:", res.error);
2151
- process.exit(1);
2152
- }
2153
- console.log("Marked as read.");
2154
- });
2155
- var files = im.command("files").description("File upload management");
2156
- files.command("upload").description("Upload a file").argument("<path>", "File path to upload").option("--mime <type>", "Override MIME type").option("--json", "JSON output").action(async (filePath, opts) => {
2157
- const client = getIMClient();
2158
- try {
2159
- const result = await client.im.files.upload(filePath, { mimeType: opts.mime });
2160
- if (opts.json) {
2161
- console.log(JSON.stringify(result, null, 2));
2162
- return;
2163
- }
2164
- console.log(`Upload ID: ${result.uploadId}`);
2165
- console.log(`CDN URL: ${result.cdnUrl}`);
2166
- console.log(`File: ${result.fileName} (${result.fileSize} bytes)`);
2167
- console.log(`MIME: ${result.mimeType}`);
2168
- } catch (err) {
2169
- console.error("Upload failed:", err instanceof Error ? err.message : err);
2170
- process.exit(1);
2171
- }
2172
- });
2173
- files.command("send").description("Upload file and send as message").argument("<conversation-id>", "Conversation ID").argument("<path>", "File path to upload").option("--content <text>", "Message text").option("--mime <type>", "Override MIME type").option("--json", "JSON output").action(async (conversationId, filePath, opts) => {
2174
- const client = getIMClient();
2175
- try {
2176
- const result = await client.im.files.sendFile(conversationId, filePath, { content: opts.content, mimeType: opts.mime });
2177
- if (opts.json) {
2178
- console.log(JSON.stringify(result, null, 2));
2179
- return;
2180
- }
2181
- console.log(`Upload ID: ${result.upload.uploadId}`);
2182
- console.log(`CDN URL: ${result.upload.cdnUrl}`);
2183
- console.log(`File: ${result.upload.fileName}`);
2184
- console.log(`Message: sent`);
2185
- } catch (err) {
2186
- console.error("Send file failed:", err instanceof Error ? err.message : err);
2187
- process.exit(1);
2188
- }
2189
- });
2190
- files.command("quota").description("Show storage quota").option("--json", "JSON output").action(async (opts) => {
4780
+ var tokenCmd = program.command("token").description("Token management");
4781
+ tokenCmd.command("refresh").description("Refresh IM JWT token").option("--json", "JSON output").action(async (opts) => {
2191
4782
  const client = getIMClient();
2192
- const res = await client.im.files.quota();
2193
- if (!res.ok) {
2194
- console.error("Error:", res.error);
2195
- process.exit(1);
2196
- }
4783
+ const res = await client.im.account.refreshToken();
2197
4784
  if (opts.json) {
2198
- console.log(JSON.stringify(res.data, null, 2));
4785
+ console.log(JSON.stringify(res, null, 2));
2199
4786
  return;
2200
4787
  }
2201
- const q = res.data;
2202
- console.log(`Used: ${q?.used ?? "-"} bytes`);
2203
- console.log(`Limit: ${q?.limit ?? "-"} bytes`);
2204
- console.log(`File Count: ${q?.fileCount ?? "-"}`);
2205
- console.log(`Tier: ${q?.tier ?? "-"}`);
2206
- });
2207
- files.command("delete").description("Delete an uploaded file").argument("<upload-id>", "Upload ID").action(async (uploadId) => {
2208
- const client = getIMClient();
2209
- const res = await client.im.files.delete(uploadId);
2210
- if (!res.ok) {
2211
- console.error("Error:", res.error);
2212
- process.exit(1);
2213
- }
2214
- console.log(`Deleted upload ${uploadId}.`);
2215
- });
2216
- files.command("types").description("List allowed MIME types").option("--json", "JSON output").action(async (opts) => {
2217
- const client = getIMClient();
2218
- const res = await client.im.files.types();
2219
4788
  if (!res.ok) {
2220
4789
  console.error("Error:", res.error);
2221
4790
  process.exit(1);
2222
4791
  }
2223
- if (opts.json) {
2224
- console.log(JSON.stringify(res.data, null, 2));
2225
- return;
2226
- }
2227
- const types = res.data?.allowedMimeTypes || [];
2228
- console.log(`Allowed MIME types (${types.length}):`);
2229
- for (const t of types) {
2230
- console.log(` ${t}`);
4792
+ const data = res.data;
4793
+ const config = readConfig();
4794
+ if (!config.auth) config.auth = {};
4795
+ if (data?.token) {
4796
+ config.auth.im_token = data.token;
4797
+ if (data.expiresIn) config.auth.im_token_expires = data.expiresIn;
4798
+ writeConfig(config);
4799
+ console.log("Token refreshed and saved.");
4800
+ } else {
4801
+ console.log("Token refreshed (no new token in response).");
2231
4802
  }
2232
4803
  });
2233
- im.command("credits").description("Show credits balance").option("--json", "JSON output").action(async (opts) => {
4804
+ register(program, getIMClient, getAPIClient);
4805
+ register2(program, getIMClient, getAPIClient);
4806
+ register3(program, getIMClient, getAPIClient);
4807
+ register4(program, getIMClient, getAPIClient);
4808
+ register5(program, getIMClient, getAPIClient);
4809
+ register6(program, getIMClient, getAPIClient);
4810
+ register7(program, getIMClient, getAPIClient);
4811
+ register8(program, getIMClient, getAPIClient);
4812
+ register9(program, getIMClient, getAPIClient);
4813
+ program.command("send").description("Send a direct message (shortcut for: im send)").argument("<user-id>", "Target user/agent ID").argument("<message>", "Message content").option("-t, --type <type>", "Message type: text, markdown, code, etc.", "text").option("--reply-to <id>", "Reply to a message ID").option("--json", "JSON output").action(async (userId, message, opts) => {
2234
4814
  const client = getIMClient();
2235
- const res = await client.im.credits.get();
2236
- if (!res.ok) {
2237
- console.error("Error:", res.error);
2238
- process.exit(1);
2239
- }
4815
+ const sendOpts = {};
4816
+ if (opts.type && opts.type !== "text") sendOpts.type = opts.type;
4817
+ if (opts.replyTo) sendOpts.parentId = opts.replyTo;
4818
+ const res = await client.im.direct.send(userId, message, sendOpts);
2240
4819
  if (opts.json) {
2241
- console.log(JSON.stringify(res.data, null, 2));
4820
+ console.log(JSON.stringify(res, null, 2));
2242
4821
  return;
2243
4822
  }
2244
- console.log(`Balance: ${res.data?.balance ?? "-"}`);
2245
- });
2246
- im.command("transactions").description("Transaction history").option("-n, --limit <n>", "Max transactions", "20").option("--json", "JSON output").action(async (opts) => {
2247
- const client = getIMClient();
2248
- const res = await client.im.credits.transactions({ limit: parseInt(opts.limit) });
2249
4823
  if (!res.ok) {
2250
4824
  console.error("Error:", res.error);
2251
4825
  process.exit(1);
2252
4826
  }
2253
- const txns = res.data || [];
2254
- if (opts.json) {
2255
- console.log(JSON.stringify(txns, null, 2));
2256
- return;
2257
- }
2258
- if (txns.length === 0) {
2259
- console.log("No transactions.");
2260
- return;
2261
- }
2262
- for (const t of txns) {
2263
- console.log(`${t.createdAt || ""} ${t.type || ""} ${t.amount ?? ""} ${t.description || ""}`);
2264
- }
4827
+ console.log(`Message sent (conversation: ${res.data?.conversationId})`);
2265
4828
  });
2266
- var ctx = program.command("context").description("Context API commands");
2267
- ctx.command("load").description("Load URL content").argument("<url>", "URL to load").option("-f, --format <fmt>", "Return format: hqcc, raw, both", "hqcc").option("--json", "JSON output").action(async (url, opts) => {
4829
+ program.command("load").description("Load URL(s) \u2192 compressed HQCC (shortcut for: context load)").argument("<urls...>", "One or more URLs").option("-f, --format <fmt>", "Return format: hqcc, raw, both", "hqcc").option("--json", "JSON output").action(async (urls, opts) => {
2268
4830
  const client = getAPIClient();
4831
+ const input = urls.length === 1 ? urls[0] : urls;
2269
4832
  const loadOpts = {};
2270
4833
  if (opts.format) loadOpts.return = { format: opts.format };
2271
- const res = await client.load(url, loadOpts);
4834
+ const res = await client.load(input, loadOpts);
2272
4835
  if (opts.json) {
2273
4836
  console.log(JSON.stringify(res, null, 2));
2274
4837
  return;
@@ -2277,23 +4840,22 @@ ctx.command("load").description("Load URL content").argument("<url>", "URL to lo
2277
4840
  console.error("Error:", res.error?.message || "Load failed");
2278
4841
  process.exit(1);
2279
4842
  }
2280
- const r = res.result;
2281
- console.log(`URL: ${r?.url || url}`);
2282
- console.log(`Status: ${r?.cached ? "cached" : "loaded"}`);
2283
- if (r?.hqcc) {
2284
- console.log(`
4843
+ const results = res.results || (res.result ? [res.result] : []);
4844
+ for (const r of results) {
4845
+ console.log(`URL: ${r.url || "?"}`);
4846
+ console.log(`Status: ${r.cached ? "cached" : "loaded"}`);
4847
+ if (r.hqcc) console.log(`
2285
4848
  --- HQCC ---
2286
4849
  ${r.hqcc.substring(0, 2e3)}`);
2287
- }
2288
- if (r?.raw) {
2289
- console.log(`
4850
+ if (r.raw) console.log(`
2290
4851
  --- Raw ---
2291
4852
  ${r.raw.substring(0, 2e3)}`);
4853
+ console.log("");
2292
4854
  }
2293
4855
  });
2294
- ctx.command("search").description("Search cached content").argument("<query>", "Search query").option("-k, --top-k <n>", "Number of results", "5").option("--json", "JSON output").action(async (query, opts) => {
4856
+ program.command("search").description("Search web content (shortcut for: context search)").argument("<query>", "Search query").option("-k, --top-k <n>", "Number of results", "5").option("--json", "JSON output").action(async (query, opts) => {
2295
4857
  const client = getAPIClient();
2296
- const res = await client.search(query, { topK: parseInt(opts.topK) });
4858
+ const res = await client.search(query, { topK: parseInt(opts.topK || "5") });
2297
4859
  if (opts.json) {
2298
4860
  console.log(JSON.stringify(res, null, 2));
2299
4861
  return;
@@ -2313,21 +4875,7 @@ ctx.command("search").description("Search cached content").argument("<query>", "
2313
4875
  if (r.hqcc) console.log(` ${r.hqcc.substring(0, 200)}`);
2314
4876
  }
2315
4877
  });
2316
- ctx.command("save").description("Save content to cache").argument("<url>", "URL key").argument("<hqcc>", "HQCC content").option("--json", "JSON output").action(async (url, hqcc, opts) => {
2317
- const client = getAPIClient();
2318
- const res = await client.save({ url, hqcc });
2319
- if (opts.json) {
2320
- console.log(JSON.stringify(res, null, 2));
2321
- return;
2322
- }
2323
- if (!res.success) {
2324
- console.error("Error:", res.error?.message || "Save failed");
2325
- process.exit(1);
2326
- }
2327
- console.log("Content saved.");
2328
- });
2329
- var parse2 = program.command("parse").description("Document parsing commands");
2330
- parse2.command("run").description("Parse a document").argument("<url>", "Document URL").option("-m, --mode <mode>", "Parse mode: fast, hires, auto", "fast").option("--json", "JSON output").action(async (url, opts) => {
4878
+ program.command("parse").description("Parse a document via OCR (shortcut for: parse run)").argument("<url>", "Document URL").option("-m, --mode <mode>", "Parse mode: fast, hires, auto", "fast").option("--async", "Async mode (returns task ID)").option("--json", "JSON output").action(async (url, opts) => {
2331
4879
  const client = getAPIClient();
2332
4880
  const res = await client.parsePdf(url, opts.mode);
2333
4881
  if (opts.json) {
@@ -2342,14 +4890,17 @@ parse2.command("run").description("Parse a document").argument("<url>", "Documen
2342
4890
  console.log(`Task ID: ${res.taskId}`);
2343
4891
  console.log(`Status: ${res.status || "processing"}`);
2344
4892
  console.log(`
2345
- Check progress: prismer parse status ${res.taskId}`);
4893
+ Check: prismer parse status ${res.taskId}`);
2346
4894
  } else if (res.document) {
2347
- console.log(`Status: complete`);
4895
+ console.log("Status: complete");
2348
4896
  const content = res.document.markdown || res.document.text || JSON.stringify(res.document, null, 2);
2349
4897
  console.log(content.substring(0, 5e3));
2350
4898
  }
2351
4899
  });
2352
- parse2.command("status").description("Check parse task status").argument("<task-id>", "Task ID").option("--json", "JSON output").action(async (taskId, opts) => {
4900
+ var parseCmd = program.commands.find((c) => c.name() === "parse");
4901
+ if (parseCmd) {
4902
+ }
4903
+ program.command("parse-status").description("Check parse task status").argument("<task-id>", "Task ID").option("--json", "JSON output").action(async (taskId, opts) => {
2353
4904
  const client = getAPIClient();
2354
4905
  const res = await client.parseStatus(taskId);
2355
4906
  if (opts.json) {
@@ -2359,7 +4910,7 @@ parse2.command("status").description("Check parse task status").argument("<task-
2359
4910
  console.log(`Task: ${taskId}`);
2360
4911
  console.log(`Status: ${res.status || (res.success ? "complete" : "unknown")}`);
2361
4912
  });
2362
- parse2.command("result").description("Get parse result").argument("<task-id>", "Task ID").option("--json", "JSON output").action(async (taskId, opts) => {
4913
+ program.command("parse-result").description("Get parse result").argument("<task-id>", "Task ID").option("--json", "JSON output").action(async (taskId, opts) => {
2363
4914
  const client = getAPIClient();
2364
4915
  const res = await client.parseResult(taskId);
2365
4916
  if (opts.json) {
@@ -2373,4 +4924,57 @@ parse2.command("result").description("Get parse result").argument("<task-id>", "
2373
4924
  const content = res.document?.markdown || res.document?.text || JSON.stringify(res.document, null, 2);
2374
4925
  console.log(content);
2375
4926
  });
4927
+ program.command("recall").description("Search across memory, cache, and evolution (shortcut for: memory recall)").argument("<query>", "Search query").option("--scope <scope>", "Scope: all, memory, cache, evolution", "all").option("-n, --limit <n>", "Max results", "10").option("--json", "JSON output").action(async (query, opts) => {
4928
+ const client = getIMClient();
4929
+ const params = { q: query };
4930
+ if (opts.scope) params.scope = opts.scope;
4931
+ if (opts.limit) params.limit = opts.limit;
4932
+ const res = await client.im.memory._r("GET", "/api/im/recall", void 0, params);
4933
+ if (opts.json) {
4934
+ console.log(JSON.stringify(res, null, 2));
4935
+ return;
4936
+ }
4937
+ if (!res.ok) {
4938
+ console.error("Error:", res.error);
4939
+ process.exit(1);
4940
+ }
4941
+ const data = res.data || [];
4942
+ if (data.length === 0) {
4943
+ console.log(`No results for "${query}".`);
4944
+ return;
4945
+ }
4946
+ for (const item of data) {
4947
+ console.log(`[${(item.source || "").toUpperCase()}] ${item.title || "?"} (score: ${(item.score || 0).toFixed(2)})`);
4948
+ if (item.snippet) console.log(` ${item.snippet.substring(0, 200)}`);
4949
+ }
4950
+ });
4951
+ program.command("discover").description("Discover available agents (shortcut for: im discover)").option("--type <type>", "Filter by agent type").option("--capability <cap>", "Filter by capability").option("--json", "JSON output").action(async (opts) => {
4952
+ const client = getIMClient();
4953
+ const discoverOpts = {};
4954
+ if (opts.type) discoverOpts.type = opts.type;
4955
+ if (opts.capability) discoverOpts.capability = opts.capability;
4956
+ const res = await client.im.contacts.discover(discoverOpts);
4957
+ if (opts.json) {
4958
+ console.log(JSON.stringify(res, null, 2));
4959
+ return;
4960
+ }
4961
+ if (!res.ok) {
4962
+ console.error("Error:", res.error);
4963
+ process.exit(1);
4964
+ }
4965
+ const agents = res.data || [];
4966
+ if (agents.length === 0) {
4967
+ console.log("No agents found.");
4968
+ return;
4969
+ }
4970
+ console.log("Username".padEnd(20) + "Type".padEnd(14) + "Status".padEnd(10) + "Display Name");
4971
+ for (const a of agents) {
4972
+ console.log(`${(a.username || "").padEnd(20)}${(a.agentType || "").padEnd(14)}${(a.status || "").padEnd(10)}${a.displayName || ""}`);
4973
+ }
4974
+ });
2376
4975
  program.parse(process.argv);
4976
+ // Annotate the CommonJS export names for ESM import in node:
4977
+ 0 && (module.exports = {
4978
+ getAPIClient,
4979
+ getIMClient
4980
+ });