@jungjaehoon/mama-os 0.32.3 → 0.34.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 (105) hide show
  1. package/README.md +15 -17
  2. package/dist/agent/os-agent-capabilities.md +2 -2
  3. package/dist/api/graph-api.d.ts +4 -4
  4. package/dist/api/graph-api.d.ts.map +1 -1
  5. package/dist/api/graph-api.js +47 -78
  6. package/dist/api/graph-api.js.map +1 -1
  7. package/dist/api/index.d.ts +10 -0
  8. package/dist/api/index.d.ts.map +1 -1
  9. package/dist/api/index.js +9 -2
  10. package/dist/api/index.js.map +1 -1
  11. package/dist/api/operator-handler.d.ts +1 -1
  12. package/dist/api/operator-handler.js +1 -1
  13. package/dist/api/runtime-status-handler.d.ts +41 -0
  14. package/dist/api/runtime-status-handler.d.ts.map +1 -0
  15. package/dist/api/runtime-status-handler.js +55 -0
  16. package/dist/api/runtime-status-handler.js.map +1 -0
  17. package/dist/cli/commands/start.d.ts.map +1 -1
  18. package/dist/cli/commands/start.js +58 -23
  19. package/dist/cli/commands/start.js.map +1 -1
  20. package/dist/cli/runtime/api-routes-init.d.ts +2 -0
  21. package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
  22. package/dist/cli/runtime/api-routes-init.js +62 -1
  23. package/dist/cli/runtime/api-routes-init.js.map +1 -1
  24. package/dist/cli/runtime/api-server-init.d.ts +12 -1
  25. package/dist/cli/runtime/api-server-init.d.ts.map +1 -1
  26. package/dist/cli/runtime/api-server-init.js +54 -0
  27. package/dist/cli/runtime/api-server-init.js.map +1 -1
  28. package/dist/cli/runtime/utilities.d.ts +1 -1
  29. package/dist/cli/runtime/utilities.d.ts.map +1 -1
  30. package/dist/cli/runtime/utilities.js +3 -1
  31. package/dist/cli/runtime/utilities.js.map +1 -1
  32. package/dist/gateways/message-router.d.ts +4 -0
  33. package/dist/gateways/message-router.d.ts.map +1 -1
  34. package/dist/gateways/message-router.js +62 -13
  35. package/dist/gateways/message-router.js.map +1 -1
  36. package/dist/gateways/owner-report-inbox.d.ts +40 -0
  37. package/dist/gateways/owner-report-inbox.d.ts.map +1 -0
  38. package/dist/gateways/owner-report-inbox.js +128 -0
  39. package/dist/gateways/owner-report-inbox.js.map +1 -0
  40. package/dist/gateways/report-projection-v1.d.ts +41 -0
  41. package/dist/gateways/report-projection-v1.d.ts.map +1 -0
  42. package/dist/gateways/report-projection-v1.js +160 -0
  43. package/dist/gateways/report-projection-v1.js.map +1 -0
  44. package/dist/gateways/session-store.d.ts +22 -0
  45. package/dist/gateways/session-store.d.ts.map +1 -1
  46. package/dist/gateways/session-store.js +76 -3
  47. package/dist/gateways/session-store.js.map +1 -1
  48. package/dist/gateways/telegram-message-ledger.d.ts +10 -0
  49. package/dist/gateways/telegram-message-ledger.d.ts.map +1 -1
  50. package/dist/gateways/telegram-message-ledger.js +23 -2
  51. package/dist/gateways/telegram-message-ledger.js.map +1 -1
  52. package/dist/gateways/telegram-report-context-store.d.ts +193 -0
  53. package/dist/gateways/telegram-report-context-store.d.ts.map +1 -0
  54. package/dist/gateways/telegram-report-context-store.js +612 -0
  55. package/dist/gateways/telegram-report-context-store.js.map +1 -0
  56. package/dist/gateways/telegram.d.ts +9 -0
  57. package/dist/gateways/telegram.d.ts.map +1 -1
  58. package/dist/gateways/telegram.js +100 -0
  59. package/dist/gateways/telegram.js.map +1 -1
  60. package/dist/gateways/types.d.ts +12 -0
  61. package/dist/gateways/types.d.ts.map +1 -1
  62. package/dist/multi-agent/dashboard-agent-persona.js +2 -2
  63. package/dist/operator/board-slot-instructions.d.ts +1 -1
  64. package/dist/operator/board-slot-instructions.js +1 -1
  65. package/dist/operator/operator-trigger-loop.d.ts +17 -1
  66. package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
  67. package/dist/operator/operator-trigger-loop.js +87 -23
  68. package/dist/operator/operator-trigger-loop.js.map +1 -1
  69. package/dist/operator/report-delivery-coordinator.d.ts +82 -0
  70. package/dist/operator/report-delivery-coordinator.d.ts.map +1 -0
  71. package/dist/operator/report-delivery-coordinator.js +123 -0
  72. package/dist/operator/report-delivery-coordinator.js.map +1 -0
  73. package/dist/operator/situation-report.d.ts +7 -0
  74. package/dist/operator/situation-report.d.ts.map +1 -1
  75. package/dist/operator/situation-report.js +12 -0
  76. package/dist/operator/situation-report.js.map +1 -1
  77. package/package.json +1 -2
  78. package/public/viewer/js/modules/system.js +183 -0
  79. package/public/viewer/js/utils/ui-commands.js +4 -9
  80. package/public/viewer/log-viewer.html +2 -192
  81. package/public/viewer/operator/operator.css +1 -0
  82. package/public/viewer/operator/operator.js +14830 -0
  83. package/public/viewer/src/modules/system.ts +242 -0
  84. package/public/viewer/src/utils/ui-commands.ts +4 -8
  85. package/public/viewer/sw.js +44 -10
  86. package/public/viewer/viewer.css +338 -331
  87. package/public/viewer/viewer.html +388 -1472
  88. package/public/ui/assets/index-BDXDGEV6.js +0 -62
  89. package/public/ui/assets/index-po2tN0xq.css +0 -1
  90. package/public/ui/index.html +0 -14
  91. package/public/ui/theme-init.js +0 -20
  92. package/public/viewer/js/modules/agents.js +0 -1153
  93. package/public/viewer/js/modules/chat.js +0 -1993
  94. package/public/viewer/js/modules/connector-feed.js +0 -352
  95. package/public/viewer/js/modules/dashboard.js +0 -456
  96. package/public/viewer/js/modules/entity-audit.js +0 -106
  97. package/public/viewer/js/modules/entity-review.js +0 -66
  98. package/public/viewer/js/modules/settings.js +0 -1257
  99. package/public/viewer/src/modules/agents.ts +0 -1302
  100. package/public/viewer/src/modules/chat.ts +0 -2426
  101. package/public/viewer/src/modules/connector-feed.ts +0 -391
  102. package/public/viewer/src/modules/dashboard.ts +0 -498
  103. package/public/viewer/src/modules/entity-audit.ts +0 -154
  104. package/public/viewer/src/modules/entity-review.ts +0 -175
  105. package/public/viewer/src/modules/settings.ts +0 -1547
