@agentproto/apps 0.8.0 → 0.9.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 +29 -1
- package/dist/agents-overview/index.d.ts +54 -0
- package/dist/agents-overview/index.d.ts.map +1 -0
- package/dist/agents-overview/panel.d.ts +14 -0
- package/dist/agents-overview/panel.d.ts.map +1 -0
- package/dist/agents-overview/panel.mjs +306 -0
- package/dist/agents-overview/panel.mjs.map +1 -0
- package/dist/agents-overview.mjs +336 -0
- package/dist/agents-overview.mjs.map +1 -0
- package/dist/bin/sync.mjs +25 -11
- package/dist/bin/sync.mjs.map +1 -1
- package/dist/bureau-sessions/index.d.ts +52 -0
- package/dist/bureau-sessions/index.d.ts.map +1 -0
- package/dist/bureau-sessions/panel.d.ts +10 -0
- package/dist/bureau-sessions/panel.d.ts.map +1 -0
- package/dist/bureau-sessions/panel.mjs +297 -0
- package/dist/bureau-sessions/panel.mjs.map +1 -0
- package/dist/bureau-sessions.mjs +329 -0
- package/dist/bureau-sessions.mjs.map +1 -0
- package/dist/content-team/workflows/produce-content.d.ts +14 -2
- package/dist/content-team/workflows/produce-content.d.ts.map +1 -1
- package/dist/content-team/workflows/produce-cover.d.ts +13 -1
- package/dist/content-team/workflows/produce-cover.d.ts.map +1 -1
- package/dist/content-team.mjs +25 -11
- package/dist/content-team.mjs.map +1 -1
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +2635 -12
- package/dist/index.mjs.map +1 -1
- package/dist/live-session/index.d.ts +46 -0
- package/dist/live-session/index.d.ts.map +1 -0
- package/dist/live-session/logic.d.ts +125 -0
- package/dist/live-session/logic.d.ts.map +1 -0
- package/dist/live-session/panel.d.ts +61 -0
- package/dist/live-session/panel.d.ts.map +1 -0
- package/dist/live-session/panel.mjs +993 -0
- package/dist/live-session/panel.mjs.map +1 -0
- package/dist/live-session.mjs +1032 -0
- package/dist/live-session.mjs.map +1 -0
- package/dist/mcp-app-types.d.ts +33 -0
- package/dist/mcp-app-types.d.ts.map +1 -0
- package/dist/panel-bridge.d.ts +38 -0
- package/dist/panel-bridge.d.ts.map +1 -0
- package/dist/session-story/index.d.ts +66 -0
- package/dist/session-story/index.d.ts.map +1 -0
- package/dist/session-story/panel.d.ts +31 -0
- package/dist/session-story/panel.d.ts.map +1 -0
- package/dist/session-story/panel.mjs +970 -0
- package/dist/session-story/panel.mjs.map +1 -0
- package/dist/session-story.mjs +1002 -0
- package/dist/session-story.mjs.map +1 -0
- package/dist/sessions-panel/index.d.ts +51 -0
- package/dist/sessions-panel/index.d.ts.map +1 -0
- package/dist/sessions-panel/panel.d.ts +20 -0
- package/dist/sessions-panel/panel.d.ts.map +1 -0
- package/dist/sessions-panel/panel.mjs +511 -0
- package/dist/sessions-panel/panel.mjs.map +1 -0
- package/dist/sessions-panel.mjs +545 -0
- package/dist/sessions-panel.mjs.map +1 -0
- package/package.json +57 -6
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { defineApp } from '@agentproto/app-kit';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @agentproto/apps v0.1.0
|
|
6
|
+
* Ready-made agentproto apps (teams of agents + workflows) built on app-kit.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
// src/panel-bridge.ts
|
|
11
|
+
function panelBridgeScript(appName) {
|
|
12
|
+
return `// \u2500\u2500 MCP Apps bridge (shared: panel-bridge.ts) \u2500\u2500
|
|
13
|
+
// JSON-RPC 2.0 over window.parent.postMessage \xB7 spec 2026-01-26
|
|
14
|
+
var _nextId = 1, _pending = {}, _notifyHandlers = [];
|
|
15
|
+
var _hostContext = null, _hostContextHandlers = [];
|
|
16
|
+
function post(msg){ window.parent.postMessage(msg, '*'); }
|
|
17
|
+
function getHostContext(){ return _hostContext; }
|
|
18
|
+
function onHostContext(cb){
|
|
19
|
+
_hostContextHandlers.push(cb);
|
|
20
|
+
// Replay the last context so a late subscriber isn't stuck blind.
|
|
21
|
+
if (_hostContext){ try { cb(_hostContext); } catch(_) {} }
|
|
22
|
+
}
|
|
23
|
+
function _setHostContext(ctx){
|
|
24
|
+
if (!ctx || typeof ctx !== 'object') return;
|
|
25
|
+
// ui/notifications/host-context-changed carries only the changed keys \u2014
|
|
26
|
+
// merge, matching the official ext-apps App behaviour.
|
|
27
|
+
_hostContext = Object.assign({}, _hostContext || {}, ctx);
|
|
28
|
+
for (var i = 0; i < _hostContextHandlers.length; i++){
|
|
29
|
+
try { _hostContextHandlers[i](_hostContext); } catch(_) {}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function rpcRequest(method, params){
|
|
33
|
+
return new Promise(function(resolve, reject){
|
|
34
|
+
var id = _nextId++;
|
|
35
|
+
_pending[id] = {resolve: resolve, reject: reject};
|
|
36
|
+
post({jsonrpc: '2.0', id: id, method: method, params: params || {}});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function rpcNotify(method, params){ post({jsonrpc: '2.0', method: method, params: params || {}}); }
|
|
40
|
+
function onHostNotification(cb){ _notifyHandlers.push(cb); }
|
|
41
|
+
window.addEventListener('message', function(evt){
|
|
42
|
+
var msg = evt.data;
|
|
43
|
+
if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;
|
|
44
|
+
if (msg.id != null && msg.method == null){
|
|
45
|
+
var p = _pending[msg.id];
|
|
46
|
+
if (!p) return;
|
|
47
|
+
delete _pending[msg.id];
|
|
48
|
+
if (msg.error) p.reject(new Error(msg.error.message || ('rpc error ' + msg.error.code)));
|
|
49
|
+
else p.resolve(msg.result);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (msg.method){
|
|
53
|
+
if (msg.method === 'ui/notifications/host-context-changed'){
|
|
54
|
+
_setHostContext(msg.params || {});
|
|
55
|
+
}
|
|
56
|
+
for (var i = 0; i < _notifyHandlers.length; i++){
|
|
57
|
+
try { _notifyHandlers[i](msg.method, msg.params || {}); } catch(_) {}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
function initBridge(){
|
|
62
|
+
return rpcRequest('ui/initialize', {
|
|
63
|
+
appInfo: {name: ${JSON.stringify(appName)}, version: '0.1.0'},
|
|
64
|
+
appCapabilities: {availableDisplayModes: ['inline', 'fullscreen', 'pip']},
|
|
65
|
+
protocolVersion: '2026-01-26'
|
|
66
|
+
}).then(function(result){
|
|
67
|
+
// The initialize result carries the initial hostContext (displayMode +
|
|
68
|
+
// availableDisplayModes) \u2014 capture it before notifying the host.
|
|
69
|
+
if (result && result.hostContext) _setHostContext(result.hostContext);
|
|
70
|
+
rpcNotify('ui/notifications/initialized', {});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function requestDisplayMode(mode){
|
|
74
|
+
return rpcRequest('ui/request-display-mode', {mode: mode});
|
|
75
|
+
}
|
|
76
|
+
function callTool(name, args){
|
|
77
|
+
return rpcRequest('tools/call', {name: name, arguments: args || {}}).then(function(result){
|
|
78
|
+
if (result.isError){
|
|
79
|
+
var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';
|
|
80
|
+
throw new Error(e);
|
|
81
|
+
}
|
|
82
|
+
var text = (result.content && result.content[0] && result.content[0].text) || '{}';
|
|
83
|
+
return JSON.parse(text);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// \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
|
|
88
|
+
// Injected by the shared bridge so every panel gets them without touching
|
|
89
|
+
// its own markup. Mirrors guilde canvas.app.ts canvasShellHtml(): the
|
|
90
|
+
// panel stays inline by default; the user expands on demand. Buttons only
|
|
91
|
+
// appear for modes the host advertises in hostContext.availableDisplayModes.
|
|
92
|
+
(function(){
|
|
93
|
+
function mount(){
|
|
94
|
+
var style = document.createElement('style');
|
|
95
|
+
style.textContent = '#dm,#pin{display:none;position:fixed;top:8px;z-index:10;'
|
|
96
|
+
+ 'border:1px solid #d0d0d0;background:#fff;color:#1a1a1a;'
|
|
97
|
+
+ 'font:600 13px/1 system-ui,sans-serif;padding:7px 12px;border-radius:6px;'
|
|
98
|
+
+ 'cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.18)}'
|
|
99
|
+
+ '#dm{right:8px}#pin{right:118px}'
|
|
100
|
+
+ '#dm:hover,#pin:hover{background:#f2f2f2;border-color:#b0b0b0}'
|
|
101
|
+
+ '@media (prefers-color-scheme:dark){'
|
|
102
|
+
+ '#dm,#pin{border-color:#555;background:#2a2a2a;color:#f0f0f0;box-shadow:0 1px 4px rgba(0,0,0,.5)}'
|
|
103
|
+
+ '#dm:hover,#pin:hover{background:#333;border-color:#777}}';
|
|
104
|
+
document.head.appendChild(style);
|
|
105
|
+
|
|
106
|
+
var btn = document.createElement('button');
|
|
107
|
+
btn.id = 'dm'; btn.type = 'button'; btn.title = "Basculer l'affichage";
|
|
108
|
+
var pin = document.createElement('button');
|
|
109
|
+
pin.id = 'pin'; pin.type = 'button'; pin.title = '\xC9pingler sur le c\xF4t\xE9 (pip)';
|
|
110
|
+
document.body.appendChild(pin);
|
|
111
|
+
document.body.appendChild(btn);
|
|
112
|
+
|
|
113
|
+
function has(avail, m){ return !!avail && avail.indexOf(m) >= 0; }
|
|
114
|
+
|
|
115
|
+
// Re-sync button visibility + label from the current host context.
|
|
116
|
+
function syncBtn(ctx){
|
|
117
|
+
ctx = ctx || {};
|
|
118
|
+
var avail = ctx.availableDisplayModes;
|
|
119
|
+
// Diagnostic: what does THIS host actually advertise? (inline/fullscreen/pip)
|
|
120
|
+
console.log('[mcp-app] displayMode=', ctx.displayMode,
|
|
121
|
+
'availableDisplayModes=', avail);
|
|
122
|
+
|
|
123
|
+
// Fullscreen toggle button.
|
|
124
|
+
if (has(avail, 'fullscreen')){
|
|
125
|
+
btn.style.display = 'block';
|
|
126
|
+
btn.textContent = (ctx.displayMode === 'fullscreen') ? '\u2921 R\xE9duire' : '\u2922 Agrandir';
|
|
127
|
+
} else { btn.style.display = 'none'; }
|
|
128
|
+
|
|
129
|
+
// Dedicated pip ("pinned on side") button \u2014 only if the host advertises pip.
|
|
130
|
+
if (has(avail, 'pip')){
|
|
131
|
+
pin.style.display = 'block';
|
|
132
|
+
pin.textContent = (ctx.displayMode === 'pip') ? '\u2921 D\xE9tacher' : '\u{1F4CC} \xC9pingler';
|
|
133
|
+
} else { pin.style.display = 'none'; }
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
onHostContext(syncBtn);
|
|
137
|
+
|
|
138
|
+
btn.addEventListener('click', function(){
|
|
139
|
+
var ctx = getHostContext() || {};
|
|
140
|
+
var inPanel = (ctx.displayMode === 'fullscreen' || ctx.displayMode === 'pip');
|
|
141
|
+
requestDisplayMode(inPanel ? 'inline' : 'fullscreen').catch(function(){});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
pin.addEventListener('click', function(){
|
|
145
|
+
var ctx = getHostContext() || {};
|
|
146
|
+
requestDisplayMode(ctx.displayMode === 'pip' ? 'inline' : 'pip').catch(function(){});
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
if (document.body) mount();
|
|
150
|
+
else document.addEventListener('DOMContentLoaded', mount);
|
|
151
|
+
})();`;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// src/bureau-sessions/panel.ts
|
|
155
|
+
var BUREAU_SESSIONS_HTML = `<!DOCTYPE html>
|
|
156
|
+
<html lang="fr">
|
|
157
|
+
<head>
|
|
158
|
+
<meta charset="UTF-8">
|
|
159
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
160
|
+
<title>bureau \u2014 sessions navigateur</title>
|
|
161
|
+
<style>
|
|
162
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
163
|
+
:root{
|
|
164
|
+
--bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;
|
|
165
|
+
--text:#e6edf3;--text2:#8b949e;
|
|
166
|
+
--green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;
|
|
167
|
+
}
|
|
168
|
+
*{box-sizing:border-box}
|
|
169
|
+
html,body{height:100%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}
|
|
170
|
+
#app{display:flex;flex-direction:column;height:100%}
|
|
171
|
+
#hdr{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--bg2);flex-shrink:0}
|
|
172
|
+
#hdr h1{font-size:13px;font-weight:600}
|
|
173
|
+
#hdr .sub{font-size:11px;color:var(--text2);margin-top:2px}
|
|
174
|
+
#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:16px;line-height:1;padding:4px 6px;border-radius:6px}
|
|
175
|
+
#refresh-btn:hover{color:var(--text);background:var(--bg3)}
|
|
176
|
+
#list{flex:1;overflow-y:auto;padding:14px 16px;display:flex;flex-direction:column;gap:10px}
|
|
177
|
+
.row{background:var(--bg2);border:1px solid var(--border);border-radius:8px;padding:11px 14px;display:flex;align-items:center;gap:14px}
|
|
178
|
+
.icon{font-size:20px;flex-shrink:0}
|
|
179
|
+
.body{flex:1;min-width:0}
|
|
180
|
+
.r1{display:flex;align-items:center;gap:8px}
|
|
181
|
+
.adapter{font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
182
|
+
.url{font-family:Menlo,Monaco,'Courier New',monospace;font-size:11.5px;color:var(--blue);margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
183
|
+
.meta{font-size:10.5px;color:var(--text2);margin-top:3px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
|
|
184
|
+
.dot{width:5px;height:5px;border-radius:50%;background:var(--text2);display:inline-block}
|
|
185
|
+
.badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:11px;white-space:nowrap}
|
|
186
|
+
.br{background:rgba(63,185,80,.16);color:var(--green)}
|
|
187
|
+
.bs{background:rgba(88,166,255,.16);color:var(--blue)}
|
|
188
|
+
.bk{background:rgba(248,81,73,.14);color:var(--red)}
|
|
189
|
+
.be{background:rgba(139,148,158,.14);color:var(--text2)}
|
|
190
|
+
.berr{background:rgba(248,81,73,.22);color:var(--red)}
|
|
191
|
+
.port{font-family:Menlo,Monaco,'Courier New',monospace}
|
|
192
|
+
#empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text2);gap:8px;padding:48px;text-align:center}
|
|
193
|
+
#empty .ico{font-size:30px}
|
|
194
|
+
#statusbar{padding:5px 16px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}
|
|
195
|
+
</style>
|
|
196
|
+
</head>
|
|
197
|
+
<body>
|
|
198
|
+
<div id="app">
|
|
199
|
+
<div id="hdr">
|
|
200
|
+
<div>
|
|
201
|
+
<h1>Bureau \u2014 sessions navigateur</h1>
|
|
202
|
+
<div class="sub">services navigateur actifs \xB7 URL / port / statut</div>
|
|
203
|
+
</div>
|
|
204
|
+
<button id="refresh-btn" title="Rafra\xEEchir" onclick="doRefresh()">↻</button>
|
|
205
|
+
</div>
|
|
206
|
+
<div id="list"><div id="empty"><div class="ico">🌐</div><div>Connexion au bridge…</div></div></div>
|
|
207
|
+
<div id="statusbar">Connexion…</div>
|
|
208
|
+
</div>
|
|
209
|
+
<script>
|
|
210
|
+
${panelBridgeScript("agentproto-bureau-sessions")}
|
|
211
|
+
|
|
212
|
+
// \u2500\u2500 State \u2500\u2500
|
|
213
|
+
var REFRESH_MS = 5000;
|
|
214
|
+
var pollTimer = null, polling = false;
|
|
215
|
+
function esc(s){ return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); }
|
|
216
|
+
function setStatus(m){ document.getElementById('statusbar').textContent = m; }
|
|
217
|
+
|
|
218
|
+
function badgeClass(st){
|
|
219
|
+
if (st === 'running') return 'br';
|
|
220
|
+
if (st === 'starting') return 'bs';
|
|
221
|
+
if (st === 'killed') return 'bk';
|
|
222
|
+
if (st === 'error') return 'berr';
|
|
223
|
+
return 'be';
|
|
224
|
+
}
|
|
225
|
+
function fmtUptime(iso, end){
|
|
226
|
+
if (!iso) return '';
|
|
227
|
+
var start = Date.parse(iso);
|
|
228
|
+
if (isNaN(start)) return '';
|
|
229
|
+
var ref = end ? Date.parse(end) : Date.now();
|
|
230
|
+
var s = Math.max(0, Math.round((ref - start) / 1000));
|
|
231
|
+
if (s < 60) return s + 's';
|
|
232
|
+
var m = Math.floor(s/60), rs = s%60;
|
|
233
|
+
if (m < 60) return m + 'm ' + rs + 's';
|
|
234
|
+
var h = Math.floor(m/60), rm = m%60;
|
|
235
|
+
return h + 'h ' + rm + 'm';
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function render(rows){
|
|
239
|
+
var list = document.getElementById('list');
|
|
240
|
+
if (!rows.length){
|
|
241
|
+
list.innerHTML = '<div id="empty"><div class="ico">🌐</div><div>Aucune session navigateur</div></div>';
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
var html = '';
|
|
245
|
+
for (var i=0;i<rows.length;i++){
|
|
246
|
+
var s = rows[i];
|
|
247
|
+
var bc = badgeClass(s.status);
|
|
248
|
+
var url = s.browserBaseUrl || (s.browserPort ? ('http://127.0.0.1:' + s.browserPort) : '');
|
|
249
|
+
var adapter = s.browserAdapterId || s.label || s.name || 'navigateur';
|
|
250
|
+
var up = fmtUptime(s.startedAt, s.endedAt);
|
|
251
|
+
html += '<div class="row">'
|
|
252
|
+
+ '<div class="icon">🌐</div>'
|
|
253
|
+
+ '<div class="body">'
|
|
254
|
+
+ '<div class="r1"><span class="adapter">' + esc(adapter) + '</span>'
|
|
255
|
+
+ '<span class="badge ' + bc + '">' + esc(s.status || '') + '</span></div>'
|
|
256
|
+
+ (url ? '<div class="url">' + esc(url) + '</div>' : '')
|
|
257
|
+
+ '<div class="meta">'
|
|
258
|
+
+ (s.browserPort ? '<span>port <span class="port">' + esc(s.browserPort) + '</span></span><span class="dot"></span>' : '')
|
|
259
|
+
+ '<span>' + (up ? 'uptime ' + esc(up) : '') + '</span>'
|
|
260
|
+
+ '</div>'
|
|
261
|
+
+ '</div>'
|
|
262
|
+
+ '</div>';
|
|
263
|
+
}
|
|
264
|
+
list.innerHTML = html;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function loadAndRender(){
|
|
268
|
+
return callTool('session_list', {kind:'all'}).then(function(data){
|
|
269
|
+
var all = data.sessions || [];
|
|
270
|
+
var browsers = all.filter(function(s){ return s.kind === 'browser'; });
|
|
271
|
+
render(browsers);
|
|
272
|
+
setStatus(browsers.length + ' session' + (browsers.length===1?'':'s') + ' \xB7 ' + new Date().toLocaleTimeString('fr-FR'));
|
|
273
|
+
}).catch(function(e){ setStatus('Erreur : ' + e.message); });
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function doPoll(){
|
|
277
|
+
if (polling) return;
|
|
278
|
+
polling = true;
|
|
279
|
+
loadAndRender().then(function(){
|
|
280
|
+
polling = false;
|
|
281
|
+
pollTimer = setTimeout(doPoll, REFRESH_MS);
|
|
282
|
+
}).catch(function(){
|
|
283
|
+
polling = false;
|
|
284
|
+
pollTimer = setTimeout(doPoll, REFRESH_MS);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
function doRefresh(){ if (pollTimer) clearTimeout(pollTimer); return loadAndRender().then(function(){ pollTimer = setTimeout(doPoll, REFRESH_MS); }); }
|
|
288
|
+
|
|
289
|
+
initBridge().then(loadAndRender).then(function(){
|
|
290
|
+
pollTimer = setTimeout(doPoll, REFRESH_MS);
|
|
291
|
+
}).catch(function(e){
|
|
292
|
+
setStatus('Bridge : ' + e.message);
|
|
293
|
+
document.getElementById('list').innerHTML = '<div id="empty"><div class="ico">⚠</div><div>\xC9chec connexion bridge : ' + esc(e.message) + '</div></div>';
|
|
294
|
+
});
|
|
295
|
+
</script>
|
|
296
|
+
</body>
|
|
297
|
+
</html>`;
|
|
298
|
+
|
|
299
|
+
// src/bureau-sessions/index.ts
|
|
300
|
+
var bureauSessionsInputSchema = z.object({
|
|
301
|
+
filter: z.enum(["running", "all"]).optional().describe("`running` = only alive browser sessions; `all` = running + recent (default).")
|
|
302
|
+
});
|
|
303
|
+
function makeBureauSessionsApp(ops) {
|
|
304
|
+
return {
|
|
305
|
+
id: "agentproto_bureau_sessions",
|
|
306
|
+
title: "Bureau \u2014 sessions navigateur",
|
|
307
|
+
description: "Open the browser-sessions panel \u2014 one row per browser service (adapter, base URL, port, status, uptime). Polls live every ~5 s.",
|
|
308
|
+
inputSchema: bureauSessionsInputSchema,
|
|
309
|
+
execute: async (input) => ({
|
|
310
|
+
sessions: ops.listSessions(input.filter).filter((s) => s.kind === "browser")
|
|
311
|
+
}),
|
|
312
|
+
html: BUREAU_SESSIONS_HTML
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
var bureauSessionsApp = defineApp({
|
|
316
|
+
id: "@agentproto/bureau-sessions",
|
|
317
|
+
name: "Bureau \u2014 sessions navigateur",
|
|
318
|
+
description: "Open the browser-sessions panel \u2014 one row per browser service (adapter, base URL, port, status, uptime).",
|
|
319
|
+
agents: [],
|
|
320
|
+
ui: {
|
|
321
|
+
html: BUREAU_SESSIONS_HTML,
|
|
322
|
+
title: "Bureau \u2014 sessions navigateur",
|
|
323
|
+
tools: ["session_list"]
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
export { bureauSessionsApp, bureauSessionsInputSchema, makeBureauSessionsApp };
|
|
328
|
+
//# sourceMappingURL=bureau-sessions.mjs.map
|
|
329
|
+
//# sourceMappingURL=bureau-sessions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/panel-bridge.ts","../src/bureau-sessions/panel.ts","../src/bureau-sessions/index.ts"],"names":[],"mappings":"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","file":"bureau-sessions.mjs","sourcesContent":["/**\n * Shared MCP Apps client bridge for agentproto panels.\n *\n * One spec-correct copy of the JSON-RPC-over-postMessage bridge that every\n * ui:// panel embeds in its <script> block. Mirrors the behaviour of\n * @agstudio/mcp-apps' mcpAppClientScript() — which we cannot import here:\n * agentproto is a standalone pnpm workspace with no @agstudio/* dependency\n * (same isolation invariant as mcp-apps-adapter.ts).\n *\n * Handshake (MCP Apps ext spec 2026-01-26, ext-apps McpUiInitializeRequest):\n * params REQUIRE `appInfo` (Implementation: {name, version}),\n * `appCapabilities`, and `protocolVersion`. Sending `clientInfo` instead\n * of `appInfo` fails the host's schema validation — hosts either reply\n * with an error or silently drop the request, so the panel's initBridge()\n * promise never resolves and the panel renders blank while every\n * server-side surface (tools, resources) works. That exact bug shipped in\n * 4 copy-pasted bridges; this module is the single corrected source.\n *\n * The script defines, in panel scope:\n * post / rpcRequest / rpcNotify — raw JSON-RPC plumbing\n * onHostNotification(cb) — subscribe to host-pushed\n * notifications (method, params)\n * initBridge() — ui/initialize → ui/notifications/initialized\n * callTool(name, args) — tools/call + JSON text unwrap\n * getHostContext() / onHostContext(cb) — host context (displayMode, theme, …),\n * captured from the initialize result and\n * merged on ui/notifications/host-context-changed\n * requestDisplayMode(mode) — ui/request-display-mode (inline|fullscreen|pip)\n *\n * Display-mode toggle: the bridge also injects two floating buttons\n * (fullscreen + pip) in the top-right corner of every panel, shown only for\n * the modes the host actually advertises via hostContext.availableDisplayModes\n * — same pattern as guilde's canvas.app.ts canvasShellHtml() (the reference\n * implementation that renders correctly in Claude hosts). No auto-request:\n * panels stay inline until the user clicks.\n */\n\nexport function panelBridgeScript(appName: string): string {\n return `// ── MCP Apps bridge (shared: panel-bridge.ts) ──\n// JSON-RPC 2.0 over window.parent.postMessage · spec 2026-01-26\nvar _nextId = 1, _pending = {}, _notifyHandlers = [];\nvar _hostContext = null, _hostContextHandlers = [];\nfunction post(msg){ window.parent.postMessage(msg, '*'); }\nfunction getHostContext(){ return _hostContext; }\nfunction onHostContext(cb){\n _hostContextHandlers.push(cb);\n // Replay the last context so a late subscriber isn't stuck blind.\n if (_hostContext){ try { cb(_hostContext); } catch(_) {} }\n}\nfunction _setHostContext(ctx){\n if (!ctx || typeof ctx !== 'object') return;\n // ui/notifications/host-context-changed carries only the changed keys —\n // merge, matching the official ext-apps App behaviour.\n _hostContext = Object.assign({}, _hostContext || {}, ctx);\n for (var i = 0; i < _hostContextHandlers.length; i++){\n try { _hostContextHandlers[i](_hostContext); } catch(_) {}\n }\n}\nfunction rpcRequest(method, params){\n return new Promise(function(resolve, reject){\n var id = _nextId++;\n _pending[id] = {resolve: resolve, reject: reject};\n post({jsonrpc: '2.0', id: id, method: method, params: params || {}});\n });\n}\nfunction rpcNotify(method, params){ post({jsonrpc: '2.0', method: method, params: params || {}}); }\nfunction onHostNotification(cb){ _notifyHandlers.push(cb); }\nwindow.addEventListener('message', function(evt){\n var msg = evt.data;\n if (!msg || typeof msg !== 'object' || msg.jsonrpc !== '2.0') return;\n if (msg.id != null && msg.method == null){\n var p = _pending[msg.id];\n if (!p) return;\n delete _pending[msg.id];\n if (msg.error) p.reject(new Error(msg.error.message || ('rpc error ' + msg.error.code)));\n else p.resolve(msg.result);\n return;\n }\n if (msg.method){\n if (msg.method === 'ui/notifications/host-context-changed'){\n _setHostContext(msg.params || {});\n }\n for (var i = 0; i < _notifyHandlers.length; i++){\n try { _notifyHandlers[i](msg.method, msg.params || {}); } catch(_) {}\n }\n }\n});\nfunction initBridge(){\n return rpcRequest('ui/initialize', {\n appInfo: {name: ${JSON.stringify(appName)}, version: '0.1.0'},\n appCapabilities: {availableDisplayModes: ['inline', 'fullscreen', 'pip']},\n protocolVersion: '2026-01-26'\n }).then(function(result){\n // The initialize result carries the initial hostContext (displayMode +\n // availableDisplayModes) — capture it before notifying the host.\n if (result && result.hostContext) _setHostContext(result.hostContext);\n rpcNotify('ui/notifications/initialized', {});\n });\n}\nfunction requestDisplayMode(mode){\n return rpcRequest('ui/request-display-mode', {mode: mode});\n}\nfunction callTool(name, args){\n return rpcRequest('tools/call', {name: name, arguments: args || {}}).then(function(result){\n if (result.isError){\n var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';\n throw new Error(e);\n }\n var text = (result.content && result.content[0] && result.content[0].text) || '{}';\n return JSON.parse(text);\n });\n}\n\n// ── Display-mode toggle buttons (NO auto-request) ──────────────────────\n// Injected by the shared bridge so every panel gets them without touching\n// its own markup. Mirrors guilde canvas.app.ts canvasShellHtml(): the\n// panel stays inline by default; the user expands on demand. Buttons only\n// appear for modes the host advertises in hostContext.availableDisplayModes.\n(function(){\n function mount(){\n var style = document.createElement('style');\n style.textContent = '#dm,#pin{display:none;position:fixed;top:8px;z-index:10;'\n + 'border:1px solid #d0d0d0;background:#fff;color:#1a1a1a;'\n + 'font:600 13px/1 system-ui,sans-serif;padding:7px 12px;border-radius:6px;'\n + 'cursor:pointer;box-shadow:0 1px 4px rgba(0,0,0,.18)}'\n + '#dm{right:8px}#pin{right:118px}'\n + '#dm:hover,#pin:hover{background:#f2f2f2;border-color:#b0b0b0}'\n + '@media (prefers-color-scheme:dark){'\n + '#dm,#pin{border-color:#555;background:#2a2a2a;color:#f0f0f0;box-shadow:0 1px 4px rgba(0,0,0,.5)}'\n + '#dm:hover,#pin:hover{background:#333;border-color:#777}}';\n document.head.appendChild(style);\n\n var btn = document.createElement('button');\n btn.id = 'dm'; btn.type = 'button'; btn.title = \"Basculer l'affichage\";\n var pin = document.createElement('button');\n pin.id = 'pin'; pin.type = 'button'; pin.title = 'Épingler sur le côté (pip)';\n document.body.appendChild(pin);\n document.body.appendChild(btn);\n\n function has(avail, m){ return !!avail && avail.indexOf(m) >= 0; }\n\n // Re-sync button visibility + label from the current host context.\n function syncBtn(ctx){\n ctx = ctx || {};\n var avail = ctx.availableDisplayModes;\n // Diagnostic: what does THIS host actually advertise? (inline/fullscreen/pip)\n console.log('[mcp-app] displayMode=', ctx.displayMode,\n 'availableDisplayModes=', avail);\n\n // Fullscreen toggle button.\n if (has(avail, 'fullscreen')){\n btn.style.display = 'block';\n btn.textContent = (ctx.displayMode === 'fullscreen') ? '⤡ Réduire' : '⤢ Agrandir';\n } else { btn.style.display = 'none'; }\n\n // Dedicated pip (\"pinned on side\") button — only if the host advertises pip.\n if (has(avail, 'pip')){\n pin.style.display = 'block';\n pin.textContent = (ctx.displayMode === 'pip') ? '⤡ Détacher' : '📌 Épingler';\n } else { pin.style.display = 'none'; }\n }\n\n onHostContext(syncBtn);\n\n btn.addEventListener('click', function(){\n var ctx = getHostContext() || {};\n var inPanel = (ctx.displayMode === 'fullscreen' || ctx.displayMode === 'pip');\n requestDisplayMode(inPanel ? 'inline' : 'fullscreen').catch(function(){});\n });\n\n pin.addEventListener('click', function(){\n var ctx = getHostContext() || {};\n requestDisplayMode(ctx.displayMode === 'pip' ? 'inline' : 'pip').catch(function(){});\n });\n }\n if (document.body) mount();\n else document.addEventListener('DOMContentLoaded', mount);\n})();`\n}\n","/**\n * HTML bundle for the agentproto \"bureau — sessions navigateur\" panel — the\n * `BUREAU_SESSIONS_HTML` served as the `ui://agentproto_bureau_sessions/view`\n * resource. Mounted via the `agentproto_bureau_sessions` tool defined in\n * ./index.ts.\n *\n * Data only — no server LLM. The whole bundle is inline (zero CDN).\n */\n\nimport { panelBridgeScript } from \"../panel-bridge.js\"\n\n// ── HTML bundle (zero CDN, CSP-safe inline) ──────────────────────────────────\n\nexport const BUREAU_SESSIONS_HTML = `<!DOCTYPE html>\n<html lang=\"fr\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>bureau — sessions navigateur</title>\n<style>\n*{box-sizing:border-box;margin:0;padding:0}\n:root{\n --bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;\n --text:#e6edf3;--text2:#8b949e;\n --green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;\n}\n*{box-sizing:border-box}\nhtml,body{height:100%;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Helvetica,Arial,sans-serif;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}\n#app{display:flex;flex-direction:column;height:100%}\n#hdr{padding:12px 16px;border-bottom:1px solid var(--border);display:flex;align-items:center;justify-content:space-between;background:var(--bg2);flex-shrink:0}\n#hdr h1{font-size:13px;font-weight:600}\n#hdr .sub{font-size:11px;color:var(--text2);margin-top:2px}\n#refresh-btn{background:none;border:none;cursor:pointer;color:var(--text2);font-size:16px;line-height:1;padding:4px 6px;border-radius:6px}\n#refresh-btn:hover{color:var(--text);background:var(--bg3)}\n#list{flex:1;overflow-y:auto;padding:14px 16px;display:flex;flex-direction:column;gap:10px}\n.row{background:var(--bg2);border:1px solid var(--border);border-radius:8px;padding:11px 14px;display:flex;align-items:center;gap:14px}\n.icon{font-size:20px;flex-shrink:0}\n.body{flex:1;min-width:0}\n.r1{display:flex;align-items:center;gap:8px}\n.adapter{font-size:12.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.url{font-family:Menlo,Monaco,'Courier New',monospace;font-size:11.5px;color:var(--blue);margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.meta{font-size:10.5px;color:var(--text2);margin-top:3px;display:flex;gap:8px;align-items:center;flex-wrap:wrap}\n.dot{width:5px;height:5px;border-radius:50%;background:var(--text2);display:inline-block}\n.badge{font-size:10px;font-weight:700;padding:2px 8px;border-radius:11px;white-space:nowrap}\n.br{background:rgba(63,185,80,.16);color:var(--green)}\n.bs{background:rgba(88,166,255,.16);color:var(--blue)}\n.bk{background:rgba(248,81,73,.14);color:var(--red)}\n.be{background:rgba(139,148,158,.14);color:var(--text2)}\n.berr{background:rgba(248,81,73,.22);color:var(--red)}\n.port{font-family:Menlo,Monaco,'Courier New',monospace}\n#empty{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:var(--text2);gap:8px;padding:48px;text-align:center}\n#empty .ico{font-size:30px}\n#statusbar{padding:5px 16px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}\n</style>\n</head>\n<body>\n<div id=\"app\">\n <div id=\"hdr\">\n <div>\n <h1>Bureau — sessions navigateur</h1>\n <div class=\"sub\">services navigateur actifs · URL / port / statut</div>\n </div>\n <button id=\"refresh-btn\" title=\"Rafraîchir\" onclick=\"doRefresh()\">↻</button>\n </div>\n <div id=\"list\"><div id=\"empty\"><div class=\"ico\">🌐</div><div>Connexion au bridge…</div></div></div>\n <div id=\"statusbar\">Connexion…</div>\n</div>\n<script>\n${panelBridgeScript(\"agentproto-bureau-sessions\")}\n\n// ── State ──\nvar REFRESH_MS = 5000;\nvar pollTimer = null, polling = false;\nfunction esc(s){ return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); }\nfunction setStatus(m){ document.getElementById('statusbar').textContent = m; }\n\nfunction badgeClass(st){\n if (st === 'running') return 'br';\n if (st === 'starting') return 'bs';\n if (st === 'killed') return 'bk';\n if (st === 'error') return 'berr';\n return 'be';\n}\nfunction fmtUptime(iso, end){\n if (!iso) return '';\n var start = Date.parse(iso);\n if (isNaN(start)) return '';\n var ref = end ? Date.parse(end) : Date.now();\n var s = Math.max(0, Math.round((ref - start) / 1000));\n if (s < 60) return s + 's';\n var m = Math.floor(s/60), rs = s%60;\n if (m < 60) return m + 'm ' + rs + 's';\n var h = Math.floor(m/60), rm = m%60;\n return h + 'h ' + rm + 'm';\n}\n\nfunction render(rows){\n var list = document.getElementById('list');\n if (!rows.length){\n list.innerHTML = '<div id=\"empty\"><div class=\"ico\">🌐</div><div>Aucune session navigateur</div></div>';\n return;\n }\n var html = '';\n for (var i=0;i<rows.length;i++){\n var s = rows[i];\n var bc = badgeClass(s.status);\n var url = s.browserBaseUrl || (s.browserPort ? ('http://127.0.0.1:' + s.browserPort) : '');\n var adapter = s.browserAdapterId || s.label || s.name || 'navigateur';\n var up = fmtUptime(s.startedAt, s.endedAt);\n html += '<div class=\"row\">'\n + '<div class=\"icon\">🌐</div>'\n + '<div class=\"body\">'\n + '<div class=\"r1\"><span class=\"adapter\">' + esc(adapter) + '</span>'\n + '<span class=\"badge ' + bc + '\">' + esc(s.status || '') + '</span></div>'\n + (url ? '<div class=\"url\">' + esc(url) + '</div>' : '')\n + '<div class=\"meta\">'\n + (s.browserPort ? '<span>port <span class=\"port\">' + esc(s.browserPort) + '</span></span><span class=\"dot\"></span>' : '')\n + '<span>' + (up ? 'uptime ' + esc(up) : '') + '</span>'\n + '</div>'\n + '</div>'\n + '</div>';\n }\n list.innerHTML = html;\n}\n\nfunction loadAndRender(){\n return callTool('session_list', {kind:'all'}).then(function(data){\n var all = data.sessions || [];\n var browsers = all.filter(function(s){ return s.kind === 'browser'; });\n render(browsers);\n setStatus(browsers.length + ' session' + (browsers.length===1?'':'s') + ' · ' + new Date().toLocaleTimeString('fr-FR'));\n }).catch(function(e){ setStatus('Erreur : ' + e.message); });\n}\n\nfunction doPoll(){\n if (polling) return;\n polling = true;\n loadAndRender().then(function(){\n polling = false;\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n }).catch(function(){\n polling = false;\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n });\n}\nfunction doRefresh(){ if (pollTimer) clearTimeout(pollTimer); return loadAndRender().then(function(){ pollTimer = setTimeout(doPoll, REFRESH_MS); }); }\n\ninitBridge().then(loadAndRender).then(function(){\n pollTimer = setTimeout(doPoll, REFRESH_MS);\n}).catch(function(e){\n setStatus('Bridge : ' + e.message);\n document.getElementById('list').innerHTML = '<div id=\"empty\"><div class=\"ico\">⚠</div><div>Échec connexion bridge : ' + esc(e.message) + '</div></div>';\n});\n</script>\n</body>\n</html>`\n","/**\n * McpApp definition for the agentproto \"bureau — sessions navigateur\" panel.\n *\n * Shows the browser sessions (kind === \"browser\"): adapter, base URL, port,\n * status and uptime. One row per live/recent browser service so you can see\n * what's bound where at a glance.\n *\n * Uses the AgnoMcpApp contract (a local McpApp-compatible shape that does\n * NOT depend on @agstudio/mcp-apps). The host (@agentproto/runtime) wires\n * this factory's output via `registerMcpApps` at boot time — see runtime's\n * builtin-apps.ts.\n *\n * Protocol flow:\n * 1. Tool `agentproto_bureau_sessions` is called by the host.\n * 2. execute() returns the browser-session snapshot.\n * 3. The HTML panel opens a JSON-RPC bridge (postMessage) and polls\n * `session_list {kind:'all'}` every ~5 s, filtering to kind===\"browser\".\n *\n * Data only — no server LLM. The whole bundle is inline (zero CDN).\n *\n * This module also exports `bureauSessionsApp`, a real `defineApp()`\n * `AppHandle` (`agents: []`, UI-only) — the catalog/emit/`app_install` path.\n * It's separate from `makeBureauSessionsApp` above, which the daemon mounts\n * directly at boot: that factory closes over LIVE `listSessions`, something\n * a static emitted `ui.html` snapshot can't carry.\n */\n\nimport { z } from \"zod\"\nimport { defineApp, type AppHandle } from \"@agentproto/app-kit\"\nimport { BUREAU_SESSIONS_HTML } from \"./panel.js\"\nimport type { AgnoMcpApp } from \"../mcp-app-types.js\"\n\nexport const bureauSessionsInputSchema = z.object({\n filter: z\n .enum([\"running\", \"all\"])\n .optional()\n .describe(\"`running` = only alive browser sessions; `all` = running + recent (default).\"),\n})\n\nexport type BureauSessionsInput = z.infer<typeof bureauSessionsInputSchema>\nexport type BureauSessionsOutput<TSession = unknown> = { sessions: TSession[] }\n\n/** Generic over the host's own session-descriptor shape — see\n * sessions-panel/index.ts's SessionsPanelOps for why. */\nexport interface BureauSessionsOps<TSession extends { kind: string }> {\n listSessions(filter?: \"running\" | \"all\"): TSession[]\n}\n\nexport type { AgnoMcpApp }\n\nexport function makeBureauSessionsApp<TSession extends { kind: string }>(\n ops: BureauSessionsOps<TSession>,\n): AgnoMcpApp<BureauSessionsInput, BureauSessionsOutput<TSession>> {\n return {\n id: \"agentproto_bureau_sessions\",\n title: \"Bureau — sessions navigateur\",\n description:\n \"Open the browser-sessions panel — one row per browser service \" +\n \"(adapter, base URL, port, status, uptime). Polls live every ~5 s.\",\n inputSchema: bureauSessionsInputSchema,\n execute: async input => ({\n sessions: ops.listSessions(input.filter).filter(s => s.kind === \"browser\"),\n }),\n html: BUREAU_SESSIONS_HTML,\n }\n}\n\nexport const bureauSessionsApp: AppHandle = defineApp({\n id: \"@agentproto/bureau-sessions\",\n name: \"Bureau — sessions navigateur\",\n description:\n \"Open the browser-sessions panel — one row per browser service (adapter, base URL, port, \" +\n \"status, uptime).\",\n agents: [],\n ui: {\n html: BUREAU_SESSIONS_HTML,\n title: \"Bureau — sessions navigateur\",\n tools: [\"session_list\"],\n },\n})\n"]}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
1
|
+
/**
|
|
2
|
+
* The one workflow the content team produces a piece through. Every team
|
|
3
|
+
* agent references it (app-kit attachment invariant).
|
|
4
|
+
*
|
|
5
|
+
* Three declarative `kind:"agent"` steps — researcher → writer → editor —
|
|
6
|
+
* one per team agent, each `agent.ref` resolving (at compile time, against
|
|
7
|
+
* this app's own install record) to that agent's emitted AGENT.md. This
|
|
8
|
+
* replaces an earlier `ToolStep`-based draft (`read_file`/`write_file`/
|
|
9
|
+
* `edit_file`/`run_command`) that dispatched daemon-side, where those tool
|
|
10
|
+
* ids don't exist — they're agent workspace tools (adapter-side), never
|
|
11
|
+
* daemon tool ids, so `app_install` rejected them. Agent steps are the
|
|
12
|
+
* adoption fix: each step spawns the named team agent as a real session,
|
|
13
|
+
* which uses its own workspace tools to read, draft, and edit.
|
|
14
|
+
*/
|
|
3
15
|
export declare const produceContent: Readonly<import("@agentproto/workflow").WorkflowDefinition>;
|
|
4
16
|
//# sourceMappingURL=produce-content.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"produce-content.d.ts","sourceRoot":"","sources":["../../../src/content-team/workflows/produce-content.ts"],"names":[],"mappings":"AAEA;
|
|
1
|
+
{"version":3,"file":"produce-content.d.ts","sourceRoot":"","sources":["../../../src/content-team/workflows/produce-content.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,cAAc,6DA6BzB,CAAA"}
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The one workflow the illustrator uses to produce a cover.
|
|
3
|
+
*
|
|
4
|
+
* A single declarative `kind:"agent"` step — `agent.ref` resolving (at
|
|
5
|
+
* compile time, against this app's own install record) to the illustrator's
|
|
6
|
+
* emitted AGENT.md. This replaces an earlier `ToolStep`-based draft
|
|
7
|
+
* (`content.cover-concept`/`content.cover-base-gen`/`content.cover-cleanup`/
|
|
8
|
+
* `content.cover-upload`) naming tools that don't exist anywhere — no driver
|
|
9
|
+
* implements them. The illustrator agent folds all four phases (concept,
|
|
10
|
+
* base generation, cleanup, upload) into one prompt for a single session
|
|
11
|
+
* turn, matching the tools it already has (`read_file`, `write_file`,
|
|
12
|
+
* `run_command`).
|
|
13
|
+
*/
|
|
2
14
|
export declare const produceCover: Readonly<import("@agentproto/workflow").WorkflowDefinition>;
|
|
3
15
|
//# sourceMappingURL=produce-cover.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"produce-cover.d.ts","sourceRoot":"","sources":["../../../src/content-team/workflows/produce-cover.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"produce-cover.d.ts","sourceRoot":"","sources":["../../../src/content-team/workflows/produce-cover.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,6DAuBvB,CAAA"}
|
package/dist/content-team.mjs
CHANGED
|
@@ -58,17 +58,29 @@ var illustrator = {
|
|
|
58
58
|
var produceContent = defineWorkflow({
|
|
59
59
|
id: "produce-content",
|
|
60
60
|
name: "Produce a piece of content",
|
|
61
|
-
description: "
|
|
61
|
+
description: "Research the sources, draft the piece, then edit it.",
|
|
62
62
|
version: "0.1.0",
|
|
63
63
|
inputs: {},
|
|
64
64
|
outputs: {},
|
|
65
|
-
// Concrete workspace tools (fs + exec), so the workflow describes a process
|
|
66
|
-
// a standard runtime can actually run — not abstract tools nothing provides.
|
|
67
65
|
steps: [
|
|
68
|
-
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
66
|
+
{
|
|
67
|
+
id: "research",
|
|
68
|
+
kind: "agent",
|
|
69
|
+
agent: { ref: "@agentproto/researcher" },
|
|
70
|
+
prompt: "Read the source material already in the workspace and hand off a tight brief with a citation for every claim."
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
id: "draft",
|
|
74
|
+
kind: "agent",
|
|
75
|
+
agent: { ref: "@agentproto/writer" },
|
|
76
|
+
prompt: "Draft the piece from the researcher's brief and its sources."
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
id: "edit",
|
|
80
|
+
kind: "agent",
|
|
81
|
+
agent: { ref: "@agentproto/editor" },
|
|
82
|
+
prompt: "Edit the draft for voice, clarity, and length, then finalize it."
|
|
83
|
+
}
|
|
72
84
|
]
|
|
73
85
|
});
|
|
74
86
|
var produceCover = defineWorkflow({
|
|
@@ -79,10 +91,12 @@ var produceCover = defineWorkflow({
|
|
|
79
91
|
inputs: {},
|
|
80
92
|
outputs: {},
|
|
81
93
|
steps: [
|
|
82
|
-
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
94
|
+
{
|
|
95
|
+
id: "illustrate",
|
|
96
|
+
kind: "agent",
|
|
97
|
+
agent: { ref: "@agentproto/illustrator" },
|
|
98
|
+
prompt: "Produce the cover for this article in one pass: (1) read the article and derive the single visual concept that best represents it, (2) write the art direction as a clean, text-free image prompt and generate the base image from it, (3) clean up the generated image (crop, color, artifacts), then (4) upload the final cover to the workspace's output location."
|
|
99
|
+
}
|
|
86
100
|
]
|
|
87
101
|
});
|
|
88
102
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/content-team/agents/researcher.ts","../src/content-team/agents/writer.ts","../src/content-team/agents/editor.ts","../src/content-team/agents/illustrator.ts","../src/content-team/workflows/produce-content.ts","../src/content-team/workflows/produce-cover.ts","../src/content-team/index.ts"],"names":["defineAgent","defineWorkflow"],"mappings":"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","file":"content-team.mjs","sourcesContent":["import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Gathers sources for the piece. */\nexport const researcher: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/researcher\",\n description: \"Reads the provided sources and summarizes them for the writer.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"Cite every claim\", \"Prefer primary sources\"],\n tools: [\"list_dir\", \"read_file\", \"run_command\"],\n workflows: [{ ref: \"produce-content\" }],\n }),\n body:\n \"You read the source material already in the workspace (list_dir, then \" +\n \"read_file the sources), extract the key facts, and hand the writer a tight \" +\n \"brief with a citation for every claim. Use run_command only to fetch a URL \" +\n \"already named in the task; do not invent sources.\",\n}\n","import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Drafts the piece from the brief. */\nexport const writer: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/writer\",\n description: \"Drafts the piece from the researcher's brief.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"Stay on the brief\", \"One idea per paragraph\"],\n tools: [\"list_dir\", \"read_file\", \"write_file\", \"edit_file\"],\n workflows: [{ ref: \"produce-content\" }],\n }),\n body:\n \"You draft the piece from the brief and its sources. Lead with the point, \" +\n \"keep one idea per paragraph, and don't invent facts the brief doesn't have.\",\n}\n","import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Tightens the draft. */\nexport const editor: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/editor\",\n description: \"Edits the draft for voice, clarity, and length.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"Preserve the writer's meaning\", \"Cut, don't pad\"],\n tools: [\"read_file\", \"edit_file\"],\n workflows: [{ ref: \"produce-content\" }],\n }),\n body:\n \"You edit the draft. Tighten the voice, cut fluff, fix clarity — without \" +\n \"changing what the writer meant. Leave it shorter than you found it.\",\n}\n","import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Art-directs the cover illustration for each article. */\nexport const illustrator: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/illustrator\",\n description: \"Art-directs the cover illustration for each article.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"One cover per article\", \"Text-free prompts only\"],\n tools: [\"read_file\", \"write_file\", \"run_command\"],\n workflows: [{ ref: \"produce-cover\" }],\n }),\n body:\n \"You art-direct a single cover illustration for the article. \" +\n \"Read the article (read_file) to extract the one visual idea that best \" +\n \"represents the piece, then write the art direction (write_file) as a \" +\n \"clean, text-free image prompt. Keep the visual discipline tight: bold \" +\n \"flat shapes, limited risograph-style palettes, strong negative space, and \" +\n \"a single focal subject. Never include text, lettering, logos, watermarks, \" +\n \"or UI chrome in the prompt. Produce exactly one cover per article; if the \" +\n \"article calls for a literal diagram or chart, fall back to a precise \" +\n \"gpt-image-1 style description and treat the diagram itself as the image \" +\n \"subject. Use run_command only to inspect generated assets or move files \" +\n \"during the upload step.\",\n}\n","import { defineWorkflow } from \"@agentproto/workflow\"\n\n/** The one workflow the content team produces a piece through. Every team\n * agent references it (app-kit attachment invariant). */\nexport const produceContent = defineWorkflow({\n id: \"produce-content\",\n name: \"Produce a piece of content\",\n description: \"Read the sources, draft the piece, edit it, then commit it.\",\n version: \"0.1.0\",\n inputs: {},\n outputs: {},\n // Concrete workspace tools (fs + exec), so the workflow describes a process\n // a standard runtime can actually run — not abstract tools nothing provides.\n steps: [\n { id: \"research\", kind: \"tool\", tool: \"read_file\" },\n { id: \"draft\", kind: \"tool\", tool: \"write_file\" },\n { id: \"edit\", kind: \"tool\", tool: \"edit_file\" },\n { id: \"publish\", kind: \"tool\", tool: \"run_command\" },\n ],\n})\n","import { defineWorkflow } from \"@agentproto/workflow\"\n\n/** The one workflow the illustrator uses to produce a cover. */\nexport const produceCover = defineWorkflow({\n id: \"produce-cover\",\n name: \"Produce a cover illustration\",\n description:\n \"Read the article, derive the cover concept, generate the base image, \" +\n \"clean it up, and upload the final cover.\",\n version: \"0.1.0\",\n inputs: {},\n outputs: {},\n steps: [\n { id: \"concept-from-article\", kind: \"tool\", tool: \"content.cover-concept\" },\n { id: \"base-gen\", kind: \"tool\", tool: \"content.cover-base-gen\" },\n { id: \"cleanup\", kind: \"tool\", tool: \"content.cover-cleanup\" },\n { id: \"upload\", kind: \"tool\", tool: \"content.cover-upload\" },\n ],\n})\n","/**\n * `content-team` — a ready-made agentproto app: a small team that produces a\n * piece of content. Three agents (researcher → writer → editor) bound to one\n * production workflow, declared with `@agentproto/app-kit`.\n *\n * Generic on purpose — `@agentproto/…` ids, no product dependency. A host\n * imports it and uses any subset of its agents/workflows.\n */\n\nimport { defineApp, type AppHandle } from \"@agentproto/app-kit\"\nimport { researcher } from \"./agents/researcher.js\"\nimport { writer } from \"./agents/writer.js\"\nimport { editor } from \"./agents/editor.js\"\nimport { illustrator } from \"./agents/illustrator.js\"\nimport { produceContent } from \"./workflows/produce-content.js\"\nimport { produceCover } from \"./workflows/produce-cover.js\"\n\nexport const contentTeam: AppHandle = defineApp({\n id: \"@agentproto/content-team\",\n name: \"Content Team\",\n version: \"0.1.0\",\n description: \"Research, draft, edit, and illustrate content.\",\n agents: [researcher, writer, editor, illustrator],\n workflows: [produceContent, produceCover],\n})\n\nexport { researcher, writer, editor, illustrator, produceContent, produceCover }\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/content-team/agents/researcher.ts","../src/content-team/agents/writer.ts","../src/content-team/agents/editor.ts","../src/content-team/agents/illustrator.ts","../src/content-team/workflows/produce-content.ts","../src/content-team/workflows/produce-cover.ts","../src/content-team/index.ts"],"names":["defineAgent","defineWorkflow"],"mappings":"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","file":"content-team.mjs","sourcesContent":["import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Gathers sources for the piece. */\nexport const researcher: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/researcher\",\n description: \"Reads the provided sources and summarizes them for the writer.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"Cite every claim\", \"Prefer primary sources\"],\n tools: [\"list_dir\", \"read_file\", \"run_command\"],\n workflows: [{ ref: \"produce-content\" }],\n }),\n body:\n \"You read the source material already in the workspace (list_dir, then \" +\n \"read_file the sources), extract the key facts, and hand the writer a tight \" +\n \"brief with a citation for every claim. Use run_command only to fetch a URL \" +\n \"already named in the task; do not invent sources.\",\n}\n","import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Drafts the piece from the brief. */\nexport const writer: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/writer\",\n description: \"Drafts the piece from the researcher's brief.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"Stay on the brief\", \"One idea per paragraph\"],\n tools: [\"list_dir\", \"read_file\", \"write_file\", \"edit_file\"],\n workflows: [{ ref: \"produce-content\" }],\n }),\n body:\n \"You draft the piece from the brief and its sources. Lead with the point, \" +\n \"keep one idea per paragraph, and don't invent facts the brief doesn't have.\",\n}\n","import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Tightens the draft. */\nexport const editor: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/editor\",\n description: \"Edits the draft for voice, clarity, and length.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"Preserve the writer's meaning\", \"Cut, don't pad\"],\n tools: [\"read_file\", \"edit_file\"],\n workflows: [{ ref: \"produce-content\" }],\n }),\n body:\n \"You edit the draft. Tighten the voice, cut fluff, fix clarity — without \" +\n \"changing what the writer meant. Leave it shorter than you found it.\",\n}\n","import { defineAgent } from \"@agentproto/agent\"\nimport type { AgentEntry } from \"@agentproto/app-kit\"\n\n/** Art-directs the cover illustration for each article. */\nexport const illustrator: AgentEntry = {\n agent: defineAgent({\n schema: \"agent/v1\",\n id: \"@agentproto/illustrator\",\n description: \"Art-directs the cover illustration for each article.\",\n model: \"claude-sonnet-5\",\n boundaries: [\"One cover per article\", \"Text-free prompts only\"],\n tools: [\"read_file\", \"write_file\", \"run_command\"],\n workflows: [{ ref: \"produce-cover\" }],\n }),\n body:\n \"You art-direct a single cover illustration for the article. \" +\n \"Read the article (read_file) to extract the one visual idea that best \" +\n \"represents the piece, then write the art direction (write_file) as a \" +\n \"clean, text-free image prompt. Keep the visual discipline tight: bold \" +\n \"flat shapes, limited risograph-style palettes, strong negative space, and \" +\n \"a single focal subject. Never include text, lettering, logos, watermarks, \" +\n \"or UI chrome in the prompt. Produce exactly one cover per article; if the \" +\n \"article calls for a literal diagram or chart, fall back to a precise \" +\n \"gpt-image-1 style description and treat the diagram itself as the image \" +\n \"subject. Use run_command only to inspect generated assets or move files \" +\n \"during the upload step.\",\n}\n","import { defineWorkflow } from \"@agentproto/workflow\"\n\n/**\n * The one workflow the content team produces a piece through. Every team\n * agent references it (app-kit attachment invariant).\n *\n * Three declarative `kind:\"agent\"` steps — researcher → writer → editor —\n * one per team agent, each `agent.ref` resolving (at compile time, against\n * this app's own install record) to that agent's emitted AGENT.md. This\n * replaces an earlier `ToolStep`-based draft (`read_file`/`write_file`/\n * `edit_file`/`run_command`) that dispatched daemon-side, where those tool\n * ids don't exist — they're agent workspace tools (adapter-side), never\n * daemon tool ids, so `app_install` rejected them. Agent steps are the\n * adoption fix: each step spawns the named team agent as a real session,\n * which uses its own workspace tools to read, draft, and edit.\n */\nexport const produceContent = defineWorkflow({\n id: \"produce-content\",\n name: \"Produce a piece of content\",\n description: \"Research the sources, draft the piece, then edit it.\",\n version: \"0.1.0\",\n inputs: {},\n outputs: {},\n steps: [\n {\n id: \"research\",\n kind: \"agent\",\n agent: { ref: \"@agentproto/researcher\" },\n prompt:\n \"Read the source material already in the workspace and hand off a tight \" +\n \"brief with a citation for every claim.\",\n },\n {\n id: \"draft\",\n kind: \"agent\",\n agent: { ref: \"@agentproto/writer\" },\n prompt: \"Draft the piece from the researcher's brief and its sources.\",\n },\n {\n id: \"edit\",\n kind: \"agent\",\n agent: { ref: \"@agentproto/editor\" },\n prompt: \"Edit the draft for voice, clarity, and length, then finalize it.\",\n },\n ],\n})\n","import { defineWorkflow } from \"@agentproto/workflow\"\n\n/**\n * The one workflow the illustrator uses to produce a cover.\n *\n * A single declarative `kind:\"agent\"` step — `agent.ref` resolving (at\n * compile time, against this app's own install record) to the illustrator's\n * emitted AGENT.md. This replaces an earlier `ToolStep`-based draft\n * (`content.cover-concept`/`content.cover-base-gen`/`content.cover-cleanup`/\n * `content.cover-upload`) naming tools that don't exist anywhere — no driver\n * implements them. The illustrator agent folds all four phases (concept,\n * base generation, cleanup, upload) into one prompt for a single session\n * turn, matching the tools it already has (`read_file`, `write_file`,\n * `run_command`).\n */\nexport const produceCover = defineWorkflow({\n id: \"produce-cover\",\n name: \"Produce a cover illustration\",\n description:\n \"Read the article, derive the cover concept, generate the base image, \" +\n \"clean it up, and upload the final cover.\",\n version: \"0.1.0\",\n inputs: {},\n outputs: {},\n steps: [\n {\n id: \"illustrate\",\n kind: \"agent\",\n agent: { ref: \"@agentproto/illustrator\" },\n prompt:\n \"Produce the cover for this article in one pass: (1) read the article \" +\n \"and derive the single visual concept that best represents it, (2) \" +\n \"write the art direction as a clean, text-free image prompt and \" +\n \"generate the base image from it, (3) clean up the generated image \" +\n \"(crop, color, artifacts), then (4) upload the final cover to the \" +\n \"workspace's output location.\",\n },\n ],\n})\n","/**\n * `content-team` — a ready-made agentproto app: a small team that produces a\n * piece of content. Three agents (researcher → writer → editor) bound to one\n * production workflow, declared with `@agentproto/app-kit`.\n *\n * Generic on purpose — `@agentproto/…` ids, no product dependency. A host\n * imports it and uses any subset of its agents/workflows.\n */\n\nimport { defineApp, type AppHandle } from \"@agentproto/app-kit\"\nimport { researcher } from \"./agents/researcher.js\"\nimport { writer } from \"./agents/writer.js\"\nimport { editor } from \"./agents/editor.js\"\nimport { illustrator } from \"./agents/illustrator.js\"\nimport { produceContent } from \"./workflows/produce-content.js\"\nimport { produceCover } from \"./workflows/produce-cover.js\"\n\nexport const contentTeam: AppHandle = defineApp({\n id: \"@agentproto/content-team\",\n name: \"Content Team\",\n version: \"0.1.0\",\n description: \"Research, draft, edit, and illustrate content.\",\n agents: [researcher, writer, editor, illustrator],\n workflows: [produceContent, produceCover],\n})\n\nexport { researcher, writer, editor, illustrator, produceContent, produceCover }\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,18 @@
|
|
|
15
15
|
* — including agentik-studio — can consume them. Each team lives in its own
|
|
16
16
|
* folder (`code-team/`, `content-team/`) with `agents/` + `workflows/`, and is
|
|
17
17
|
* re-exported here + as a subpath (`@agentproto/apps/<team>`).
|
|
18
|
+
*
|
|
19
|
+
* This package also carries five daemon-builtin panels (`sessions-panel`,
|
|
20
|
+
* `agents-overview`, `bureau-sessions`, `session-story`, `live-session`) —
|
|
21
|
+
* @agentproto/runtime's house-app-quality UI widgets. Each ships in two
|
|
22
|
+
* forms: a real `AppHandle` (`agents: []`, UI-only — the catalog/emit/
|
|
23
|
+
* `app_install` path, e.g. `sessionsPanelApp`) AND a separate
|
|
24
|
+
* `make<Name>App(ops)` factory producing the `AgnoMcpApp` shape
|
|
25
|
+
* @agentproto/runtime mounts directly at boot (see runtime's
|
|
26
|
+
* builtin-apps.ts) — no `app_install` step required there. The two forms
|
|
27
|
+
* coexist because the boot-time mount needs LIVE daemon closures
|
|
28
|
+
* (`listSessions`, `httpBaseUrl`) that a static emitted `ui.html` snapshot
|
|
29
|
+
* can't carry.
|
|
18
30
|
*/
|
|
19
31
|
export { codeTeam } from "./code-team/index.js";
|
|
20
32
|
export { contentTeam } from "./content-team/index.js";
|
|
@@ -22,4 +34,16 @@ export { mailTriage } from "./mail-triage/index.js";
|
|
|
22
34
|
export { mediaViewer } from "./media-viewer/index.js";
|
|
23
35
|
export { opsPanel } from "./ops-panel/index.js";
|
|
24
36
|
export { sessionViewer } from "./session-viewer/index.js";
|
|
37
|
+
export type { AgnoMcpApp } from "./mcp-app-types.js";
|
|
38
|
+
export { panelBridgeScript } from "./panel-bridge.js";
|
|
39
|
+
export { makeSessionsPanelApp, sessionsPanelApp } from "./sessions-panel/index.js";
|
|
40
|
+
export type { SessionsPanelOps, SessionsInput, SessionsOutput } from "./sessions-panel/index.js";
|
|
41
|
+
export { makeAgentsOverviewApp, agentsOverviewApp } from "./agents-overview/index.js";
|
|
42
|
+
export type { AgentsOverviewOps, AgentsOverviewInput, AgentsOverviewOutput } from "./agents-overview/index.js";
|
|
43
|
+
export { makeBureauSessionsApp, bureauSessionsApp } from "./bureau-sessions/index.js";
|
|
44
|
+
export type { BureauSessionsOps, BureauSessionsInput, BureauSessionsOutput } from "./bureau-sessions/index.js";
|
|
45
|
+
export { makeSessionStoryPanelApp, sessionStoryApp } from "./session-story/index.js";
|
|
46
|
+
export type { SessionStoryOps, SessionStoryInput, SessionStoryOutput } from "./session-story/index.js";
|
|
47
|
+
export { makeLiveSessionApp, liveSessionApp } from "./live-session/index.js";
|
|
48
|
+
export type { LiveSessionOps, LiveSessionInput, LiveSessionOutput } from "./live-session/index.js";
|
|
25
49
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEzD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAClF,YAAY,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAA;AAChG,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AACrF,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAC9G,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AACrF,YAAY,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAA;AAC9G,OAAO,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AACpF,YAAY,EAAE,eAAe,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AACtG,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAA;AAC5E,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA"}
|