@pmate/cli 0.21.15 → 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 +479 -518
- 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,307 +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;
|
|
15994
|
+
}
|
|
15995
|
+
const rows = await el.locator(":scope > *").count().catch(() => 0);
|
|
15996
|
+
if (rows >= bestRows) {
|
|
15997
|
+
bestRows = rows;
|
|
15998
|
+
bestIdx = i;
|
|
16098
15999
|
}
|
|
16099
|
-
return null;
|
|
16100
16000
|
}
|
|
16101
|
-
|
|
16102
|
-
|
|
16103
|
-
var privates = controller.getAllPrivateConversations();
|
|
16104
|
-
all.push.apply(all, privates.models || privates || []);
|
|
16105
|
-
}
|
|
16106
|
-
if (typeof controller.getAllGroups === 'function') {
|
|
16107
|
-
var groups = controller.getAllGroups();
|
|
16108
|
-
all.push.apply(all, groups.models || groups || []);
|
|
16109
|
-
}
|
|
16110
|
-
var seen = {};
|
|
16111
|
-
var threads = [];
|
|
16112
|
-
for (var i = 0; i < all.length; i++) {
|
|
16113
|
-
var model = all[i];
|
|
16114
|
-
var conversationId = normalize(model && model.get ? model.get('id') : model && model.id);
|
|
16115
|
-
if (!conversationId || seen[conversationId]) continue;
|
|
16116
|
-
seen[conversationId] = true;
|
|
16117
|
-
var name = pickName(model);
|
|
16118
|
-
if (!name) continue;
|
|
16119
|
-
threads.push({
|
|
16120
|
-
conversationId: conversationId,
|
|
16121
|
-
name: name,
|
|
16122
|
-
unread: pickUnread(model),
|
|
16123
|
-
preview: pickPreview(model),
|
|
16124
|
-
sentAt: pickSentAt(model),
|
|
16125
|
-
});
|
|
16001
|
+
if (bestRows >= 0) {
|
|
16002
|
+
return strong.nth(bestIdx);
|
|
16126
16003
|
}
|
|
16127
|
-
threads.sort(function(left, right) {
|
|
16128
|
-
return (Number(right.sentAt || 0) - Number(left.sentAt || 0)) || left.name.localeCompare(right.name);
|
|
16129
|
-
});
|
|
16130
|
-
return { ok: true, threads: threads };
|
|
16131
|
-
} catch(e) {
|
|
16132
|
-
return { ok: false, reason: e && e.message ? e.message : String(e) };
|
|
16133
16004
|
}
|
|
16134
|
-
|
|
16135
|
-
|
|
16136
|
-
|
|
16137
|
-
|
|
16138
|
-
|
|
16139
|
-
|
|
16140
|
-
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
|
|
16144
|
-
|
|
16145
|
-
|
|
16146
|
-
|
|
16147
|
-
|
|
16148
|
-
function normalize(value) {
|
|
16149
|
-
return String(value || '').replace(/\\s+/g, ' ').trim();
|
|
16150
|
-
}
|
|
16151
|
-
function resolveSenderName(source, model) {
|
|
16152
|
-
if (!source) return null;
|
|
16153
|
-
var contact = typeof controller.get === 'function' ? controller.get(source) : null;
|
|
16154
|
-
var fields = [
|
|
16155
|
-
contact && contact.get ? contact.get('name') : contact && contact.name,
|
|
16156
|
-
contact && contact.get ? contact.get('profileName') : contact && contact.profileName,
|
|
16157
|
-
contact && contact.get ? contact.get('title') : contact && contact.title,
|
|
16158
|
-
source,
|
|
16159
|
-
];
|
|
16160
|
-
for (var i = 0; i < fields.length; i++) {
|
|
16161
|
-
var value = normalize(fields[i]);
|
|
16162
|
-
if (value) return value;
|
|
16163
|
-
}
|
|
16164
|
-
return null;
|
|
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 };
|
|
16165
16019
|
}
|
|
16166
|
-
var conversation = typeof controller.get === 'function' ? controller.get('${escapedConversationId}') : null;
|
|
16167
|
-
if (!conversation) return { ok: false, reason: 'Conversation not found: ${escapedConversationId}' };
|
|
16168
|
-
var fetched = await signal.Data.getMessagesByConversation('${escapedConversationId}', {
|
|
16169
|
-
limit: ${limit},
|
|
16170
|
-
MessageCollection: whisper.MessageCollection,
|
|
16171
|
-
});
|
|
16172
|
-
var models = (fetched.models || fetched || []).slice();
|
|
16173
|
-
models.sort(function(left, right) {
|
|
16174
|
-
var leftSentAt = left && left.get ? (left.get('sent_at') || 0) : (left && left.sent_at) || 0;
|
|
16175
|
-
var rightSentAt = right && right.get ? (right.get('sent_at') || 0) : (right && right.sent_at) || 0;
|
|
16176
|
-
return leftSentAt - rightSentAt;
|
|
16177
|
-
});
|
|
16178
|
-
return {
|
|
16179
|
-
ok: true,
|
|
16180
|
-
conversationId: '${escapedConversationId}',
|
|
16181
|
-
messages: models.map(function(model, index) {
|
|
16182
|
-
var attrs = typeof model.attributes === 'object' ? model.attributes : model;
|
|
16183
|
-
var source = (typeof model.getSource === 'function' ? model.getSource() : attrs.source) || null;
|
|
16184
|
-
var quote = attrs.quote ? {
|
|
16185
|
-
id: attrs.quote.id || null,
|
|
16186
|
-
author: attrs.quote.author || null,
|
|
16187
|
-
text: attrs.quote.text || null,
|
|
16188
|
-
} : null;
|
|
16189
|
-
var attachments = Array.isArray(attrs.attachments) ? attrs.attachments.map(function(attachment) {
|
|
16190
|
-
return {
|
|
16191
|
-
path: attachment && attachment.path || null,
|
|
16192
|
-
contentType: attachment && attachment.contentType || null,
|
|
16193
|
-
fileName: attachment && attachment.fileName || null,
|
|
16194
|
-
};
|
|
16195
|
-
}) : [];
|
|
16196
|
-
return {
|
|
16197
|
-
index: index,
|
|
16198
|
-
body: attrs.body || '',
|
|
16199
|
-
source: source,
|
|
16200
|
-
senderName: resolveSenderName(source, model),
|
|
16201
|
-
sentAt: attrs.sent_at || attrs.timestamp || null,
|
|
16202
|
-
id: attrs.id || model.id || '',
|
|
16203
|
-
attachments: attachments,
|
|
16204
|
-
quote: quote,
|
|
16205
|
-
};
|
|
16206
|
-
}),
|
|
16207
|
-
};
|
|
16208
|
-
} catch(e) {
|
|
16209
|
-
return { ok: false, reason: e && e.message ? e.message : String(e) };
|
|
16210
16020
|
}
|
|
16211
|
-
|
|
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);
|
|
16047
|
+
}
|
|
16048
|
+
}
|
|
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;
|
|
16212
16095
|
}
|
|
16213
|
-
function
|
|
16214
|
-
return value.replace(
|
|
16096
|
+
function normalizeText(value) {
|
|
16097
|
+
return value.replace(/\s+/g, " ").replace(/\u200B/g, "").trim();
|
|
16215
16098
|
}
|
|
16216
|
-
function
|
|
16217
|
-
const
|
|
16218
|
-
|
|
16219
|
-
|
|
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 };
|
|
16220
16127
|
}
|
|
16221
|
-
|
|
16222
|
-
|
|
16128
|
+
return {
|
|
16129
|
+
time,
|
|
16130
|
+
sender: normalizeText(senderMatch[1] ?? "") || null,
|
|
16131
|
+
content: normalizeText(senderMatch[2] ?? "")
|
|
16132
|
+
};
|
|
16223
16133
|
}
|
|
16224
|
-
function
|
|
16225
|
-
|
|
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
|
+
}
|
|
16226
16174
|
}
|
|
16227
|
-
function
|
|
16228
|
-
|
|
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;
|
|
16229
16189
|
}
|
|
16230
16190
|
|
|
16231
16191
|
// src/commands/AgentCommandHandler.ts
|
|
16232
|
-
var
|
|
16233
|
-
var
|
|
16192
|
+
var import_node_fs13 = require("fs");
|
|
16193
|
+
var import_node_path18 = __toESM(require("path"));
|
|
16234
16194
|
init_AgentLlmClient();
|
|
16235
16195
|
init_sessionStore();
|
|
16236
16196
|
|
|
@@ -16238,7 +16198,7 @@ init_sessionStore();
|
|
|
16238
16198
|
var STORE_LOG_VERSION = 1;
|
|
16239
16199
|
var LOG_KIND_TABLE = 1e4;
|
|
16240
16200
|
var LOG_KIND_MAPPING = 6003;
|
|
16241
|
-
function
|
|
16201
|
+
function createHash4() {
|
|
16242
16202
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
16243
16203
|
}
|
|
16244
16204
|
function createDescriptor(input) {
|
|
@@ -16263,8 +16223,8 @@ function descriptorPathSegments(descriptor) {
|
|
|
16263
16223
|
return ["chains", normalized.chain, "namespaces", normalized.ns, normalized.kind, normalized.name];
|
|
16264
16224
|
}
|
|
16265
16225
|
function buildPathUrl(baseUrl, pathSegments, query) {
|
|
16266
|
-
const
|
|
16267
|
-
const url = new URL(
|
|
16226
|
+
const path28 = `/${pathSegments.map((segment) => encodeURIComponent(segment)).join("/")}`;
|
|
16227
|
+
const url = new URL(path28, baseUrl);
|
|
16268
16228
|
if (query) {
|
|
16269
16229
|
for (const [key, value] of Object.entries(query)) {
|
|
16270
16230
|
url.searchParams.set(key, String(value));
|
|
@@ -16377,7 +16337,7 @@ var Namespace = class {
|
|
|
16377
16337
|
},
|
|
16378
16338
|
appendRow: async (data) => {
|
|
16379
16339
|
const log = {
|
|
16380
|
-
hash:
|
|
16340
|
+
hash: createHash4(),
|
|
16381
16341
|
t: Date.now(),
|
|
16382
16342
|
kind: LOG_KIND_TABLE,
|
|
16383
16343
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16389,7 +16349,7 @@ var Namespace = class {
|
|
|
16389
16349
|
updateRow: async (data) => {
|
|
16390
16350
|
const { id, ...value } = data;
|
|
16391
16351
|
const log = {
|
|
16392
|
-
hash:
|
|
16352
|
+
hash: createHash4(),
|
|
16393
16353
|
t: Date.now(),
|
|
16394
16354
|
kind: LOG_KIND_TABLE,
|
|
16395
16355
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16400,7 +16360,7 @@ var Namespace = class {
|
|
|
16400
16360
|
},
|
|
16401
16361
|
deleteRow: async (id) => {
|
|
16402
16362
|
const log = {
|
|
16403
|
-
hash:
|
|
16363
|
+
hash: createHash4(),
|
|
16404
16364
|
t: Date.now(),
|
|
16405
16365
|
kind: LOG_KIND_TABLE,
|
|
16406
16366
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16443,7 +16403,7 @@ var Namespace = class {
|
|
|
16443
16403
|
},
|
|
16444
16404
|
set: async (key, value) => {
|
|
16445
16405
|
const log = {
|
|
16446
|
-
hash:
|
|
16406
|
+
hash: createHash4(),
|
|
16447
16407
|
t: Date.now(),
|
|
16448
16408
|
kind: LOG_KIND_MAPPING,
|
|
16449
16409
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16454,7 +16414,7 @@ var Namespace = class {
|
|
|
16454
16414
|
},
|
|
16455
16415
|
delete: async (key) => {
|
|
16456
16416
|
const log = {
|
|
16457
|
-
hash:
|
|
16417
|
+
hash: createHash4(),
|
|
16458
16418
|
t: Date.now(),
|
|
16459
16419
|
kind: LOG_KIND_MAPPING,
|
|
16460
16420
|
topic: descriptorToTopic(descriptor),
|
|
@@ -16696,11 +16656,11 @@ var AgentCommandHandler = class {
|
|
|
16696
16656
|
}).token;
|
|
16697
16657
|
}
|
|
16698
16658
|
readJsonFile(filePath) {
|
|
16699
|
-
const absolutePath =
|
|
16700
|
-
if (!(0,
|
|
16659
|
+
const absolutePath = import_node_path18.default.resolve(process.cwd(), filePath);
|
|
16660
|
+
if (!(0, import_node_fs13.existsSync)(absolutePath)) {
|
|
16701
16661
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
16702
16662
|
}
|
|
16703
|
-
const raw = (0,
|
|
16663
|
+
const raw = (0, import_node_fs13.readFileSync)(absolutePath, "utf8");
|
|
16704
16664
|
try {
|
|
16705
16665
|
return JSON.parse(raw);
|
|
16706
16666
|
} catch (error) {
|
|
@@ -16711,7 +16671,7 @@ var AgentCommandHandler = class {
|
|
|
16711
16671
|
readJsonObjectFile(filePath) {
|
|
16712
16672
|
const parsed = this.readJsonFile(filePath);
|
|
16713
16673
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
16714
|
-
const absolutePath =
|
|
16674
|
+
const absolutePath = import_node_path18.default.resolve(process.cwd(), filePath);
|
|
16715
16675
|
throw new Error(`Invalid JSON in ${absolutePath}: expected an object`);
|
|
16716
16676
|
}
|
|
16717
16677
|
return parsed;
|
|
@@ -16795,8 +16755,8 @@ var AgentCommandHandler = class {
|
|
|
16795
16755
|
};
|
|
16796
16756
|
|
|
16797
16757
|
// src/commands/RunnerCommandHandler.ts
|
|
16798
|
-
var
|
|
16799
|
-
var
|
|
16758
|
+
var import_node_fs14 = require("fs");
|
|
16759
|
+
var import_node_path19 = __toESM(require("path"));
|
|
16800
16760
|
init_sessionStore();
|
|
16801
16761
|
init_namespacedRef();
|
|
16802
16762
|
var RunnerCommandHandler = class {
|
|
@@ -16891,11 +16851,11 @@ var RunnerCommandHandler = class {
|
|
|
16891
16851
|
}).token;
|
|
16892
16852
|
}
|
|
16893
16853
|
readJsonFile(filePath) {
|
|
16894
|
-
const absolutePath =
|
|
16895
|
-
if (!(0,
|
|
16854
|
+
const absolutePath = import_node_path19.default.resolve(process.cwd(), filePath);
|
|
16855
|
+
if (!(0, import_node_fs14.existsSync)(absolutePath)) {
|
|
16896
16856
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
16897
16857
|
}
|
|
16898
|
-
const raw = (0,
|
|
16858
|
+
const raw = (0, import_node_fs14.readFileSync)(absolutePath, "utf8");
|
|
16899
16859
|
try {
|
|
16900
16860
|
return JSON.parse(raw);
|
|
16901
16861
|
} catch (error) {
|
|
@@ -17014,8 +16974,8 @@ var NsCommandHandler = class {
|
|
|
17014
16974
|
};
|
|
17015
16975
|
|
|
17016
16976
|
// src/commands/StoreCommandHandler.ts
|
|
17017
|
-
var
|
|
17018
|
-
var
|
|
16977
|
+
var import_node_fs15 = require("fs");
|
|
16978
|
+
var import_node_path20 = __toESM(require("path"));
|
|
17019
16979
|
var StoreCommandHandler = class {
|
|
17020
16980
|
async handle(args) {
|
|
17021
16981
|
if (args.scope === "namespace") {
|
|
@@ -17157,11 +17117,11 @@ var StoreCommandHandler = class {
|
|
|
17157
17117
|
return payload.data ?? [];
|
|
17158
17118
|
}
|
|
17159
17119
|
readJsonFile(filePath) {
|
|
17160
|
-
const absolutePath =
|
|
17161
|
-
if (!(0,
|
|
17120
|
+
const absolutePath = import_node_path20.default.resolve(process.cwd(), filePath);
|
|
17121
|
+
if (!(0, import_node_fs15.existsSync)(absolutePath)) {
|
|
17162
17122
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
17163
17123
|
}
|
|
17164
|
-
const raw = (0,
|
|
17124
|
+
const raw = (0, import_node_fs15.readFileSync)(absolutePath, "utf8");
|
|
17165
17125
|
try {
|
|
17166
17126
|
return JSON.parse(raw);
|
|
17167
17127
|
} catch (error) {
|
|
@@ -17213,13 +17173,13 @@ var StoreCommandHandler = class {
|
|
|
17213
17173
|
};
|
|
17214
17174
|
|
|
17215
17175
|
// src/commands/AppCommandHandler.ts
|
|
17216
|
-
var
|
|
17217
|
-
var
|
|
17176
|
+
var import_node_fs17 = require("fs");
|
|
17177
|
+
var import_node_path22 = __toESM(require("path"));
|
|
17218
17178
|
init_sessionStore();
|
|
17219
17179
|
|
|
17220
17180
|
// src/appIcon.ts
|
|
17221
|
-
var
|
|
17222
|
-
var
|
|
17181
|
+
var import_node_fs16 = require("fs");
|
|
17182
|
+
var import_node_path21 = __toESM(require("path"));
|
|
17223
17183
|
var import_sharp = __toESM(require("sharp"));
|
|
17224
17184
|
init_namespacedRef();
|
|
17225
17185
|
var ANDROID_ICON_SPECS = [
|
|
@@ -17240,33 +17200,19 @@ var IOS_ICON_SPECS = [
|
|
|
17240
17200
|
var pngToIco = require("png-to-ico").default;
|
|
17241
17201
|
function normalizeAppIcon(icon, cwd) {
|
|
17242
17202
|
if (typeof icon !== "string" || !icon.trim()) {
|
|
17243
|
-
throw new Error("App icon must be a non-empty
|
|
17203
|
+
throw new Error("App icon must be a non-empty http(s) URL.");
|
|
17244
17204
|
}
|
|
17245
17205
|
const trimmed = icon.trim();
|
|
17246
17206
|
if (looksLikeSvgMarkup(trimmed)) {
|
|
17247
|
-
|
|
17207
|
+
throw new Error("App icon cannot be inline SVG. Upload the SVG to OSS first and use its http(s) URL.");
|
|
17248
17208
|
}
|
|
17249
17209
|
if (trimmed.startsWith("data:")) {
|
|
17250
|
-
|
|
17210
|
+
throw new Error("App icon cannot be a data URL. Upload the SVG to OSS first and use its http(s) URL.");
|
|
17251
17211
|
}
|
|
17252
17212
|
if (/^https?:\/\//i.test(trimmed)) {
|
|
17253
|
-
|
|
17254
|
-
}
|
|
17255
|
-
const absolutePath = import_node_path20.default.resolve(cwd, trimmed);
|
|
17256
|
-
if (!(0, import_node_fs15.existsSync)(absolutePath)) {
|
|
17257
|
-
if (trimmed.toLowerCase().endsWith(".svg")) {
|
|
17258
|
-
throw new Error(`App icon SVG file not found: ${absolutePath}`);
|
|
17259
|
-
}
|
|
17260
|
-
throw new Error("App icon must be inline SVG, an SVG data URL, or a .svg file path.");
|
|
17261
|
-
}
|
|
17262
|
-
if (import_node_path20.default.extname(absolutePath).toLowerCase() !== ".svg") {
|
|
17263
|
-
throw new Error(`App icon file must use the .svg extension: ${absolutePath}`);
|
|
17264
|
-
}
|
|
17265
|
-
const svg = (0, import_node_fs15.readFileSync)(absolutePath, "utf8").trim();
|
|
17266
|
-
if (!looksLikeSvgMarkup(svg)) {
|
|
17267
|
-
throw new Error(`App icon file is not valid SVG: ${absolutePath}`);
|
|
17213
|
+
return trimmed;
|
|
17268
17214
|
}
|
|
17269
|
-
|
|
17215
|
+
throw new Error("App icon must be an http(s) URL. Upload SVG files to OSS first and use the public link.");
|
|
17270
17216
|
}
|
|
17271
17217
|
function prepareAppPayload(payload, cwd) {
|
|
17272
17218
|
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
@@ -17287,13 +17233,13 @@ function createAppIconExportPlans(input) {
|
|
|
17287
17233
|
if (!input.outDir) {
|
|
17288
17234
|
throw new Error("App icon preset export requires --out-dir.");
|
|
17289
17235
|
}
|
|
17290
|
-
const outDir =
|
|
17291
|
-
(0,
|
|
17236
|
+
const outDir = import_node_path21.default.resolve(input.cwd, input.outDir);
|
|
17237
|
+
(0, import_node_fs16.mkdirSync)(outDir, { recursive: true });
|
|
17292
17238
|
return specs.map((spec) => ({
|
|
17293
17239
|
width: spec.width,
|
|
17294
17240
|
height: spec.height,
|
|
17295
17241
|
format: "png",
|
|
17296
|
-
outputPath:
|
|
17242
|
+
outputPath: import_node_path21.default.join(
|
|
17297
17243
|
outDir,
|
|
17298
17244
|
`${namespace}-${objectId}-${spec.name}-${spec.width}x${spec.height}.png`
|
|
17299
17245
|
)
|
|
@@ -17306,8 +17252,8 @@ function createAppIconExportPlans(input) {
|
|
|
17306
17252
|
if (!input.output) {
|
|
17307
17253
|
throw new Error("Single-size app icon export requires --output.");
|
|
17308
17254
|
}
|
|
17309
|
-
const resolvedOutput =
|
|
17310
|
-
(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 });
|
|
17311
17257
|
return [
|
|
17312
17258
|
{
|
|
17313
17259
|
width: input.width,
|
|
@@ -17317,11 +17263,34 @@ function createAppIconExportPlans(input) {
|
|
|
17317
17263
|
}
|
|
17318
17264
|
];
|
|
17319
17265
|
}
|
|
17320
|
-
async function exportAppIcon(
|
|
17266
|
+
async function exportAppIcon(icon, plans) {
|
|
17267
|
+
const svg = await resolveAppIconSvg(icon);
|
|
17321
17268
|
for (const plan of plans) {
|
|
17322
17269
|
const bytes = await renderAppIcon(svg, plan.width, plan.height, plan.format);
|
|
17323
|
-
(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}`);
|
|
17324
17289
|
}
|
|
17290
|
+
if (!looksLikeSvgMarkup(svg)) {
|
|
17291
|
+
throw new Error("App icon URL does not contain valid SVG markup.");
|
|
17292
|
+
}
|
|
17293
|
+
return svg;
|
|
17325
17294
|
}
|
|
17326
17295
|
async function renderAppIcon(svg, width, height, format) {
|
|
17327
17296
|
if (format === "svg") {
|
|
@@ -17343,23 +17312,6 @@ async function renderAppIcon(svg, width, height, format) {
|
|
|
17343
17312
|
function looksLikeSvgMarkup(value) {
|
|
17344
17313
|
return /<svg[\s>]/i.test(value);
|
|
17345
17314
|
}
|
|
17346
|
-
function normalizeSvgDataUrl(value) {
|
|
17347
|
-
const match = /^data:([^;,]+)?(?:;charset=[^;,]+)?(?:;(base64))?,(.*)$/i.exec(value);
|
|
17348
|
-
if (!match) {
|
|
17349
|
-
throw new Error("Invalid app icon data URL.");
|
|
17350
|
-
}
|
|
17351
|
-
const mimeType = (match[1] || "").toLowerCase();
|
|
17352
|
-
if (mimeType !== "image/svg+xml") {
|
|
17353
|
-
throw new Error(`App icon data URL must be image/svg+xml. Received: ${mimeType || "unknown"}`);
|
|
17354
|
-
}
|
|
17355
|
-
const payload = match[3] || "";
|
|
17356
|
-
const decoded = match[2] ? Buffer.from(payload, "base64").toString("utf8") : decodeURIComponent(payload);
|
|
17357
|
-
const svg = decoded.trim();
|
|
17358
|
-
if (!looksLikeSvgMarkup(svg)) {
|
|
17359
|
-
throw new Error("App icon data URL does not contain valid SVG markup.");
|
|
17360
|
-
}
|
|
17361
|
-
return svg;
|
|
17362
|
-
}
|
|
17363
17315
|
|
|
17364
17316
|
// src/commands/AppCommandHandler.ts
|
|
17365
17317
|
init_namespacedRef();
|
|
@@ -17375,7 +17327,12 @@ var AppCommandHandler = class {
|
|
|
17375
17327
|
"GET",
|
|
17376
17328
|
"/apps"
|
|
17377
17329
|
);
|
|
17378
|
-
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
|
+
});
|
|
17379
17336
|
this.renderList(items, args.json);
|
|
17380
17337
|
return;
|
|
17381
17338
|
}
|
|
@@ -17511,10 +17468,10 @@ var AppCommandHandler = class {
|
|
|
17511
17468
|
}
|
|
17512
17469
|
readJsonFile(filePath) {
|
|
17513
17470
|
const absolutePath = this.resolveFilePath(filePath);
|
|
17514
|
-
if (!(0,
|
|
17471
|
+
if (!(0, import_node_fs17.existsSync)(absolutePath)) {
|
|
17515
17472
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
17516
17473
|
}
|
|
17517
|
-
const raw = (0,
|
|
17474
|
+
const raw = (0, import_node_fs17.readFileSync)(absolutePath, "utf8");
|
|
17518
17475
|
try {
|
|
17519
17476
|
return JSON.parse(raw);
|
|
17520
17477
|
} catch (error) {
|
|
@@ -17524,10 +17481,10 @@ var AppCommandHandler = class {
|
|
|
17524
17481
|
}
|
|
17525
17482
|
preparePayload(filePath) {
|
|
17526
17483
|
const absolutePath = this.resolveFilePath(filePath);
|
|
17527
|
-
return prepareAppPayload(this.readJsonFile(filePath),
|
|
17484
|
+
return prepareAppPayload(this.readJsonFile(filePath), import_node_path22.default.dirname(absolutePath));
|
|
17528
17485
|
}
|
|
17529
17486
|
resolveFilePath(filePath) {
|
|
17530
|
-
return
|
|
17487
|
+
return import_node_path22.default.resolve(process.cwd(), filePath);
|
|
17531
17488
|
}
|
|
17532
17489
|
async request(baseUrl, token, method, pathname, body) {
|
|
17533
17490
|
const response = await fetch(`${baseUrl}${pathname}`, {
|
|
@@ -17601,15 +17558,15 @@ function readNamespaceFromPayload(payload) {
|
|
|
17601
17558
|
}
|
|
17602
17559
|
|
|
17603
17560
|
// src/commands/ServiceCommandHandler.ts
|
|
17604
|
-
var
|
|
17561
|
+
var import_node_fs19 = require("fs");
|
|
17605
17562
|
var import_promises5 = require("fs/promises");
|
|
17606
|
-
var
|
|
17563
|
+
var import_node_path24 = __toESM(require("path"));
|
|
17607
17564
|
var import_promises6 = require("readline/promises");
|
|
17608
17565
|
|
|
17609
17566
|
// src/services/ServiceRuntimeRunner.ts
|
|
17610
|
-
var
|
|
17611
|
-
var
|
|
17612
|
-
var
|
|
17567
|
+
var import_node_fs18 = require("fs");
|
|
17568
|
+
var import_node_os8 = __toESM(require("os"));
|
|
17569
|
+
var import_node_path23 = __toESM(require("path"));
|
|
17613
17570
|
var import_node_child_process10 = require("child_process");
|
|
17614
17571
|
var import_node_readline = require("readline");
|
|
17615
17572
|
var import_chalk3 = __toESM(require("chalk"));
|
|
@@ -17774,14 +17731,14 @@ var ServiceRuntimeRunner = class {
|
|
|
17774
17731
|
}
|
|
17775
17732
|
resolveRepoRoot(service, cwd) {
|
|
17776
17733
|
if (cwd) {
|
|
17777
|
-
return
|
|
17734
|
+
return import_node_path23.default.resolve(process.cwd(), cwd);
|
|
17778
17735
|
}
|
|
17779
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();
|
|
17780
17737
|
if (repository) {
|
|
17781
17738
|
const repoName = repository.replace(/\/+$/, "").split("/").pop()?.replace(/\.git$/i, "");
|
|
17782
17739
|
if (repoName) {
|
|
17783
|
-
const candidate =
|
|
17784
|
-
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)) {
|
|
17785
17742
|
return candidate;
|
|
17786
17743
|
}
|
|
17787
17744
|
}
|
|
@@ -17794,12 +17751,12 @@ var ServiceRuntimeRunner = class {
|
|
|
17794
17751
|
if (!dir) {
|
|
17795
17752
|
throw new Error(`Missing service dir for ${service.id}`);
|
|
17796
17753
|
}
|
|
17797
|
-
return
|
|
17754
|
+
return import_node_path23.default.resolve(repoRoot, dir);
|
|
17798
17755
|
}
|
|
17799
17756
|
async deployVite(service, options) {
|
|
17800
17757
|
const appDir = this.resolveLocalDir(service, options.cwd);
|
|
17801
|
-
const packageJsonPath =
|
|
17802
|
-
if (!(0,
|
|
17758
|
+
const packageJsonPath = import_node_path23.default.join(appDir, "package.json");
|
|
17759
|
+
if (!(0, import_node_fs18.existsSync)(packageJsonPath)) {
|
|
17803
17760
|
throw new Error(`No package.json found at ${packageJsonPath}`);
|
|
17804
17761
|
}
|
|
17805
17762
|
const pkg2 = this.loadPackageJson(packageJsonPath);
|
|
@@ -17808,8 +17765,8 @@ var ServiceRuntimeRunner = class {
|
|
|
17808
17765
|
throw new Error(`Missing package name in ${packageJsonPath}`);
|
|
17809
17766
|
}
|
|
17810
17767
|
await this.runCommand("pnpm", ["--filter", pkgName, "build"], this.resolveRepoRoot(service, options.cwd));
|
|
17811
|
-
const distDir =
|
|
17812
|
-
if (!(0,
|
|
17768
|
+
const distDir = import_node_path23.default.join(appDir, "dist");
|
|
17769
|
+
if (!(0, import_node_fs18.existsSync)(distDir)) {
|
|
17813
17770
|
throw new Error(`No dist directory found at ${distDir}`);
|
|
17814
17771
|
}
|
|
17815
17772
|
const site = this.getSite(service);
|
|
@@ -17821,8 +17778,8 @@ var ServiceRuntimeRunner = class {
|
|
|
17821
17778
|
}
|
|
17822
17779
|
async deployStatic(service, options) {
|
|
17823
17780
|
const appDir = this.resolveLocalDir(service, options.cwd);
|
|
17824
|
-
const srcDir =
|
|
17825
|
-
if (!(0,
|
|
17781
|
+
const srcDir = import_node_path23.default.join(appDir, "src");
|
|
17782
|
+
if (!(0, import_node_fs18.existsSync)(srcDir)) {
|
|
17826
17783
|
throw new Error(`No src directory found at ${srcDir}`);
|
|
17827
17784
|
}
|
|
17828
17785
|
const site = this.getSite(service);
|
|
@@ -17942,7 +17899,7 @@ var ServiceRuntimeRunner = class {
|
|
|
17942
17899
|
const serverAddress = await resolveServerAddress(server);
|
|
17943
17900
|
const templateName = exposeType === "websocket" ? "nginx.ws.template" : "nginx.rest.template";
|
|
17944
17901
|
const templatePath = this.resolveTemplatePath(templateName);
|
|
17945
|
-
const template = (0,
|
|
17902
|
+
const template = (0, import_node_fs18.readFileSync)(templatePath, "utf8");
|
|
17946
17903
|
const host = `${subdomain}.${("domain" in network ? network.domain?.trim() : void 0) || "pmate.chat"}`;
|
|
17947
17904
|
const rendered = template.replace(/\$\{\{PORT\}\}/g, String(port)).replace(/\$\{\{HOSTS\}\}/g, host).replace(/\$\{\{HOST\}\}/g, host);
|
|
17948
17905
|
const remotePath = `/etc/nginx/sites-enabled/${subdomain}.conf`;
|
|
@@ -17974,11 +17931,11 @@ var ServiceRuntimeRunner = class {
|
|
|
17974
17931
|
}
|
|
17975
17932
|
if (config.ensurePackageJson) {
|
|
17976
17933
|
const appDir = this.resolveLocalDir(service, options.cwd);
|
|
17977
|
-
const packageJsonPath =
|
|
17978
|
-
if (!(0,
|
|
17934
|
+
const packageJsonPath = import_node_path23.default.join(appDir, "package.json");
|
|
17935
|
+
if (!(0, import_node_fs18.existsSync)(packageJsonPath)) {
|
|
17979
17936
|
throw new Error(`Missing package.json at ${packageJsonPath}`);
|
|
17980
17937
|
}
|
|
17981
|
-
const pkgStat = (0,
|
|
17938
|
+
const pkgStat = (0, import_node_fs18.statSync)(packageJsonPath);
|
|
17982
17939
|
if (!pkgStat.isFile()) {
|
|
17983
17940
|
throw new Error(`package.json is not a file at ${packageJsonPath}`);
|
|
17984
17941
|
}
|
|
@@ -18402,9 +18359,9 @@ var ServiceRuntimeRunner = class {
|
|
|
18402
18359
|
return tokens;
|
|
18403
18360
|
}
|
|
18404
18361
|
readPathValue(source, pathExpr) {
|
|
18405
|
-
const
|
|
18362
|
+
const path28 = pathExpr.split(".").map((segment) => segment.trim()).filter(Boolean);
|
|
18406
18363
|
let cursor = source;
|
|
18407
|
-
for (const segment of
|
|
18364
|
+
for (const segment of path28) {
|
|
18408
18365
|
if (!cursor || typeof cursor !== "object" || Array.isArray(cursor)) {
|
|
18409
18366
|
return void 0;
|
|
18410
18367
|
}
|
|
@@ -18447,12 +18404,12 @@ var ServiceRuntimeRunner = class {
|
|
|
18447
18404
|
}
|
|
18448
18405
|
resolveTemplatePath(templateName) {
|
|
18449
18406
|
const candidates = [
|
|
18450
|
-
|
|
18451
|
-
|
|
18452
|
-
|
|
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)
|
|
18453
18410
|
];
|
|
18454
18411
|
for (const candidate of candidates) {
|
|
18455
|
-
if ((0,
|
|
18412
|
+
if ((0, import_node_fs18.existsSync)(candidate)) {
|
|
18456
18413
|
return candidate;
|
|
18457
18414
|
}
|
|
18458
18415
|
}
|
|
@@ -18484,7 +18441,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18484
18441
|
});
|
|
18485
18442
|
}
|
|
18486
18443
|
loadPackageJson(packageJsonPath) {
|
|
18487
|
-
const raw = (0,
|
|
18444
|
+
const raw = (0, import_node_fs18.readFileSync)(packageJsonPath, "utf8");
|
|
18488
18445
|
const parsed = JSON.parse(raw);
|
|
18489
18446
|
if (!parsed || typeof parsed !== "object") {
|
|
18490
18447
|
throw new Error(`Invalid package.json at ${packageJsonPath}`);
|
|
@@ -18493,7 +18450,7 @@ var ServiceRuntimeRunner = class {
|
|
|
18493
18450
|
}
|
|
18494
18451
|
writePackageJson(packageJsonPath, data) {
|
|
18495
18452
|
const serialized = JSON.stringify(data, null, 2);
|
|
18496
|
-
(0,
|
|
18453
|
+
(0, import_node_fs18.writeFileSync)(packageJsonPath, `${serialized}
|
|
18497
18454
|
`, "utf8");
|
|
18498
18455
|
}
|
|
18499
18456
|
runCommand(command, args, cwd) {
|
|
@@ -18830,7 +18787,7 @@ var ServiceCommandHandler = class {
|
|
|
18830
18787
|
format: "dotenv"
|
|
18831
18788
|
}
|
|
18832
18789
|
);
|
|
18833
|
-
const outputPath =
|
|
18790
|
+
const outputPath = import_node_path24.default.resolve(process.cwd(), args.output);
|
|
18834
18791
|
await (0, import_promises5.writeFile)(outputPath, payload.content, "utf8");
|
|
18835
18792
|
ui.success(`Wrote env file for ${args.appId} to ${outputPath}`);
|
|
18836
18793
|
this.renderJson({ ...payload, output: outputPath }, args.json);
|
|
@@ -18859,11 +18816,11 @@ var ServiceCommandHandler = class {
|
|
|
18859
18816
|
return (baseUrl || process.env.PMATE_APPS_API_BASE_URL || "https://apps-api.pmate.chat").replace(/\/+$/, "");
|
|
18860
18817
|
}
|
|
18861
18818
|
readJsonFile(filePath) {
|
|
18862
|
-
const absolutePath =
|
|
18863
|
-
if (!(0,
|
|
18819
|
+
const absolutePath = import_node_path24.default.resolve(process.cwd(), filePath);
|
|
18820
|
+
if (!(0, import_node_fs19.existsSync)(absolutePath)) {
|
|
18864
18821
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
18865
18822
|
}
|
|
18866
|
-
const raw = (0,
|
|
18823
|
+
const raw = (0, import_node_fs19.readFileSync)(absolutePath, "utf8");
|
|
18867
18824
|
try {
|
|
18868
18825
|
return JSON.parse(raw);
|
|
18869
18826
|
} catch (error) {
|
|
@@ -19203,8 +19160,8 @@ var RoleCommandHandler = class {
|
|
|
19203
19160
|
};
|
|
19204
19161
|
|
|
19205
19162
|
// src/commands/AccountCommandHandler.ts
|
|
19206
|
-
var
|
|
19207
|
-
var
|
|
19163
|
+
var import_node_fs20 = require("fs");
|
|
19164
|
+
var import_node_path25 = __toESM(require("path"));
|
|
19208
19165
|
init_sessionStore();
|
|
19209
19166
|
var AccountCommandHandler = class {
|
|
19210
19167
|
async handle(args) {
|
|
@@ -19452,10 +19409,10 @@ var AccountCommandHandler = class {
|
|
|
19452
19409
|
throw new Error("Missing visible apps input");
|
|
19453
19410
|
}
|
|
19454
19411
|
const absolutePath = this.resolveFilePath(args.filePath);
|
|
19455
|
-
if (!(0,
|
|
19412
|
+
if (!(0, import_node_fs20.existsSync)(absolutePath)) {
|
|
19456
19413
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
19457
19414
|
}
|
|
19458
|
-
const raw = (0,
|
|
19415
|
+
const raw = (0, import_node_fs20.readFileSync)(absolutePath, "utf8");
|
|
19459
19416
|
let parsed;
|
|
19460
19417
|
try {
|
|
19461
19418
|
parsed = JSON.parse(raw);
|
|
@@ -19469,7 +19426,7 @@ var AccountCommandHandler = class {
|
|
|
19469
19426
|
return parsed;
|
|
19470
19427
|
}
|
|
19471
19428
|
resolveFilePath(filePath) {
|
|
19472
|
-
return
|
|
19429
|
+
return import_node_path25.default.resolve(process.cwd(), filePath);
|
|
19473
19430
|
}
|
|
19474
19431
|
};
|
|
19475
19432
|
function encodePathSegment(value) {
|
|
@@ -19477,8 +19434,8 @@ function encodePathSegment(value) {
|
|
|
19477
19434
|
}
|
|
19478
19435
|
|
|
19479
19436
|
// src/commands/OrgCommandHandler.ts
|
|
19480
|
-
var
|
|
19481
|
-
var
|
|
19437
|
+
var import_node_fs21 = require("fs");
|
|
19438
|
+
var import_node_path26 = __toESM(require("path"));
|
|
19482
19439
|
init_sessionStore();
|
|
19483
19440
|
var OrgCommandHandler = class {
|
|
19484
19441
|
async handle(args) {
|
|
@@ -19649,11 +19606,11 @@ var OrgCommandHandler = class {
|
|
|
19649
19606
|
if (!filePath) {
|
|
19650
19607
|
throw new Error(`Missing ${itemLabel} input`);
|
|
19651
19608
|
}
|
|
19652
|
-
const absolutePath =
|
|
19653
|
-
if (!(0,
|
|
19609
|
+
const absolutePath = import_node_path26.default.resolve(process.cwd(), filePath);
|
|
19610
|
+
if (!(0, import_node_fs21.existsSync)(absolutePath)) {
|
|
19654
19611
|
throw new Error(`JSON file not found: ${absolutePath}`);
|
|
19655
19612
|
}
|
|
19656
|
-
const raw = (0,
|
|
19613
|
+
const raw = (0, import_node_fs21.readFileSync)(absolutePath, "utf8");
|
|
19657
19614
|
let parsed;
|
|
19658
19615
|
try {
|
|
19659
19616
|
parsed = JSON.parse(raw);
|
|
@@ -20552,6 +20509,7 @@ function parseAppArgs(tokens) {
|
|
|
20552
20509
|
};
|
|
20553
20510
|
if (action === "list") {
|
|
20554
20511
|
let namespace;
|
|
20512
|
+
let all = false;
|
|
20555
20513
|
while (rest.length > 0) {
|
|
20556
20514
|
const token = rest.shift();
|
|
20557
20515
|
switch (token) {
|
|
@@ -20559,6 +20517,9 @@ function parseAppArgs(tokens) {
|
|
|
20559
20517
|
case "--namespace":
|
|
20560
20518
|
namespace = requireValue5(rest, token);
|
|
20561
20519
|
break;
|
|
20520
|
+
case "--all":
|
|
20521
|
+
all = true;
|
|
20522
|
+
break;
|
|
20562
20523
|
case "--base-url":
|
|
20563
20524
|
baseUrl = requireValue5(rest, token);
|
|
20564
20525
|
break;
|
|
@@ -20569,7 +20530,7 @@ function parseAppArgs(tokens) {
|
|
|
20569
20530
|
throw new Error(`Unknown app list option: ${token}`);
|
|
20570
20531
|
}
|
|
20571
20532
|
}
|
|
20572
|
-
return { type: "app" /* App */, action, namespace, baseUrl, json };
|
|
20533
|
+
return { type: "app" /* App */, action, namespace, all, baseUrl, json };
|
|
20573
20534
|
}
|
|
20574
20535
|
if (action === "view") {
|
|
20575
20536
|
const rawRef = rest.shift();
|
|
@@ -22138,7 +22099,7 @@ function requireValue11(tokens, option) {
|
|
|
22138
22099
|
|
|
22139
22100
|
// src/index.ts
|
|
22140
22101
|
var pkg = JSON.parse(
|
|
22141
|
-
(0,
|
|
22102
|
+
(0, import_node_fs22.readFileSync)(import_node_path27.default.resolve(__dirname, "..", "package.json"), "utf8")
|
|
22142
22103
|
);
|
|
22143
22104
|
var HELP_TEXT = [
|
|
22144
22105
|
import_chalk4.default.bold(`pmate v${pkg.version}`),
|
|
@@ -22281,7 +22242,7 @@ var HELP_TEXT = [
|
|
|
22281
22242
|
` ${import_chalk4.default.gray(" kv list|get|exists|set|delete <name> [options]")}`,
|
|
22282
22243
|
` ${import_chalk4.default.gray(" defaults: chain=pmate namespace=pmate env base URLs from BLOCKCHAIN_BASE_URL / INDEXER_BASE_URL")}`,
|
|
22283
22244
|
` ${import_chalk4.default.cyan("app")} Manage app registry entries via apps-api`,
|
|
22284
|
-
` ${import_chalk4.default.gray(" list [--ns <namespace>] [--base-url <url>] [--json]")}`,
|
|
22245
|
+
` ${import_chalk4.default.gray(" list [--ns <namespace>] [--all] [--base-url <url>] [--json]")}`,
|
|
22285
22246
|
` ${import_chalk4.default.gray(" get <ns:objectId> [--base-url <url>] [--json]")}`,
|
|
22286
22247
|
` ${import_chalk4.default.gray(" view <ns:objectId> [--base-url <url>]")}`,
|
|
22287
22248
|
` ${import_chalk4.default.gray(" create --file <path> [--base-url <url>] [--json]")}`,
|