@@ -1,352 +0,0 @@
1
- import { API } from '../utils/api.js';
2
- import { DebugLogger } from '../utils/debug-logger.js';
3
- import { createCollapsible, createResizeHandle } from '../utils/dom.js';
4
- import { reportPageContext } from '../utils/ui-commands.js';
5
- const logger = new DebugLogger('ConnectorFeed');
6
- // ── Mobile helpers ──────────────────────────────────────────────────────────
7
- const MOBILE_BREAKPOINT = 768;
8
- function isMobile() {
9
- return window.innerWidth < MOBILE_BREAKPOINT;
10
- }
11
- const backBtnStyle = 'display:flex;align-items:center;gap:6px;' +
12
- 'padding:8px 12px;margin-bottom:8px;' +
13
- 'font-size:13px;color:#6B6560;cursor:pointer;' +
14
- 'border:none;background:none;';
15
- // ── Style constants ─────────────────────────────────────────────────────────
16
- const COLOR = {
17
- primary: '#1A1A1A',
18
- secondary: '#6B6560',
19
- tertiary: '#9E9891',
20
- border: '#EDE9E1',
21
- bg: '#FAFAF8',
22
- red: '#D94F4F',
23
- green: '#3A9E7E',
24
- yellow: '#F5C518',
25
- };
26
- const CONNECTOR_ICON = {
27
- calendar: '\u{1F4C5}',
28
- slack: '\u{1F4AC}',
29
- discord: '\u{1F4AC}',
30
- telegram: '\u{1F4AC}',
31
- trello: '\u{1F4CB}',
32
- kagemusha: '\u{1F977}',
33
- 'claude-code': '\u{1F916}',
34
- gmail: '\u{1F4E7}',
35
- notion: '\u{1F4DD}',
36
- obsidian: '\u{1F4D3}',
37
- sheets: '\u{1F4CA}',
38
- drive: '\u{1F4C1}',
39
- chatwork: '\u{1F4AC}',
40
- imessage: '\u{1F4AC}',
41
- };
42
- // ── Helpers ─────────────────────────────────────────────────────────────────
43
- function esc(s) {
44
- return s
45
- .replace(/&/g, '&amp;')
46
- .replace(/</g, '&lt;')
47
- .replace(/>/g, '&gt;')
48
- .replace(/"/g, '&quot;');
49
- }
50
- function relativeTime(ts) {
51
- const diffMs = Date.now() - new Date(ts).getTime();
52
- const diffMin = Math.floor(diffMs / 60_000);
53
- if (diffMin < 1)
54
- return 'just now';
55
- if (diffMin < 60)
56
- return `${diffMin}m ago`;
57
- const diffHr = Math.floor(diffMin / 60);
58
- if (diffHr < 24)
59
- return `${diffHr}h ago`;
60
- const diffDays = Math.floor(diffHr / 24);
61
- return `${diffDays}d ago`;
62
- }
63
- // ── Connector Feed Module ───────────────────────────────────────────────────
64
- export class ConnectorFeedModule {
65
- container = null;
66
- selectedConnector = null;
67
- cachedConnectors = [];
68
- resizeHandler = null;
69
- mobileShowingDetail = false;
70
- init() {
71
- this.container = document.getElementById('feed-content');
72
- if (!this.container)
73
- return;
74
- this.resizeHandler = () => this.handleResize();
75
- window.addEventListener('resize', this.resizeHandler);
76
- this.loadConnectors();
77
- }
78
- async loadConnectors() {
79
- if (!this.container)
80
- return;
81
- try {
82
- const res = await API.getConnectorActivity();
83
- this.cachedConnectors = res.connectors;
84
- this.renderConnectorList(res.connectors);
85
- }
86
- catch (err) {
87
- logger.error('Failed to load connectors', err);
88
- this.container.innerHTML =
89
- '<div style="padding:40px;text-align:center;color:#9E9891;font-size:14px">Failed to load connectors.</div>';
90
- }
91
- }
92
- renderConnectorList(connectors) {
93
- if (!this.container)
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
- });
106
- if (connectors.length === 0) {
107
- this.container.innerHTML =
108
- '<div style="padding:40px;text-align:center;color:#9E9891;font-size:14px">' +
109
- 'No connectors configured. Add connectors in Settings to see their feeds here.</div>';
110
- return;
111
- }
112
- const mobile = isMobile();
113
- let html = `<div style="display:flex;gap:${mobile ? '0' : '16'}px;height:100%">`;
114
- // Left: Connector list
115
- const listStyle = mobile
116
- ? 'width:100%;overflow-y:auto;padding-right:0'
117
- : `width:280px;min-width:280px;overflow-y:auto;border-right:1px solid ${COLOR.border};padding-right:16px`;
118
- html += `<div id="connector-list" style="${listStyle}">`;
119
- html += `<h2 style="font-family:Inter,'Noto Sans KR',sans-serif;font-size:16px;font-weight:600;color:${COLOR.primary};margin:0 0 12px 0">Connectors</h2>`;
120
- for (const c of connectors) {
121
- const isActive = this.selectedConnector === c.connector;
122
- const bgColor = isActive ? '#F5F3EF' : 'transparent';
123
- const borderLeft = isActive ? `3px solid ${COLOR.primary}` : '3px solid transparent';
124
- const icon = CONNECTOR_ICON[c.connector] || '\u{1F517}';
125
- let statusHtml = '';
126
- if (c.status === 'active') {
127
- const rel = relativeTime(c.timestamp);
128
- statusHtml = `<span style="font-size:11px;color:${COLOR.green}">\u25CF active</span> <span style="font-size:10px;color:${COLOR.tertiary}">${esc(rel)}</span>`;
129
- }
130
- else if (c.status === 'idle') {
131
- statusHtml = `<span style="font-size:11px;color:${COLOR.tertiary}">\u25CB idle</span>`;
132
- }
133
- else {
134
- statusHtml = `<span style="font-size:11px;color:${COLOR.red}">\u26A0\uFE0F \uBBF8\uC5F0\uACB0</span>`;
135
- }
136
- html +=
137
- `<div class="connector-item" data-connector="${esc(c.connector)}" ` +
138
- `style="padding:10px 12px;margin-bottom:4px;border-radius:4px;cursor:pointer;` +
139
- `background:${bgColor};border-left:${borderLeft};transition:background 0.15s">` +
140
- `<div style="display:flex;align-items:center;gap:8px">` +
141
- `<span style="font-size:16px">${icon}</span>` +
142
- `<span style="font-size:13px;font-weight:600;color:${COLOR.primary}">${esc(c.connector)}</span>` +
143
- `</div>` +
144
- `<div style="margin-top:4px;padding-left:24px">${statusHtml}</div>` +
145
- `</div>`;
146
- }
147
- html += '</div>';
148
- // Right: Detail panel
149
- const detailDisplay = mobile ? 'display:none;' : '';
150
- const detailStyle = mobile
151
- ? `flex:1;overflow-y:auto;${detailDisplay}width:100%`
152
- : `flex:1;overflow-y:auto;padding-left:16px;${detailDisplay}`;
153
- html += `<div id="connector-detail" style="${detailStyle}">`;
154
- if (this.selectedConnector) {
155
- html += `<div style="color:${COLOR.tertiary};font-size:13px">Loading...</div>`;
156
- }
157
- else if (!mobile) {
158
- html +=
159
- `<div style="padding:40px;text-align:center;color:${COLOR.tertiary};font-size:13px">` +
160
- 'Select a connector to view its feed.</div>';
161
- }
162
- html += '</div></div>';
163
- this.container.innerHTML = html;
164
- // Attach resize handle to connector list panel (desktop only)
165
- if (!mobile) {
166
- const listPanel = document.getElementById('connector-list');
167
- if (listPanel) {
168
- createResizeHandle(listPanel, {
169
- storageKey: 'feed-connector-list-width',
170
- minWidth: 180,
171
- maxWidth: 500,
172
- });
173
- }
174
- }
175
- // Bind click events
176
- this.container.querySelectorAll('.connector-item').forEach((el) => {
177
- el.addEventListener('click', () => {
178
- const name = el.dataset.connector;
179
- if (name)
180
- this.selectConnector(name, connectors);
181
- });
182
- });
183
- // Auto-select first connector if none selected (desktop only)
184
- if (!this.selectedConnector && connectors.length > 0 && !mobile) {
185
- this.selectConnector(connectors[0].connector, connectors);
186
- }
187
- }
188
- async selectConnector(name, _connectors) {
189
- this.selectedConnector = name;
190
- // Update list selection highlight
191
- this.container?.querySelectorAll('.connector-item').forEach((el) => {
192
- const id = el.dataset.connector;
193
- const isActive = id === name;
194
- el.style.background = isActive ? '#F5F3EF' : 'transparent';
195
- el.style.borderLeft = isActive
196
- ? `3px solid ${COLOR.primary}`
197
- : '3px solid transparent';
198
- });
199
- // Mobile: hide list, show detail
200
- if (isMobile()) {
201
- this.mobileShowingDetail = true;
202
- const list = document.getElementById('connector-list');
203
- const detail = document.getElementById('connector-detail');
204
- if (list)
205
- list.style.display = 'none';
206
- if (detail) {
207
- detail.style.display = '';
208
- detail.style.width = '100%';
209
- }
210
- }
211
- const detail = document.getElementById('connector-detail');
212
- if (!detail)
213
- return;
214
- detail.innerHTML = `<div style="color:${COLOR.tertiary};font-size:13px">Loading feed...</div>`;
215
- try {
216
- const res = await API.getConnectorFeed(name);
217
- this.renderFeedDetail(detail, name, res.feed);
218
- }
219
- catch (err) {
220
- logger.error('Failed to load connector feed', err);
221
- detail.innerHTML = `<div style="color:${COLOR.red};font-size:13px">Failed to load feed.</div>`;
222
- }
223
- }
224
- showMobileList() {
225
- this.mobileShowingDetail = false;
226
- this.selectedConnector = null;
227
- const list = document.getElementById('connector-list');
228
- const detail = document.getElementById('connector-detail');
229
- if (list)
230
- list.style.display = '';
231
- if (detail)
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
- });
246
- }
247
- handleResize() {
248
- const list = document.getElementById('connector-list');
249
- const detail = document.getElementById('connector-detail');
250
- if (!list || !detail)
251
- return;
252
- if (isMobile()) {
253
- // Mobile: show one panel at a time
254
- list.style.width = '100%';
255
- list.style.minWidth = '';
256
- list.style.borderRight = 'none';
257
- list.style.paddingRight = '0';
258
- detail.style.paddingLeft = '0';
259
- detail.style.width = '100%';
260
- if (this.mobileShowingDetail) {
261
- list.style.display = 'none';
262
- detail.style.display = '';
263
- }
264
- else {
265
- list.style.display = '';
266
- detail.style.display = 'none';
267
- }
268
- }
269
- else {
270
- // Desktop: side-by-side
271
- list.style.display = '';
272
- list.style.width = '280px';
273
- list.style.minWidth = '280px';
274
- list.style.borderRight = `1px solid ${COLOR.border}`;
275
- list.style.paddingRight = '16px';
276
- detail.style.display = '';
277
- detail.style.paddingLeft = '16px';
278
- detail.style.width = '';
279
- this.mobileShowingDetail = false;
280
- }
281
- }
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
- });
292
- const icon = CONNECTOR_ICON[name] || '\u{1F517}';
293
- // Clear and build header
294
- container.innerHTML = '';
295
- // Mobile back button
296
- if (isMobile()) {
297
- const backBtn = document.createElement('button');
298
- backBtn.setAttribute('style', backBtnStyle);
299
- backBtn.innerHTML = '\u2190 Connectors';
300
- backBtn.addEventListener('click', () => this.showMobileList());
301
- container.appendChild(backBtn);
302
- }
303
- const header = document.createElement('div');
304
- header.setAttribute('style', 'margin-bottom:16px');
305
- header.innerHTML =
306
- `<h2 style="font-family:Inter,'Noto Sans KR',sans-serif;font-size:16px;font-weight:600;color:${COLOR.primary};margin:0">${icon} ${esc(name)}</h2>` +
307
- `<div style="font-size:11px;color:${COLOR.tertiary};margin-top:4px">${feed.length} channel${feed.length !== 1 ? 's' : ''}</div>`;
308
- container.appendChild(header);
309
- if (feed.length === 0) {
310
- const empty = document.createElement('div');
311
- empty.setAttribute('style', `padding:20px;text-align:center;color:${COLOR.tertiary};font-size:13px`);
312
- empty.textContent = 'No feed data available for this connector.';
313
- container.appendChild(empty);
314
- return;
315
- }
316
- // Channel-grouped items with collapsible headers and newest-first sort
317
- for (const ch of feed) {
318
- // Sort items newest first by timestamp
319
- const sorted = [...ch.items].sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
320
- let itemsHtml = '';
321
- for (const item of sorted) {
322
- const rel = relativeTime(item.timestamp);
323
- const preview = item.content.replace(/\n/g, ' ').slice(0, 120);
324
- itemsHtml += `<div style="padding:8px 12px;border-bottom:1px solid ${COLOR.border}">`;
325
- itemsHtml += `<div style="display:flex;align-items:baseline;gap:8px;margin-bottom:2px">`;
326
- itemsHtml += `<span style="font-size:11px;font-weight:600;color:${COLOR.primary}">${esc(item.author)}</span>`;
327
- itemsHtml += `<span style="font-size:10px;color:${COLOR.tertiary};padding:0 4px;background:${COLOR.bg};border-radius:2px">${esc(item.type)}</span>`;
328
- itemsHtml += `<span style="font-size:10px;color:${COLOR.tertiary};margin-left:auto;white-space:nowrap">${esc(rel)}</span>`;
329
- itemsHtml += `</div>`;
330
- itemsHtml += `<div style="font-size:11px;color:${COLOR.secondary};line-height:1.5">${esc(preview)}</div>`;
331
- itemsHtml += `</div>`;
332
- }
333
- const channelHeading = `#${esc(ch.channel)} (${ch.items.length} items)`;
334
- const channelGroup = createCollapsible(channelHeading, itemsHtml, {
335
- storageKey: `feed-channel-${name}-${ch.channel}`,
336
- defaultOpen: true,
337
- headingStyle: `font-size:12px;font-weight:600;color:${COLOR.primary};padding:10px 12px;background:${COLOR.bg};`,
338
- containerStyle: `margin-bottom:16px;border:1px solid ${COLOR.border};border-radius:4px;background:#fff;overflow:hidden;`,
339
- });
340
- container.appendChild(channelGroup);
341
- }
342
- }
343
- destroy() {
344
- this.selectedConnector = null;
345
- this.cachedConnectors = [];
346
- this.mobileShowingDetail = false;
347
- if (this.resizeHandler) {
348
- window.removeEventListener('resize', this.resizeHandler);
349
- this.resizeHandler = null;
350
- }
351
- }
352
- }