@pmate/cli 0.24.44 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +226 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -16179,7 +16179,11 @@ var CollectCommandHandler = class {
|
|
|
16179
16179
|
if (!thread) {
|
|
16180
16180
|
throw new Error(`Thread not found: ${args.thread}`);
|
|
16181
16181
|
}
|
|
16182
|
-
await this.sendReplyViaConversation(targetPage, thread, args.text);
|
|
16182
|
+
const result = await this.sendReplyViaConversation(targetPage, thread, args.text, args.dryRun);
|
|
16183
|
+
if (args.dryRun) {
|
|
16184
|
+
ui.plain(JSON.stringify({ source: target.sourceKey, thread: thread.name, ...result }, null, 2));
|
|
16185
|
+
return;
|
|
16186
|
+
}
|
|
16183
16187
|
ui.success("im1 reply sent", { source: target.sourceKey, thread: thread.name });
|
|
16184
16188
|
} catch (error) {
|
|
16185
16189
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -16412,14 +16416,15 @@ var CollectCommandHandler = class {
|
|
|
16412
16416
|
await session.detach().catch(() => void 0);
|
|
16413
16417
|
}
|
|
16414
16418
|
}
|
|
16415
|
-
async sendReplyViaConversation(page, thread, text) {
|
|
16419
|
+
async sendReplyViaConversation(page, thread, text, dryRun) {
|
|
16416
16420
|
const result = await this.evaluateInPage(
|
|
16417
16421
|
page,
|
|
16418
|
-
buildSendMessageExpr(thread.conversationId, text)
|
|
16422
|
+
buildSendMessageExpr(thread.conversationId, text, dryRun)
|
|
16419
16423
|
);
|
|
16420
16424
|
if (!result?.ok) {
|
|
16421
16425
|
throw new Error(result?.reason || "Send failed");
|
|
16422
16426
|
}
|
|
16427
|
+
return result;
|
|
16423
16428
|
}
|
|
16424
16429
|
};
|
|
16425
16430
|
async function archiveMessageImages(rootDir, sourceKey, threadKey, messages2) {
|
|
@@ -16674,7 +16679,7 @@ function buildGetMessagesByConversationExpr(conversationId, limit) {
|
|
|
16674
16679
|
}
|
|
16675
16680
|
})()`;
|
|
16676
16681
|
}
|
|
16677
|
-
function buildSendMessageExpr(conversationId, message) {
|
|
16682
|
+
function buildSendMessageExpr(conversationId, message, dryRun = false) {
|
|
16678
16683
|
const escapedConversationId = escapeForJs(conversationId);
|
|
16679
16684
|
const escapedMessage = escapeForJs(message);
|
|
16680
16685
|
return `(async function() {
|
|
@@ -16690,8 +16695,216 @@ function buildSendMessageExpr(conversationId, message) {
|
|
|
16690
16695
|
}
|
|
16691
16696
|
var type = conversation.get ? conversation.get('type') : null;
|
|
16692
16697
|
var name = conversation.get ? (conversation.get('name') || conversation.get('id')) : '${escapedConversationId}';
|
|
16693
|
-
|
|
16694
|
-
|
|
16698
|
+
function normalizeMentionName(value) {
|
|
16699
|
+
return String(value || '')
|
|
16700
|
+
.replace(/\\s+/g, ' ')
|
|
16701
|
+
.replace(/\\u200B/g, '')
|
|
16702
|
+
.trim();
|
|
16703
|
+
}
|
|
16704
|
+
function addLookup(lookup, name, id, label) {
|
|
16705
|
+
var normalized = normalizeMentionName(name);
|
|
16706
|
+
if (!normalized || !id || lookup[normalized]) return;
|
|
16707
|
+
lookup[normalized] = { uid: id, label: normalizeMentionName(label || name) };
|
|
16708
|
+
}
|
|
16709
|
+
function addMentionAliases(lookup, name, id) {
|
|
16710
|
+
var normalized = normalizeMentionName(name);
|
|
16711
|
+
addLookup(lookup, normalized, id, normalized);
|
|
16712
|
+
addLookup(lookup, normalized.replace(/\\s*\\([^)]*\\)\\s*$/g, ''), id, normalized);
|
|
16713
|
+
addLookup(lookup, normalized.replace(/\\s*\\[[^\\]]*\\]\\s*$/g, ''), id, normalized);
|
|
16714
|
+
addLookup(lookup, normalized.replace(/\\s*[\uFF08][^\uFF09]*[\uFF09]\\s*$/g, ''), id, normalized);
|
|
16715
|
+
}
|
|
16716
|
+
function addContactToLookup(lookup, contact) {
|
|
16717
|
+
if (!contact) return;
|
|
16718
|
+
var id = normalizeMentionName(contact && contact.get ? contact.get('id') : contact && contact.id);
|
|
16719
|
+
if (!id) return;
|
|
16720
|
+
addMentionAliases(lookup, contact && contact.get ? contact.get('name') : contact && contact.name, id);
|
|
16721
|
+
addMentionAliases(lookup, contact && contact.get ? contact.get('profileName') : contact && contact.profileName, id);
|
|
16722
|
+
addMentionAliases(lookup, contact && contact.get ? contact.get('title') : contact && contact.title, id);
|
|
16723
|
+
}
|
|
16724
|
+
function buildMentionLookup() {
|
|
16725
|
+
var lookup = {};
|
|
16726
|
+
var all = [];
|
|
16727
|
+
if (controller && typeof controller.getAllPrivateConversations === 'function') {
|
|
16728
|
+
var privates = controller.getAllPrivateConversations();
|
|
16729
|
+
all = privates.models || privates || [];
|
|
16730
|
+
}
|
|
16731
|
+
for (var i = 0; i < all.length; i++) {
|
|
16732
|
+
addContactToLookup(lookup, all[i]);
|
|
16733
|
+
}
|
|
16734
|
+
var memberIds = [];
|
|
16735
|
+
var membersV2 = conversation && conversation.get ? (conversation.get('membersV2') || []) : [];
|
|
16736
|
+
var members = conversation && conversation.get ? (conversation.get('members') || []) : [];
|
|
16737
|
+
for (var j = 0; j < membersV2.length; j++) {
|
|
16738
|
+
memberIds.push(membersV2[j].id || membersV2[j]);
|
|
16739
|
+
addMentionAliases(lookup, membersV2[j].displayName, membersV2[j].id);
|
|
16740
|
+
}
|
|
16741
|
+
for (var k = 0; k < members.length; k++) {
|
|
16742
|
+
memberIds.push(members[k]);
|
|
16743
|
+
}
|
|
16744
|
+
for (var m = 0; m < memberIds.length; m++) {
|
|
16745
|
+
var memberContact = controller.get(memberIds[m]);
|
|
16746
|
+
if (memberContact) addContactToLookup(lookup, memberContact);
|
|
16747
|
+
}
|
|
16748
|
+
return lookup;
|
|
16749
|
+
}
|
|
16750
|
+
function normalizeMentionKey(value) {
|
|
16751
|
+
return normalizeMentionName(value)
|
|
16752
|
+
.replace(/^@+/, '')
|
|
16753
|
+
.replace(/\\s*\\([^)]*\\)\\s*$/g, '')
|
|
16754
|
+
.replace(/\\s*\\[[^\\]]*\\]\\s*$/g, '')
|
|
16755
|
+
.replace(/\\s*[\uFF08][^\uFF09]*[\uFF09]\\s*$/g, '')
|
|
16756
|
+
.toLowerCase()
|
|
16757
|
+
.replace(/[^\\p{L}\\p{N}]+/gu, ' ')
|
|
16758
|
+
.trim();
|
|
16759
|
+
}
|
|
16760
|
+
function hasWordBoundary(text, end) {
|
|
16761
|
+
return end >= text.length || !/[\\p{L}\\p{N}_]/u.test(text[end]);
|
|
16762
|
+
}
|
|
16763
|
+
function readMentionQuery(text, atIndex) {
|
|
16764
|
+
var start = atIndex + 1;
|
|
16765
|
+
var end = start;
|
|
16766
|
+
while (end < text.length && /[\\p{L}\\p{N}_-]/u.test(text[end])) {
|
|
16767
|
+
end += 1;
|
|
16768
|
+
}
|
|
16769
|
+
if (end === start) return null;
|
|
16770
|
+
return { raw: text.slice(start, end), start: atIndex, end: end };
|
|
16771
|
+
}
|
|
16772
|
+
function resolveFuzzyMention(query, lookup) {
|
|
16773
|
+
var queryKey = normalizeMentionKey(query);
|
|
16774
|
+
if (!queryKey) return { uid: null, reason: 'empty-query', candidates: [] };
|
|
16775
|
+
var scoresByUid = {};
|
|
16776
|
+
var labelsByUid = {};
|
|
16777
|
+
var aliases = Object.keys(lookup);
|
|
16778
|
+
for (var i = 0; i < aliases.length; i++) {
|
|
16779
|
+
var alias = aliases[i];
|
|
16780
|
+
var aliasKey = normalizeMentionKey(alias);
|
|
16781
|
+
if (!aliasKey) continue;
|
|
16782
|
+
var score = 0;
|
|
16783
|
+
var aliasTokens = aliasKey.split(' ');
|
|
16784
|
+
if (aliasKey === queryKey) score = 100;
|
|
16785
|
+
else if (aliasTokens.indexOf(queryKey) !== -1) score = 80;
|
|
16786
|
+
else if (aliasKey.indexOf(queryKey) !== -1) score = 60;
|
|
16787
|
+
else if (queryKey.indexOf(aliasKey) !== -1) score = 40;
|
|
16788
|
+
if (score === 0) continue;
|
|
16789
|
+
var entry = lookup[alias];
|
|
16790
|
+
var uid = entry.uid;
|
|
16791
|
+
if (!scoresByUid[uid] || score > scoresByUid[uid]) {
|
|
16792
|
+
scoresByUid[uid] = score;
|
|
16793
|
+
labelsByUid[uid] = entry.label || alias;
|
|
16794
|
+
}
|
|
16795
|
+
}
|
|
16796
|
+
var bestUid = null;
|
|
16797
|
+
var bestScore = 0;
|
|
16798
|
+
var bestCount = 0;
|
|
16799
|
+
var uids = Object.keys(scoresByUid);
|
|
16800
|
+
var candidates = uids.map(function(uid) {
|
|
16801
|
+
return { uid: uid, name: labelsByUid[uid], score: scoresByUid[uid] };
|
|
16802
|
+
}).sort(function(a, b) { return b.score - a.score || String(a.name || '').localeCompare(String(b.name || '')); });
|
|
16803
|
+
for (var j = 0; j < uids.length; j++) {
|
|
16804
|
+
var uidScore = scoresByUid[uids[j]];
|
|
16805
|
+
if (uidScore > bestScore) {
|
|
16806
|
+
bestUid = uids[j];
|
|
16807
|
+
bestScore = uidScore;
|
|
16808
|
+
bestCount = 1;
|
|
16809
|
+
} else if (uidScore === bestScore) {
|
|
16810
|
+
bestCount += 1;
|
|
16811
|
+
}
|
|
16812
|
+
}
|
|
16813
|
+
if (!bestUid) return { uid: null, reason: 'no-match', candidates: candidates.slice(0, 5) };
|
|
16814
|
+
if (bestCount !== 1) return { uid: null, reason: 'ambiguous', candidates: candidates.slice(0, 5) };
|
|
16815
|
+
return { uid: bestUid, label: labelsByUid[bestUid], reason: 'matched', candidates: candidates.slice(0, 5) };
|
|
16816
|
+
}
|
|
16817
|
+
function extractMentions(text) {
|
|
16818
|
+
var lookup = buildMentionLookup();
|
|
16819
|
+
var names = Object.keys(lookup).sort(function(a, b) { return b.length - a.length; });
|
|
16820
|
+
var replacements = [];
|
|
16821
|
+
var debug = [];
|
|
16822
|
+
var occupied = [];
|
|
16823
|
+
function overlaps(start, end) {
|
|
16824
|
+
for (var i = 0; i < occupied.length; i++) {
|
|
16825
|
+
if (start < occupied[i].end && end > occupied[i].start) return true;
|
|
16826
|
+
}
|
|
16827
|
+
return false;
|
|
16828
|
+
}
|
|
16829
|
+
var atIndex = 0;
|
|
16830
|
+
while (atIndex < text.length) {
|
|
16831
|
+
var idx = text.indexOf('@', atIndex);
|
|
16832
|
+
if (idx === -1) break;
|
|
16833
|
+
if (overlaps(idx, idx + 1)) {
|
|
16834
|
+
atIndex = idx + 1;
|
|
16835
|
+
continue;
|
|
16836
|
+
}
|
|
16837
|
+
var matched = null;
|
|
16838
|
+
var debugItem = { raw: null, start: idx, matched: false, reason: 'not-parsed', uid: null, candidates: [] };
|
|
16839
|
+
for (var i = 0; i < names.length; i++) {
|
|
16840
|
+
var mentionText = '@' + names[i];
|
|
16841
|
+
if (text.slice(idx, idx + mentionText.length) === mentionText && hasWordBoundary(text, idx + mentionText.length)) {
|
|
16842
|
+
var entry = lookup[names[i]];
|
|
16843
|
+
matched = { uid: entry.uid, label: entry.label || names[i], start: idx, end: idx + mentionText.length };
|
|
16844
|
+
debugItem = { raw: mentionText, start: idx, matched: true, reason: 'exact', uid: matched.uid, replacement: '@' + matched.label, candidates: [{ uid: matched.uid, name: matched.label, score: 100 }] };
|
|
16845
|
+
break;
|
|
16846
|
+
}
|
|
16847
|
+
}
|
|
16848
|
+
if (!matched) {
|
|
16849
|
+
var query = readMentionQuery(text, idx);
|
|
16850
|
+
if (query) {
|
|
16851
|
+
var fuzzy = resolveFuzzyMention(query.raw, lookup);
|
|
16852
|
+
debugItem = { raw: '@' + query.raw, start: query.start, matched: !!fuzzy.uid, reason: fuzzy.reason, uid: fuzzy.uid, replacement: fuzzy.label ? '@' + fuzzy.label : null, candidates: fuzzy.candidates };
|
|
16853
|
+
if (fuzzy.uid) {
|
|
16854
|
+
matched = { uid: fuzzy.uid, label: fuzzy.label || query.raw, start: query.start, end: query.end };
|
|
16855
|
+
}
|
|
16856
|
+
}
|
|
16857
|
+
}
|
|
16858
|
+
if (matched && !overlaps(matched.start, matched.end)) {
|
|
16859
|
+
replacements.push({ uid: matched.uid, label: matched.label, start: matched.start, end: matched.end });
|
|
16860
|
+
occupied.push({ start: matched.start, end: matched.end });
|
|
16861
|
+
debugItem.matched = true;
|
|
16862
|
+
debugItem.uid = matched.uid;
|
|
16863
|
+
debugItem.replacement = '@' + matched.label;
|
|
16864
|
+
atIndex = matched.end;
|
|
16865
|
+
} else {
|
|
16866
|
+
atIndex = idx + 1;
|
|
16867
|
+
}
|
|
16868
|
+
debug.push(debugItem);
|
|
16869
|
+
}
|
|
16870
|
+
replacements.sort(function(a, b) { return a.start - b.start; });
|
|
16871
|
+
var finalText = '';
|
|
16872
|
+
var mentions = [];
|
|
16873
|
+
var cursor = 0;
|
|
16874
|
+
for (var r = 0; r < replacements.length; r++) {
|
|
16875
|
+
var replacement = '@' + replacements[r].label;
|
|
16876
|
+
finalText += text.slice(cursor, replacements[r].start);
|
|
16877
|
+
var finalStart = finalText.length;
|
|
16878
|
+
finalText += replacement;
|
|
16879
|
+
mentions.push({ uid: replacements[r].uid, start: finalStart, length: replacement.length, type: 0 });
|
|
16880
|
+
cursor = replacements[r].end;
|
|
16881
|
+
}
|
|
16882
|
+
finalText += text.slice(cursor);
|
|
16883
|
+
mentions.sort(function(a, b) { return a.start - b.start; });
|
|
16884
|
+
return { message: finalText, mentions: mentions, debug: debug, lookupSize: names.length };
|
|
16885
|
+
}
|
|
16886
|
+
var plan = extractMentions('${escapedMessage}');
|
|
16887
|
+
var mentions = plan.mentions;
|
|
16888
|
+
var mentionTarget = mentions.length > 0 ? mentions[0].uid : null;
|
|
16889
|
+
var mentionsArg = mentions.length > 0 ? mentions : null;
|
|
16890
|
+
if (${dryRun ? "true" : "false"}) {
|
|
16891
|
+
return {
|
|
16892
|
+
ok: true,
|
|
16893
|
+
dryRun: true,
|
|
16894
|
+
conversationId: '${escapedConversationId}',
|
|
16895
|
+
inputMessage: '${escapedMessage}',
|
|
16896
|
+
message: plan.message,
|
|
16897
|
+
name: name,
|
|
16898
|
+
type: type,
|
|
16899
|
+
mentionTarget: mentionTarget,
|
|
16900
|
+
mentions: mentions,
|
|
16901
|
+
mentionCount: mentions.length,
|
|
16902
|
+
mentionDebug: plan.debug,
|
|
16903
|
+
mentionLookupSize: plan.lookupSize
|
|
16904
|
+
};
|
|
16905
|
+
}
|
|
16906
|
+
await conversation.sendMessage(plan.message, mentionTarget, mentionsArg, [], null, null, null, null, null, null);
|
|
16907
|
+
return { ok: true, name: name, type: type, mentionCount: mentions.length };
|
|
16695
16908
|
} catch(e) {
|
|
16696
16909
|
return { ok: false, reason: e && e.message ? e.message : String(e) };
|
|
16697
16910
|
}
|
|
@@ -25219,6 +25432,7 @@ function parseIm1ReplyArgs(tokens) {
|
|
|
25219
25432
|
const targetTokens = [];
|
|
25220
25433
|
let thread;
|
|
25221
25434
|
let text;
|
|
25435
|
+
let dryRun = false;
|
|
25222
25436
|
while (rest.length > 0) {
|
|
25223
25437
|
const token = rest.shift();
|
|
25224
25438
|
switch (token) {
|
|
@@ -25228,6 +25442,10 @@ function parseIm1ReplyArgs(tokens) {
|
|
|
25228
25442
|
case "--text":
|
|
25229
25443
|
text = requireValue11(rest, token);
|
|
25230
25444
|
break;
|
|
25445
|
+
case "--dryrun":
|
|
25446
|
+
case "--dry-run":
|
|
25447
|
+
dryRun = true;
|
|
25448
|
+
break;
|
|
25231
25449
|
case "--source":
|
|
25232
25450
|
case "--endpoint":
|
|
25233
25451
|
targetTokens.push(token, requireValue11(rest, token));
|
|
@@ -25249,7 +25467,8 @@ function parseIm1ReplyArgs(tokens) {
|
|
|
25249
25467
|
source: target.source,
|
|
25250
25468
|
endpoint: target.endpoint,
|
|
25251
25469
|
thread,
|
|
25252
|
-
text
|
|
25470
|
+
text,
|
|
25471
|
+
dryRun
|
|
25253
25472
|
};
|
|
25254
25473
|
}
|
|
25255
25474
|
function parseTargetOptions(tokens) {
|