@jungjaehoon/mama-os 0.18.2 → 0.19.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/agent/agent-loop.d.ts +25 -0
- package/dist/agent/agent-loop.d.ts.map +1 -1
- package/dist/agent/agent-loop.js +67 -14
- package/dist/agent/agent-loop.js.map +1 -1
- package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
- package/dist/agent/code-act/host-bridge.js +98 -0
- package/dist/agent/code-act/host-bridge.js.map +1 -1
- package/dist/agent/code-act/type-definition-generator.d.ts.map +1 -1
- package/dist/agent/code-act/type-definition-generator.js +0 -1
- package/dist/agent/code-act/type-definition-generator.js.map +1 -1
- package/dist/agent/gateway-tool-executor.d.ts +36 -1
- package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
- package/dist/agent/gateway-tool-executor.js +938 -54
- package/dist/agent/gateway-tool-executor.js.map +1 -1
- package/dist/agent/gateway-tools.md +9 -0
- package/dist/agent/managed-agent-runtime-sync.d.ts +36 -0
- package/dist/agent/managed-agent-runtime-sync.d.ts.map +1 -0
- package/dist/agent/managed-agent-runtime-sync.js +207 -0
- package/dist/agent/managed-agent-runtime-sync.js.map +1 -0
- package/dist/agent/managed-agent-validation.d.ts +4 -0
- package/dist/agent/managed-agent-validation.d.ts.map +1 -0
- package/dist/agent/managed-agent-validation.js +84 -0
- package/dist/agent/managed-agent-validation.js.map +1 -0
- package/dist/agent/os-agent-capabilities.md +400 -0
- package/dist/agent/skill-loader.d.ts +2 -0
- package/dist/agent/skill-loader.d.ts.map +1 -1
- package/dist/agent/skill-loader.js +28 -0
- package/dist/agent/skill-loader.js.map +1 -1
- package/dist/agent/tool-registry.d.ts.map +1 -1
- package/dist/agent/tool-registry.js +66 -0
- package/dist/agent/tool-registry.js.map +1 -1
- package/dist/agent/types.d.ts +2 -1
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js.map +1 -1
- package/dist/api/agent-handler.d.ts +34 -0
- package/dist/api/agent-handler.d.ts.map +1 -0
- package/dist/api/agent-handler.js +216 -0
- package/dist/api/agent-handler.js.map +1 -0
- package/dist/api/graph-api-types.d.ts +4 -0
- package/dist/api/graph-api-types.d.ts.map +1 -1
- package/dist/api/graph-api.d.ts +2 -2
- package/dist/api/graph-api.d.ts.map +1 -1
- package/dist/api/graph-api.js +480 -51
- package/dist/api/graph-api.js.map +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +4 -0
- package/dist/api/index.js.map +1 -1
- package/dist/api/token-handler.d.ts +1 -0
- package/dist/api/token-handler.d.ts.map +1 -1
- package/dist/api/token-handler.js +4 -3
- package/dist/api/token-handler.js.map +1 -1
- package/dist/api/ui-command-handler.d.ts +48 -0
- package/dist/api/ui-command-handler.d.ts.map +1 -0
- package/dist/api/ui-command-handler.js +160 -0
- package/dist/api/ui-command-handler.js.map +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +127 -1
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/config/config-manager.d.ts.map +1 -1
- package/dist/cli/config/config-manager.js +16 -31
- package/dist/cli/config/config-manager.js.map +1 -1
- package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
- package/dist/cli/runtime/agent-loop-init.js +31 -7
- package/dist/cli/runtime/agent-loop-init.js.map +1 -1
- package/dist/cli/runtime/api-routes-init.d.ts +3 -0
- package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
- package/dist/cli/runtime/api-routes-init.js +283 -34
- package/dist/cli/runtime/api-routes-init.js.map +1 -1
- package/dist/cli/runtime/gateway-init.d.ts +2 -1
- package/dist/cli/runtime/gateway-init.d.ts.map +1 -1
- package/dist/cli/runtime/gateway-init.js +5 -1
- package/dist/cli/runtime/gateway-init.js.map +1 -1
- package/dist/connectors/framework/raw-store.d.ts +4 -0
- package/dist/connectors/framework/raw-store.d.ts.map +1 -1
- package/dist/connectors/framework/raw-store.js +33 -10
- package/dist/connectors/framework/raw-store.js.map +1 -1
- package/dist/db/agent-store.d.ts +115 -0
- package/dist/db/agent-store.d.ts.map +1 -0
- package/dist/db/agent-store.js +248 -0
- package/dist/db/agent-store.js.map +1 -0
- package/dist/db/migrations/agent-activity-validation-columns.d.ts +3 -0
- package/dist/db/migrations/agent-activity-validation-columns.d.ts.map +1 -0
- package/dist/db/migrations/agent-activity-validation-columns.js +22 -0
- package/dist/db/migrations/agent-activity-validation-columns.js.map +1 -0
- package/dist/db/migrations/agent-metrics-response-avg.d.ts +3 -0
- package/dist/db/migrations/agent-metrics-response-avg.d.ts.map +1 -0
- package/dist/db/migrations/agent-metrics-response-avg.js +19 -0
- package/dist/db/migrations/agent-metrics-response-avg.js.map +1 -0
- package/dist/db/migrations/agent-store-tables.d.ts +3 -0
- package/dist/db/migrations/agent-store-tables.d.ts.map +1 -0
- package/dist/db/migrations/agent-store-tables.js +59 -0
- package/dist/db/migrations/agent-store-tables.js.map +1 -0
- package/dist/db/migrations/token-usage-agent-version.d.ts +3 -0
- package/dist/db/migrations/token-usage-agent-version.d.ts.map +1 -0
- package/dist/db/migrations/token-usage-agent-version.js +16 -0
- package/dist/db/migrations/token-usage-agent-version.js.map +1 -0
- package/dist/db/migrations/validation-session-tables.d.ts +3 -0
- package/dist/db/migrations/validation-session-tables.d.ts.map +1 -0
- package/dist/db/migrations/validation-session-tables.js +59 -0
- package/dist/db/migrations/validation-session-tables.js.map +1 -0
- package/dist/gateways/message-router.d.ts +10 -0
- package/dist/gateways/message-router.d.ts.map +1 -1
- package/dist/gateways/message-router.js +188 -14
- package/dist/gateways/message-router.js.map +1 -1
- package/dist/gateways/types.d.ts +1 -1
- package/dist/gateways/types.d.ts.map +1 -1
- package/dist/multi-agent/agent-process-manager.js +1 -1
- package/dist/multi-agent/agent-process-manager.js.map +1 -1
- package/dist/multi-agent/conductor-persona.d.ts +13 -0
- package/dist/multi-agent/conductor-persona.d.ts.map +1 -0
- package/dist/multi-agent/conductor-persona.js +157 -0
- package/dist/multi-agent/conductor-persona.js.map +1 -0
- package/dist/multi-agent/dashboard-agent-persona.d.ts +1 -1
- package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
- package/dist/multi-agent/dashboard-agent-persona.js +7 -3
- package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
- package/dist/multi-agent/delegation-manager.d.ts +5 -0
- package/dist/multi-agent/delegation-manager.d.ts.map +1 -1
- package/dist/multi-agent/delegation-manager.js +37 -0
- package/dist/multi-agent/delegation-manager.js.map +1 -1
- package/dist/multi-agent/ultrawork.d.ts +3 -0
- package/dist/multi-agent/ultrawork.d.ts.map +1 -1
- package/dist/multi-agent/ultrawork.js +9 -0
- package/dist/multi-agent/ultrawork.js.map +1 -1
- package/dist/validation/session-service.d.ts +72 -0
- package/dist/validation/session-service.d.ts.map +1 -0
- package/dist/validation/session-service.js +298 -0
- package/dist/validation/session-service.js.map +1 -0
- package/dist/validation/store.d.ts +25 -0
- package/dist/validation/store.d.ts.map +1 -0
- package/dist/validation/store.js +200 -0
- package/dist/validation/store.js.map +1 -0
- package/dist/validation/types.d.ts +119 -0
- package/dist/validation/types.d.ts.map +1 -0
- package/dist/validation/types.js +57 -0
- package/dist/validation/types.js.map +1 -0
- package/package.json +3 -3
- package/public/viewer/js/modules/agents.js +1148 -0
- package/public/viewer/js/modules/chat.js +20 -11
- package/public/viewer/js/modules/connector-feed.js +35 -0
- package/public/viewer/js/modules/dashboard.js +49 -0
- package/public/viewer/js/modules/memory.js +32 -0
- package/public/viewer/js/modules/settings.js +34 -79
- package/public/viewer/js/modules/wiki.js +59 -4
- package/public/viewer/js/utils/api.js +70 -0
- package/public/viewer/js/utils/dom.js +3 -0
- package/public/viewer/js/utils/ui-commands.js +93 -0
- package/public/viewer/log-viewer.html +2 -2
- package/public/viewer/src/modules/agents.ts +1299 -0
- package/public/viewer/src/modules/chat.ts +23 -14
- package/public/viewer/src/modules/connector-feed.ts +35 -0
- package/public/viewer/src/modules/dashboard.ts +50 -0
- package/public/viewer/src/modules/memory.ts +31 -0
- package/public/viewer/src/modules/settings.ts +36 -96
- package/public/viewer/src/modules/wiki.ts +73 -6
- package/public/viewer/src/types/global.d.ts +0 -9
- package/public/viewer/src/utils/api.ts +156 -2
- package/public/viewer/src/utils/dom.ts +6 -1
- package/public/viewer/src/utils/ui-commands.ts +118 -0
- package/public/viewer/viewer.css +105 -10
- package/public/viewer/viewer.html +1868 -777
- package/scripts/generate-gateway-tools.ts +5 -1
- package/public/viewer/js/modules/playground.js +0 -148
- package/public/viewer/js/modules/skills.js +0 -451
- package/public/viewer/src/modules/playground.ts +0 -173
- package/public/viewer/src/modules/skills.ts +0 -491
- package/templates/playgrounds/cron-workflow-lab.html +0 -1601
- package/templates/playgrounds/mama-log-viewer.html +0 -1341
- package/templates/playgrounds/skill-lab-playground.html +0 -1625
- package/templates/playgrounds/wave-visualizer.html +0 -694
- package/templates/skills/playground.md +0 -197
|
@@ -314,10 +314,16 @@ export class ChatModule {
|
|
|
314
314
|
}
|
|
315
315
|
this.addUserMessage(message);
|
|
316
316
|
this.enableSend(false);
|
|
317
|
+
// Include current viewer tab context (SmartStore ChatPanel pattern)
|
|
318
|
+
const tabIndicator = document.getElementById('chat-tab-indicator');
|
|
319
|
+
const viewerContext = {
|
|
320
|
+
currentTab: tabIndicator?.textContent?.toLowerCase() || 'unknown',
|
|
321
|
+
};
|
|
317
322
|
this.ws.send(JSON.stringify({
|
|
318
323
|
type: 'send',
|
|
319
324
|
sessionId: this.sessionId,
|
|
320
325
|
content: message,
|
|
326
|
+
viewerContext,
|
|
321
327
|
}));
|
|
322
328
|
// Search for related MAMA decisions
|
|
323
329
|
if (this.memoryModule) {
|
|
@@ -829,25 +835,20 @@ export class ChatModule {
|
|
|
829
835
|
logger.warn('Status element not found');
|
|
830
836
|
return;
|
|
831
837
|
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
if (!indicator || !text) {
|
|
835
|
-
logger.warn('Status indicator or text not found');
|
|
836
|
-
return;
|
|
837
|
-
}
|
|
838
|
-
indicator.className = 'status-indicator ' + status;
|
|
838
|
+
// #chat-status IS the indicator element (not a wrapper with children)
|
|
839
|
+
statusEl.className = 'status-indicator w-1.5 h-1.5 rounded-full flex-shrink-0 ' + status;
|
|
839
840
|
switch (status) {
|
|
840
841
|
case 'connected':
|
|
841
|
-
|
|
842
|
+
statusEl.title = 'Connected';
|
|
842
843
|
break;
|
|
843
844
|
case 'disconnected':
|
|
844
|
-
|
|
845
|
+
statusEl.title = 'Disconnected';
|
|
845
846
|
break;
|
|
846
847
|
case 'connecting':
|
|
847
|
-
|
|
848
|
+
statusEl.title = 'Connecting...';
|
|
848
849
|
break;
|
|
849
850
|
default:
|
|
850
|
-
|
|
851
|
+
statusEl.title = status;
|
|
851
852
|
}
|
|
852
853
|
}
|
|
853
854
|
/**
|
|
@@ -1645,12 +1646,20 @@ export class ChatModule {
|
|
|
1645
1646
|
const resizeHandle = getElementByIdOrNull('chat-resize-handle');
|
|
1646
1647
|
const panel = getElementByIdOrNull('chat-panel');
|
|
1647
1648
|
const header = getElementByIdOrNull('chat-header');
|
|
1649
|
+
// Right panel mode: no bubble, auto-init session
|
|
1650
|
+
const isRightPanel = !bubble && !!document.getElementById('chat-panel-wrapper');
|
|
1651
|
+
if (isRightPanel && !this.ws) {
|
|
1652
|
+
this.initSession();
|
|
1653
|
+
}
|
|
1648
1654
|
if (bubble) {
|
|
1649
1655
|
bubble.addEventListener('click', () => this.togglePanel());
|
|
1650
1656
|
}
|
|
1651
1657
|
if (closeBtn) {
|
|
1652
1658
|
closeBtn.addEventListener('click', () => this.togglePanel(false));
|
|
1653
1659
|
}
|
|
1660
|
+
// Right panel mode: skip drag/resize handlers (handled by viewer.html inline JS)
|
|
1661
|
+
if (isRightPanel)
|
|
1662
|
+
return;
|
|
1654
1663
|
if (panel && header) {
|
|
1655
1664
|
let dragging = false;
|
|
1656
1665
|
let startX = 0;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { API } from '../utils/api.js';
|
|
2
2
|
import { DebugLogger } from '../utils/debug-logger.js';
|
|
3
3
|
import { createCollapsible, createResizeHandle } from '../utils/dom.js';
|
|
4
|
+
import { reportPageContext } from '../utils/ui-commands.js';
|
|
4
5
|
const logger = new DebugLogger('ConnectorFeed');
|
|
5
6
|
// ── Mobile helpers ──────────────────────────────────────────────────────────
|
|
6
7
|
const MOBILE_BREAKPOINT = 768;
|
|
@@ -91,6 +92,17 @@ export class ConnectorFeedModule {
|
|
|
91
92
|
renderConnectorList(connectors) {
|
|
92
93
|
if (!this.container)
|
|
93
94
|
return;
|
|
95
|
+
reportPageContext('feed', {
|
|
96
|
+
pageType: 'connector-list',
|
|
97
|
+
selectedConnector: this.selectedConnector,
|
|
98
|
+
connectorCount: connectors.length,
|
|
99
|
+
connectors: connectors.slice(0, 10).map((c) => ({
|
|
100
|
+
connector: c.connector,
|
|
101
|
+
status: c.status,
|
|
102
|
+
channel: c.channel,
|
|
103
|
+
timestamp: c.timestamp,
|
|
104
|
+
})),
|
|
105
|
+
});
|
|
94
106
|
if (connectors.length === 0) {
|
|
95
107
|
this.container.innerHTML =
|
|
96
108
|
'<div style="padding:40px;text-align:center;color:#9E9891;font-size:14px">' +
|
|
@@ -211,12 +223,26 @@ export class ConnectorFeedModule {
|
|
|
211
223
|
}
|
|
212
224
|
showMobileList() {
|
|
213
225
|
this.mobileShowingDetail = false;
|
|
226
|
+
this.selectedConnector = null;
|
|
214
227
|
const list = document.getElementById('connector-list');
|
|
215
228
|
const detail = document.getElementById('connector-detail');
|
|
216
229
|
if (list)
|
|
217
230
|
list.style.display = '';
|
|
218
231
|
if (detail)
|
|
219
232
|
detail.style.display = 'none';
|
|
233
|
+
reportPageContext('feed', {
|
|
234
|
+
pageType: 'connector-list',
|
|
235
|
+
selectedConnector: null,
|
|
236
|
+
connectorCount: this.cachedConnectors.length,
|
|
237
|
+
channelCount: 0,
|
|
238
|
+
channels: [],
|
|
239
|
+
connectors: this.cachedConnectors.slice(0, 10).map((c) => ({
|
|
240
|
+
connector: c.connector,
|
|
241
|
+
status: c.status,
|
|
242
|
+
channel: c.channel,
|
|
243
|
+
timestamp: c.timestamp,
|
|
244
|
+
})),
|
|
245
|
+
});
|
|
220
246
|
}
|
|
221
247
|
handleResize() {
|
|
222
248
|
const list = document.getElementById('connector-list');
|
|
@@ -254,6 +280,15 @@ export class ConnectorFeedModule {
|
|
|
254
280
|
}
|
|
255
281
|
}
|
|
256
282
|
renderFeedDetail(container, name, feed) {
|
|
283
|
+
reportPageContext('feed', {
|
|
284
|
+
pageType: 'connector-detail',
|
|
285
|
+
selectedConnector: name,
|
|
286
|
+
channelCount: feed.length,
|
|
287
|
+
channels: feed.slice(0, 10).map((channel) => ({
|
|
288
|
+
channel: channel.channel,
|
|
289
|
+
itemCount: channel.items.length,
|
|
290
|
+
})),
|
|
291
|
+
});
|
|
257
292
|
const icon = CONNECTOR_ICON[name] || '\u{1F517}';
|
|
258
293
|
// Clear and build header
|
|
259
294
|
container.innerHTML = '';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { API, } from '../utils/api.js';
|
|
2
2
|
import { DebugLogger } from '../utils/debug-logger.js';
|
|
3
3
|
import { createCollapsible } from '../utils/dom.js';
|
|
4
|
+
import { reportPageContext } from '../utils/ui-commands.js';
|
|
4
5
|
const logger = new DebugLogger('Dashboard');
|
|
5
6
|
// ── Style constants ─────────────────────────────────────────────────────────
|
|
6
7
|
const COLOR = {
|
|
@@ -64,6 +65,17 @@ export class DashboardModule {
|
|
|
64
65
|
container = null;
|
|
65
66
|
eventSource = null;
|
|
66
67
|
refreshTimer = null;
|
|
68
|
+
selectedProject = null;
|
|
69
|
+
selectedConnector = null;
|
|
70
|
+
getCurrentPageType() {
|
|
71
|
+
if (this.selectedConnector) {
|
|
72
|
+
return 'dashboard-connector';
|
|
73
|
+
}
|
|
74
|
+
if (this.selectedProject) {
|
|
75
|
+
return 'dashboard-project';
|
|
76
|
+
}
|
|
77
|
+
return 'dashboard-overview';
|
|
78
|
+
}
|
|
67
79
|
init() {
|
|
68
80
|
this.container = document.getElementById('dashboard-slots');
|
|
69
81
|
if (!this.container)
|
|
@@ -136,6 +148,17 @@ export class DashboardModule {
|
|
|
136
148
|
render(data) {
|
|
137
149
|
if (!this.container)
|
|
138
150
|
return;
|
|
151
|
+
reportPageContext('dashboard', {
|
|
152
|
+
pageType: this.getCurrentPageType(),
|
|
153
|
+
selectedProject: this.selectedProject,
|
|
154
|
+
selectedConnector: this.selectedConnector,
|
|
155
|
+
noticeCount: data.notices.length,
|
|
156
|
+
pipelineCount: data.pipeline.length,
|
|
157
|
+
connectorCount: data.connectors.length,
|
|
158
|
+
totalDecisions: data.totalDecisions,
|
|
159
|
+
agentCount: data.agentCount,
|
|
160
|
+
summary: data.summary.text?.slice(0, 300) ?? '',
|
|
161
|
+
});
|
|
139
162
|
const emptyEl = document.getElementById('slots-empty');
|
|
140
163
|
const hasData = data.summary.text ||
|
|
141
164
|
data.notices.length > 0 ||
|
|
@@ -239,6 +262,12 @@ export class DashboardModule {
|
|
|
239
262
|
if (isOpen) {
|
|
240
263
|
detail.style.display = 'none';
|
|
241
264
|
arrow.textContent = '\u25B6';
|
|
265
|
+
this.selectedProject = null;
|
|
266
|
+
reportPageContext('dashboard', {
|
|
267
|
+
pageType: this.getCurrentPageType(),
|
|
268
|
+
selectedProject: null,
|
|
269
|
+
selectedConnector: this.selectedConnector,
|
|
270
|
+
});
|
|
242
271
|
}
|
|
243
272
|
else {
|
|
244
273
|
detail.style.display = '';
|
|
@@ -247,6 +276,13 @@ export class DashboardModule {
|
|
|
247
276
|
if (projectName && detail.textContent === 'Loading...') {
|
|
248
277
|
this.loadPipelineDetail(detail, projectName);
|
|
249
278
|
}
|
|
279
|
+
this.selectedProject = projectName ?? null;
|
|
280
|
+
this.selectedConnector = null;
|
|
281
|
+
reportPageContext('dashboard', {
|
|
282
|
+
pageType: 'dashboard-project',
|
|
283
|
+
selectedProject: this.selectedProject,
|
|
284
|
+
selectedConnector: this.selectedConnector,
|
|
285
|
+
});
|
|
250
286
|
}
|
|
251
287
|
});
|
|
252
288
|
});
|
|
@@ -310,6 +346,12 @@ export class DashboardModule {
|
|
|
310
346
|
if (isOpen) {
|
|
311
347
|
detail.style.display = 'none';
|
|
312
348
|
arrow.textContent = '\u25B6';
|
|
349
|
+
this.selectedConnector = null;
|
|
350
|
+
reportPageContext('dashboard', {
|
|
351
|
+
pageType: this.getCurrentPageType(),
|
|
352
|
+
selectedProject: this.selectedProject,
|
|
353
|
+
selectedConnector: null,
|
|
354
|
+
});
|
|
313
355
|
}
|
|
314
356
|
else {
|
|
315
357
|
detail.style.display = '';
|
|
@@ -318,6 +360,13 @@ export class DashboardModule {
|
|
|
318
360
|
if (connName && detail.textContent === 'Loading...') {
|
|
319
361
|
this.loadConnectorDetail(detail, connName);
|
|
320
362
|
}
|
|
363
|
+
this.selectedConnector = connName ?? null;
|
|
364
|
+
this.selectedProject = null;
|
|
365
|
+
reportPageContext('dashboard', {
|
|
366
|
+
pageType: 'dashboard-connector',
|
|
367
|
+
selectedProject: this.selectedProject,
|
|
368
|
+
selectedConnector: this.selectedConnector,
|
|
369
|
+
});
|
|
321
370
|
}
|
|
322
371
|
});
|
|
323
372
|
});
|
|
@@ -14,6 +14,7 @@ import { escapeHtml, debounce, showToast, getElementByIdOrNull } from '../utils/
|
|
|
14
14
|
import { formatRelativeTime, truncateText } from '../utils/format.js';
|
|
15
15
|
import { API } from '../utils/api.js';
|
|
16
16
|
import { DebugLogger } from '../utils/debug-logger.js';
|
|
17
|
+
import { reportPageContext } from '../utils/ui-commands.js';
|
|
17
18
|
const logger = new DebugLogger('Memory');
|
|
18
19
|
/**
|
|
19
20
|
* Memory Module Class
|
|
@@ -106,6 +107,17 @@ export class MemoryModule {
|
|
|
106
107
|
this.searchData = data.results || [];
|
|
107
108
|
this.renderResults(this.searchData, query);
|
|
108
109
|
this.setStatus(`Found ${this.searchData.length} decision(s)`, '');
|
|
110
|
+
reportPageContext('memory', {
|
|
111
|
+
pageType: 'memory-search',
|
|
112
|
+
query,
|
|
113
|
+
resultCount: this.searchData.length,
|
|
114
|
+
results: this.searchData.slice(0, 10).map((item) => ({
|
|
115
|
+
id: item.id ?? null,
|
|
116
|
+
topic: item.topic ?? null,
|
|
117
|
+
outcome: item.outcome ?? null,
|
|
118
|
+
similarity: item.similarity ?? null,
|
|
119
|
+
})),
|
|
120
|
+
});
|
|
109
121
|
}
|
|
110
122
|
catch (error) {
|
|
111
123
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -138,6 +150,17 @@ export class MemoryModule {
|
|
|
138
150
|
*/
|
|
139
151
|
async showRelatedForMessage(message) {
|
|
140
152
|
const results = await this.searchRelated(message);
|
|
153
|
+
reportPageContext('memory', {
|
|
154
|
+
pageType: 'memory-related',
|
|
155
|
+
query: message,
|
|
156
|
+
resultCount: results.length,
|
|
157
|
+
results: results.slice(0, 10).map((item) => ({
|
|
158
|
+
id: item.id ?? null,
|
|
159
|
+
topic: item.topic ?? null,
|
|
160
|
+
outcome: item.outcome ?? null,
|
|
161
|
+
similarity: item.similarity ?? null,
|
|
162
|
+
})),
|
|
163
|
+
});
|
|
141
164
|
if (results.length > 0) {
|
|
142
165
|
this.searchData = results;
|
|
143
166
|
// Update search input with the query (if element exists)
|
|
@@ -151,6 +174,9 @@ export class MemoryModule {
|
|
|
151
174
|
// Show notification
|
|
152
175
|
showToast(`🧠 ${results.length} related MAMA decision(s) found`);
|
|
153
176
|
}
|
|
177
|
+
else {
|
|
178
|
+
this.setStatus('No related decisions found', '');
|
|
179
|
+
}
|
|
154
180
|
}
|
|
155
181
|
/**
|
|
156
182
|
* Render search results
|
|
@@ -227,6 +253,12 @@ export class MemoryModule {
|
|
|
227
253
|
</div>
|
|
228
254
|
`;
|
|
229
255
|
this.setStatus('', '');
|
|
256
|
+
reportPageContext('memory', {
|
|
257
|
+
pageType: 'memory-search',
|
|
258
|
+
query: '',
|
|
259
|
+
resultCount: 0,
|
|
260
|
+
results: [],
|
|
261
|
+
});
|
|
230
262
|
// Reinitialize Lucide icons for dynamic content
|
|
231
263
|
if (typeof lucide !== 'undefined' && typeof window.lucideConfig !== 'undefined') {
|
|
232
264
|
lucide.createIcons(window.lucideConfig);
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { showToast, escapeHtml, escapeAttr, getElementByIdOrNull } from '../utils/dom.js';
|
|
14
14
|
import { formatModelName } from '../utils/format.js';
|
|
15
15
|
import { DebugLogger } from '../utils/debug-logger.js';
|
|
16
|
+
import { reportPageContext } from '../utils/ui-commands.js';
|
|
16
17
|
import { API, } from '../utils/api.js';
|
|
17
18
|
const logger = new DebugLogger('Settings');
|
|
18
19
|
// Model options by backend (single source of truth)
|
|
@@ -233,6 +234,13 @@ export class SettingsModule {
|
|
|
233
234
|
}
|
|
234
235
|
return;
|
|
235
236
|
}
|
|
237
|
+
const goAgentsButton = target.closest('[data-action="go-agents-tab"]');
|
|
238
|
+
if (goAgentsButton) {
|
|
239
|
+
e.preventDefault();
|
|
240
|
+
if (typeof window.switchTab === 'function') {
|
|
241
|
+
window.switchTab('agents');
|
|
242
|
+
}
|
|
243
|
+
}
|
|
236
244
|
});
|
|
237
245
|
}
|
|
238
246
|
/**
|
|
@@ -319,6 +327,23 @@ export class SettingsModule {
|
|
|
319
327
|
this.populateSkillsSection();
|
|
320
328
|
this.populateTokenSection();
|
|
321
329
|
this.populateCronSection();
|
|
330
|
+
reportPageContext('settings', {
|
|
331
|
+
pageType: 'settings-overview',
|
|
332
|
+
gateways: {
|
|
333
|
+
discord: this.config.discord?.enabled ?? false,
|
|
334
|
+
slack: this.config.slack?.enabled ?? false,
|
|
335
|
+
telegram: this.config.telegram?.enabled ?? false,
|
|
336
|
+
chatwork: this.config.chatwork?.enabled ?? false,
|
|
337
|
+
},
|
|
338
|
+
agent: {
|
|
339
|
+
backend: this.config.agent?.backend ?? 'claude',
|
|
340
|
+
model: this.config.agent?.model ?? null,
|
|
341
|
+
max_turns: this.config.agent?.max_turns ?? null,
|
|
342
|
+
timeout: this.config.agent?.timeout ?? null,
|
|
343
|
+
},
|
|
344
|
+
multiAgentCount: this.multiAgentData.agents.length,
|
|
345
|
+
mcpServerCount: this.mcpServersData.servers.length,
|
|
346
|
+
});
|
|
322
347
|
}
|
|
323
348
|
/**
|
|
324
349
|
* Populate timeouts section from config
|
|
@@ -901,91 +926,21 @@ export class SettingsModule {
|
|
|
901
926
|
}
|
|
902
927
|
/**
|
|
903
928
|
* Populate Multi-Agent Team section (F3)
|
|
929
|
+
* Agent editing has moved to the Agents tab — show redirect notice.
|
|
904
930
|
*/
|
|
905
931
|
populateMultiAgentSection() {
|
|
906
932
|
const container = getElementByIdOrNull('settings-multi-agent-container');
|
|
907
933
|
if (!container) {
|
|
908
934
|
return;
|
|
909
935
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
<
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
919
|
-
// Tier badge colors
|
|
920
|
-
const tierColors = {
|
|
921
|
-
1: 'bg-indigo-100 text-indigo-700',
|
|
922
|
-
2: 'bg-green-100 text-green-700',
|
|
923
|
-
3: 'bg-yellow-100 text-yellow-700',
|
|
924
|
-
};
|
|
925
|
-
const agentCards = agents
|
|
926
|
-
.map((agent) => {
|
|
927
|
-
const tierValue = Number(agent.tier) || 1;
|
|
928
|
-
const tierColor = tierColors[tierValue] || tierColors[1];
|
|
929
|
-
const backend = (agent.backend || this.config?.agent?.backend || 'claude');
|
|
930
|
-
const normalizedModel = this.getNormalizedModelForBackend(backend, agent.model || '');
|
|
931
|
-
const agentId = agent.id || '';
|
|
932
|
-
const backendOptions = ['codex-mcp', 'claude']
|
|
933
|
-
.map((b) => `<option value="${escapeAttr(b)}" ${backend === b ? 'selected' : ''}>${escapeHtml(b)}</option>`)
|
|
934
|
-
.join('');
|
|
935
|
-
const modelOptions = MODEL_OPTIONS[backend] || MODEL_OPTIONS.claude;
|
|
936
|
-
const modelOptionHtml = modelOptions
|
|
937
|
-
.map((m) => `<option value="${escapeAttr(m)}" ${m === normalizedModel ? 'selected' : ''}>${escapeHtml(formatModelName(m))}</option>`)
|
|
938
|
-
.join('');
|
|
939
|
-
// Effort level (Claude 4.6 models only, max on Opus).
|
|
940
|
-
const supportsAgentEffort = this.supportsEffortModel(normalizedModel);
|
|
941
|
-
const selectedAgentEffort = this.normalizeEffortForModel(normalizedModel, (agent.effort || 'medium'));
|
|
942
|
-
const effortOptions = this.buildEffortOptions(normalizedModel, selectedAgentEffort);
|
|
943
|
-
// Permission flags — only check explicit tool_permissions, not tier
|
|
944
|
-
const canDelegate = agent.can_delegate ?? false;
|
|
945
|
-
const hasAllTools = agent.tool_permissions?.allowed?.includes('*') ?? false;
|
|
946
|
-
return `
|
|
947
|
-
<div class="bg-white border border-gray-200 rounded-lg p-3 hover:shadow-md transition-shadow">
|
|
948
|
-
<!-- Header: Tier + Name + Toggle -->
|
|
949
|
-
<div class="flex items-center justify-between mb-2">
|
|
950
|
-
<div class="flex items-center gap-1.5">
|
|
951
|
-
<span class="${tierColor} text-[10px] font-bold px-1.5 py-0.5 rounded">T${escapeHtml(String(tierValue))}</span>
|
|
952
|
-
<span class="font-medium text-gray-900 text-xs" title="${escapeAttr(agent.display_name || agent.name)}">${escapeHtml(agent.display_name || agent.name)}</span>
|
|
953
|
-
</div>
|
|
954
|
-
<label class="relative inline-flex items-center cursor-pointer">
|
|
955
|
-
<input type="checkbox" class="sr-only peer" data-action="agent-toggle" data-agent-id="${escapeAttr(agentId)}" ${agent.enabled ? 'checked' : ''}>
|
|
956
|
-
<div class="w-7 h-4 bg-gray-200 rounded-full peer peer-checked:after:translate-x-full after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-3 after:w-3 after:transition-all peer-checked:bg-green-500"></div>
|
|
957
|
-
</label>
|
|
958
|
-
</div>
|
|
959
|
-
|
|
960
|
-
<!-- Backend -->
|
|
961
|
-
<select id="agent-backend-${escapeAttr(agentId)}" data-action="agent-backend" data-agent-id="${escapeAttr(agentId)}" class="w-full text-[11px] rounded border border-gray-200 px-1.5 py-1 bg-gray-50 mb-1">${backendOptions}</select>
|
|
962
|
-
<!-- Model -->
|
|
963
|
-
<select id="agent-model-${escapeAttr(agentId)}" data-action="agent-model" data-agent-id="${escapeAttr(agentId)}" class="w-full text-[11px] rounded border border-gray-200 px-1.5 py-1 bg-gray-50 mb-1">${modelOptionHtml}</select>
|
|
964
|
-
<!-- Effort (Claude 4.6 only) -->
|
|
965
|
-
<div id="agent-effort-container-${escapeAttr(agentId)}" class="mb-1" style="display: ${supportsAgentEffort ? 'block' : 'none'}">
|
|
966
|
-
<select id="agent-effort-${escapeAttr(agentId)}" class="w-full text-[11px] rounded border border-gray-200 px-1.5 py-1 bg-gray-50">${effortOptions}</select>
|
|
967
|
-
</div>
|
|
968
|
-
|
|
969
|
-
<!-- Permissions + Save -->
|
|
970
|
-
<div class="flex items-center justify-between mt-2">
|
|
971
|
-
<div class="flex items-center gap-2 text-[10px] text-gray-600">
|
|
972
|
-
<label class="flex items-center gap-0.5 cursor-pointer">
|
|
973
|
-
<input type="checkbox" id="agent-delegate-${escapeAttr(agentId)}" class="w-3 h-3 rounded border-gray-300 text-yellow-500 focus:ring-yellow-400" ${canDelegate ? 'checked' : ''}>
|
|
974
|
-
<span>Delegate</span>
|
|
975
|
-
</label>
|
|
976
|
-
<label class="flex items-center gap-0.5 cursor-pointer">
|
|
977
|
-
<input type="checkbox" id="agent-alltools-${escapeAttr(agentId)}" class="w-3 h-3 rounded border-gray-300 text-yellow-500 focus:ring-yellow-400" ${hasAllTools ? 'checked' : ''}>
|
|
978
|
-
<span>All Tools</span>
|
|
979
|
-
</label>
|
|
980
|
-
</div>
|
|
981
|
-
<button type="button" data-action="agent-save" data-agent-id="${escapeAttr(agentId)}" class="text-[10px] px-3 py-1 rounded bg-mama-yellow text-mama-black hover:bg-mama-yellow-hover font-medium">Save</button>
|
|
982
|
-
</div>
|
|
983
|
-
</div>
|
|
984
|
-
`;
|
|
985
|
-
})
|
|
986
|
-
.join('');
|
|
987
|
-
// Grid layout: 2 cols on mobile, 3 cols on md+
|
|
988
|
-
container.innerHTML = `<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-2">${agentCards}</div>`;
|
|
936
|
+
container.innerHTML = `
|
|
937
|
+
<div class="bg-white border border-gray-200 rounded-lg p-4 text-center">
|
|
938
|
+
<p class="text-sm text-gray-600 mb-2">Agent management has moved to the Agents tab.</p>
|
|
939
|
+
<button data-action="go-agents-tab"
|
|
940
|
+
class="text-sm px-4 py-1.5 rounded-md bg-mama-yellow text-mama-black hover:bg-mama-yellow-hover font-medium">
|
|
941
|
+
Go to Agents
|
|
942
|
+
</button>
|
|
943
|
+
</div>`;
|
|
989
944
|
}
|
|
990
945
|
/**
|
|
991
946
|
* Toggle agent enabled status (F3)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { API } from '../utils/api.js';
|
|
2
2
|
import { DebugLogger } from '../utils/debug-logger.js';
|
|
3
3
|
import { createResizeHandle } from '../utils/dom.js';
|
|
4
|
+
import { reportPageContext } from '../utils/ui-commands.js';
|
|
4
5
|
const logger = new DebugLogger('Wiki');
|
|
5
6
|
// ── Mobile helpers ──────────────────────────────────────────────────────────
|
|
6
7
|
const MOBILE_BREAKPOINT = 768;
|
|
@@ -51,7 +52,12 @@ function renderTreeNode(node, depth = 0) {
|
|
|
51
52
|
`${escapeHtml(node.name.replace(/\.md$/, ''))}</div>`);
|
|
52
53
|
}
|
|
53
54
|
function escapeHtml(s) {
|
|
54
|
-
return s
|
|
55
|
+
return s
|
|
56
|
+
.replace(/&/g, '&')
|
|
57
|
+
.replace(/</g, '<')
|
|
58
|
+
.replace(/>/g, '>')
|
|
59
|
+
.replace(/"/g, '"')
|
|
60
|
+
.replace(/'/g, ''');
|
|
55
61
|
}
|
|
56
62
|
export class WikiModule {
|
|
57
63
|
container = null;
|
|
@@ -59,6 +65,7 @@ export class WikiModule {
|
|
|
59
65
|
resizeHandler = null;
|
|
60
66
|
mobileShowingPage = false;
|
|
61
67
|
initialized = false;
|
|
68
|
+
treeLoadPromise = null;
|
|
62
69
|
init() {
|
|
63
70
|
if (this.initialized) {
|
|
64
71
|
return;
|
|
@@ -70,7 +77,26 @@ export class WikiModule {
|
|
|
70
77
|
this.initialized = true;
|
|
71
78
|
this.resizeHandler = () => this.handleResize();
|
|
72
79
|
window.addEventListener('resize', this.resizeHandler);
|
|
73
|
-
this.loadTree();
|
|
80
|
+
this.treeLoadPromise = this.loadTree();
|
|
81
|
+
}
|
|
82
|
+
publishListContext() {
|
|
83
|
+
reportPageContext('wiki', {
|
|
84
|
+
pageType: 'wiki-list',
|
|
85
|
+
path: null,
|
|
86
|
+
activePath: this.currentPath,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
publishPageContext(page) {
|
|
90
|
+
const title = String(page.frontmatter.title ?? '').trim() ||
|
|
91
|
+
page.path.split('/').pop()?.replace(/\.md$/, '') ||
|
|
92
|
+
page.path;
|
|
93
|
+
reportPageContext('wiki', {
|
|
94
|
+
pageType: 'wiki-page',
|
|
95
|
+
path: page.path,
|
|
96
|
+
title,
|
|
97
|
+
frontmatter: page.frontmatter,
|
|
98
|
+
content_preview: page.raw.slice(0, 400),
|
|
99
|
+
}, { type: 'wiki-page', id: page.path });
|
|
74
100
|
}
|
|
75
101
|
async loadTree() {
|
|
76
102
|
if (!this.container)
|
|
@@ -149,11 +175,14 @@ export class WikiModule {
|
|
|
149
175
|
});
|
|
150
176
|
document.getElementById('wiki-new-btn')?.addEventListener('click', () => this.promptNewPage());
|
|
151
177
|
// Auto-open index page only on initial load (no page selected yet)
|
|
152
|
-
if (!
|
|
178
|
+
if (!this.currentPath) {
|
|
153
179
|
const indexNode = tree.find((n) => n.name === 'index.md');
|
|
154
|
-
if (indexNode) {
|
|
180
|
+
if (!mobile && indexNode) {
|
|
155
181
|
this.openPage(indexNode.path);
|
|
156
182
|
}
|
|
183
|
+
else {
|
|
184
|
+
this.publishListContext();
|
|
185
|
+
}
|
|
157
186
|
}
|
|
158
187
|
}
|
|
159
188
|
async openPage(path) {
|
|
@@ -173,6 +202,7 @@ export class WikiModule {
|
|
|
173
202
|
try {
|
|
174
203
|
const page = await API.getWikiPage(path);
|
|
175
204
|
this.renderPageView(pageEl, page);
|
|
205
|
+
this.publishPageContext(page);
|
|
176
206
|
}
|
|
177
207
|
catch {
|
|
178
208
|
pageEl.innerHTML = `<div style="color:#D94F4F;padding:20px">Failed to load ${path}</div>`;
|
|
@@ -190,12 +220,14 @@ export class WikiModule {
|
|
|
190
220
|
}
|
|
191
221
|
showMobileTree() {
|
|
192
222
|
this.mobileShowingPage = false;
|
|
223
|
+
this.currentPath = null;
|
|
193
224
|
const treeEl = document.getElementById('wiki-tree');
|
|
194
225
|
const pageEl = document.getElementById('wiki-page');
|
|
195
226
|
if (treeEl)
|
|
196
227
|
treeEl.style.display = '';
|
|
197
228
|
if (pageEl)
|
|
198
229
|
pageEl.style.display = 'none';
|
|
230
|
+
this.publishListContext();
|
|
199
231
|
}
|
|
200
232
|
handleResize() {
|
|
201
233
|
const treeEl = document.getElementById('wiki-tree');
|
|
@@ -367,4 +399,27 @@ export class WikiModule {
|
|
|
367
399
|
this.resizeHandler = null;
|
|
368
400
|
}
|
|
369
401
|
}
|
|
402
|
+
async navigateTo(path) {
|
|
403
|
+
if (!this.initialized) {
|
|
404
|
+
this.init();
|
|
405
|
+
}
|
|
406
|
+
if (this.treeLoadPromise) {
|
|
407
|
+
await this.treeLoadPromise;
|
|
408
|
+
}
|
|
409
|
+
if (path) {
|
|
410
|
+
await this.openPage(path);
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (this.currentPath) {
|
|
414
|
+
try {
|
|
415
|
+
const page = await API.getWikiPage(this.currentPath);
|
|
416
|
+
this.publishPageContext(page);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
catch {
|
|
420
|
+
/* fall through to list context */
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
this.publishListContext();
|
|
424
|
+
}
|
|
370
425
|
}
|
|
@@ -285,6 +285,76 @@ export class API {
|
|
|
285
285
|
return this.post(`/api/multi-agent/agents/${encodeURIComponent(agentId)}/stop`, {});
|
|
286
286
|
}
|
|
287
287
|
// =============================================
|
|
288
|
+
// Agent Management API (Managed Agents pattern)
|
|
289
|
+
// =============================================
|
|
290
|
+
static async getAgents() {
|
|
291
|
+
return this.get('/api/agents');
|
|
292
|
+
}
|
|
293
|
+
static async getAgent(agentId) {
|
|
294
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}`);
|
|
295
|
+
}
|
|
296
|
+
static async createAgent(body) {
|
|
297
|
+
return this.post('/api/agents', body);
|
|
298
|
+
}
|
|
299
|
+
static async updateAgent(agentId, body) {
|
|
300
|
+
return this.post(`/api/agents/${encodeURIComponent(agentId)}`, body);
|
|
301
|
+
}
|
|
302
|
+
static async archiveAgent(agentId) {
|
|
303
|
+
return this.post(`/api/agents/${encodeURIComponent(agentId)}/archive`, {});
|
|
304
|
+
}
|
|
305
|
+
static async getAgentVersions(agentId) {
|
|
306
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}/versions`);
|
|
307
|
+
}
|
|
308
|
+
static async compareAgentVersions(agentId, v1, v2) {
|
|
309
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}/versions/${v1}/compare/${v2}`);
|
|
310
|
+
}
|
|
311
|
+
static async getAgentMetrics(agentId, from, to) {
|
|
312
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}/metrics`, { from, to });
|
|
313
|
+
}
|
|
314
|
+
static async getAgentActivity(agentId, limit = 20) {
|
|
315
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}/activity?limit=${limit}`);
|
|
316
|
+
}
|
|
317
|
+
static async getActivitySummary(since) {
|
|
318
|
+
return this.get(`/api/agents/activity-summary?since=${encodeURIComponent(since)}`);
|
|
319
|
+
}
|
|
320
|
+
// =============================================
|
|
321
|
+
// Validation API
|
|
322
|
+
// =============================================
|
|
323
|
+
static async getValidationSummary(agentId, triggerType = 'agent_test') {
|
|
324
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}/validation/summary?trigger_type=${encodeURIComponent(triggerType)}`);
|
|
325
|
+
}
|
|
326
|
+
static async getValidationHistory(agentId, limit = 50, triggerType = 'agent_test') {
|
|
327
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}/validation/history?limit=${limit}&trigger_type=${encodeURIComponent(triggerType)}`);
|
|
328
|
+
}
|
|
329
|
+
static async getValidationSessionDetail(sessionId) {
|
|
330
|
+
return this.get(`/api/validation-sessions/${encodeURIComponent(sessionId)}`);
|
|
331
|
+
}
|
|
332
|
+
static async approveValidationSession(agentId, sessionId) {
|
|
333
|
+
return this.post(`/api/agents/${encodeURIComponent(agentId)}/validation/approve?session_id=${encodeURIComponent(sessionId)}`, {});
|
|
334
|
+
}
|
|
335
|
+
static async getValidationCompare(agentId, sessionId, baseline = 'approved') {
|
|
336
|
+
return this.get(`/api/agents/${encodeURIComponent(agentId)}/validation/compare?session=${encodeURIComponent(sessionId)}&baseline=${encodeURIComponent(baseline)}`);
|
|
337
|
+
}
|
|
338
|
+
// =============================================
|
|
339
|
+
// UI Command API (SmartStore pattern)
|
|
340
|
+
// =============================================
|
|
341
|
+
static async getUICommands() {
|
|
342
|
+
return this.get('/api/ui/commands');
|
|
343
|
+
}
|
|
344
|
+
static async ackUICommands(commandIds) {
|
|
345
|
+
return this.post('/api/ui/commands/ack', {
|
|
346
|
+
command_ids: commandIds,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
static async pushPageContext(route, data, selectedItem, channelId) {
|
|
350
|
+
return this.post('/api/ui/page-context', {
|
|
351
|
+
currentRoute: route,
|
|
352
|
+
pageData: data,
|
|
353
|
+
...(selectedItem ? { selectedItem } : {}),
|
|
354
|
+
...(channelId ? { channelId } : {}),
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
// =============================================
|
|
288
358
|
// Metrics / Health API
|
|
289
359
|
// =============================================
|
|
290
360
|
static async getHealthReport() {
|
|
@@ -109,6 +109,9 @@ export function scrollToBottom(container) {
|
|
|
109
109
|
* @param {number} maxRows - Maximum number of rows (default: 5)
|
|
110
110
|
*/
|
|
111
111
|
export function autoResizeTextarea(textarea, maxRows = 5) {
|
|
112
|
+
// Skip for non-textarea elements (e.g. input[type=text] in SmartStore-style panel)
|
|
113
|
+
if (!textarea || textarea.tagName !== 'TEXTAREA')
|
|
114
|
+
return;
|
|
112
115
|
// Use requestAnimationFrame to defer resize to the next frame, avoiding layout thrash from rapid input events
|
|
113
116
|
requestAnimationFrame(() => {
|
|
114
117
|
textarea.style.height = 'auto'; // Reset height before measuring
|