polyai-agent 1.0.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 (142) hide show
  1. package/README.md +464 -0
  2. package/REQUIREMENTS.md +158 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +500 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/cluster-monitor/cluster-monitor.d.ts +49 -0
  8. package/dist/cluster-monitor/cluster-monitor.d.ts.map +1 -0
  9. package/dist/cluster-monitor/cluster-monitor.js +374 -0
  10. package/dist/cluster-monitor/cluster-monitor.js.map +1 -0
  11. package/dist/cluster-monitor/index.d.ts +9 -0
  12. package/dist/cluster-monitor/index.d.ts.map +1 -0
  13. package/dist/cluster-monitor/index.js +19 -0
  14. package/dist/cluster-monitor/index.js.map +1 -0
  15. package/dist/cluster-monitor/kubernetes-connector.d.ts +21 -0
  16. package/dist/cluster-monitor/kubernetes-connector.d.ts.map +1 -0
  17. package/dist/cluster-monitor/kubernetes-connector.js +109 -0
  18. package/dist/cluster-monitor/kubernetes-connector.js.map +1 -0
  19. package/dist/cluster-monitor/notifications.d.ts +26 -0
  20. package/dist/cluster-monitor/notifications.d.ts.map +1 -0
  21. package/dist/cluster-monitor/notifications.js +182 -0
  22. package/dist/cluster-monitor/notifications.js.map +1 -0
  23. package/dist/cluster-monitor/remediation.d.ts +33 -0
  24. package/dist/cluster-monitor/remediation.d.ts.map +1 -0
  25. package/dist/cluster-monitor/remediation.js +134 -0
  26. package/dist/cluster-monitor/remediation.js.map +1 -0
  27. package/dist/cluster-monitor/rules.d.ts +26 -0
  28. package/dist/cluster-monitor/rules.d.ts.map +1 -0
  29. package/dist/cluster-monitor/rules.js +133 -0
  30. package/dist/cluster-monitor/rules.js.map +1 -0
  31. package/dist/cluster-monitor/types.d.ts +184 -0
  32. package/dist/cluster-monitor/types.d.ts.map +1 -0
  33. package/dist/cluster-monitor/types.js +3 -0
  34. package/dist/cluster-monitor/types.js.map +1 -0
  35. package/dist/index.d.ts +47 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +115 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/live-debugger/index.d.ts +32 -0
  40. package/dist/live-debugger/index.d.ts.map +1 -0
  41. package/dist/live-debugger/index.js +119 -0
  42. package/dist/live-debugger/index.js.map +1 -0
  43. package/dist/live-debugger/log-watcher.d.ts +19 -0
  44. package/dist/live-debugger/log-watcher.d.ts.map +1 -0
  45. package/dist/live-debugger/log-watcher.js +77 -0
  46. package/dist/live-debugger/log-watcher.js.map +1 -0
  47. package/dist/live-debugger/service-connector.d.ts +33 -0
  48. package/dist/live-debugger/service-connector.d.ts.map +1 -0
  49. package/dist/live-debugger/service-connector.js +123 -0
  50. package/dist/live-debugger/service-connector.js.map +1 -0
  51. package/dist/providers/anthropic.d.ts +9 -0
  52. package/dist/providers/anthropic.d.ts.map +1 -0
  53. package/dist/providers/anthropic.js +71 -0
  54. package/dist/providers/anthropic.js.map +1 -0
  55. package/dist/providers/base.d.ts +29 -0
  56. package/dist/providers/base.d.ts.map +1 -0
  57. package/dist/providers/base.js +14 -0
  58. package/dist/providers/base.js.map +1 -0
  59. package/dist/providers/gemini.d.ts +11 -0
  60. package/dist/providers/gemini.d.ts.map +1 -0
  61. package/dist/providers/gemini.js +73 -0
  62. package/dist/providers/gemini.js.map +1 -0
  63. package/dist/providers/index.d.ts +14 -0
  64. package/dist/providers/index.d.ts.map +1 -0
  65. package/dist/providers/index.js +38 -0
  66. package/dist/providers/index.js.map +1 -0
  67. package/dist/providers/openai.d.ts +9 -0
  68. package/dist/providers/openai.d.ts.map +1 -0
  69. package/dist/providers/openai.js +59 -0
  70. package/dist/providers/openai.js.map +1 -0
  71. package/dist/session/guardrails.d.ts +20 -0
  72. package/dist/session/guardrails.d.ts.map +1 -0
  73. package/dist/session/guardrails.js +83 -0
  74. package/dist/session/guardrails.js.map +1 -0
  75. package/dist/session/index.d.ts +6 -0
  76. package/dist/session/index.d.ts.map +1 -0
  77. package/dist/session/index.js +12 -0
  78. package/dist/session/index.js.map +1 -0
  79. package/dist/session/session-manager.d.ts +15 -0
  80. package/dist/session/session-manager.d.ts.map +1 -0
  81. package/dist/session/session-manager.js +89 -0
  82. package/dist/session/session-manager.js.map +1 -0
  83. package/dist/session/session.d.ts +63 -0
  84. package/dist/session/session.d.ts.map +1 -0
  85. package/dist/session/session.js +123 -0
  86. package/dist/session/session.js.map +1 -0
  87. package/dist/speckits/base.d.ts +9 -0
  88. package/dist/speckits/base.d.ts.map +1 -0
  89. package/dist/speckits/base.js +3 -0
  90. package/dist/speckits/base.js.map +1 -0
  91. package/dist/speckits/cluster-debugger.d.ts +3 -0
  92. package/dist/speckits/cluster-debugger.d.ts.map +1 -0
  93. package/dist/speckits/cluster-debugger.js +48 -0
  94. package/dist/speckits/cluster-debugger.js.map +1 -0
  95. package/dist/speckits/code-review.d.ts +3 -0
  96. package/dist/speckits/code-review.d.ts.map +1 -0
  97. package/dist/speckits/code-review.js +41 -0
  98. package/dist/speckits/code-review.js.map +1 -0
  99. package/dist/speckits/debugger.d.ts +3 -0
  100. package/dist/speckits/debugger.d.ts.map +1 -0
  101. package/dist/speckits/debugger.js +38 -0
  102. package/dist/speckits/debugger.js.map +1 -0
  103. package/dist/speckits/index.d.ts +11 -0
  104. package/dist/speckits/index.d.ts.map +1 -0
  105. package/dist/speckits/index.js +40 -0
  106. package/dist/speckits/index.js.map +1 -0
  107. package/dist/speckits/more-speckits.d.ts +6 -0
  108. package/dist/speckits/more-speckits.d.ts.map +1 -0
  109. package/dist/speckits/more-speckits.js +136 -0
  110. package/dist/speckits/more-speckits.js.map +1 -0
  111. package/dist/speckits/vibe-coder.d.ts +3 -0
  112. package/dist/speckits/vibe-coder.d.ts.map +1 -0
  113. package/dist/speckits/vibe-coder.js +32 -0
  114. package/dist/speckits/vibe-coder.js.map +1 -0
  115. package/dist/utils/config.d.ts +18 -0
  116. package/dist/utils/config.d.ts.map +1 -0
  117. package/dist/utils/config.js +107 -0
  118. package/dist/utils/config.js.map +1 -0
  119. package/dist/utils/file-ops.d.ts +15 -0
  120. package/dist/utils/file-ops.d.ts.map +1 -0
  121. package/dist/utils/file-ops.js +109 -0
  122. package/dist/utils/file-ops.js.map +1 -0
  123. package/dist/utils/logger.d.ts +4 -0
  124. package/dist/utils/logger.d.ts.map +1 -0
  125. package/dist/utils/logger.js +25 -0
  126. package/dist/utils/logger.js.map +1 -0
  127. package/dist/web/public/css/app.css +370 -0
  128. package/dist/web/public/index.html +91 -0
  129. package/dist/web/public/js/app.js +212 -0
  130. package/dist/web/routes/sessions.d.ts +4 -0
  131. package/dist/web/routes/sessions.d.ts.map +1 -0
  132. package/dist/web/routes/sessions.js +51 -0
  133. package/dist/web/routes/sessions.js.map +1 -0
  134. package/dist/web/routes/settings.d.ts +3 -0
  135. package/dist/web/routes/settings.d.ts.map +1 -0
  136. package/dist/web/routes/settings.js +33 -0
  137. package/dist/web/routes/settings.js.map +1 -0
  138. package/dist/web/server.d.ts +16 -0
  139. package/dist/web/server.d.ts.map +1 -0
  140. package/dist/web/server.js +76 -0
  141. package/dist/web/server.js.map +1 -0
  142. package/package.json +86 -0
