@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.
Files changed (171) hide show
  1. package/dist/agent/agent-loop.d.ts +25 -0
  2. package/dist/agent/agent-loop.d.ts.map +1 -1
  3. package/dist/agent/agent-loop.js +67 -14
  4. package/dist/agent/agent-loop.js.map +1 -1
  5. package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
  6. package/dist/agent/code-act/host-bridge.js +98 -0
  7. package/dist/agent/code-act/host-bridge.js.map +1 -1
  8. package/dist/agent/code-act/type-definition-generator.d.ts.map +1 -1
  9. package/dist/agent/code-act/type-definition-generator.js +0 -1
  10. package/dist/agent/code-act/type-definition-generator.js.map +1 -1
  11. package/dist/agent/gateway-tool-executor.d.ts +36 -1
  12. package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
  13. package/dist/agent/gateway-tool-executor.js +938 -54
  14. package/dist/agent/gateway-tool-executor.js.map +1 -1
  15. package/dist/agent/gateway-tools.md +9 -0
  16. package/dist/agent/managed-agent-runtime-sync.d.ts +36 -0
  17. package/dist/agent/managed-agent-runtime-sync.d.ts.map +1 -0
  18. package/dist/agent/managed-agent-runtime-sync.js +207 -0
  19. package/dist/agent/managed-agent-runtime-sync.js.map +1 -0
  20. package/dist/agent/managed-agent-validation.d.ts +4 -0
  21. package/dist/agent/managed-agent-validation.d.ts.map +1 -0
  22. package/dist/agent/managed-agent-validation.js +84 -0
  23. package/dist/agent/managed-agent-validation.js.map +1 -0
  24. package/dist/agent/os-agent-capabilities.md +400 -0
  25. package/dist/agent/skill-loader.d.ts +2 -0
  26. package/dist/agent/skill-loader.d.ts.map +1 -1
  27. package/dist/agent/skill-loader.js +28 -0
  28. package/dist/agent/skill-loader.js.map +1 -1
  29. package/dist/agent/tool-registry.d.ts.map +1 -1
  30. package/dist/agent/tool-registry.js +66 -0
  31. package/dist/agent/tool-registry.js.map +1 -1
  32. package/dist/agent/types.d.ts +2 -1
  33. package/dist/agent/types.d.ts.map +1 -1
  34. package/dist/agent/types.js.map +1 -1
  35. package/dist/api/agent-handler.d.ts +34 -0
  36. package/dist/api/agent-handler.d.ts.map +1 -0
  37. package/dist/api/agent-handler.js +216 -0
  38. package/dist/api/agent-handler.js.map +1 -0
  39. package/dist/api/graph-api-types.d.ts +4 -0
  40. package/dist/api/graph-api-types.d.ts.map +1 -1
  41. package/dist/api/graph-api.d.ts +2 -2
  42. package/dist/api/graph-api.d.ts.map +1 -1
  43. package/dist/api/graph-api.js +480 -51
  44. package/dist/api/graph-api.js.map +1 -1
  45. package/dist/api/index.d.ts.map +1 -1
  46. package/dist/api/index.js +4 -0
  47. package/dist/api/index.js.map +1 -1
  48. package/dist/api/token-handler.d.ts +1 -0
  49. package/dist/api/token-handler.d.ts.map +1 -1
  50. package/dist/api/token-handler.js +4 -3
  51. package/dist/api/token-handler.js.map +1 -1
  52. package/dist/api/ui-command-handler.d.ts +48 -0
  53. package/dist/api/ui-command-handler.d.ts.map +1 -0
  54. package/dist/api/ui-command-handler.js +160 -0
  55. package/dist/api/ui-command-handler.js.map +1 -0
  56. package/dist/cli/commands/start.d.ts.map +1 -1
  57. package/dist/cli/commands/start.js +127 -1
  58. package/dist/cli/commands/start.js.map +1 -1
  59. package/dist/cli/config/config-manager.d.ts.map +1 -1
  60. package/dist/cli/config/config-manager.js +16 -31
  61. package/dist/cli/config/config-manager.js.map +1 -1
  62. package/dist/cli/runtime/agent-loop-init.d.ts.map +1 -1
  63. package/dist/cli/runtime/agent-loop-init.js +31 -7
  64. package/dist/cli/runtime/agent-loop-init.js.map +1 -1
  65. package/dist/cli/runtime/api-routes-init.d.ts +3 -0
  66. package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
  67. package/dist/cli/runtime/api-routes-init.js +283 -34
  68. package/dist/cli/runtime/api-routes-init.js.map +1 -1
  69. package/dist/cli/runtime/gateway-init.d.ts +2 -1
  70. package/dist/cli/runtime/gateway-init.d.ts.map +1 -1
  71. package/dist/cli/runtime/gateway-init.js +5 -1
  72. package/dist/cli/runtime/gateway-init.js.map +1 -1
  73. package/dist/connectors/framework/raw-store.d.ts +4 -0
  74. package/dist/connectors/framework/raw-store.d.ts.map +1 -1
  75. package/dist/connectors/framework/raw-store.js +33 -10
  76. package/dist/connectors/framework/raw-store.js.map +1 -1
  77. package/dist/db/agent-store.d.ts +115 -0
  78. package/dist/db/agent-store.d.ts.map +1 -0
  79. package/dist/db/agent-store.js +248 -0
  80. package/dist/db/agent-store.js.map +1 -0
  81. package/dist/db/migrations/agent-activity-validation-columns.d.ts +3 -0
  82. package/dist/db/migrations/agent-activity-validation-columns.d.ts.map +1 -0
  83. package/dist/db/migrations/agent-activity-validation-columns.js +22 -0
  84. package/dist/db/migrations/agent-activity-validation-columns.js.map +1 -0
  85. package/dist/db/migrations/agent-metrics-response-avg.d.ts +3 -0
  86. package/dist/db/migrations/agent-metrics-response-avg.d.ts.map +1 -0
  87. package/dist/db/migrations/agent-metrics-response-avg.js +19 -0
  88. package/dist/db/migrations/agent-metrics-response-avg.js.map +1 -0
  89. package/dist/db/migrations/agent-store-tables.d.ts +3 -0
  90. package/dist/db/migrations/agent-store-tables.d.ts.map +1 -0
  91. package/dist/db/migrations/agent-store-tables.js +59 -0
  92. package/dist/db/migrations/agent-store-tables.js.map +1 -0
  93. package/dist/db/migrations/token-usage-agent-version.d.ts +3 -0
  94. package/dist/db/migrations/token-usage-agent-version.d.ts.map +1 -0
  95. package/dist/db/migrations/token-usage-agent-version.js +16 -0
  96. package/dist/db/migrations/token-usage-agent-version.js.map +1 -0
  97. package/dist/db/migrations/validation-session-tables.d.ts +3 -0
  98. package/dist/db/migrations/validation-session-tables.d.ts.map +1 -0
  99. package/dist/db/migrations/validation-session-tables.js +59 -0
  100. package/dist/db/migrations/validation-session-tables.js.map +1 -0
  101. package/dist/gateways/message-router.d.ts +10 -0
  102. package/dist/gateways/message-router.d.ts.map +1 -1
  103. package/dist/gateways/message-router.js +188 -14
  104. package/dist/gateways/message-router.js.map +1 -1
  105. package/dist/gateways/types.d.ts +1 -1
  106. package/dist/gateways/types.d.ts.map +1 -1
  107. package/dist/multi-agent/agent-process-manager.js +1 -1
  108. package/dist/multi-agent/agent-process-manager.js.map +1 -1
  109. package/dist/multi-agent/conductor-persona.d.ts +13 -0
  110. package/dist/multi-agent/conductor-persona.d.ts.map +1 -0
  111. package/dist/multi-agent/conductor-persona.js +157 -0
  112. package/dist/multi-agent/conductor-persona.js.map +1 -0
  113. package/dist/multi-agent/dashboard-agent-persona.d.ts +1 -1
  114. package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
  115. package/dist/multi-agent/dashboard-agent-persona.js +7 -3
  116. package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
  117. package/dist/multi-agent/delegation-manager.d.ts +5 -0
  118. package/dist/multi-agent/delegation-manager.d.ts.map +1 -1
  119. package/dist/multi-agent/delegation-manager.js +37 -0
  120. package/dist/multi-agent/delegation-manager.js.map +1 -1
  121. package/dist/multi-agent/ultrawork.d.ts +3 -0
  122. package/dist/multi-agent/ultrawork.d.ts.map +1 -1
  123. package/dist/multi-agent/ultrawork.js +9 -0
  124. package/dist/multi-agent/ultrawork.js.map +1 -1
  125. package/dist/validation/session-service.d.ts +72 -0
  126. package/dist/validation/session-service.d.ts.map +1 -0
  127. package/dist/validation/session-service.js +298 -0
  128. package/dist/validation/session-service.js.map +1 -0
  129. package/dist/validation/store.d.ts +25 -0
  130. package/dist/validation/store.d.ts.map +1 -0
  131. package/dist/validation/store.js +200 -0
  132. package/dist/validation/store.js.map +1 -0
  133. package/dist/validation/types.d.ts +119 -0
  134. package/dist/validation/types.d.ts.map +1 -0
  135. package/dist/validation/types.js +57 -0
  136. package/dist/validation/types.js.map +1 -0
  137. package/package.json +3 -3
  138. package/public/viewer/js/modules/agents.js +1148 -0
  139. package/public/viewer/js/modules/chat.js +20 -11
  140. package/public/viewer/js/modules/connector-feed.js +35 -0
  141. package/public/viewer/js/modules/dashboard.js +49 -0
  142. package/public/viewer/js/modules/memory.js +32 -0
  143. package/public/viewer/js/modules/settings.js +34 -79
  144. package/public/viewer/js/modules/wiki.js +59 -4
  145. package/public/viewer/js/utils/api.js +70 -0
  146. package/public/viewer/js/utils/dom.js +3 -0
  147. package/public/viewer/js/utils/ui-commands.js +93 -0
  148. package/public/viewer/log-viewer.html +2 -2
  149. package/public/viewer/src/modules/agents.ts +1299 -0
  150. package/public/viewer/src/modules/chat.ts +23 -14
  151. package/public/viewer/src/modules/connector-feed.ts +35 -0
  152. package/public/viewer/src/modules/dashboard.ts +50 -0
  153. package/public/viewer/src/modules/memory.ts +31 -0
  154. package/public/viewer/src/modules/settings.ts +36 -96
  155. package/public/viewer/src/modules/wiki.ts +73 -6
  156. package/public/viewer/src/types/global.d.ts +0 -9
  157. package/public/viewer/src/utils/api.ts +156 -2
  158. package/public/viewer/src/utils/dom.ts +6 -1
  159. package/public/viewer/src/utils/ui-commands.ts +118 -0
  160. package/public/viewer/viewer.css +105 -10
  161. package/public/viewer/viewer.html +1868 -777
  162. package/scripts/generate-gateway-tools.ts +5 -1
  163. package/public/viewer/js/modules/playground.js +0 -148
  164. package/public/viewer/js/modules/skills.js +0 -451
  165. package/public/viewer/src/modules/playground.ts +0 -173
  166. package/public/viewer/src/modules/skills.ts +0 -491
  167. package/templates/playgrounds/cron-workflow-lab.html +0 -1601
  168. package/templates/playgrounds/mama-log-viewer.html +0 -1341
  169. package/templates/playgrounds/skill-lab-playground.html +0 -1625
  170. package/templates/playgrounds/wave-visualizer.html +0 -694
  171. 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
