@prismer/sdk 1.8.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env node
2
1
  "use strict";
3
2
  var __create = Object.create;
4
3
  var __defProp = Object.defineProperty;
@@ -36,8 +35,8 @@ __export(cli_exports, {
36
35
  });
37
36
  module.exports = __toCommonJS(cli_exports);
38
37
  var import_commander = require("commander");
39
- var fs2 = __toESM(require("fs"));
40
- var path2 = __toESM(require("path"));
38
+ var fs3 = __toESM(require("fs"));
39
+ var path3 = __toESM(require("path"));
41
40
  var os2 = __toESM(require("os"));
42
41
  var TOML2 = __toESM(require("@iarna/toml"));
43
42
 
@@ -163,7 +162,7 @@ var RealtimeWSClient = class extends TypedEmitter {
163
162
  if (this._state === "connected" || this._state === "connecting") return;
164
163
  this._state = "connecting";
165
164
  this.intentionalClose = false;
166
- return new Promise((resolve, reject) => {
165
+ return new Promise((resolve2, reject) => {
167
166
  try {
168
167
  this.ws = new this.WS(this.wsUrl);
169
168
  } catch (err) {
@@ -185,7 +184,7 @@ var RealtimeWSClient = class extends TypedEmitter {
185
184
  this.emit("connected", void 0);
186
185
  this.ws.removeEventListener("message", onFirstMessage);
187
186
  this.ws.addEventListener("message", this.handleMessage);
188
- resolve();
187
+ resolve2();
189
188
  }
190
189
  } catch (_) {
191
190
  }
@@ -257,12 +256,12 @@ var RealtimeWSClient = class extends TypedEmitter {
257
256
  }
258
257
  ping() {
259
258
  const requestId = `ping-${++this.pingCounter}`;
260
- return new Promise((resolve, reject) => {
259
+ return new Promise((resolve2, reject) => {
261
260
  const timer = setTimeout(() => {
262
261
  this.pendingPings.delete(requestId);
263
262
  reject(new Error("Ping timeout"));
264
263
  }, 1e4);
265
- this.pendingPings.set(requestId, { resolve, timer });
264
+ this.pendingPings.set(requestId, { resolve: resolve2, timer });
266
265
  this.sendRaw({ type: "ping", payload: { requestId } });
267
266
  });
268
267
  }
@@ -515,9 +514,9 @@ var WRITE_PATTERNS = [
515
514
  { method: "POST", pattern: /\/api\/im\/community\/posts\/[^/]+\/comments$/, opType: "community_comment" },
516
515
  { method: "POST", pattern: /\/api\/im\/community\/vote$/, opType: "community_vote" }
517
516
  ];
518
- function matchWriteOp(method, path3) {
517
+ function matchWriteOp(method, path4) {
519
518
  for (const { method: m, pattern, opType } of WRITE_PATTERNS) {
520
- if (method === m && pattern.test(path3)) return opType;
519
+ if (method === m && pattern.test(path4)) return opType;
521
520
  }
522
521
  return null;
523
522
  }
@@ -585,18 +584,18 @@ var OfflineManager = class extends OfflineEmitter {
585
584
  /**
586
585
  * Dispatch an IM request. Write ops go through outbox; reads check local cache.
587
586
  */
588
- async dispatch(method, path3, body, query) {
589
- const opType = matchWriteOp(method, path3);
587
+ async dispatch(method, path4, body, query) {
588
+ const opType = matchWriteOp(method, path4);
590
589
  if (opType) {
591
- return this.dispatchWrite(opType, method, path3, body, query);
590
+ return this.dispatchWrite(opType, method, path4, body, query);
592
591
  }
593
592
  if (method === "GET") {
594
- const cached = await this.readFromCache(path3, query);
593
+ const cached = await this.readFromCache(path4, query);
595
594
  if (cached !== null) return cached;
596
595
  }
597
596
  try {
598
- const result = await this.networkRequest(method, path3, body, query);
599
- if (method === "GET") this.cacheReadResult(path3, query, result);
597
+ const result = await this.networkRequest(method, path4, body, query);
598
+ if (method === "GET") this.cacheReadResult(path4, query, result);
600
599
  return result;
601
600
  } catch {
602
601
  if (!this._isOnline) {
@@ -606,7 +605,7 @@ var OfflineManager = class extends OfflineEmitter {
606
605
  }
607
606
  }
608
607
  // ── Outbox: write operations ──────────────────────────────
609
- async dispatchWrite(opType, method, path3, body, query) {
608
+ async dispatchWrite(opType, method, path4, body, query) {
610
609
  const clientId = generateId();
611
610
  const idempotencyKey = `sdk-${clientId}`;
612
611
  let enrichedBody = body;
@@ -620,7 +619,7 @@ var OfflineManager = class extends OfflineEmitter {
620
619
  let localMessage;
621
620
  if (opType === "message.send" && body && typeof body === "object") {
622
621
  const b = body;
623
- const convIdMatch = path3.match(/\/(?:messages|direct|groups)\/([^/]+)/);
622
+ const convIdMatch = path4.match(/\/(?:messages|direct|groups)\/([^/]+)/);
624
623
  const conversationId = convIdMatch?.[1] ?? "";
625
624
  localMessage = {
626
625
  id: `local-${clientId}`,
@@ -641,7 +640,7 @@ var OfflineManager = class extends OfflineEmitter {
641
640
  id: clientId,
642
641
  type: opType,
643
642
  method,
644
- path: path3,
643
+ path: path4,
645
644
  body: enrichedBody,
646
645
  query,
647
646
  status: "pending",
@@ -961,28 +960,28 @@ var OfflineManager = class extends OfflineEmitter {
961
960
  return 0;
962
961
  }
963
962
  // ── Read cache ────────────────────────────────────────────
964
- async readFromCache(path3, query) {
965
- if (/\/api\/im\/conversations$/.test(path3)) {
963
+ async readFromCache(path4, query) {
964
+ if (/\/api\/im\/conversations$/.test(path4)) {
966
965
  const convos = await this.storage.getConversations({ limit: 50 });
967
966
  if (convos.length > 0) return { ok: true, data: convos };
968
967
  }
969
- const msgMatch = path3.match(/\/api\/im\/messages\/([^/]+)$/);
968
+ const msgMatch = path4.match(/\/api\/im\/messages\/([^/]+)$/);
970
969
  if (msgMatch) {
971
970
  const convId = msgMatch[1];
972
971
  const limit = query?.limit ? parseInt(query.limit) : 50;
973
972
  const messages = await this.storage.getMessages(convId, { limit, before: query?.before });
974
973
  if (messages.length > 0) return { ok: true, data: messages };
975
974
  }
976
- if (/\/api\/im\/contacts$/.test(path3)) {
975
+ if (/\/api\/im\/contacts$/.test(path4)) {
977
976
  const contacts = await this.storage.getContacts();
978
977
  if (contacts.length > 0) return { ok: true, data: contacts };
979
978
  }
980
979
  return null;
981
980
  }
982
- async cacheReadResult(path3, _query, result) {
981
+ async cacheReadResult(path4, _query, result) {
983
982
  if (!result?.ok || !result?.data) return;
984
983
  try {
985
- if (/\/api\/im\/conversations$/.test(path3) && Array.isArray(result.data)) {
984
+ if (/\/api\/im\/conversations$/.test(path4) && Array.isArray(result.data)) {
986
985
  const convos = result.data.map((c) => ({
987
986
  id: c.id,
988
987
  type: c.type ?? "direct",
@@ -996,7 +995,7 @@ var OfflineManager = class extends OfflineEmitter {
996
995
  }));
997
996
  await this.storage.putConversations(convos);
998
997
  }
999
- const msgMatch = path3.match(/\/api\/im\/messages\/([^/]+)$/);
998
+ const msgMatch = path4.match(/\/api\/im\/messages\/([^/]+)$/);
1000
999
  if (msgMatch && Array.isArray(result.data)) {
1001
1000
  const messages = result.data.map((m) => ({
1002
1001
  id: m.id,
@@ -1011,7 +1010,7 @@ var OfflineManager = class extends OfflineEmitter {
1011
1010
  }));
1012
1011
  await this.storage.putMessages(messages);
1013
1012
  }
1014
- if (/\/api\/im\/contacts$/.test(path3) && Array.isArray(result.data)) {
1013
+ if (/\/api\/im\/contacts$/.test(path4) && Array.isArray(result.data)) {
1015
1014
  await this.storage.putContacts(result.data);
1016
1015
  }
1017
1016
  } catch {
@@ -1784,7 +1783,8 @@ var DirectClient = class {
1784
1783
  content,
1785
1784
  type: options?.type ?? "text",
1786
1785
  metadata: options?.metadata,
1787
- parentId: options?.parentId
1786
+ parentId: options?.parentId,
1787
+ quotedMessageId: options?.quotedMessageId
1788
1788
  });
1789
1789
  }
1790
1790
  /** Get direct message history with a user */
@@ -1817,7 +1817,8 @@ var GroupsClient = class {
1817
1817
  content,
1818
1818
  type: options?.type ?? "text",
1819
1819
  metadata: options?.metadata,
1820
- parentId: options?.parentId
1820
+ parentId: options?.parentId,
1821
+ quotedMessageId: options?.quotedMessageId
1821
1822
  });
1822
1823
  }
1823
1824
  /** Get group message history */
@@ -1894,7 +1895,8 @@ var MessagesClient = class {
1894
1895
  content,
1895
1896
  type: options?.type ?? "text",
1896
1897
  metadata: options?.metadata,
1897
- parentId: options?.parentId
1898
+ parentId: options?.parentId,
1899
+ quotedMessageId: options?.quotedMessageId
1898
1900
  });
1899
1901
  }
1900
1902
  /** Get message history for a conversation */
@@ -1916,6 +1918,17 @@ var MessagesClient = class {
1916
1918
  async markDelivered(conversationId, messageIds) {
1917
1919
  return this._r("POST", "/api/im/messages/delivered", { conversationId, messageIds });
1918
1920
  }
1921
+ /**
1922
+ * Add or remove an emoji reaction on a message (v1.8.2).
1923
+ * Idempotent — adding an existing reaction or removing a non-existent one is a no-op.
1924
+ * Returns the full reactions snapshot: `{ "👍": ["userId-a", ...], ... }`.
1925
+ */
1926
+ async react(conversationId, messageId, emoji, options) {
1927
+ return this._r("POST", `/api/im/messages/${conversationId}/${messageId}/reactions`, {
1928
+ emoji,
1929
+ ...options?.remove ? { remove: true } : {}
1930
+ });
1931
+ }
1919
1932
  };
1920
1933
  var ContactsClient = class {
1921
1934
  constructor(_r) {
@@ -2111,8 +2124,20 @@ var TasksClient = class {
2111
2124
  return this._r("POST", `/api/im/tasks/${taskId}/complete`, options);
2112
2125
  }
2113
2126
  /** Fail a task with error */
2114
- async fail(taskId, error, metadata) {
2115
- return this._r("POST", `/api/im/tasks/${taskId}/fail`, { error, metadata });
2127
+ async fail(taskId, error2, metadata) {
2128
+ return this._r("POST", `/api/im/tasks/${taskId}/fail`, { error: error2, metadata });
2129
+ }
2130
+ /** Approve a completed task */
2131
+ async approve(taskId) {
2132
+ return this._r("POST", `/api/im/tasks/${taskId}/approve`);
2133
+ }
2134
+ /** Reject a task with reason */
2135
+ async reject(taskId, reason) {
2136
+ return this._r("POST", `/api/im/tasks/${taskId}/reject`, { reason });
2137
+ }
2138
+ /** Cancel a task */
2139
+ async cancel(taskId) {
2140
+ return this._r("DELETE", `/api/im/tasks/${taskId}`);
2116
2141
  }
2117
2142
  };
2118
2143
  var MemoryClient = class {
@@ -2534,30 +2559,30 @@ var EvolutionClient = class {
2534
2559
  }
2535
2560
  const localPaths = [];
2536
2561
  try {
2537
- const fs3 = await import("fs");
2538
- const path3 = await import("path");
2562
+ const fs4 = await import("fs");
2563
+ const path4 = await import("path");
2539
2564
  const os3 = await import("os");
2540
2565
  const home = os3.homedir();
2541
- const pluginBase = process.env.PRISMER_PLUGIN_DIR || path3.join(home, ".claude", "plugins", "prismer");
2566
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path4.join(home, ".claude", "plugins", "prismer");
2542
2567
  const platformPaths = options?.project ? {
2543
- "claude-code": path3.join(options.projectRoot || ".", ".claude", "skills", slug),
2544
- "openclaw": path3.join(options.projectRoot || ".", "skills", slug),
2545
- "opencode": path3.join(options.projectRoot || ".", ".opencode", "skills", slug),
2546
- "plugin": path3.join(options.projectRoot || ".", ".claude", "plugins", "prismer", "skills", slug)
2568
+ "claude-code": path4.join(options.projectRoot || ".", ".claude", "skills", slug),
2569
+ "openclaw": path4.join(options.projectRoot || ".", "skills", slug),
2570
+ "opencode": path4.join(options.projectRoot || ".", ".opencode", "skills", slug),
2571
+ "plugin": path4.join(options.projectRoot || ".", ".claude", "plugins", "prismer", "skills", slug)
2547
2572
  } : {
2548
- "claude-code": path3.join(home, ".claude", "skills", slug),
2549
- "openclaw": path3.join(home, ".openclaw", "skills", slug),
2550
- "opencode": path3.join(home, ".config", "opencode", "skills", slug),
2551
- "plugin": path3.join(pluginBase, "skills", slug)
2573
+ "claude-code": path4.join(home, ".claude", "skills", slug),
2574
+ "openclaw": path4.join(home, ".openclaw", "skills", slug),
2575
+ "opencode": path4.join(home, ".config", "opencode", "skills", slug),
2576
+ "plugin": path4.join(pluginBase, "skills", slug)
2552
2577
  };
2553
2578
  const targets = options?.platforms || Object.keys(platformPaths);
2554
2579
  for (const platform of targets) {
2555
2580
  const dir = platformPaths[platform];
2556
2581
  if (!dir) continue;
2557
2582
  try {
2558
- fs3.mkdirSync(dir, { recursive: true });
2559
- const filePath = path3.join(dir, "SKILL.md");
2560
- fs3.writeFileSync(filePath, content, "utf-8");
2583
+ fs4.mkdirSync(dir, { recursive: true });
2584
+ const filePath = path4.join(dir, "SKILL.md");
2585
+ fs4.writeFileSync(filePath, content, "utf-8");
2561
2586
  localPaths.push(filePath);
2562
2587
  } catch {
2563
2588
  }
@@ -2575,21 +2600,21 @@ var EvolutionClient = class {
2575
2600
  const slug = safeSlug(slugOrId);
2576
2601
  if (!slug) return { ...result, data: { uninstalled: result.data?.uninstalled ?? false, removedPaths } };
2577
2602
  try {
2578
- const fs3 = await import("fs");
2579
- const path3 = await import("path");
2603
+ const fs4 = await import("fs");
2604
+ const path4 = await import("path");
2580
2605
  const os3 = await import("os");
2581
2606
  const home = os3.homedir();
2582
- const pluginBase = process.env.PRISMER_PLUGIN_DIR || path3.join(home, ".claude", "plugins", "prismer");
2607
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path4.join(home, ".claude", "plugins", "prismer");
2583
2608
  const dirs = [
2584
- path3.join(home, ".claude", "skills", slug),
2585
- path3.join(home, ".openclaw", "skills", slug),
2586
- path3.join(home, ".config", "opencode", "skills", slug),
2587
- path3.join(pluginBase, "skills", slug)
2609
+ path4.join(home, ".claude", "skills", slug),
2610
+ path4.join(home, ".openclaw", "skills", slug),
2611
+ path4.join(home, ".config", "opencode", "skills", slug),
2612
+ path4.join(pluginBase, "skills", slug)
2588
2613
  ];
2589
2614
  for (const dir of dirs) {
2590
2615
  try {
2591
- if (fs3.existsSync(dir)) {
2592
- fs3.rmSync(dir, { recursive: true });
2616
+ if (fs4.existsSync(dir)) {
2617
+ fs4.rmSync(dir, { recursive: true });
2593
2618
  removedPaths.push(dir);
2594
2619
  }
2595
2620
  } catch {
@@ -2626,25 +2651,25 @@ var EvolutionClient = class {
2626
2651
  failed++;
2627
2652
  continue;
2628
2653
  }
2629
- const fs3 = await import("fs");
2630
- const path3 = await import("path");
2654
+ const fs4 = await import("fs");
2655
+ const path4 = await import("path");
2631
2656
  const os3 = await import("os");
2632
2657
  const home = os3.homedir();
2633
- const pluginBase = process.env.PRISMER_PLUGIN_DIR || path3.join(home, ".claude", "plugins", "prismer");
2658
+ const pluginBase = process.env.PRISMER_PLUGIN_DIR || path4.join(home, ".claude", "plugins", "prismer");
2634
2659
  const platformPaths = {
2635
- "claude-code": path3.join(home, ".claude", "skills", slug),
2636
- "openclaw": path3.join(home, ".openclaw", "skills", slug),
2637
- "opencode": path3.join(home, ".config", "opencode", "skills", slug),
2638
- "plugin": path3.join(pluginBase, "skills", slug)
2660
+ "claude-code": path4.join(home, ".claude", "skills", slug),
2661
+ "openclaw": path4.join(home, ".openclaw", "skills", slug),
2662
+ "opencode": path4.join(home, ".config", "opencode", "skills", slug),
2663
+ "plugin": path4.join(pluginBase, "skills", slug)
2639
2664
  };
2640
2665
  const targets = options?.platforms || Object.keys(platformPaths);
2641
2666
  for (const platform of targets) {
2642
2667
  const dir = platformPaths[platform];
2643
2668
  if (!dir) continue;
2644
2669
  try {
2645
- fs3.mkdirSync(dir, { recursive: true });
2646
- const filePath = path3.join(dir, "SKILL.md");
2647
- fs3.writeFileSync(filePath, content, "utf-8");
2670
+ fs4.mkdirSync(dir, { recursive: true });
2671
+ const filePath = path4.join(dir, "SKILL.md");
2672
+ fs4.writeFileSync(filePath, content, "utf-8");
2648
2673
  paths.push(filePath);
2649
2674
  } catch {
2650
2675
  }
@@ -2784,11 +2809,11 @@ var FilesClient = class {
2784
2809
  let bytes;
2785
2810
  let fileName;
2786
2811
  if (typeof input === "string") {
2787
- const fs3 = await import("fs");
2788
- const path3 = await import("path");
2789
- const buf = await fs3.promises.readFile(input);
2812
+ const fs4 = await import("fs");
2813
+ const path4 = await import("path");
2814
+ const buf = await fs4.promises.readFile(input);
2790
2815
  bytes = new Uint8Array(buf);
2791
- fileName = opts?.fileName || path3.basename(input);
2816
+ fileName = opts?.fileName || path4.basename(input);
2792
2817
  } else if (typeof Blob !== "undefined" && input instanceof Blob) {
2793
2818
  const ab = await input.arrayBuffer();
2794
2819
  bytes = new Uint8Array(ab);
@@ -3000,20 +3025,20 @@ var PrismerClient = class {
3000
3025
  let imRequest = this._offlineManager ? (m, p, b, q) => this._offlineManager.dispatch(m, p, b, q) : (m, p, b, q) => this._request(m, p, b, q);
3001
3026
  if (config.identity) {
3002
3027
  const baseRequest = imRequest;
3003
- imRequest = (method, path3, body, query) => {
3004
- if (method === "POST" && path3.includes("/messages") && body) {
3028
+ imRequest = (method, path4, body, query) => {
3029
+ if (method === "POST" && path4.includes("/messages") && body) {
3005
3030
  const b = body;
3006
3031
  if (!b.signature && !b.skipSigning) {
3007
3032
  const ready = this._identityReady || Promise.resolve();
3008
3033
  return ready.then(() => {
3009
3034
  if (this._identity) {
3010
- return this._signAndSend(baseRequest, method, path3, b, query);
3035
+ return this._signAndSend(baseRequest, method, path4, b, query);
3011
3036
  }
3012
- return baseRequest(method, path3, body, query);
3037
+ return baseRequest(method, path4, body, query);
3013
3038
  });
3014
3039
  }
3015
3040
  }
3016
- return baseRequest(method, path3, body, query);
3041
+ return baseRequest(method, path4, body, query);
3017
3042
  };
3018
3043
  }
3019
3044
  this.im = new IMClient(
@@ -3031,9 +3056,9 @@ var PrismerClient = class {
3031
3056
  return this._identity;
3032
3057
  }
3033
3058
  /** Auto-sign a message body and send (v1.8.0 S1) */
3034
- async _signAndSend(baseRequest, method, path3, body, query) {
3059
+ async _signAndSend(baseRequest, method, path4, body, query) {
3035
3060
  if (this._identityReady) await this._identityReady;
3036
- if (!this._identity) return baseRequest(method, path3, body, query);
3061
+ if (!this._identity) return baseRequest(method, path4, body, query);
3037
3062
  const content = body.content || "";
3038
3063
  const contentHashBytes = new Uint8Array(
3039
3064
  await crypto.subtle.digest("SHA-256", new TextEncoder().encode(content))
@@ -3043,7 +3068,7 @@ var PrismerClient = class {
3043
3068
  const payload = `1|${this._identity.did}|${body.type || "text"}|${timestamp}|${contentHash}`;
3044
3069
  const payloadBytes = new TextEncoder().encode(payload);
3045
3070
  const signature = await this._identity.sign(payloadBytes);
3046
- return baseRequest(method, path3, {
3071
+ return baseRequest(method, path4, {
3047
3072
  ...body,
3048
3073
  secVersion: 1,
3049
3074
  senderDid: this._identity.did,
@@ -3075,11 +3100,11 @@ var PrismerClient = class {
3075
3100
  // --------------------------------------------------------------------------
3076
3101
  // Internal request helper
3077
3102
  // --------------------------------------------------------------------------
3078
- async _request(method, path3, body, query, _isRetry) {
3103
+ async _request(method, path4, body, query, _isRetry) {
3079
3104
  const controller = new AbortController();
3080
3105
  const timeoutId = setTimeout(() => controller.abort(), this.timeout);
3081
3106
  try {
3082
- let url = `${this.baseUrl}${path3}`;
3107
+ let url = `${this.baseUrl}${path4}`;
3083
3108
  if (query && Object.keys(query).length > 0) {
3084
3109
  url += "?" + new URLSearchParams(query).toString();
3085
3110
  }
@@ -3097,12 +3122,12 @@ var PrismerClient = class {
3097
3122
  }
3098
3123
  const response = await this.fetchFn(url, init);
3099
3124
  const data = await response.json();
3100
- if (response.status === 401 && this.apiKey.startsWith("eyJ") && !_isRetry && !path3.includes("/token/refresh")) {
3125
+ if (response.status === 401 && this.apiKey.startsWith("eyJ") && !_isRetry && !path4.includes("/token/refresh")) {
3101
3126
  try {
3102
3127
  const refreshRes = await this._request("POST", "/api/im/token/refresh", void 0, void 0, true);
3103
3128
  if (refreshRes?.ok && refreshRes?.data?.token) {
3104
3129
  this.apiKey = refreshRes.data.token;
3105
- return this._request(method, path3, body, query, true);
3130
+ return this._request(method, path4, body, query, true);
3106
3131
  }
3107
3132
  } catch {
3108
3133
  }
@@ -3112,14 +3137,14 @@ var PrismerClient = class {
3112
3137
  return { ...data, success: false, ok: false, error: err };
3113
3138
  }
3114
3139
  return data;
3115
- } catch (error) {
3116
- if (error instanceof Error && error.name === "AbortError") {
3140
+ } catch (error2) {
3141
+ if (error2 instanceof Error && error2.name === "AbortError") {
3117
3142
  return { success: false, ok: false, error: { code: "TIMEOUT", message: "Request timed out" } };
3118
3143
  }
3119
3144
  return {
3120
3145
  success: false,
3121
3146
  ok: false,
3122
- error: { code: "NETWORK_ERROR", message: error instanceof Error ? error.message : "Unknown error" }
3147
+ error: { code: "NETWORK_ERROR", message: error2 instanceof Error ? error2.message : "Unknown error" }
3123
3148
  };
3124
3149
  } finally {
3125
3150
  clearTimeout(timeoutId);
@@ -3181,6 +3206,125 @@ var PrismerClient = class {
3181
3206
  }
3182
3207
  };
3183
3208
 
3209
+ // src/ui.ts
3210
+ var pc = __toESM(require("picocolors"));
3211
+ var clack = __toESM(require("@clack/prompts"));
3212
+ var fs = __toESM(require("fs"));
3213
+ var path = __toESM(require("path"));
3214
+ var isTTY = !!process.stdout.isTTY || !!process.env.FORCE_COLOR;
3215
+ function displayBanner() {
3216
+ if (!isTTY) return;
3217
+ let iconPath;
3218
+ try {
3219
+ iconPath = path.resolve(__dirname, "..", "icon");
3220
+ if (!fs.existsSync(iconPath)) {
3221
+ iconPath = path.resolve(__dirname, "..", "..", "icon");
3222
+ }
3223
+ if (!fs.existsSync(iconPath)) return;
3224
+ const raw = fs.readFileSync(iconPath, "utf-8");
3225
+ const lines = raw.split("\n");
3226
+ const termWidth = process.stdout.columns || 80;
3227
+ const colorized = lines.map((line) => {
3228
+ const trimmed = line.trimEnd();
3229
+ if (!trimmed) return "";
3230
+ let result = "";
3231
+ let visibleLen = 0;
3232
+ for (const ch of trimmed) {
3233
+ if (visibleLen >= termWidth - 1) break;
3234
+ if (ch === "\u2592") {
3235
+ result += pc.cyan(ch);
3236
+ } else if (ch === "\u2593") {
3237
+ result += pc.white(ch);
3238
+ } else if (ch === "\u2588") {
3239
+ result += pc.white(ch);
3240
+ } else {
3241
+ result += ch;
3242
+ }
3243
+ visibleLen++;
3244
+ }
3245
+ return result;
3246
+ });
3247
+ while (colorized.length > 0 && colorized[colorized.length - 1].trim() === "") {
3248
+ colorized.pop();
3249
+ }
3250
+ console.log(colorized.join("\n"));
3251
+ console.log();
3252
+ } catch {
3253
+ }
3254
+ }
3255
+ var SYMBOLS = {
3256
+ success: isTTY ? "\u2713" : "[ok]",
3257
+ // ✓
3258
+ error: isTTY ? "\u2717" : "[error]",
3259
+ // ✗
3260
+ warn: isTTY ? "\u26A0" : "[warn]",
3261
+ // ⚠
3262
+ info: isTTY ? "\u2139" : "[info]"
3263
+ // ℹ
3264
+ };
3265
+ function success(msg) {
3266
+ console.log(pc.green(`${SYMBOLS.success} ${msg}`));
3267
+ }
3268
+ function error(msg) {
3269
+ console.error(pc.red(`${SYMBOLS.error} ${msg}`));
3270
+ }
3271
+ function warn(msg) {
3272
+ console.warn(pc.yellow(`${SYMBOLS.warn} ${msg}`));
3273
+ }
3274
+ function info(msg) {
3275
+ console.log(pc.blue(`${SYMBOLS.info} ${msg}`));
3276
+ }
3277
+ function dim2(msg) {
3278
+ console.log(pc.dim(msg));
3279
+ }
3280
+ async function withSpinner(message, fn) {
3281
+ if (!isTTY) {
3282
+ return fn();
3283
+ }
3284
+ const s = clack.spinner();
3285
+ s.start(message);
3286
+ try {
3287
+ const result = await fn();
3288
+ s.stop(pc.green(`${SYMBOLS.success} ${message}`));
3289
+ return result;
3290
+ } catch (err) {
3291
+ s.stop(pc.red(`${SYMBOLS.error} ${message}`));
3292
+ throw err;
3293
+ }
3294
+ }
3295
+ function table(headers, rows) {
3296
+ if (headers.length === 0) return;
3297
+ const widths = headers.map((h, i) => {
3298
+ const dataMax = rows.reduce((max, row) => Math.max(max, (row[i] || "").length), 0);
3299
+ return Math.max(h.length, dataMax);
3300
+ });
3301
+ const PAD = 2;
3302
+ const headerLine = headers.map((h, i) => h.padEnd(widths[i] + PAD)).join("");
3303
+ if (isTTY) {
3304
+ console.log(pc.bold(headerLine));
3305
+ const separator = widths.map((w) => "\u2500".repeat(w)).join(" ");
3306
+ console.log(pc.dim(separator));
3307
+ } else {
3308
+ console.log(headerLine);
3309
+ const separator = widths.map((w) => "-".repeat(w)).join(" ");
3310
+ console.log(separator);
3311
+ }
3312
+ for (const row of rows) {
3313
+ const line = headers.map((_, i) => (row[i] || "").padEnd(widths[i] + PAD)).join("");
3314
+ console.log(line);
3315
+ }
3316
+ }
3317
+ function keyValue(pairs) {
3318
+ const keys = Object.keys(pairs);
3319
+ if (keys.length === 0) return;
3320
+ const maxKeyLen = keys.reduce((max, k) => Math.max(max, k.length), 0);
3321
+ for (const key of keys) {
3322
+ const label = isTTY ? pc.bold(key.padEnd(maxKeyLen)) : key.padEnd(maxKeyLen);
3323
+ const value = pairs[key];
3324
+ console.log(` ${label} ${value}`);
3325
+ }
3326
+ }
3327
+
3184
3328
  // src/commands/im.ts
3185
3329
  function register(parent, getIMClient2, _getAPIClient) {
3186
3330
  const im = parent.command("im").description("IM messaging, groups, conversations, and credits");
@@ -3877,7 +4021,7 @@ function register3(parent, getIMClient2, _getAPIClient) {
3877
4021
  const maxIterations = 30;
3878
4022
  let lastStatus;
3879
4023
  for (let i = 0; i < maxIterations; i++) {
3880
- await new Promise((resolve) => setTimeout(resolve, 2e3));
4024
+ await new Promise((resolve2) => setTimeout(resolve2, 2e3));
3881
4025
  if (!opts.json) process.stdout.write(".");
3882
4026
  const statusRes = await client.im.evolution.getReportStatus(traceId);
3883
4027
  if (!statusRes.ok) break;
@@ -4262,14 +4406,13 @@ function register3(parent, getIMClient2, _getAPIClient) {
4262
4406
  // src/commands/task.ts
4263
4407
  function register4(parent, getIMClient2, _getAPIClient) {
4264
4408
  const task = parent.command("task").description("Manage tasks in the task marketplace");
4265
- 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) => {
4409
+ task.command("create").description("Create a new task").requiredOption("--title <title>", "task title").option("--description <description>", "task description").option("--capability <capability>", "required agent capability").option("--budget <budget>", "budget in credits", parseFloat).option("--json", "output raw JSON response").action(async (opts) => {
4266
4410
  const client = getIMClient2();
4267
4411
  try {
4268
4412
  const res = await client.im.tasks.create({
4269
4413
  title: opts.title,
4270
4414
  description: opts.description,
4271
- priority: opts.priority,
4272
- requiredCapability: opts.capability,
4415
+ capability: opts.capability,
4273
4416
  budget: opts.budget
4274
4417
  });
4275
4418
  if (opts.json) {
@@ -4290,12 +4433,10 @@ function register4(parent, getIMClient2, _getAPIClient) {
4290
4433
  process.stdout.write(`Title: ${t.title}
4291
4434
  `);
4292
4435
  process.stdout.write(`Status: ${t.status}
4293
- `);
4294
- process.stdout.write(`Priority: ${t.priority}
4295
4436
  `);
4296
4437
  if (t.description) process.stdout.write(`Description: ${t.description}
4297
4438
  `);
4298
- if (t.requiredCapability) process.stdout.write(`Capability: ${t.requiredCapability}
4439
+ if (t.capability) process.stdout.write(`Capability: ${t.capability}
4299
4440
  `);
4300
4441
  if (t.budget !== void 0) process.stdout.write(`Budget: ${t.budget}
4301
4442
  `);
@@ -4329,17 +4470,16 @@ function register4(parent, getIMClient2, _getAPIClient) {
4329
4470
  return;
4330
4471
  }
4331
4472
  const idW = 24;
4332
- const statusW = 10;
4333
- const priorityW = 10;
4473
+ const statusW = 12;
4334
4474
  const titleW = 40;
4335
- const header = "ID".padEnd(idW) + "STATUS".padEnd(statusW) + "PRIORITY".padEnd(priorityW) + "TITLE";
4336
- const sep = "-".repeat(idW + statusW + priorityW + titleW);
4475
+ const header = "ID".padEnd(idW) + "STATUS".padEnd(statusW) + "TITLE";
4476
+ const sep = "-".repeat(idW + statusW + titleW);
4337
4477
  process.stdout.write(header + "\n");
4338
4478
  process.stdout.write(sep + "\n");
4339
4479
  for (const t of tasks) {
4340
4480
  const title = t.title.length > titleW ? t.title.slice(0, titleW - 3) + "..." : t.title;
4341
4481
  process.stdout.write(
4342
- String(t.id).padEnd(idW) + String(t.status).padEnd(statusW) + String(t.priority).padEnd(priorityW) + title + "\n"
4482
+ String(t.id).padEnd(idW) + String(t.status).padEnd(statusW) + title + "\n"
4343
4483
  );
4344
4484
  }
4345
4485
  process.stdout.write(`
@@ -4371,14 +4511,16 @@ ${tasks.length} task(s) listed.
4371
4511
  process.stdout.write(`Title: ${t.title}
4372
4512
  `);
4373
4513
  process.stdout.write(`Status: ${t.status}
4374
- `);
4375
- process.stdout.write(`Priority: ${t.priority}
4376
4514
  `);
4377
4515
  if (t.description) process.stdout.write(`Description: ${t.description}
4378
4516
  `);
4379
- if (t.requiredCapability) process.stdout.write(`Capability: ${t.requiredCapability}
4517
+ if (t.capability) process.stdout.write(`Capability: ${t.capability}
4380
4518
  `);
4381
4519
  if (t.budget !== void 0) process.stdout.write(`Budget: ${t.budget}
4520
+ `);
4521
+ if (t.progress != null) process.stdout.write(`Progress: ${t.progress}
4522
+ `);
4523
+ if (t.statusMessage) process.stdout.write(`Status Msg: ${t.statusMessage}
4382
4524
  `);
4383
4525
  if (t.creatorId) process.stdout.write(`Creator: ${t.creatorId}
4384
4526
  `);
@@ -4387,6 +4529,8 @@ ${tasks.length} task(s) listed.
4387
4529
  if (t.createdAt) process.stdout.write(`Created: ${t.createdAt}
4388
4530
  `);
4389
4531
  if (t.updatedAt) process.stdout.write(`Updated: ${t.updatedAt}
4532
+ `);
4533
+ if (t.completedAt) process.stdout.write(`Completed: ${t.completedAt}
4390
4534
  `);
4391
4535
  if (t.result) process.stdout.write(`Result: ${t.result}
4392
4536
  `);
@@ -4433,8 +4577,6 @@ Logs (${logs.length}):
4433
4577
  process.stdout.write(`Title: ${t.title}
4434
4578
  `);
4435
4579
  process.stdout.write(`Status: ${t.status}
4436
- `);
4437
- process.stdout.write(`Priority: ${t.priority}
4438
4580
  `);
4439
4581
  } catch (err) {
4440
4582
  const message = err instanceof Error ? err.message : String(err);
@@ -4443,13 +4585,15 @@ Logs (${logs.length}):
4443
4585
  process.exit(1);
4444
4586
  }
4445
4587
  });
4446
- 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) => {
4588
+ task.command("update <task-id>").description("Update a task").option("--title <title>", "new title").option("--description <description>", "new description").option("--status <status>", "new status").option("--progress <progress>", "progress (0.0 to 1.0)", parseFloat).option("--status-message <statusMessage>", "status message").option("--json", "output raw JSON response").action(async (taskId, opts) => {
4447
4589
  const client = getIMClient2();
4448
4590
  try {
4449
4591
  const res = await client.im.tasks.update(taskId, {
4450
4592
  title: opts.title,
4451
4593
  description: opts.description,
4452
- priority: opts.priority
4594
+ status: opts.status,
4595
+ progress: opts.progress,
4596
+ statusMessage: opts.statusMessage
4453
4597
  });
4454
4598
  if (opts.json) {
4455
4599
  process.stdout.write(JSON.stringify(res, null, 2) + "\n");
@@ -4470,7 +4614,9 @@ Logs (${logs.length}):
4470
4614
  `);
4471
4615
  process.stdout.write(`Status: ${t.status}
4472
4616
  `);
4473
- process.stdout.write(`Priority: ${t.priority}
4617
+ if (t.progress != null) process.stdout.write(`Progress: ${t.progress}
4618
+ `);
4619
+ if (t.statusMessage) process.stdout.write(`Message: ${t.statusMessage}
4474
4620
  `);
4475
4621
  } catch (err) {
4476
4622
  const message = err instanceof Error ? err.message : String(err);
@@ -4541,6 +4687,96 @@ Logs (${logs.length}):
4541
4687
  } catch (err) {
4542
4688
  const message = err instanceof Error ? err.message : String(err);
4543
4689
  process.stderr.write(`Error: ${message}
4690
+ `);
4691
+ process.exit(1);
4692
+ }
4693
+ });
4694
+ task.command("approve <task-id>").description("Approve a completed task").option("--json", "output raw JSON response").action(async (taskId, opts) => {
4695
+ const client = getIMClient2();
4696
+ try {
4697
+ const res = await client.im.tasks.approve(taskId);
4698
+ if (opts.json) {
4699
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
4700
+ return;
4701
+ }
4702
+ if (!res.ok) {
4703
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
4704
+ `);
4705
+ process.exit(1);
4706
+ }
4707
+ const t = res.data;
4708
+ process.stdout.write(`Task approved successfully
4709
+
4710
+ `);
4711
+ process.stdout.write(`ID: ${t.id}
4712
+ `);
4713
+ process.stdout.write(`Title: ${t.title}
4714
+ `);
4715
+ process.stdout.write(`Status: ${t.status}
4716
+ `);
4717
+ } catch (err) {
4718
+ const message = err instanceof Error ? err.message : String(err);
4719
+ process.stderr.write(`Error: ${message}
4720
+ `);
4721
+ process.exit(1);
4722
+ }
4723
+ });
4724
+ task.command("reject <task-id>").description("Reject a task").requiredOption("--reason <reason>", "reason for rejection").option("--json", "output raw JSON response").action(async (taskId, opts) => {
4725
+ const client = getIMClient2();
4726
+ try {
4727
+ const res = await client.im.tasks.reject(taskId, opts.reason);
4728
+ if (opts.json) {
4729
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
4730
+ return;
4731
+ }
4732
+ if (!res.ok) {
4733
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
4734
+ `);
4735
+ process.exit(1);
4736
+ }
4737
+ const t = res.data;
4738
+ process.stdout.write(`Task rejected
4739
+
4740
+ `);
4741
+ process.stdout.write(`ID: ${t.id}
4742
+ `);
4743
+ process.stdout.write(`Title: ${t.title}
4744
+ `);
4745
+ process.stdout.write(`Status: ${t.status}
4746
+ `);
4747
+ } catch (err) {
4748
+ const message = err instanceof Error ? err.message : String(err);
4749
+ process.stderr.write(`Error: ${message}
4750
+ `);
4751
+ process.exit(1);
4752
+ }
4753
+ });
4754
+ task.command("cancel <task-id>").description("Cancel a task").option("--json", "output raw JSON response").action(async (taskId, opts) => {
4755
+ const client = getIMClient2();
4756
+ try {
4757
+ const res = await client.im.tasks.cancel(taskId);
4758
+ if (opts.json) {
4759
+ process.stdout.write(JSON.stringify(res, null, 2) + "\n");
4760
+ return;
4761
+ }
4762
+ if (!res.ok) {
4763
+ process.stderr.write(`Error: ${res.error?.message || "Unknown error"}
4764
+ `);
4765
+ process.exit(1);
4766
+ }
4767
+ const t = res.data;
4768
+ process.stdout.write(`Task cancelled
4769
+
4770
+ `);
4771
+ process.stdout.write(`ID: ${t.id}
4772
+ `);
4773
+ process.stdout.write(`Title: ${t.title}
4774
+ `);
4775
+ process.stdout.write(`Status: ${t.status}
4776
+ `);
4777
+ } catch (err) {
4778
+ const message = err instanceof Error ? err.message : String(err);
4779
+ process.stderr.write(`Error: ${message}
4544
4780
  `);
4545
4781
  process.exit(1);
4546
4782
  }
@@ -4774,7 +5010,7 @@ function printFileTable(files) {
4774
5010
  const idLen = Math.max(2, ...files.map((f) => f.id.length));
4775
5011
  const scopeLen = Math.max(5, ...files.map((f) => f.scope.length));
4776
5012
  const pathLen = Math.max(4, ...files.map((f) => f.path.length));
4777
- const row = (id, scope, path3) => `${id.padEnd(idLen)} ${scope.padEnd(scopeLen)} ${path3.padEnd(pathLen)}`;
5013
+ const row = (id, scope, path4) => `${id.padEnd(idLen)} ${scope.padEnd(scopeLen)} ${path4.padEnd(pathLen)}`;
4778
5014
  process.stdout.write(row("ID", "SCOPE", "PATH") + "\n");
4779
5015
  process.stdout.write(`${"-".repeat(idLen)} ${"-".repeat(scopeLen)} ${"-".repeat(pathLen)}
4780
5016
  `);
@@ -5144,11 +5380,11 @@ function register8(parent, getIMClient2, _getAPIClient) {
5144
5380
  try {
5145
5381
  const capabilities = opts.agentCapabilities ? opts.agentCapabilities.split(",").map((s) => s.trim()) : void 0;
5146
5382
  const res = await client.im.workspace.init({
5147
- name,
5383
+ workspaceId: name,
5148
5384
  userId: opts.userId,
5149
- userName: opts.userName,
5150
- agentId: opts.agentId,
5151
- agentName: opts.agentName,
5385
+ userDisplayName: opts.userName,
5386
+ agentName: opts.agentId,
5387
+ agentDisplayName: opts.agentName,
5152
5388
  agentType: opts.agentType,
5153
5389
  ...capabilities !== void 0 && { agentCapabilities: capabilities }
5154
5390
  });
@@ -5172,14 +5408,16 @@ function register8(parent, getIMClient2, _getAPIClient) {
5172
5408
  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) => {
5173
5409
  const client = getIMClient2();
5174
5410
  try {
5175
- let members;
5411
+ let users;
5176
5412
  try {
5177
- members = JSON.parse(opts.members);
5413
+ const parsed = JSON.parse(opts.members);
5414
+ if (!Array.isArray(parsed)) throw new Error("not an array");
5415
+ users = parsed;
5178
5416
  } catch {
5179
- process.stderr.write("Error: --members must be a valid JSON array\n");
5417
+ process.stderr.write("Error: --members must be a valid JSON array of {userId, displayName}\n");
5180
5418
  process.exit(1);
5181
5419
  }
5182
- const res = await client.im.workspace.initGroup({ name, members });
5420
+ const res = await client.im.workspace.initGroup({ workspaceId: name, title: name, users });
5183
5421
  if (!res.ok) {
5184
5422
  process.stderr.write(`Error: ${res.error?.message || JSON.stringify(res.error)}
5185
5423
  `);
@@ -5660,8 +5898,8 @@ function register10(parent, getIMClient2, _getAPIClient) {
5660
5898
  }
5661
5899
 
5662
5900
  // src/daemon.ts
5663
- var fs = __toESM(require("fs"));
5664
- var path = __toESM(require("path"));
5901
+ var fs2 = __toESM(require("fs"));
5902
+ var path2 = __toESM(require("path"));
5665
5903
  var import_path = require("path");
5666
5904
  var os = __toESM(require("os"));
5667
5905
  var import_os = require("os");
@@ -5669,22 +5907,22 @@ var http = __toESM(require("http"));
5669
5907
  var import_http = require("http");
5670
5908
  var import_child_process = require("child_process");
5671
5909
  var TOML = __toESM(require("@iarna/toml"));
5672
- var CONFIG_DIR = path.join(os.homedir(), ".prismer");
5673
- var CONFIG_PATH = path.join(CONFIG_DIR, "config.toml");
5674
- var PID_PATH = path.join(CONFIG_DIR, "daemon.pid");
5675
- var PORT_PATH = path.join(CONFIG_DIR, "daemon.port");
5676
- var CACHE_DIR = path.join(CONFIG_DIR, "cache");
5677
- var EVOLUTION_CACHE_PATH = path.join(CACHE_DIR, "evolution.json");
5678
- var OUTBOX_PATH = path.join(CACHE_DIR, "outbox.json");
5910
+ var CONFIG_DIR = path2.join(os.homedir(), ".prismer");
5911
+ var CONFIG_PATH = path2.join(CONFIG_DIR, "config.toml");
5912
+ var PID_PATH = path2.join(CONFIG_DIR, "daemon.pid");
5913
+ var PORT_PATH = path2.join(CONFIG_DIR, "daemon.port");
5914
+ var CACHE_DIR = path2.join(CONFIG_DIR, "cache");
5915
+ var EVOLUTION_CACHE_PATH = path2.join(CACHE_DIR, "evolution.json");
5916
+ var OUTBOX_PATH = path2.join(CACHE_DIR, "outbox.json");
5679
5917
  var SYNC_INTERVAL_MS = 6e4;
5680
5918
  var FLUSH_INTERVAL_MS = 3e4;
5681
5919
  var API_TIMEOUT_MS = 1e4;
5682
5920
  var EVENTS_FILE = (0, import_path.join)(CACHE_DIR, "events.json");
5683
5921
  var MAX_EVENTS = 1e3;
5684
5922
  function loadConfig() {
5685
- if (!fs.existsSync(CONFIG_PATH)) return null;
5923
+ if (!fs2.existsSync(CONFIG_PATH)) return null;
5686
5924
  try {
5687
- const raw = fs.readFileSync(CONFIG_PATH, "utf-8");
5925
+ const raw = fs2.readFileSync(CONFIG_PATH, "utf-8");
5688
5926
  const parsed = TOML.parse(raw);
5689
5927
  const apiKey = parsed?.default?.api_key || "";
5690
5928
  const baseUrl = parsed?.default?.base_url || "https://prismer.cloud";
@@ -5695,13 +5933,13 @@ function loadConfig() {
5695
5933
  }
5696
5934
  }
5697
5935
  function ensureCacheDir() {
5698
- if (!fs.existsSync(CACHE_DIR)) {
5699
- fs.mkdirSync(CACHE_DIR, { recursive: true });
5936
+ if (!fs2.existsSync(CACHE_DIR)) {
5937
+ fs2.mkdirSync(CACHE_DIR, { recursive: true });
5700
5938
  }
5701
5939
  }
5702
5940
  function loadEvents() {
5703
5941
  try {
5704
- return JSON.parse(fs.readFileSync(EVENTS_FILE, "utf-8"));
5942
+ return JSON.parse(fs2.readFileSync(EVENTS_FILE, "utf-8"));
5705
5943
  } catch {
5706
5944
  return [];
5707
5945
  }
@@ -5710,7 +5948,7 @@ function appendEvent(event) {
5710
5948
  const events = loadEvents();
5711
5949
  events.push(event);
5712
5950
  if (events.length > MAX_EVENTS) events.splice(0, events.length - MAX_EVENTS);
5713
- fs.writeFileSync(EVENTS_FILE, JSON.stringify(events), { encoding: "utf-8", mode: 384 });
5951
+ fs2.writeFileSync(EVENTS_FILE, JSON.stringify(events), { encoding: "utf-8", mode: 384 });
5714
5952
  }
5715
5953
  function emitSyncEvent(genesCount) {
5716
5954
  if (genesCount > 0) {
@@ -5725,9 +5963,9 @@ function emitSyncEvent(genesCount) {
5725
5963
  }
5726
5964
  }
5727
5965
  function readPid() {
5728
- if (!fs.existsSync(PID_PATH)) return null;
5966
+ if (!fs2.existsSync(PID_PATH)) return null;
5729
5967
  try {
5730
- const raw = fs.readFileSync(PID_PATH, "utf-8").trim();
5968
+ const raw = fs2.readFileSync(PID_PATH, "utf-8").trim();
5731
5969
  const pid = parseInt(raw, 10);
5732
5970
  return isNaN(pid) ? null : pid;
5733
5971
  } catch {
@@ -5735,9 +5973,9 @@ function readPid() {
5735
5973
  }
5736
5974
  }
5737
5975
  function readPort() {
5738
- if (!fs.existsSync(PORT_PATH)) return null;
5976
+ if (!fs2.existsSync(PORT_PATH)) return null;
5739
5977
  try {
5740
- const raw = fs.readFileSync(PORT_PATH, "utf-8").trim();
5978
+ const raw = fs2.readFileSync(PORT_PATH, "utf-8").trim();
5741
5979
  const port = parseInt(raw, 10);
5742
5980
  return isNaN(port) ? null : port;
5743
5981
  } catch {
@@ -5754,24 +5992,24 @@ function isProcessRunning(pid) {
5754
5992
  }
5755
5993
  function writePid(pid) {
5756
5994
  ensureCacheDir();
5757
- if (!fs.existsSync(CONFIG_DIR)) {
5758
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
5995
+ if (!fs2.existsSync(CONFIG_DIR)) {
5996
+ fs2.mkdirSync(CONFIG_DIR, { recursive: true });
5759
5997
  }
5760
- fs.writeFileSync(PID_PATH, String(pid), { encoding: "utf-8", mode: 384 });
5998
+ fs2.writeFileSync(PID_PATH, String(pid), { encoding: "utf-8", mode: 384 });
5761
5999
  }
5762
6000
  function writePort(port) {
5763
- if (!fs.existsSync(CONFIG_DIR)) {
5764
- fs.mkdirSync(CONFIG_DIR, { recursive: true });
6001
+ if (!fs2.existsSync(CONFIG_DIR)) {
6002
+ fs2.mkdirSync(CONFIG_DIR, { recursive: true });
5765
6003
  }
5766
- fs.writeFileSync(PORT_PATH, String(port), { encoding: "utf-8", mode: 384 });
6004
+ fs2.writeFileSync(PORT_PATH, String(port), { encoding: "utf-8", mode: 384 });
5767
6005
  }
5768
6006
  function cleanupPidFiles() {
5769
6007
  try {
5770
- if (fs.existsSync(PID_PATH)) fs.unlinkSync(PID_PATH);
6008
+ if (fs2.existsSync(PID_PATH)) fs2.unlinkSync(PID_PATH);
5771
6009
  } catch {
5772
6010
  }
5773
6011
  try {
5774
- if (fs.existsSync(PORT_PATH)) fs.unlinkSync(PORT_PATH);
6012
+ if (fs2.existsSync(PORT_PATH)) fs2.unlinkSync(PORT_PATH);
5775
6013
  } catch {
5776
6014
  }
5777
6015
  }
@@ -5794,9 +6032,9 @@ async function runDaemonProcess() {
5794
6032
  let lastSync = 0;
5795
6033
  let syncCount = 0;
5796
6034
  let evolutionCursor = 0;
5797
- if (fs.existsSync(EVOLUTION_CACHE_PATH)) {
6035
+ if (fs2.existsSync(EVOLUTION_CACHE_PATH)) {
5798
6036
  try {
5799
- const cached = JSON.parse(fs.readFileSync(EVOLUTION_CACHE_PATH, "utf-8"));
6037
+ const cached = JSON.parse(fs2.readFileSync(EVOLUTION_CACHE_PATH, "utf-8"));
5800
6038
  if (typeof cached?.cursor === "number") evolutionCursor = cached.cursor;
5801
6039
  } catch {
5802
6040
  }
@@ -5804,9 +6042,9 @@ async function runDaemonProcess() {
5804
6042
  const server = (0, import_http.createServer)((req, res) => {
5805
6043
  if (req.method === "GET" && req.url === "/health") {
5806
6044
  let outboxSize = 0;
5807
- if (fs.existsSync(OUTBOX_PATH)) {
6045
+ if (fs2.existsSync(OUTBOX_PATH)) {
5808
6046
  try {
5809
- const entries = JSON.parse(fs.readFileSync(OUTBOX_PATH, "utf-8"));
6047
+ const entries = JSON.parse(fs2.readFileSync(OUTBOX_PATH, "utf-8"));
5810
6048
  if (Array.isArray(entries)) outboxSize = entries.length;
5811
6049
  } catch {
5812
6050
  }
@@ -5869,7 +6107,7 @@ async function runDaemonProcess() {
5869
6107
  }
5870
6108
  ensureCacheDir();
5871
6109
  const pulled = data?.data || data;
5872
- fs.writeFileSync(
6110
+ fs2.writeFileSync(
5873
6111
  EVOLUTION_CACHE_PATH,
5874
6112
  JSON.stringify({ cursor: evolutionCursor, lastSync, data: pulled }, null, 2),
5875
6113
  { encoding: "utf-8", mode: 384 }
@@ -5880,10 +6118,10 @@ async function runDaemonProcess() {
5880
6118
  }
5881
6119
  };
5882
6120
  const doOutboxFlush = async () => {
5883
- if (!fs.existsSync(OUTBOX_PATH)) return;
6121
+ if (!fs2.existsSync(OUTBOX_PATH)) return;
5884
6122
  let entries = [];
5885
6123
  try {
5886
- entries = JSON.parse(fs.readFileSync(OUTBOX_PATH, "utf-8"));
6124
+ entries = JSON.parse(fs2.readFileSync(OUTBOX_PATH, "utf-8"));
5887
6125
  if (!Array.isArray(entries) || entries.length === 0) return;
5888
6126
  } catch {
5889
6127
  return;
@@ -5904,7 +6142,7 @@ async function runDaemonProcess() {
5904
6142
  }
5905
6143
  );
5906
6144
  if (res.ok) {
5907
- fs.writeFileSync(OUTBOX_PATH, "[]", { encoding: "utf-8", mode: 384 });
6145
+ fs2.writeFileSync(OUTBOX_PATH, "[]", { encoding: "utf-8", mode: 384 });
5908
6146
  }
5909
6147
  } catch {
5910
6148
  }
@@ -6022,7 +6260,7 @@ function resolveNpxPath() {
6022
6260
  } catch {
6023
6261
  for (const p of ["/usr/local/bin/npx", "/opt/homebrew/bin/npx", `${(0, import_os.homedir)()}/.nvm/current/bin/npx`]) {
6024
6262
  try {
6025
- fs.accessSync(p);
6263
+ fs2.accessSync(p);
6026
6264
  return p;
6027
6265
  } catch {
6028
6266
  }
@@ -6064,8 +6302,8 @@ function installLaunchd() {
6064
6302
  <string>${(0, import_path.join)((0, import_os.homedir)(), ".prismer", "daemon.stderr.log")}</string>
6065
6303
  </dict>
6066
6304
  </plist>`;
6067
- fs.mkdirSync((0, import_path.dirname)(plistPath), { recursive: true });
6068
- fs.writeFileSync(plistPath, plist, { mode: 384 });
6305
+ fs2.mkdirSync((0, import_path.dirname)(plistPath), { recursive: true });
6306
+ fs2.writeFileSync(plistPath, plist, { mode: 384 });
6069
6307
  try {
6070
6308
  (0, import_child_process.execSync)(`launchctl load ${plistPath}`, { stdio: "pipe" });
6071
6309
  console.log("[prismer] Daemon service installed and started (launchd)");
@@ -6081,7 +6319,7 @@ function uninstallLaunchd() {
6081
6319
  } catch {
6082
6320
  }
6083
6321
  try {
6084
- fs.unlinkSync(plistPath);
6322
+ fs2.unlinkSync(plistPath);
6085
6323
  } catch {
6086
6324
  }
6087
6325
  console.log("[prismer] Daemon service uninstalled (launchd)");
@@ -6106,8 +6344,8 @@ RestartSec=10
6106
6344
  [Install]
6107
6345
  WantedBy=default.target
6108
6346
  `;
6109
- fs.mkdirSync(serviceDir, { recursive: true });
6110
- fs.writeFileSync(servicePath, unit, { mode: 420 });
6347
+ fs2.mkdirSync(serviceDir, { recursive: true });
6348
+ fs2.writeFileSync(servicePath, unit, { mode: 420 });
6111
6349
  try {
6112
6350
  (0, import_child_process.execSync)("systemctl --user daemon-reload", { stdio: "pipe" });
6113
6351
  (0, import_child_process.execSync)("systemctl --user enable prismer-daemon", { stdio: "pipe" });
@@ -6130,7 +6368,7 @@ function uninstallSystemd() {
6130
6368
  }
6131
6369
  const servicePath = (0, import_path.join)((0, import_os.homedir)(), ".config", "systemd", "user", "prismer-daemon.service");
6132
6370
  try {
6133
- fs.unlinkSync(servicePath);
6371
+ fs2.unlinkSync(servicePath);
6134
6372
  } catch {
6135
6373
  }
6136
6374
  try {
@@ -6170,26 +6408,26 @@ if (process.env["PRISMER_DAEMON"] === "1") {
6170
6408
  // src/cli.ts
6171
6409
  var cliVersion = "1.7.2";
6172
6410
  try {
6173
- const pkgPath = path2.join(__dirname, "..", "package.json");
6174
- const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
6411
+ const pkgPath = path3.join(__dirname, "..", "package.json");
6412
+ const pkg = JSON.parse(fs3.readFileSync(pkgPath, "utf8"));
6175
6413
  cliVersion = pkg.version || cliVersion;
6176
6414
  } catch {
6177
6415
  }
6178
- var CONFIG_DIR2 = path2.join(os2.homedir(), ".prismer");
6179
- var CONFIG_PATH2 = path2.join(CONFIG_DIR2, "config.toml");
6416
+ var CONFIG_DIR2 = path3.join(os2.homedir(), ".prismer");
6417
+ var CONFIG_PATH2 = path3.join(CONFIG_DIR2, "config.toml");
6180
6418
  function ensureConfigDir() {
6181
- if (!fs2.existsSync(CONFIG_DIR2)) {
6182
- fs2.mkdirSync(CONFIG_DIR2, { recursive: true });
6419
+ if (!fs3.existsSync(CONFIG_DIR2)) {
6420
+ fs3.mkdirSync(CONFIG_DIR2, { recursive: true });
6183
6421
  }
6184
6422
  }
6185
6423
  function readConfig() {
6186
- if (!fs2.existsSync(CONFIG_PATH2)) return {};
6187
- const raw = fs2.readFileSync(CONFIG_PATH2, "utf-8");
6424
+ if (!fs3.existsSync(CONFIG_PATH2)) return {};
6425
+ const raw = fs3.readFileSync(CONFIG_PATH2, "utf-8");
6188
6426
  return TOML2.parse(raw);
6189
6427
  }
6190
6428
  function writeConfig(config) {
6191
6429
  ensureConfigDir();
6192
- fs2.writeFileSync(CONFIG_PATH2, TOML2.stringify(config), { encoding: "utf-8", mode: 384 });
6430
+ fs3.writeFileSync(CONFIG_PATH2, TOML2.stringify(config), { encoding: "utf-8", mode: 384 });
6193
6431
  }
6194
6432
  function setNestedValue(obj, dotPath, value) {
6195
6433
  const parts = dotPath.split(".");
@@ -6205,7 +6443,7 @@ function getIMClient() {
6205
6443
  const cfg = readConfig();
6206
6444
  const token = cfg?.auth?.im_token;
6207
6445
  if (!token) {
6208
- console.error('No IM token. Run "prismer setup --agent" or "prismer register <username>" first.');
6446
+ error('No IM token. Run "prismer setup --agent" or "prismer register <username>" first.');
6209
6447
  process.exit(1);
6210
6448
  }
6211
6449
  const env = cfg?.default?.environment || "production";
@@ -6216,7 +6454,7 @@ function getAPIClient() {
6216
6454
  const cfg = readConfig();
6217
6455
  const apiKey = cfg?.default?.api_key;
6218
6456
  if (!apiKey) {
6219
- console.error('No API key. Run "prismer setup" to sign in and get your key.');
6457
+ error('No API key. Run "prismer setup" to sign in and get your key.');
6220
6458
  process.exit(1);
6221
6459
  }
6222
6460
  const env = cfg?.default?.environment || "production";
@@ -6227,12 +6465,12 @@ var program = new import_commander.Command();
6227
6465
  program.name("prismer").description("Prismer Cloud SDK CLI").version(cliVersion);
6228
6466
  async function verifyAndSaveKey(config, apiKey) {
6229
6467
  if (!apiKey) {
6230
- console.error("No key provided.");
6468
+ error("No key provided.");
6231
6469
  process.exit(1);
6232
6470
  }
6233
6471
  if (!apiKey.startsWith("sk-prismer-")) {
6234
- console.error("Invalid key format. API keys start with sk-prismer-");
6235
- console.error("Get your key at: https://prismer.cloud/setup");
6472
+ error("Invalid key format. API keys start with sk-prismer-");
6473
+ dim2(" Get your key at: https://prismer.cloud/setup");
6236
6474
  process.exit(1);
6237
6475
  }
6238
6476
  const baseUrl = config.default?.base_url || "https://prismer.cloud";
@@ -6241,25 +6479,25 @@ async function verifyAndSaveKey(config, apiKey) {
6241
6479
  headers: { Authorization: `Bearer ${apiKey}` }
6242
6480
  });
6243
6481
  if (res.status === 401) {
6244
- console.error("API key is invalid or expired.");
6245
- console.error("Get a new key at: https://prismer.cloud/setup");
6482
+ error("API key is invalid or expired.");
6483
+ dim2(" Get a new key at: https://prismer.cloud/setup");
6246
6484
  process.exit(1);
6247
6485
  }
6248
- console.log("API key verified \u2713");
6486
+ success("API key verified");
6249
6487
  } catch (err) {
6250
- console.warn(`Could not verify key (${err.message}). Saving anyway.`);
6488
+ warn(`Could not verify key (${err.message}). Saving anyway.`);
6251
6489
  }
6252
6490
  if (!config.default) config.default = {};
6253
6491
  config.default.api_key = apiKey;
6254
6492
  if (!config.default.environment) config.default.environment = "production";
6255
6493
  writeConfig(config);
6256
6494
  console.log("");
6257
- console.log("Saved to ~/.prismer/config.toml");
6258
- console.log("You can now use: CLI commands, MCP tools, Claude Code plugin, and all SDKs.");
6495
+ success("Saved to ~/.prismer/config.toml");
6496
+ info("You can now use: CLI commands, MCP tools, Claude Code plugin, and all SDKs.");
6259
6497
  try {
6260
6498
  installDaemonService();
6261
6499
  } catch {
6262
- console.log("Daemon auto-start setup skipped. Run manually: prismer daemon install");
6500
+ dim2("Daemon auto-start setup skipped. Run manually: prismer daemon install");
6263
6501
  }
6264
6502
  }
6265
6503
  function openBrowser(url) {
@@ -6284,10 +6522,10 @@ async function runSetup(opts, apiKey) {
6284
6522
  const baseUrl = config.default.base_url || "https://prismer.cloud";
6285
6523
  if (!opts.force && config.default.api_key?.startsWith("sk-prismer-")) {
6286
6524
  const masked = config.default.api_key.slice(0, 12) + "..." + config.default.api_key.slice(-4);
6287
- console.log(`Already configured: ${masked}`);
6525
+ success(`Already configured: ${masked}`);
6288
6526
  console.log("");
6289
- console.log("To reconfigure, run: prismer setup --force");
6290
- console.log("To check status: prismer status");
6527
+ dim2(" To reconfigure, run: prismer setup --force");
6528
+ dim2(" To check status: prismer status");
6291
6529
  return;
6292
6530
  }
6293
6531
  if (apiKey) {
@@ -6296,8 +6534,8 @@ async function runSetup(opts, apiKey) {
6296
6534
  }
6297
6535
  if (opts.agent) {
6298
6536
  if (!opts.force && config.auth?.im_token) {
6299
- console.log("Already registered as agent (IM token exists).");
6300
- console.log("For API key access, run: prismer setup");
6537
+ success("Already registered as agent (IM token exists).");
6538
+ dim2(" For API key access, run: prismer setup");
6301
6539
  return;
6302
6540
  }
6303
6541
  const username = `agent-${Date.now().toString(36)}`;
@@ -6314,32 +6552,34 @@ async function runSetup(opts, apiKey) {
6314
6552
  config.auth.im_user_id = data.data?.imUserId || data.data?.userId;
6315
6553
  config.auth.im_username = data.data?.username || username;
6316
6554
  writeConfig(config);
6317
- console.log("Agent registered with free credits \u2713");
6318
- console.log(` Username: ${config.auth.im_username}`);
6319
- console.log(` User ID: ${config.auth.im_user_id}`);
6555
+ success("Agent registered with free credits");
6556
+ keyValue({
6557
+ "Username": config.auth.im_username || "",
6558
+ "User ID": config.auth.im_user_id || ""
6559
+ });
6320
6560
  console.log("");
6321
- console.log("For full API access, sign in: prismer setup");
6561
+ info("For full API access, sign in: prismer setup");
6322
6562
  } catch (err) {
6323
- console.error(`Agent registration failed: ${err.message}`);
6324
- console.error("Try signing in instead: prismer setup");
6563
+ error(`Agent registration failed: ${err.message}`);
6564
+ dim2(" Try signing in instead: prismer setup");
6325
6565
  process.exit(1);
6326
6566
  }
6327
6567
  return;
6328
6568
  }
6329
6569
  if (opts.manual) {
6330
6570
  const setupUrl = `${baseUrl}/setup?utm_source=cli&utm_medium=manual`;
6331
- console.log("Opening browser to sign in...");
6332
- console.log(` ${setupUrl}`);
6571
+ info("Opening browser to sign in...");
6572
+ dim2(` ${setupUrl}`);
6333
6573
  console.log("");
6334
6574
  openBrowser(setupUrl);
6335
- console.log("After signing in, copy the API key from the page and paste it below.");
6575
+ info("After signing in, copy the API key from the page and paste it below.");
6336
6576
  console.log("");
6337
6577
  const readline = require("readline");
6338
6578
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
6339
6579
  rl.question("Paste your API key: ", (key) => {
6340
6580
  rl.close();
6341
6581
  verifyAndSaveKey(config, key.trim()).catch((err) => {
6342
- console.error(`Setup failed: ${err.message}`);
6582
+ error(`Setup failed: ${err.message}`);
6343
6583
  process.exit(1);
6344
6584
  });
6345
6585
  });
@@ -6382,20 +6622,20 @@ async function runSetup(opts, apiKey) {
6382
6622
  const port = server.address().port;
6383
6623
  const callbackUrl = `http://127.0.0.1:${port}/callback`;
6384
6624
  const setupUrl = `${baseUrl}/setup?callback=${encodeURIComponent(callbackUrl)}&state=${state}&utm_source=cli&utm_medium=auto`;
6385
- console.log("Opening browser to sign in...");
6625
+ info("Opening browser to sign in...");
6386
6626
  console.log("");
6387
6627
  openBrowser(setupUrl);
6388
- console.log("Waiting for authentication...");
6389
- console.log("(If the browser didn't open, visit this URL manually:)");
6390
- console.log(` ${setupUrl}`);
6628
+ info("Waiting for authentication...");
6629
+ dim2(" (If the browser didn't open, visit this URL manually:)");
6630
+ dim2(` ${setupUrl}`);
6391
6631
  console.log("");
6392
6632
  setTimeout(() => {
6393
6633
  if (!resolved) {
6394
- console.error("Timed out waiting for authentication (5 min).");
6395
- console.error("");
6396
- console.error("Alternatives:");
6397
- console.error(" prismer setup --manual Paste key manually");
6398
- console.error(" prismer setup --agent Register as agent (free credits, no browser)");
6634
+ error("Timed out waiting for authentication (5 min).");
6635
+ console.log("");
6636
+ dim2(" Alternatives:");
6637
+ dim2(" prismer setup --manual Paste key manually");
6638
+ dim2(" prismer setup --agent Register as agent (free credits, no browser)");
6399
6639
  server.close();
6400
6640
  process.exit(1);
6401
6641
  }
@@ -6406,7 +6646,7 @@ program.command("setup [api-key]").description("Set up Prismer \u2014 sign in vi
6406
6646
  await runSetup(opts, apiKey);
6407
6647
  });
6408
6648
  program.command("init [api-key]").description('Alias for "prismer setup" (deprecated, use setup instead)').option("--manual", "Paste API key manually").option("--agent", "Register as agent with free credits").option("--force", "Reconfigure even if already set up").action(async (apiKey, opts) => {
6409
- console.log('Note: "prismer init" is deprecated. Use "prismer setup" instead.');
6649
+ warn('"prismer init" is deprecated. Use "prismer setup" instead.');
6410
6650
  console.log("");
6411
6651
  await runSetup(opts, apiKey);
6412
6652
  });
@@ -6414,7 +6654,7 @@ program.command("register <username>").description("Register an IM identity and
6414
6654
  const config = readConfig();
6415
6655
  const apiKey = config.default?.api_key;
6416
6656
  if (!apiKey) {
6417
- console.error('No API key. Run "prismer setup" first.');
6657
+ error('No API key. Run "prismer setup" first.');
6418
6658
  process.exit(1);
6419
6659
  }
6420
6660
  const client = new PrismerClient({
@@ -6434,7 +6674,7 @@ program.command("register <username>").description("Register an IM identity and
6434
6674
  try {
6435
6675
  const result = await client.im.account.register(registerOpts);
6436
6676
  if (!result.ok || !result.data) {
6437
- console.error("Registration failed:", result.error?.message || "Unknown error");
6677
+ error(`Registration failed: ${result.error?.message || "Unknown error"}`);
6438
6678
  process.exit(1);
6439
6679
  }
6440
6680
  const data = result.data;
@@ -6444,84 +6684,89 @@ program.command("register <username>").description("Register an IM identity and
6444
6684
  config.auth.im_username = data.username;
6445
6685
  config.auth.im_token_expires = data.expiresIn;
6446
6686
  writeConfig(config);
6447
- console.log("Registration successful!");
6448
- console.log(` User ID: ${data.imUserId}`);
6449
- console.log(` Username: ${data.username}`);
6450
- console.log(` Display: ${data.displayName}`);
6451
- console.log(` Role: ${data.role}`);
6452
- console.log(` New: ${data.isNew}`);
6453
- console.log("Token stored in ~/.prismer/config.toml");
6687
+ success("Registration successful!");
6688
+ keyValue({
6689
+ "User ID": data.imUserId,
6690
+ "Username": data.username,
6691
+ "Display": data.displayName,
6692
+ "Role": data.role,
6693
+ "New": String(data.isNew)
6694
+ });
6695
+ dim2(" Token stored in ~/.prismer/config.toml");
6454
6696
  } catch (err) {
6455
- console.error("Registration failed:", err instanceof Error ? err.message : err);
6697
+ error(`Registration failed: ${err instanceof Error ? err.message : String(err)}`);
6456
6698
  process.exit(1);
6457
6699
  }
6458
6700
  });
6459
6701
  program.command("status").description("Show current config and live info").action(async () => {
6460
6702
  const config = readConfig();
6461
- console.log("=== Prismer Status ===\n");
6703
+ info("Prismer Status");
6704
+ console.log("");
6462
6705
  const apiKey = config.default?.api_key;
6463
- if (apiKey) {
6464
- const masked = apiKey.length > 16 ? apiKey.slice(0, 12) + "..." + apiKey.slice(-4) : "***";
6465
- console.log(`API Key: ${masked}`);
6466
- } else {
6467
- console.log("API Key: (not set)");
6468
- }
6469
- console.log(`Environment: ${config.default?.environment || "(not set)"}`);
6470
- console.log(`Base URL: ${config.default?.base_url || "(default)"}
6471
- `);
6706
+ const maskedKey = apiKey ? apiKey.length > 16 ? apiKey.slice(0, 12) + "..." + apiKey.slice(-4) : "***" : "(not set)";
6707
+ keyValue({
6708
+ "API Key": maskedKey,
6709
+ "Environment": config.default?.environment || "(not set)",
6710
+ "Base URL": config.default?.base_url || "(default)"
6711
+ });
6712
+ console.log("");
6472
6713
  const token = config.auth?.im_token;
6473
6714
  if (token) {
6474
- console.log(`IM User ID: ${config.auth?.im_user_id || "(unknown)"}`);
6475
- console.log(`IM Username: ${config.auth?.im_username || "(unknown)"}`);
6715
+ let tokenStatus = "set (expiry unknown)";
6476
6716
  const expires = config.auth?.im_token_expires;
6477
6717
  if (expires) {
6478
6718
  const expiresDate = new Date(expires);
6479
6719
  if (!isNaN(expiresDate.getTime())) {
6480
- const label = expiresDate <= /* @__PURE__ */ new Date() ? "EXPIRED" : "valid";
6481
- console.log(`IM Token: ${label} (expires ${expiresDate.toISOString()})`);
6720
+ tokenStatus = expiresDate <= /* @__PURE__ */ new Date() ? "EXPIRED" : `valid (expires ${expiresDate.toISOString()})`;
6482
6721
  } else {
6483
- console.log(`IM Token: set (expires in ${expires})`);
6722
+ tokenStatus = `set (expires in ${expires})`;
6484
6723
  }
6485
- } else {
6486
- console.log("IM Token: set (expiry unknown)");
6487
6724
  }
6488
- console.log("\n--- Live Info ---");
6489
- try {
6725
+ keyValue({
6726
+ "IM User ID": config.auth?.im_user_id || "(unknown)",
6727
+ "IM Username": config.auth?.im_username || "(unknown)",
6728
+ "IM Token": tokenStatus
6729
+ });
6730
+ console.log("");
6731
+ const me = await withSpinner("Fetching live info", async () => {
6490
6732
  const client = new PrismerClient({
6491
6733
  apiKey: token,
6492
6734
  environment: config.default?.environment || "production",
6493
6735
  baseUrl: config.default?.base_url || void 0
6494
6736
  });
6495
- const me = await client.im.account.me();
6496
- if (me.ok && me.data) {
6497
- console.log(`Display: ${me.data.user.displayName}`);
6498
- console.log(`Role: ${me.data.user.role}`);
6499
- console.log(`Credits: ${me.data.credits.balance}`);
6500
- console.log(`Messages: ${me.data.stats.messagesSent}`);
6501
- console.log(`Unread: ${me.data.stats.unreadCount}`);
6502
- } else {
6503
- console.log(`Could not fetch live info: ${me.error?.message || "unknown error"}`);
6504
- }
6505
- } catch (err) {
6506
- console.log(`Could not fetch live info: ${err instanceof Error ? err.message : err}`);
6737
+ return client.im.account.me();
6738
+ }).catch((err) => {
6739
+ warn(`Could not fetch live info: ${err instanceof Error ? err.message : String(err)}`);
6740
+ return null;
6741
+ });
6742
+ if (me && me.ok && me.data) {
6743
+ keyValue({
6744
+ "Display": me.data.user.displayName,
6745
+ "Role": me.data.user.role,
6746
+ "Credits": String(me.data.credits.balance),
6747
+ "Messages": String(me.data.stats.messagesSent),
6748
+ "Unread": String(me.data.stats.unreadCount)
6749
+ });
6750
+ } else if (me) {
6751
+ warn(`Could not fetch live info: ${me.error?.message || "unknown error"}`);
6507
6752
  }
6508
6753
  } else {
6509
- console.log("IM Token: (not registered)");
6754
+ dim2(" IM Token: (not registered)");
6510
6755
  }
6511
6756
  });
6512
6757
  var configCmd = program.command("config").description("Manage config file");
6513
6758
  configCmd.command("show").description("Print config file").action(() => {
6514
- if (!fs2.existsSync(CONFIG_PATH2)) {
6515
- console.log('No config file. Run "prismer setup" to create one.');
6759
+ if (!fs3.existsSync(CONFIG_PATH2)) {
6760
+ warn('No config file. Run "prismer setup" to create one.');
6516
6761
  return;
6517
6762
  }
6518
- console.log(fs2.readFileSync(CONFIG_PATH2, "utf-8"));
6763
+ console.log(fs3.readFileSync(CONFIG_PATH2, "utf-8"));
6519
6764
  });
6520
6765
  configCmd.command("set <key> <value>").description("Set a config value (e.g. default.base_url)").action((key, value) => {
6521
6766
  const config = readConfig();
6522
6767
  setNestedValue(config, key, value);
6523
6768
  writeConfig(config);
6524
- console.log(`Set ${key} = ${value}`);
6769
+ success(`Set ${key} = ${value}`);
6525
6770
  });
6526
6771
  var tokenCmd = program.command("token").description("Token management");
6527
6772
  tokenCmd.command("refresh").description("Refresh IM JWT token").option("--json", "JSON output").action(async (opts) => {
@@ -6532,7 +6777,7 @@ tokenCmd.command("refresh").description("Refresh IM JWT token").option("--json",
6532
6777
  return;
6533
6778
  }
6534
6779
  if (!res.ok) {
6535
- console.error("Error:", res.error);
6780
+ error(`Token refresh failed: ${JSON.stringify(res.error)}`);
6536
6781
  process.exit(1);
6537
6782
  }
6538
6783
  const data = res.data;
@@ -6542,9 +6787,9 @@ tokenCmd.command("refresh").description("Refresh IM JWT token").option("--json",
6542
6787
  config.auth.im_token = data.token;
6543
6788
  if (data.expiresIn) config.auth.im_token_expires = data.expiresIn;
6544
6789
  writeConfig(config);
6545
- console.log("Token refreshed and saved.");
6790
+ success("Token refreshed and saved.");
6546
6791
  } else {
6547
- console.log("Token refreshed (no new token in response).");
6792
+ info("Token refreshed (no new token in response).");
6548
6793
  }
6549
6794
  });
6550
6795
  register(program, getIMClient, getAPIClient);
@@ -6562,35 +6807,41 @@ program.command("send").description("Send a direct message (shortcut for: im sen
6562
6807
  const sendOpts = {};
6563
6808
  if (opts.type && opts.type !== "text") sendOpts.type = opts.type;
6564
6809
  if (opts.replyTo) sendOpts.parentId = opts.replyTo;
6565
- const res = await client.im.direct.send(userId, message, sendOpts);
6810
+ const res = await withSpinner("Sending message", async () => {
6811
+ return client.im.direct.send(userId, message, sendOpts);
6812
+ });
6566
6813
  if (opts.json) {
6567
6814
  console.log(JSON.stringify(res, null, 2));
6568
6815
  return;
6569
6816
  }
6570
6817
  if (!res.ok) {
6571
- console.error("Error:", res.error);
6818
+ error(`Send failed: ${JSON.stringify(res.error)}`);
6572
6819
  process.exit(1);
6573
6820
  }
6574
- console.log(`Message sent (conversation: ${res.data?.conversationId})`);
6821
+ success(`Message sent (conversation: ${res.data?.conversationId})`);
6575
6822
  });
6576
6823
  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) => {
6577
6824
  const client = getAPIClient();
6578
6825
  const input = urls.length === 1 ? urls[0] : urls;
6579
6826
  const loadOpts = {};
6580
6827
  if (opts.format) loadOpts.return = { format: opts.format };
6581
- const res = await client.load(input, loadOpts);
6828
+ const res = await withSpinner(`Loading ${urls.length} URL(s)`, async () => {
6829
+ return client.load(input, loadOpts);
6830
+ });
6582
6831
  if (opts.json) {
6583
6832
  console.log(JSON.stringify(res, null, 2));
6584
6833
  return;
6585
6834
  }
6586
6835
  if (!res.success) {
6587
- console.error("Error:", res.error?.message || "Load failed");
6836
+ error(res.error?.message || "Load failed");
6588
6837
  process.exit(1);
6589
6838
  }
6590
6839
  const results = res.results || (res.result ? [res.result] : []);
6591
6840
  for (const r of results) {
6592
- console.log(`URL: ${r.url || "?"}`);
6593
- console.log(`Status: ${r.cached ? "cached" : "loaded"}`);
6841
+ keyValue({
6842
+ "URL": r.url || "?",
6843
+ "Status": r.cached ? "cached" : "loaded"
6844
+ });
6594
6845
  if (r.hqcc) console.log(`
6595
6846
  --- HQCC ---
6596
6847
  ${r.hqcc.substring(0, 2e3)}`);
@@ -6602,44 +6853,58 @@ ${r.raw.substring(0, 2e3)}`);
6602
6853
  });
6603
6854
  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) => {
6604
6855
  const client = getAPIClient();
6605
- const res = await client.search(query, { topK: parseInt(opts.topK || "5") });
6856
+ const res = await withSpinner(`Searching: ${query}`, async () => {
6857
+ return client.search(query, { topK: parseInt(opts.topK || "5") });
6858
+ });
6606
6859
  if (opts.json) {
6607
6860
  console.log(JSON.stringify(res, null, 2));
6608
6861
  return;
6609
6862
  }
6610
6863
  if (!res.success) {
6611
- console.error("Error:", res.error?.message || "Search failed");
6864
+ error(res.error?.message || "Search failed");
6612
6865
  process.exit(1);
6613
6866
  }
6614
6867
  const results = res.results || [];
6615
6868
  if (results.length === 0) {
6616
- console.log("No results.");
6869
+ warn("No results.");
6617
6870
  return;
6618
6871
  }
6872
+ const rows = results.map((r, i) => [
6873
+ String(i + 1),
6874
+ r.url || "(no url)",
6875
+ String(r.ranking?.score ?? "-")
6876
+ ]);
6877
+ table(["#", "URL", "Score"], rows);
6619
6878
  for (let i = 0; i < results.length; i++) {
6620
6879
  const r = results[i];
6621
- console.log(`${i + 1}. ${r.url || "(no url)"} score: ${r.ranking?.score ?? "-"}`);
6622
- if (r.hqcc) console.log(` ${r.hqcc.substring(0, 200)}`);
6880
+ if (r.hqcc) {
6881
+ console.log("");
6882
+ dim2(` ${i + 1}. ${r.hqcc.substring(0, 200)}`);
6883
+ }
6623
6884
  }
6624
6885
  });
6625
6886
  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) => {
6626
6887
  const client = getAPIClient();
6627
- const res = await client.parsePdf(url, opts.mode);
6888
+ const res = await withSpinner(`Parsing: ${url}`, async () => {
6889
+ return client.parsePdf(url, opts.mode);
6890
+ });
6628
6891
  if (opts.json) {
6629
6892
  console.log(JSON.stringify(res, null, 2));
6630
6893
  return;
6631
6894
  }
6632
6895
  if (!res.success) {
6633
- console.error("Error:", res.error?.message || "Parse failed");
6896
+ error(res.error?.message || "Parse failed");
6634
6897
  process.exit(1);
6635
6898
  }
6636
6899
  if (res.taskId) {
6637
- console.log(`Task ID: ${res.taskId}`);
6638
- console.log(`Status: ${res.status || "processing"}`);
6639
- console.log(`
6640
- Check: prismer parse status ${res.taskId}`);
6900
+ keyValue({
6901
+ "Task ID": res.taskId,
6902
+ "Status": res.status || "processing"
6903
+ });
6904
+ console.log("");
6905
+ dim2(` Check: prismer parse-status ${res.taskId}`);
6641
6906
  } else if (res.document) {
6642
- console.log("Status: complete");
6907
+ success("Parse complete");
6643
6908
  const content = res.document.markdown || res.document.text || JSON.stringify(res.document, null, 2);
6644
6909
  console.log(content.substring(0, 5e3));
6645
6910
  }
@@ -6654,8 +6919,10 @@ program.command("parse-status").description("Check parse task status").argument(
6654
6919
  console.log(JSON.stringify(res, null, 2));
6655
6920
  return;
6656
6921
  }
6657
- console.log(`Task: ${taskId}`);
6658
- console.log(`Status: ${res.status || (res.success ? "complete" : "unknown")}`);
6922
+ keyValue({
6923
+ "Task": taskId,
6924
+ "Status": res.status || (res.success ? "complete" : "unknown")
6925
+ });
6659
6926
  });
6660
6927
  program.command("parse-result").description("Get parse result").argument("<task-id>", "Task ID").option("--json", "JSON output").action(async (taskId, opts) => {
6661
6928
  const client = getAPIClient();
@@ -6665,9 +6932,10 @@ program.command("parse-result").description("Get parse result").argument("<task-
6665
6932
  return;
6666
6933
  }
6667
6934
  if (!res.success) {
6668
- console.error("Error:", res.error?.message || "Not ready");
6935
+ error(res.error?.message || "Not ready");
6669
6936
  process.exit(1);
6670
6937
  }
6938
+ success("Parse result ready");
6671
6939
  const content = res.document?.markdown || res.document?.text || JSON.stringify(res.document, null, 2);
6672
6940
  console.log(content);
6673
6941
  });
@@ -6676,23 +6944,32 @@ program.command("recall").description("Search across memory, cache, and evolutio
6676
6944
  const params = { q: query };
6677
6945
  if (opts.scope) params.scope = opts.scope;
6678
6946
  if (opts.limit) params.limit = opts.limit;
6679
- const res = await client.im.memory._r("GET", "/api/im/recall", void 0, params);
6947
+ const res = await withSpinner(`Recalling: ${query}`, async () => {
6948
+ return client.im.memory._r("GET", "/api/im/recall", void 0, params);
6949
+ });
6680
6950
  if (opts.json) {
6681
6951
  console.log(JSON.stringify(res, null, 2));
6682
6952
  return;
6683
6953
  }
6684
6954
  if (!res.ok) {
6685
- console.error("Error:", res.error);
6955
+ error(`Recall failed: ${JSON.stringify(res.error)}`);
6686
6956
  process.exit(1);
6687
6957
  }
6688
6958
  const data = res.data || [];
6689
6959
  if (data.length === 0) {
6690
- console.log(`No results for "${query}".`);
6960
+ warn(`No results for "${query}".`);
6691
6961
  return;
6692
6962
  }
6963
+ const rows = data.map((item) => [
6964
+ (item.source || "").toUpperCase(),
6965
+ item.title || "?",
6966
+ (item.score || 0).toFixed(2)
6967
+ ]);
6968
+ table(["Source", "Title", "Score"], rows);
6693
6969
  for (const item of data) {
6694
- console.log(`[${(item.source || "").toUpperCase()}] ${item.title || "?"} (score: ${(item.score || 0).toFixed(2)})`);
6695
- if (item.snippet) console.log(` ${item.snippet.substring(0, 200)}`);
6970
+ if (item.snippet) {
6971
+ dim2(` ${item.snippet.substring(0, 200)}`);
6972
+ }
6696
6973
  }
6697
6974
  });
6698
6975
  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) => {
@@ -6700,24 +6977,29 @@ program.command("discover").description("Discover available agents (shortcut for
6700
6977
  const discoverOpts = {};
6701
6978
  if (opts.type) discoverOpts.type = opts.type;
6702
6979
  if (opts.capability) discoverOpts.capability = opts.capability;
6703
- const res = await client.im.contacts.discover(discoverOpts);
6980
+ const res = await withSpinner("Discovering agents", async () => {
6981
+ return client.im.contacts.discover(discoverOpts);
6982
+ });
6704
6983
  if (opts.json) {
6705
6984
  console.log(JSON.stringify(res, null, 2));
6706
6985
  return;
6707
6986
  }
6708
6987
  if (!res.ok) {
6709
- console.error("Error:", res.error);
6988
+ error(`Discovery failed: ${JSON.stringify(res.error)}`);
6710
6989
  process.exit(1);
6711
6990
  }
6712
6991
  const agents = res.data || [];
6713
6992
  if (agents.length === 0) {
6714
- console.log("No agents found.");
6993
+ warn("No agents found.");
6715
6994
  return;
6716
6995
  }
6717
- console.log("Username".padEnd(20) + "Type".padEnd(14) + "Status".padEnd(10) + "Display Name");
6718
- for (const a of agents) {
6719
- console.log(`${(a.username || "").padEnd(20)}${(a.agentType || "").padEnd(14)}${(a.status || "").padEnd(10)}${a.displayName || ""}`);
6720
- }
6996
+ const rows = agents.map((a) => [
6997
+ a.username || "",
6998
+ a.agentType || "",
6999
+ a.status || "",
7000
+ a.displayName || ""
7001
+ ]);
7002
+ table(["Username", "Type", "Status", "Display Name"], rows);
6721
7003
  });
6722
7004
  program.command("daemon <action>").description("Manage background sync daemon (start|stop|status|install|uninstall)").action(async (action) => {
6723
7005
  switch (action) {
@@ -6737,13 +7019,17 @@ program.command("daemon <action>").description("Manage background sync daemon (s
6737
7019
  uninstallDaemonService();
6738
7020
  break;
6739
7021
  default:
6740
- console.error(`Unknown daemon action: ${action}. Use: start, stop, status, install, uninstall`);
7022
+ error(`Unknown daemon action: ${action}. Use: start, stop, status, install, uninstall`);
6741
7023
  process.exit(1);
6742
7024
  }
6743
7025
  });
7026
+ displayBanner();
6744
7027
  program.parse(process.argv);
6745
7028
  // Annotate the CommonJS export names for ESM import in node:
6746
7029
  0 && (module.exports = {
6747
7030
  getAPIClient,
6748
7031
  getIMClient
6749
7032
  });
7033
+ ,
7034
+ getIMClient
7035
+ });