@prismer/sdk 1.7.0 → 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/LICENSE +21 -0
- package/README.md +402 -190
- package/dist/cli.js +3083 -479
- package/dist/index.d.mts +1029 -3
- package/dist/index.d.ts +1029 -3
- package/dist/index.js +1129 -6
- package/dist/index.mjs +1112 -5
- package/package.json +2 -2
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,
|
|
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
|
|
951
|
-
if (
|
|
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
|
|
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(
|
|
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/
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
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
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
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
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
4767
|
+
configCmd.command("show").description("Print config file").action(() => {
|
|
1927
4768
|
if (!fs.existsSync(CONFIG_PATH)) {
|
|
1928
|
-
console.log(
|
|
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
|
-
|
|
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
|
|
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
|
|
1942
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
console.log(
|
|
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
|
-
|
|
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
|
|
2236
|
-
if (
|
|
2237
|
-
|
|
2238
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
4893
|
+
Check: prismer parse status ${res.taskId}`);
|
|
2346
4894
|
} else if (res.document) {
|
|
2347
|
-
console.log(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
});
|