@@ -0,0 +1,370 @@
1
+ :root {
2
+ --bg: #0f1117;
3
+ --surface: #1a1d27;
4
+ --surface2: #252836;
5
+ --border: #2e3147;
6
+ --accent: #6c63ff;
7
+ --accent-hover: #5a52d5;
8
+ --text: #e8eaf0;
9
+ --text-muted: #8b8fa8;
10
+ --danger: #e05252;
11
+ --success: #52c982;
12
+ --warning: #e0a852;
13
+ --radius: 8px;
14
+ --sidebar-width: 220px;
15
+ }
16
+
17
+ * { box-sizing: border-box; margin: 0; padding: 0; }
18
+
19
+ body {
20
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
21
+ background: var(--bg);
22
+ color: var(--text);
23
+ height: 100vh;
24
+ overflow: hidden;
25
+ }
26
+
27
+ #app {
28
+ display: flex;
29
+ height: 100vh;
30
+ }
31
+
32
+ /* Sidebar */
33
+ .sidebar {
34
+ width: var(--sidebar-width);
35
+ background: var(--surface);
36
+ border-right: 1px solid var(--border);
37
+ display: flex;
38
+ flex-direction: column;
39
+ flex-shrink: 0;
40
+ }
41
+
42
+ .sidebar-header {
43
+ padding: 20px 16px;
44
+ border-bottom: 1px solid var(--border);
45
+ }
46
+
47
+ .logo {
48
+ font-size: 1rem;
49
+ font-weight: 700;
50
+ letter-spacing: 0.02em;
51
+ }
52
+
53
+ .sidebar-nav {
54
+ display: flex;
55
+ flex-direction: column;
56
+ padding: 12px 8px;
57
+ gap: 4px;
58
+ }
59
+
60
+ .nav-item {
61
+ display: block;
62
+ padding: 10px 12px;
63
+ border-radius: var(--radius);
64
+ text-decoration: none;
65
+ color: var(--text-muted);
66
+ font-size: 0.9rem;
67
+ transition: background 0.15s, color 0.15s;
68
+ }
69
+ .nav-item:hover, .nav-item.active {
70
+ background: var(--surface2);
71
+ color: var(--text);
72
+ }
73
+
74
+ /* Main content */
75
+ .main-content {
76
+ flex: 1;
77
+ overflow-y: auto;
78
+ padding: 24px;
79
+ }
80
+
81
+ /* Pages */
82
+ .page { display: none; }
83
+ .page.active { display: block; }
84
+
85
+ .page-header {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: 16px;
89
+ margin-bottom: 24px;
90
+ }
91
+
92
+ .page-header h1 {
93
+ font-size: 1.4rem;
94
+ font-weight: 600;
95
+ flex: 1;
96
+ }
97
+
98
+ .header-actions {
99
+ display: flex;
100
+ gap: 8px;
101
+ }
102
+
103
+ /* Buttons */
104
+ .btn {
105
+ padding: 8px 16px;
106
+ border-radius: var(--radius);
107
+ border: none;
108
+ font-size: 0.875rem;
109
+ cursor: pointer;
110
+ font-weight: 500;
111
+ transition: background 0.15s;
112
+ white-space: nowrap;
113
+ }
114
+ .btn-primary { background: var(--accent); color: #fff; }
115
+ .btn-primary:hover { background: var(--accent-hover); }
116
+ .btn-secondary { background: var(--surface2); color: var(--text); border: 1px solid var(--border); }
117
+ .btn-secondary:hover { background: var(--border); }
118
+ .btn-danger { background: transparent; color: var(--danger); border: 1px solid var(--danger); }
119
+ .btn-danger:hover { background: var(--danger); color: #fff; }
120
+ .btn-ghost { background: transparent; color: var(--text-muted); }
121
+ .btn-ghost:hover { color: var(--text); }
122
+
123
+ /* Sessions list */
124
+ .sessions-list {
125
+ display: grid;
126
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
127
+ gap: 16px;
128
+ }
129
+
130
+ .session-card {
131
+ background: var(--surface);
132
+ border: 1px solid var(--border);
133
+ border-radius: var(--radius);
134
+ padding: 16px;
135
+ cursor: pointer;
136
+ transition: border-color 0.15s, transform 0.1s;
137
+ }
138
+ .session-card:hover {
139
+ border-color: var(--accent);
140
+ transform: translateY(-1px);
141
+ }
142
+
143
+ .session-card-header {
144
+ display: flex;
145
+ align-items: flex-start;
146
+ gap: 12px;
147
+ margin-bottom: 8px;
148
+ }
149
+
150
+ .session-status {
151
+ width: 10px;
152
+ height: 10px;
153
+ border-radius: 50%;
154
+ margin-top: 5px;
155
+ flex-shrink: 0;
156
+ }
157
+ .status-active { background: var(--success); box-shadow: 0 0 6px var(--success); }
158
+ .status-paused { background: var(--warning); }
159
+ .status-completed { background: var(--text-muted); }
160
+
161
+ .session-name {
162
+ font-weight: 600;
163
+ font-size: 0.95rem;
164
+ }
165
+ .session-meta {
166
+ font-size: 0.8rem;
167
+ color: var(--text-muted);
168
+ margin-top: 2px;
169
+ }
170
+ .session-tags {
171
+ display: flex;
172
+ gap: 6px;
173
+ flex-wrap: wrap;
174
+ margin-top: 10px;
175
+ }
176
+ .tag {
177
+ font-size: 0.75rem;
178
+ background: var(--surface2);
179
+ border: 1px solid var(--border);
180
+ padding: 2px 8px;
181
+ border-radius: 20px;
182
+ color: var(--text-muted);
183
+ }
184
+
185
+ .loading {
186
+ color: var(--text-muted);
187
+ font-size: 0.9rem;
188
+ padding: 20px;
189
+ }
190
+
191
+ .empty-state {
192
+ text-align: center;
193
+ padding: 60px 20px;
194
+ color: var(--text-muted);
195
+ }
196
+ .empty-state h2 {
197
+ font-size: 1.1rem;
198
+ margin-bottom: 8px;
199
+ }
200
+ .empty-state p { font-size: 0.85rem; }
201
+
202
+ /* Session Detail */
203
+ .session-info {
204
+ background: var(--surface);
205
+ border: 1px solid var(--border);
206
+ border-radius: var(--radius);
207
+ padding: 16px;
208
+ margin-bottom: 20px;
209
+ display: grid;
210
+ grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
211
+ gap: 12px;
212
+ }
213
+ .session-info-item label {
214
+ font-size: 0.75rem;
215
+ color: var(--text-muted);
216
+ text-transform: uppercase;
217
+ letter-spacing: 0.05em;
218
+ display: block;
219
+ margin-bottom: 4px;
220
+ }
221
+ .session-info-item span {
222
+ font-size: 0.9rem;
223
+ font-weight: 500;
224
+ }
225
+
226
+ .guardrails-section, .turns-section {
227
+ margin-bottom: 24px;
228
+ }
229
+ .section-title {
230
+ font-size: 1rem;
231
+ font-weight: 600;
232
+ margin-bottom: 12px;
233
+ color: var(--text);
234
+ }
235
+
236
+ .guardrail-item {
237
+ background: var(--surface);
238
+ border: 1px solid var(--border);
239
+ border-radius: var(--radius);
240
+ padding: 10px 14px;
241
+ margin-bottom: 8px;
242
+ font-size: 0.85rem;
243
+ }
244
+ .guardrail-type {
245
+ font-size: 0.75rem;
246
+ color: var(--accent);
247
+ text-transform: uppercase;
248
+ margin-bottom: 4px;
249
+ }
250
+
251
+ .turn-item {
252
+ background: var(--surface);
253
+ border: 1px solid var(--border);
254
+ border-radius: var(--radius);
255
+ margin-bottom: 12px;
256
+ overflow: hidden;
257
+ }
258
+ .turn-header {
259
+ padding: 10px 14px;
260
+ background: var(--surface2);
261
+ font-size: 0.8rem;
262
+ color: var(--text-muted);
263
+ border-bottom: 1px solid var(--border);
264
+ }
265
+ .turn-messages {
266
+ padding: 14px;
267
+ }
268
+ .message {
269
+ margin-bottom: 12px;
270
+ }
271
+ .message-role {
272
+ font-size: 0.75rem;
273
+ text-transform: uppercase;
274
+ font-weight: 600;
275
+ margin-bottom: 4px;
276
+ }
277
+ .message-role.user { color: var(--accent); }
278
+ .message-role.assistant { color: var(--success); }
279
+ .message-content {
280
+ font-size: 0.875rem;
281
+ line-height: 1.5;
282
+ white-space: pre-wrap;
283
+ word-break: break-word;
284
+ }
285
+
286
+ .file-changes {
287
+ margin-top: 12px;
288
+ padding-top: 12px;
289
+ border-top: 1px solid var(--border);
290
+ }
291
+ .file-change-title {
292
+ font-size: 0.8rem;
293
+ color: var(--text-muted);
294
+ margin-bottom: 8px;
295
+ }
296
+ .file-change-item {
297
+ font-size: 0.8rem;
298
+ background: var(--bg);
299
+ border: 1px solid var(--border);
300
+ border-radius: 4px;
301
+ padding: 6px 10px;
302
+ margin-bottom: 4px;
303
+ font-family: monospace;
304
+ color: var(--warning);
305
+ }
306
+
307
+ /* Settings form */
308
+ .settings-form {
309
+ max-width: 480px;
310
+ }
311
+ .form-group {
312
+ margin-bottom: 20px;
313
+ }
314
+ .form-group label {
315
+ display: block;
316
+ font-size: 0.875rem;
317
+ font-weight: 500;
318
+ margin-bottom: 6px;
319
+ color: var(--text);
320
+ }
321
+ .form-group input,
322
+ .form-group select {
323
+ width: 100%;
324
+ padding: 9px 12px;
325
+ background: var(--surface);
326
+ border: 1px solid var(--border);
327
+ border-radius: var(--radius);
328
+ color: var(--text);
329
+ font-size: 0.875rem;
330
+ }
331
+ .form-group input:focus,
332
+ .form-group select:focus {
333
+ outline: none;
334
+ border-color: var(--accent);
335
+ }
336
+ .api-key-note p {
337
+ font-size: 0.8rem;
338
+ color: var(--text-muted);
339
+ background: var(--surface);
340
+ border: 1px solid var(--border);
341
+ border-radius: var(--radius);
342
+ padding: 12px;
343
+ line-height: 1.5;
344
+ }
345
+ .api-key-note code {
346
+ background: var(--surface2);
347
+ padding: 1px 5px;
348
+ border-radius: 3px;
349
+ font-family: monospace;
350
+ font-size: 0.8rem;
351
+ color: var(--accent);
352
+ }
353
+
354
+ /* Toast */
355
+ .toast {
356
+ position: fixed;
357
+ bottom: 24px;
358
+ right: 24px;
359
+ background: var(--surface2);
360
+ border: 1px solid var(--border);
361
+ border-radius: var(--radius);
362
+ padding: 12px 20px;
363
+ font-size: 0.875rem;
364
+ z-index: 100;
365
+ box-shadow: 0 4px 16px rgba(0,0,0,0.4);
366
+ transition: opacity 0.3s;
367
+ }
368
+ .toast.hidden { display: none; }
369
+ .toast.success { border-color: var(--success); color: var(--success); }
370
+ .toast.error { border-color: var(--danger); color: var(--danger); }
@@ -0,0 +1,91 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>AI Agent CLI — Session Manager</title>
7
+ <link rel="stylesheet" href="/css/app.css" />
8
+ </head>
9
+ <body>
10
+ <div id="app">
11
+ <aside class="sidebar">
12
+ <div class="sidebar-header">
13
+ <span class="logo">🤖 AI Agent CLI</span>
14
+ </div>
15
+ <nav class="sidebar-nav">
16
+ <a href="#sessions" class="nav-item active" data-page="sessions">Sessions</a>
17
+ <a href="#settings" class="nav-item" data-page="settings">Settings</a>
18
+ </nav>
19
+ </aside>
20
+
21
+ <main class="main-content">
22
+ <!-- Sessions Page -->
23
+ <section id="page-sessions" class="page active">
24
+ <div class="page-header">
25
+ <h1>Sessions</h1>
26
+ <button id="refresh-btn" class="btn btn-secondary">↻ Refresh</button>
27
+ </div>
28
+ <div id="sessions-list" class="sessions-list">
29
+ <div class="loading">Loading sessions…</div>
30
+ </div>
31
+ </section>
32
+
33
+ <!-- Session Detail Page -->
34
+ <section id="page-session-detail" class="page">
35
+ <div class="page-header">
36
+ <button id="back-btn" class="btn btn-ghost">← Back</button>
37
+ <h1 id="session-detail-title">Session</h1>
38
+ <div class="header-actions">
39
+ <button id="export-btn" class="btn btn-secondary">⬇ Export</button>
40
+ <button id="delete-btn" class="btn btn-danger">🗑 Delete</button>
41
+ </div>
42
+ </div>
43
+ <div id="session-detail-content"></div>
44
+ </section>
45
+
46
+ <!-- Settings Page -->
47
+ <section id="page-settings" class="page">
48
+ <div class="page-header">
49
+ <h1>Settings</h1>
50
+ </div>
51
+ <form id="settings-form" class="settings-form">
52
+ <div class="form-group">
53
+ <label for="provider">Default AI Provider</label>
54
+ <select id="provider" name="provider">
55
+ <option value="openai">OpenAI</option>
56
+ <option value="anthropic">Anthropic</option>
57
+ <option value="gemini">Google Gemini</option>
58
+ </select>
59
+ </div>
60
+ <div class="form-group">
61
+ <label for="model">Default Model</label>
62
+ <input type="text" id="model" name="model" placeholder="e.g. gpt-4o" />
63
+ </div>
64
+ <div class="form-group">
65
+ <label for="port">Web UI Port</label>
66
+ <input type="number" id="port" name="port" placeholder="3000" />
67
+ </div>
68
+ <div class="form-group">
69
+ <label for="logLevel">Log Level</label>
70
+ <select id="logLevel" name="logLevel">
71
+ <option value="info">info</option>
72
+ <option value="debug">debug</option>
73
+ <option value="warn">warn</option>
74
+ <option value="error">error</option>
75
+ </select>
76
+ </div>
77
+ <div class="form-group api-key-note">
78
+ <p>⚠️ API keys are configured via environment variables (<code>OPENAI_API_KEY</code>, <code>ANTHROPIC_API_KEY</code>, <code>GEMINI_API_KEY</code>) and are never stored in this interface.</p>
79
+ </div>
80
+ <button type="submit" class="btn btn-primary">Save Settings</button>
81
+ </form>
82
+ </section>
83
+ </main>
84
+ </div>
85
+
86
+ <div id="toast" class="toast hidden"></div>
87
+
88
+ <script src="/socket.io/socket.io.js"></script>
89
+ <script src="/js/app.js"></script>
90
+ </body>
91
+ </html>
@@ -0,0 +1,212 @@
1
+ /* UI application logic - vanilla JS for browser compatibility */
2
+ (function () {
3
+ const socket = io();
4
+ let currentSessionId = null;
5
+
6
+ // Navigation
7
+ document.querySelectorAll('.nav-item').forEach(function (link) {
8
+ link.addEventListener('click', function (e) {
9
+ e.preventDefault();
10
+ const page = link.getAttribute('data-page');
11
+ showPage(page);
12
+ document.querySelectorAll('.nav-item').forEach(function (l) { l.classList.remove('active'); });
13
+ link.classList.add('active');
14
+ });
15
+ });
16
+
17
+ function showPage(name) {
18
+ document.querySelectorAll('.page').forEach(function (p) { p.classList.remove('active'); });
19
+ const page = document.getElementById('page-' + name);
20
+ if (page) page.classList.add('active');
21
+ }
22
+
23
+ // Toast notifications
24
+ function showToast(message, type) {
25
+ const toast = document.getElementById('toast');
26
+ toast.textContent = message;
27
+ toast.className = 'toast ' + (type || '');
28
+ setTimeout(function () { toast.className = 'toast hidden'; }, 3000);
29
+ }
30
+
31
+ // --- Sessions ---
32
+ function loadSessions() {
33
+ fetch('/api/sessions')
34
+ .then(function (r) { return r.json(); })
35
+ .then(function (data) { renderSessions(data.sessions || []); })
36
+ .catch(function (err) {
37
+ document.getElementById('sessions-list').innerHTML =
38
+ '<div class="loading">Error loading sessions: ' + err.message + '</div>';
39
+ });
40
+ }
41
+
42
+ function renderSessions(sessions) {
43
+ const container = document.getElementById('sessions-list');
44
+ if (!sessions.length) {
45
+ container.innerHTML = '<div class="empty-state"><h2>No sessions yet</h2><p>Start a session from the CLI with <code>ai-agent chat</code></p></div>';
46
+ return;
47
+ }
48
+ container.innerHTML = sessions.map(function (s) {
49
+ const statusClass = 'status-' + s.status;
50
+ const turns = (s.turns || []).length;
51
+ const updated = new Date(s.updatedAt).toLocaleString();
52
+ return '<div class="session-card" data-id="' + s.id + '">' +
53
+ '<div class="session-card-header">' +
54
+ '<div class="session-status ' + statusClass + '"></div>' +
55
+ '<div>' +
56
+ '<div class="session-name">' + escHtml(s.name) + '</div>' +
57
+ '<div class="session-meta">' + turns + ' turns · Updated ' + updated + '</div>' +
58
+ '</div>' +
59
+ '</div>' +
60
+ '<div class="session-tags">' +
61
+ '<span class="tag">' + escHtml(s.config.provider) + '</span>' +
62
+ '<span class="tag">' + escHtml(s.config.model || 'default') + '</span>' +
63
+ (s.config.speckit ? '<span class="tag">' + escHtml(s.config.speckit) + '</span>' : '') +
64
+ '</div>' +
65
+ '</div>';
66
+ }).join('');
67
+
68
+ document.querySelectorAll('.session-card').forEach(function (card) {
69
+ card.addEventListener('click', function () {
70
+ openSession(card.getAttribute('data-id'));
71
+ });
72
+ });
73
+ }
74
+
75
+ function openSession(id) {
76
+ currentSessionId = id;
77
+ fetch('/api/sessions/' + id)
78
+ .then(function (r) { return r.json(); })
79
+ .then(function (data) { renderSessionDetail(data); })
80
+ .catch(function (err) { showToast('Error: ' + err.message, 'error'); });
81
+ }
82
+
83
+ function renderSessionDetail(session) {
84
+ document.getElementById('session-detail-title').textContent = session.name;
85
+ showPage('session-detail');
86
+
87
+ const guardrails = (session.config.guardrails || []);
88
+ const turns = (session.turns || []);
89
+
90
+ const html =
91
+ '<div class="session-info">' +
92
+ infoItem('ID', session.id) +
93
+ infoItem('Status', session.status) +
94
+ infoItem('Provider', session.config.provider) +
95
+ infoItem('Model', session.config.model || 'default') +
96
+ infoItem('Speckit', session.config.speckit || '—') +
97
+ infoItem('Created', new Date(session.createdAt).toLocaleString()) +
98
+ '</div>' +
99
+
100
+ (guardrails.length ? '<div class="guardrails-section"><div class="section-title">Guardrails (' + guardrails.length + ')</div>' +
101
+ guardrails.map(function (g) {
102
+ return '<div class="guardrail-item"><div class="guardrail-type">' + escHtml(g.type) + '</div>' +
103
+ (g.description || '') + ' ' + JSON.stringify(g.value) + '</div>';
104
+ }).join('') + '</div>' : '') +
105
+
106
+ '<div class="turns-section"><div class="section-title">Conversation (' + turns.length + ' turns)</div>' +
107
+ (turns.length === 0 ? '<div class="loading">No conversation yet</div>' :
108
+ turns.map(function (t) {
109
+ const fileChanges = (t.fileChanges || []);
110
+ return '<div class="turn-item">' +
111
+ '<div class="turn-header">' + new Date(t.timestamp).toLocaleString() +
112
+ (t.usage ? ' · ' + t.usage.totalTokens + ' tokens' : '') + '</div>' +
113
+ '<div class="turn-messages">' +
114
+ '<div class="message"><div class="message-role user">You</div>' +
115
+ '<div class="message-content">' + escHtml(t.userMessage) + '</div></div>' +
116
+ '<div class="message"><div class="message-role assistant">Assistant</div>' +
117
+ '<div class="message-content">' + escHtml(t.assistantMessage.slice(0, 800)) +
118
+ (t.assistantMessage.length > 800 ? '…' : '') + '</div></div>' +
119
+ (fileChanges.length ? '<div class="file-changes"><div class="file-change-title">Files changed:</div>' +
120
+ fileChanges.map(function (fc) { return '<div class="file-change-item">' + escHtml(fc.filePath) + '</div>'; }).join('') +
121
+ '</div>' : '') +
122
+ '</div></div>';
123
+ }).join('')) +
124
+ '</div>';
125
+
126
+ document.getElementById('session-detail-content').innerHTML = html;
127
+
128
+ // Subscribe to real-time updates
129
+ socket.emit('subscribe:session', currentSessionId);
130
+ }
131
+
132
+ function infoItem(label, value) {
133
+ return '<div class="session-info-item"><label>' + label + '</label><span>' + escHtml(String(value)) + '</span></div>';
134
+ }
135
+
136
+ document.getElementById('back-btn').addEventListener('click', function () {
137
+ if (currentSessionId) socket.emit('unsubscribe:session', currentSessionId);
138
+ currentSessionId = null;
139
+ showPage('sessions');
140
+ loadSessions();
141
+ });
142
+
143
+ document.getElementById('refresh-btn').addEventListener('click', loadSessions);
144
+
145
+ document.getElementById('export-btn').addEventListener('click', function () {
146
+ if (currentSessionId) {
147
+ window.location.href = '/api/sessions/' + currentSessionId + '/export';
148
+ }
149
+ });
150
+
151
+ document.getElementById('delete-btn').addEventListener('click', function () {
152
+ if (!currentSessionId) return;
153
+ if (!confirm('Delete this session? This cannot be undone.')) return;
154
+ fetch('/api/sessions/' + currentSessionId, { method: 'DELETE' })
155
+ .then(function (r) { return r.json(); })
156
+ .then(function () {
157
+ showToast('Session deleted', 'success');
158
+ document.getElementById('back-btn').click();
159
+ })
160
+ .catch(function (err) { showToast('Error: ' + err.message, 'error'); });
161
+ });
162
+
163
+ // --- Settings ---
164
+ function loadSettings() {
165
+ fetch('/api/settings')
166
+ .then(function (r) { return r.json(); })
167
+ .then(function (data) {
168
+ const f = document.getElementById('settings-form');
169
+ if (data.provider) f.provider.value = data.provider;
170
+ if (data.model) f.model.value = data.model;
171
+ if (data.port) f.port.value = data.port;
172
+ if (data.logLevel) f.logLevel.value = data.logLevel;
173
+ });
174
+ }
175
+
176
+ document.getElementById('settings-form').addEventListener('submit', function (e) {
177
+ e.preventDefault();
178
+ const f = e.target;
179
+ const body = {
180
+ provider: f.provider.value,
181
+ model: f.model.value,
182
+ port: parseInt(f.port.value) || 3000,
183
+ logLevel: f.logLevel.value,
184
+ };
185
+ fetch('/api/settings', {
186
+ method: 'POST',
187
+ headers: { 'Content-Type': 'application/json' },
188
+ body: JSON.stringify(body),
189
+ })
190
+ .then(function () { showToast('Settings saved', 'success'); })
191
+ .catch(function (err) { showToast('Error: ' + err.message, 'error'); });
192
+ });
193
+
194
+ // Real-time session update
195
+ socket.on('session:updated', function (data) {
196
+ if (data.sessionId === currentSessionId) {
197
+ openSession(currentSessionId);
198
+ }
199
+ });
200
+
201
+ function escHtml(str) {
202
+ return String(str)
203
+ .replace(/&/g, '&amp;')
204
+ .replace(/</g, '&lt;')
205
+ .replace(/>/g, '&gt;')
206
+ .replace(/"/g, '&quot;');
207
+ }
208
+
209
+ // Init
210
+ loadSessions();
211
+ loadSettings();
212
+ })();
@@ -0,0 +1,4 @@
1
+ import { Router } from 'express';
2
+ import { SessionManager } from '../../session/session-manager';
3
+ export declare function createSessionRoutes(sessionManager: SessionManager): Router;
4
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../src/web/routes/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAqB,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAE/D,wBAAgB,mBAAmB,CAAC,cAAc,EAAE,cAAc,GAAG,MAAM,CA8C1E"}