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, "")