- const indicator = statusEl.querySelector('.status-indicator');
833
- const text = statusEl.querySelector('span:not(.status-indicator)');
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
- text.textContent = 'Connected';
842
+ statusEl.title = 'Connected';
842
843
  break;
843
844
  case 'disconnected':
844
- text.textContent = 'Disconnected';
845
+ statusEl.title = 'Disconnected';
845
846
  break;
846
847
  case 'connecting':
847
- text.textContent = 'Connecting...';
848
+ statusEl.title = 'Connecting...';
848
849
  break;
849
850
  default:
850
- text.textContent = status;
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
- const agents = this.multiAgentData?.agents || [];
911
- if (agents.length === 0) {
912
- container.innerHTML = `
913
- <div class="bg-white border border-gray-200 rounded-lg p-3 text-xs text-gray-500">
914
- No agents configured. Add agents in <code class="bg-gray-100 px-1 rounded">config.yaml</code>
915
- </div>
916
- `;
917
- return;
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.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
55
+ return s
56
+ .replace(/&/g, '&amp;')
57
+ .replace(/</g, '&lt;')
58
+ .replace(/>/g, '&gt;')
59
+ .replace(/"/g, '&quot;')
60
+ .replace(/'/g, '&#39;');
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 (!mobile && !this.currentPath) {
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