refactor: move drawMessageCodeExe into plugin JS extension
linuztx committed
Mar 8, 2026 at 23:20 UTC
7bb9e62e7c59372ccb2edc6f72e310fa4a76246b
2 files changed
+80
-81
plugins/code_execution/extensions/webui/get_message_handler/code-exe-handler.js
+77
-1
@@ -1,7 +1,83 @@
1
-import { drawMessageCodeExe } from "/js/messages.js";
1
+import {
2
+ createActionButton,
3
+ copyToClipboard,
4
+} from "/components/messages/action-buttons/simple-action-buttons.js";
5
+import { store as stepDetailStore } from "/components/modals/process-step-detail/step-detail-store.js";
6
+import {
7
+ buildDetailPayload,
8
+ cleanStepTitle,
9
+ drawProcessStep,
10
+} from "/js/messages.js";
11
12
export default async function registerCodeExeHandler(extData) {
13
if (extData?.type === "code_exe") {
14
extData.handler = drawMessageCodeExe;
15
}
16
}
17
+
18
+function drawMessageCodeExe({
19
+ id,
20
+ type,
21
+ heading,
22
+ test,
23
+ content,
24
+ kvps,
25
+ timestamp,
26
+ agentno = 0,
27
+ ...additional
28
+}) {
29
+ let title = "Code Execution";
30
+ // show command at the start and end
31
+ if (kvps?.code && /done_all|code_execution_tool/.test(heading || "")) {
32
+ const s = kvps.session;
33
+ title = `${s != null ? `[${s}] ` : ""}${kvps.runtime || "bash"}> ${kvps.code.trim()}`;
34
+ } else {
35
+ // during execution show the original heading (current step)
36
+ title = cleanStepTitle(heading);
37
+ }
38
+
39
+ const displayKvps = {};
40
+
41
+ const headerLabels = [
42
+ kvps?.runtime && { label: kvps.runtime, class: "tool-name-badge" },
43
+ kvps?.session != null && {
44
+ label: `Session ${kvps.session}`,
45
+ class: "header-label",
46
+ },
47
+ ].filter(Boolean);
48
+
49
+ const commandText = String(kvps?.code ?? "");
50
+ const outputText = String(content ?? "");
51
+
52
+ const actionButtons = [];
53
+ actionButtons.push(
54
+ createActionButton("detail", "", () =>
55
+ stepDetailStore.showStepDetail(
56
+ buildDetailPayload(arguments[0], { headerLabels }),
57
+ ),
58
+ ),
59
+ );
60
+ if (commandText.trim()) {
61
+ actionButtons.push(
62
+ createActionButton("copy", "Command", () => copyToClipboard(commandText)),
63
+ );
64
+ }
65
+ if (outputText.trim()) {
66
+ actionButtons.push(
67
+ createActionButton("copy", "Output", () => copyToClipboard(outputText)),
68
+ );
69
+ }
70
+ const stepData = drawProcessStep({
71
+ id,
72
+ title,
73
+ code: "EXE",
74
+ classes: undefined,
75
+ kvps: displayKvps,
76
+ content,
77
+ contentClasses: ["terminal-output"],
78
+ actionButtons,
79
+ log: arguments[0],
80
+ });
81
+
82
+ return stepData;
83
+}
webui/js/messages.js
+3
-80
@@ -94,8 +94,6 @@ export async function getMessageHandler(type) {
94
return drawMessageResponse;
95
case "tool":
96
return drawMessageTool;
97
- case "code_exe":
98
- return drawMessageCodeExe;
97
case "browser":
98
return drawMessageBrowser;
99
case "progress":
@@ -319,7 +317,7 @@ function getOrCreateProcessGroup(id, allowCompleted = true) {
317
return group;
318
}
319
322
-function buildDetailPayload(stepData, extras = {}) {
320
+export function buildDetailPayload(stepData, extras = {}) {
321
if (!stepData) return null;
322
return {
323
...stepData,
@@ -331,7 +329,7 @@ function buildDetailPayload(stepData, extras = {}) {
329
* @param {ProcessStepArgs & Record<string, any>} param0
330
* @returns {MessageHandlerResult}
331
*/
334
-function drawProcessStep({
332
+export function drawProcessStep({
333
id,
334
title,
335
code,
@@ -1204,81 +1202,6 @@ export function drawMessageToolSimple({
1202
});
1203
}
1204
1207
-/**
1208
- * @param {MessageHandlerArgs & Record<string, any>} param0
1209
- * @returns {MessageHandlerResult}
1210
- */
1211
-export function drawMessageCodeExe({
1212
- id,
1213
- type,
1214
- heading,
1215
- test,
1216
- content,
1217
- kvps,
1218
- timestamp,
1219
- agentno = 0,
1220
- ...additional
1221
-}) {
1222
- let title = "Code Execution";
1223
- // show command at the start and end
1224
- if (kvps?.code && /done_all|code_execution_tool/.test(heading || "")) {
1225
- const s = kvps.session;
1226
- title = `${s != null ? `[${s}] ` : ""}${kvps.runtime || "bash"}> ${kvps.code.trim()}`;
1227
- } else {
1228
- // during execution show the original heading (current step)
1229
- title = cleanStepTitle(heading);
1230
- }
1231
-
1232
- // KVPS to show
1233
- const displayKvps = {};
1234
- // if (kvps?.runtime) displayKvps.runtime = kvps.runtime;
1235
- // if (kvps?.session>=0) displayKvps.session = kvps.session;
1236
-
1237
- const headerLabels = [
1238
- kvps?.runtime && { label: kvps.runtime, class: "tool-name-badge" },
1239
- kvps?.session != null && {
1240
- label: `Session ${kvps.session}`,
1241
- class: "header-label",
1242
- },
1243
- ].filter(Boolean);
1244
-
1245
- // render the standard step
1246
- const commandText = String(kvps?.code ?? "");
1247
- const outputText = String(content ?? "");
1248
-
1249
- const actionButtons = [];
1250
- actionButtons.push(
1251
- createActionButton("detail", "", () =>
1252
- stepDetailStore.showStepDetail(
1253
- buildDetailPayload(arguments[0], { headerLabels }),
1254
- ),
1255
- ),
1256
- );
1257
- if (commandText.trim()) {
1258
- actionButtons.push(
1259
- createActionButton("copy", "Command", () => copyToClipboard(commandText)),
1260
- );
1261
- }
1262
- if (outputText.trim()) {
1263
- actionButtons.push(
1264
- createActionButton("copy", "Output", () => copyToClipboard(outputText)),
1265
- );
1266
- }
1267
- const stepData = drawProcessStep({
1268
- id,
1269
- title,
1270
- code: "EXE",
1271
- classes: undefined,
1272
- kvps: displayKvps,
1273
- content,
1274
- contentClasses: ["terminal-output"],
1275
- actionButtons,
1276
- log: arguments[0],
1277
- });
1278
-
1279
- return stepData;
1280
-}
1281
-
1205
/**
1206
* @param {MessageHandlerArgs & Record<string, any>} param0
1207
* @returns {MessageHandlerResult}
@@ -2143,7 +2066,7 @@ export function convertIcons(html, classes = "") {
2066
* Clean step title by removing icon:// prefixes and status phrases
2067
* Preserves agent markers (A1:, A2:, etc.) so users can see which subordinate agent is executing
2068
*/
2146
-function cleanStepTitle(text, maxLength = 100) {
2069
+export function cleanStepTitle(text, maxLength = 100) {
2070
if (!text) return "";
2071
let cleaned = String(text)
2072
.replace(/icon:\/\/[a-zA-Z0-9_]+(\[(?:\\.|[^\]])*\])?\s*/g, "")