@pmate/cli 0.21.16 → 0.21.17
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.d.ts +1 -0
- package/dist/index.js +478 -531
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9435,8 +9435,8 @@ __export(index_exports, {
|
|
|
9435
9435
|
parseCommandArgs: () => parseCommandArgs
|
|
9436
9436
|
});
|
|
9437
9437
|
module.exports = __toCommonJS(index_exports);
|
|
9438
|
-
var
|
|
9439
|
-
var
|
|
9438
|
+
var import_node_fs22 = require("fs");
|
|
9439
|
+
var import_node_path27 = __toESM(require("path"));
|
|
9440
9440
|
var import_chalk4 = __toESM(require("chalk"));
|
|
9441
9441
|
|
|
9442
9442
|
// src/cli.ts
|
|
@@ -14585,9 +14585,9 @@ ${indent}\`\`\``;
|
|
|
14585
14585
|
static richTextToPlain(richText) {
|
|
14586
14586
|
return richText.map((item) => item.plain_text ?? item.text?.content ?? "").join("").trim();
|
|
14587
14587
|
}
|
|
14588
|
-
static async requestJson(
|
|
14588
|
+
static async requestJson(path28, init) {
|
|
14589
14589
|
const token = this.getToken();
|
|
14590
|
-
const response = await fetch(`${this.baseUrl}${
|
|
14590
|
+
const response = await fetch(`${this.baseUrl}${path28}`, {
|
|
14591
14591
|
method: init.method,
|
|
14592
14592
|
headers: {
|
|
14593
14593
|
Authorization: `Bearer ${token}`,
|
|
@@ -15664,6 +15664,10 @@ var QuizCommandHandler = class {
|
|
|
15664
15664
|
|
|
15665
15665
|
// src/commands/CollectCommandHandler.ts
|
|
15666
15666
|
var import_playwright = require("playwright");
|
|
15667
|
+
var import_node_crypto4 = require("crypto");
|
|
15668
|
+
var import_node_fs12 = require("fs");
|
|
15669
|
+
var import_node_os7 = __toESM(require("os"));
|
|
15670
|
+
var import_node_path17 = __toESM(require("path"));
|
|
15667
15671
|
|
|
15668
15672
|
// src/collectStore.ts
|
|
15669
15673
|
var import_node_crypto3 = require("crypto");
|
|
@@ -15683,30 +15687,18 @@ function toThreadKey(name) {
|
|
|
15683
15687
|
return `${base}-${suffix}`;
|
|
15684
15688
|
}
|
|
15685
15689
|
async function readStoredThread(rootDir, threadKey) {
|
|
15686
|
-
const filePath =
|
|
15690
|
+
const filePath = getThreadFilePath(rootDir, threadKey);
|
|
15687
15691
|
try {
|
|
15688
15692
|
const raw = await import_node_fs11.promises.readFile(filePath, "utf8");
|
|
15689
|
-
|
|
15690
|
-
if ("messages" in parsed && Array.isArray(parsed.messages)) {
|
|
15691
|
-
return parsed;
|
|
15692
|
-
}
|
|
15693
|
-
const messages2 = await readStoredMessages(rootDir, threadKey);
|
|
15694
|
-
return {
|
|
15695
|
-
...parsed,
|
|
15696
|
-
messages: messages2
|
|
15697
|
-
};
|
|
15693
|
+
return JSON.parse(raw);
|
|
15698
15694
|
} catch {
|
|
15699
|
-
return
|
|
15695
|
+
return null;
|
|
15700
15696
|
}
|
|
15701
15697
|
}
|
|
15702
15698
|
async function writeStoredThread(rootDir, thread) {
|
|
15703
|
-
const
|
|
15704
|
-
|
|
15705
|
-
|
|
15706
|
-
await import_node_fs11.promises.mkdir(import_node_path16.default.dirname(metaPath), { recursive: true });
|
|
15707
|
-
await import_node_fs11.promises.writeFile(metaPath, JSON.stringify(meta, null, 2) + "\n", "utf8");
|
|
15708
|
-
const body = messages2.map((message) => JSON.stringify(message)).join("\n");
|
|
15709
|
-
await import_node_fs11.promises.writeFile(messagePath, `${body}${body ? "\n" : ""}`, "utf8");
|
|
15699
|
+
const filePath = getThreadFilePath(rootDir, thread.threadKey);
|
|
15700
|
+
await import_node_fs11.promises.mkdir(import_node_path16.default.dirname(filePath), { recursive: true });
|
|
15701
|
+
await import_node_fs11.promises.writeFile(filePath, JSON.stringify(thread, null, 2) + "\n", "utf8");
|
|
15710
15702
|
}
|
|
15711
15703
|
async function writeStoredIndex(rootDir, index) {
|
|
15712
15704
|
await import_node_fs11.promises.mkdir(rootDir, { recursive: true });
|
|
@@ -15714,91 +15706,22 @@ async function writeStoredIndex(rootDir, index) {
|
|
|
15714
15706
|
await import_node_fs11.promises.writeFile(filePath, JSON.stringify(index, null, 2) + "\n", "utf8");
|
|
15715
15707
|
}
|
|
15716
15708
|
function mergeMessages(existing, incoming) {
|
|
15717
|
-
const
|
|
15718
|
-
existing.map((message) => normalizeMessageId(message.messageId)).filter((value) => !!value)
|
|
15719
|
-
);
|
|
15709
|
+
const seen = new Set(existing.map((message) => message.hash));
|
|
15720
15710
|
const merged = [...existing];
|
|
15721
15711
|
let added = 0;
|
|
15722
15712
|
for (const message of incoming) {
|
|
15723
|
-
|
|
15724
|
-
if (incomingMessageId && seenMessageIds.has(incomingMessageId)) {
|
|
15725
|
-
continue;
|
|
15726
|
-
}
|
|
15727
|
-
const upgradeIndex = merged.findIndex((current) => shouldUpgradeMessage(current, message));
|
|
15728
|
-
if (upgradeIndex >= 0) {
|
|
15729
|
-
merged[upgradeIndex] = message;
|
|
15730
|
-
if (incomingMessageId) {
|
|
15731
|
-
seenMessageIds.add(incomingMessageId);
|
|
15732
|
-
}
|
|
15713
|
+
if (seen.has(message.hash)) {
|
|
15733
15714
|
continue;
|
|
15734
15715
|
}
|
|
15735
|
-
|
|
15736
|
-
seenMessageIds.add(incomingMessageId);
|
|
15737
|
-
}
|
|
15716
|
+
seen.add(message.hash);
|
|
15738
15717
|
merged.push(message);
|
|
15739
15718
|
added += 1;
|
|
15740
15719
|
}
|
|
15741
15720
|
return { messages: merged, added };
|
|
15742
15721
|
}
|
|
15743
|
-
function
|
|
15744
|
-
const existingMessageId = normalizeMessageId(existing.messageId);
|
|
15745
|
-
const incomingMessageId = normalizeMessageId(incoming.messageId);
|
|
15746
|
-
if (existingMessageId && incomingMessageId && existingMessageId === incomingMessageId) {
|
|
15747
|
-
return false;
|
|
15748
|
-
}
|
|
15749
|
-
if (existing.time && incoming.time && existing.time !== incoming.time) {
|
|
15750
|
-
return false;
|
|
15751
|
-
}
|
|
15752
|
-
return normalizeMessageField(existing.sender) === normalizeMessageField(incoming.sender) && normalizeMessageField(existing.content) === normalizeMessageField(incoming.content) && joinNormalized(existing.links) === joinNormalized(incoming.links) && joinNormalized(existing.images) === joinNormalized(incoming.images) && (!!incoming.time && !existing.time);
|
|
15753
|
-
}
|
|
15754
|
-
function normalizeMessageField(value) {
|
|
15755
|
-
return (value ?? "").trim();
|
|
15756
|
-
}
|
|
15757
|
-
function normalizeMessageId(value) {
|
|
15758
|
-
const normalized = (value ?? "").trim();
|
|
15759
|
-
return normalized || null;
|
|
15760
|
-
}
|
|
15761
|
-
function joinNormalized(values) {
|
|
15762
|
-
return values.map((value) => value.trim()).join("|");
|
|
15763
|
-
}
|
|
15764
|
-
async function readStoredMessages(rootDir, threadKey) {
|
|
15765
|
-
const filePath = getThreadMessagesFilePath(rootDir, threadKey);
|
|
15766
|
-
try {
|
|
15767
|
-
const raw = await import_node_fs11.promises.readFile(filePath, "utf8");
|
|
15768
|
-
return raw.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => normalizeStoredMessage(JSON.parse(line)));
|
|
15769
|
-
} catch {
|
|
15770
|
-
return [];
|
|
15771
|
-
}
|
|
15772
|
-
}
|
|
15773
|
-
async function readLegacyStoredThread(rootDir, threadKey) {
|
|
15774
|
-
const filePath = getLegacyThreadFilePath(rootDir, threadKey);
|
|
15775
|
-
try {
|
|
15776
|
-
const raw = await import_node_fs11.promises.readFile(filePath, "utf8");
|
|
15777
|
-
return JSON.parse(raw);
|
|
15778
|
-
} catch {
|
|
15779
|
-
return null;
|
|
15780
|
-
}
|
|
15781
|
-
}
|
|
15782
|
-
function getThreadMetaFilePath(rootDir, threadKey) {
|
|
15783
|
-
return import_node_path16.default.join(rootDir, "threads", `${threadKey}.json`);
|
|
15784
|
-
}
|
|
15785
|
-
function getThreadMessagesFilePath(rootDir, threadKey) {
|
|
15786
|
-
return import_node_path16.default.join(rootDir, "threads", `${threadKey}.jsonl`);
|
|
15787
|
-
}
|
|
15788
|
-
function getLegacyThreadFilePath(rootDir, threadKey) {
|
|
15722
|
+
function getThreadFilePath(rootDir, threadKey) {
|
|
15789
15723
|
return import_node_path16.default.join(rootDir, "threads", `${threadKey}.json`);
|
|
15790
15724
|
}
|
|
15791
|
-
function normalizeStoredMessage(message) {
|
|
15792
|
-
return {
|
|
15793
|
-
messageId: normalizeMessageId(message.messageId),
|
|
15794
|
-
time: message.time ?? null,
|
|
15795
|
-
sender: message.sender ?? null,
|
|
15796
|
-
content: message.content ?? "",
|
|
15797
|
-
links: Array.isArray(message.links) ? message.links : [],
|
|
15798
|
-
images: Array.isArray(message.images) ? message.images : [],
|
|
15799
|
-
collectedAt: message.collectedAt
|
|
15800
|
-
};
|
|
15801
|
-
}
|
|
15802
15725
|
|
|
15803
15726
|
// src/commands/CollectCommandHandler.ts
|
|
15804
15727
|
var CollectCommandHandler = class {
|
|
@@ -15813,39 +15736,22 @@ var CollectCommandHandler = class {
|
|
|
15813
15736
|
if (!targetPage) {
|
|
15814
15737
|
throw new Error("Cannot find target page from CDP contexts.");
|
|
15815
15738
|
}
|
|
15816
|
-
const
|
|
15739
|
+
const { rows } = await this.locateThreadRows(targetPage);
|
|
15740
|
+
const threads = await this.extractThreads(rows);
|
|
15817
15741
|
if (threads.length === 0) {
|
|
15818
|
-
throw new Error("No threads found in
|
|
15742
|
+
throw new Error("No threads found in target page.");
|
|
15819
15743
|
}
|
|
15820
15744
|
const syncedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
15821
15745
|
const results = [];
|
|
15822
|
-
const failures = [];
|
|
15823
15746
|
for (const thread of threads) {
|
|
15824
|
-
|
|
15825
|
-
|
|
15826
|
-
|
|
15827
|
-
|
|
15828
|
-
|
|
15829
|
-
target.rootDir,
|
|
15830
|
-
target,
|
|
15831
|
-
thread,
|
|
15832
|
-
messages2,
|
|
15833
|
-
syncedAt,
|
|
15834
|
-
existing
|
|
15835
|
-
);
|
|
15836
|
-
results.push(result);
|
|
15837
|
-
} catch (error) {
|
|
15838
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
15839
|
-
failures.push({ threadName: thread.name, message });
|
|
15840
|
-
ui.warn(`Skipped thread: ${thread.name}`, message);
|
|
15841
|
-
}
|
|
15842
|
-
}
|
|
15843
|
-
if (results.length === 0) {
|
|
15844
|
-
const firstFailure = failures[0]?.message ?? "No thread could be collected.";
|
|
15845
|
-
throw new Error(firstFailure);
|
|
15747
|
+
await this.clickThreadRow(rows, thread);
|
|
15748
|
+
await targetPage.waitForTimeout(1200);
|
|
15749
|
+
const messages2 = await this.extractMessages(targetPage, thread.name);
|
|
15750
|
+
const result = await this.persistThread(target.rootDir, target, thread, messages2, syncedAt);
|
|
15751
|
+
results.push(result);
|
|
15846
15752
|
}
|
|
15847
15753
|
await this.writeIndex(target.rootDir, target, results, syncedAt);
|
|
15848
|
-
this.printSyncSummary(target.sourceKey, target.rootDir, threads.length, results
|
|
15754
|
+
this.printSyncSummary(target.sourceKey, target.rootDir, threads.length, results);
|
|
15849
15755
|
} catch (error) {
|
|
15850
15756
|
const message = error instanceof Error ? error.message : String(error);
|
|
15851
15757
|
throw new Error(`collect failed: ${message}`);
|
|
@@ -15853,10 +15759,11 @@ var CollectCommandHandler = class {
|
|
|
15853
15759
|
await browser?.close().catch(() => void 0);
|
|
15854
15760
|
}
|
|
15855
15761
|
}
|
|
15856
|
-
async persistThread(rootDir, target, thread, messages2, syncedAt
|
|
15762
|
+
async persistThread(rootDir, target, thread, messages2, syncedAt) {
|
|
15857
15763
|
const threadKey = toThreadKey(thread.name);
|
|
15764
|
+
const existing = await readStoredThread(rootDir, threadKey);
|
|
15858
15765
|
const incoming = messages2.map((message) => ({
|
|
15859
|
-
|
|
15766
|
+
hash: message.hash,
|
|
15860
15767
|
time: message.time,
|
|
15861
15768
|
sender: message.sender,
|
|
15862
15769
|
content: message.content,
|
|
@@ -15904,18 +15811,14 @@ var CollectCommandHandler = class {
|
|
|
15904
15811
|
threads
|
|
15905
15812
|
});
|
|
15906
15813
|
}
|
|
15907
|
-
printSyncSummary(sourceKey, rootDir, scannedThreads, results
|
|
15814
|
+
printSyncSummary(sourceKey, rootDir, scannedThreads, results) {
|
|
15908
15815
|
const updatedThreads = results.filter((result) => result.updated).length;
|
|
15909
15816
|
const newMessages = results.reduce((sum, result) => sum + result.addedMessages, 0);
|
|
15910
15817
|
ui.plain(`Synced source: ${sourceKey}`);
|
|
15911
15818
|
ui.plain(`Threads scanned: ${scannedThreads}`);
|
|
15912
15819
|
ui.plain(`Threads updated: ${updatedThreads}`);
|
|
15913
|
-
ui.plain(`Threads failed: ${failures.length}`);
|
|
15914
15820
|
ui.plain(`New messages: ${newMessages}`);
|
|
15915
15821
|
ui.plain(`Saved under: ${rootDir}`);
|
|
15916
|
-
for (const failure of failures.slice(0, 10)) {
|
|
15917
|
-
ui.warn(`Thread failed: ${failure.threadName}`, failure.message);
|
|
15918
|
-
}
|
|
15919
15822
|
}
|
|
15920
15823
|
async pickTargetPage(pages) {
|
|
15921
15824
|
let best = null;
|
|
@@ -15930,321 +15833,364 @@ var CollectCommandHandler = class {
|
|
|
15930
15833
|
}
|
|
15931
15834
|
return best?.page ?? null;
|
|
15932
15835
|
}
|
|
15933
|
-
async
|
|
15934
|
-
const
|
|
15935
|
-
|
|
15936
|
-
|
|
15937
|
-
|
|
15938
|
-
|
|
15939
|
-
|
|
15940
|
-
|
|
15941
|
-
|
|
15836
|
+
async locateThreadRows(page) {
|
|
15837
|
+
const preferred = page.locator(".ReactVirtualized__Grid__innerScrollContainer").first();
|
|
15838
|
+
const preferredCount = await preferred.locator(":scope > *").count().catch(() => 0);
|
|
15839
|
+
if (preferredCount >= 1) {
|
|
15840
|
+
return { rows: preferred.locator(":scope > *") };
|
|
15841
|
+
}
|
|
15842
|
+
const seeds = [
|
|
15843
|
+
'[role="list"]',
|
|
15844
|
+
'[role="listbox"]',
|
|
15845
|
+
'[class*="list" i]',
|
|
15846
|
+
'[class*="conversation" i]',
|
|
15847
|
+
'[class*="thread" i]',
|
|
15848
|
+
'[class*="chat" i]',
|
|
15849
|
+
"div"
|
|
15850
|
+
];
|
|
15851
|
+
let best = null;
|
|
15852
|
+
for (const seed of seeds) {
|
|
15853
|
+
const containers = page.locator(seed);
|
|
15854
|
+
const count = await containers.count().catch(() => 0);
|
|
15855
|
+
const max = seed === "div" ? Math.min(count, 180) : Math.min(count, 40);
|
|
15856
|
+
for (let i = 0; i < max; i += 1) {
|
|
15857
|
+
const rows = containers.nth(i).locator(":scope > *");
|
|
15858
|
+
const rowCount = await rows.count().catch(() => 0);
|
|
15859
|
+
if (rowCount < 1 || rowCount > 500) {
|
|
15860
|
+
continue;
|
|
15861
|
+
}
|
|
15862
|
+
const textCount = await containers.nth(i).locator("text=/./").count().catch(() => 0);
|
|
15863
|
+
const score = rowCount + Math.min(textCount, rowCount * 4);
|
|
15864
|
+
if (!best || score > best.score) {
|
|
15865
|
+
best = { rows, score };
|
|
15866
|
+
}
|
|
15867
|
+
}
|
|
15942
15868
|
}
|
|
15943
|
-
|
|
15944
|
-
|
|
15945
|
-
name: normalizeText(thread.name ?? ""),
|
|
15946
|
-
unread: normalizeUnreadCount(thread.unread),
|
|
15947
|
-
preview: normalizeText(thread.preview ?? ""),
|
|
15948
|
-
time: formatSentAt(thread.sentAt)
|
|
15949
|
-
})).filter((thread) => thread.conversationId && thread.name);
|
|
15950
|
-
}
|
|
15951
|
-
async extractMessages(page, thread, existingMessages) {
|
|
15952
|
-
const fromDataStore = await this.extractMessagesFromConversationData(
|
|
15953
|
-
page,
|
|
15954
|
-
thread,
|
|
15955
|
-
existingMessages
|
|
15956
|
-
);
|
|
15957
|
-
if ("error" in fromDataStore) {
|
|
15958
|
-
throw new Error(
|
|
15959
|
-
`Failed to load messages from CC data store for thread: ${thread.name} (${fromDataStore.error})`
|
|
15960
|
-
);
|
|
15869
|
+
if (!best) {
|
|
15870
|
+
throw new Error("Failed to detect thread list container.");
|
|
15961
15871
|
}
|
|
15962
|
-
return
|
|
15872
|
+
return { rows: best.rows };
|
|
15963
15873
|
}
|
|
15964
|
-
async
|
|
15965
|
-
const
|
|
15966
|
-
const result =
|
|
15967
|
-
|
|
15968
|
-
|
|
15969
|
-
|
|
15970
|
-
|
|
15971
|
-
|
|
15972
|
-
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15976
|
-
|
|
15977
|
-
|
|
15978
|
-
|
|
15979
|
-
|
|
15980
|
-
|
|
15981
|
-
|
|
15982
|
-
|
|
15983
|
-
|
|
15984
|
-
|
|
15985
|
-
|
|
15874
|
+
async extractThreads(rows) {
|
|
15875
|
+
const count = await rows.count().catch(() => 0);
|
|
15876
|
+
const result = [];
|
|
15877
|
+
for (let i = 0; i < count; i += 1) {
|
|
15878
|
+
const lines = await this.collectLines(rows.nth(i), 12);
|
|
15879
|
+
if (lines.length === 0) {
|
|
15880
|
+
continue;
|
|
15881
|
+
}
|
|
15882
|
+
const unread = this.extractUnread(lines);
|
|
15883
|
+
const time = this.findTime(lines);
|
|
15884
|
+
const name = this.findThreadName(lines, time);
|
|
15885
|
+
if (!name) {
|
|
15886
|
+
continue;
|
|
15887
|
+
}
|
|
15888
|
+
const preview = lines.find(
|
|
15889
|
+
(line) => line !== name && line !== time && !/^\d{1,4}\+?$/.test(line) && !/^\[[^\]]+\]$/.test(line)
|
|
15890
|
+
) ?? "";
|
|
15891
|
+
result.push({ index: i, name, unread, preview, time });
|
|
15892
|
+
}
|
|
15893
|
+
return dedupeThreads(result);
|
|
15894
|
+
}
|
|
15895
|
+
async extractMessages(page, threadName) {
|
|
15896
|
+
const container = await this.locateMessageContainer(page);
|
|
15897
|
+
const rows = container.locator(":scope > *");
|
|
15898
|
+
const count = await rows.count().catch(() => 0);
|
|
15899
|
+
const messages2 = [];
|
|
15900
|
+
let lastFingerprint = "";
|
|
15901
|
+
for (let i = 0; i < count; i += 1) {
|
|
15902
|
+
const row = rows.nth(i);
|
|
15903
|
+
const rawText = normalizeText(await row.textContent().catch(() => "") || "");
|
|
15904
|
+
const links = await this.extractLinks(row);
|
|
15905
|
+
const images = await this.extractImages(row);
|
|
15906
|
+
const parsed = parseMessageText(rawText);
|
|
15986
15907
|
const message = {
|
|
15987
|
-
index:
|
|
15988
|
-
|
|
15989
|
-
time:
|
|
15990
|
-
sender:
|
|
15991
|
-
content:
|
|
15992
|
-
links
|
|
15993
|
-
images
|
|
15908
|
+
index: i,
|
|
15909
|
+
hash: "",
|
|
15910
|
+
time: parsed.time,
|
|
15911
|
+
sender: parsed.sender,
|
|
15912
|
+
content: parsed.content || (images.length > 0 ? "[Image]" : ""),
|
|
15913
|
+
links,
|
|
15914
|
+
images
|
|
15994
15915
|
};
|
|
15995
|
-
|
|
15916
|
+
message.hash = computeMessageHash(threadName, message);
|
|
15917
|
+
const fingerprint = [
|
|
15918
|
+
message.time ?? "",
|
|
15919
|
+
message.sender ?? "",
|
|
15920
|
+
message.content,
|
|
15921
|
+
message.links.join("|"),
|
|
15922
|
+
message.images.join("|")
|
|
15923
|
+
].join("||");
|
|
15924
|
+
if (!message.content && message.links.length === 0 && message.images.length === 0) {
|
|
15996
15925
|
continue;
|
|
15997
15926
|
}
|
|
15998
|
-
if (
|
|
15999
|
-
|
|
15927
|
+
if (fingerprint === lastFingerprint) {
|
|
15928
|
+
continue;
|
|
16000
15929
|
}
|
|
16001
|
-
|
|
15930
|
+
lastFingerprint = fingerprint;
|
|
15931
|
+
messages2.push(message);
|
|
16002
15932
|
}
|
|
16003
|
-
return
|
|
15933
|
+
return messages2;
|
|
16004
15934
|
}
|
|
16005
|
-
async
|
|
16006
|
-
const
|
|
16007
|
-
|
|
16008
|
-
|
|
16009
|
-
|
|
16010
|
-
|
|
16011
|
-
|
|
16012
|
-
|
|
16013
|
-
if (response.exceptionDetails) {
|
|
16014
|
-
throw new Error(response.exceptionDetails.text || "Runtime.evaluate failed");
|
|
15935
|
+
async clickThreadRow(rows, matched) {
|
|
15936
|
+
const row = rows.nth(matched.index);
|
|
15937
|
+
const clicked = await this.tryClick(row);
|
|
15938
|
+
if (!clicked) {
|
|
15939
|
+
const exactInRows = rows.filter({ hasText: matched.name }).first();
|
|
15940
|
+
const exactCount = await exactInRows.count().catch(() => 0);
|
|
15941
|
+
if (exactCount > 0 && await this.tryClick(exactInRows)) {
|
|
15942
|
+
return;
|
|
16015
15943
|
}
|
|
16016
|
-
|
|
16017
|
-
} finally {
|
|
16018
|
-
await session.detach().catch(() => void 0);
|
|
15944
|
+
throw new Error(`Failed to select thread row: ${matched.name}`);
|
|
16019
15945
|
}
|
|
16020
15946
|
}
|
|
16021
|
-
|
|
16022
|
-
function normalizeText(value) {
|
|
16023
|
-
return value.replace(/\s+/g, " ").replace(/\u200B/g, "").trim();
|
|
16024
|
-
}
|
|
16025
|
-
function normalizeUnreadCount(value) {
|
|
16026
|
-
const parsed = typeof value === "number" ? value : typeof value === "string" && value.trim() ? Number.parseInt(value, 10) : 0;
|
|
16027
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
16028
|
-
}
|
|
16029
|
-
function buildListThreadsExpr() {
|
|
16030
|
-
return `(function() {
|
|
15947
|
+
async tryClick(row) {
|
|
16031
15948
|
try {
|
|
16032
|
-
|
|
16033
|
-
|
|
16034
|
-
|
|
16035
|
-
|
|
16036
|
-
|
|
16037
|
-
|
|
16038
|
-
|
|
16039
|
-
|
|
16040
|
-
|
|
16041
|
-
|
|
16042
|
-
|
|
16043
|
-
|
|
16044
|
-
|
|
16045
|
-
|
|
16046
|
-
|
|
16047
|
-
for (var i = 0; i < fields.length; i++) {
|
|
16048
|
-
var value = normalize(fields[i]);
|
|
16049
|
-
if (value) return value;
|
|
16050
|
-
}
|
|
16051
|
-
return '';
|
|
16052
|
-
}
|
|
16053
|
-
function pickPreview(model) {
|
|
16054
|
-
var attrs = typeof model.attributes === 'object' ? model.attributes : model || {};
|
|
16055
|
-
var fields = [
|
|
16056
|
-
attrs.draft,
|
|
16057
|
-
attrs.lastMessage,
|
|
16058
|
-
attrs.lastMessageText,
|
|
16059
|
-
attrs.snippet,
|
|
16060
|
-
attrs.body,
|
|
16061
|
-
];
|
|
16062
|
-
for (var i = 0; i < fields.length; i++) {
|
|
16063
|
-
var value = normalize(fields[i]);
|
|
16064
|
-
if (value) return value;
|
|
16065
|
-
}
|
|
16066
|
-
return '';
|
|
16067
|
-
}
|
|
16068
|
-
function pickUnread(model) {
|
|
16069
|
-
var attrs = typeof model.attributes === 'object' ? model.attributes : model || {};
|
|
16070
|
-
var candidates = [
|
|
16071
|
-
attrs.unreadCount,
|
|
16072
|
-
attrs.unreadMessagesCount,
|
|
16073
|
-
attrs.unread,
|
|
16074
|
-
model && model.get ? model.get('unreadCount') : null,
|
|
16075
|
-
model && model.get ? model.get('unreadMessagesCount') : null,
|
|
16076
|
-
model && model.get ? model.get('unread') : null,
|
|
16077
|
-
];
|
|
16078
|
-
for (var i = 0; i < candidates.length; i++) {
|
|
16079
|
-
var value = Number(candidates[i] || 0);
|
|
16080
|
-
if (Number.isFinite(value) && value > 0) return value;
|
|
16081
|
-
}
|
|
16082
|
-
return 0;
|
|
15949
|
+
await row.scrollIntoViewIfNeeded({ timeout: 3e3 });
|
|
15950
|
+
await row.click({ timeout: 5e3 });
|
|
15951
|
+
return true;
|
|
15952
|
+
} catch {
|
|
15953
|
+
return false;
|
|
15954
|
+
}
|
|
15955
|
+
}
|
|
15956
|
+
async extractLinks(row) {
|
|
15957
|
+
const links = row.locator("a[href]");
|
|
15958
|
+
const count = await links.count().catch(() => 0);
|
|
15959
|
+
const out = [];
|
|
15960
|
+
for (let i = 0; i < count; i += 1) {
|
|
15961
|
+
const href = await links.nth(i).getAttribute("href").catch(() => null);
|
|
15962
|
+
if (href && !out.includes(href)) {
|
|
15963
|
+
out.push(href);
|
|
16083
15964
|
}
|
|
16084
|
-
|
|
16085
|
-
|
|
16086
|
-
|
|
16087
|
-
|
|
16088
|
-
|
|
16089
|
-
|
|
16090
|
-
|
|
16091
|
-
|
|
16092
|
-
|
|
16093
|
-
|
|
16094
|
-
|
|
16095
|
-
|
|
16096
|
-
|
|
16097
|
-
|
|
15965
|
+
}
|
|
15966
|
+
return out;
|
|
15967
|
+
}
|
|
15968
|
+
async extractImages(row) {
|
|
15969
|
+
const imgs = row.locator(
|
|
15970
|
+
'img.module-image__image, img[alt="Image attached to message"]'
|
|
15971
|
+
);
|
|
15972
|
+
const count = await imgs.count().catch(() => 0);
|
|
15973
|
+
const out = [];
|
|
15974
|
+
for (let i = 0; i < count; i += 1) {
|
|
15975
|
+
const src = await imgs.nth(i).getAttribute("src").catch(() => null);
|
|
15976
|
+
if (src && !out.includes(src)) {
|
|
15977
|
+
const displayable = await toDisplayableImagePath(src);
|
|
15978
|
+
out.push(displayable);
|
|
15979
|
+
}
|
|
15980
|
+
}
|
|
15981
|
+
return out;
|
|
15982
|
+
}
|
|
15983
|
+
async locateMessageContainer(page) {
|
|
15984
|
+
const strong = page.locator(".messages");
|
|
15985
|
+
const strongCount = await strong.count().catch(() => 0);
|
|
15986
|
+
if (strongCount > 0) {
|
|
15987
|
+
let bestIdx = 0;
|
|
15988
|
+
let bestRows = -1;
|
|
15989
|
+
for (let i = 0; i < strongCount; i += 1) {
|
|
15990
|
+
const el = strong.nth(i);
|
|
15991
|
+
const visible = await el.isVisible().catch(() => false);
|
|
15992
|
+
if (!visible) {
|
|
15993
|
+
continue;
|
|
16098
15994
|
}
|
|
16099
|
-
|
|
16100
|
-
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
var candidates = [
|
|
16104
|
-
attrs.isArchived,
|
|
16105
|
-
attrs.archived,
|
|
16106
|
-
model && model.get ? model.get('isArchived') : null,
|
|
16107
|
-
model && model.get ? model.get('archived') : null,
|
|
16108
|
-
];
|
|
16109
|
-
for (var i = 0; i < candidates.length; i++) {
|
|
16110
|
-
if (candidates[i] === true) return true;
|
|
15995
|
+
const rows = await el.locator(":scope > *").count().catch(() => 0);
|
|
15996
|
+
if (rows >= bestRows) {
|
|
15997
|
+
bestRows = rows;
|
|
15998
|
+
bestIdx = i;
|
|
16111
15999
|
}
|
|
16112
|
-
return false;
|
|
16113
16000
|
}
|
|
16114
|
-
|
|
16115
|
-
|
|
16116
|
-
var privates = controller.getAllPrivateConversations();
|
|
16117
|
-
all.push.apply(all, privates.models || privates || []);
|
|
16118
|
-
}
|
|
16119
|
-
if (typeof controller.getAllGroups === 'function') {
|
|
16120
|
-
var groups = controller.getAllGroups();
|
|
16121
|
-
all.push.apply(all, groups.models || groups || []);
|
|
16122
|
-
}
|
|
16123
|
-
var seen = {};
|
|
16124
|
-
var threads = [];
|
|
16125
|
-
for (var i = 0; i < all.length; i++) {
|
|
16126
|
-
var model = all[i];
|
|
16127
|
-
var conversationId = normalize(model && model.get ? model.get('id') : model && model.id);
|
|
16128
|
-
if (!conversationId || seen[conversationId]) continue;
|
|
16129
|
-
seen[conversationId] = true;
|
|
16130
|
-
if (isArchived(model)) continue;
|
|
16131
|
-
var name = pickName(model);
|
|
16132
|
-
if (!name) continue;
|
|
16133
|
-
threads.push({
|
|
16134
|
-
conversationId: conversationId,
|
|
16135
|
-
name: name,
|
|
16136
|
-
unread: pickUnread(model),
|
|
16137
|
-
preview: pickPreview(model),
|
|
16138
|
-
sentAt: pickSentAt(model),
|
|
16139
|
-
});
|
|
16001
|
+
if (bestRows >= 0) {
|
|
16002
|
+
return strong.nth(bestIdx);
|
|
16140
16003
|
}
|
|
16141
|
-
threads.sort(function(left, right) {
|
|
16142
|
-
return (Number(right.sentAt || 0) - Number(left.sentAt || 0)) || left.name.localeCompare(right.name);
|
|
16143
|
-
});
|
|
16144
|
-
return { ok: true, threads: threads };
|
|
16145
|
-
} catch(e) {
|
|
16146
|
-
return { ok: false, reason: e && e.message ? e.message : String(e) };
|
|
16147
16004
|
}
|
|
16148
|
-
|
|
16149
|
-
|
|
16150
|
-
|
|
16151
|
-
|
|
16152
|
-
|
|
16153
|
-
|
|
16154
|
-
|
|
16155
|
-
|
|
16156
|
-
|
|
16157
|
-
|
|
16158
|
-
|
|
16159
|
-
|
|
16160
|
-
|
|
16161
|
-
|
|
16162
|
-
|
|
16163
|
-
|
|
16164
|
-
|
|
16165
|
-
|
|
16166
|
-
|
|
16167
|
-
|
|
16168
|
-
|
|
16169
|
-
|
|
16170
|
-
|
|
16171
|
-
|
|
16172
|
-
|
|
16173
|
-
|
|
16174
|
-
|
|
16175
|
-
|
|
16176
|
-
|
|
16177
|
-
|
|
16178
|
-
|
|
16005
|
+
const fallback = page.locator(".discussion-container, .conversation-stack, .main.panel, div");
|
|
16006
|
+
const count = await fallback.count().catch(() => 0);
|
|
16007
|
+
let best = null;
|
|
16008
|
+
for (let i = 0; i < Math.min(count, 280); i += 1) {
|
|
16009
|
+
const el = fallback.nth(i);
|
|
16010
|
+
const visible = await el.isVisible().catch(() => false);
|
|
16011
|
+
if (!visible) {
|
|
16012
|
+
continue;
|
|
16013
|
+
}
|
|
16014
|
+
const children = await el.locator(":scope > *").count().catch(() => 0);
|
|
16015
|
+
const texts = await el.locator("text=/./").count().catch(() => 0);
|
|
16016
|
+
const score = texts + children;
|
|
16017
|
+
if (!best || score > best.score) {
|
|
16018
|
+
best = { idx: i, score };
|
|
16019
|
+
}
|
|
16020
|
+
}
|
|
16021
|
+
if (!best) {
|
|
16022
|
+
throw new Error("Cannot find conversation container.");
|
|
16023
|
+
}
|
|
16024
|
+
return fallback.nth(best.idx);
|
|
16025
|
+
}
|
|
16026
|
+
async collectLines(row, max = 12) {
|
|
16027
|
+
const items = row.locator("text=/./");
|
|
16028
|
+
const count = await items.count().catch(() => 0);
|
|
16029
|
+
const lines = [];
|
|
16030
|
+
for (let i = 0; i < Math.min(count, max); i += 1) {
|
|
16031
|
+
const text = normalizeText(await items.nth(i).textContent().catch(() => "") || "");
|
|
16032
|
+
if (text && !lines.includes(text)) {
|
|
16033
|
+
lines.push(text);
|
|
16034
|
+
}
|
|
16035
|
+
}
|
|
16036
|
+
return lines;
|
|
16037
|
+
}
|
|
16038
|
+
extractUnread(lines) {
|
|
16039
|
+
let unread = 0;
|
|
16040
|
+
for (const line of lines) {
|
|
16041
|
+
if (!/^\d{1,4}\+?$/.test(line)) {
|
|
16042
|
+
continue;
|
|
16043
|
+
}
|
|
16044
|
+
const value = Number.parseInt(line.replace("+", ""), 10);
|
|
16045
|
+
if (Number.isFinite(value)) {
|
|
16046
|
+
unread = Math.max(unread, value);
|
|
16179
16047
|
}
|
|
16180
|
-
var conversation = typeof controller.get === 'function' ? controller.get('${escapedConversationId}') : null;
|
|
16181
|
-
if (!conversation) return { ok: false, reason: 'Conversation not found: ${escapedConversationId}' };
|
|
16182
|
-
var fetched = await signal.Data.getMessagesByConversation('${escapedConversationId}', {
|
|
16183
|
-
limit: ${limit},
|
|
16184
|
-
MessageCollection: whisper.MessageCollection,
|
|
16185
|
-
});
|
|
16186
|
-
var models = (fetched.models || fetched || []).slice();
|
|
16187
|
-
models.sort(function(left, right) {
|
|
16188
|
-
var leftSentAt = left && left.get ? (left.get('sent_at') || 0) : (left && left.sent_at) || 0;
|
|
16189
|
-
var rightSentAt = right && right.get ? (right.get('sent_at') || 0) : (right && right.sent_at) || 0;
|
|
16190
|
-
return leftSentAt - rightSentAt;
|
|
16191
|
-
});
|
|
16192
|
-
return {
|
|
16193
|
-
ok: true,
|
|
16194
|
-
conversationId: '${escapedConversationId}',
|
|
16195
|
-
messages: models.map(function(model, index) {
|
|
16196
|
-
var attrs = typeof model.attributes === 'object' ? model.attributes : model;
|
|
16197
|
-
var source = (typeof model.getSource === 'function' ? model.getSource() : attrs.source) || null;
|
|
16198
|
-
var quote = attrs.quote ? {
|
|
16199
|
-
id: attrs.quote.id || null,
|
|
16200
|
-
author: attrs.quote.author || null,
|
|
16201
|
-
text: attrs.quote.text || null,
|
|
16202
|
-
} : null;
|
|
16203
|
-
var attachments = Array.isArray(attrs.attachments) ? attrs.attachments.map(function(attachment) {
|
|
16204
|
-
return {
|
|
16205
|
-
path: attachment && attachment.path || null,
|
|
16206
|
-
contentType: attachment && attachment.contentType || null,
|
|
16207
|
-
fileName: attachment && attachment.fileName || null,
|
|
16208
|
-
};
|
|
16209
|
-
}) : [];
|
|
16210
|
-
return {
|
|
16211
|
-
index: index,
|
|
16212
|
-
body: attrs.body || '',
|
|
16213
|
-
source: source,
|
|
16214
|
-
senderName: resolveSenderName(source, model),
|
|
16215
|
-
sentAt: attrs.sent_at || attrs.timestamp || null,
|
|
16216
|
-
id: attrs.id || model.id || '',
|
|
16217
|
-
attachments: attachments,
|
|
16218
|
-
quote: quote,
|
|
16219
|
-
};
|
|
16220
|
-
}),
|
|
16221
|
-
};
|
|
16222
|
-
} catch(e) {
|
|
16223
|
-
return { ok: false, reason: e && e.message ? e.message : String(e) };
|
|
16224
16048
|
}
|
|
16225
|
-
|
|
16049
|
+
return unread;
|
|
16050
|
+
}
|
|
16051
|
+
findTime(lines) {
|
|
16052
|
+
return lines.find(
|
|
16053
|
+
(line) => /^\d{1,2}:\d{2}\s?(?:AM|PM)?$/i.test(line) || /^\d{1,2}\/\d{1,2}$/.test(line) || /^\d{4}\/\d{1,2}\/\d{1,2}$/.test(line)
|
|
16054
|
+
) ?? null;
|
|
16055
|
+
}
|
|
16056
|
+
findThreadName(lines, time) {
|
|
16057
|
+
const candidates = [];
|
|
16058
|
+
for (const line of lines) {
|
|
16059
|
+
if (line === time) {
|
|
16060
|
+
continue;
|
|
16061
|
+
}
|
|
16062
|
+
if (/^\d{1,4}\+?$/.test(line)) {
|
|
16063
|
+
continue;
|
|
16064
|
+
}
|
|
16065
|
+
if (/^\[[^\]]+\]$/.test(line)) {
|
|
16066
|
+
continue;
|
|
16067
|
+
}
|
|
16068
|
+
candidates.push(line);
|
|
16069
|
+
}
|
|
16070
|
+
const alphaNoColon = candidates.find(
|
|
16071
|
+
(line) => /[A-Za-z\u4e00-\u9fff]/.test(line) && !line.includes(":")
|
|
16072
|
+
);
|
|
16073
|
+
if (alphaNoColon) {
|
|
16074
|
+
return alphaNoColon;
|
|
16075
|
+
}
|
|
16076
|
+
const alphaPreferred = candidates.find((line) => /[A-Za-z\u4e00-\u9fff]/.test(line));
|
|
16077
|
+
if (alphaPreferred) {
|
|
16078
|
+
return alphaPreferred;
|
|
16079
|
+
}
|
|
16080
|
+
return candidates[0] ?? "";
|
|
16081
|
+
}
|
|
16082
|
+
};
|
|
16083
|
+
function dedupeThreads(threads) {
|
|
16084
|
+
const seen = /* @__PURE__ */ new Set();
|
|
16085
|
+
const result = [];
|
|
16086
|
+
for (const thread of threads) {
|
|
16087
|
+
const key = `${thread.name}::${thread.preview}::${thread.time ?? ""}`;
|
|
16088
|
+
if (seen.has(key)) {
|
|
16089
|
+
continue;
|
|
16090
|
+
}
|
|
16091
|
+
seen.add(key);
|
|
16092
|
+
result.push(thread);
|
|
16093
|
+
}
|
|
16094
|
+
return result;
|
|
16226
16095
|
}
|
|
16227
|
-
function
|
|
16228
|
-
return value.replace(
|
|
16096
|
+
function normalizeText(value) {
|
|
16097
|
+
return value.replace(/\s+/g, " ").replace(/\u200B/g, "").trim();
|
|
16229
16098
|
}
|
|
16230
|
-
function
|
|
16231
|
-
const
|
|
16232
|
-
|
|
16233
|
-
|
|
16099
|
+
function computeMessageHash(threadName, message) {
|
|
16100
|
+
const base = [
|
|
16101
|
+
normalizeText(threadName),
|
|
16102
|
+
normalizeText(message.sender ?? ""),
|
|
16103
|
+
normalizeText(message.time ?? ""),
|
|
16104
|
+
normalizeText(message.content),
|
|
16105
|
+
message.links.map(normalizeText).join("|"),
|
|
16106
|
+
message.images.map(normalizeText).join("|")
|
|
16107
|
+
].join("||");
|
|
16108
|
+
return (0, import_node_crypto4.createHash)("sha1").update(base).digest("hex").slice(0, 16);
|
|
16109
|
+
}
|
|
16110
|
+
function parseMessageText(rawText) {
|
|
16111
|
+
const text = normalizeText(rawText);
|
|
16112
|
+
if (!text) {
|
|
16113
|
+
return { time: null, sender: null, content: "" };
|
|
16114
|
+
}
|
|
16115
|
+
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+(.*)$/);
|
|
16116
|
+
if (!timeMatch) {
|
|
16117
|
+
return { time: null, sender: null, content: text };
|
|
16118
|
+
}
|
|
16119
|
+
const time = timeMatch[1];
|
|
16120
|
+
const rest = normalizeText(timeMatch[2] ?? "");
|
|
16121
|
+
if (!rest) {
|
|
16122
|
+
return { time, sender: null, content: "" };
|
|
16123
|
+
}
|
|
16124
|
+
const senderMatch = rest.match(/^([^:]{1,80}):\s*(.*)$/);
|
|
16125
|
+
if (!senderMatch) {
|
|
16126
|
+
return { time, sender: null, content: rest };
|
|
16234
16127
|
}
|
|
16235
|
-
|
|
16236
|
-
|
|
16128
|
+
return {
|
|
16129
|
+
time,
|
|
16130
|
+
sender: normalizeText(senderMatch[1] ?? "") || null,
|
|
16131
|
+
content: normalizeText(senderMatch[2] ?? "")
|
|
16132
|
+
};
|
|
16237
16133
|
}
|
|
16238
|
-
function
|
|
16239
|
-
|
|
16134
|
+
async function toDisplayableImagePath(src) {
|
|
16135
|
+
if (!import_node_path17.default.isAbsolute(src)) {
|
|
16136
|
+
return src;
|
|
16137
|
+
}
|
|
16138
|
+
const ext = import_node_path17.default.extname(src);
|
|
16139
|
+
if (ext) {
|
|
16140
|
+
return src;
|
|
16141
|
+
}
|
|
16142
|
+
try {
|
|
16143
|
+
const stat = await import_node_fs12.promises.stat(src);
|
|
16144
|
+
if (!stat.isFile()) {
|
|
16145
|
+
return src;
|
|
16146
|
+
}
|
|
16147
|
+
const fh = await import_node_fs12.promises.open(src, "r");
|
|
16148
|
+
try {
|
|
16149
|
+
const buf = Buffer.alloc(32);
|
|
16150
|
+
const { bytesRead } = await fh.read(buf, 0, 32, 0);
|
|
16151
|
+
const header = buf.subarray(0, bytesRead);
|
|
16152
|
+
const guessedExt = guessImageExtension(header);
|
|
16153
|
+
if (!guessedExt) {
|
|
16154
|
+
return src;
|
|
16155
|
+
}
|
|
16156
|
+
const cacheDir = import_node_path17.default.join(
|
|
16157
|
+
import_node_os7.default.homedir(),
|
|
16158
|
+
".pmate",
|
|
16159
|
+
"messages",
|
|
16160
|
+
"images"
|
|
16161
|
+
);
|
|
16162
|
+
await import_node_fs12.promises.mkdir(cacheDir, { recursive: true });
|
|
16163
|
+
const base = (0, import_node_crypto4.createHash)("sha1").update(src).digest("hex");
|
|
16164
|
+
const displayPath = import_node_path17.default.join(cacheDir, `${base}.${guessedExt}`);
|
|
16165
|
+
await import_node_fs12.promises.rm(displayPath, { force: true }).catch(() => void 0);
|
|
16166
|
+
await import_node_fs12.promises.copyFile(src, displayPath);
|
|
16167
|
+
return displayPath;
|
|
16168
|
+
} finally {
|
|
16169
|
+
await fh.close();
|
|
16170
|
+
}
|
|
16171
|
+
} catch {
|
|
16172
|
+
return src;
|
|
16173
|
+
}
|
|
16240
16174
|
}
|
|
16241
|
-
function
|
|
16242
|
-
|
|
16175
|
+
function guessImageExtension(header) {
|
|
16176
|
+
if (header.length >= 3 && header[0] === 255 && header[1] === 216 && header[2] === 255) {
|
|
16177
|
+
return "jpg";
|
|
16178
|
+
}
|
|
16179
|
+
if (header.length >= 8 && header[0] === 137 && header[1] === 80 && header[2] === 78 && header[3] === 71) {
|
|
16180
|
+
return "png";
|
|
16181
|
+
}
|
|
16182
|
+
if (header.length >= 4 && header[0] === 71 && header[1] === 73 && header[2] === 70 && header[3] === 56) {
|
|
16183
|
+
return "gif";
|
|
16184
|
+
}
|
|
16185
|
+
if (header.length >= 12 && header.subarray(0, 4).toString("ascii") === "RIFF" && header.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
16186
|
+
return "webp";
|
|
16187
|
+
}
|
|
16188
|
+
return null;
|
|
16243
16189
|
}
|
|
16244
16190
|
|
|
16245
16191
|
// src/commands/AgentCommandHandler.ts
|
|
16246
|
-
var
|
|
16247
|
-
var
|
|
16192
|
+
var import_node_fs13 = require("fs");
|
|
16193
|
+
var import_node_path18 = __toESM(require("path"));
|
|
16248
16194
|
init_AgentLlmClient();
|
|
16249
16195
|
init_sessionStore();
|
|
16250
16196
|
|
|
@@ -16252,7 +16198,7 @@ init_sessionStore();
|
|
|
16252
16198
|
var STORE_LOG_VERSION = 1;
|
|
16253
16199
|
var LOG_KIND_TABLE = 1e4;
|
|
16254
16200
|
var LOG_KIND_MAPPING = 6003;
|
|
16255
|
-
function
|
|
16201
|
+
function createHash4() {
|
|
16256
16202
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
16257
16203
|
}
|
|
16258
16204
|
function createDescriptor(input) {
|
|
@@ -16277,8 +16223,8 @@ function descriptorPathSegments(descriptor) {
|
|
|
16277
16223
|
return ["chains", normalized.chain, "namespaces", normalized.ns, normalized.kind, normalized.name];
|
|
16278
16224
|
}
|
|
16279
16225
|
function buildPathUrl(baseUrl, pathSegments, query) {
|
|
16280
|
-
const
|
|
16281
|
-
const url = new URL(
|
|
16226
|
+
const path28 = `/${pathSegments.map((segment) => encodeURIComponent(segment)).join("/")}`;
|
|
16227
|
+
const url = new URL(path28, baseUrl);
|
|
16282
16228
|
if (query) {
|
|
16283
16229
|
for (const [key, value] of Object.entries(query)) {
|
|
16284
16230
|
url.searchParams.set(key, String(value));
|
|
@@ -16391,7 +16337,7 @@ var Namespace = class {
|
|
|
16391
16337
|
},
|
|
16392
16338
|
appendRow: async (data) => {
|
|
16393
16339
|
const log = {
|
|
16394
|
-
hash:
|
|
16340
|
+
hash: createHash4(),
|
|
16395
16341
|
t: Date.now(),
|
|
16396
16342
|
kind: LOG_KIND_TABLE,
|
|
16397
16343
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16403,7 +16349,7 @@ var Namespace = class {
|
|
|
16403
16349
|
updateRow: async (data) => {
|
|
16404
16350
|
const { id, ...value } = data;
|
|
16405
16351
|
const log = {
|
|
16406
|
-
hash:
|
|
16352
|
+
hash: createHash4(),
|
|
16407
16353
|
t: Date.now(),
|
|
16408
16354
|
kind: LOG_KIND_TABLE,
|
|
16409
16355
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16414,7 +16360,7 @@ var Namespace = class {
|
|
|
16414
16360
|
},
|
|
16415
16361
|
deleteRow: async (id) => {
|
|
16416
16362
|
const log = {
|
|
16417
|
-
hash:
|
|
16363
|
+
hash: createHash4(),
|
|
16418
16364
|
t: Date.now(),
|
|
16419
16365
|
kind: LOG_KIND_TABLE,
|
|
16420
16366
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16457,7 +16403,7 @@ var Namespace = class {
|
|
|
16457
16403
|
},
|
|
16458
16404
|
set: async (key, value) => {
|
|
16459
16405
|
const log = {
|
|
16460
|
-
hash:
|
|
16406
|
+
hash: createHash4(),
|
|
16461
16407
|
t: Date.now(),
|
|
16462
16408
|
kind: LOG_KIND_MAPPING,
|
|
16463
16409
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16468,7 +16414,7 @@ var Namespace = class {
|
|
|
16468
16414
|
},
|
|
16469
16415
|
delete: async (key) => {
|
|
16470
16416
|
const log = {
|
|
16471
|
-
hash:
|
|
16417
|
+
hash: createHash4(),
|
|
16472
16418
|
t: Date.now(),
|
|
16473
16419
|
kind: LOG_KIND_MAPPING,
|
|
16474
16420
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16710,11 +16656,11 @@ var AgentCommandHandler = class {
|
|
|
16710
16656
|
}).token;
|
|
16711
16657
|
}
|
|
16712
16658
|
readJsonFile(filePath) {
|
|
16713
|
-
const absolutePath =
|
|
16714
|
-
if (!(0,
|
|
16659
|
+
const absolutePath = import_node_path18.default.resolve(process.cwd(), filePath);
|
|
16660
|
+
if (!(0, import_node_fs13.existsSync)(absolutePath)) {
|
|
16715
16661
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
16716
16662
|
}
|
|
16717
|
-
const raw = (0,
|
|
16663
|
+
const raw = (0, import_node_fs13.readFileSync)(absolutePath, "utf8");
|
|
16718
16664
|
try {
|
|
16719
16665
|
return JSON.parse(raw);
|
|
16720
16666
|
} catch (error) {
|
|
@@ -16725,7 +16671,7 @@ var AgentCommandHandler = class {
|
|
|
16725
16671
|
readJsonObjectFile(filePath) {
|
|
16726
16672
|
const parsed = this.readJsonFile(filePath);
|
|
16727
16673
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
16728
|
-
const absolutePath =
|
|
16674
|
+
const absolutePath = import_node_path18.default.resolve(process.cwd(), filePath);
|
|
16729
16675
|
throw new Error(`Invalid JSON in ${absolutePath}: expected an object`);
|
|
16730
16676
|
}
|
|
16731
16677
|
return parsed;
|
|
@@ -16809,8 +16755,8 @@ var AgentCommandHandler = class {
|
|
|
16809
16755
|
};
|
|
16810
16756
|
|
|
16811
16757
|
// src/commands/RunnerCommandHandler.ts
|
|
16812
|
-
var
|
|
16813
|
-
var
|
|
16758
|
+
var import_node_fs14 = require("fs");
|
|
16759
|
+
var import_node_path19 = __toESM(require("path"));
|
|
16814
16760
|
init_sessionStore();
|
|
16815
16761
|
init_namespacedRef();
|
|
16816
16762
|
var RunnerCommandHandler = class {
|
|
@@ -16905,11 +16851,11 @@ var RunnerCommandHandler = class {
|
|
|
16905
16851
|
}).token;
|
|
16906
16852
|
}
|
|
16907
16853
|
readJsonFile(filePath) {
|
|
16908
|
-
const absolutePath =
|
|
16909
|
-
if (!(0,
|
|
16854
|
+
const absolutePath = import_node_path19.default.resolve(process.cwd(), filePath);
|
|
16855
|
+
if (!(0, import_node_fs14.existsSync)(absolutePath)) {
|
|
16910
16856
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
16911
16857
|
}
|
|
16912
|
-
const raw = (0,
|
|
16858
|
+
const raw = (0, import_node_fs14.readFileSync)(absolutePath, "utf8");
|
|
16913
16859
|
try {
|
|
16914
16860
|
return JSON.parse(raw);
|
|
16915
16861
|
} catch (error) {
|
|
@@ -17028,8 +16974,8 @@ var NsCommandHandler = class {
|
|
|
17028
16974
|
};
|
|
17029
16975
|
|
|
17030
16976
|
// src/commands/StoreCommandHandler.ts
|
|
17031
|
-
var
|
|
17032
|
-
var
|
|
16977
|
+
var import_node_fs15 = require("fs");
|
|
16978
|
+
var import_node_path20 = __toESM(require("path"));
|
|
17033
16979
|
var StoreCommandHandler = class {
|
|
17034
16980
|
async handle(args) {
|
|
17035
16981
|
if (args.scope === "namespace") {
|
|
@@ -17171,11 +17117,11 @@ var StoreCommandHandler = class {
|
|
|
17171
17117
|
return payload.data ?? [];
|
|
17172
17118
|
}
|
|
17173
17119
|
readJsonFile(filePath) {
|
|
17174
|
-
const absolutePath =
|
|
17175
|
-
if (!(0,
|
|
17120
|
+
const absolutePath = import_node_path20.default.resolve(process.cwd(), filePath);
|
|
17121
|
+
if (!(0, import_node_fs15.existsSync)(absolutePath)) {
|
|
17176
17122
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
17177
17123
|
}
|
|
17178
|
-
const raw = (0,
|
|
17124
|
+
const raw = (0, import_node_fs15.readFileSync)(absolutePath, "utf8");
|
|
17179
17125
|
try {
|
|
17180
17126
|
return JSON.parse(raw);
|
|
17181
17127
|
} catch (error) {
|
|
@@ -17227,13 +17173,13 @@ var StoreCommandHandler = class {
|
|
|
17227
17173
|
};
|
|
17228
17174
|
|
|
17229
17175
|
// src/commands/AppCommandHandler.ts
|
|
17230
|
-
var
|
|
17231
|
-
var
|
|
17176
|
+
var import_node_fs17 = require("fs");
|
|
17177
|
+
var import_node_path22 = __toESM(require("path"));
|
|
17232
17178
|
init_sessionStore();
|
|
17233
17179
|
|
|
17234
17180
|
// src/appIcon.ts
|
|
17235
|
-
var
|
|
17236
|
-
var
|
|
17181
|
+
var import_node_fs16 = require("fs");
|
|
17182
|
+
var import_node_path21 = __toESM(require("path"));
|
|
17237
17183
|
var import_sharp = __toESM(require("sharp"));
|
|
17238
17184
|
init_namespacedRef();
|
|
17239
17185
|
var ANDROID_ICON_SPECS = [
|
|
@@ -17254,33 +17200,19 @@ var IOS_ICON_SPECS = [
|
|
|
17254
17200
|
var pngToIco = require("png-to-ico").default;
|
|
17255
17201
|
function normalizeAppIcon(icon, cwd) {
|
|
17256
17202
|
if (typeof icon !== "string" || !icon.trim()) {
|
|
17257
|
-
throw new Error("App icon must be a non-empty
|
|
17203
|
+
throw new Error("App icon must be a non-empty http(s) URL.");
|
|
17258
17204
|
}
|
|
17259
17205
|
const trimmed = icon.trim();
|
|
17260
17206
|
if (looksLikeSvgMarkup(trimmed)) {
|
|
17261
|
-
|
|
17207
|
+
throw new Error("App icon cannot be inline SVG. Upload the SVG to OSS first and use its http(s) URL.");
|
|
17262
17208
|
}
|
|
17263
17209
|
if (trimmed.startsWith("data:")) {
|
|
17264
|
-
|
|
17210
|
+
throw new Error("App icon cannot be a data URL. Upload the SVG to OSS first and use its http(s) URL.");
|
|
17265
17211
|
}
|
|
17266
17212
|
if (/^https?:\/\//i.test(trimmed)) {
|
|
17267
|
-
|
|
17268
|
-
}
|
|
17269
|
-
const absolutePath = import_node_path20.default.resolve(cwd, trimmed);
|
|
17270
|
-
if (!(0, import_node_fs15.existsSync)(absolutePath)) {
|
|
17271
|
-
if (trimmed.toLowerCase().endsWith(".svg")) {
|
|
17272
|
-
throw new Error(`App icon SVG file not found: ${absolutePath}`);
|
|
17273
|
-
}
|
|
17274
|
-
throw new Error("App icon must be inline SVG, an SVG data URL, or a .svg file path.");
|
|
17275
|
-
}
|
|
17276
|
-
if (import_node_path20.default.extname(absolutePath).toLowerCase() !== ".svg") {
|
|
17277
|
-
throw new Error(`App icon file must use the .svg extension: ${absolutePath}`);
|
|
17278
|
-
}
|
|
17279
|
-
const svg = (0, import_node_fs15.readFileSync)(absolutePath, "utf8").trim();
|
|
17280
|
-
if (!looksLikeSvgMarkup(svg)) {
|
|
17281
|
-
throw new Error(`App icon file is not valid SVG: ${absolutePath}`);
|
|
17213
|
+
return trimmed;
|
|
17282
17214
|
}
|
|
17283
|
-
|
|
17215
|
+
throw new Error("App icon must be an http(s) URL. Upload SVG files to OSS first and use the public link.");
|
|
17284
17216
|
}
|
|
17285
17217
|
function prepareAppPayload(payload, cwd) {
|
|
17286
17218
|
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
@@ -17301,13 +17233,13 @@ function createAppIconExportPlans(input) {
|
|
|
17301
17233
|
if (!input.outDir) {
|
|
17302
17234
|
throw new Error("App icon preset export requires --out-dir.");
|
|
17303
17235
|
}
|
|
17304
|
-
const outDir =
|
|
17305
|
-
(0,
|
|
17236
|
+
const outDir = import_node_path21.default.resolve(input.cwd, input.outDir);
|
|
17237
|
+
(0, import_node_fs16.mkdirSync)(outDir, { recursive: true });
|
|
17306
17238
|
return specs.map((spec) => ({
|
|
17307
17239
|
width: spec.width,
|
|
17308
17240
|
height: spec.height,
|
|
17309
17241
|
format: "png",
|
|
17310
|
-
outputPath:
|
|
17242
|
+
outputPath: import_node_path21.default.join(
|
|
17311
17243
|
outDir,
|
|
17312
17244
|
`${namespace}-${objectId}-${spec.name}-${spec.width}x${spec.height}.png`
|
|
17313
17245
|
)
|
|
@@ -17320,8 +17252,8 @@ function createAppIconExportPlans(input) {
|
|
|
17320
17252
|
if (!input.output) {
|
|
17321
17253
|
throw new Error("Single-size app icon export requires --output.");
|
|
17322
17254
|
}
|
|
17323
|
-
const resolvedOutput =
|
|
17324
|
-
(0,
|
|
17255
|
+
const resolvedOutput = import_node_path21.default.resolve(input.cwd, input.output);
|
|
17256
|
+
(0, import_node_fs16.mkdirSync)(import_node_path21.default.dirname(resolvedOutput), { recursive: true });
|
|
17325
17257
|
return [
|
|
17326
17258
|
{
|
|
17327
17259
|
width: input.width,
|
|
@@ -17331,11 +17263,34 @@ function createAppIconExportPlans(input) {
|
|
|
17331
17263
|
}
|
|
17332
17264
|
];
|
|
17333
17265
|
}
|
|
17334
|
-
async function exportAppIcon(
|
|
17266
|
+
async function exportAppIcon(icon, plans) {
|
|
17267
|
+
const svg = await resolveAppIconSvg(icon);
|
|
17335
17268
|
for (const plan of plans) {
|
|
17336
17269
|
const bytes = await renderAppIcon(svg, plan.width, plan.height, plan.format);
|
|
17337
|
-
(0,
|
|
17270
|
+
(0, import_node_fs16.writeFileSync)(plan.outputPath, bytes);
|
|
17271
|
+
}
|
|
17272
|
+
}
|
|
17273
|
+
async function resolveAppIconSvg(icon) {
|
|
17274
|
+
const trimmed = icon.trim();
|
|
17275
|
+
if (looksLikeSvgMarkup(trimmed)) {
|
|
17276
|
+
return trimmed;
|
|
17277
|
+
}
|
|
17278
|
+
if (!/^https?:\/\//i.test(trimmed)) {
|
|
17279
|
+
throw new Error("App icon export requires inline SVG or an http(s) SVG URL.");
|
|
17280
|
+
}
|
|
17281
|
+
const response = await fetch(trimmed);
|
|
17282
|
+
if (!response.ok) {
|
|
17283
|
+
throw new Error(`Failed to fetch app icon SVG: ${response.status} ${response.statusText}`.trim());
|
|
17284
|
+
}
|
|
17285
|
+
const contentType = response.headers.get("content-type")?.toLowerCase() || "";
|
|
17286
|
+
const svg = (await response.text()).trim();
|
|
17287
|
+
if (contentType && !contentType.includes("image/svg+xml") && !looksLikeSvgMarkup(svg)) {
|
|
17288
|
+
throw new Error(`App icon URL must return SVG content. Received: ${contentType}`);
|
|
17338
17289
|
}
|
|
17290
|
+
if (!looksLikeSvgMarkup(svg)) {
|
|
17291
|
+
throw new Error("App icon URL does not contain valid SVG markup.");
|
|
17292
|
+
}
|
|
17293
|
+
return svg;
|
|
17339
17294
|
}
|
|
17340
17295
|
async function renderAppIcon(svg, width, height, format) {
|
|
17341
17296
|
if (format === "svg") {
|
|
@@ -17357,23 +17312,6 @@ async function renderAppIcon(svg, width, height, format) {
|
|
|
17357
17312
|
function looksLikeSvgMarkup(value) {
|
|
17358
17313
|
return /<svg[\s>]/i.test(value);
|
|
17359
17314
|
}
|
|
17360
|
-
function normalizeSvgDataUrl(value) {
|
|
17361
|
-
const match = /^data:([^;,]+)?(?:;charset=[^;,]+)?(?:;(base64))?,(.*)$/i.exec(value);
|
|
17362
|
-
if (!match) {
|
|
17363
|
-
throw new Error("Invalid app icon data URL.");
|
|
17364
|
-
}
|
|
17365
|
-
const mimeType = (match[1] || "").toLowerCase();
|
|
17366
|
-
if (mimeType !== "image/svg+xml") {
|
|
17367
|
-
throw new Error(`App icon data URL must be image/svg+xml. Received: ${mimeType || "unknown"}`);
|
|
17368
|
-
}
|
|
17369
|
-
const payload = match[3] || "";
|
|
17370
|
-
const decoded = match[2] ? Buffer.from(payload, "base64").toString("utf8") : decodeURIComponent(payload);
|
|
17371
|
-
const svg = decoded.trim();
|
|
17372
|
-
if (!looksLikeSvgMarkup(svg)) {
|
|
17373
|
-
throw new Error("App icon data URL does not contain valid SVG markup.");
|
|
17374
|
-
}
|
|
17375
|
-
return svg;
|
|
17376
|
-
}
|
|
17377
17315
|
|
|
17378
17316
|
// src/commands/AppCommandHandler.ts
|
|
17379
17317
|
init_namespacedRef();
|
|
@@ -17389,7 +17327,12 @@ var AppCommandHandler = class {
|
|
|
17389
17327
|
"GET",
|
|
17390
17328
|
"/apps"
|
|
17391
17329
|
);
|
|
17392
|
-
const items =
|
|
17330
|
+
const items = response.items.filter((item) => {
|
|
17331
|
+
if (!args.all && item.status !== "active") {
|
|
17332
|
+
return false;
|
|
17333
|
+
}
|
|
17334
|
+
return args.namespace ? item.namespace === args.namespace : true;
|
|
17335
|
+
});
|
|
17393
17336
|
this.renderList(items, args.json);
|
|
17394
17337
|
return;
|
|
17395
17338
|
}
|
|
@@ -17525,10 +17468,10 @@ var AppCommandHandler = class {
|
|
|
17525
17468
|
}
|
|
17526
17469
|
readJsonFile(filePath) {
|
|
17527
17470
|
const absolutePath = this.resolveFilePath(filePath);
|
|
17528
|
-
if (!(0,
|
|
17471
|
+
if (!(0, import_node_fs17.existsSync)(absolutePath)) {
|
|
17529
17472
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
17530
17473
|
}
|
|
17531
|
-
const raw = (0,
|
|
17474
|
+
const raw = (0, import_node_fs17.readFileSync)(absolutePath, "utf8");
|
|
17532
17475
|
try {
|
|
17533
17476
|
return JSON.parse(raw);
|
|
17534
17477
|
} catch (error) {
|
|
@@ -17538,10 +17481,10 @@ var AppCommandHandler = class {
|
|
|
17538
17481
|
}
|
|
17539
17482
|
preparePayload(filePath) {
|
|
17540
17483
|
const absolutePath = this.resolveFilePath(filePath);
|
|
17541
|
-
return prepareAppPayload(this.readJsonFile(filePath),
|
|
17484
|
+
return prepareAppPayload(this.readJsonFile(filePath), import_node_path22.default.dirname(absolutePath));
|
|
17542
17485
|
}
|
|
17543
17486
|
resolveFilePath(filePath) {
|
|
17544
|
-
return
|
|
17487
|
+
return import_node_path22.default.resolve(process.cwd(), filePath);
|
|
17545
17488
|
}
|
|
17546
17489
|
async request(baseUrl, token, method, pathname, body) {
|
|
17547
17490
|
const response = await fetch(`${baseUrl}${pathname}`, {
|
|
@@ -17615,15 +17558,15 @@ function readNamespaceFromPayload(payload) {
|
|
|
17615
17558
|
}
|
|
17616
17559
|
|
|
17617
17560
|
// src/commands/ServiceCommandHandler.ts
|
|
17618
|
-
var
|
|
17561
|
+
var import_node_fs19 = require("fs");
|
|
17619
17562
|
var import_promises5 = require("fs/promises");
|
|
17620
|
-
var
|
|
17563
|
+
var import_node_path24 = __toESM(require("path"));
|
|
17621
17564
|
var import_promises6 = require("readline/promises");
|
|
17622
17565
|
|
|
17623
17566
|
// src/services/ServiceRuntimeRunner.ts
|
|
17624
|
-
var
|
|
17625
|
-
var
|
|
17626
|
-
var
|
|
17567
|
+
var import_node_fs18 = require("fs");
|
|
17568
|
+
var import_node_os8 = __toESM(require("os"));
|
|
17569
|
+
var import_node_path23 = __toESM(require("path"));
|
|
17627
17570
|
var import_node_child_process10 = require("child_process");
|
|
17628
17571
|
var import_node_readline = require("readline");
|
|
17629
17572
|
var import_chalk3 = __toESM(require("chalk"));
|
|
@@ -17788,14 +17731,14 @@ var ServiceRuntimeRunner = class {
|
|
|
17788
17731
|
}
|
|
17789
17732
|
resolveRepoRoot(service, cwd) {
|
|
17790
17733
|
if (cwd) {
|
|
17791
|
-
return
|
|
17734
|
+
return import_node_path23.default.resolve(process.cwd(), cwd);
|
|
17792
17735
|
}
|
|
17793
17736
|
const repository = this.getType(service) === "vite" || this.getType(service) === "static" ? this.getSite(service).repository?.trim() : this.getType(service) === "ios" || this.getType(service) === "android" ? void 0 : this.getNetwork(service).repository?.trim();
|
|
17794
17737
|
if (repository) {
|
|
17795
17738
|
const repoName = repository.replace(/\/+$/, "").split("/").pop()?.replace(/\.git$/i, "");
|
|
17796
17739
|
if (repoName) {
|
|
17797
|
-
const candidate =
|
|
17798
|
-
if ((0,
|
|
17740
|
+
const candidate = import_node_path23.default.join(import_node_os8.default.homedir(), "dev", "pmate", repoName);
|
|
17741
|
+
if ((0, import_node_fs18.existsSync)(candidate)) {
|
|
17799
17742
|
return candidate;
|
|
17800
17743
|
}
|
|
17801
17744
|
}
|
|
@@ -17808,12 +17751,12 @@ var ServiceRuntimeRunner = class {
|
|
|
17808
17751
|
if (!dir) {
|
|
17809
17752
|
throw new Error(`Missing service dir for ${service.id}`);
|
|
17810
17753
|
}
|
|
17811
|
-
return
|
|
17754
|
+
return import_node_path23.default.resolve(repoRoot, dir);
|
|
17812
17755
|
}
|
|
17813
17756
|
async deployVite(service, options) {
|
|
17814
17757
|
const appDir = this.resolveLocalDir(service, options.cwd);
|
|
17815
|
-
const packageJsonPath =
|
|
17816
|
-
if (!(0,
|
|
17758
|
+
const packageJsonPath = import_node_path23.default.join(appDir, "package.json");
|
|
17759
|
+
if (!(0, import_node_fs18.existsSync)(packageJsonPath)) {
|
|
17817
17760
|
throw new Error(`No package.json found at ${packageJsonPath}`);
|
|
17818
17761
|
}
|
|
17819
17762
|
const pkg2 = this.loadPackageJson(packageJsonPath);
|
|
@@ -17822,8 +17765,8 @@ var ServiceRuntimeRunner = class {
|
|
|
17822
17765
|
throw new Error(`Missing package name in ${packageJsonPath}`);
|
|
17823
17766
|
}
|
|
17824
17767
|
await this.runCommand("pnpm", ["--filter", pkgName, "build"], this.resolveRepoRoot(service, options.cwd));
|
|
17825
|
-
const distDir =
|
|
17826
|
-
if (!(0,
|
|
17768
|
+
const distDir = import_node_path23.default.join(appDir, "dist");
|
|
17769
|
+
if (!(0, import_node_fs18.existsSync)(distDir)) {
|
|
17827
17770
|
throw new Error(`No dist directory found at ${distDir}`);
|
|
17828
17771
|
}
|
|
17829
17772
|
const site = this.getSite(service);
|
|
@@ -17835,8 +17778,8 @@ var ServiceRuntimeRunner = class {
|
|
|
17835
17778
|
}
|
|
17836
17779
|
async deployStatic(service, options) {
|
|
17837
17780
|
const appDir = this.resolveLocalDir(service, options.cwd);
|
|
17838
|
-
const srcDir =
|
|
17839
|
-
if (!(0,
|
|
17781
|
+
const srcDir = import_node_path23.default.join(appDir, "src");
|
|
17782
|
+
if (!(0, import_node_fs18.existsSync)(srcDir)) {
|
|
17840
17783
|
throw new Error(`No src directory found at ${srcDir}`);
|
|
17841
17784
|
}
|
|
17842
17785
|
const site = this.getSite(service);
|
|
@@ -17956,7 +17899,7 @@ var ServiceRuntimeRunner = class {
|
|
|
17956
17899
|
const serverAddress = await resolveServerAddress(server);
|
|
17957
17900
|
const templateName = exposeType === "websocket" ? "nginx.ws.template" : "nginx.rest.template";
|
|
17958
17901
|
const templatePath = this.resolveTemplatePath(templateName);
|
|
17959
|
-
const template = (0,
|
|
17902
|
+
const template = (0, import_node_fs18.readFileSync)(templatePath, "utf8");
|
|
17960
17903
|
const host = `${subdomain}.${("domain" in network ? network.domain?.trim() : void 0) || "pmate.chat"}`;
|
|
17961
17904
|
const rendered = template.replace(/\$\{\{PORT\}\}/g, String(port)).replace(/\$\{\{HOSTS\}\}/g, host).replace(/\$\{\{HOST\}\}/g, host);
|
|
17962
17905
|
const remotePath = `/etc/nginx/sites-enabled/${subdomain}.conf`;
|
|
@@ -17988,11 +17931,11 @@ var ServiceRuntimeRunner = class {
|
|
|
17988
17931
|
}
|
|
17989
17932
|
if (config.ensurePackageJson) {
|
|
17990
17933
|
const appDir = this.resolveLocalDir(service, options.cwd);
|
|
17991
|
-
const packageJsonPath =
|
|
17992
|
-
if (!(0,
|
|
17934
|
+
const packageJsonPath = import_node_path23.default.join(appDir, "package.json");
|
|
17935
|
+
if (!(0, import_node_fs18.existsSync)(packageJsonPath)) {
|
|
17993
17936
|
throw new Error(`Missing package.json at ${packageJsonPath}`);
|
|
17994
17937
|
}
|
|
17995
|
-
const pkgStat = (0,
|
|
17938
|
+
const pkgStat = (0, import_node_fs18.statSync)(packageJsonPath);
|
|
17996
17939
|
if (!pkgStat.isFile()) {
|
|
17997
17940
|
throw new Error(`package.json is not a file at ${packageJsonPath}`);
|
|
17998
17941
|
}
|
|
@@ -18416,9 +18359,9 @@ var ServiceRuntimeRunner = class {
|
|
|
18416
18359
|
return tokens;
|
|
18417
18360
|
}
|
|
18418
18361
|
readPathValue(source, pathExpr) {
|
|
18419
|
-
const
|
|
18362
|
+
const path28 = pathExpr.split(".").map((segment) => segment.trim()).filter(Boolean);
|
|
18420
18363
|
let cursor = source;
|
|
18421
|
-
for (const segment of
|
|
18364
|
+
for (const segment of path28) {
|
|
18422
18365
|
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) {
|
|
18423
18366
|
return void 0;
|
|
18424
18367
|
}
|
|
@@ -18461,12 +18404,12 @@ var ServiceRuntimeRunner = class {
|
|
|
18461
18404
|
}
|
|
18462
18405
|
resolveTemplatePath(templateName) {
|
|
18463
18406
|
const candidates = [
|
|
18464
|
-
|
|
18465
|
-
|
|
18466
|
-
|
|
18407
|
+
import_node_path23.default.join(__dirname, "..", "templates", templateName),
|
|
18408
|
+
import_node_path23.default.join(__dirname, "..", "src", "templates", templateName),
|
|
18409
|
+
import_node_path23.default.join(__dirname, "templates", templateName)
|
|
18467
18410
|
];
|
|
18468
18411
|
for (const candidate of candidates) {
|
|
18469
|
-
if ((0,
|
|
18412
|
+
if ((0, import_node_fs18.existsSync)(candidate)) {
|
|
18470
18413
|
return candidate;
|
|
18471
18414
|
}
|
|
18472
18415
|
}
|
|
@@ -18498,7 +18441,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18498
18441
|
});
|
|
18499
18442
|
}
|
|
18500
18443
|
loadPackageJson(packageJsonPath) {
|
|
18501
|
-
const raw = (0,
|
|
18444
|
+
const raw = (0, import_node_fs18.readFileSync)(packageJsonPath, "utf8");
|
|
18502
18445
|
const parsed = JSON.parse(raw);
|
|
18503
18446
|
if (!parsed || typeof parsed !== "object") {
|
|
18504
18447
|
throw new Error(`Invalid package.json at ${packageJsonPath}`);
|
|
@@ -18507,7 +18450,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18507
18450
|
}
|
|
18508
18451
|
writePackageJson(packageJsonPath, data) {
|
|
18509
18452
|
const serialized = JSON.stringify(data, null, 2);
|
|
18510
|
-
(0,
|
|
18453
|
+
(0, import_node_fs18.writeFileSync)(packageJsonPath, `${serialized}
|
|
18511
18454
|
`, "utf8");
|
|
18512
18455
|
}
|
|
18513
18456
|
runCommand(command, args, cwd) {
|
|
@@ -18844,7 +18787,7 @@ var ServiceCommandHandler = class {
|
|
|
18844
18787
|
format: "dotenv"
|
|
18845
18788
|
}
|
|
18846
18789
|
);
|
|
18847
|
-
const outputPath =
|
|
18790
|
+
const outputPath = import_node_path24.default.resolve(process.cwd(), args.output);
|
|
18848
18791
|
await (0, import_promises5.writeFile)(outputPath, payload.content, "utf8");
|
|
18849
18792
|
ui.success(`Wrote env file for ${args.appId} to ${outputPath}`);
|
|
18850
18793
|
this.renderJson({ ...payload, output: outputPath }, args.json);
|
|
@@ -18873,11 +18816,11 @@ var ServiceCommandHandler = class {
|
|
|
18873
18816
|
return (baseUrl || process.env.PMATE_APPS_API_BASE_URL || "https://apps-api.pmate.chat").replace(/\/+$/, "");
|
|
18874
18817
|
}
|
|
18875
18818
|
readJsonFile(filePath) {
|
|
18876
|
-
const absolutePath =
|
|
18877
|
-
if (!(0,
|
|
18819
|
+
const absolutePath = import_node_path24.default.resolve(process.cwd(), filePath);
|
|
18820
|
+
if (!(0, import_node_fs19.existsSync)(absolutePath)) {
|
|
18878
18821
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
18879
18822
|
}
|
|
18880
|
-
const raw = (0,
|
|
18823
|
+
const raw = (0, import_node_fs19.readFileSync)(absolutePath, "utf8");
|
|
18881
18824
|
try {
|
|
18882
18825
|
return JSON.parse(raw);
|
|
18883
18826
|
} catch (error) {
|
|
@@ -19217,8 +19160,8 @@ var RoleCommandHandler = class {
|
|
|
19217
19160
|
};
|
|
19218
19161
|
|
|
19219
19162
|
// src/commands/AccountCommandHandler.ts
|
|
19220
|
-
var
|
|
19221
|
-
var
|
|
19163
|
+
var import_node_fs20 = require("fs");
|
|
19164
|
+
var import_node_path25 = __toESM(require("path"));
|
|
19222
19165
|
init_sessionStore();
|
|
19223
19166
|
var AccountCommandHandler = class {
|
|
19224
19167
|
async handle(args) {
|
|
@@ -19466,10 +19409,10 @@ var AccountCommandHandler = class {
|
|
|
19466
19409
|
throw new Error("Missing visible apps input");
|
|
19467
19410
|
}
|
|
19468
19411
|
const absolutePath = this.resolveFilePath(args.filePath);
|
|
19469
|
-
if (!(0,
|
|
19412
|
+
if (!(0, import_node_fs20.existsSync)(absolutePath)) {
|
|
19470
19413
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
19471
19414
|
}
|
|
19472
|
-
const raw = (0,
|
|
19415
|
+
const raw = (0, import_node_fs20.readFileSync)(absolutePath, "utf8");
|
|
19473
19416
|
let parsed;
|
|
19474
19417
|
try {
|
|
19475
19418
|
parsed = JSON.parse(raw);
|
|
@@ -19483,7 +19426,7 @@ var AccountCommandHandler = class {
|
|
|
19483
19426
|
return parsed;
|
|
19484
19427
|
}
|
|
19485
19428
|
resolveFilePath(filePath) {
|
|
19486
|
-
return
|
|
19429
|
+
return import_node_path25.default.resolve(process.cwd(), filePath);
|
|
19487
19430
|
}
|
|
19488
19431
|
};
|
|
19489
19432
|
function encodePathSegment(value) {
|
|
@@ -19491,8 +19434,8 @@ function encodePathSegment(value) {
|
|
|
19491
19434
|
}
|
|
19492
19435
|
|
|
19493
19436
|
// src/commands/OrgCommandHandler.ts
|
|
19494
|
-
var
|
|
19495
|
-
var
|
|
19437
|
+
var import_node_fs21 = require("fs");
|
|
19438
|
+
var import_node_path26 = __toESM(require("path"));
|
|
19496
19439
|
init_sessionStore();
|
|
19497
19440
|
var OrgCommandHandler = class {
|
|
19498
19441
|
async handle(args) {
|
|
@@ -19663,11 +19606,11 @@ var OrgCommandHandler = class {
|
|
|
19663
19606
|
if (!filePath) {
|
|
19664
19607
|
throw new Error(`Missing ${itemLabel} input`);
|
|
19665
19608
|
}
|
|
19666
|
-
const absolutePath =
|
|
19667
|
-
if (!(0,
|
|
19609
|
+
const absolutePath = import_node_path26.default.resolve(process.cwd(), filePath);
|
|
19610
|
+
if (!(0, import_node_fs21.existsSync)(absolutePath)) {
|
|
19668
19611
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
19669
19612
|
}
|
|
19670
|
-
const raw = (0,
|
|
19613
|
+
const raw = (0, import_node_fs21.readFileSync)(absolutePath, "utf8");
|
|
19671
19614
|
let parsed;
|
|
19672
19615
|
try {
|
|
19673
19616
|
parsed = JSON.parse(raw);
|
|
@@ -20566,6 +20509,7 @@ function parseAppArgs(tokens) {
|
|
|
20566
20509
|
};
|
|
20567
20510
|
if (action === "list") {
|
|
20568
20511
|
let namespace;
|
|
20512
|
+
let all = false;
|
|
20569
20513
|
while (rest.length > 0) {
|
|
20570
20514
|
const token = rest.shift();
|
|
20571
20515
|
switch (token) {
|
|
@@ -20573,6 +20517,9 @@ function parseAppArgs(tokens) {
|
|
|
20573
20517
|
case "--namespace":
|
|
20574
20518
|
namespace = requireValue5(rest, token);
|
|
20575
20519
|
break;
|
|
20520
|
+
case "--all":
|
|
20521
|
+
all = true;
|
|
20522
|
+
break;
|
|
20576
20523
|
case "--base-url":
|
|
20577
20524
|
baseUrl = requireValue5(rest, token);
|
|
20578
20525
|
break;
|
|
@@ -20583,7 +20530,7 @@ function parseAppArgs(tokens) {
|
|
|
20583
20530
|
throw new Error(`Unknown app list option: ${token}`);
|
|
20584
20531
|
}
|
|
20585
20532
|
}
|
|
20586
|
-
return { type: "app" /* App */, action, namespace, baseUrl, json };
|
|
20533
|
+
return { type: "app" /* App */, action, namespace, all, baseUrl, json };
|
|
20587
20534
|
}
|
|
20588
20535
|
if (action === "view") {
|
|
20589
20536
|
const rawRef = rest.shift();
|
|
@@ -22152,7 +22099,7 @@ function requireValue11(tokens, option) {
|
|
|
22152
22099
|
|
|
22153
22100
|
// src/index.ts
|
|
22154
22101
|
var pkg = JSON.parse(
|
|
22155
|
-
(0,
|
|
22102
|
+
(0, import_node_fs22.readFileSync)(import_node_path27.default.resolve(__dirname, "..", "package.json"), "utf8")
|
|
22156
22103
|
);
|
|
22157
22104
|
var HELP_TEXT = [
|
|
22158
22105
|
import_chalk4.default.bold(`pmate v${pkg.version}`),
|
|
@@ -22295,7 +22242,7 @@ var HELP_TEXT = [
|
|
|
22295
22242
|
` ${import_chalk4.default.gray(" kv list|get|exists|set|delete <name> [options]")}`,
|
|
22296
22243
|
` ${import_chalk4.default.gray(" defaults: chain=pmate namespace=pmate env base URLs from BLOCKCHAIN_BASE_URL / INDEXER_BASE_URL")}`,
|
|
22297
22244
|
` ${import_chalk4.default.cyan("app")} Manage app registry entries via apps-api`,
|
|
22298
|
-
` ${import_chalk4.default.gray(" list [--ns <namespace>] [--base-url <url>] [--json]")}`,
|
|
22245
|
+
` ${import_chalk4.default.gray(" list [--ns <namespace>] [--all] [--base-url <url>] [--json]")}`,
|
|
22299
22246
|
` ${import_chalk4.default.gray(" get <ns:objectId> [--base-url <url>] [--json]")}`,
|
|
22300
22247
|
` ${import_chalk4.default.gray(" view <ns:objectId> [--base-url <url>]")}`,
|
|
22301
22248
|
` ${import_chalk4.default.gray(" create --file <path> [--base-url <url>] [--json]")}`,
|