@agentproto/runtime 2.10.1 → 2.11.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/README.md +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.mjs +639 -2841
- package/dist/index.mjs.map +1 -1
- package/dist/pr-provenance.d.ts +11 -1
- package/dist/pr-provenance.mjs +10 -1
- package/dist/pr-provenance.mjs.map +1 -1
- package/dist/resume-strategies.mjs.map +1 -1
- package/dist/session-story.d.ts +1 -1
- package/dist/session-story.mjs.map +1 -1
- package/package.json +12 -16
- package/dist/session-story-panel.d.ts +0 -26
- package/dist/session-story-panel.mjs +0 -970
- package/dist/session-story-panel.mjs.map +0 -1
|
@@ -1,970 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @agentproto/runtime v0.1.0-alpha
|
|
3
|
-
* Long-running gateway: MCP server + HTTP transport + HEARTBEAT autonomy + conversation persistence over a workspace dir.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
// src/panel-bridge.ts
|
|
7
|
-
function panelBridgeScript(appName) {
|
|
8
|
-
return `// \u2500\u2500 MCP Apps bridge (shared: panel-bridge.ts) \u2500\u2500
|
|
9
|
-
// JSON-RPC 2.0 over window.parent.postMessage \xB7 spec 2026-01-26
|
|
10
|
-
var _nextId = 1, _pending = {}, _notifyHandlers = [];
|
|
11
|
-
var _hostContext = null, _hostContextHandlers = [];
|
|
12
|
-
function post(msg){ window.parent.postMessage(msg, '*'); }
|
|
13
|
-
function getHostContext(){ return _hostContext; }
|
|
14
|
-
function onHostContext(cb){
|
|
15
|
-
_hostContextHandlers.push(cb);
|
|
16
|
-
// Replay the last context so a late subscriber isn't stuck blind.
|
|
17
|
-
if (_hostContext){ try { cb(_hostContext); } catch(_) {} }
|
|
18
|
-
}
|
|
19
|
-
function _setHostContext(ctx){
|
|
20
|
-
if (!ctx || typeof ctx !== 'object') return;
|
|
21
|
-
// ui/notifications/host-context-changed carries only the changed keys \u2014
|
|
22
|
-
// merge, matching the official ext-apps App behaviour.
|
|
23
|
-
_hostContext = Object.assign({}, _hostContext || {}, ctx);
|
|
24
|
-
for (var i = 0; i < _hostContextHandlers.length; i++){
|
|
25
|
-
try { _hostContextHandlers[i](_hostContext); } catch(_) {}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
function rpcRequest(method, params){
|
|
29
|
-
return new Promise(function(resolve, reject){
|
|
30
|
-
var id = _nextId++;
|
|
31
|
-
_pending[id] = {resolve: resolve, reject: reject};
|
|
32
|
-
post({jsonrpc: '2.0', id: id, method: method, params: params || {}});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
function rpcNotify(method, params){ post({jsonrpc: '2.0', method: method, params: params || {}}); }
|
|
36
|
-
function onHostNotification(cb){ _notifyHandlers.push(cb); }
|
|
37
|
-
window.addEventListener('message', function(evt){
|
|
38
|
-
var msg = evt.data;
|
|
39
|
-
if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;
|
|
40
|
-
if (msg.id != null && msg.method == null){
|
|
41
|
-
var p = _pending[msg.id];
|
|
42
|
-
if (!p) return;
|
|
43
|
-
delete _pending[msg.id];
|
|
44
|
-
if (msg.error) p.reject(new Error(msg.error.message || ('rpc error ' + msg.error.code)));
|
|
45
|
-
else p.resolve(msg.result);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
if (msg.method){
|
|
49
|
-
if (msg.method === 'ui/notifications/host-context-changed'){
|
|
50
|
-
_setHostContext(msg.params || {});
|
|
51
|
-
}
|
|
52
|
-
for (var i = 0; i < _notifyHandlers.length; i++){
|
|
53
|
-
try { _notifyHandlers[i](msg.method, msg.params || {}); } catch(_) {}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
function initBridge(){
|
|
58
|
-
return rpcRequest('ui/initialize', {
|
|
59
|
-
appInfo: {name: ${JSON.stringify(appName)}, version: '0.1.0'},
|
|
60
|
-
appCapabilities: {availableDisplayModes: ['inline', 'fullscreen', 'pip']},
|
|
61
|
-
protocolVersion: '2026-01-26'
|
|
62
|
-
}).then(function(result){
|
|
63
|
-
// The initialize result carries the initial hostContext (displayMode +
|
|
64
|
-
// availableDisplayModes) \u2014 capture it before notifying the host.
|
|
65
|
-
if (result && result.hostContext) _setHostContext(result.hostContext);
|
|
66
|
-
rpcNotify('ui/notifications/initialized', {});
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
function requestDisplayMode(mode){
|
|
70
|
-
return rpcRequest('ui/request-display-mode', {mode: mode});
|
|
71
|
-
}
|
|
72
|
-
function callTool(name, args){
|
|
73
|
-
return rpcRequest('tools/call', {name: name, arguments: args || {}}).then(function(result){
|
|
74
|
-
if (result.isError){
|
|
75
|
-
var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';
|
|
76
|
-
throw new Error(e);
|
|
77
|
-
}
|
|
78
|
-
var text = (result.content && result.content[0] && result.content[0].text) || '{}';
|
|
79
|
-
return JSON.parse(text);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// \u2500\u2500 Display-mode toggle buttons (NO auto-request) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
84
|
-
// Injected by the shared bridge so every panel gets them without touching
|
|
85
|
-
// its own markup. Mirrors guilde canvas.app.ts canvasShellHtml(): the
|
|
86
|
-
// panel stays inline by default; the user expands on demand. Buttons only
|
|
87
|
-
// appear for modes the host advertises in hostContext.availableDisplayModes.
|
|
88
|
-
(function(){
|
|
89
|
-
function mount(){
|
|
90
|
-
var style = document.createElement('style');
|
|
91
|
-
style.textContent = '#dm,#pin{display:none;position:fixed;top:8px;z-index:10;'
|
|
92
|
-
+ 'border:1px solid #d0d0d0;background:#fff;color:#1a1a1a;'
|
|
93
|
-
+ 'font:600 13px/1 system-ui,sans-serif;padding:7px 12px;border-radius:6px;'
|
|
94
|
-
+ 'cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.18)}'
|
|
95
|
-
+ '#dm{right:8px}#pin{right:118px}'
|
|
96
|
-
+ '#dm:hover,#pin:hover{background:#f2f2f2;border-color:#b0b0b0}'
|
|
97
|
-
+ '@media (prefers-color-scheme:dark){'
|
|
98
|
-
+ '#dm,#pin{border-color:#555;background:#2a2a2a;color:#f0f0f0;box-shadow:0 1px 4px rgba(0,0,0,.5)}'
|
|
99
|
-
+ '#dm:hover,#pin:hover{background:#333;border-color:#777}}';
|
|
100
|
-
document.head.appendChild(style);
|
|
101
|
-
|
|
102
|
-
var btn = document.createElement('button');
|
|
103
|
-
btn.id = 'dm'; btn.type = 'button'; btn.title = "Basculer l'affichage";
|
|
104
|
-
var pin = document.createElement('button');
|
|
105
|
-
pin.id = 'pin'; pin.type = 'button'; pin.title = '\xC9pingler sur le c\xF4t\xE9 (pip)';
|
|
106
|
-
document.body.appendChild(pin);
|
|
107
|
-
document.body.appendChild(btn);
|
|
108
|
-
|
|
109
|
-
function has(avail, m){ return !!avail && avail.indexOf(m) >= 0; }
|
|
110
|
-
|
|
111
|
-
// Re-sync button visibility + label from the current host context.
|
|
112
|
-
function syncBtn(ctx){
|
|
113
|
-
ctx = ctx || {};
|
|
114
|
-
var avail = ctx.availableDisplayModes;
|
|
115
|
-
// Diagnostic: what does THIS host actually advertise? (inline/fullscreen/pip)
|
|
116
|
-
console.log('[mcp-app] displayMode=', ctx.displayMode,
|
|
117
|
-
'availableDisplayModes=', avail);
|
|
118
|
-
|
|
119
|
-
// Fullscreen toggle button.
|
|
120
|
-
if (has(avail, 'fullscreen')){
|
|
121
|
-
btn.style.display = 'block';
|
|
122
|
-
btn.textContent = (ctx.displayMode === 'fullscreen') ? '\u2921 R\xE9duire' : '\u2922 Agrandir';
|
|
123
|
-
} else { btn.style.display = 'none'; }
|
|
124
|
-
|
|
125
|
-
// Dedicated pip ("pinned on side") button \u2014 only if the host advertises pip.
|
|
126
|
-
if (has(avail, 'pip')){
|
|
127
|
-
pin.style.display = 'block';
|
|
128
|
-
pin.textContent = (ctx.displayMode === 'pip') ? '\u2921 D\xE9tacher' : '\u{1F4CC} \xC9pingler';
|
|
129
|
-
} else { pin.style.display = 'none'; }
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
onHostContext(syncBtn);
|
|
133
|
-
|
|
134
|
-
btn.addEventListener('click', function(){
|
|
135
|
-
var ctx = getHostContext() || {};
|
|
136
|
-
var inPanel = (ctx.displayMode === 'fullscreen' || ctx.displayMode === 'pip');
|
|
137
|
-
requestDisplayMode(inPanel ? 'inline' : 'fullscreen').catch(function(){});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
pin.addEventListener('click', function(){
|
|
141
|
-
var ctx = getHostContext() || {};
|
|
142
|
-
requestDisplayMode(ctx.displayMode === 'pip' ? 'inline' : 'pip').catch(function(){});
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
|
-
if (document.body) mount();
|
|
146
|
-
else document.addEventListener('DOMContentLoaded', mount);
|
|
147
|
-
})();`;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// src/session-story-panel.ts
|
|
151
|
-
var SESSION_STORY_PANEL_HTML = `<!doctype html>
|
|
152
|
-
<html lang="fr">
|
|
153
|
-
<head>
|
|
154
|
-
<meta charset="utf-8" />
|
|
155
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
156
|
-
<title>session story</title>
|
|
157
|
-
<style>
|
|
158
|
-
:root {
|
|
159
|
-
color-scheme: light;
|
|
160
|
-
--bg:#faf8f5; --panel:#fffdfa; --line:#ece5da; --line-soft:#f2ede3;
|
|
161
|
-
--ink:#241f1a; --ink-mute:#7d7060; --ink-faint:#a9997f; --ink-ghost:#b3a893;
|
|
162
|
-
--accent:#0d7a4f; --accent-soft:#e8f4ec;
|
|
163
|
-
--gold:#a6701b; --gold-soft:#fff2dc;
|
|
164
|
-
--blue:#1d4e80; --blue-soft:#e9f1fb;
|
|
165
|
-
--violet:#5b3fa6; --violet-soft:#ede9ff;
|
|
166
|
-
--sel:#fbeccd; --red:#b3261e; --red-soft:#fbeae8;
|
|
167
|
-
}
|
|
168
|
-
* { box-sizing:border-box; }
|
|
169
|
-
html,body { height:100%; }
|
|
170
|
-
body { margin:0; font-family:ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif; background:var(--bg); color:var(--ink); -webkit-font-smoothing:antialiased; }
|
|
171
|
-
.app { height:100vh; display:flex; flex-direction:column; }
|
|
172
|
-
.hidden { display:none !important; }
|
|
173
|
-
|
|
174
|
-
/* \u2500\u2500 picker screen \u2500\u2500 */
|
|
175
|
-
#pickerScreen { height:100vh; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:14px; padding:24px; }
|
|
176
|
-
#pickerScreen h1 { font-size:15px; font-weight:700; }
|
|
177
|
-
#pickerList { width:min(520px,90vw); max-height:60vh; overflow-y:auto; border:1px solid var(--line); border-radius:12px; background:var(--panel); }
|
|
178
|
-
.pk-item { padding:10px 14px; border-bottom:1px solid var(--line-soft); cursor:pointer; display:flex; align-items:center; gap:10px; }
|
|
179
|
-
.pk-item:last-child { border-bottom:none; }
|
|
180
|
-
.pk-item:hover { background:var(--line-soft); }
|
|
181
|
-
.pk-name { flex:1; min-width:0; font-size:13px; font-weight:600; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
182
|
-
.pk-meta { flex:none; font-size:10.5px; color:var(--ink-faint); font-weight:600; }
|
|
183
|
-
.pk-empty { padding:24px; text-align:center; color:var(--ink-mute); font-size:12.5px; }
|
|
184
|
-
.badge { display:inline-block; padding:1px 8px; border-radius:999px; font-size:10px; font-weight:700; }
|
|
185
|
-
.badge.running { background:var(--accent-soft); color:var(--accent); }
|
|
186
|
-
.badge.starting { background:var(--blue-soft); color:var(--blue); }
|
|
187
|
-
.badge.exited { background:var(--line-soft); color:var(--ink-faint); }
|
|
188
|
-
.badge.killed, .badge.error { background:var(--red-soft); color:var(--red); }
|
|
189
|
-
|
|
190
|
-
/* \u2500\u2500 big picture : mission + plan de sous-t\xE2ches \u2500\u2500 */
|
|
191
|
-
.hero { flex:none; padding:13px 20px 0; border-bottom:1px solid var(--line); background:var(--panel); }
|
|
192
|
-
.hero-top { display:flex; align-items:center; gap:13px; }
|
|
193
|
-
.pulse { width:10px; height:10px; border-radius:50%; background:var(--accent); flex:none;
|
|
194
|
-
box-shadow:0 0 0 0 rgba(13,122,79,.35); animation:pulse 2.4s infinite; }
|
|
195
|
-
.pulse.off { background:var(--ink-ghost); animation:none; }
|
|
196
|
-
@keyframes pulse { 70% { box-shadow:0 0 0 9px rgba(13,122,79,0); } 100% { box-shadow:0 0 0 0 rgba(13,122,79,0); } }
|
|
197
|
-
.who { min-width:0; flex:1; }
|
|
198
|
-
.who .h1 { font-size:14.5px; font-weight:700; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
199
|
-
.who .h2 { font-size:12px; color:var(--ink-mute); margin-top:1px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
200
|
-
.modewrap { display:flex; border:1px solid var(--line); border-radius:9px; overflow:hidden; flex:none; }
|
|
201
|
-
.modewrap button { border:none; background:var(--panel); color:var(--ink-mute); font-size:11px; font-weight:700; padding:6px 11px; cursor:pointer; }
|
|
202
|
-
.modewrap button.on { background:var(--ink); color:#fdf9f2; }
|
|
203
|
-
button.sim, a.sim { border:1px solid var(--line); background:var(--panel); color:var(--ink-mute); font-weight:700;
|
|
204
|
-
font-size:11.5px; border-radius:8px; padding:6px 12px; cursor:pointer; flex:none; }
|
|
205
|
-
button.sim.on { background:var(--ink); border-color:var(--ink); color:#fdf9f2; }
|
|
206
|
-
a.sim { display:inline-flex; align-items:center; text-decoration:none; }
|
|
207
|
-
a.sim:hover { border-color:var(--ink-ghost); color:var(--ink); }
|
|
208
|
-
|
|
209
|
-
/* plan strip : les sous-t\xE2ches, l'avancement d'un coup d'\u0153il */
|
|
210
|
-
.plan { display:flex; gap:6px; overflow-x:auto; padding:11px 0 12px; scrollbar-width:none; }
|
|
211
|
-
.plan::-webkit-scrollbar { display:none; }
|
|
212
|
-
.pt { flex:none; display:flex; align-items:center; gap:6px; font-size:11.5px; font-weight:700; padding:5px 11px;
|
|
213
|
-
border-radius:999px; border:1px solid var(--line); background:var(--bg); color:var(--ink-mute); cursor:pointer; white-space:nowrap; }
|
|
214
|
-
.pt:hover { border-color:var(--ink-ghost); }
|
|
215
|
-
.pt .st { font-size:10px; }
|
|
216
|
-
.pt.done { color:var(--accent); background:var(--accent-soft); border-color:transparent; }
|
|
217
|
-
.pt.cur { color:var(--gold); background:var(--gold-soft); border-color:transparent; }
|
|
218
|
-
.pt.cur .st { animation:blink 1.6s infinite; }
|
|
219
|
-
@keyframes blink { 50% { opacity:.35; } }
|
|
220
|
-
|
|
221
|
-
/* \u2500\u2500 corps \u2500\u2500 */
|
|
222
|
-
.body { flex:1; display:flex; min-height:0; }
|
|
223
|
-
.feedcol { flex:1; min-width:320px; display:flex; flex-direction:column; }
|
|
224
|
-
.feed { flex:1; overflow-y:auto; padding:4px 14px 10px; display:flex; flex-direction:column; scroll-behavior:smooth; }
|
|
225
|
-
.fspacer { flex:1; }
|
|
226
|
-
|
|
227
|
-
/* chapitres */
|
|
228
|
-
.chap { flex:none; position:sticky; top:0; z-index:5; margin:8px -4px 2px; padding:7px 12px; display:flex; align-items:center; gap:9px;
|
|
229
|
-
background:color-mix(in srgb, var(--bg) 88%, transparent); backdrop-filter:blur(6px);
|
|
230
|
-
border-radius:9px; cursor:pointer; font-size:11.5px; font-weight:800; letter-spacing:.03em; color:var(--ink-mute); }
|
|
231
|
-
.chap:hover { color:var(--ink); }
|
|
232
|
-
.chap .cst { flex:none; width:17px; height:17px; border-radius:50%; display:grid; place-items:center; font-size:9.5px; font-weight:900; }
|
|
233
|
-
.chap.done .cst { background:var(--accent-soft); color:var(--accent); }
|
|
234
|
-
.chap.cur .cst { background:var(--gold-soft); color:var(--gold); }
|
|
235
|
-
.chap .cnum { color:var(--ink-ghost); font-weight:700; }
|
|
236
|
-
.chap .csum { flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
237
|
-
.chap .cmeta { flex:none; font-size:10.5px; color:var(--ink-ghost); font-weight:600; }
|
|
238
|
-
.chap .cchev { flex:none; color:var(--ink-ghost); transition:transform .15s; }
|
|
239
|
-
.chap.open .cchev { transform:rotate(90deg); }
|
|
240
|
-
|
|
241
|
-
.row { flex:none; min-height:44px; margin:1px 0 1px 10px; padding:5px 12px 5px 10px; display:flex; align-items:center; gap:11px;
|
|
242
|
-
cursor:pointer; border-radius:10px; border-left:3px solid transparent; transition:background .12s; }
|
|
243
|
-
.row:hover { background:var(--line-soft); }
|
|
244
|
-
.row[aria-selected="true"] { background:var(--sel); border-left-color:var(--gold); }
|
|
245
|
-
.row .ico { width:24px; height:24px; border-radius:8px; flex:none; display:grid; place-items:center; font-size:11.5px; font-weight:800; }
|
|
246
|
-
.ico.k-text { background:var(--blue-soft); color:var(--blue); }
|
|
247
|
-
.ico.k-edit { background:var(--gold-soft); color:var(--gold); }
|
|
248
|
-
.ico.k-bash { background:var(--accent-soft); color:var(--accent); }
|
|
249
|
-
.ico.k-read { background:var(--violet-soft); color:var(--violet); }
|
|
250
|
-
.ico.k-user { background:var(--ink); color:#fdf9f2; }
|
|
251
|
-
.row .mid { flex:1; min-width:0; }
|
|
252
|
-
.row .sum { display:block; font-size:13.5px; line-height:1.35; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
|
253
|
-
.row .raw1 { display:block; font-size:10.5px; color:var(--ink-faint); font-family:ui-monospace,Menlo,monospace;
|
|
254
|
-
white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }
|
|
255
|
-
body:not(.tech) .row .raw1 { display:none; }
|
|
256
|
-
.row .route { display:inline-block; font-size:10px; font-weight:800; padding:1px 8px; border-radius:999px; margin-top:2px; }
|
|
257
|
-
.route.cont { background:var(--blue-soft); color:var(--blue); }
|
|
258
|
-
.route.newt { background:var(--gold-soft); color:var(--gold); }
|
|
259
|
-
.row .cnt { flex:none; font-size:10px; font-weight:800; color:var(--gold); background:var(--gold-soft); padding:2px 7px; border-radius:999px; }
|
|
260
|
-
.row .ts { flex:none; font-size:10.5px; color:var(--ink-ghost); font-variant-numeric:tabular-nums; }
|
|
261
|
-
@keyframes slidein { from { opacity:0; transform:translateY(6px); } }
|
|
262
|
-
.row.new { animation:slidein .25s ease-out; }
|
|
263
|
-
|
|
264
|
-
/* \u2500\u2500 panneau ancr\xE9 \u2500\u2500 */
|
|
265
|
-
.panel { flex:none; width:0; overflow:hidden; border-left:1px solid transparent; background:var(--panel);
|
|
266
|
-
display:flex; flex-direction:column; transition:width .22s ease, border-color .22s; }
|
|
267
|
-
.panel.open { width:min(430px,46vw); border-left-color:var(--line); }
|
|
268
|
-
.panel-inner { width:min(430px,46vw); flex:1; display:flex; flex-direction:column; min-height:0; }
|
|
269
|
-
.phead { flex:none; padding:14px 16px 12px; border-bottom:1px solid var(--line); display:flex; align-items:flex-start; gap:11px; }
|
|
270
|
-
.phead .ico { width:28px; height:28px; font-size:13px; border-radius:9px; }
|
|
271
|
-
.phead .tt { min-width:0; flex:1; }
|
|
272
|
-
.phead .t { font-size:14px; font-weight:700; line-height:1.4; }
|
|
273
|
-
.phead .s { font-size:11px; color:var(--ink-faint); margin-top:3px; font-variant-numeric:tabular-nums; }
|
|
274
|
-
.pnav { display:flex; gap:4px; flex:none; }
|
|
275
|
-
.pnav button { width:26px; height:26px; border:1px solid var(--line); background:var(--panel); border-radius:8px;
|
|
276
|
-
color:var(--ink-mute); font-size:12px; cursor:pointer; display:grid; place-items:center; }
|
|
277
|
-
.pnav button:disabled { opacity:.3; cursor:default; }
|
|
278
|
-
.pbody { flex:1; overflow-y:auto; padding:16px; display:flex; flex-direction:column; gap:14px; }
|
|
279
|
-
.plain { font-size:14px; line-height:1.7; }
|
|
280
|
-
.plain .why { margin-top:8px; font-size:12.5px; color:var(--ink-mute); line-height:1.6; }
|
|
281
|
-
.facts { display:flex; flex-wrap:wrap; gap:6px; }
|
|
282
|
-
.fact { font-size:11px; font-weight:700; background:var(--bg); border:1px solid var(--line); color:var(--ink-mute); padding:4px 10px; border-radius:999px; }
|
|
283
|
-
.fact.ok { background:var(--accent-soft); border-color:transparent; color:var(--accent); }
|
|
284
|
-
details.techbox { border:1px solid var(--line); border-radius:12px; background:var(--bg); overflow:hidden; }
|
|
285
|
-
details.techbox summary { list-style:none; cursor:pointer; padding:10px 14px; font-size:11.5px; font-weight:800;
|
|
286
|
-
letter-spacing:.04em; text-transform:uppercase; color:var(--ink-faint); display:flex; align-items:center; gap:8px; }
|
|
287
|
-
details.techbox summary::-webkit-details-marker { display:none; }
|
|
288
|
-
details.techbox summary::after { content:"\u25B8"; margin-left:auto; transition:transform .15s; }
|
|
289
|
-
details.techbox[open] summary::after { transform:rotate(90deg); }
|
|
290
|
-
.techlist { padding:0 12px 12px; display:flex; flex-direction:column; gap:8px; }
|
|
291
|
-
.titem { border:1px solid var(--line); border-radius:10px; background:var(--panel); overflow:hidden; }
|
|
292
|
-
.titem .th { padding:8px 12px; font-size:11.5px; font-weight:700; color:var(--ink-mute); display:flex; align-items:center; gap:8px; }
|
|
293
|
-
.titem .th .copy { margin-left:auto; border:none; background:none; color:var(--ink-ghost); font-size:11px; cursor:pointer; padding:2px 4px; border-radius:5px; }
|
|
294
|
-
.titem .th .copy:hover { color:var(--ink); background:var(--line-soft); }
|
|
295
|
-
.titem pre { margin:0; border-top:1px solid var(--line-soft); font-family:ui-monospace,Menlo,monospace; font-size:11.5px;
|
|
296
|
-
line-height:1.55; color:#4a4236; padding:9px 12px; overflow:auto; max-height:240px; white-space:pre-wrap; word-break:break-word; }
|
|
297
|
-
.d-text { font-size:13.5px; line-height:1.7; }
|
|
298
|
-
.d-text p { margin:0 0 8px; }
|
|
299
|
-
.d-text p:last-child { margin-bottom:0; }
|
|
300
|
-
.d-text h1, .d-text h2, .d-text h3, .d-text h4, .d-text h5, .d-text h6 { margin:12px 0 6px; line-height:1.3; }
|
|
301
|
-
.d-text h1:first-child, .d-text h2:first-child, .d-text h3:first-child { margin-top:0; }
|
|
302
|
-
.d-text ul, .d-text ol { margin:0 0 8px; padding-left:20px; }
|
|
303
|
-
.d-text code { font-family:ui-monospace,Menlo,monospace; font-size:12.5px; background:var(--bg); border-radius:4px; padding:1px 5px; }
|
|
304
|
-
.d-text pre { margin:0 0 8px; background:var(--bg); border:1px solid var(--line); border-radius:8px; padding:9px 12px; overflow:auto; }
|
|
305
|
-
.d-text pre code { background:none; border-radius:0; padding:0; }
|
|
306
|
-
.d-text table { border-collapse:collapse; margin:0 0 8px; font-size:12.5px; }
|
|
307
|
-
.d-text th, .d-text td { border:1px solid var(--line); padding:4px 8px; text-align:left; }
|
|
308
|
-
.d-text a { color:var(--blue); }
|
|
309
|
-
.pfoot { flex:none; border-top:1px solid var(--line); padding:9px 16px; font-size:11px; color:var(--ink-ghost); display:flex; gap:10px; }
|
|
310
|
-
.kbd { font-family:ui-monospace,Menlo,monospace; font-size:10px; border:1px solid var(--line); border-bottom-width:2px;
|
|
311
|
-
border-radius:5px; padding:1px 5px; background:var(--panel); color:var(--ink-mute); }
|
|
312
|
-
|
|
313
|
-
/* \u2500\u2500 bo\xEEte d'envoi + routage IA \u2500\u2500 */
|
|
314
|
-
.composer { flex:none; border-top:1px solid var(--line); background:var(--panel); padding:10px 14px; }
|
|
315
|
-
.composer .cbar { display:flex; gap:8px; }
|
|
316
|
-
.composer textarea { flex:1; resize:none; border:1px solid var(--line); border-radius:10px; padding:9px 12px; font:inherit; font-size:13px; max-height:110px; background:var(--bg); }
|
|
317
|
-
.composer textarea:focus { outline:2px solid #241f1a22; }
|
|
318
|
-
.composer textarea:disabled { opacity:.5; cursor:not-allowed; }
|
|
319
|
-
.composer button { border:none; border-radius:10px; padding:0 16px; background:var(--ink); color:#fdf9f2; font-weight:700; font-size:13px; cursor:pointer; }
|
|
320
|
-
.composer button:disabled { opacity:.4; cursor:not-allowed; }
|
|
321
|
-
.composer .routing { font-size:11px; color:var(--ink-faint); padding:6px 2px 0; min-height:22px; }
|
|
322
|
-
.composer .routing .r-cont { color:var(--blue); font-weight:700; }
|
|
323
|
-
.composer .routing .r-newt { color:var(--gold); font-weight:700; }
|
|
324
|
-
#statusbar { flex:none; padding:4px 20px; font-size:10.5px; color:var(--ink-ghost); border-top:1px solid var(--line-soft); }
|
|
325
|
-
</style>
|
|
326
|
-
</head>
|
|
327
|
-
<body>
|
|
328
|
-
<div id="pickerScreen">
|
|
329
|
-
<h1>Choisis une session</h1>
|
|
330
|
-
<div id="pickerList"><div class="pk-empty">Connexion…</div></div>
|
|
331
|
-
</div>
|
|
332
|
-
|
|
333
|
-
<div class="app hidden" id="storyScreen">
|
|
334
|
-
<div class="hero">
|
|
335
|
-
<div class="hero-top">
|
|
336
|
-
<span class="pulse" id="pulse"></span>
|
|
337
|
-
<div class="who">
|
|
338
|
-
<div class="h1" id="heroTitle"></div>
|
|
339
|
-
<div class="h2" id="heroSub"></div>
|
|
340
|
-
</div>
|
|
341
|
-
<div class="modewrap"><button id="modeSimple" class="on" type="button">Simple</button><button id="modeTech" type="button">Tech</button></div>
|
|
342
|
-
<a class="sim" id="fullPanelLink" href="#" target="_blank" rel="noopener" title="Ouvrir le panneau complet (Terminal/Chat/JSON/TTY)">↗ panneau complet</a>
|
|
343
|
-
<button class="sim" id="switchBtn" type="button">⇆ changer</button>
|
|
344
|
-
</div>
|
|
345
|
-
<div class="plan" id="plan"></div>
|
|
346
|
-
</div>
|
|
347
|
-
|
|
348
|
-
<div class="body">
|
|
349
|
-
<div class="feedcol">
|
|
350
|
-
<div class="feed" id="feed"><div class="fspacer"></div><div id="rows"></div></div>
|
|
351
|
-
<div class="composer">
|
|
352
|
-
<div class="cbar">
|
|
353
|
-
<textarea id="msgBox" rows="1" placeholder="\xC9cris \xE0 l'agent\u2026 (la surcouche classe ton message : suite de la sous-t\xE2che ou nouvelle sous-t\xE2che)"></textarea>
|
|
354
|
-
<button id="sendBtn" type="button">Envoyer</button>
|
|
355
|
-
</div>
|
|
356
|
-
<div class="routing" id="routing"></div>
|
|
357
|
-
</div>
|
|
358
|
-
</div>
|
|
359
|
-
|
|
360
|
-
<aside class="panel" id="panel" aria-label="D\xE9tail de l'\xE9tape">
|
|
361
|
-
<div class="panel-inner">
|
|
362
|
-
<div class="phead">
|
|
363
|
-
<span class="ico" id="pIco"></span>
|
|
364
|
-
<div class="tt"><div class="t" id="pTitle"></div><div class="s" id="pSub"></div></div>
|
|
365
|
-
<div class="pnav"><button id="pPrev" type="button">\u2191</button><button id="pNext" type="button">\u2193</button><button id="pClose" type="button">\u2715</button></div>
|
|
366
|
-
</div>
|
|
367
|
-
<div class="pbody" id="pBody"></div>
|
|
368
|
-
<div class="pfoot"><span class="kbd">\u2191</span><span class="kbd">\u2193</span> naviguer \xB7 <span class="kbd">Esc</span> fermer</div>
|
|
369
|
-
</div>
|
|
370
|
-
</aside>
|
|
371
|
-
</div>
|
|
372
|
-
<div id="statusbar"></div>
|
|
373
|
-
</div>
|
|
374
|
-
|
|
375
|
-
<script>
|
|
376
|
-
var $=function(id){ return document.getElementById(id); };
|
|
377
|
-
var esc=function(s){ return String(s==null?"":s).replace(/[&<>]/g,function(c){ return {"&":"&","<":"<",">":">"}[c]; }); };
|
|
378
|
-
|
|
379
|
-
// ============================================================
|
|
380
|
-
// renderMd \u2014 vanilla-JS port of markdown-lite.ts. Kept
|
|
381
|
-
// function-for-function identical so the two are easy to diff (same
|
|
382
|
-
// self-contained-panel constraint as buildStoryJs below): headers,
|
|
383
|
-
// bold/italic, inline/fenced code, bullet/numbered lists, pipe tables and
|
|
384
|
-
// links, with every raw text run HTML-escaped before any generated tag
|
|
385
|
-
// wraps it.
|
|
386
|
-
// ============================================================
|
|
387
|
-
function escHtmlMd(s){ return String(s).replace(/[&<>"]/g,function(c){ if(c==='&') return '&'; if(c==='<') return '<'; if(c==='>') return '>'; return '"'; }); }
|
|
388
|
-
function renderInlineMd(text){
|
|
389
|
-
var out=escHtmlMd(text);
|
|
390
|
-
out=out.replace(/\`([^\`]+)\`/g,function(_m,code){ return '<code>'+code+'</code>'; });
|
|
391
|
-
out=out.replace(/\\[([^\\]]+)\\]\\((https?:\\/\\/[^\\s)]+)\\)/g,function(_m,label,url){ return '<a href="'+url+'" target="_blank" rel="noopener noreferrer">'+label+'</a>'; });
|
|
392
|
-
out=out.replace(/\\*\\*([^*]+)\\*\\*/g,'<strong>$1</strong>');
|
|
393
|
-
out=out.replace(/(^|[^*])\\*([^*]+)\\*(?!\\*)/g,'$1<em>$2</em>');
|
|
394
|
-
return out;
|
|
395
|
-
}
|
|
396
|
-
function isTableSepMd(line){ return /^\\s*\\|?\\s*:?-+:?\\s*(\\|\\s*:?-+:?\\s*)+\\|?\\s*$/.test(line); }
|
|
397
|
-
function splitRowMd(line){ return line.trim().replace(/^\\|/,'').replace(/\\|$/,'').split('|').map(function(c){ return c.trim(); }); }
|
|
398
|
-
function renderMd(md){
|
|
399
|
-
var lines=String(md==null?'':md).replace(/\\r\\n?/g,'\\n').split('\\n');
|
|
400
|
-
var out=[], para=[], list=null;
|
|
401
|
-
function flushPara(){ if(para.length){ out.push('<p>'+para.map(renderInlineMd).join('<br>')+'</p>'); para=[]; } }
|
|
402
|
-
function flushList(){ if(list){ var tag=list.ordered?'ol':'ul'; out.push('<'+tag+'>'+list.items.map(function(i){ return '<li>'+renderInlineMd(i)+'</li>'; }).join('')+'</'+tag+'>'); list=null; } }
|
|
403
|
-
function flushAll(){ flushPara(); flushList(); }
|
|
404
|
-
var i=0;
|
|
405
|
-
while(i<lines.length){
|
|
406
|
-
var line=lines[i];
|
|
407
|
-
if(/^\\s*\`\`\`/.test(line)){
|
|
408
|
-
flushAll();
|
|
409
|
-
var code=[]; i+=1;
|
|
410
|
-
while(i<lines.length && !/^\\s*\`\`\`/.test(lines[i])){ code.push(lines[i]); i+=1; }
|
|
411
|
-
i+=1;
|
|
412
|
-
out.push('<pre><code>'+escHtmlMd(code.join('\\n'))+'</code></pre>');
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
var header=line.match(/^(#{1,6})\\s+(.*)$/);
|
|
416
|
-
if(header){
|
|
417
|
-
flushAll();
|
|
418
|
-
var level=header[1].length;
|
|
419
|
-
out.push('<h'+level+'>'+renderInlineMd(header[2].trim())+'</h'+level+'>');
|
|
420
|
-
i+=1;
|
|
421
|
-
continue;
|
|
422
|
-
}
|
|
423
|
-
if(/^\\s*\\|/.test(line) && i+1<lines.length && isTableSepMd(lines[i+1])){
|
|
424
|
-
flushAll();
|
|
425
|
-
var headCells=splitRowMd(line);
|
|
426
|
-
i+=2;
|
|
427
|
-
var bodyRows=[];
|
|
428
|
-
while(i<lines.length && /^\\s*\\|/.test(lines[i])){ bodyRows.push(splitRowMd(lines[i])); i+=1; }
|
|
429
|
-
out.push('<table><thead><tr>'+headCells.map(function(c){ return '<th>'+renderInlineMd(c)+'</th>'; }).join('')+'</tr></thead><tbody>'
|
|
430
|
-
+bodyRows.map(function(r){ return '<tr>'+r.map(function(c){ return '<td>'+renderInlineMd(c)+'</td>'; }).join('')+'</tr>'; }).join('')+'</tbody></table>');
|
|
431
|
-
continue;
|
|
432
|
-
}
|
|
433
|
-
var bullet=line.match(/^\\s*[-*+]\\s+(.*)$/);
|
|
434
|
-
var numbered=line.match(/^\\s*\\d+\\.\\s+(.*)$/);
|
|
435
|
-
if(bullet || numbered){
|
|
436
|
-
flushPara();
|
|
437
|
-
var ordered=!!numbered;
|
|
438
|
-
var item=(bullet||numbered)[1];
|
|
439
|
-
if(!list || list.ordered!==ordered){ flushList(); list={ordered:ordered,items:[]}; }
|
|
440
|
-
list.items.push(item);
|
|
441
|
-
i+=1;
|
|
442
|
-
continue;
|
|
443
|
-
}
|
|
444
|
-
if(line.trim()===''){ flushAll(); i+=1; continue; }
|
|
445
|
-
flushList();
|
|
446
|
-
para.push(line);
|
|
447
|
-
i+=1;
|
|
448
|
-
}
|
|
449
|
-
flushAll();
|
|
450
|
-
return out.join('');
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
${panelBridgeScript("agentproto-session-story-panel")}
|
|
454
|
-
// Best-effort: some hosts forward the triggering tool call's arguments as
|
|
455
|
-
// a notification so the panel can auto-open the right session. Purely
|
|
456
|
-
// additive \u2014 the session picker is the reliable path when this never
|
|
457
|
-
// arrives.
|
|
458
|
-
var pendingSessionId=null;
|
|
459
|
-
onHostNotification(function(method, params){
|
|
460
|
-
if(/tool-input|tool-call/.test(method)){
|
|
461
|
-
var args=(params && (params.arguments || params.input)) || {};
|
|
462
|
-
if(args && args.sessionId) pendingSessionId=args.sessionId;
|
|
463
|
-
}
|
|
464
|
-
});
|
|
465
|
-
|
|
466
|
-
// ============================================================
|
|
467
|
-
// buildStory \u2014 vanilla-JS port of session-story.ts. Kept
|
|
468
|
-
// function-for-function identical so the two are easy to diff; the panel
|
|
469
|
-
// resource must be fully self-contained (no bundler/dynamic import), so it
|
|
470
|
-
// cannot import the TS module directly.
|
|
471
|
-
// ============================================================
|
|
472
|
-
|
|
473
|
-
var SALIENT_KEYS=["file_path","path","filePath","file","command","pattern","query","q","url","todos","description","prompt"];
|
|
474
|
-
function truncateStr(v,max){ var o=String(v).replace(/\\s+/g,' ').trim(); return o.length>max? o.slice(0,max-1)+'\u2026':o; }
|
|
475
|
-
function formatArgValue(v){
|
|
476
|
-
if(typeof v==='string') return v;
|
|
477
|
-
if(Array.isArray(v)) return v.length+' item'+(v.length===1?'':'s');
|
|
478
|
-
if(v && typeof v==='object') return JSON.stringify(v);
|
|
479
|
-
return String(v);
|
|
480
|
-
}
|
|
481
|
-
function pickSalient(args){
|
|
482
|
-
for(var i=0;i<SALIENT_KEYS.length;i++){
|
|
483
|
-
var k=SALIENT_KEYS[i], v=args[k];
|
|
484
|
-
if(v!==undefined && v!==null && v!=='') return formatArgValue(v);
|
|
485
|
-
}
|
|
486
|
-
return null;
|
|
487
|
-
}
|
|
488
|
-
function formatToolCall(name,args){
|
|
489
|
-
name=name||'tool';
|
|
490
|
-
args=(args && typeof args==='object' && !Array.isArray(args)) ? args : {};
|
|
491
|
-
var salient=pickSalient(args);
|
|
492
|
-
if(salient!==null){
|
|
493
|
-
if(name.toLowerCase().indexOf(salient.toLowerCase())>=0) return truncateStr(name,120);
|
|
494
|
-
return truncateStr(name+' '+salient,120);
|
|
495
|
-
}
|
|
496
|
-
if(Object.keys(args).length===0) return name;
|
|
497
|
-
return truncateStr(name+' '+JSON.stringify(args),120);
|
|
498
|
-
}
|
|
499
|
-
function extractText(v){
|
|
500
|
-
if(v==null) return null;
|
|
501
|
-
if(typeof v==='string') return v;
|
|
502
|
-
if(Array.isArray(v)){
|
|
503
|
-
var parts=v.map(extractText).filter(function(x){ return x!=null; });
|
|
504
|
-
return parts.length? parts.join('\\n') : null;
|
|
505
|
-
}
|
|
506
|
-
if(typeof v==='object'){
|
|
507
|
-
if(typeof v.text==='string') return v.text;
|
|
508
|
-
if(typeof v.message==='string') return v.message;
|
|
509
|
-
if(Array.isArray(v.content)) return extractText(v.content);
|
|
510
|
-
if(typeof v.error==='string') return v.error;
|
|
511
|
-
if(v.error && typeof v.error==='object' && typeof v.error.message==='string') return v.error.message;
|
|
512
|
-
return null;
|
|
513
|
-
}
|
|
514
|
-
return null;
|
|
515
|
-
}
|
|
516
|
-
function formatToolResult(toolName,result,isError){
|
|
517
|
-
var text=extractText(result);
|
|
518
|
-
if(isError){
|
|
519
|
-
var message=text!=null? text : (result!=null? JSON.stringify(result) : 'failed');
|
|
520
|
-
var firstLine=String(message).split(/\\r?\\n/)[0] || message;
|
|
521
|
-
return truncateStr(firstLine,160);
|
|
522
|
-
}
|
|
523
|
-
if(text==null) return null;
|
|
524
|
-
var trimmed=text.trim();
|
|
525
|
-
if(!trimmed) return null;
|
|
526
|
-
var lines=trimmed.split(/\\r?\\n/);
|
|
527
|
-
if(lines.length>1){
|
|
528
|
-
var bytes=new TextEncoder().encode(trimmed).length;
|
|
529
|
-
return lines.length+' lines, '+bytes+'B';
|
|
530
|
-
}
|
|
531
|
-
return truncateStr(lines[0],160);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
function classifyKind(toolCalls){
|
|
535
|
-
if(!toolCalls || toolCalls.length===0) return 'text';
|
|
536
|
-
var names=toolCalls.map(function(t){ return t.name.toLowerCase(); });
|
|
537
|
-
if(names.some(function(n){ return /edit|write/.test(n); })) return 'edit';
|
|
538
|
-
if(names.some(function(n){ return /bash|terminal|command/.test(n); })) return 'bash';
|
|
539
|
-
if(names.some(function(n){ return /read|grep|glob/.test(n); })) return 'read';
|
|
540
|
-
return 'text';
|
|
541
|
-
}
|
|
542
|
-
var NEW_CHAPTER_RE=/\\b(aussi|autre|ensuite|nouveau|nouvelle|plut[o\xF4]t|maintenant|apr[e\xE8]s \xE7a|il faudrait|peux[- ]tu|on pourrait|ajoute|g[e\xE8]re)\\b/iu;
|
|
543
|
-
function classifyRoute(text){
|
|
544
|
-
var newt=NEW_CHAPTER_RE.test(text);
|
|
545
|
-
if(!newt) return {route:'cont'};
|
|
546
|
-
var title=text.replace(/[.?!].*$/,'').slice(0,42);
|
|
547
|
-
return {route:'newt', title:title};
|
|
548
|
-
}
|
|
549
|
-
function formatTsJs(ts){
|
|
550
|
-
if(ts===undefined || ts===null || isNaN(ts)) return '';
|
|
551
|
-
return new Date(ts).toISOString().slice(11,19);
|
|
552
|
-
}
|
|
553
|
-
function firstMeaningfulLine(text){
|
|
554
|
-
if(!text) return undefined;
|
|
555
|
-
var lines=text.split('\\n').map(function(l){ return l.trim(); }).filter(function(l){ return l.length>0; });
|
|
556
|
-
return lines[0];
|
|
557
|
-
}
|
|
558
|
-
function lineCountOf(text){
|
|
559
|
-
var n=(text||'').split('\\n').filter(function(l){ return l.trim().length>0; }).length;
|
|
560
|
-
return n||1;
|
|
561
|
-
}
|
|
562
|
-
function parseArgsJson(s){ try{ return JSON.parse(s); }catch(e){ return {}; } }
|
|
563
|
-
|
|
564
|
-
function foldToolStep(assistant,toolResults){
|
|
565
|
-
var toolCalls=assistant.toolCalls||[];
|
|
566
|
-
var kind=classifyKind(toolCalls);
|
|
567
|
-
var count=toolCalls.length||1;
|
|
568
|
-
var items=[], facts=[];
|
|
569
|
-
if(assistant.text && assistant.text.trim()) items.push({text:assistant.text.trim()});
|
|
570
|
-
toolCalls.forEach(function(tc,i){
|
|
571
|
-
var args=parseArgsJson(tc.args);
|
|
572
|
-
var h=formatToolCall(tc.name,args);
|
|
573
|
-
var resultMsg=toolResults[i];
|
|
574
|
-
var resultText=(resultMsg && resultMsg.text) || '';
|
|
575
|
-
var isError=resultText.indexOf('[error]')===0;
|
|
576
|
-
var r=isError? resultText.slice(7).trim() : resultText;
|
|
577
|
-
items.push({h:h,r:r});
|
|
578
|
-
var fact=formatToolResult(tc.name,r,isError);
|
|
579
|
-
if(fact) facts.push(fact);
|
|
580
|
-
});
|
|
581
|
-
var firstLine=firstMeaningfulLine(assistant.text);
|
|
582
|
-
var firstToolCall=toolCalls[0];
|
|
583
|
-
var sum=firstLine!==undefined? firstLine : (firstToolCall? formatToolCall(firstToolCall.name,parseArgsJson(firstToolCall.args)) : '\u2026');
|
|
584
|
-
var raw1;
|
|
585
|
-
if(toolCalls.length===0) raw1='assistant \xB7 '+lineCountOf(assistant.text)+' ligne(s)';
|
|
586
|
-
else if(toolCalls.length===1) raw1=formatToolCall(firstToolCall.name,parseArgsJson(firstToolCall.args));
|
|
587
|
-
else raw1=(firstToolCall? firstToolCall.name : 'tool')+' \xD7'+toolCalls.length;
|
|
588
|
-
return {kind:kind, ts:formatTsJs(assistant.ts), sum:sum, raw1:raw1, count:count, facts:facts, items:items};
|
|
589
|
-
}
|
|
590
|
-
function foldUserStep(msg){
|
|
591
|
-
var text=msg.text||'';
|
|
592
|
-
return {kind:'user', ts:formatTsJs(msg.ts), sum:'\xAB '+truncateStr(text,80)+' \xBB', raw1:'user \xB7 '+lineCountOf(text)+' ligne(s)', count:1, facts:[], items:[{text:text}], userText:text};
|
|
593
|
-
}
|
|
594
|
-
function foldOrphanToolStep(msg){
|
|
595
|
-
var text=msg.text||'';
|
|
596
|
-
var isError=text.indexOf('[error]')===0;
|
|
597
|
-
var r=isError? text.slice(7).trim() : text;
|
|
598
|
-
var name=msg.toolName||'tool';
|
|
599
|
-
var fact=formatToolResult(name,r,isError);
|
|
600
|
-
return {kind:classifyKind([{name:name}]), ts:formatTsJs(msg.ts), sum: msg.toolName? (msg.toolName+' \xB7 r\xE9sultat') : "R\xE9sultat d'outil", raw1: msg.toolName||'tool', count:1, facts: fact?[fact]:[], items:[{h:name,r:r}]};
|
|
601
|
-
}
|
|
602
|
-
function foldSystemStep(msg){
|
|
603
|
-
var text=msg.text||'';
|
|
604
|
-
var line=firstMeaningfulLine(text);
|
|
605
|
-
return {kind:'text', ts:formatTsJs(msg.ts), sum: line!==undefined? line : text, raw1:'system', count:1, facts:[], items: text?[{text:text}]:[]};
|
|
606
|
-
}
|
|
607
|
-
function foldMessages(messages){
|
|
608
|
-
var steps=[], i=0;
|
|
609
|
-
while(i<messages.length){
|
|
610
|
-
var msg=messages[i];
|
|
611
|
-
if(msg.role==='user'){ steps.push(foldUserStep(msg)); i+=1; continue; }
|
|
612
|
-
if(msg.role==='assistant'){
|
|
613
|
-
var j=i+1, toolResults=[];
|
|
614
|
-
while(j<messages.length && messages[j].role==='tool'){ toolResults.push(messages[j]); j+=1; }
|
|
615
|
-
steps.push(foldToolStep(msg,toolResults)); i=j; continue;
|
|
616
|
-
}
|
|
617
|
-
if(msg.role==='tool'){ steps.push(foldOrphanToolStep(msg)); i+=1; continue; }
|
|
618
|
-
steps.push(foldSystemStep(msg)); i+=1;
|
|
619
|
-
}
|
|
620
|
-
return steps;
|
|
621
|
-
}
|
|
622
|
-
function buildStoryJs(messages){
|
|
623
|
-
var folded=foldMessages(messages||[]);
|
|
624
|
-
var chapters=[], steps=[];
|
|
625
|
-
var currentChapterId, sawFirstUser=false;
|
|
626
|
-
function closeCurrent(){ var cur=chapters.filter(function(c){ return c.id===currentChapterId; })[0]; if(cur) cur.status='done'; }
|
|
627
|
-
function openChapter(title){ var id='c'+(chapters.length+1); chapters.push({id:id,title:title,status:'cur'}); return id; }
|
|
628
|
-
folded.forEach(function(step){
|
|
629
|
-
var route;
|
|
630
|
-
if(step.kind==='user' && step.userText!==undefined){
|
|
631
|
-
if(!sawFirstUser){ sawFirstUser=true; currentChapterId=openChapter('Cadrage'); }
|
|
632
|
-
else {
|
|
633
|
-
var verdict=classifyRoute(step.userText);
|
|
634
|
-
route=verdict.route;
|
|
635
|
-
if(verdict.route==='newt'){ closeCurrent(); currentChapterId=openChapter(verdict.title||'Nouvelle sous-t\xE2che'); }
|
|
636
|
-
}
|
|
637
|
-
} else if(currentChapterId===undefined){ currentChapterId=openChapter('Cadrage'); }
|
|
638
|
-
var out={chap:currentChapterId, kind:step.kind, ts:step.ts, sum:step.sum, raw1:step.raw1, count:step.count, facts:step.facts, items:step.items};
|
|
639
|
-
if(route) out.route=route;
|
|
640
|
-
steps.push(out);
|
|
641
|
-
});
|
|
642
|
-
return {chapters:chapters, steps:steps};
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
// ============================================================
|
|
646
|
-
// App state
|
|
647
|
-
// ============================================================
|
|
648
|
-
var sessions=[];
|
|
649
|
-
var activeSessionId=null;
|
|
650
|
-
var story={chapters:[], steps:[]};
|
|
651
|
-
var open={};
|
|
652
|
-
var selected=-1;
|
|
653
|
-
var lastSeenOutputAt=null;
|
|
654
|
-
var pollTimer=null, polling=false;
|
|
655
|
-
var ICONS={text:["k-text","A"],edit:["k-edit","\u270E"],bash:["k-bash","\u25B8"],read:["k-read","\u2315"],user:["k-user","T"]};
|
|
656
|
-
var icoSpec=function(k){ return ICONS[k]||ICONS.text; };
|
|
657
|
-
var chapOf=function(id){ return story.chapters.filter(function(c){ return c.id===id; })[0]; };
|
|
658
|
-
var curChap=function(){ return story.chapters.filter(function(c){ return c.status==='cur'; })[0] || story.chapters[story.chapters.length-1]; };
|
|
659
|
-
|
|
660
|
-
function setStatus(msg){ $('statusbar').textContent=msg; }
|
|
661
|
-
function nowTs(){ return new Date().toLocaleTimeString('fr-FR',{hour:'2-digit',minute:'2-digit',second:'2-digit'}); }
|
|
662
|
-
|
|
663
|
-
function titleOf(s){
|
|
664
|
-
return s.label || s.name || (s.command? s.command.split(/\\s+/)[0].split('/').pop() : null) || s.id.slice(0,8);
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
// ============================================================
|
|
668
|
-
// Picker screen
|
|
669
|
-
// ============================================================
|
|
670
|
-
function renderPicker(){
|
|
671
|
-
var el=$('pickerList');
|
|
672
|
-
if(!sessions.length){ el.innerHTML='<div class="pk-empty">Aucune session</div>'; return; }
|
|
673
|
-
var html='';
|
|
674
|
-
sessions.forEach(function(s){
|
|
675
|
-
html+='<div class="pk-item" data-id="'+esc(s.id)+'">'
|
|
676
|
-
+ '<span class="pk-name">'+esc(titleOf(s))+'</span>'
|
|
677
|
-
+ '<span class="badge '+esc(s.status)+'">'+esc(s.status)+'</span>'
|
|
678
|
-
+ '<span class="pk-meta">'+esc(s.kind||'')+'</span>'
|
|
679
|
-
+ '</div>';
|
|
680
|
-
});
|
|
681
|
-
el.innerHTML=html;
|
|
682
|
-
Array.prototype.forEach.call(el.querySelectorAll('.pk-item'), function(row){
|
|
683
|
-
row.onclick=function(){ openSession(row.getAttribute('data-id')); };
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
function showPicker(){
|
|
688
|
-
activeSessionId=null;
|
|
689
|
-
$('pickerScreen').classList.remove('hidden');
|
|
690
|
-
$('storyScreen').classList.add('hidden');
|
|
691
|
-
renderPicker();
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
function openSession(id){
|
|
695
|
-
activeSessionId=id;
|
|
696
|
-
story={chapters:[], steps:[]};
|
|
697
|
-
open={};
|
|
698
|
-
selected=-1;
|
|
699
|
-
lastSeenOutputAt=null;
|
|
700
|
-
$('pickerScreen').classList.add('hidden');
|
|
701
|
-
$('storyScreen').classList.remove('hidden');
|
|
702
|
-
$('fullPanelLink').href='https://cli.agentproto.sh/panel?session='+encodeURIComponent(id);
|
|
703
|
-
closePanel();
|
|
704
|
-
loadStory().then(renderAll);
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
// ============================================================
|
|
708
|
-
// Story loading
|
|
709
|
-
// ============================================================
|
|
710
|
-
function activeSession(){ return sessions.filter(function(s){ return s.id===activeSessionId; })[0]; }
|
|
711
|
-
|
|
712
|
-
function loadStory(){
|
|
713
|
-
return callTool('agent_export', {sessionId:activeSessionId, format:'json'}).then(function(data){
|
|
714
|
-
var messages=(data && data.messages) || [];
|
|
715
|
-
story=buildStoryJs(messages);
|
|
716
|
-
// Default open state: only the last (current) chapter is expanded.
|
|
717
|
-
var last=story.chapters[story.chapters.length-1];
|
|
718
|
-
if(last && !(last.id in open)) open[last.id]=true;
|
|
719
|
-
}).catch(function(e){
|
|
720
|
-
setStatus('Erreur export : '+e.message);
|
|
721
|
-
});
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
function canSend(){
|
|
725
|
-
var s=activeSession();
|
|
726
|
-
return !!s && s.kind==='agent-cli' && s.status==='running';
|
|
727
|
-
}
|
|
728
|
-
|
|
729
|
-
function renderComposer(){
|
|
730
|
-
var s=activeSession();
|
|
731
|
-
var box=$('msgBox'), btn=$('sendBtn');
|
|
732
|
-
var enabled=canSend();
|
|
733
|
-
box.disabled=!enabled;
|
|
734
|
-
btn.disabled=!enabled;
|
|
735
|
-
if(!s){ box.placeholder='Session introuvable.'; }
|
|
736
|
-
else if(!enabled) box.placeholder='Lecture seule \u2014 session '+esc(s.status)+'.';
|
|
737
|
-
else box.placeholder="\xC9cris \xE0 l'agent\u2026 (la surcouche classe ton message : suite de la sous-t\xE2che ou nouvelle sous-t\xE2che)";
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
function renderHero(){
|
|
741
|
-
var s=activeSession();
|
|
742
|
-
$('heroTitle').textContent=s? titleOf(s) : (activeSessionId||'');
|
|
743
|
-
var firstUser=story.steps.filter(function(st){ return st.kind==='user'; })[0];
|
|
744
|
-
var mission=firstUser? firstUser.userText || (firstUser.items[0] && firstUser.items[0].text) : null;
|
|
745
|
-
$('heroSub').textContent=mission? truncateStr(mission,200) : 'Aucun message pour le moment.';
|
|
746
|
-
var p=$('pulse');
|
|
747
|
-
p.classList.toggle('off', !(s && (s.status==='running' || s.status==='starting')));
|
|
748
|
-
renderComposer();
|
|
749
|
-
}
|
|
750
|
-
|
|
751
|
-
function renderAll(){
|
|
752
|
-
renderHero();
|
|
753
|
-
renderPlan();
|
|
754
|
-
renderRows('bottom');
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
// ============================================================
|
|
758
|
-
// big picture strip
|
|
759
|
-
// ============================================================
|
|
760
|
-
function renderPlan(){
|
|
761
|
-
var done=story.chapters.filter(function(c){ return c.status==='done'; }).length;
|
|
762
|
-
$('plan').innerHTML=story.chapters.map(function(c,i){
|
|
763
|
-
return '<span class="pt '+c.status+'" data-c="'+esc(c.id)+'"><span class="st">'+(c.status==='done'?'\u2713':'\u25CF')+'</span>'+(i+1)+'. '+esc(c.title)+'</span>';
|
|
764
|
-
}).join('') + '<span class="pt" style="cursor:default"><b>'+done+'/'+story.chapters.length+'</b> faites</span>';
|
|
765
|
-
Array.prototype.forEach.call($('plan').querySelectorAll('.pt[data-c]'), function(el){
|
|
766
|
-
el.onclick=function(){ open[el.getAttribute('data-c')]=true; renderRows(); jumpToChap(el.getAttribute('data-c')); };
|
|
767
|
-
});
|
|
768
|
-
}
|
|
769
|
-
function jumpToChap(cid){
|
|
770
|
-
var el=document.querySelector('.chap[data-c="'+cid+'"]');
|
|
771
|
-
if(el) el.scrollIntoView({block:'start',behavior:'smooth'});
|
|
772
|
-
}
|
|
773
|
-
|
|
774
|
-
// ============================================================
|
|
775
|
-
// feed segment\xE9 par chapitres
|
|
776
|
-
// ============================================================
|
|
777
|
-
function rowHtml(s,i,isNew){
|
|
778
|
-
var spec=icoSpec(s.kind), cls=spec[0], ch=spec[1];
|
|
779
|
-
var route=s.route? '<span class="route '+(s.route==='newt'?'newt':'cont')+'">'+(s.route==='newt'?'\u2605 nouvelle sous-t\xE2che':'\u21B3 suite')+'</span>' : '';
|
|
780
|
-
return '<div class="row '+(isNew?'new':'')+'" aria-selected="'+(i===selected)+'" data-i="'+i+'">'
|
|
781
|
-
+ '<span class="ico '+cls+'">'+ch+'</span>'
|
|
782
|
-
+ '<span class="mid"><span class="sum">'+esc(s.sum)+'</span><span class="raw1">'+esc(s.raw1||'')+'</span>'+route+'</span>'
|
|
783
|
-
+ (s.count>1? '<span class="cnt">\xD7'+s.count+'</span>':'') + '<span class="ts">'+esc(s.ts||'')+'</span>'
|
|
784
|
-
+ '</div>';
|
|
785
|
-
}
|
|
786
|
-
function renderRows(keepScroll,newIdx){
|
|
787
|
-
var feed=$('feed');
|
|
788
|
-
var prevH=feed.scrollHeight, prevTop=feed.scrollTop;
|
|
789
|
-
var html='';
|
|
790
|
-
story.chapters.forEach(function(c,ci){
|
|
791
|
-
var chapSteps=[];
|
|
792
|
-
story.steps.forEach(function(s,i){ if(s.chap===c.id) chapSteps.push({s:s,i:i}); });
|
|
793
|
-
if(!chapSteps.length) return;
|
|
794
|
-
var isOpen=!!open[c.id];
|
|
795
|
-
html+='<div class="chap '+c.status+' '+(isOpen?'open':'')+'" data-c="'+esc(c.id)+'">'
|
|
796
|
-
+ '<span class="cst">'+(c.status==='done'?'\u2713':'\u25CF')+'</span><span class="cnum">'+(ci+1)+'.</span>'
|
|
797
|
-
+ '<span class="csum">'+esc(c.title)+'</span>'
|
|
798
|
-
+ '<span class="cmeta">'+chapSteps.length+' \xE9tape'+(chapSteps.length>1?'s':'')+'</span><span class="cchev">\u25B8</span>'
|
|
799
|
-
+ '</div>';
|
|
800
|
-
if(isOpen) html += chapSteps.map(function(x){ return rowHtml(x.s,x.i,x.i===newIdx); }).join('');
|
|
801
|
-
});
|
|
802
|
-
$('rows').innerHTML=html;
|
|
803
|
-
Array.prototype.forEach.call(document.querySelectorAll('.row'), function(el){
|
|
804
|
-
el.onclick=function(){ selectStep(Number(el.getAttribute('data-i'))); };
|
|
805
|
-
});
|
|
806
|
-
Array.prototype.forEach.call(document.querySelectorAll('.chap'), function(el){
|
|
807
|
-
el.onclick=function(){ var c=el.getAttribute('data-c'); open[c]=!open[c]; renderRows(); };
|
|
808
|
-
});
|
|
809
|
-
if(keepScroll==='bottom') feed.scrollTop=feed.scrollHeight;
|
|
810
|
-
else if(keepScroll==='preserve') feed.scrollTop=feed.scrollHeight-prevH+prevTop;
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
// ============================================================
|
|
814
|
-
// panneau ancr\xE9
|
|
815
|
-
// ============================================================
|
|
816
|
-
function selectStep(i){
|
|
817
|
-
selected=i;
|
|
818
|
-
var s=story.steps[i]; if(!s) return;
|
|
819
|
-
open[s.chap]=true;
|
|
820
|
-
$('panel').classList.add('open');
|
|
821
|
-
var spec=icoSpec(s.kind), cls=spec[0], ch=spec[1];
|
|
822
|
-
var ico=$('pIco'); ico.className='ico '+cls; ico.textContent=ch;
|
|
823
|
-
$('pTitle').textContent=s.sum;
|
|
824
|
-
var c=chapOf(s.chap);
|
|
825
|
-
$('pSub').textContent=(s.ts? s.ts+' \xB7 ':'')+(c? ('sous-t\xE2che : '+c.title) : '');
|
|
826
|
-
var facts=(s.facts||[]).map(function(f){
|
|
827
|
-
return '<span class="fact '+(/\u2713|exit 0|passed|0 match/.test(f)?'ok':'')+'">'+esc(f)+'</span>';
|
|
828
|
-
}).join('');
|
|
829
|
-
var tech=(s.items||[]).map(function(it,k){
|
|
830
|
-
return it.text!==undefined
|
|
831
|
-
? '<div class="d-text">'+renderMd(it.text)+'</div>'
|
|
832
|
-
: '<div class="titem"><div class="th">'+esc(it.h)+'<button class="copy" data-k="'+k+'" type="button">\u29C9</button></div><pre>'+esc(it.r)+'</pre></div>';
|
|
833
|
-
}).join('');
|
|
834
|
-
$('pBody').innerHTML=''
|
|
835
|
-
+ '<div class="plain"><div>'+esc(s.sum)+'.</div><div class="why">'+esc(s.why||'')+'</div></div>'
|
|
836
|
-
+ (facts? '<div class="facts">'+facts+'</div>':'')
|
|
837
|
-
+ '<details class="techbox" '+(document.body.classList.contains('tech')?'open':'')+'>'
|
|
838
|
-
+ '<summary>D\xE9tail technique \xB7 '+(s.items||[]).length+'</summary><div class="techlist">'+tech+'</div>'
|
|
839
|
-
+ '</details>';
|
|
840
|
-
Array.prototype.forEach.call($('pBody').querySelectorAll('.copy'), function(btn){
|
|
841
|
-
btn.onclick=function(e){
|
|
842
|
-
e.stopPropagation();
|
|
843
|
-
var it=(s.items||[])[Number(btn.getAttribute('data-k'))];
|
|
844
|
-
var payload=(it.h||'')+'\\n'+(it.r||it.text||'');
|
|
845
|
-
if(navigator.clipboard) navigator.clipboard.writeText(payload).catch(function(){});
|
|
846
|
-
btn.textContent='\u2713'; setTimeout(function(){ btn.textContent='\u29C9'; },900);
|
|
847
|
-
};
|
|
848
|
-
});
|
|
849
|
-
$('pPrev').disabled=i<=0; $('pNext').disabled=i>=story.steps.length-1;
|
|
850
|
-
renderRows();
|
|
851
|
-
var el=document.querySelector('.row[data-i="'+i+'"]');
|
|
852
|
-
if(el) el.scrollIntoView({block:'nearest',behavior:'smooth'});
|
|
853
|
-
}
|
|
854
|
-
function closePanel(){ selected=-1; var p=$('panel'); if(p) p.classList.remove('open'); renderRows(); }
|
|
855
|
-
$('pClose').addEventListener('click',closePanel);
|
|
856
|
-
$('pPrev').addEventListener('click',function(){ if(selected>0) selectStep(selected-1); });
|
|
857
|
-
$('pNext').addEventListener('click',function(){ if(selected<story.steps.length-1) selectStep(selected+1); });
|
|
858
|
-
document.addEventListener('keydown',function(e){
|
|
859
|
-
if(e.key==='Escape'){ closePanel(); return; }
|
|
860
|
-
if($('storyScreen').classList.contains('hidden')) return;
|
|
861
|
-
if(selected<0 || e.target.tagName==='TEXTAREA') return;
|
|
862
|
-
if(e.key==='ArrowUp'){ e.preventDefault(); if(selected>0) selectStep(selected-1); }
|
|
863
|
-
if(e.key==='ArrowDown'){ e.preventDefault(); if(selected<story.steps.length-1) selectStep(selected+1); }
|
|
864
|
-
});
|
|
865
|
-
|
|
866
|
-
// ============================================================
|
|
867
|
-
// Simple / Tech modes
|
|
868
|
-
// ============================================================
|
|
869
|
-
function setMode(tech){
|
|
870
|
-
document.body.classList.toggle('tech',tech);
|
|
871
|
-
$('modeTech').classList.toggle('on',tech);
|
|
872
|
-
$('modeSimple').classList.toggle('on',!tech);
|
|
873
|
-
if(selected>=0) selectStep(selected);
|
|
874
|
-
}
|
|
875
|
-
$('modeSimple').addEventListener('click',function(){ setMode(false); });
|
|
876
|
-
$('modeTech').addEventListener('click',function(){ setMode(true); });
|
|
877
|
-
$('switchBtn').addEventListener('click', function(){ if(pollTimer) clearTimeout(pollTimer); showPicker(); doPoll(); });
|
|
878
|
-
|
|
879
|
-
// ============================================================
|
|
880
|
-
// composer \u2014 local chapter-routing classification + agent_prompt
|
|
881
|
-
// ============================================================
|
|
882
|
-
$('sendBtn').addEventListener('click', sendMsg);
|
|
883
|
-
$('msgBox').addEventListener('keydown', function(e){
|
|
884
|
-
if(e.key==='Enter' && !e.shiftKey){ e.preventDefault(); sendMsg(); }
|
|
885
|
-
});
|
|
886
|
-
function sendMsg(){
|
|
887
|
-
if(!canSend()) return;
|
|
888
|
-
var box=$('msgBox'), text=box.value.trim();
|
|
889
|
-
if(!text) return;
|
|
890
|
-
box.value='';
|
|
891
|
-
var cur=curChap();
|
|
892
|
-
var r=cur? classifyRoute(text) : {route:'cont'};
|
|
893
|
-
var chapId=cur? cur.id : null;
|
|
894
|
-
if(r.route==='newt' && cur){
|
|
895
|
-
cur.status='done';
|
|
896
|
-
var id='c'+(story.chapters.length+1);
|
|
897
|
-
story.chapters.push({id:id, title:r.title||'Nouvelle sous-t\xE2che', status:'cur'});
|
|
898
|
-
chapId=id; open[id]=true;
|
|
899
|
-
$('routing').innerHTML='\u2726 class\xE9 : <span class="r-newt">\u2605 nouvelle sous-t\xE2che \xAB '+esc(r.title||'')+' \xBB</span>';
|
|
900
|
-
} else {
|
|
901
|
-
$('routing').innerHTML='\u2726 class\xE9 : <span class="r-cont">\u21B3 suite de \xAB '+esc(cur? cur.title : '')+' \xBB</span>';
|
|
902
|
-
}
|
|
903
|
-
setTimeout(function(){ $('routing').textContent=''; },5000);
|
|
904
|
-
story.steps.push({
|
|
905
|
-
chap:chapId, kind:'user', ts:nowTs(),
|
|
906
|
-
sum:'\xAB '+text.slice(0,80)+(text.length>80?'\u2026':'')+' \xBB',
|
|
907
|
-
raw1:'user \xB7 '+text.split('\\n').length+' ligne(s)',
|
|
908
|
-
route:r.route, facts:[], items:[{text:text}], userText:text,
|
|
909
|
-
});
|
|
910
|
-
renderPlan(); renderRows('bottom', story.steps.length-1);
|
|
911
|
-
callTool('agent_prompt', {sessionId:activeSessionId, prompt:text}).catch(function(e){
|
|
912
|
-
setStatus('Envoi \xE9chou\xE9 : '+e.message);
|
|
913
|
-
});
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
// ============================================================
|
|
917
|
-
// Poll \u2014 session_list every ~5s; re-fetch agent_export only on turn
|
|
918
|
-
// boundaries (lastOutputAt changed for the active session).
|
|
919
|
-
// ============================================================
|
|
920
|
-
var POLL_MS=5000;
|
|
921
|
-
function loadSessions(){
|
|
922
|
-
return callTool('session_list', {kind:'all'}).then(function(data){
|
|
923
|
-
sessions=data.sessions||[];
|
|
924
|
-
if($('pickerScreen') && !$('pickerScreen').classList.contains('hidden')) renderPicker();
|
|
925
|
-
}).catch(function(e){ setStatus('Erreur : '+e.message); });
|
|
926
|
-
}
|
|
927
|
-
function doPoll(){
|
|
928
|
-
if(polling) return;
|
|
929
|
-
polling=true;
|
|
930
|
-
loadSessions().then(function(){
|
|
931
|
-
if(!activeSessionId){ polling=false; pollTimer=setTimeout(doPoll,POLL_MS); return; }
|
|
932
|
-
var s=activeSession();
|
|
933
|
-
if(!s){ polling=false; pollTimer=setTimeout(doPoll,POLL_MS); return; }
|
|
934
|
-
renderHero();
|
|
935
|
-
var changed=s.lastOutputAt && s.lastOutputAt!==lastSeenOutputAt;
|
|
936
|
-
if(changed){
|
|
937
|
-
lastSeenOutputAt=s.lastOutputAt;
|
|
938
|
-
loadStory().then(function(){ renderPlan(); renderRows('bottom'); polling=false; pollTimer=setTimeout(doPoll,POLL_MS); });
|
|
939
|
-
} else {
|
|
940
|
-
polling=false; pollTimer=setTimeout(doPoll,POLL_MS);
|
|
941
|
-
}
|
|
942
|
-
}).catch(function(){ polling=false; pollTimer=setTimeout(doPoll,POLL_MS); });
|
|
943
|
-
}
|
|
944
|
-
|
|
945
|
-
// ============================================================
|
|
946
|
-
// Boot
|
|
947
|
-
// ============================================================
|
|
948
|
-
initBridge().then(loadSessions).then(function(){
|
|
949
|
-
setTimeout(function(){
|
|
950
|
-
var target=pendingSessionId && sessions.some(function(s){ return s.id===pendingSessionId; })
|
|
951
|
-
? pendingSessionId
|
|
952
|
-
: null;
|
|
953
|
-
if(!target){
|
|
954
|
-
var agentSessions=sessions.filter(function(s){ return s.kind==='agent-cli'; });
|
|
955
|
-
if(agentSessions.length===1) target=agentSessions[0].id;
|
|
956
|
-
}
|
|
957
|
-
if(target) openSession(target); else showPicker();
|
|
958
|
-
pollTimer=setTimeout(doPoll,POLL_MS);
|
|
959
|
-
}, 50);
|
|
960
|
-
}).catch(function(e){
|
|
961
|
-
setStatus('Bridge : '+e.message);
|
|
962
|
-
$('pickerList').innerHTML='<div class="pk-empty">\xC9chec connexion bridge : '+esc(e.message)+'</div>';
|
|
963
|
-
});
|
|
964
|
-
</script>
|
|
965
|
-
</body>
|
|
966
|
-
</html>`;
|
|
967
|
-
|
|
968
|
-
export { SESSION_STORY_PANEL_HTML };
|
|
969
|
-
//# sourceMappingURL=session-story-panel.mjs.map
|
|
970
|
-
//# sourceMappingURL=session-story-panel.mjs.map
|