@pmate/cli 0.20.11 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -158,7 +158,15 @@ function loadExistingSessionStoreOrEmpty() {
158
158
  sessions: {}
159
159
  };
160
160
  }
161
- return loadSessionStore();
161
+ try {
162
+ return loadSessionStore();
163
+ } catch {
164
+ return {
165
+ version: SESSION_STORE_VERSION,
166
+ activeAppRef: DEFAULT_APP_ID,
167
+ sessions: {}
168
+ };
169
+ }
162
170
  }
163
171
  function loadSessionStoreWithPath() {
164
172
  const sessionPath = buildSessionStorePath();
@@ -12651,16 +12659,23 @@ function readSessionToken() {
12651
12659
  preferredApp: DEFAULT_APP_ID
12652
12660
  }).token;
12653
12661
  }
12654
- function unwrapAgentResult(value) {
12662
+ function unwrapAgentResult(agentId, value) {
12655
12663
  if (!value || typeof value !== "object") {
12664
+ if (value == null) {
12665
+ throw new Error(`Agent ${agentId} returned no result`);
12666
+ }
12656
12667
  return value;
12657
12668
  }
12658
12669
  if ("content" in value && "type" in value) {
12659
- return value.content ?? null;
12670
+ const content = value.content;
12671
+ if (content == null) {
12672
+ throw new Error(`Agent ${agentId} returned empty envelope content`);
12673
+ }
12674
+ return content;
12660
12675
  }
12661
12676
  return value;
12662
12677
  }
12663
- var import_agent_sdk, DEFAULT_AGENT_API_BASE_URL, DEFAULT_AGENT_HUB_BASE_URL, DEFAULT_NAMESPACE, DEFAULT_FROM, AgentLlmClient;
12678
+ var import_agent_sdk, DEFAULT_AGENT_API_BASE_URL, DEFAULT_AGENT_HUB_BASE_URL, DEFAULT_NAMESPACE, DEFAULT_FROM, DEFAULT_AGENT_PROMPT_TIMEOUT_MS, AgentLlmClient;
12664
12679
  var init_AgentLlmClient = __esm({
12665
12680
  "src/llm/AgentLlmClient.ts"() {
12666
12681
  "use strict";
@@ -12670,6 +12685,7 @@ var init_AgentLlmClient = __esm({
12670
12685
  DEFAULT_AGENT_HUB_BASE_URL = "https://hub.pmate.chat";
12671
12686
  DEFAULT_NAMESPACE = "pmate-cli";
12672
12687
  DEFAULT_FROM = "pmate-cli";
12688
+ DEFAULT_AGENT_PROMPT_TIMEOUT_MS = 12e4;
12673
12689
  AgentLlmClient = class {
12674
12690
  constructor(options) {
12675
12691
  this.token = options?.token ?? readSessionToken();
@@ -12688,7 +12704,8 @@ var init_AgentLlmClient = __esm({
12688
12704
  async call(agentId, payload, options) {
12689
12705
  const client = new import_agent_sdk.AgentClient({
12690
12706
  baseUrl: options?.hubBaseUrl ?? this.hubBaseUrl,
12691
- agentService: this.agentService
12707
+ agentService: this.agentService,
12708
+ timeoutMs: DEFAULT_AGENT_PROMPT_TIMEOUT_MS
12692
12709
  });
12693
12710
  try {
12694
12711
  await client.login(options?.from ?? this.from, {
@@ -12698,7 +12715,7 @@ var init_AgentLlmClient = __esm({
12698
12715
  agentId,
12699
12716
  payload
12700
12717
  });
12701
- return unwrapAgentResult(result);
12718
+ return unwrapAgentResult(agentId, result);
12702
12719
  } finally {
12703
12720
  client.close();
12704
12721
  }
@@ -12713,8 +12730,8 @@ __export(index_exports, {
12713
12730
  parseCommandArgs: () => parseCommandArgs
12714
12731
  });
12715
12732
  module.exports = __toCommonJS(index_exports);
12716
- var import_node_fs16 = require("fs");
12717
- var import_node_path21 = __toESM(require("path"));
12733
+ var import_node_fs17 = require("fs");
12734
+ var import_node_path22 = __toESM(require("path"));
12718
12735
  var import_chalk4 = __toESM(require("chalk"));
12719
12736
 
12720
12737
  // src/cli.ts
@@ -17613,9 +17630,9 @@ ${indent}\`\`\``;
17613
17630
  static richTextToPlain(richText) {
17614
17631
  return richText.map((item) => item.plain_text ?? item.text?.content ?? "").join("").trim();
17615
17632
  }
17616
- static async requestJson(path22, init) {
17633
+ static async requestJson(path23, init) {
17617
17634
  const token = this.getToken();
17618
- const response = await fetch(`${this.baseUrl}${path22}`, {
17635
+ const response = await fetch(`${this.baseUrl}${path23}`, {
17619
17636
  method: init.method,
17620
17637
  headers: {
17621
17638
  Authorization: `Bearer ${token}`,
@@ -18652,15 +18669,72 @@ var QuizCommandHandler = class {
18652
18669
 
18653
18670
  // src/commands/CollectCommandHandler.ts
18654
18671
  var import_playwright = require("playwright");
18672
+ var import_node_crypto4 = require("crypto");
18673
+ var import_node_fs11 = require("fs");
18674
+ var import_node_os6 = __toESM(require("os"));
18675
+ var import_node_path16 = __toESM(require("path"));
18676
+
18677
+ // src/collectStore.ts
18655
18678
  var import_node_crypto3 = require("crypto");
18656
18679
  var import_node_fs10 = require("fs");
18657
18680
  var import_node_os5 = __toESM(require("os"));
18658
18681
  var import_node_path15 = __toESM(require("path"));
18682
+ function resolveCollectTarget(input) {
18683
+ const endpoint = input.endpoint ?? (input.source === "cc" ? "http://localhost:9223" : "http://localhost:9222");
18684
+ const sourceKey = input.source ?? `endpoint-${(0, import_node_crypto3.createHash)("sha1").update(endpoint).digest("hex").slice(0, 8)}`;
18685
+ const rootDir = import_node_path15.default.join(import_node_os5.default.homedir(), ".pmate", "collect", sourceKey);
18686
+ return { sourceKey, endpoint, rootDir };
18687
+ }
18688
+ function toThreadKey(name) {
18689
+ const normalized = name.trim().toLowerCase().replace(/[^a-z0-9\u4e00-\u9fff]+/g, "-").replace(/^-+|-+$/g, "");
18690
+ const base = normalized || "thread";
18691
+ const suffix = (0, import_node_crypto3.createHash)("sha1").update(name).digest("hex").slice(0, 8);
18692
+ return `${base}-${suffix}`;
18693
+ }
18694
+ async function readStoredThread(rootDir, threadKey) {
18695
+ const filePath = getThreadFilePath(rootDir, threadKey);
18696
+ try {
18697
+ const raw = await import_node_fs10.promises.readFile(filePath, "utf8");
18698
+ return JSON.parse(raw);
18699
+ } catch {
18700
+ return null;
18701
+ }
18702
+ }
18703
+ async function writeStoredThread(rootDir, thread) {
18704
+ const filePath = getThreadFilePath(rootDir, thread.threadKey);
18705
+ await import_node_fs10.promises.mkdir(import_node_path15.default.dirname(filePath), { recursive: true });
18706
+ await import_node_fs10.promises.writeFile(filePath, JSON.stringify(thread, null, 2) + "\n", "utf8");
18707
+ }
18708
+ async function writeStoredIndex(rootDir, index) {
18709
+ await import_node_fs10.promises.mkdir(rootDir, { recursive: true });
18710
+ const filePath = import_node_path15.default.join(rootDir, "index.json");
18711
+ await import_node_fs10.promises.writeFile(filePath, JSON.stringify(index, null, 2) + "\n", "utf8");
18712
+ }
18713
+ function mergeMessages(existing, incoming) {
18714
+ const seen = new Set(existing.map((message) => message.hash));
18715
+ const merged = [...existing];
18716
+ let added = 0;
18717
+ for (const message of incoming) {
18718
+ if (seen.has(message.hash)) {
18719
+ continue;
18720
+ }
18721
+ seen.add(message.hash);
18722
+ merged.push(message);
18723
+ added += 1;
18724
+ }
18725
+ return { messages: merged, added };
18726
+ }
18727
+ function getThreadFilePath(rootDir, threadKey) {
18728
+ return import_node_path15.default.join(rootDir, "threads", `${threadKey}.json`);
18729
+ }
18730
+
18731
+ // src/commands/CollectCommandHandler.ts
18659
18732
  var CollectCommandHandler = class {
18660
18733
  async handle(args) {
18661
18734
  let browser = null;
18662
18735
  try {
18663
- browser = await import_playwright.chromium.connectOverCDP(args.endpoint);
18736
+ const target = resolveCollectTarget(args);
18737
+ browser = await import_playwright.chromium.connectOverCDP(target.endpoint);
18664
18738
  const targetPage = await this.pickTargetPage(
18665
18739
  browser.contexts().flatMap((context) => context.pages())
18666
18740
  );
@@ -18669,36 +18743,20 @@ var CollectCommandHandler = class {
18669
18743
  }
18670
18744
  const { rows } = await this.locateThreadRows(targetPage);
18671
18745
  const threads = await this.extractThreads(rows);
18672
- if (args.mode === "list") {
18673
- if (args.json) {
18674
- ui.plain(JSON.stringify({ total: threads.length, threads }, null, 2));
18675
- return;
18676
- }
18677
- this.printThreadList(threads);
18678
- return;
18679
- }
18680
- const matched = this.findThread(threads, args.threadName || "");
18681
- if (!matched) {
18682
- throw new Error(`Thread not found: ${args.threadName}`);
18683
- }
18684
- await this.clickThreadRow(rows, matched);
18685
- await targetPage.waitForTimeout(1200);
18686
- const messages = await this.extractMessages(targetPage, matched.name);
18687
- if (args.json) {
18688
- ui.plain(
18689
- JSON.stringify(
18690
- {
18691
- thread: matched,
18692
- totalMessages: messages.length,
18693
- messages
18694
- },
18695
- null,
18696
- 2
18697
- )
18698
- );
18699
- return;
18700
- }
18701
- this.printThreadMessages(matched, messages);
18746
+ if (threads.length === 0) {
18747
+ throw new Error("No threads found in target page.");
18748
+ }
18749
+ const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
18750
+ const results = [];
18751
+ for (const thread of threads) {
18752
+ await this.clickThreadRow(rows, thread);
18753
+ await targetPage.waitForTimeout(1200);
18754
+ const messages = await this.extractMessages(targetPage, thread.name);
18755
+ const result = await this.persistThread(target.rootDir, target, thread, messages, syncedAt);
18756
+ results.push(result);
18757
+ }
18758
+ await this.writeIndex(target.rootDir, target, results, syncedAt);
18759
+ this.printSyncSummary(target.sourceKey, target.rootDir, threads.length, results);
18702
18760
  } catch (error) {
18703
18761
  const message = error instanceof Error ? error.message : String(error);
18704
18762
  throw new Error(`collect failed: ${message}`);
@@ -18706,6 +18764,67 @@ var CollectCommandHandler = class {
18706
18764
  await browser?.close().catch(() => void 0);
18707
18765
  }
18708
18766
  }
18767
+ async persistThread(rootDir, target, thread, messages, syncedAt) {
18768
+ const threadKey = toThreadKey(thread.name);
18769
+ const existing = await readStoredThread(rootDir, threadKey);
18770
+ const incoming = messages.map((message) => ({
18771
+ hash: message.hash,
18772
+ time: message.time,
18773
+ sender: message.sender,
18774
+ content: message.content,
18775
+ links: [...message.links],
18776
+ images: [...message.images],
18777
+ collectedAt: syncedAt
18778
+ }));
18779
+ const merged = mergeMessages(existing?.messages ?? [], incoming);
18780
+ const stored = {
18781
+ source: target.sourceKey,
18782
+ endpoint: target.endpoint,
18783
+ threadKey,
18784
+ threadName: thread.name,
18785
+ preview: thread.preview,
18786
+ unread: thread.unread,
18787
+ lastMessageAt: thread.time,
18788
+ lastSyncedAt: syncedAt,
18789
+ messageCount: merged.messages.length,
18790
+ messages: merged.messages
18791
+ };
18792
+ await writeStoredThread(rootDir, stored);
18793
+ return {
18794
+ thread: stored,
18795
+ addedMessages: merged.added,
18796
+ updated: merged.added > 0 || !existing || existing.preview !== stored.preview || existing.unread !== stored.unread || existing.lastMessageAt !== stored.lastMessageAt
18797
+ };
18798
+ }
18799
+ async writeIndex(rootDir, target, results, syncedAt) {
18800
+ const threads = results.map(({ thread }) => ({
18801
+ threadKey: thread.threadKey,
18802
+ name: thread.threadName,
18803
+ unread: thread.unread,
18804
+ preview: thread.preview,
18805
+ lastMessageAt: thread.lastMessageAt,
18806
+ messageCount: thread.messageCount,
18807
+ lastSyncedAt: thread.lastSyncedAt
18808
+ })).sort((left, right) => left.name.localeCompare(right.name));
18809
+ const messageCount = threads.reduce((sum, thread) => sum + thread.messageCount, 0);
18810
+ await writeStoredIndex(rootDir, {
18811
+ source: target.sourceKey,
18812
+ endpoint: target.endpoint,
18813
+ lastSyncedAt: syncedAt,
18814
+ threadCount: threads.length,
18815
+ messageCount,
18816
+ threads
18817
+ });
18818
+ }
18819
+ printSyncSummary(sourceKey, rootDir, scannedThreads, results) {
18820
+ const updatedThreads = results.filter((result) => result.updated).length;
18821
+ const newMessages = results.reduce((sum, result) => sum + result.addedMessages, 0);
18822
+ ui.plain(`Synced source: ${sourceKey}`);
18823
+ ui.plain(`Threads scanned: ${scannedThreads}`);
18824
+ ui.plain(`Threads updated: ${updatedThreads}`);
18825
+ ui.plain(`New messages: ${newMessages}`);
18826
+ ui.plain(`Saved under: ${rootDir}`);
18827
+ }
18709
18828
  async pickTargetPage(pages) {
18710
18829
  let best = null;
18711
18830
  for (const page of pages) {
@@ -18722,7 +18841,7 @@ var CollectCommandHandler = class {
18722
18841
  async locateThreadRows(page) {
18723
18842
  const preferred = page.locator(".ReactVirtualized__Grid__innerScrollContainer").first();
18724
18843
  const preferredCount = await preferred.locator(":scope > *").count().catch(() => 0);
18725
- if (preferredCount >= 5) {
18844
+ if (preferredCount >= 1) {
18726
18845
  return { rows: preferred.locator(":scope > *") };
18727
18846
  }
18728
18847
  const seeds = [
@@ -18742,7 +18861,7 @@ var CollectCommandHandler = class {
18742
18861
  for (let i = 0; i < max; i += 1) {
18743
18862
  const rows = containers.nth(i).locator(":scope > *");
18744
18863
  const rowCount = await rows.count().catch(() => 0);
18745
- if (rowCount < 5 || rowCount > 500) {
18864
+ if (rowCount < 1 || rowCount > 500) {
18746
18865
  continue;
18747
18866
  }
18748
18867
  const textCount = await containers.nth(i).locator("text=/./").count().catch(() => 0);
@@ -18776,21 +18895,7 @@ var CollectCommandHandler = class {
18776
18895
  ) ?? "";
18777
18896
  result.push({ index: i, name, unread, preview, time });
18778
18897
  }
18779
- return result;
18780
- }
18781
- findThread(threads, name) {
18782
- const target = normalizeText(name).toLowerCase();
18783
- if (!target) {
18784
- return null;
18785
- }
18786
- const exact = threads.find((thread) => thread.name.toLowerCase() === target);
18787
- if (exact) {
18788
- return exact;
18789
- }
18790
- const contains = threads.find(
18791
- (thread) => thread.name.toLowerCase().includes(target) || target.includes(thread.name.toLowerCase())
18792
- );
18793
- return contains ?? null;
18898
+ return dedupeThreads(result);
18794
18899
  }
18795
18900
  async extractMessages(page, threadName) {
18796
18901
  const container = await this.locateMessageContainer(page);
@@ -18833,17 +18938,14 @@ var CollectCommandHandler = class {
18833
18938
  return messages;
18834
18939
  }
18835
18940
  async clickThreadRow(rows, matched) {
18836
- const exactInRows = rows.filter({ hasText: matched.name }).first();
18837
- const exactCount = await exactInRows.count().catch(() => 0);
18838
- if (exactCount > 0) {
18839
- const clicked2 = await this.tryClick(exactInRows);
18840
- if (clicked2) {
18941
+ const row = rows.nth(matched.index);
18942
+ const clicked = await this.tryClick(row);
18943
+ if (!clicked) {
18944
+ const exactInRows = rows.filter({ hasText: matched.name }).first();
18945
+ const exactCount = await exactInRows.count().catch(() => 0);
18946
+ if (exactCount > 0 && await this.tryClick(exactInRows)) {
18841
18947
  return;
18842
18948
  }
18843
- }
18844
- const fallback = rows.nth(matched.index);
18845
- const clicked = await this.tryClick(fallback);
18846
- if (!clicked) {
18847
18949
  throw new Error(`Failed to select thread row: ${matched.name}`);
18848
18950
  }
18849
18951
  }
@@ -18982,31 +19084,20 @@ var CollectCommandHandler = class {
18982
19084
  }
18983
19085
  return candidates[0] ?? "";
18984
19086
  }
18985
- printThreadList(threads) {
18986
- for (const thread of threads) {
18987
- const unread = thread.unread > 0 ? ` (${thread.unread})` : "";
18988
- const preview = thread.preview ? ` - ${thread.preview}` : "";
18989
- ui.plain(`- ${thread.name}${unread}${preview}`);
18990
- }
18991
- }
18992
- printThreadMessages(thread, messages) {
18993
- const unread = thread.unread > 0 ? thread.unread : messages.length;
18994
- ui.plain(`## ${thread.name} (${unread})`);
18995
- for (const message of messages) {
18996
- ui.plain("-");
18997
- ui.plain(` time: ${message.time ?? ""}`);
18998
- ui.plain(` sender: ${message.sender ?? ""}`);
18999
- ui.plain(` content: ${message.content}`);
19000
- ui.plain(` hash: ${message.hash}`);
19001
- ui.plain(
19002
- ` links: ${message.links.length > 0 ? message.links.join(", ") : ""}`
19003
- );
19004
- ui.plain(
19005
- ` images: ${message.images.length > 0 ? message.images.join(", ") : ""}`
19006
- );
19087
+ };
19088
+ function dedupeThreads(threads) {
19089
+ const seen = /* @__PURE__ */ new Set();
19090
+ const result = [];
19091
+ for (const thread of threads) {
19092
+ const key = `${thread.name}::${thread.preview}::${thread.time ?? ""}`;
19093
+ if (seen.has(key)) {
19094
+ continue;
19007
19095
  }
19096
+ seen.add(key);
19097
+ result.push(thread);
19008
19098
  }
19009
- };
19099
+ return result;
19100
+ }
19010
19101
  function normalizeText(value) {
19011
19102
  return value.replace(/\s+/g, " ").replace(/\u200B/g, "").trim();
19012
19103
  }
@@ -19019,22 +19110,46 @@ function computeMessageHash(threadName, message) {
19019
19110
  message.links.map(normalizeText).join("|"),
19020
19111
  message.images.map(normalizeText).join("|")
19021
19112
  ].join("||");
19022
- return (0, import_node_crypto3.createHash)("sha1").update(base).digest("hex").slice(0, 16);
19113
+ return (0, import_node_crypto4.createHash)("sha1").update(base).digest("hex").slice(0, 16);
19114
+ }
19115
+ function parseMessageText(rawText) {
19116
+ const text = normalizeText(rawText);
19117
+ if (!text) {
19118
+ return { time: null, sender: null, content: "" };
19119
+ }
19120
+ const timeMatch = text.match(/^(\d{1,2}:\d{2}\s?(?:AM|PM)?)\s+(.*)$/i) ?? text.match(/^(\d{1,2}\/\d{1,2}|\d{4}\/\d{1,2}\/\d{1,2})\s+(.*)$/);
19121
+ if (!timeMatch) {
19122
+ return { time: null, sender: null, content: text };
19123
+ }
19124
+ const time = timeMatch[1];
19125
+ const rest = normalizeText(timeMatch[2] ?? "");
19126
+ if (!rest) {
19127
+ return { time, sender: null, content: "" };
19128
+ }
19129
+ const senderMatch = rest.match(/^([^:]{1,80}):\s*(.*)$/);
19130
+ if (!senderMatch) {
19131
+ return { time, sender: null, content: rest };
19132
+ }
19133
+ return {
19134
+ time,
19135
+ sender: normalizeText(senderMatch[1] ?? "") || null,
19136
+ content: normalizeText(senderMatch[2] ?? "")
19137
+ };
19023
19138
  }
19024
19139
  async function toDisplayableImagePath(src) {
19025
- if (!import_node_path15.default.isAbsolute(src)) {
19140
+ if (!import_node_path16.default.isAbsolute(src)) {
19026
19141
  return src;
19027
19142
  }
19028
- const ext = import_node_path15.default.extname(src);
19143
+ const ext = import_node_path16.default.extname(src);
19029
19144
  if (ext) {
19030
19145
  return src;
19031
19146
  }
19032
19147
  try {
19033
- const stat = await import_node_fs10.promises.stat(src);
19148
+ const stat = await import_node_fs11.promises.stat(src);
19034
19149
  if (!stat.isFile()) {
19035
19150
  return src;
19036
19151
  }
19037
- const fh = await import_node_fs10.promises.open(src, "r");
19152
+ const fh = await import_node_fs11.promises.open(src, "r");
19038
19153
  try {
19039
19154
  const buf = Buffer.alloc(32);
19040
19155
  const { bytesRead } = await fh.read(buf, 0, 32, 0);
@@ -19043,17 +19158,17 @@ async function toDisplayableImagePath(src) {
19043
19158
  if (!guessedExt) {
19044
19159
  return src;
19045
19160
  }
19046
- const cacheDir = import_node_path15.default.join(
19047
- import_node_os5.default.homedir(),
19161
+ const cacheDir = import_node_path16.default.join(
19162
+ import_node_os6.default.homedir(),
19048
19163
  ".pmate",
19049
19164
  "messages",
19050
19165
  "images"
19051
19166
  );
19052
- await import_node_fs10.promises.mkdir(cacheDir, { recursive: true });
19053
- const base = (0, import_node_crypto3.createHash)("sha1").update(src).digest("hex");
19054
- const displayPath = import_node_path15.default.join(cacheDir, `${base}.${guessedExt}`);
19055
- await import_node_fs10.promises.rm(displayPath, { force: true }).catch(() => void 0);
19056
- await import_node_fs10.promises.copyFile(src, displayPath);
19167
+ await import_node_fs11.promises.mkdir(cacheDir, { recursive: true });
19168
+ const base = (0, import_node_crypto4.createHash)("sha1").update(src).digest("hex");
19169
+ const displayPath = import_node_path16.default.join(cacheDir, `${base}.${guessedExt}`);
19170
+ await import_node_fs11.promises.rm(displayPath, { force: true }).catch(() => void 0);
19171
+ await import_node_fs11.promises.copyFile(src, displayPath);
19057
19172
  return displayPath;
19058
19173
  } finally {
19059
19174
  await fh.close();
@@ -19077,40 +19192,10 @@ function guessImageExtension(header) {
19077
19192
  }
19078
19193
  return null;
19079
19194
  }
19080
- function parseMessageText(raw) {
19081
- if (!raw) {
19082
- return { time: null, sender: null, content: "" };
19083
- }
19084
- const timeMatches = raw.match(/\b\d{1,2}:\d{2}\s?(?:AM|PM)\b/gi) || [];
19085
- const time = timeMatches.length > 0 ? timeMatches[timeMatches.length - 1] : null;
19086
- let sender = null;
19087
- const chefSender = raw.match(/^(Chef\s+[A-Za-z0-9_-]+)/);
19088
- if (chefSender) {
19089
- sender = chefSender[1];
19090
- } else {
19091
- const simpleSender = raw.match(/^([A-Za-z][A-Za-z0-9._-]{1,30})/);
19092
- sender = simpleSender ? simpleSender[1] : null;
19093
- }
19094
- let content = raw;
19095
- if (sender && content.startsWith(sender)) {
19096
- content = content.slice(sender.length).trim();
19097
- }
19098
- if (time) {
19099
- const timeIdx = content.lastIndexOf(time);
19100
- if (timeIdx >= 0) {
19101
- content = content.slice(0, timeIdx).trim();
19102
- }
19103
- }
19104
- content = content.replace(
19105
- /QuoteReply|Forward|Save to Note|Select|Pin|Add To-Do|Info|Translate>English中文/g,
19106
- " "
19107
- ).replace(/Group Chat History|Chat History/g, " ").replace(/\s+/g, " ").trim();
19108
- return { time, sender, content };
19109
- }
19110
19195
 
19111
19196
  // src/commands/AgentCommandHandler.ts
19112
- var import_node_fs11 = require("fs");
19113
- var import_node_path16 = __toESM(require("path"));
19197
+ var import_node_fs12 = require("fs");
19198
+ var import_node_path17 = __toESM(require("path"));
19114
19199
  init_AgentLlmClient();
19115
19200
  init_sessionStore();
19116
19201
 
@@ -19118,7 +19203,7 @@ init_sessionStore();
19118
19203
  var STORE_LOG_VERSION = 1;
19119
19204
  var LOG_KIND_TABLE = 1e4;
19120
19205
  var LOG_KIND_MAPPING = 6003;
19121
- function createHash3() {
19206
+ function createHash4() {
19122
19207
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
19123
19208
  }
19124
19209
  function createDescriptor(input) {
@@ -19143,8 +19228,8 @@ function descriptorPathSegments(descriptor) {
19143
19228
  return ["chains", normalized.chain, "namespaces", normalized.ns, normalized.kind, normalized.name];
19144
19229
  }
19145
19230
  function buildPathUrl(baseUrl, pathSegments, query) {
19146
- const path22 = `/${pathSegments.map((segment) => encodeURIComponent(segment)).join("/")}`;
19147
- const url = new URL(path22, baseUrl);
19231
+ const path23 = `/${pathSegments.map((segment) => encodeURIComponent(segment)).join("/")}`;
19232
+ const url = new URL(path23, baseUrl);
19148
19233
  if (query) {
19149
19234
  for (const [key, value] of Object.entries(query)) {
19150
19235
  url.searchParams.set(key, String(value));
@@ -19257,7 +19342,7 @@ var Namespace = class {
19257
19342
  },
19258
19343
  appendRow: async (data) => {
19259
19344
  const log = {
19260
- hash: createHash3(),
19345
+ hash: createHash4(),
19261
19346
  t: Date.now(),
19262
19347
  kind: LOG_KIND_TABLE,
19263
19348
  topic: descriptorToTopic(descriptor),
@@ -19269,7 +19354,7 @@ var Namespace = class {
19269
19354
  updateRow: async (data) => {
19270
19355
  const { id, ...value } = data;
19271
19356
  const log = {
19272
- hash: createHash3(),
19357
+ hash: createHash4(),
19273
19358
  t: Date.now(),
19274
19359
  kind: LOG_KIND_TABLE,
19275
19360
  topic: descriptorToTopic(descriptor),
@@ -19280,7 +19365,7 @@ var Namespace = class {
19280
19365
  },
19281
19366
  deleteRow: async (id) => {
19282
19367
  const log = {
19283
- hash: createHash3(),
19368
+ hash: createHash4(),
19284
19369
  t: Date.now(),
19285
19370
  kind: LOG_KIND_TABLE,
19286
19371
  topic: descriptorToTopic(descriptor),
@@ -19323,7 +19408,7 @@ var Namespace = class {
19323
19408
  },
19324
19409
  set: async (key, value) => {
19325
19410
  const log = {
19326
- hash: createHash3(),
19411
+ hash: createHash4(),
19327
19412
  t: Date.now(),
19328
19413
  kind: LOG_KIND_MAPPING,
19329
19414
  topic: descriptorToTopic(descriptor),
@@ -19334,7 +19419,7 @@ var Namespace = class {
19334
19419
  },
19335
19420
  delete: async (key) => {
19336
19421
  const log = {
19337
- hash: createHash3(),
19422
+ hash: createHash4(),
19338
19423
  t: Date.now(),
19339
19424
  kind: LOG_KIND_MAPPING,
19340
19425
  topic: descriptorToTopic(descriptor),
@@ -19527,6 +19612,24 @@ var AgentCommandHandler = class {
19527
19612
  this.renderJson(record, args.json);
19528
19613
  return;
19529
19614
  }
19615
+ case "move": {
19616
+ const record = await this.request(
19617
+ baseUrl,
19618
+ token,
19619
+ "POST",
19620
+ `/agents/${encodeURIComponent(args.namespace)}/move`,
19621
+ {
19622
+ from: args.fromName,
19623
+ toNamespace: args.targetNamespace,
19624
+ ...args.toName ? { to: args.toName } : {}
19625
+ }
19626
+ );
19627
+ ui.success(
19628
+ `Moved agent ${formatNamespacedDisplayId(args.namespace, args.fromName)} -> ${record.id}`
19629
+ );
19630
+ this.renderJson(record, args.json);
19631
+ return;
19632
+ }
19530
19633
  }
19531
19634
  }
19532
19635
  resolveBaseUrl(baseUrl) {
@@ -19558,11 +19661,11 @@ var AgentCommandHandler = class {
19558
19661
  }).token;
19559
19662
  }
19560
19663
  readJsonFile(filePath) {
19561
- const absolutePath = import_node_path16.default.resolve(process.cwd(), filePath);
19562
- if (!(0, import_node_fs11.existsSync)(absolutePath)) {
19664
+ const absolutePath = import_node_path17.default.resolve(process.cwd(), filePath);
19665
+ if (!(0, import_node_fs12.existsSync)(absolutePath)) {
19563
19666
  throw new Error(`JSON file not found: ${absolutePath}`);
19564
19667
  }
19565
- const raw = (0, import_node_fs11.readFileSync)(absolutePath, "utf8");
19668
+ const raw = (0, import_node_fs12.readFileSync)(absolutePath, "utf8");
19566
19669
  try {
19567
19670
  return JSON.parse(raw);
19568
19671
  } catch (error) {
@@ -19573,7 +19676,7 @@ var AgentCommandHandler = class {
19573
19676
  readJsonObjectFile(filePath) {
19574
19677
  const parsed = this.readJsonFile(filePath);
19575
19678
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
19576
- const absolutePath = import_node_path16.default.resolve(process.cwd(), filePath);
19679
+ const absolutePath = import_node_path17.default.resolve(process.cwd(), filePath);
19577
19680
  throw new Error(`Invalid JSON in ${absolutePath}: expected an object`);
19578
19681
  }
19579
19682
  return parsed;
@@ -19722,8 +19825,8 @@ var NsCommandHandler = class {
19722
19825
  };
19723
19826
 
19724
19827
  // src/commands/StoreCommandHandler.ts
19725
- var import_node_fs12 = require("fs");
19726
- var import_node_path17 = __toESM(require("path"));
19828
+ var import_node_fs13 = require("fs");
19829
+ var import_node_path18 = __toESM(require("path"));
19727
19830
  var StoreCommandHandler = class {
19728
19831
  async handle(args) {
19729
19832
  if (args.scope === "namespace") {
@@ -19865,11 +19968,11 @@ var StoreCommandHandler = class {
19865
19968
  return payload.data ?? [];
19866
19969
  }
19867
19970
  readJsonFile(filePath) {
19868
- const absolutePath = import_node_path17.default.resolve(process.cwd(), filePath);
19869
- if (!(0, import_node_fs12.existsSync)(absolutePath)) {
19971
+ const absolutePath = import_node_path18.default.resolve(process.cwd(), filePath);
19972
+ if (!(0, import_node_fs13.existsSync)(absolutePath)) {
19870
19973
  throw new Error(`JSON file not found: ${absolutePath}`);
19871
19974
  }
19872
- const raw = (0, import_node_fs12.readFileSync)(absolutePath, "utf8");
19975
+ const raw = (0, import_node_fs13.readFileSync)(absolutePath, "utf8");
19873
19976
  try {
19874
19977
  return JSON.parse(raw);
19875
19978
  } catch (error) {
@@ -19921,8 +20024,8 @@ var StoreCommandHandler = class {
19921
20024
  };
19922
20025
 
19923
20026
  // src/commands/AppCommandHandler.ts
19924
- var import_node_fs13 = require("fs");
19925
- var import_node_path18 = __toESM(require("path"));
20027
+ var import_node_fs14 = require("fs");
20028
+ var import_node_path19 = __toESM(require("path"));
19926
20029
  init_sessionStore();
19927
20030
  init_namespacedRef();
19928
20031
  var AppCommandHandler = class {
@@ -20010,6 +20113,24 @@ var AppCommandHandler = class {
20010
20113
  this.renderJson(record, args.json);
20011
20114
  return;
20012
20115
  }
20116
+ case "move": {
20117
+ const record = await this.request(
20118
+ baseUrl,
20119
+ token,
20120
+ "POST",
20121
+ `/apps/${encodeURIComponent(args.namespace)}/move`,
20122
+ {
20123
+ fromId: args.fromId,
20124
+ toNamespace: args.targetNamespace,
20125
+ ...args.toId ? { toId: args.toId } : {}
20126
+ }
20127
+ );
20128
+ ui.success(
20129
+ `Moved app ${formatNamespacedDisplayId(args.namespace, args.fromId)} -> ${formatNamespacedDisplayId(record.namespace, record.id)}`
20130
+ );
20131
+ this.renderJson(record, args.json);
20132
+ return;
20133
+ }
20013
20134
  }
20014
20135
  }
20015
20136
  resolveBaseUrl(baseUrl) {
@@ -20021,11 +20142,11 @@ var AppCommandHandler = class {
20021
20142
  }).token;
20022
20143
  }
20023
20144
  readJsonFile(filePath) {
20024
- const absolutePath = import_node_path18.default.resolve(process.cwd(), filePath);
20025
- if (!(0, import_node_fs13.existsSync)(absolutePath)) {
20145
+ const absolutePath = import_node_path19.default.resolve(process.cwd(), filePath);
20146
+ if (!(0, import_node_fs14.existsSync)(absolutePath)) {
20026
20147
  throw new Error(`JSON file not found: ${absolutePath}`);
20027
20148
  }
20028
- const raw = (0, import_node_fs13.readFileSync)(absolutePath, "utf8");
20149
+ const raw = (0, import_node_fs14.readFileSync)(absolutePath, "utf8");
20029
20150
  try {
20030
20151
  return JSON.parse(raw);
20031
20152
  } catch (error) {
@@ -20105,13 +20226,13 @@ function readNamespaceFromPayload(payload) {
20105
20226
  }
20106
20227
 
20107
20228
  // src/commands/ServiceCommandHandler.ts
20108
- var import_node_fs15 = require("fs");
20109
- var import_node_path20 = __toESM(require("path"));
20229
+ var import_node_fs16 = require("fs");
20230
+ var import_node_path21 = __toESM(require("path"));
20110
20231
 
20111
20232
  // src/services/ServiceRuntimeRunner.ts
20112
- var import_node_fs14 = require("fs");
20113
- var import_node_os6 = __toESM(require("os"));
20114
- var import_node_path19 = __toESM(require("path"));
20233
+ var import_node_fs15 = require("fs");
20234
+ var import_node_os7 = __toESM(require("os"));
20235
+ var import_node_path20 = __toESM(require("path"));
20115
20236
  var import_node_child_process9 = require("child_process");
20116
20237
  var import_node_readline = require("readline");
20117
20238
  var import_chalk3 = __toESM(require("chalk"));
@@ -20224,14 +20345,14 @@ var ServiceRuntimeRunner = class {
20224
20345
  }
20225
20346
  resolveRepoRoot(service, cwd) {
20226
20347
  if (cwd) {
20227
- return import_node_path19.default.resolve(process.cwd(), cwd);
20348
+ return import_node_path20.default.resolve(process.cwd(), cwd);
20228
20349
  }
20229
20350
  const repository = this.getDeploy(service).repository?.trim();
20230
20351
  if (repository) {
20231
20352
  const repoName = repository.replace(/\/+$/, "").split("/").pop()?.replace(/\.git$/i, "");
20232
20353
  if (repoName) {
20233
- const candidate = import_node_path19.default.join(import_node_os6.default.homedir(), "dev", "pmate", repoName);
20234
- if ((0, import_node_fs14.existsSync)(candidate)) {
20354
+ const candidate = import_node_path20.default.join(import_node_os7.default.homedir(), "dev", "pmate", repoName);
20355
+ if ((0, import_node_fs15.existsSync)(candidate)) {
20235
20356
  return candidate;
20236
20357
  }
20237
20358
  }
@@ -20244,12 +20365,12 @@ var ServiceRuntimeRunner = class {
20244
20365
  if (!dir) {
20245
20366
  throw new Error(`Missing deploy.dir for ${service.id}`);
20246
20367
  }
20247
- return import_node_path19.default.resolve(repoRoot, dir);
20368
+ return import_node_path20.default.resolve(repoRoot, dir);
20248
20369
  }
20249
20370
  async deployVite(service, options) {
20250
20371
  const appDir = this.resolveLocalDir(service, options.cwd);
20251
- const packageJsonPath = import_node_path19.default.join(appDir, "package.json");
20252
- if (!(0, import_node_fs14.existsSync)(packageJsonPath)) {
20372
+ const packageJsonPath = import_node_path20.default.join(appDir, "package.json");
20373
+ if (!(0, import_node_fs15.existsSync)(packageJsonPath)) {
20253
20374
  throw new Error(`No package.json found at ${packageJsonPath}`);
20254
20375
  }
20255
20376
  const pkg2 = this.loadPackageJson(packageJsonPath);
@@ -20258,8 +20379,8 @@ var ServiceRuntimeRunner = class {
20258
20379
  throw new Error(`Missing package name in ${packageJsonPath}`);
20259
20380
  }
20260
20381
  await this.runCommand("pnpm", ["--filter", pkgName, "build"], this.resolveRepoRoot(service, options.cwd));
20261
- const distDir = import_node_path19.default.join(appDir, "dist");
20262
- if (!(0, import_node_fs14.existsSync)(distDir)) {
20382
+ const distDir = import_node_path20.default.join(appDir, "dist");
20383
+ if (!(0, import_node_fs15.existsSync)(distDir)) {
20263
20384
  throw new Error(`No dist directory found at ${distDir}`);
20264
20385
  }
20265
20386
  const bucketName = this.getDeploy(service).bucket?.trim();
@@ -20270,8 +20391,8 @@ var ServiceRuntimeRunner = class {
20270
20391
  }
20271
20392
  async deployStatic(service, options) {
20272
20393
  const appDir = this.resolveLocalDir(service, options.cwd);
20273
- const srcDir = import_node_path19.default.join(appDir, "src");
20274
- if (!(0, import_node_fs14.existsSync)(srcDir)) {
20394
+ const srcDir = import_node_path20.default.join(appDir, "src");
20395
+ if (!(0, import_node_fs15.existsSync)(srcDir)) {
20275
20396
  throw new Error(`No src directory found at ${srcDir}`);
20276
20397
  }
20277
20398
  const bucketName = this.getDeploy(service).bucket?.trim();
@@ -20389,7 +20510,7 @@ var ServiceRuntimeRunner = class {
20389
20510
  const serverAddress = await resolveServerAddress(server);
20390
20511
  const templateName = serviceType === "ws" ? "nginx.ws.template" : "nginx.rest.template";
20391
20512
  const templatePath = this.resolveTemplatePath(templateName);
20392
- const template = (0, import_node_fs14.readFileSync)(templatePath, "utf8");
20513
+ const template = (0, import_node_fs15.readFileSync)(templatePath, "utf8");
20393
20514
  const host = `${subdomain}.${deploy.domain?.trim() || "pmate.chat"}`;
20394
20515
  const rendered = template.replace(/\$\{\{PORT\}\}/g, String(port)).replace(/\$\{\{HOSTS\}\}/g, host).replace(/\$\{\{HOST\}\}/g, host);
20395
20516
  const remotePath = `/etc/nginx/sites-enabled/${subdomain}.conf`;
@@ -20421,11 +20542,11 @@ var ServiceRuntimeRunner = class {
20421
20542
  }
20422
20543
  if (config.ensurePackageJson) {
20423
20544
  const appDir = this.resolveLocalDir(service, options.cwd);
20424
- const packageJsonPath = import_node_path19.default.join(appDir, "package.json");
20425
- if (!(0, import_node_fs14.existsSync)(packageJsonPath)) {
20545
+ const packageJsonPath = import_node_path20.default.join(appDir, "package.json");
20546
+ if (!(0, import_node_fs15.existsSync)(packageJsonPath)) {
20426
20547
  throw new Error(`Missing package.json at ${packageJsonPath}`);
20427
20548
  }
20428
- const pkgStat = (0, import_node_fs14.statSync)(packageJsonPath);
20549
+ const pkgStat = (0, import_node_fs15.statSync)(packageJsonPath);
20429
20550
  if (!pkgStat.isFile()) {
20430
20551
  throw new Error(`package.json is not a file at ${packageJsonPath}`);
20431
20552
  }
@@ -20848,9 +20969,9 @@ var ServiceRuntimeRunner = class {
20848
20969
  return tokens;
20849
20970
  }
20850
20971
  readPathValue(source, pathExpr) {
20851
- const path22 = pathExpr.split(".").map((segment) => segment.trim()).filter(Boolean);
20972
+ const path23 = pathExpr.split(".").map((segment) => segment.trim()).filter(Boolean);
20852
20973
  let cursor = source;
20853
- for (const segment of path22) {
20974
+ for (const segment of path23) {
20854
20975
  if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) {
20855
20976
  return void 0;
20856
20977
  }
@@ -20893,12 +21014,12 @@ var ServiceRuntimeRunner = class {
20893
21014
  }
20894
21015
  resolveTemplatePath(templateName) {
20895
21016
  const candidates = [
20896
- import_node_path19.default.join(__dirname, "..", "templates", templateName),
20897
- import_node_path19.default.join(__dirname, "..", "src", "templates", templateName),
20898
- import_node_path19.default.join(__dirname, "templates", templateName)
21017
+ import_node_path20.default.join(__dirname, "..", "templates", templateName),
21018
+ import_node_path20.default.join(__dirname, "..", "src", "templates", templateName),
21019
+ import_node_path20.default.join(__dirname, "templates", templateName)
20899
21020
  ];
20900
21021
  for (const candidate of candidates) {
20901
- if ((0, import_node_fs14.existsSync)(candidate)) {
21022
+ if ((0, import_node_fs15.existsSync)(candidate)) {
20902
21023
  return candidate;
20903
21024
  }
20904
21025
  }
@@ -20930,7 +21051,7 @@ var ServiceRuntimeRunner = class {
20930
21051
  });
20931
21052
  }
20932
21053
  loadPackageJson(packageJsonPath) {
20933
- const raw = (0, import_node_fs14.readFileSync)(packageJsonPath, "utf8");
21054
+ const raw = (0, import_node_fs15.readFileSync)(packageJsonPath, "utf8");
20934
21055
  const parsed = JSON.parse(raw);
20935
21056
  if (!parsed || typeof parsed !== "object") {
20936
21057
  throw new Error(`Invalid package.json at ${packageJsonPath}`);
@@ -20939,7 +21060,7 @@ var ServiceRuntimeRunner = class {
20939
21060
  }
20940
21061
  writePackageJson(packageJsonPath, data) {
20941
21062
  const serialized = JSON.stringify(data, null, 2);
20942
- (0, import_node_fs14.writeFileSync)(packageJsonPath, `${serialized}
21063
+ (0, import_node_fs15.writeFileSync)(packageJsonPath, `${serialized}
20943
21064
  `, "utf8");
20944
21065
  }
20945
21066
  runCommand(command, args, cwd) {
@@ -21009,15 +21130,24 @@ var ServiceRegistryClient = class {
21009
21130
  if (repository) {
21010
21131
  searchParams.set("repo", repository);
21011
21132
  }
21133
+ const server = filters?.server?.trim();
21134
+ if (server) {
21135
+ searchParams.set("server", server);
21136
+ }
21012
21137
  const payload = await this.request(
21013
21138
  "GET",
21014
21139
  `/services${searchParams.size > 0 ? `?${searchParams.toString()}` : ""}`
21015
21140
  );
21016
21141
  const namespace = filters?.namespace?.trim();
21017
- if (!namespace) {
21018
- return payload.items;
21019
- }
21020
- return payload.items.filter((item) => item.namespace === namespace);
21142
+ return payload.items.filter((item) => {
21143
+ if (namespace && item.namespace !== namespace) {
21144
+ return false;
21145
+ }
21146
+ if (server && item.deploy?.server?.trim() !== server) {
21147
+ return false;
21148
+ }
21149
+ return true;
21150
+ });
21021
21151
  }
21022
21152
  async getService(namespace, name) {
21023
21153
  return this.request(
@@ -21087,7 +21217,8 @@ var ServiceCommandHandler = class {
21087
21217
  case "list": {
21088
21218
  const items = await registry.listServices({
21089
21219
  namespace: args.namespace,
21090
- repository: args.repository
21220
+ repository: args.repository,
21221
+ server: args.server
21091
21222
  });
21092
21223
  this.renderList(items, args.json);
21093
21224
  return;
@@ -21101,6 +21232,7 @@ var ServiceCommandHandler = class {
21101
21232
  case "create": {
21102
21233
  const payload = this.readJsonFile(args.filePath);
21103
21234
  await this.requireNamespace(payload, baseUrl);
21235
+ await this.requireUniqueServerPort(payload, registry);
21104
21236
  const record = await this.request(
21105
21237
  baseUrl,
21106
21238
  "POST",
@@ -21113,6 +21245,10 @@ var ServiceCommandHandler = class {
21113
21245
  }
21114
21246
  case "update": {
21115
21247
  const payload = this.readJsonFile(args.filePath);
21248
+ await this.requireUniqueServerPort(payload, registry, {
21249
+ namespace: args.namespace,
21250
+ name: args.name
21251
+ });
21116
21252
  const record = await this.request(
21117
21253
  baseUrl,
21118
21254
  "PUT",
@@ -21149,6 +21285,23 @@ var ServiceCommandHandler = class {
21149
21285
  this.renderJson(record, args.json);
21150
21286
  return;
21151
21287
  }
21288
+ case "move": {
21289
+ const record = await this.request(
21290
+ baseUrl,
21291
+ "POST",
21292
+ `/services/${encodeURIComponent(args.namespace)}/move`,
21293
+ {
21294
+ from: args.fromName,
21295
+ toNamespace: args.targetNamespace,
21296
+ ...args.toName ? { to: args.toName } : {}
21297
+ }
21298
+ );
21299
+ ui.success(
21300
+ `Moved service ${formatNamespacedDisplayId(args.namespace, args.fromName)} -> ${record.id}`
21301
+ );
21302
+ this.renderJson(record, args.json);
21303
+ return;
21304
+ }
21152
21305
  case "deploy": {
21153
21306
  const record = await registry.getService(args.namespace, args.name);
21154
21307
  await runtime.deploy(record, { cwd: args.cwd });
@@ -21175,11 +21328,11 @@ var ServiceCommandHandler = class {
21175
21328
  return (baseUrl || process.env.PMATE_APPS_API_BASE_URL || "https://apps-api.pmate.chat").replace(/\/+$/, "");
21176
21329
  }
21177
21330
  readJsonFile(filePath) {
21178
- const absolutePath = import_node_path20.default.resolve(process.cwd(), filePath);
21179
- if (!(0, import_node_fs15.existsSync)(absolutePath)) {
21331
+ const absolutePath = import_node_path21.default.resolve(process.cwd(), filePath);
21332
+ if (!(0, import_node_fs16.existsSync)(absolutePath)) {
21180
21333
  throw new Error(`JSON file not found: ${absolutePath}`);
21181
21334
  }
21182
- const raw = (0, import_node_fs15.readFileSync)(absolutePath, "utf8");
21335
+ const raw = (0, import_node_fs16.readFileSync)(absolutePath, "utf8");
21183
21336
  try {
21184
21337
  return JSON.parse(raw);
21185
21338
  } catch (error) {
@@ -21225,6 +21378,37 @@ var ServiceCommandHandler = class {
21225
21378
  throw new Error(`Namespace "${namespace}" is not registered. Run: pmate ns create ${namespace}`);
21226
21379
  }
21227
21380
  }
21381
+ async requireUniqueServerPort(payload, registry, currentService) {
21382
+ if (!payload || typeof payload !== "object") {
21383
+ return;
21384
+ }
21385
+ const deploy = payload.deploy;
21386
+ if (!deploy || typeof deploy !== "object") {
21387
+ return;
21388
+ }
21389
+ const serverValue = deploy.server;
21390
+ const portValue = deploy.port;
21391
+ const server = typeof serverValue === "string" ? serverValue.trim() : "";
21392
+ const port = typeof portValue === "number" ? portValue : typeof portValue === "string" && portValue.trim() ? Number(portValue) : void 0;
21393
+ if (!server || port === void 0 || !Number.isFinite(port)) {
21394
+ return;
21395
+ }
21396
+ const services = await registry.listServices({ server });
21397
+ const conflict = services.find((service) => {
21398
+ if (service.deploy?.port !== port) {
21399
+ return false;
21400
+ }
21401
+ if (!currentService) {
21402
+ return true;
21403
+ }
21404
+ return !(service.namespace === currentService.namespace && service.name === currentService.name);
21405
+ });
21406
+ if (conflict) {
21407
+ throw new Error(
21408
+ `Port ${port} is already used on server ${server} by ${formatNamespacedDisplayId(conflict.namespace, conflict.name)}`
21409
+ );
21410
+ }
21411
+ }
21228
21412
  renderList(items, asJson) {
21229
21413
  if (asJson) {
21230
21414
  ui.plain(JSON.stringify(items, null, 2));
@@ -21235,11 +21419,7 @@ var ServiceCommandHandler = class {
21235
21419
  return;
21236
21420
  }
21237
21421
  for (const item of items) {
21238
- ui.info(formatNamespacedDisplayId(item.namespace, item.name), {
21239
- kind: item.kind,
21240
- runtimeType: item.runtimeType,
21241
- status: item.status
21242
- });
21422
+ ui.info(formatNamespacedDisplayId(item.namespace, item.name), item);
21243
21423
  }
21244
21424
  }
21245
21425
  renderJson(value, asJson) {
@@ -21863,6 +22043,54 @@ function parseAgentArgs(tokens) {
21863
22043
  json
21864
22044
  };
21865
22045
  }
22046
+ if (action === "move") {
22047
+ let namespace;
22048
+ let from;
22049
+ let targetNamespace;
22050
+ let to;
22051
+ while (rest.length > 0) {
22052
+ const token = rest.shift();
22053
+ switch (token) {
22054
+ case "--ns":
22055
+ case "--namespace":
22056
+ namespace = requireValue(rest, token);
22057
+ break;
22058
+ case "--from":
22059
+ from = parseBareRenameId(requireValue(rest, token), "agent");
22060
+ break;
22061
+ case "--to-ns":
22062
+ case "--target-namespace":
22063
+ targetNamespace = requireValue(rest, token);
22064
+ break;
22065
+ case "--to":
22066
+ to = parseBareRenameId(requireValue(rest, token), "agent");
22067
+ break;
22068
+ case "--base-url":
22069
+ baseUrl = requireValue(rest, token);
22070
+ break;
22071
+ case "--json":
22072
+ json = true;
22073
+ break;
22074
+ default:
22075
+ throw new Error(`Unknown agent move option: ${token}`);
22076
+ }
22077
+ }
22078
+ if (!namespace || !from || !targetNamespace) {
22079
+ throw new Error(
22080
+ "Usage: agent move --from <id> --ns <namespace> --to-ns <namespace> [--to <id>] [--base-url <url>] [--json]"
22081
+ );
22082
+ }
22083
+ return {
22084
+ type: "agent" /* Agent */,
22085
+ action,
22086
+ namespace,
22087
+ fromName: from,
22088
+ targetNamespace,
22089
+ toName: to,
22090
+ baseUrl,
22091
+ json
22092
+ };
22093
+ }
21866
22094
  throw new Error(`Unknown agent action: ${action}`);
21867
22095
  }
21868
22096
  function requireValue(tokens, optionName) {
@@ -22178,7 +22406,7 @@ function parseAppArgs(tokens) {
22178
22406
  const rawAction = rest.shift();
22179
22407
  const action = rawAction === "view" ? "view" : rawAction;
22180
22408
  if (!action) {
22181
- throw new Error("Missing app action. Use: app list|get|view|create|update|rename|delete");
22409
+ throw new Error("Missing app action. Use: app list|get|view|create|update|rename|move|delete");
22182
22410
  }
22183
22411
  let baseUrl;
22184
22412
  let json = false;
@@ -22344,6 +22572,45 @@ function parseAppArgs(tokens) {
22344
22572
  }
22345
22573
  return { type: "app" /* App */, action, namespace, fromId, toId, baseUrl, json };
22346
22574
  }
22575
+ if (action === "move") {
22576
+ let namespace;
22577
+ let fromId;
22578
+ let targetNamespace;
22579
+ let toId;
22580
+ while (rest.length > 0) {
22581
+ const token = rest.shift();
22582
+ switch (token) {
22583
+ case "--ns":
22584
+ case "--namespace":
22585
+ namespace = requireValue4(rest, token);
22586
+ break;
22587
+ case "--from":
22588
+ fromId = parseBareRenameId2(requireValue4(rest, token), "app");
22589
+ break;
22590
+ case "--to-ns":
22591
+ case "--target-namespace":
22592
+ targetNamespace = requireValue4(rest, token);
22593
+ break;
22594
+ case "--to":
22595
+ toId = parseBareRenameId2(requireValue4(rest, token), "app");
22596
+ break;
22597
+ case "--base-url":
22598
+ baseUrl = requireValue4(rest, token);
22599
+ break;
22600
+ case "--json":
22601
+ json = true;
22602
+ break;
22603
+ default:
22604
+ throw new Error(`Unknown app move option: ${token}`);
22605
+ }
22606
+ }
22607
+ if (!namespace || !fromId || !targetNamespace) {
22608
+ throw new Error(
22609
+ "Usage: app move --from <id> --ns <namespace> --to-ns <namespace> [--to <id>] [--base-url <url>] [--json]"
22610
+ );
22611
+ }
22612
+ return { type: "app" /* App */, action, namespace, fromId, targetNamespace, toId, baseUrl, json };
22613
+ }
22347
22614
  throw new Error(`Unknown app action: ${action}`);
22348
22615
  }
22349
22616
  function requireValue4(tokens, optionName) {
@@ -22375,6 +22642,7 @@ function parseServiceArgs(tokens) {
22375
22642
  if (action === "list") {
22376
22643
  let namespace;
22377
22644
  let repository;
22645
+ let server;
22378
22646
  while (rest.length > 0) {
22379
22647
  const token = rest.shift();
22380
22648
  switch (token) {
@@ -22384,6 +22652,9 @@ function parseServiceArgs(tokens) {
22384
22652
  case "--repo":
22385
22653
  repository = requireValue5(rest, token);
22386
22654
  break;
22655
+ case "--server":
22656
+ server = requireValue5(rest, token);
22657
+ break;
22387
22658
  case "--base-url":
22388
22659
  baseUrl = requireValue5(rest, token);
22389
22660
  break;
@@ -22394,7 +22665,7 @@ function parseServiceArgs(tokens) {
22394
22665
  throw new Error(`Unknown service list option: ${token}`);
22395
22666
  }
22396
22667
  }
22397
- return { type: "service" /* Service */, action, namespace, repository, baseUrl, json };
22668
+ return { type: "service" /* Service */, action, namespace, repository, server, baseUrl, json };
22398
22669
  }
22399
22670
  if (action === "view") {
22400
22671
  const ref = rest.shift();
@@ -22568,6 +22839,54 @@ function parseServiceArgs(tokens) {
22568
22839
  json
22569
22840
  };
22570
22841
  }
22842
+ if (action === "move") {
22843
+ let namespace;
22844
+ let from;
22845
+ let targetNamespace;
22846
+ let to;
22847
+ while (rest.length > 0) {
22848
+ const token = rest.shift();
22849
+ switch (token) {
22850
+ case "--ns":
22851
+ case "--namespace":
22852
+ namespace = requireValue5(rest, token);
22853
+ break;
22854
+ case "--from":
22855
+ from = parseBareRenameId3(requireValue5(rest, token), "service");
22856
+ break;
22857
+ case "--to-ns":
22858
+ case "--target-namespace":
22859
+ targetNamespace = requireValue5(rest, token);
22860
+ break;
22861
+ case "--to":
22862
+ to = parseBareRenameId3(requireValue5(rest, token), "service");
22863
+ break;
22864
+ case "--base-url":
22865
+ baseUrl = requireValue5(rest, token);
22866
+ break;
22867
+ case "--json":
22868
+ json = true;
22869
+ break;
22870
+ default:
22871
+ throw new Error(`Unknown service move option: ${token}`);
22872
+ }
22873
+ }
22874
+ if (!namespace || !from || !targetNamespace) {
22875
+ throw new Error(
22876
+ "Usage: service move --from <id> --ns <namespace> --to-ns <namespace> [--to <id>] [--base-url <url>] [--json]"
22877
+ );
22878
+ }
22879
+ return {
22880
+ type: "service" /* Service */,
22881
+ action,
22882
+ namespace,
22883
+ fromName: from,
22884
+ targetNamespace,
22885
+ toName: to,
22886
+ baseUrl,
22887
+ json
22888
+ };
22889
+ }
22571
22890
  throw new Error(`Unknown service action: ${action}`);
22572
22891
  }
22573
22892
  function requireValue5(tokens, optionName) {
@@ -22812,9 +23131,59 @@ function requireValue7(tokens, optionName) {
22812
23131
  return value;
22813
23132
  }
22814
23133
 
23134
+ // src/collectCommandParser.ts
23135
+ function parseCollectArgs(tokens) {
23136
+ const rest = [...tokens];
23137
+ const options = {
23138
+ action: "sync",
23139
+ source: void 0,
23140
+ endpoint: void 0
23141
+ };
23142
+ const action = rest.shift();
23143
+ if (action !== "sync") {
23144
+ throw new Error(
23145
+ "Usage: collect sync (--source <cc|yelling> | --endpoint <url>)"
23146
+ );
23147
+ }
23148
+ while (rest.length > 0) {
23149
+ const token = rest.shift();
23150
+ switch (token) {
23151
+ case "--source": {
23152
+ const value = requireValue8(rest, token);
23153
+ if (value !== "cc" && value !== "yelling") {
23154
+ throw new Error(`Unsupported collect source: ${value}`);
23155
+ }
23156
+ options.source = value;
23157
+ break;
23158
+ }
23159
+ case "--endpoint":
23160
+ options.endpoint = requireValue8(rest, token);
23161
+ break;
23162
+ default:
23163
+ throw new Error(`Unknown collect option: ${token}`);
23164
+ }
23165
+ }
23166
+ if (options.source && options.endpoint) {
23167
+ throw new Error("Use either --source or --endpoint, not both.");
23168
+ }
23169
+ if (!options.source && !options.endpoint) {
23170
+ throw new Error(
23171
+ "Usage: collect sync (--source <cc|yelling> | --endpoint <url>)"
23172
+ );
23173
+ }
23174
+ return { type: "collect" /* Collect */, ...options };
23175
+ }
23176
+ function requireValue8(tokens, optionName) {
23177
+ const value = tokens.shift();
23178
+ if (!value) {
23179
+ throw new Error(`Missing value for ${optionName}`);
23180
+ }
23181
+ return value;
23182
+ }
23183
+
22815
23184
  // src/index.ts
22816
23185
  var pkg = JSON.parse(
22817
- (0, import_node_fs16.readFileSync)(import_node_path21.default.resolve(__dirname, "..", "package.json"), "utf8")
23186
+ (0, import_node_fs17.readFileSync)(import_node_path22.default.resolve(__dirname, "..", "package.json"), "utf8")
22818
23187
  );
22819
23188
  var HELP_TEXT = [
22820
23189
  import_chalk4.default.bold(`pmate v${pkg.version}`),
@@ -22893,8 +23262,7 @@ var HELP_TEXT = [
22893
23262
  ` ${import_chalk4.default.gray(" [--count <n>]")}`,
22894
23263
  ` ${import_chalk4.default.gray(" --easy [--words <n>] [--digits <n>] [--separator <s>] [--count <n>]")}`,
22895
23264
  ` ${import_chalk4.default.cyan("collect")} Collect threads/messages from Electron chat app via CDP`,
22896
- ` ${import_chalk4.default.gray(" --list [--endpoint <url>] [--json]")}`,
22897
- ` ${import_chalk4.default.gray(" --thread <name> [--endpoint <url>] [--json]")}`,
23265
+ ` ${import_chalk4.default.gray(" sync (--source <cc|yelling> | --endpoint <url>)")}`,
22898
23266
  ` ${import_chalk4.default.cyan("agent")} Manage agent registry entries and call agents for debugging`,
22899
23267
  ` ${import_chalk4.default.gray(" namespaces [--base-url <url>] [--json]")}`,
22900
23268
  ` ${import_chalk4.default.gray(" list [--namespace <ns>] [--base-url <url>] [--json]")}`,
@@ -22903,6 +23271,7 @@ var HELP_TEXT = [
22903
23271
  ` ${import_chalk4.default.gray(" create [<namespace>] --file <path> [--base-url <url>] [--json]")}`,
22904
23272
  ` ${import_chalk4.default.gray(" update <ns:objectId> --file <path> [--base-url <url>] [--json]")}`,
22905
23273
  ` ${import_chalk4.default.gray(" rename --from <id> --to <id> --ns <namespace> [--base-url <url>] [--json]")}`,
23274
+ ` ${import_chalk4.default.gray(" move --from <id> --ns <namespace> --to-ns <namespace> [--to <id>] [--base-url <url>] [--json]")}`,
22906
23275
  ` ${import_chalk4.default.gray(" call <ns:objectId> [--payload <json>] [--file <path>] [--base-url <url>] [--hub-base-url <url>] [--from <id>] [--json]")}`,
22907
23276
  ` ${import_chalk4.default.gray(" delete <ns:objectId> [--base-url <url>] [--json]")}`,
22908
23277
  ` ${import_chalk4.default.gray(" list defaults to all namespaces; create defaults to namespace: pmate; default base URL: https://agent-api.pmate.chat; call uses pmate:cli session and default hub: https://hub.pmate.chat")}`,
@@ -22932,15 +23301,17 @@ var HELP_TEXT = [
22932
23301
  ` ${import_chalk4.default.gray(" create --file <path> [--base-url <url>] [--json]")}`,
22933
23302
  ` ${import_chalk4.default.gray(" update <ns:objectId> --file <path> [--base-url <url>] [--json]")}`,
22934
23303
  ` ${import_chalk4.default.gray(" rename --from <id> --to <id> --ns <namespace> [--base-url <url>] [--json]")}`,
23304
+ ` ${import_chalk4.default.gray(" move --from <id> --ns <namespace> --to-ns <namespace> [--to <id>] [--base-url <url>] [--json]")}`,
22935
23305
  ` ${import_chalk4.default.gray(" delete <ns:objectId> [--base-url <url>] [--json]")}`,
22936
23306
  ` ${import_chalk4.default.gray(" default base URL: https://apps-api.pmate.chat")}`,
22937
23307
  ` ${import_chalk4.default.cyan("service")} Manage service registry entries via apps-api`,
22938
- ` ${import_chalk4.default.gray(" list [--namespace <ns>] [--repo <owner/name|https://github.com/owner/name>] [--base-url <url>] [--json]")}`,
23308
+ ` ${import_chalk4.default.gray(" list [--namespace <ns>] [--repo <owner/name|https://github.com/owner/name>] [--server <name>] [--base-url <url>] [--json]")}`,
22939
23309
  ` ${import_chalk4.default.gray(" get <ns:objectId> [--base-url <url>] [--json]")}`,
22940
23310
  ` ${import_chalk4.default.gray(" view <ns:objectId> [--base-url <url>]")}`,
22941
23311
  ` ${import_chalk4.default.gray(" create --file <path> [--base-url <url>] [--json]")}`,
22942
23312
  ` ${import_chalk4.default.gray(" update <ns:objectId> --file <path> [--base-url <url>] [--json]")}`,
22943
23313
  ` ${import_chalk4.default.gray(" rename --from <id> --to <id> --ns <namespace> [--base-url <url>] [--json]")}`,
23314
+ ` ${import_chalk4.default.gray(" move --from <id> --ns <namespace> --to-ns <namespace> [--to <id>] [--base-url <url>] [--json]")}`,
22944
23315
  ` ${import_chalk4.default.gray(" delete <ns:objectId> [--base-url <url>] [--json]")}`,
22945
23316
  ` ${import_chalk4.default.gray(" deploy <ns:objectId> [--cwd <dir>] [--base-url <url>]")}`,
22946
23317
  ` ${import_chalk4.default.gray(" init <ns:objectId> [--cwd <dir>] [--base-url <url>]")}`,
@@ -23006,7 +23377,7 @@ function parseCommandArgs(args) {
23006
23377
  const token = rest.shift();
23007
23378
  switch (token) {
23008
23379
  case "--app":
23009
- app = requireValue8(rest, token);
23380
+ app = requireValue9(rest, token);
23010
23381
  break;
23011
23382
  default:
23012
23383
  throw new Error(`Unknown login option: ${token}`);
@@ -23103,7 +23474,7 @@ function parseVercelArgs(tokens) {
23103
23474
  const token = rest.shift();
23104
23475
  switch (token) {
23105
23476
  case "--scope":
23106
- scope = requireValue8(rest, token);
23477
+ scope = requireValue9(rest, token);
23107
23478
  break;
23108
23479
  default:
23109
23480
  throw new Error(`Unknown vercel option: ${token}`);
@@ -23123,10 +23494,10 @@ function parseVercelArgs(tokens) {
23123
23494
  const token = rest.shift();
23124
23495
  switch (token) {
23125
23496
  case "--scope":
23126
- scope = requireValue8(rest, token);
23497
+ scope = requireValue9(rest, token);
23127
23498
  break;
23128
23499
  case "--project":
23129
- project = requireValue8(rest, token);
23500
+ project = requireValue9(rest, token);
23130
23501
  break;
23131
23502
  case "--last-week":
23132
23503
  lastWeek = true;
@@ -23157,16 +23528,16 @@ function parseAddDnsArgs(tokens) {
23157
23528
  const token = rest.shift();
23158
23529
  switch (token) {
23159
23530
  case "--type":
23160
- options.dnsType = requireValue8(rest, token);
23531
+ options.dnsType = requireValue9(rest, token);
23161
23532
  break;
23162
23533
  case "--value":
23163
- options.dnsValue = requireValue8(rest, token);
23534
+ options.dnsValue = requireValue9(rest, token);
23164
23535
  break;
23165
23536
  case "--rr":
23166
- options.dnsRr = requireValue8(rest, token);
23537
+ options.dnsRr = requireValue9(rest, token);
23167
23538
  break;
23168
23539
  case "--ttl": {
23169
- const ttlValue = requireValue8(rest, token);
23540
+ const ttlValue = requireValue9(rest, token);
23170
23541
  const ttl = Number.parseInt(ttlValue, 10);
23171
23542
  if (!Number.isFinite(ttl) || ttl <= 0) {
23172
23543
  throw new Error(`Invalid --ttl value: ${ttlValue}`);
@@ -23175,7 +23546,7 @@ function parseAddDnsArgs(tokens) {
23175
23546
  break;
23176
23547
  }
23177
23548
  case "--domain":
23178
- options.dnsDomain = requireValue8(rest, token);
23549
+ options.dnsDomain = requireValue9(rest, token);
23179
23550
  break;
23180
23551
  default:
23181
23552
  throw new Error(`Unknown add-dns option: ${token}`);
@@ -23208,13 +23579,13 @@ function parseBucketArgs(tokens) {
23208
23579
  options.bucketCreate = true;
23209
23580
  break;
23210
23581
  case "--name":
23211
- options.bucketName = requireValue8(rest, token);
23582
+ options.bucketName = requireValue9(rest, token);
23212
23583
  break;
23213
23584
  case "--subdomain":
23214
- options.bucketSubdomain = requireValue8(rest, token);
23585
+ options.bucketSubdomain = requireValue9(rest, token);
23215
23586
  break;
23216
23587
  case "--domain":
23217
- options.bucketDomain = requireValue8(rest, token);
23588
+ options.bucketDomain = requireValue9(rest, token);
23218
23589
  break;
23219
23590
  default:
23220
23591
  throw new Error(`Unknown bucket option: ${token}`);
@@ -23246,7 +23617,7 @@ function parseDevArgs(tokens) {
23246
23617
  const token = rest.shift();
23247
23618
  switch (token) {
23248
23619
  case "--cwd":
23249
- options.devCwd = requireValue8(rest, token);
23620
+ options.devCwd = requireValue9(rest, token);
23250
23621
  break;
23251
23622
  default:
23252
23623
  throw new Error(`Unknown dev option: ${token}`);
@@ -23266,7 +23637,7 @@ function parseDeleteArgs(tokens) {
23266
23637
  const token = rest.shift();
23267
23638
  switch (token) {
23268
23639
  case "--cwd":
23269
- deleteCwd = requireValue8(rest, token);
23640
+ deleteCwd = requireValue9(rest, token);
23270
23641
  break;
23271
23642
  default:
23272
23643
  throw new Error(`Unknown delete option: ${token}`);
@@ -23300,13 +23671,13 @@ function parseOssArgs(tokens) {
23300
23671
  const token = rest.shift();
23301
23672
  switch (token) {
23302
23673
  case "--bucket":
23303
- bucket = requireValue8(rest, token);
23674
+ bucket = requireValue9(rest, token);
23304
23675
  break;
23305
23676
  case "--file":
23306
- filePath = requireValue8(rest, token);
23677
+ filePath = requireValue9(rest, token);
23307
23678
  break;
23308
23679
  case "--key":
23309
- objectKey = requireValue8(rest, token);
23680
+ objectKey = requireValue9(rest, token);
23310
23681
  break;
23311
23682
  default:
23312
23683
  throw new Error(`Unknown oss option: ${token}`);
@@ -23339,7 +23710,7 @@ function parseEnvArgs(tokens) {
23339
23710
  throw new Error("Only one env action is allowed.");
23340
23711
  }
23341
23712
  action = "set";
23342
- key = requireValue8(rest, token);
23713
+ key = requireValue9(rest, token);
23343
23714
  break;
23344
23715
  case "--list":
23345
23716
  if (action) {
@@ -23352,17 +23723,17 @@ function parseEnvArgs(tokens) {
23352
23723
  throw new Error("Only one env action is allowed.");
23353
23724
  }
23354
23725
  action = "delete";
23355
- key = requireValue8(rest, token);
23726
+ key = requireValue9(rest, token);
23356
23727
  break;
23357
23728
  case "--value":
23358
- value = requireValue8(rest, token);
23729
+ value = requireValue9(rest, token);
23359
23730
  break;
23360
23731
  case "--verbose":
23361
23732
  case "-v":
23362
23733
  verbose = true;
23363
23734
  break;
23364
23735
  case "--cwd":
23365
- cwd = requireValue8(rest, token);
23736
+ cwd = requireValue9(rest, token);
23366
23737
  break;
23367
23738
  default:
23368
23739
  throw new Error(`Unknown env option: ${token}`);
@@ -23420,7 +23791,7 @@ function parseCommitArgs(tokens) {
23420
23791
  push = true;
23421
23792
  break;
23422
23793
  case "--cwd":
23423
- cwd = requireValue8(rest, token);
23794
+ cwd = requireValue9(rest, token);
23424
23795
  break;
23425
23796
  default:
23426
23797
  throw new Error(`Unknown commit option: ${token}`);
@@ -23436,10 +23807,10 @@ function parseSummaryArgs(tokens) {
23436
23807
  const token = rest.shift();
23437
23808
  switch (token) {
23438
23809
  case "--pr":
23439
- prRef = requireValue8(rest, token);
23810
+ prRef = requireValue9(rest, token);
23440
23811
  break;
23441
23812
  case "--cwd":
23442
- cwd = requireValue8(rest, token);
23813
+ cwd = requireValue9(rest, token);
23443
23814
  break;
23444
23815
  default:
23445
23816
  throw new Error(`Unknown summary option: ${token}`);
@@ -23464,13 +23835,13 @@ function parseQuizArgs(tokens) {
23464
23835
  const token = rest.shift();
23465
23836
  switch (token) {
23466
23837
  case "--paper-id":
23467
- paperId = requireValue8(rest, token);
23838
+ paperId = requireValue9(rest, token);
23468
23839
  break;
23469
23840
  case "--base-url":
23470
- apiBaseUrl = requireValue8(rest, token);
23841
+ apiBaseUrl = requireValue9(rest, token);
23471
23842
  break;
23472
23843
  case "--link-base":
23473
- linkBaseUrl = requireValue8(rest, token);
23844
+ linkBaseUrl = requireValue9(rest, token);
23474
23845
  break;
23475
23846
  default:
23476
23847
  throw new Error(`Unknown quiz create-draft option: ${token}`);
@@ -23496,16 +23867,16 @@ function parseQuizArgs(tokens) {
23496
23867
  const token = rest.shift();
23497
23868
  switch (token) {
23498
23869
  case "--paper-id":
23499
- paperId = requireValue8(rest, token);
23870
+ paperId = requireValue9(rest, token);
23500
23871
  break;
23501
23872
  case "--file":
23502
- filePath = requireValue8(rest, token);
23873
+ filePath = requireValue9(rest, token);
23503
23874
  break;
23504
23875
  case "--base-url":
23505
- apiBaseUrl = requireValue8(rest, token);
23876
+ apiBaseUrl = requireValue9(rest, token);
23506
23877
  break;
23507
23878
  case "--link-base":
23508
- linkBaseUrl = requireValue8(rest, token);
23879
+ linkBaseUrl = requireValue9(rest, token);
23509
23880
  break;
23510
23881
  default:
23511
23882
  throw new Error(`Unknown quiz update-meta option: ${token}`);
@@ -23535,16 +23906,16 @@ function parseQuizArgs(tokens) {
23535
23906
  const token = rest.shift();
23536
23907
  switch (token) {
23537
23908
  case "--paper-id":
23538
- paperId = requireValue8(rest, token);
23909
+ paperId = requireValue9(rest, token);
23539
23910
  break;
23540
23911
  case "--file":
23541
- filePath = requireValue8(rest, token);
23912
+ filePath = requireValue9(rest, token);
23542
23913
  break;
23543
23914
  case "--base-url":
23544
- apiBaseUrl = requireValue8(rest, token);
23915
+ apiBaseUrl = requireValue9(rest, token);
23545
23916
  break;
23546
23917
  case "--link-base":
23547
- linkBaseUrl = requireValue8(rest, token);
23918
+ linkBaseUrl = requireValue9(rest, token);
23548
23919
  break;
23549
23920
  default:
23550
23921
  throw new Error(`Unknown quiz append-step option: ${token}`);
@@ -23575,19 +23946,19 @@ function parseQuizArgs(tokens) {
23575
23946
  const token = rest.shift();
23576
23947
  switch (token) {
23577
23948
  case "--paper-id":
23578
- paperId = requireValue8(rest, token);
23949
+ paperId = requireValue9(rest, token);
23579
23950
  break;
23580
23951
  case "--step-id":
23581
- stepId = requireValue8(rest, token);
23952
+ stepId = requireValue9(rest, token);
23582
23953
  break;
23583
23954
  case "--file":
23584
- filePath = requireValue8(rest, token);
23955
+ filePath = requireValue9(rest, token);
23585
23956
  break;
23586
23957
  case "--base-url":
23587
- apiBaseUrl = requireValue8(rest, token);
23958
+ apiBaseUrl = requireValue9(rest, token);
23588
23959
  break;
23589
23960
  case "--link-base":
23590
- linkBaseUrl = requireValue8(rest, token);
23961
+ linkBaseUrl = requireValue9(rest, token);
23591
23962
  break;
23592
23963
  default:
23593
23964
  throw new Error(`Unknown quiz update-step option: ${token}`);
@@ -23621,16 +23992,16 @@ function parseQuizArgs(tokens) {
23621
23992
  const token = rest.shift();
23622
23993
  switch (token) {
23623
23994
  case "--paper-id":
23624
- paperId = requireValue8(rest, token);
23995
+ paperId = requireValue9(rest, token);
23625
23996
  break;
23626
23997
  case "--step-ids":
23627
- stepIdsRaw = requireValue8(rest, token);
23998
+ stepIdsRaw = requireValue9(rest, token);
23628
23999
  break;
23629
24000
  case "--base-url":
23630
- apiBaseUrl = requireValue8(rest, token);
24001
+ apiBaseUrl = requireValue9(rest, token);
23631
24002
  break;
23632
24003
  case "--link-base":
23633
- linkBaseUrl = requireValue8(rest, token);
24004
+ linkBaseUrl = requireValue9(rest, token);
23634
24005
  break;
23635
24006
  default:
23636
24007
  throw new Error(`Unknown quiz reorder option: ${token}`);
@@ -23663,13 +24034,13 @@ function parseQuizArgs(tokens) {
23663
24034
  const token = rest.shift();
23664
24035
  switch (token) {
23665
24036
  case "--paper-id":
23666
- paperId = requireValue8(rest, token);
24037
+ paperId = requireValue9(rest, token);
23667
24038
  break;
23668
24039
  case "--base-url":
23669
- apiBaseUrl = requireValue8(rest, token);
24040
+ apiBaseUrl = requireValue9(rest, token);
23670
24041
  break;
23671
24042
  case "--link-base":
23672
- linkBaseUrl = requireValue8(rest, token);
24043
+ linkBaseUrl = requireValue9(rest, token);
23673
24044
  break;
23674
24045
  default:
23675
24046
  throw new Error(`Unknown quiz activate option: ${token}`);
@@ -23694,13 +24065,13 @@ function parseQuizArgs(tokens) {
23694
24065
  const token = rest.shift();
23695
24066
  switch (token) {
23696
24067
  case "--paper-id":
23697
- paperId = requireValue8(rest, token);
24068
+ paperId = requireValue9(rest, token);
23698
24069
  break;
23699
24070
  case "--base-url":
23700
- apiBaseUrl = requireValue8(rest, token);
24071
+ apiBaseUrl = requireValue9(rest, token);
23701
24072
  break;
23702
24073
  case "--link-base":
23703
- linkBaseUrl = requireValue8(rest, token);
24074
+ linkBaseUrl = requireValue9(rest, token);
23704
24075
  break;
23705
24076
  default:
23706
24077
  throw new Error(`Unknown quiz view option: ${token}`);
@@ -23729,22 +24100,22 @@ function parseQuizArgs(tokens) {
23729
24100
  const token = rest.shift();
23730
24101
  switch (token) {
23731
24102
  case "--paper-id":
23732
- paperId = requireValue8(rest, token);
24103
+ paperId = requireValue9(rest, token);
23733
24104
  break;
23734
24105
  case "--step-id":
23735
- stepId = requireValue8(rest, token);
24106
+ stepId = requireValue9(rest, token);
23736
24107
  break;
23737
24108
  case "--file":
23738
- filePath = requireValue8(rest, token);
24109
+ filePath = requireValue9(rest, token);
23739
24110
  break;
23740
24111
  case "--new-paper-id":
23741
- newPaperId = requireValue8(rest, token);
24112
+ newPaperId = requireValue9(rest, token);
23742
24113
  break;
23743
24114
  case "--base-url":
23744
- apiBaseUrl = requireValue8(rest, token);
24115
+ apiBaseUrl = requireValue9(rest, token);
23745
24116
  break;
23746
24117
  case "--link-base":
23747
- linkBaseUrl = requireValue8(rest, token);
24118
+ linkBaseUrl = requireValue9(rest, token);
23748
24119
  break;
23749
24120
  case "--activate":
23750
24121
  activate = true;
@@ -23834,10 +24205,10 @@ function parseLinearPrArgs(tokens) {
23834
24205
  const token = rest.shift();
23835
24206
  switch (token) {
23836
24207
  case "--account":
23837
- account = requireValue8(rest, token);
24208
+ account = requireValue9(rest, token);
23838
24209
  break;
23839
24210
  case "--cwd":
23840
- cwd = requireValue8(rest, token);
24211
+ cwd = requireValue9(rest, token);
23841
24212
  break;
23842
24213
  default:
23843
24214
  throw new Error(`Unknown linear option: ${token}`);
@@ -23866,35 +24237,35 @@ function parseLinearCreateArgs(tokens) {
23866
24237
  const token = rest.shift();
23867
24238
  switch (token) {
23868
24239
  case "--account":
23869
- account = requireValue8(rest, token);
24240
+ account = requireValue9(rest, token);
23870
24241
  break;
23871
24242
  case "--repl":
23872
24243
  useRepl = true;
23873
24244
  break;
23874
24245
  case "--title":
23875
- title = requireValue8(rest, token);
24246
+ title = requireValue9(rest, token);
23876
24247
  break;
23877
24248
  case "--desc":
23878
24249
  case "--description":
23879
- description = decodeEscapedNewlines(requireValue8(rest, token));
24250
+ description = decodeEscapedNewlines(requireValue9(rest, token));
23880
24251
  break;
23881
24252
  case "--team-id":
23882
- teamId = requireValue8(rest, token);
24253
+ teamId = requireValue9(rest, token);
23883
24254
  break;
23884
24255
  case "--team-key":
23885
- teamKey = requireValue8(rest, token);
24256
+ teamKey = requireValue9(rest, token);
23886
24257
  break;
23887
24258
  case "--priority":
23888
- priority = parseLinearPriority(requireValue8(rest, token));
24259
+ priority = parseLinearPriority(requireValue9(rest, token));
23889
24260
  break;
23890
24261
  case "--parent-id":
23891
- parentId = requireValue8(rest, token);
24262
+ parentId = requireValue9(rest, token);
23892
24263
  break;
23893
24264
  case "--state-id":
23894
- stateId = requireValue8(rest, token);
24265
+ stateId = requireValue9(rest, token);
23895
24266
  break;
23896
24267
  case "--cwd":
23897
- cwd = requireValue8(rest, token);
24268
+ cwd = requireValue9(rest, token);
23898
24269
  break;
23899
24270
  default:
23900
24271
  throw new Error(`Unknown linear option: ${token}`);
@@ -23929,10 +24300,10 @@ function parseLinearWhoamiArgs(tokens) {
23929
24300
  const token = rest.shift();
23930
24301
  switch (token) {
23931
24302
  case "--account":
23932
- account = requireValue8(rest, token);
24303
+ account = requireValue9(rest, token);
23933
24304
  break;
23934
24305
  case "--cwd":
23935
- cwd = requireValue8(rest, token);
24306
+ cwd = requireValue9(rest, token);
23936
24307
  break;
23937
24308
  default:
23938
24309
  throw new Error(`Unknown linear option: ${token}`);
@@ -23957,10 +24328,10 @@ function parseLinearViewArgs(tokens) {
23957
24328
  const token = rest.shift();
23958
24329
  switch (token) {
23959
24330
  case "--account":
23960
- account = requireValue8(rest, token);
24331
+ account = requireValue9(rest, token);
23961
24332
  break;
23962
24333
  case "--cwd":
23963
- cwd = requireValue8(rest, token);
24334
+ cwd = requireValue9(rest, token);
23964
24335
  break;
23965
24336
  default:
23966
24337
  throw new Error(`Unknown linear option: ${token}`);
@@ -23995,32 +24366,32 @@ function parseLinearUpdateArgs(tokens) {
23995
24366
  const token = rest.shift();
23996
24367
  switch (token) {
23997
24368
  case "--account":
23998
- account = requireValue8(rest, token);
24369
+ account = requireValue9(rest, token);
23999
24370
  break;
24000
24371
  case "--title":
24001
- title = requireValue8(rest, token);
24372
+ title = requireValue9(rest, token);
24002
24373
  break;
24003
24374
  case "--desc":
24004
24375
  case "--description":
24005
- description = decodeEscapedNewlines(requireValue8(rest, token));
24376
+ description = decodeEscapedNewlines(requireValue9(rest, token));
24006
24377
  break;
24007
24378
  case "--team-id":
24008
- teamId = requireValue8(rest, token);
24379
+ teamId = requireValue9(rest, token);
24009
24380
  break;
24010
24381
  case "--team-key":
24011
- teamKey = requireValue8(rest, token);
24382
+ teamKey = requireValue9(rest, token);
24012
24383
  break;
24013
24384
  case "--priority":
24014
- priority = parseLinearPriority(requireValue8(rest, token));
24385
+ priority = parseLinearPriority(requireValue9(rest, token));
24015
24386
  break;
24016
24387
  case "--parent-id":
24017
- parentId = requireValue8(rest, token);
24388
+ parentId = requireValue9(rest, token);
24018
24389
  break;
24019
24390
  case "--state-id":
24020
- stateId = requireValue8(rest, token);
24391
+ stateId = requireValue9(rest, token);
24021
24392
  break;
24022
24393
  case "--cwd":
24023
- cwd = requireValue8(rest, token);
24394
+ cwd = requireValue9(rest, token);
24024
24395
  break;
24025
24396
  default:
24026
24397
  throw new Error(`Unknown linear option: ${token}`);
@@ -24058,10 +24429,10 @@ function parseLinearSubIssuesArgs(tokens) {
24058
24429
  const token = rest.shift();
24059
24430
  switch (token) {
24060
24431
  case "--account":
24061
- account = requireValue8(rest, token);
24432
+ account = requireValue9(rest, token);
24062
24433
  break;
24063
24434
  case "--cwd":
24064
- cwd = requireValue8(rest, token);
24435
+ cwd = requireValue9(rest, token);
24065
24436
  break;
24066
24437
  default:
24067
24438
  throw new Error(`Unknown linear option: ${token}`);
@@ -24088,15 +24459,15 @@ function parseLinearCommentArgs(tokens) {
24088
24459
  const token = rest.shift();
24089
24460
  switch (token) {
24090
24461
  case "--account":
24091
- account = requireValue8(rest, token);
24462
+ account = requireValue9(rest, token);
24092
24463
  break;
24093
24464
  case "--body":
24094
24465
  case "--desc":
24095
24466
  case "--description":
24096
- body = decodeEscapedNewlines(requireValue8(rest, token));
24467
+ body = decodeEscapedNewlines(requireValue9(rest, token));
24097
24468
  break;
24098
24469
  case "--cwd":
24099
- cwd = requireValue8(rest, token);
24470
+ cwd = requireValue9(rest, token);
24100
24471
  break;
24101
24472
  default:
24102
24473
  throw new Error(`Unknown linear option: ${token}`);
@@ -24126,10 +24497,10 @@ function parseLinearCommentsArgs(tokens) {
24126
24497
  const token = rest.shift();
24127
24498
  switch (token) {
24128
24499
  case "--account":
24129
- account = requireValue8(rest, token);
24500
+ account = requireValue9(rest, token);
24130
24501
  break;
24131
24502
  case "--cwd":
24132
- cwd = requireValue8(rest, token);
24503
+ cwd = requireValue9(rest, token);
24133
24504
  break;
24134
24505
  default:
24135
24506
  throw new Error(`Unknown linear option: ${token}`);
@@ -24153,16 +24524,16 @@ function parseLinearCycleArgs(tokens) {
24153
24524
  const token = rest.shift();
24154
24525
  switch (token) {
24155
24526
  case "--account":
24156
- account = requireValue8(rest, token);
24527
+ account = requireValue9(rest, token);
24157
24528
  break;
24158
24529
  case "--team-id":
24159
- teamId = requireValue8(rest, token);
24530
+ teamId = requireValue9(rest, token);
24160
24531
  break;
24161
24532
  case "--team-key":
24162
- teamKey = requireValue8(rest, token);
24533
+ teamKey = requireValue9(rest, token);
24163
24534
  break;
24164
24535
  case "--cwd":
24165
- cwd = requireValue8(rest, token);
24536
+ cwd = requireValue9(rest, token);
24166
24537
  break;
24167
24538
  default:
24168
24539
  throw new Error(`Unknown linear option: ${token}`);
@@ -24185,10 +24556,10 @@ function parseLinearTeamsArgs(tokens) {
24185
24556
  const token = rest.shift();
24186
24557
  switch (token) {
24187
24558
  case "--account":
24188
- account = requireValue8(rest, token);
24559
+ account = requireValue9(rest, token);
24189
24560
  break;
24190
24561
  case "--cwd":
24191
- cwd = requireValue8(rest, token);
24562
+ cwd = requireValue9(rest, token);
24192
24563
  break;
24193
24564
  default:
24194
24565
  throw new Error(`Unknown linear option: ${token}`);
@@ -24215,16 +24586,16 @@ function parseLinearUserIssuesArgs(tokens) {
24215
24586
  const token = rest.shift();
24216
24587
  switch (token) {
24217
24588
  case "--account":
24218
- account = requireValue8(rest, token);
24589
+ account = requireValue9(rest, token);
24219
24590
  break;
24220
24591
  case "--cycle":
24221
- cycle = parseLinearCycle(requireValue8(rest, token));
24592
+ cycle = parseLinearCycle(requireValue9(rest, token));
24222
24593
  break;
24223
24594
  case "--status":
24224
- status = parseLinearStatus(requireValue8(rest, token));
24595
+ status = parseLinearStatus(requireValue9(rest, token));
24225
24596
  break;
24226
24597
  case "--cwd":
24227
- cwd = requireValue8(rest, token);
24598
+ cwd = requireValue9(rest, token);
24228
24599
  break;
24229
24600
  default:
24230
24601
  throw new Error(`Unknown linear option: ${token}`);
@@ -24258,28 +24629,28 @@ function parseLinearIssuesArgs(tokens) {
24258
24629
  const token = rest.shift();
24259
24630
  switch (token) {
24260
24631
  case "--account":
24261
- account = requireValue8(rest, token);
24632
+ account = requireValue9(rest, token);
24262
24633
  break;
24263
24634
  case "--team-id":
24264
- teamId = requireValue8(rest, token);
24635
+ teamId = requireValue9(rest, token);
24265
24636
  break;
24266
24637
  case "--team-key":
24267
- teamKey = requireValue8(rest, token);
24638
+ teamKey = requireValue9(rest, token);
24268
24639
  break;
24269
24640
  case "--user":
24270
- user = requireValue8(rest, token);
24641
+ user = requireValue9(rest, token);
24271
24642
  break;
24272
24643
  case "--cycle":
24273
- cycle = parseLinearCycle(requireValue8(rest, token));
24644
+ cycle = parseLinearCycle(requireValue9(rest, token));
24274
24645
  break;
24275
24646
  case "--status":
24276
- status = parseLinearStatus(requireValue8(rest, token));
24647
+ status = parseLinearStatus(requireValue9(rest, token));
24277
24648
  break;
24278
24649
  case "--query":
24279
- query = requireValue8(rest, token).trim();
24650
+ query = requireValue9(rest, token).trim();
24280
24651
  break;
24281
24652
  case "--limit": {
24282
- const value = Number.parseInt(requireValue8(rest, token), 10);
24653
+ const value = Number.parseInt(requireValue9(rest, token), 10);
24283
24654
  if (!Number.isInteger(value) || value < 1 || value > 250) {
24284
24655
  throw new Error("Invalid --limit. Expected an integer between 1 and 250.");
24285
24656
  }
@@ -24287,7 +24658,7 @@ function parseLinearIssuesArgs(tokens) {
24287
24658
  break;
24288
24659
  }
24289
24660
  case "--cwd":
24290
- cwd = requireValue8(rest, token);
24661
+ cwd = requireValue9(rest, token);
24291
24662
  break;
24292
24663
  default:
24293
24664
  throw new Error(`Unknown linear option: ${token}`);
@@ -24328,10 +24699,10 @@ function parseLinearLegacyArgs(tokens) {
24328
24699
  useScreenshot = true;
24329
24700
  break;
24330
24701
  case "--account":
24331
- account = requireValue8(rest, token);
24702
+ account = requireValue9(rest, token);
24332
24703
  break;
24333
24704
  case "--cwd":
24334
- cwd = requireValue8(rest, token);
24705
+ cwd = requireValue9(rest, token);
24335
24706
  break;
24336
24707
  default:
24337
24708
  throw new Error(`Unknown linear option: ${token}`);
@@ -24425,19 +24796,19 @@ function parseNotionArgs(tokens) {
24425
24796
  const token = rest.shift();
24426
24797
  switch (token) {
24427
24798
  case "--parent":
24428
- parentPageId = requireValue8(rest, token);
24799
+ parentPageId = requireValue9(rest, token);
24429
24800
  break;
24430
24801
  case "--title":
24431
- title = requireValue8(rest, token);
24802
+ title = requireValue9(rest, token);
24432
24803
  break;
24433
24804
  case "--private":
24434
24805
  isPrivate = true;
24435
24806
  break;
24436
24807
  case "--content":
24437
- content2 = requireValue8(rest, token);
24808
+ content2 = requireValue9(rest, token);
24438
24809
  break;
24439
24810
  case "--file":
24440
- filePath2 = requireValue8(rest, token);
24811
+ filePath2 = requireValue9(rest, token);
24441
24812
  break;
24442
24813
  default:
24443
24814
  throw new Error(`Unknown notion option: ${token}`);
@@ -24481,10 +24852,10 @@ function parseNotionArgs(tokens) {
24481
24852
  const token = rest.shift();
24482
24853
  switch (token) {
24483
24854
  case "--content":
24484
- content = requireValue8(rest, token);
24855
+ content = requireValue9(rest, token);
24485
24856
  break;
24486
24857
  case "--file":
24487
- filePath = requireValue8(rest, token);
24858
+ filePath = requireValue9(rest, token);
24488
24859
  break;
24489
24860
  case "--append":
24490
24861
  append = true;
@@ -24529,11 +24900,11 @@ function parseRandomArgs(tokens) {
24529
24900
  mode = "easy";
24530
24901
  break;
24531
24902
  case "--length":
24532
- length = parsePositiveInt(requireValue8(rest, token), token);
24903
+ length = parsePositiveInt(requireValue9(rest, token), token);
24533
24904
  seenLength = true;
24534
24905
  break;
24535
24906
  case "--charset": {
24536
- const value = requireValue8(rest, token);
24907
+ const value = requireValue9(rest, token);
24537
24908
  if (!["base64url", "hex", "alnum", "ascii"].includes(value)) {
24538
24909
  throw new Error(
24539
24910
  `Invalid --charset value: ${value}. Use base64url|hex|alnum|ascii.`
@@ -24544,18 +24915,18 @@ function parseRandomArgs(tokens) {
24544
24915
  break;
24545
24916
  }
24546
24917
  case "--count":
24547
- count = parsePositiveInt(requireValue8(rest, token), token);
24918
+ count = parsePositiveInt(requireValue9(rest, token), token);
24548
24919
  break;
24549
24920
  case "--words":
24550
- words = parsePositiveInt(requireValue8(rest, token), token);
24921
+ words = parsePositiveInt(requireValue9(rest, token), token);
24551
24922
  seenWords = true;
24552
24923
  break;
24553
24924
  case "--digits":
24554
- digits = parseNonNegativeInt(requireValue8(rest, token), token);
24925
+ digits = parseNonNegativeInt(requireValue9(rest, token), token);
24555
24926
  seenDigits = true;
24556
24927
  break;
24557
24928
  case "--separator":
24558
- separator = requireValue8(rest, token);
24929
+ separator = requireValue9(rest, token);
24559
24930
  seenSeparator = true;
24560
24931
  break;
24561
24932
  default:
@@ -24586,40 +24957,7 @@ function parseRandomArgs(tokens) {
24586
24957
  count
24587
24958
  };
24588
24959
  }
24589
- function parseCollectArgs(tokens) {
24590
- const rest = [...tokens];
24591
- const options = {
24592
- endpoint: "http://localhost:9222",
24593
- json: false,
24594
- mode: "list",
24595
- threadName: void 0
24596
- };
24597
- while (rest.length > 0) {
24598
- const token = rest.shift();
24599
- switch (token) {
24600
- case "--endpoint":
24601
- options.endpoint = requireValue8(rest, token);
24602
- break;
24603
- case "--json":
24604
- options.json = true;
24605
- break;
24606
- case "--list":
24607
- options.mode = "list";
24608
- break;
24609
- case "--thread":
24610
- options.mode = "thread";
24611
- options.threadName = requireValue8(rest, token);
24612
- break;
24613
- default:
24614
- throw new Error(`Unknown collect option: ${token}`);
24615
- }
24616
- }
24617
- if (options.mode === "thread" && !options.threadName) {
24618
- throw new Error("Missing thread name. Usage: collect --thread <name>.");
24619
- }
24620
- return { type: "collect" /* Collect */, ...options };
24621
- }
24622
- function requireValue8(tokens, optionName) {
24960
+ function requireValue9(tokens, optionName) {
24623
24961
  const value = tokens.shift();
24624
24962
  if (!value) {
24625
24963
  throw new Error(`Missing value for ${optionName}`);