@pmate/cli 0.24.43 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +162 -59
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -16179,8 +16179,7 @@ var CollectCommandHandler = class {
|
|
|
16179
16179
|
if (!thread) {
|
|
16180
16180
|
throw new Error(`Thread not found: ${args.thread}`);
|
|
16181
16181
|
}
|
|
16182
|
-
await this.
|
|
16183
|
-
await this.sendReplyText(targetPage, args.text);
|
|
16182
|
+
await this.sendReplyViaConversation(targetPage, thread, args.text);
|
|
16184
16183
|
ui.success("im1 reply sent", { source: target.sourceKey, thread: thread.name });
|
|
16185
16184
|
} catch (error) {
|
|
16186
16185
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -16413,47 +16412,14 @@ var CollectCommandHandler = class {
|
|
|
16413
16412
|
await session.detach().catch(() => void 0);
|
|
16414
16413
|
}
|
|
16415
16414
|
}
|
|
16416
|
-
async
|
|
16417
|
-
const
|
|
16415
|
+
async sendReplyViaConversation(page, thread, text) {
|
|
16416
|
+
const result = await this.evaluateInPage(
|
|
16418
16417
|
page,
|
|
16419
|
-
|
|
16420
|
-
)
|
|
16421
|
-
|
|
16422
|
-
|
|
16423
|
-
}));
|
|
16424
|
-
if (!opened.ok) {
|
|
16425
|
-
await page.getByText(thread.name, { exact: true }).first().click({ timeout: 5e3 });
|
|
16426
|
-
}
|
|
16427
|
-
await page.waitForTimeout(500);
|
|
16428
|
-
}
|
|
16429
|
-
async sendReplyText(page, text) {
|
|
16430
|
-
const selectors = [
|
|
16431
|
-
'[data-testid="CompositionInput"]',
|
|
16432
|
-
'[aria-label="Message"]',
|
|
16433
|
-
'[aria-label="Write a message"]',
|
|
16434
|
-
'[contenteditable="true"]',
|
|
16435
|
-
"textarea"
|
|
16436
|
-
];
|
|
16437
|
-
let focused = false;
|
|
16438
|
-
for (const selector of selectors) {
|
|
16439
|
-
const locator = page.locator(selector).last();
|
|
16440
|
-
if (await locator.count().catch(() => 0) === 0) {
|
|
16441
|
-
continue;
|
|
16442
|
-
}
|
|
16443
|
-
await locator.click({ timeout: 3e3 }).catch(() => void 0);
|
|
16444
|
-
focused = await locator.evaluate((element) => {
|
|
16445
|
-
const activeElement = element.ownerDocument?.activeElement;
|
|
16446
|
-
return activeElement === element || element.contains(activeElement);
|
|
16447
|
-
}).catch(() => false);
|
|
16448
|
-
if (focused) {
|
|
16449
|
-
break;
|
|
16450
|
-
}
|
|
16451
|
-
}
|
|
16452
|
-
if (!focused) {
|
|
16453
|
-
throw new Error("Cannot focus CC message composer.");
|
|
16418
|
+
buildSendMessageExpr(thread.conversationId, text)
|
|
16419
|
+
);
|
|
16420
|
+
if (!result?.ok) {
|
|
16421
|
+
throw new Error(result?.reason || "Send failed");
|
|
16454
16422
|
}
|
|
16455
|
-
await page.keyboard.insertText(text);
|
|
16456
|
-
await page.keyboard.press("Enter");
|
|
16457
16423
|
}
|
|
16458
16424
|
};
|
|
16459
16425
|
async function archiveMessageImages(rootDir, sourceKey, threadKey, messages2) {
|
|
@@ -16708,31 +16674,168 @@ function buildGetMessagesByConversationExpr(conversationId, limit) {
|
|
|
16708
16674
|
}
|
|
16709
16675
|
})()`;
|
|
16710
16676
|
}
|
|
16711
|
-
function
|
|
16677
|
+
function buildSendMessageExpr(conversationId, message) {
|
|
16712
16678
|
const escapedConversationId = escapeForJs(conversationId);
|
|
16679
|
+
const escapedMessage = escapeForJs(message);
|
|
16713
16680
|
return `(async function() {
|
|
16714
16681
|
try {
|
|
16715
|
-
var
|
|
16716
|
-
|
|
16717
|
-
|
|
16718
|
-
|
|
16719
|
-
|
|
16720
|
-
if (
|
|
16721
|
-
|
|
16722
|
-
|
|
16723
|
-
|
|
16724
|
-
|
|
16682
|
+
var controller = globalThis.ConversationController;
|
|
16683
|
+
if (!controller || typeof controller.get !== 'function') {
|
|
16684
|
+
return { ok: false, reason: 'ConversationController unavailable' };
|
|
16685
|
+
}
|
|
16686
|
+
var conversation = controller.get('${escapedConversationId}');
|
|
16687
|
+
if (!conversation) return { ok: false, reason: 'Conversation not found: ${escapedConversationId}' };
|
|
16688
|
+
if (typeof conversation.sendMessage !== 'function') {
|
|
16689
|
+
return { ok: false, reason: 'Conversation sendMessage unavailable' };
|
|
16690
|
+
}
|
|
16691
|
+
var type = conversation.get ? conversation.get('type') : null;
|
|
16692
|
+
var name = conversation.get ? (conversation.get('name') || conversation.get('id')) : '${escapedConversationId}';
|
|
16693
|
+
function normalizeMentionName(value) {
|
|
16694
|
+
return String(value || '')
|
|
16695
|
+
.replace(/\\s+/g, ' ')
|
|
16696
|
+
.replace(/\\u200B/g, '')
|
|
16697
|
+
.trim();
|
|
16698
|
+
}
|
|
16699
|
+
function addLookup(lookup, name, id) {
|
|
16700
|
+
var normalized = normalizeMentionName(name);
|
|
16701
|
+
if (!normalized || !id || lookup[normalized]) return;
|
|
16702
|
+
lookup[normalized] = id;
|
|
16703
|
+
}
|
|
16704
|
+
function addMentionAliases(lookup, name, id) {
|
|
16705
|
+
var normalized = normalizeMentionName(name);
|
|
16706
|
+
addLookup(lookup, normalized, id);
|
|
16707
|
+
addLookup(lookup, normalized.replace(/\\s*\\([^)]*\\)\\s*$/g, ''), id);
|
|
16708
|
+
addLookup(lookup, normalized.replace(/\\s*\\[[^\\]]*\\]\\s*$/g, ''), id);
|
|
16709
|
+
addLookup(lookup, normalized.replace(/\\s*[\uFF08][^\uFF09]*[\uFF09]\\s*$/g, ''), id);
|
|
16710
|
+
}
|
|
16711
|
+
function buildMentionLookup() {
|
|
16712
|
+
var lookup = {};
|
|
16713
|
+
var all = [];
|
|
16714
|
+
if (controller && typeof controller.getAllPrivateConversations === 'function') {
|
|
16715
|
+
var privates = controller.getAllPrivateConversations();
|
|
16716
|
+
all = privates.models || privates || [];
|
|
16717
|
+
}
|
|
16718
|
+
for (var i = 0; i < all.length; i++) {
|
|
16719
|
+
var contact = all[i];
|
|
16720
|
+
var id = normalizeMentionName(contact && contact.get ? contact.get('id') : contact && contact.id);
|
|
16721
|
+
if (!id) continue;
|
|
16722
|
+
addMentionAliases(lookup, contact && contact.get ? contact.get('name') : contact && contact.name, id);
|
|
16723
|
+
addMentionAliases(lookup, contact && contact.get ? contact.get('profileName') : contact && contact.profileName, id);
|
|
16724
|
+
addMentionAliases(lookup, contact && contact.get ? contact.get('title') : contact && contact.title, id);
|
|
16725
|
+
}
|
|
16726
|
+
return lookup;
|
|
16727
|
+
}
|
|
16728
|
+
function normalizeMentionKey(value) {
|
|
16729
|
+
return normalizeMentionName(value)
|
|
16730
|
+
.replace(/^@+/, '')
|
|
16731
|
+
.replace(/\\s*\\([^)]*\\)\\s*$/g, '')
|
|
16732
|
+
.replace(/\\s*\\[[^\\]]*\\]\\s*$/g, '')
|
|
16733
|
+
.replace(/\\s*[\uFF08][^\uFF09]*[\uFF09]\\s*$/g, '')
|
|
16734
|
+
.toLowerCase()
|
|
16735
|
+
.replace(/[^\\p{L}\\p{N}]+/gu, ' ')
|
|
16736
|
+
.trim();
|
|
16737
|
+
}
|
|
16738
|
+
function hasWordBoundary(text, end) {
|
|
16739
|
+
return end >= text.length || !/[\\p{L}\\p{N}_]/u.test(text[end]);
|
|
16740
|
+
}
|
|
16741
|
+
function readMentionQuery(text, atIndex) {
|
|
16742
|
+
var start = atIndex + 1;
|
|
16743
|
+
var end = start;
|
|
16744
|
+
while (end < text.length && /[\\p{L}\\p{N}_-]/u.test(text[end])) {
|
|
16745
|
+
end += 1;
|
|
16746
|
+
}
|
|
16747
|
+
if (end === start) return null;
|
|
16748
|
+
return { raw: text.slice(start, end), start: atIndex, end: end };
|
|
16749
|
+
}
|
|
16750
|
+
function resolveFuzzyMention(query, lookup) {
|
|
16751
|
+
var queryKey = normalizeMentionKey(query);
|
|
16752
|
+
if (!queryKey) return null;
|
|
16753
|
+
var scoresByUid = {};
|
|
16754
|
+
var aliases = Object.keys(lookup);
|
|
16755
|
+
for (var i = 0; i < aliases.length; i++) {
|
|
16756
|
+
var alias = aliases[i];
|
|
16757
|
+
var aliasKey = normalizeMentionKey(alias);
|
|
16758
|
+
if (!aliasKey) continue;
|
|
16759
|
+
var score = 0;
|
|
16760
|
+
var aliasTokens = aliasKey.split(' ');
|
|
16761
|
+
if (aliasKey === queryKey) score = 100;
|
|
16762
|
+
else if (aliasTokens.indexOf(queryKey) !== -1) score = 80;
|
|
16763
|
+
else if (aliasKey.indexOf(queryKey) !== -1) score = 60;
|
|
16764
|
+
else if (queryKey.indexOf(aliasKey) !== -1) score = 40;
|
|
16765
|
+
if (score === 0) continue;
|
|
16766
|
+
var uid = lookup[alias];
|
|
16767
|
+
if (!scoresByUid[uid] || score > scoresByUid[uid]) {
|
|
16768
|
+
scoresByUid[uid] = score;
|
|
16769
|
+
}
|
|
16725
16770
|
}
|
|
16726
|
-
|
|
16727
|
-
|
|
16728
|
-
|
|
16771
|
+
var bestUid = null;
|
|
16772
|
+
var bestScore = 0;
|
|
16773
|
+
var bestCount = 0;
|
|
16774
|
+
var uids = Object.keys(scoresByUid);
|
|
16775
|
+
for (var j = 0; j < uids.length; j++) {
|
|
16776
|
+
var uidScore = scoresByUid[uids[j]];
|
|
16777
|
+
if (uidScore > bestScore) {
|
|
16778
|
+
bestUid = uids[j];
|
|
16779
|
+
bestScore = uidScore;
|
|
16780
|
+
bestCount = 1;
|
|
16781
|
+
} else if (uidScore === bestScore) {
|
|
16782
|
+
bestCount += 1;
|
|
16783
|
+
}
|
|
16729
16784
|
}
|
|
16785
|
+
return bestUid && bestCount === 1 ? bestUid : null;
|
|
16730
16786
|
}
|
|
16731
|
-
|
|
16732
|
-
|
|
16733
|
-
|
|
16787
|
+
function extractMentions(text) {
|
|
16788
|
+
var lookup = buildMentionLookup();
|
|
16789
|
+
var names = Object.keys(lookup).sort(function(a, b) { return b.length - a.length; });
|
|
16790
|
+
var mentions = [];
|
|
16791
|
+
var occupied = [];
|
|
16792
|
+
function overlaps(start, end) {
|
|
16793
|
+
for (var i = 0; i < occupied.length; i++) {
|
|
16794
|
+
if (start < occupied[i].end && end > occupied[i].start) return true;
|
|
16795
|
+
}
|
|
16796
|
+
return false;
|
|
16797
|
+
}
|
|
16798
|
+
var atIndex = 0;
|
|
16799
|
+
while (atIndex < text.length) {
|
|
16800
|
+
var idx = text.indexOf('@', atIndex);
|
|
16801
|
+
if (idx === -1) break;
|
|
16802
|
+
if (overlaps(idx, idx + 1)) {
|
|
16803
|
+
atIndex = idx + 1;
|
|
16804
|
+
continue;
|
|
16805
|
+
}
|
|
16806
|
+
var matched = null;
|
|
16807
|
+
for (var i = 0; i < names.length; i++) {
|
|
16808
|
+
var mentionText = '@' + names[i];
|
|
16809
|
+
if (text.slice(idx, idx + mentionText.length) === mentionText && hasWordBoundary(text, idx + mentionText.length)) {
|
|
16810
|
+
matched = { uid: lookup[names[i]], start: idx, end: idx + mentionText.length };
|
|
16811
|
+
break;
|
|
16812
|
+
}
|
|
16813
|
+
}
|
|
16814
|
+
if (!matched) {
|
|
16815
|
+
var query = readMentionQuery(text, idx);
|
|
16816
|
+
if (query) {
|
|
16817
|
+
var fuzzyUid = resolveFuzzyMention(query.raw, lookup);
|
|
16818
|
+
if (fuzzyUid) {
|
|
16819
|
+
matched = { uid: fuzzyUid, start: query.start, end: query.end };
|
|
16820
|
+
}
|
|
16821
|
+
}
|
|
16822
|
+
}
|
|
16823
|
+
if (matched && !overlaps(matched.start, matched.end)) {
|
|
16824
|
+
mentions.push({ uid: matched.uid, start: matched.start, length: matched.end - matched.start, type: 0 });
|
|
16825
|
+
occupied.push({ start: matched.start, end: matched.end });
|
|
16826
|
+
atIndex = matched.end;
|
|
16827
|
+
} else {
|
|
16828
|
+
atIndex = idx + 1;
|
|
16829
|
+
}
|
|
16830
|
+
}
|
|
16831
|
+
mentions.sort(function(a, b) { return a.start - b.start; });
|
|
16832
|
+
return mentions;
|
|
16734
16833
|
}
|
|
16735
|
-
|
|
16834
|
+
var mentions = extractMentions('${escapedMessage}');
|
|
16835
|
+
var mentionTarget = mentions.length > 0 ? mentions[0].uid : null;
|
|
16836
|
+
var mentionsArg = mentions.length > 0 ? mentions : null;
|
|
16837
|
+
await conversation.sendMessage('${escapedMessage}', mentionTarget, mentionsArg, [], null, null, null, null, null, null);
|
|
16838
|
+
return { ok: true, name: name, type: type, mentionCount: mentions.length };
|
|
16736
16839
|
} catch(e) {
|
|
16737
16840
|
return { ok: false, reason: e && e.message ? e.message : String(e) };
|
|
16738
16841
|
}
|