openclaw-openagent 1.0.2 → 1.0.4
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/src/app/download-file-tool.js +1 -1
- package/dist/src/app/remote-agent-tool.js +1 -1
- package/dist/src/plugin-ui/assets/openagent-override.js +15 -4
- package/dist/src/plugin-ui/ui-extension-loader/registry-regex.js +73 -50
- package/package.json +2 -2
- package/src/app/download-file-tool.ts +1 -1
- package/src/app/remote-agent-tool.ts +1 -1
- package/src/plugin-ui/assets/openagent-override.js +15 -4
- package/src/plugin-ui/modules/agent-book/panel/inject-ui.js +14 -3
- package/src/plugin-ui/modules/agent-book/panel/theme-adapter.js +86 -0
- package/src/plugin-ui/ui-extension-loader/registry-regex.ts +75 -53
|
@@ -71,7 +71,7 @@ export function createDownloadFileTool() {
|
|
|
71
71
|
return fail('OASN transport not ready');
|
|
72
72
|
}
|
|
73
73
|
// ② Resolve download URL
|
|
74
|
-
const accessBase = rt.config?.accessApiBase;
|
|
74
|
+
const accessBase = rt.config?.accessApiBase || rt.config?.apiBase;
|
|
75
75
|
const downloadUrl = resolveOasnAccessUrl(accessBase, contentUrl);
|
|
76
76
|
logger.info(`[download-tool] Downloading artifact: url=${downloadUrl} saveTo=${savePath}`);
|
|
77
77
|
// ③ Download
|
|
@@ -290,7 +290,7 @@ export function createCallRemoteAgentTool() {
|
|
|
290
290
|
// 在 visible_result.webui_continuation 里返回可继续交互的入口。
|
|
291
291
|
if (result.webuiContinuation?.launchUrl) {
|
|
292
292
|
const rawLink = result.webuiContinuation.launchUrl;
|
|
293
|
-
const accessBase = rt.config?.accessApiBase;
|
|
293
|
+
const accessBase = rt.config?.accessApiBase || rt.config?.apiBase;
|
|
294
294
|
const link = resolveOasnAccessUrl(accessBase, rawLink);
|
|
295
295
|
const label = result.webuiContinuation.displayName || 'Open WebUI';
|
|
296
296
|
content = content.trim()
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* OpenAgent UI Override — Auto-generated, do not edit directly!
|
|
3
3
|
*
|
|
4
4
|
* Source: src/plugin-ui/modules/
|
|
5
|
-
* Built: 2026-06-
|
|
5
|
+
* Built: 2026-06-25T07:10:51.968Z
|
|
6
6
|
*
|
|
7
7
|
* To modify, edit the source modules and run:
|
|
8
8
|
* npm run build:override
|
|
@@ -2891,7 +2891,16 @@ liveTextarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
|
2891
2891
|
// tryInject() 只做 DOM 注入(@ 按钮 + CSS class),不绑定任何事件。
|
|
2892
2892
|
|
|
2893
2893
|
// ── textarea 选择器(全局复用)──
|
|
2894
|
-
|
|
2894
|
+
// 多策略回退:v3 "Message..." / v4 "发消息..." / 结构化选择器
|
|
2895
|
+
const _CL_TEXTAREA_SELECTOR = [
|
|
2896
|
+
'textarea[placeholder*="发消息"]',
|
|
2897
|
+
'textarea[placeholder*="Message"]',
|
|
2898
|
+
'textarea[placeholder*="Enter to send"]',
|
|
2899
|
+
'.agent-chat__composer-combobox textarea',
|
|
2900
|
+
'.chat-composer textarea',
|
|
2901
|
+
'.chat-input textarea',
|
|
2902
|
+
'[class*="composer"] textarea:not([placeholder*="Search"])',
|
|
2903
|
+
].join(', ');
|
|
2895
2904
|
|
|
2896
2905
|
function _getTextarea() {
|
|
2897
2906
|
return document.querySelector(_CL_TEXTAREA_SELECTOR);
|
|
@@ -2929,7 +2938,8 @@ function _isLikelyNativeSendButton(target, textarea) {
|
|
|
2929
2938
|
if (!button || !textarea) return false;
|
|
2930
2939
|
if (button.classList && button.classList.contains('openagent-at-btn')) return false;
|
|
2931
2940
|
|
|
2932
|
-
const inputContainer = textarea.closest('.
|
|
2941
|
+
const inputContainer = textarea.closest('.agent-chat__composer-combobox')
|
|
2942
|
+
|| textarea.closest('.chat-input')
|
|
2933
2943
|
|| textarea.closest('[class*="chat-composer"]')
|
|
2934
2944
|
|| textarea.closest('[class*="chat"]')
|
|
2935
2945
|
|| textarea.parentElement;
|
|
@@ -3086,7 +3096,8 @@ function tryInject() {
|
|
|
3086
3096
|
}
|
|
3087
3097
|
|
|
3088
3098
|
// ── 给输入区域加 position: relative 包裹层 ──
|
|
3089
|
-
const inputContainer = textarea.closest('.
|
|
3099
|
+
const inputContainer = textarea.closest('.agent-chat__composer-combobox')
|
|
3100
|
+
|| textarea.closest('.chat-input')
|
|
3090
3101
|
|| textarea.closest('[class*="chat-composer"]')
|
|
3091
3102
|
|| textarea.closest('[class*="chat"]')
|
|
3092
3103
|
|| textareaParent?.parentElement
|
|
@@ -264,47 +264,61 @@ const toolcardRender = {
|
|
|
264
264
|
const toolMessageAnchor = 'toolmsg:${';
|
|
265
265
|
let patchedToolMessageWrapper = false;
|
|
266
266
|
if (content.includes(toolMessageAnchor)) {
|
|
267
|
+
let toolMessageOk = true;
|
|
267
268
|
const toolMessageFn = findFunctionByAnchor(content, toolMessageAnchor, 8000);
|
|
268
269
|
if (!toolMessageFn) {
|
|
269
270
|
logger.warn('[ui-ext:regex] toolcard-render: tool message wrapper function not found');
|
|
270
|
-
|
|
271
|
+
toolMessageOk = false;
|
|
271
272
|
}
|
|
272
|
-
if (!toolMessageFn.body.includes('chat-tool-msg-collapse--manual')
|
|
273
|
-
|| !toolMessageFn.body.includes('chat-tool-msg-body')) {
|
|
273
|
+
if (toolMessageOk && (!toolMessageFn.body.includes('chat-tool-msg-collapse--manual')
|
|
274
|
+
|| !toolMessageFn.body.includes('chat-tool-msg-body'))) {
|
|
274
275
|
logger.warn('[ui-ext:regex] toolcard-render: tool message wrapper shape mismatch');
|
|
275
|
-
|
|
276
|
+
toolMessageOk = false;
|
|
276
277
|
}
|
|
277
|
-
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
const cardsVar = singleCardMatch[2];
|
|
289
|
-
const mediaVar = singleCardMatch[4];
|
|
290
|
-
const chatBubbleClassMatch = toolMessageFn.body.match(/[,;]([a-zA-Z_$]\w*)=\[`chat-bubble`,/);
|
|
291
|
-
if (!chatBubbleClassMatch) {
|
|
292
|
-
logger.warn('[ui-ext:regex] toolcard-render: tool message chat-bubble class var not found');
|
|
293
|
-
return false;
|
|
278
|
+
let toolMessageHtmlVar = '';
|
|
279
|
+
if (toolMessageOk) {
|
|
280
|
+
const toolMessageReturnTagMatch = toolMessageFn.body.match(/return\s+([a-zA-Z_$]\w*)\s*`/);
|
|
281
|
+
if (!toolMessageReturnTagMatch) {
|
|
282
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message Lit html tag not found');
|
|
283
|
+
toolMessageOk = false;
|
|
284
|
+
}
|
|
285
|
+
else {
|
|
286
|
+
toolMessageHtmlVar = toolMessageReturnTagMatch[1];
|
|
287
|
+
}
|
|
294
288
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
289
|
+
if (toolMessageOk) {
|
|
290
|
+
const singleCardMatch = toolMessageFn.body.match(/(?:let\s+|,)([a-zA-Z_$]\w*)=([a-zA-Z_$]\w*)\.length===1\?\2\[0\]:null,\w+=\1&&!([a-zA-Z_$]\w*)&&!([a-zA-Z_$]\w*)\?/);
|
|
291
|
+
if (!singleCardMatch) {
|
|
292
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message single-card guard not found');
|
|
293
|
+
toolMessageOk = false;
|
|
294
|
+
}
|
|
295
|
+
if (toolMessageOk) {
|
|
296
|
+
const cardsVar = singleCardMatch[2];
|
|
297
|
+
const mediaVar = singleCardMatch[4];
|
|
298
|
+
const chatBubbleClassMatch = toolMessageFn.body.match(/[,;]([a-zA-Z_$]\w*)=\[`chat-bubble`,/);
|
|
299
|
+
if (!chatBubbleClassMatch) {
|
|
300
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message chat-bubble class var not found');
|
|
301
|
+
toolMessageOk = false;
|
|
302
|
+
}
|
|
303
|
+
if (toolMessageOk) {
|
|
304
|
+
const chatBubbleClassVar = chatBubbleClassMatch[1];
|
|
305
|
+
const toolMessageParams = toolMessageFn.params.split(',').map((s) => s.trim());
|
|
306
|
+
const toolMessageSidebarArg = toolMessageParams[3] || 'undefined';
|
|
307
|
+
const toolMessageReturnIdx = toolMessageFn.body.indexOf(`return ${toolMessageHtmlVar}\``);
|
|
308
|
+
if (toolMessageReturnIdx < 0) {
|
|
309
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message return anchor not found');
|
|
310
|
+
toolMessageOk = false;
|
|
311
|
+
}
|
|
312
|
+
if (toolMessageOk) {
|
|
313
|
+
const toolMessageHook = `${marker}let __openagentToolMsgCard=null;if(!${mediaVar}&&window.__openagentRenderToolCard){for(let __openagentI=${cardsVar}.length-1;__openagentI>=0&&!__openagentToolMsgCard;__openagentI--){let __openagentCandidate=${cardsVar}[__openagentI];if(__openagentCandidate&&(__openagentCandidate.outputText||__openagentCandidate.text))__openagentToolMsgCard=window.__openagentRenderToolCard(__openagentCandidate,${toolMessageSidebarArg})}for(let __openagentI=0;__openagentI<${cardsVar}.length&&!__openagentToolMsgCard;__openagentI++){__openagentToolMsgCard=window.__openagentRenderToolCard(${cardsVar}[__openagentI],${toolMessageSidebarArg})}}if(__openagentToolMsgCard)return ${toolMessageHtmlVar}\`<div class="\${${chatBubbleClassVar}}">\${__openagentToolMsgCard}</div>\`;`;
|
|
314
|
+
const toolMessageInsertAt = toolMessageFn.bodyStart + toolMessageReturnIdx;
|
|
315
|
+
content = content.substring(0, toolMessageInsertAt) + toolMessageHook + content.substring(toolMessageInsertAt);
|
|
316
|
+
patchedToolMessageWrapper = true;
|
|
317
|
+
logger.info(`[ui-ext:regex] toolcard-render: patched tool message wrapper ${toolMessageFn.funcName}(${toolMessageFn.params.substring(0, 20)}) html=${toolMessageHtmlVar}`);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
302
321
|
}
|
|
303
|
-
const toolMessageHook = `${marker}let __openagentToolMsgCard=null;if(!${mediaVar}&&window.__openagentRenderToolCard){for(let __openagentI=${cardsVar}.length-1;__openagentI>=0&&!__openagentToolMsgCard;__openagentI--){let __openagentCandidate=${cardsVar}[__openagentI];if(__openagentCandidate&&(__openagentCandidate.outputText||__openagentCandidate.text))__openagentToolMsgCard=window.__openagentRenderToolCard(__openagentCandidate,${toolMessageSidebarArg})}for(let __openagentI=0;__openagentI<${cardsVar}.length&&!__openagentToolMsgCard;__openagentI++){__openagentToolMsgCard=window.__openagentRenderToolCard(${cardsVar}[__openagentI],${toolMessageSidebarArg})}}if(__openagentToolMsgCard)return ${toolMessageHtmlVar}\`<div class="\${${chatBubbleClassVar}}">\${__openagentToolMsgCard}</div>\`;`;
|
|
304
|
-
const toolMessageInsertAt = toolMessageFn.bodyStart + toolMessageReturnIdx;
|
|
305
|
-
content = content.substring(0, toolMessageInsertAt) + toolMessageHook + content.substring(toolMessageInsertAt);
|
|
306
|
-
patchedToolMessageWrapper = true;
|
|
307
|
-
logger.info(`[ui-ext:regex] toolcard-render: patched tool message wrapper ${toolMessageFn.funcName}(${toolMessageFn.params.substring(0, 20)}) html=${toolMessageHtmlVar}`);
|
|
308
322
|
}
|
|
309
323
|
writeFileSync(bundlePath, content, 'utf-8');
|
|
310
324
|
logger.info(`[ui-ext:regex] toolcard-render: patched ${funcName}(${params.substring(0, 20)}) html=${litHtmlVar}${patchedWrapper ? ' + wrapper' : ''}${patchedToolMessageWrapper ? ' + tool-message' : ''}`);
|
|
@@ -411,7 +425,7 @@ const toolcallidPropagate = {
|
|
|
411
425
|
logger.debug(`[ui-ext:regex] toolcallid-propagate: mVar=${mVar} cards=${cardsVar} callLoop=${callLoopVar} resultLoop=${resultLoopVar}`);
|
|
412
426
|
// 计算注入内容
|
|
413
427
|
const marker = makeMarker(this.id);
|
|
414
|
-
const tcidCapture = `${marker}var __tcid=(typeof ${
|
|
428
|
+
const tcidCapture = `${marker}var __tcid=(typeof ${msgParam}.toolCallId==='string'&&${msgParam}.toolCallId)||(typeof ${msgParam}.tool_call_id==='string'&&${msgParam}.tool_call_id)||'';`;
|
|
415
429
|
const inlinePatchCall = callLoopVar
|
|
416
430
|
? `,toolCallId:__tcid||${callLoopVar}.id||${callLoopVar}.toolCallId||${callLoopVar}.tool_call_id||''`
|
|
417
431
|
: `,toolCallId:__tcid`;
|
|
@@ -423,16 +437,16 @@ const toolcallidPropagate = {
|
|
|
423
437
|
const arrInitPattern = `,${cardsVar}=[];`;
|
|
424
438
|
let arrInitIdx = funcBody.indexOf(arrInitPattern);
|
|
425
439
|
if (arrInitIdx < 0) {
|
|
426
|
-
// v4.11+: 可能是 ,i=[]
|
|
440
|
+
// v4.11+: 可能是 ,i=[](后接逗号,如 a=[],o=...),不能直接插 var
|
|
427
441
|
const altPattern = `,${cardsVar}=[]`;
|
|
428
442
|
arrInitIdx = funcBody.indexOf(altPattern);
|
|
429
443
|
if (arrInitIdx < 0) {
|
|
430
444
|
logger.warn('[ui-ext:regex] toolcallid-propagate: cards init not found');
|
|
431
445
|
return false;
|
|
432
446
|
}
|
|
433
|
-
//
|
|
434
|
-
|
|
435
|
-
|
|
447
|
+
// altPattern 后面是逗号(逗号表达式),var 声明无法插入此处
|
|
448
|
+
// 改为插入到函数体开头,利用 var 提升特性
|
|
449
|
+
arrInitIdx = 0;
|
|
436
450
|
}
|
|
437
451
|
else {
|
|
438
452
|
arrInitIdx += arrInitPattern.length;
|
|
@@ -630,7 +644,7 @@ const remoteAgentMessageShortCircuit = {
|
|
|
630
644
|
// ── Extension 7: mention-hooks ───────────────────────────────────────────
|
|
631
645
|
const mentionHooks = {
|
|
632
646
|
id: 'mention-hooks',
|
|
633
|
-
version:
|
|
647
|
+
version: 3,
|
|
634
648
|
sharedFile: 'index-bundle',
|
|
635
649
|
apply(controlUiDir) {
|
|
636
650
|
const bundlePath = resolveBundlePath(controlUiDir);
|
|
@@ -643,9 +657,9 @@ const mentionHooks = {
|
|
|
643
657
|
if (!backupFile(bundlePath))
|
|
644
658
|
return false;
|
|
645
659
|
// 注入点 A: handleKeyDown
|
|
646
|
-
//
|
|
647
|
-
//
|
|
648
|
-
const keydownRe = /;return\}
|
|
660
|
+
// 锚定 ;return}if(X.key===`Enter`&&!X.shiftKey){
|
|
661
|
+
// 不再依赖内层 isComposing:2026.6.10 已把 isComposing 检查拆到独立 handler
|
|
662
|
+
const keydownRe = /;return\}if\(([a-zA-Z_$][a-zA-Z0-9_$]*)\.key===`Enter`&&!\1\.shiftKey\)\{/;
|
|
649
663
|
const keydownMatch = content.match(keydownRe);
|
|
650
664
|
if (!keydownMatch) {
|
|
651
665
|
logger.warn('[ui-ext:regex] mention-hooks: keydown anchor not found');
|
|
@@ -656,31 +670,40 @@ const mentionHooks = {
|
|
|
656
670
|
const markerA = makeMarker(this.id);
|
|
657
671
|
const hookA = `${markerA}if(window.__clMention?.onKeyDown(${eventParam}))return;`;
|
|
658
672
|
content = content.substring(0, keydownInsertIdx) + hookA + content.substring(keydownInsertIdx);
|
|
659
|
-
// 注入点 B: handleInput —
|
|
660
|
-
// Shape A (old):
|
|
661
|
-
// Shape B (4.11
|
|
673
|
+
// 注入点 B: handleInput — 支持三种形态
|
|
674
|
+
// Shape A (old): .onDraftChange(target.value)}}
|
|
675
|
+
// Shape B (4.11~4.x): .onDraftChange(target.value) (arrow function 内)
|
|
676
|
+
// Shape C (2026.6.x): be=t=>{let n=t.target;pL(e,n.value)} — 引入 pL helper,
|
|
677
|
+
// arrow body 末尾不再出现 onDraftChange 字面
|
|
662
678
|
const inputReA = /\.onDraftChange\(([a-zA-Z_$][a-zA-Z0-9_$]*)\.value\)\}\}/;
|
|
663
679
|
const inputReB = /\.onDraftChange\(([a-zA-Z_$][a-zA-Z0-9_$]*)\.value\)/;
|
|
680
|
+
const inputReC = /let ([a-zA-Z_$][a-zA-Z0-9_$]*)=[a-zA-Z_$][a-zA-Z0-9_$]*\.target;[a-zA-Z_$][a-zA-Z0-9_$]*\([a-zA-Z_$][a-zA-Z0-9_$]*,\1\.value\)\}/;
|
|
664
681
|
let inputMatch = content.match(inputReA);
|
|
665
682
|
let inputShape = 'A';
|
|
683
|
+
if (!inputMatch) {
|
|
684
|
+
inputMatch = content.match(inputReC);
|
|
685
|
+
inputShape = 'C';
|
|
686
|
+
}
|
|
666
687
|
if (!inputMatch) {
|
|
667
688
|
inputMatch = content.match(inputReB);
|
|
668
689
|
inputShape = 'B';
|
|
669
690
|
}
|
|
670
691
|
if (!inputMatch) {
|
|
671
|
-
logger.warn('[ui-ext:regex] mention-hooks: input anchor not found (
|
|
692
|
+
logger.warn('[ui-ext:regex] mention-hooks: input anchor not found (Shape A/B/C all missed)');
|
|
672
693
|
return false;
|
|
673
694
|
}
|
|
674
695
|
const targetVar = inputMatch[1];
|
|
675
696
|
const inputAnchorIdx = content.indexOf(inputMatch[0]);
|
|
676
|
-
//
|
|
697
|
+
// Shape A: }} 之前;Shape C: 末尾 } 之前;Shape B: ) 之后
|
|
677
698
|
const draftCallEnd = inputShape === 'A'
|
|
678
|
-
? inputAnchorIdx + inputMatch[0].length - 2
|
|
679
|
-
:
|
|
699
|
+
? inputAnchorIdx + inputMatch[0].length - 2
|
|
700
|
+
: inputShape === 'C'
|
|
701
|
+
? inputAnchorIdx + inputMatch[0].length - 1
|
|
702
|
+
: inputAnchorIdx + inputMatch[0].length;
|
|
680
703
|
const hookB = `;window.__clMention?.onInput?.(${targetVar})`;
|
|
681
704
|
content = content.substring(0, draftCallEnd) + hookB + content.substring(draftCallEnd);
|
|
682
705
|
writeFileSync(bundlePath, content, 'utf-8');
|
|
683
|
-
logger.info(`[ui-ext:regex] mention-hooks: injected (event=${eventParam}, target=${targetVar})`);
|
|
706
|
+
logger.info(`[ui-ext:regex] mention-hooks: injected (shape=${inputShape}, event=${eventParam}, target=${targetVar})`);
|
|
684
707
|
return true;
|
|
685
708
|
},
|
|
686
709
|
revert(controlUiDir) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openclaw-openagent",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenAgent channel plugin for OpenClaw",
|
|
6
6
|
"license": "MIT",
|
|
@@ -75,7 +75,7 @@
|
|
|
75
75
|
"@types/node": "^25.5.0",
|
|
76
76
|
"@types/sql.js": "^1.4.11",
|
|
77
77
|
"@types/yazl": "^3.3.1",
|
|
78
|
-
"openclaw": "^2026.6.
|
|
78
|
+
"openclaw": "^2026.6.10",
|
|
79
79
|
"tsx": "^4.21.0",
|
|
80
80
|
"typescript": "^6.0.2"
|
|
81
81
|
}
|
|
@@ -93,7 +93,7 @@ export function createDownloadFileTool(): ToolDescriptor {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
// ② Resolve download URL
|
|
96
|
-
const accessBase = rt.config?.accessApiBase;
|
|
96
|
+
const accessBase = rt.config?.accessApiBase || rt.config?.apiBase;
|
|
97
97
|
const downloadUrl = resolveOasnAccessUrl(accessBase, contentUrl);
|
|
98
98
|
|
|
99
99
|
logger.info(
|
|
@@ -349,7 +349,7 @@ export function createCallRemoteAgentTool(): ToolDescriptor {
|
|
|
349
349
|
// 在 visible_result.webui_continuation 里返回可继续交互的入口。
|
|
350
350
|
if (result.webuiContinuation?.launchUrl) {
|
|
351
351
|
const rawLink = result.webuiContinuation.launchUrl;
|
|
352
|
-
const accessBase = rt.config?.accessApiBase;
|
|
352
|
+
const accessBase = rt.config?.accessApiBase || rt.config?.apiBase;
|
|
353
353
|
const link = resolveOasnAccessUrl(accessBase, rawLink);
|
|
354
354
|
const label = result.webuiContinuation.displayName || 'Open WebUI';
|
|
355
355
|
content = content.trim()
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* OpenAgent UI Override — Auto-generated, do not edit directly!
|
|
3
3
|
*
|
|
4
4
|
* Source: src/plugin-ui/modules/
|
|
5
|
-
* Built: 2026-06-
|
|
5
|
+
* Built: 2026-06-25T07:10:51.968Z
|
|
6
6
|
*
|
|
7
7
|
* To modify, edit the source modules and run:
|
|
8
8
|
* npm run build:override
|
|
@@ -2891,7 +2891,16 @@ liveTextarea.dispatchEvent(new Event('change', { bubbles: true }));
|
|
|
2891
2891
|
// tryInject() 只做 DOM 注入(@ 按钮 + CSS class),不绑定任何事件。
|
|
2892
2892
|
|
|
2893
2893
|
// ── textarea 选择器(全局复用)──
|
|
2894
|
-
|
|
2894
|
+
// 多策略回退:v3 "Message..." / v4 "发消息..." / 结构化选择器
|
|
2895
|
+
const _CL_TEXTAREA_SELECTOR = [
|
|
2896
|
+
'textarea[placeholder*="发消息"]',
|
|
2897
|
+
'textarea[placeholder*="Message"]',
|
|
2898
|
+
'textarea[placeholder*="Enter to send"]',
|
|
2899
|
+
'.agent-chat__composer-combobox textarea',
|
|
2900
|
+
'.chat-composer textarea',
|
|
2901
|
+
'.chat-input textarea',
|
|
2902
|
+
'[class*="composer"] textarea:not([placeholder*="Search"])',
|
|
2903
|
+
].join(', ');
|
|
2895
2904
|
|
|
2896
2905
|
function _getTextarea() {
|
|
2897
2906
|
return document.querySelector(_CL_TEXTAREA_SELECTOR);
|
|
@@ -2929,7 +2938,8 @@ function _isLikelyNativeSendButton(target, textarea) {
|
|
|
2929
2938
|
if (!button || !textarea) return false;
|
|
2930
2939
|
if (button.classList && button.classList.contains('openagent-at-btn')) return false;
|
|
2931
2940
|
|
|
2932
|
-
const inputContainer = textarea.closest('.
|
|
2941
|
+
const inputContainer = textarea.closest('.agent-chat__composer-combobox')
|
|
2942
|
+
|| textarea.closest('.chat-input')
|
|
2933
2943
|
|| textarea.closest('[class*="chat-composer"]')
|
|
2934
2944
|
|| textarea.closest('[class*="chat"]')
|
|
2935
2945
|
|| textarea.parentElement;
|
|
@@ -3086,7 +3096,8 @@ function tryInject() {
|
|
|
3086
3096
|
}
|
|
3087
3097
|
|
|
3088
3098
|
// ── 给输入区域加 position: relative 包裹层 ──
|
|
3089
|
-
const inputContainer = textarea.closest('.
|
|
3099
|
+
const inputContainer = textarea.closest('.agent-chat__composer-combobox')
|
|
3100
|
+
|| textarea.closest('.chat-input')
|
|
3090
3101
|
|| textarea.closest('[class*="chat-composer"]')
|
|
3091
3102
|
|| textarea.closest('[class*="chat"]')
|
|
3092
3103
|
|| textareaParent?.parentElement
|
|
@@ -10,7 +10,16 @@
|
|
|
10
10
|
// tryInject() 只做 DOM 注入(@ 按钮 + CSS class),不绑定任何事件。
|
|
11
11
|
|
|
12
12
|
// ── textarea 选择器(全局复用)──
|
|
13
|
-
|
|
13
|
+
// 多策略回退:v3 "Message..." / v4 "发消息..." / 结构化选择器
|
|
14
|
+
const _CL_TEXTAREA_SELECTOR = [
|
|
15
|
+
'textarea[placeholder*="发消息"]',
|
|
16
|
+
'textarea[placeholder*="Message"]',
|
|
17
|
+
'textarea[placeholder*="Enter to send"]',
|
|
18
|
+
'.agent-chat__composer-combobox textarea',
|
|
19
|
+
'.chat-composer textarea',
|
|
20
|
+
'.chat-input textarea',
|
|
21
|
+
'[class*="composer"] textarea:not([placeholder*="Search"])',
|
|
22
|
+
].join(', ');
|
|
14
23
|
|
|
15
24
|
function _getTextarea() {
|
|
16
25
|
return document.querySelector(_CL_TEXTAREA_SELECTOR);
|
|
@@ -48,7 +57,8 @@ function _isLikelyNativeSendButton(target, textarea) {
|
|
|
48
57
|
if (!button || !textarea) return false;
|
|
49
58
|
if (button.classList && button.classList.contains('openagent-at-btn')) return false;
|
|
50
59
|
|
|
51
|
-
const inputContainer = textarea.closest('.
|
|
60
|
+
const inputContainer = textarea.closest('.agent-chat__composer-combobox')
|
|
61
|
+
|| textarea.closest('.chat-input')
|
|
52
62
|
|| textarea.closest('[class*="chat-composer"]')
|
|
53
63
|
|| textarea.closest('[class*="chat"]')
|
|
54
64
|
|| textarea.parentElement;
|
|
@@ -205,7 +215,8 @@ function tryInject() {
|
|
|
205
215
|
}
|
|
206
216
|
|
|
207
217
|
// ── 给输入区域加 position: relative 包裹层 ──
|
|
208
|
-
const inputContainer = textarea.closest('.
|
|
218
|
+
const inputContainer = textarea.closest('.agent-chat__composer-combobox')
|
|
219
|
+
|| textarea.closest('.chat-input')
|
|
209
220
|
|| textarea.closest('[class*="chat-composer"]')
|
|
210
221
|
|| textarea.closest('[class*="chat"]')
|
|
211
222
|
|| textareaParent?.parentElement
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// ── OpenAgent Theme Adapter ──
|
|
2
|
+
//
|
|
3
|
+
// 运行时检测 OpenClaw Control UI 主题系统(v4.x vscode tokens / v5.x glassmorphism),
|
|
4
|
+
// 注入 --oa-* CSS 变量供 styles.js 中的 var() fallback 消费。
|
|
5
|
+
//
|
|
6
|
+
// 必须早于 styles.js 加载(由 build.cjs MANIFEST 顺序保证)。
|
|
7
|
+
|
|
8
|
+
(function _clInitThemeAdapter() {
|
|
9
|
+
if (window.__openagentThemeAdapterInstalled) return;
|
|
10
|
+
window.__openagentThemeAdapterInstalled = true;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* 检测当前 OC 主题系统类型。
|
|
14
|
+
* @returns {{ hasGlass: boolean, hasVscode: boolean, isDark: boolean }}
|
|
15
|
+
*/
|
|
16
|
+
function detectThemeSystem() {
|
|
17
|
+
var cs = getComputedStyle(document.documentElement);
|
|
18
|
+
var hasGlass = !!(cs.getPropertyValue('--glass-surface').trim());
|
|
19
|
+
var hasKn = !!(cs.getPropertyValue('--kn-bg-primary').trim());
|
|
20
|
+
var hasVscode = !!(cs.getPropertyValue('--vscode-editor-background').trim());
|
|
21
|
+
|
|
22
|
+
// 多策略暗色检测:v4 data-theme-mode / v5 data-theme / prefers-color-scheme
|
|
23
|
+
var themeMode = document.documentElement.getAttribute('data-theme-mode') // v4.x
|
|
24
|
+
|| document.documentElement.getAttribute('data-theme') // v5.x
|
|
25
|
+
|| '';
|
|
26
|
+
var isDark = themeMode.indexOf('dark') >= 0
|
|
27
|
+
|| window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
28
|
+
|
|
29
|
+
return {
|
|
30
|
+
hasGlass: hasGlass || hasKn,
|
|
31
|
+
hasVscode: hasVscode,
|
|
32
|
+
isDark: isDark
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 注入 --oa-* CSS 变量到 :root。
|
|
38
|
+
* styles.js 中的 var(--oa-xxx, fallback) 会优先取这些值。
|
|
39
|
+
*/
|
|
40
|
+
function setupThemeVariables() {
|
|
41
|
+
var system = detectThemeSystem();
|
|
42
|
+
var root = document.documentElement;
|
|
43
|
+
|
|
44
|
+
if (system.hasGlass) {
|
|
45
|
+
// v5.x Glassmorphism: 使用 --glass-* / --kn-* token 族
|
|
46
|
+
root.style.setProperty('--oa-panel-bg', 'var(--glass-surface, var(--card))');
|
|
47
|
+
root.style.setProperty('--oa-panel-text', 'var(--kn-text-primary, var(--text, #e0e0e0))');
|
|
48
|
+
root.style.setProperty('--oa-card-bg', 'var(--glass-card, var(--card, #f5f5f5))');
|
|
49
|
+
root.style.setProperty('--oa-card-hover-bg', 'var(--glass-card-hover, var(--card-hover))');
|
|
50
|
+
root.style.setProperty('--oa-border', 'var(--glass-border, var(--border, #e5e5e5))');
|
|
51
|
+
root.style.setProperty('--oa-shadow-color', 'rgba(0, 0, 0, 0.08)');
|
|
52
|
+
root.style.setProperty('--oa-divider', 'var(--glass-divider, var(--border, #eee))');
|
|
53
|
+
root.style.setProperty('--oa-muted-text', 'var(--kn-text-secondary, var(--text-secondary, #999))');
|
|
54
|
+
} else if (system.hasVscode) {
|
|
55
|
+
// v4.x VSCode tokens: 使用 --vscode-* 变量
|
|
56
|
+
root.style.setProperty('--oa-panel-bg', 'var(--vscode-editor-background, #fff)');
|
|
57
|
+
root.style.setProperty('--oa-panel-text', 'var(--vscode-editor-foreground, #2F2F33)');
|
|
58
|
+
root.style.setProperty('--oa-card-bg', 'var(--vscode-sideBar-background, #f5f5f5)');
|
|
59
|
+
root.style.setProperty('--oa-card-hover-bg', 'var(--vscode-list-hoverBackground, #f0f0f0)');
|
|
60
|
+
root.style.setProperty('--oa-border', 'var(--vscode-panel-border, #e5e5e5)');
|
|
61
|
+
root.style.setProperty('--oa-shadow-color', 'rgba(0, 0, 0, 0.10)');
|
|
62
|
+
root.style.setProperty('--oa-divider', 'var(--vscode-sideBar-border, #eee)');
|
|
63
|
+
root.style.setProperty('--oa-muted-text', 'var(--vscode-descriptionForeground, #999)');
|
|
64
|
+
}
|
|
65
|
+
// 无特征 → 不注入变量,styles.js 中的 var() 会 fallback 到硬编码值
|
|
66
|
+
|
|
67
|
+
// 注入暗色 class 标记供 styles.js 选择器使用
|
|
68
|
+
if (system.isDark) {
|
|
69
|
+
root.style.setProperty('--oa-is-dark', '1');
|
|
70
|
+
} else {
|
|
71
|
+
root.style.setProperty('--oa-is-dark', '0');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 立即执行 + 监听主题变更(v5.x 可能运行时切换主题)
|
|
76
|
+
setupThemeVariables();
|
|
77
|
+
|
|
78
|
+
// 监听 data-theme / data-theme-mode 属性变更
|
|
79
|
+
var themeObserver = new MutationObserver(function () {
|
|
80
|
+
setupThemeVariables();
|
|
81
|
+
});
|
|
82
|
+
themeObserver.observe(document.documentElement, {
|
|
83
|
+
attributes: true,
|
|
84
|
+
attributeFilter: ['data-theme', 'data-theme-mode', 'class']
|
|
85
|
+
});
|
|
86
|
+
})();
|
|
@@ -288,52 +288,64 @@ const toolcardRender: UIExtension = {
|
|
|
288
288
|
const toolMessageAnchor = 'toolmsg:${';
|
|
289
289
|
let patchedToolMessageWrapper = false;
|
|
290
290
|
if (content.includes(toolMessageAnchor)) {
|
|
291
|
+
let toolMessageOk = true;
|
|
291
292
|
const toolMessageFn = findFunctionByAnchor(content, toolMessageAnchor, 8000);
|
|
292
293
|
if (!toolMessageFn) {
|
|
293
294
|
logger.warn('[ui-ext:regex] toolcard-render: tool message wrapper function not found');
|
|
294
|
-
|
|
295
|
+
toolMessageOk = false;
|
|
295
296
|
}
|
|
296
297
|
|
|
297
|
-
if (!toolMessageFn
|
|
298
|
-
|| !toolMessageFn
|
|
298
|
+
if (toolMessageOk && (!toolMessageFn!.body.includes('chat-tool-msg-collapse--manual')
|
|
299
|
+
|| !toolMessageFn!.body.includes('chat-tool-msg-body'))) {
|
|
299
300
|
logger.warn('[ui-ext:regex] toolcard-render: tool message wrapper shape mismatch');
|
|
300
|
-
|
|
301
|
+
toolMessageOk = false;
|
|
301
302
|
}
|
|
302
303
|
|
|
303
|
-
|
|
304
|
-
if (
|
|
305
|
-
|
|
306
|
-
|
|
304
|
+
let toolMessageHtmlVar = '';
|
|
305
|
+
if (toolMessageOk) {
|
|
306
|
+
const toolMessageReturnTagMatch = toolMessageFn!.body.match(/return\s+([a-zA-Z_$]\w*)\s*`/);
|
|
307
|
+
if (!toolMessageReturnTagMatch) {
|
|
308
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message Lit html tag not found');
|
|
309
|
+
toolMessageOk = false;
|
|
310
|
+
} else {
|
|
311
|
+
toolMessageHtmlVar = toolMessageReturnTagMatch[1];
|
|
312
|
+
}
|
|
307
313
|
}
|
|
308
|
-
const toolMessageHtmlVar = toolMessageReturnTagMatch[1];
|
|
309
314
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
315
|
+
if (toolMessageOk) {
|
|
316
|
+
const singleCardMatch = toolMessageFn!.body.match(/(?:let\s+|,)([a-zA-Z_$]\w*)=([a-zA-Z_$]\w*)\.length===1\?\2\[0\]:null,\w+=\1&&!([a-zA-Z_$]\w*)&&!([a-zA-Z_$]\w*)\?/);
|
|
317
|
+
if (!singleCardMatch) {
|
|
318
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message single-card guard not found');
|
|
319
|
+
toolMessageOk = false;
|
|
320
|
+
}
|
|
321
|
+
if (toolMessageOk) {
|
|
322
|
+
const cardsVar = singleCardMatch![2];
|
|
323
|
+
const mediaVar = singleCardMatch![4];
|
|
324
|
+
const chatBubbleClassMatch = toolMessageFn!.body.match(/[,;]([a-zA-Z_$]\w*)=\[`chat-bubble`,/);
|
|
325
|
+
if (!chatBubbleClassMatch) {
|
|
326
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message chat-bubble class var not found');
|
|
327
|
+
toolMessageOk = false;
|
|
328
|
+
}
|
|
329
|
+
if (toolMessageOk) {
|
|
330
|
+
const chatBubbleClassVar = chatBubbleClassMatch![1];
|
|
331
|
+
const toolMessageParams = toolMessageFn!.params.split(',').map((s: string) => s.trim());
|
|
332
|
+
const toolMessageSidebarArg = toolMessageParams[3] || 'undefined';
|
|
333
|
+
const toolMessageReturnIdx = toolMessageFn!.body.indexOf(`return ${toolMessageHtmlVar}\``);
|
|
334
|
+
if (toolMessageReturnIdx < 0) {
|
|
335
|
+
logger.warn('[ui-ext:regex] toolcard-render: tool message return anchor not found');
|
|
336
|
+
toolMessageOk = false;
|
|
337
|
+
}
|
|
338
|
+
if (toolMessageOk) {
|
|
339
|
+
const toolMessageHook =
|
|
340
|
+
`${marker}let __openagentToolMsgCard=null;if(!${mediaVar}&&window.__openagentRenderToolCard){for(let __openagentI=${cardsVar}.length-1;__openagentI>=0&&!__openagentToolMsgCard;__openagentI--){let __openagentCandidate=${cardsVar}[__openagentI];if(__openagentCandidate&&(__openagentCandidate.outputText||__openagentCandidate.text))__openagentToolMsgCard=window.__openagentRenderToolCard(__openagentCandidate,${toolMessageSidebarArg})}for(let __openagentI=0;__openagentI<${cardsVar}.length&&!__openagentToolMsgCard;__openagentI++){__openagentToolMsgCard=window.__openagentRenderToolCard(${cardsVar}[__openagentI],${toolMessageSidebarArg})}}if(__openagentToolMsgCard)return ${toolMessageHtmlVar}\`<div class="\${${chatBubbleClassVar}}">\${__openagentToolMsgCard}</div>\`;`;
|
|
341
|
+
const toolMessageInsertAt = toolMessageFn!.bodyStart + toolMessageReturnIdx;
|
|
342
|
+
content = content.substring(0, toolMessageInsertAt) + toolMessageHook + content.substring(toolMessageInsertAt);
|
|
343
|
+
patchedToolMessageWrapper = true;
|
|
344
|
+
logger.info(`[ui-ext:regex] toolcard-render: patched tool message wrapper ${toolMessageFn!.funcName}(${toolMessageFn!.params.substring(0, 20)}) html=${toolMessageHtmlVar}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
329
348
|
}
|
|
330
|
-
|
|
331
|
-
const toolMessageHook =
|
|
332
|
-
`${marker}let __openagentToolMsgCard=null;if(!${mediaVar}&&window.__openagentRenderToolCard){for(let __openagentI=${cardsVar}.length-1;__openagentI>=0&&!__openagentToolMsgCard;__openagentI--){let __openagentCandidate=${cardsVar}[__openagentI];if(__openagentCandidate&&(__openagentCandidate.outputText||__openagentCandidate.text))__openagentToolMsgCard=window.__openagentRenderToolCard(__openagentCandidate,${toolMessageSidebarArg})}for(let __openagentI=0;__openagentI<${cardsVar}.length&&!__openagentToolMsgCard;__openagentI++){__openagentToolMsgCard=window.__openagentRenderToolCard(${cardsVar}[__openagentI],${toolMessageSidebarArg})}}if(__openagentToolMsgCard)return ${toolMessageHtmlVar}\`<div class="\${${chatBubbleClassVar}}">\${__openagentToolMsgCard}</div>\`;`;
|
|
333
|
-
const toolMessageInsertAt = toolMessageFn.bodyStart + toolMessageReturnIdx;
|
|
334
|
-
content = content.substring(0, toolMessageInsertAt) + toolMessageHook + content.substring(toolMessageInsertAt);
|
|
335
|
-
patchedToolMessageWrapper = true;
|
|
336
|
-
logger.info(`[ui-ext:regex] toolcard-render: patched tool message wrapper ${toolMessageFn.funcName}(${toolMessageFn.params.substring(0, 20)}) html=${toolMessageHtmlVar}`);
|
|
337
349
|
}
|
|
338
350
|
|
|
339
351
|
writeFileSync(bundlePath, content, 'utf-8');
|
|
@@ -440,7 +452,7 @@ const toolcallidPropagate: UIExtension = {
|
|
|
440
452
|
|
|
441
453
|
// 计算注入内容
|
|
442
454
|
const marker = makeMarker(this.id);
|
|
443
|
-
const tcidCapture = `${marker}var __tcid=(typeof ${
|
|
455
|
+
const tcidCapture = `${marker}var __tcid=(typeof ${msgParam}.toolCallId==='string'&&${msgParam}.toolCallId)||(typeof ${msgParam}.tool_call_id==='string'&&${msgParam}.tool_call_id)||'';`;
|
|
444
456
|
|
|
445
457
|
const inlinePatchCall = callLoopVar
|
|
446
458
|
? `,toolCallId:__tcid||${callLoopVar}.id||${callLoopVar}.toolCallId||${callLoopVar}.tool_call_id||''`
|
|
@@ -454,16 +466,16 @@ const toolcallidPropagate: UIExtension = {
|
|
|
454
466
|
const arrInitPattern = `,${cardsVar}=[];`;
|
|
455
467
|
let arrInitIdx = funcBody.indexOf(arrInitPattern);
|
|
456
468
|
if (arrInitIdx < 0) {
|
|
457
|
-
// v4.11+: 可能是 ,i=[]
|
|
469
|
+
// v4.11+: 可能是 ,i=[](后接逗号,如 a=[],o=...),不能直接插 var
|
|
458
470
|
const altPattern = `,${cardsVar}=[]`;
|
|
459
471
|
arrInitIdx = funcBody.indexOf(altPattern);
|
|
460
472
|
if (arrInitIdx < 0) {
|
|
461
473
|
logger.warn('[ui-ext:regex] toolcallid-propagate: cards init not found');
|
|
462
474
|
return false;
|
|
463
475
|
}
|
|
464
|
-
//
|
|
465
|
-
|
|
466
|
-
|
|
476
|
+
// altPattern 后面是逗号(逗号表达式),var 声明无法插入此处
|
|
477
|
+
// 改为插入到函数体开头,利用 var 提升特性
|
|
478
|
+
arrInitIdx = 0;
|
|
467
479
|
} else {
|
|
468
480
|
arrInitIdx += arrInitPattern.length;
|
|
469
481
|
}
|
|
@@ -672,7 +684,7 @@ const remoteAgentMessageShortCircuit: UIExtension = {
|
|
|
672
684
|
|
|
673
685
|
const mentionHooks: UIExtension = {
|
|
674
686
|
id: 'mention-hooks',
|
|
675
|
-
version:
|
|
687
|
+
version: 3,
|
|
676
688
|
sharedFile: 'index-bundle',
|
|
677
689
|
|
|
678
690
|
apply(controlUiDir: string): boolean {
|
|
@@ -683,9 +695,9 @@ const mentionHooks: UIExtension = {
|
|
|
683
695
|
if (!backupFile(bundlePath)) return false;
|
|
684
696
|
|
|
685
697
|
// 注入点 A: handleKeyDown
|
|
686
|
-
//
|
|
687
|
-
//
|
|
688
|
-
const keydownRe = /;return\}
|
|
698
|
+
// 锚定 ;return}if(X.key===`Enter`&&!X.shiftKey){
|
|
699
|
+
// 不再依赖内层 isComposing:2026.6.10 已把 isComposing 检查拆到独立 handler
|
|
700
|
+
const keydownRe = /;return\}if\(([a-zA-Z_$][a-zA-Z0-9_$]*)\.key===`Enter`&&!\1\.shiftKey\)\{/;
|
|
689
701
|
const keydownMatch = content.match(keydownRe);
|
|
690
702
|
if (!keydownMatch) {
|
|
691
703
|
logger.warn('[ui-ext:regex] mention-hooks: keydown anchor not found');
|
|
@@ -697,34 +709,44 @@ const mentionHooks: UIExtension = {
|
|
|
697
709
|
const hookA = `${markerA}if(window.__clMention?.onKeyDown(${eventParam}))return;`;
|
|
698
710
|
content = content.substring(0, keydownInsertIdx) + hookA + content.substring(keydownInsertIdx);
|
|
699
711
|
|
|
700
|
-
// 注入点 B: handleInput —
|
|
701
|
-
// Shape A (old):
|
|
702
|
-
// Shape B (4.11
|
|
712
|
+
// 注入点 B: handleInput — 支持三种形态
|
|
713
|
+
// Shape A (old): .onDraftChange(target.value)}}
|
|
714
|
+
// Shape B (4.11~4.x): .onDraftChange(target.value) (arrow function 内)
|
|
715
|
+
// Shape C (2026.6.x): be=t=>{let n=t.target;pL(e,n.value)} — 引入 pL helper,
|
|
716
|
+
// arrow body 末尾不再出现 onDraftChange 字面
|
|
703
717
|
const inputReA = /\.onDraftChange\(([a-zA-Z_$][a-zA-Z0-9_$]*)\.value\)\}\}/;
|
|
704
718
|
const inputReB = /\.onDraftChange\(([a-zA-Z_$][a-zA-Z0-9_$]*)\.value\)/;
|
|
719
|
+
const inputReC = /let ([a-zA-Z_$][a-zA-Z0-9_$]*)=[a-zA-Z_$][a-zA-Z0-9_$]*\.target;[a-zA-Z_$][a-zA-Z0-9_$]*\([a-zA-Z_$][a-zA-Z0-9_$]*,\1\.value\)\}/;
|
|
720
|
+
|
|
705
721
|
let inputMatch = content.match(inputReA);
|
|
706
|
-
let inputShape: 'A' | 'B' = 'A';
|
|
722
|
+
let inputShape: 'A' | 'B' | 'C' = 'A';
|
|
707
723
|
|
|
724
|
+
if (!inputMatch) {
|
|
725
|
+
inputMatch = content.match(inputReC);
|
|
726
|
+
inputShape = 'C';
|
|
727
|
+
}
|
|
708
728
|
if (!inputMatch) {
|
|
709
729
|
inputMatch = content.match(inputReB);
|
|
710
730
|
inputShape = 'B';
|
|
711
731
|
}
|
|
712
732
|
|
|
713
733
|
if (!inputMatch) {
|
|
714
|
-
logger.warn('[ui-ext:regex] mention-hooks: input anchor not found (
|
|
734
|
+
logger.warn('[ui-ext:regex] mention-hooks: input anchor not found (Shape A/B/C all missed)');
|
|
715
735
|
return false;
|
|
716
736
|
}
|
|
717
737
|
const targetVar = inputMatch[1];
|
|
718
738
|
const inputAnchorIdx = content.indexOf(inputMatch[0]);
|
|
719
|
-
//
|
|
739
|
+
// Shape A: }} 之前;Shape C: 末尾 } 之前;Shape B: ) 之后
|
|
720
740
|
const draftCallEnd = inputShape === 'A'
|
|
721
|
-
? inputAnchorIdx + inputMatch[0].length - 2
|
|
722
|
-
:
|
|
741
|
+
? inputAnchorIdx + inputMatch[0].length - 2
|
|
742
|
+
: inputShape === 'C'
|
|
743
|
+
? inputAnchorIdx + inputMatch[0].length - 1
|
|
744
|
+
: inputAnchorIdx + inputMatch[0].length;
|
|
723
745
|
const hookB = `;window.__clMention?.onInput?.(${targetVar})`;
|
|
724
746
|
content = content.substring(0, draftCallEnd) + hookB + content.substring(draftCallEnd);
|
|
725
747
|
|
|
726
748
|
writeFileSync(bundlePath, content, 'utf-8');
|
|
727
|
-
logger.info(`[ui-ext:regex] mention-hooks: injected (event=${eventParam}, target=${targetVar})`);
|
|
749
|
+
logger.info(`[ui-ext:regex] mention-hooks: injected (shape=${inputShape}, event=${eventParam}, target=${targetVar})`);
|
|
728
750
|
return true;
|
|
729
751
|
},
|
|
730
752
|
|