@agentproto/apps 0.10.0 → 0.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/dist/agents-overview/panel.mjs +18 -1
- package/dist/agents-overview/panel.mjs.map +1 -1
- package/dist/agents-overview.mjs +18 -1
- package/dist/agents-overview.mjs.map +1 -1
- package/dist/bureau-sessions/panel.mjs +18 -1
- package/dist/bureau-sessions/panel.mjs.map +1 -1
- package/dist/bureau-sessions.mjs +18 -1
- package/dist/bureau-sessions.mjs.map +1 -1
- package/dist/index.mjs +622 -288
- package/dist/index.mjs.map +1 -1
- package/dist/live-session/panel.mjs +18 -1
- package/dist/live-session/panel.mjs.map +1 -1
- package/dist/live-session.mjs +18 -1
- package/dist/live-session.mjs.map +1 -1
- package/dist/panel-bridge.d.ts +48 -0
- package/dist/panel-bridge.d.ts.map +1 -1
- package/dist/session-story/panel.mjs +18 -1
- package/dist/session-story/panel.mjs.map +1 -1
- package/dist/session-story.mjs +18 -1
- package/dist/session-story.mjs.map +1 -1
- package/dist/sessions-panel/panel.mjs +18 -1
- package/dist/sessions-panel/panel.mjs.map +1 -1
- package/dist/sessions-panel.mjs +18 -1
- package/dist/sessions-panel.mjs.map +1 -1
- package/dist/work-board/index.d.ts.map +1 -1
- package/dist/work-board/panel.d.ts +39 -6
- package/dist/work-board/panel.d.ts.map +1 -1
- package/dist/work-board/panel.generated.d.ts +13 -0
- package/dist/work-board/panel.generated.d.ts.map +1 -0
- package/dist/work-board/panel.mjs +469 -296
- package/dist/work-board/panel.mjs.map +1 -1
- package/dist/work-board.mjs +471 -298
- package/dist/work-board.mjs.map +1 -1
- package/package.json +12 -8
package/dist/work-board.mjs
CHANGED
|
@@ -7,12 +7,25 @@ import { defineApp } from '@agentproto/app-kit';
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
// src/panel
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
// src/work-board/panel.generated.ts
|
|
11
|
+
var WORK_BOARD_HTML_GENERATED = `<!DOCTYPE html>
|
|
12
|
+
<html lang="en">
|
|
13
|
+
<head>
|
|
14
|
+
<meta charset="UTF-8" />
|
|
15
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
16
|
+
<title>agentproto work board</title>
|
|
17
|
+
<!-- PANEL_BRIDGE: replaced with the inline panelBridgeScript() output by
|
|
18
|
+
vite.config.ts's injectPanelBridge plugin \u2014 a classic (non-module)
|
|
19
|
+
script so its \`initBridge\`/\`callTool\` land as globals before the
|
|
20
|
+
deferred module script below runs. -->
|
|
21
|
+
<script>// \u2500\u2500 MCP Apps bridge (shared: panel-bridge.ts) \u2500\u2500
|
|
13
22
|
// JSON-RPC 2.0 over window.parent.postMessage \xB7 spec 2026-01-26
|
|
14
23
|
var _nextId = 1, _pending = {}, _notifyHandlers = [];
|
|
15
24
|
var _hostContext = null, _hostContextHandlers = [];
|
|
25
|
+
var _standaloneApp = null;
|
|
26
|
+
function _isStandalone(){
|
|
27
|
+
return window.parent === window && !!window.McpApp && typeof window.McpApp.connect === 'function';
|
|
28
|
+
}
|
|
16
29
|
function post(msg){ window.parent.postMessage(msg, '*'); }
|
|
17
30
|
function getHostContext(){ return _hostContext; }
|
|
18
31
|
function onHostContext(cb){
|
|
@@ -59,8 +72,18 @@ window.addEventListener('message', function(evt){
|
|
|
59
72
|
}
|
|
60
73
|
});
|
|
61
74
|
function initBridge(){
|
|
75
|
+
if (_isStandalone()){
|
|
76
|
+
return window.McpApp.connect().then(function(conn){
|
|
77
|
+
_standaloneApp = conn;
|
|
78
|
+
// No host to advertise a hostContext \u2014 default to inline with no
|
|
79
|
+
// other modes available, which keeps the #dm/#pin toggle buttons
|
|
80
|
+
// hidden (they only show for modes hostContext.availableDisplayModes
|
|
81
|
+
// lists) instead of rendering two buttons with nothing to switch to.
|
|
82
|
+
_setHostContext({displayMode: 'inline', availableDisplayModes: []});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
62
85
|
return rpcRequest('ui/initialize', {
|
|
63
|
-
appInfo: {name:
|
|
86
|
+
appInfo: {name: "agentproto-work-board-panel", version: '0.1.0'},
|
|
64
87
|
appCapabilities: {availableDisplayModes: ['inline', 'fullscreen', 'pip']},
|
|
65
88
|
protocolVersion: '2026-01-26'
|
|
66
89
|
}).then(function(result){
|
|
@@ -74,7 +97,10 @@ function requestDisplayMode(mode){
|
|
|
74
97
|
return rpcRequest('ui/request-display-mode', {mode: mode});
|
|
75
98
|
}
|
|
76
99
|
function callTool(name, args){
|
|
77
|
-
|
|
100
|
+
var raw = _standaloneApp
|
|
101
|
+
? _standaloneApp.callTool(name, args || {})
|
|
102
|
+
: rpcRequest('tools/call', {name: name, arguments: args || {}});
|
|
103
|
+
return raw.then(function(result){
|
|
78
104
|
if (result.isError){
|
|
79
105
|
var e = (result.content && result.content[0] && result.content[0].text) || 'tool error';
|
|
80
106
|
throw new Error(e);
|
|
@@ -148,320 +174,467 @@ function callTool(name, args){
|
|
|
148
174
|
}
|
|
149
175
|
if (document.body) mount();
|
|
150
176
|
else document.addEventListener('DOMContentLoaded', mount);
|
|
151
|
-
})()
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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
|
-
html,body{height:100%;font-family:Menlo,Monaco,'Courier New',monospace;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}
|
|
169
|
-
#app{display:flex;flex-direction:column;height:100%}
|
|
170
|
-
#toolbar{padding:8px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;background:var(--bg2);flex-shrink:0}
|
|
171
|
-
#board-label{font-size:11px;color:var(--text2)}
|
|
172
|
-
#board-id{font-weight:600;color:var(--text);font-size:12px}
|
|
173
|
-
#board-input{background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:4px 8px;border-radius:4px;font-size:12px;font-family:inherit;width:220px}
|
|
174
|
-
.tbtn{background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:4px 10px;border-radius:4px;cursor:pointer;font-size:12px;font-family:inherit}
|
|
175
|
-
.tbtn:hover{background:var(--border)}
|
|
176
|
-
#new-title{flex:1;min-width:120px;background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:4px 8px;border-radius:4px;font-size:12px;font-family:inherit}
|
|
177
|
-
#columns{flex:1;display:flex;overflow-x:auto;overflow-y:hidden}
|
|
178
|
-
.col{width:260px;min-width:220px;flex-shrink:0;display:flex;flex-direction:column;border-right:1px solid var(--border)}
|
|
179
|
-
.col-hdr{padding:8px 10px;border-bottom:1px solid var(--border);background:var(--bg2);font-size:11px;font-weight:600;color:var(--text2);text-transform:uppercase;letter-spacing:.05em;display:flex;justify-content:space-between}
|
|
180
|
-
.col-body{flex:1;overflow-y:auto;padding:8px;display:flex;flex-direction:column;gap:8px}
|
|
181
|
-
.card{background:var(--bg2);border:1px solid var(--border);border-radius:6px;padding:8px 10px}
|
|
182
|
-
.c-title{font-size:12px;font-weight:500;margin-bottom:4px;word-break:break-word}
|
|
183
|
-
.c-id{font-size:10px;color:var(--text2);margin-bottom:6px}
|
|
184
|
-
.c-row{display:flex;flex-wrap:wrap;gap:4px;align-items:center;margin-bottom:6px}
|
|
185
|
-
.tag{display:inline-block;padding:1px 6px;border-radius:10px;font-size:10px;font-weight:600;white-space:nowrap}
|
|
186
|
-
.t-unclaimed{background:rgba(139,148,158,.15);color:var(--text2);border:1px dashed var(--text2)}
|
|
187
|
-
.t-owner{background:rgba(88,166,255,.15);color:var(--blue)}
|
|
188
|
-
.t-gate{background:rgba(63,185,80,.18);color:var(--green)}
|
|
189
|
-
.t-self{background:rgba(210,153,34,.18);color:var(--yellow)}
|
|
190
|
-
.t-human{background:rgba(88,166,255,.18);color:var(--blue)}
|
|
191
|
-
.t-gated{background:rgba(139,148,158,.12);color:var(--text2)}
|
|
192
|
-
.t-cancelled{background:rgba(139,148,158,.12);color:var(--text2)}
|
|
193
|
-
.c-err{font-size:10px;color:var(--red);margin-bottom:6px;word-break:break-word}
|
|
194
|
-
.c-actions{display:flex;flex-wrap:wrap;gap:4px}
|
|
195
|
-
.abtn{background:var(--bg3);border:1px solid var(--border);color:var(--text);padding:3px 8px;border-radius:4px;cursor:pointer;font-size:11px;font-family:inherit}
|
|
196
|
-
.abtn:hover{background:var(--border)}
|
|
197
|
-
.abtn.danger{border-color:var(--red);color:var(--red)}
|
|
198
|
-
.abtn.primary{border-color:var(--green);color:var(--green)}
|
|
199
|
-
#statusbar{padding:4px 12px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}
|
|
200
|
-
.empty{padding:16px 8px;color:var(--text2);font-size:11px;text-align:center}
|
|
201
|
-
</style>
|
|
202
|
-
</head>
|
|
203
|
-
<body>
|
|
204
|
-
<div id="app">
|
|
205
|
-
<div id="toolbar">
|
|
206
|
-
<span id="board-label">Board:</span>
|
|
207
|
-
<span id="board-id">\u2014</span>
|
|
208
|
-
<input id="board-input" type="text" placeholder="tree:<sessionId> or ws:<slug>">
|
|
209
|
-
<button class="tbtn" id="go-btn">Go</button>
|
|
210
|
-
<button class="tbtn" id="refresh-btn" title="Refresh">↻</button>
|
|
211
|
-
<input id="new-title" type="text" placeholder="New task title…">
|
|
212
|
-
<button class="tbtn" id="add-btn">+ Add</button>
|
|
213
|
-
</div>
|
|
214
|
-
<div id="columns"></div>
|
|
215
|
-
<div id="statusbar">Connecting to bridge…</div>
|
|
216
|
-
</div>
|
|
217
|
-
<script>
|
|
218
|
-
${panelBridgeScript("agentproto-work-board-panel")}
|
|
219
|
-
|
|
220
|
-
// ============================================================
|
|
221
|
-
// State
|
|
222
|
-
// ============================================================
|
|
223
|
-
|
|
224
|
-
var COLUMNS = [
|
|
225
|
-
{key: 'pending', label: 'Pending'},
|
|
226
|
-
{key: 'in_progress', label: 'In Progress'},
|
|
227
|
-
{key: 'done', label: 'Done'},
|
|
228
|
-
{key: 'failed', label: 'Failed'}
|
|
229
|
-
];
|
|
230
|
-
|
|
231
|
-
var boardId = null;
|
|
232
|
-
var tasks = [];
|
|
233
|
-
var pollTimer = null;
|
|
234
|
-
var pollActive = false;
|
|
235
|
-
|
|
236
|
-
function setStatus(msg) {
|
|
237
|
-
document.getElementById('statusbar').textContent = msg;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function esc(s) {
|
|
241
|
-
return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// A cancelled task folds into the Failed column, tagged distinctly \u2014 v1
|
|
245
|
-
// treats both as terminal scrap, and a fifth column for a rarely-used
|
|
246
|
-
// status isn't worth the width.
|
|
247
|
-
function columnOf(status) {
|
|
248
|
-
if (status === 'cancelled') return 'failed';
|
|
249
|
-
return status;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// ============================================================
|
|
253
|
-
// Verification tell \u2014 never render an unverified done as gate-passed.
|
|
254
|
-
// ============================================================
|
|
255
|
-
|
|
256
|
-
function verificationTag(t) {
|
|
257
|
-
var v = t.verification;
|
|
258
|
-
if (v) {
|
|
259
|
-
if (v.kind === 'gate') return '<span class="tag t-gate">✓ gate</span>';
|
|
260
|
-
if (v.kind === 'self-report') return '<span class="tag t-self">self-report</span>';
|
|
261
|
-
if (v.kind === 'human') return '<span class="tag t-human">human</span>';
|
|
177
|
+
})();</script>
|
|
178
|
+
<script>(function() {
|
|
179
|
+
"use strict";
|
|
180
|
+
const COLUMN_STATUSES = ["pending", "in_progress", "done", "failed"];
|
|
181
|
+
const COLUMN_LABELS = {
|
|
182
|
+
pending: "Pending",
|
|
183
|
+
in_progress: "In Progress",
|
|
184
|
+
done: "Done",
|
|
185
|
+
failed: "Failed"
|
|
186
|
+
};
|
|
187
|
+
function esc(value) {
|
|
188
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
262
189
|
}
|
|
263
|
-
|
|
264
|
-
return
|
|
190
|
+
function columnOf(status) {
|
|
191
|
+
return status === "cancelled" ? "failed" : status;
|
|
265
192
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
// ============================================================
|
|
278
|
-
|
|
279
|
-
function actionsFor(t) {
|
|
280
|
-
var a = [];
|
|
281
|
-
if (t.status === 'pending') {
|
|
282
|
-
if (!t.owner) a.push({label: 'Claim', action: 'claim', cls: 'primary'});
|
|
283
|
-
else a.push({label: 'Start', action: 'start', cls: 'primary'});
|
|
284
|
-
a.push({label: 'Cancel', action: 'cancel', cls: 'danger'});
|
|
285
|
-
} else if (t.status === 'in_progress') {
|
|
286
|
-
a.push({label: 'Done', action: 'done', cls: 'primary'});
|
|
287
|
-
a.push({label: 'Fail', action: 'fail', cls: 'danger'});
|
|
288
|
-
a.push({label: 'Release', action: 'release', cls: ''});
|
|
289
|
-
a.push({label: 'Cancel', action: 'cancel', cls: 'danger'});
|
|
290
|
-
} else if (t.status === 'done') {
|
|
291
|
-
a.push({label: 'Reopen', action: 'reopen', cls: ''});
|
|
193
|
+
function verificationTag(task) {
|
|
194
|
+
const v = task.verification;
|
|
195
|
+
if (v) {
|
|
196
|
+
if (v.kind === "gate") return '<span class="tag t-gate">✓ gate</span>';
|
|
197
|
+
if (v.kind === "self-report") return '<span class="tag t-self">self-report</span>';
|
|
198
|
+
if (v.kind === "human") return '<span class="tag t-human">human</span>';
|
|
199
|
+
}
|
|
200
|
+
if (task.status === "in_progress" && task.verify) {
|
|
201
|
+
return '<span class="tag t-gated">gated</span>';
|
|
202
|
+
}
|
|
203
|
+
return "";
|
|
292
204
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
function applyAction(taskId, action) {
|
|
297
|
-
var t = null;
|
|
298
|
-
for (var i = 0; i < tasks.length; i++) {
|
|
299
|
-
if (tasks[i].taskId === taskId) { t = tasks[i]; break; }
|
|
205
|
+
function ownerTag(task) {
|
|
206
|
+
if (!task.owner) return '<span class="tag t-unclaimed">Unclaimed</span>';
|
|
207
|
+
return \`<span class="tag t-owner">\${esc(task.owner)}</span>\`;
|
|
300
208
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
209
|
+
function actionsFor(task) {
|
|
210
|
+
if (task.status === "pending") {
|
|
211
|
+
return [
|
|
212
|
+
task.owner ? { label: "Start", action: "start", cls: "primary" } : { label: "Claim", action: "claim", cls: "primary" },
|
|
213
|
+
{ label: "Cancel", action: "cancel", cls: "danger" }
|
|
214
|
+
];
|
|
215
|
+
}
|
|
216
|
+
if (task.status === "in_progress") {
|
|
217
|
+
return [
|
|
218
|
+
{ label: "Done", action: "done", cls: "primary" },
|
|
219
|
+
{ label: "Fail", action: "fail", cls: "danger" },
|
|
220
|
+
{ label: "Release", action: "release", cls: "" },
|
|
221
|
+
{ label: "Cancel", action: "cancel", cls: "danger" }
|
|
222
|
+
];
|
|
223
|
+
}
|
|
224
|
+
if (task.status === "done") {
|
|
225
|
+
return [{ label: "Reopen", action: "reopen", cls: "" }];
|
|
226
|
+
}
|
|
227
|
+
return [];
|
|
319
228
|
}
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
229
|
+
function renderCard(task) {
|
|
230
|
+
let html = \`<div class="card" data-taskid="\${esc(task.taskId)}">\`;
|
|
231
|
+
html += \`<div class="c-title">\${esc(task.title)}</div>\`;
|
|
232
|
+
html += \`<div class="c-id">#\${esc(task.taskId)}</div>\`;
|
|
233
|
+
html += \`<div class="c-row">\${ownerTag(task)}\${verificationTag(task)}\`;
|
|
234
|
+
if (task.status === "cancelled") html += '<span class="tag t-cancelled">cancelled</span>';
|
|
235
|
+
html += "</div>";
|
|
236
|
+
if (task.lastVerifyError) {
|
|
237
|
+
html += \`<div class="c-err">verify failed: \${esc(task.lastVerifyError)}</div>\`;
|
|
327
238
|
}
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
function renderCard(t) {
|
|
339
|
-
var html = '<div class="card" data-taskid="' + esc(t.taskId) + '">';
|
|
340
|
-
html += '<div class="c-title">' + esc(t.title) + '</div>';
|
|
341
|
-
html += '<div class="c-id">#' + esc(t.taskId) + '</div>';
|
|
342
|
-
html += '<div class="c-row">' + ownerTag(t) + verificationTag(t);
|
|
343
|
-
if (t.status === 'cancelled') html += '<span class="tag t-cancelled">cancelled</span>';
|
|
344
|
-
html += '</div>';
|
|
345
|
-
if (t.lastVerifyError) {
|
|
346
|
-
html += '<div class="c-err">verify failed: ' + esc(t.lastVerifyError) + '</div>';
|
|
239
|
+
const actions = actionsFor(task);
|
|
240
|
+
if (actions.length > 0) {
|
|
241
|
+
html += '<div class="c-actions">';
|
|
242
|
+
for (const a of actions) {
|
|
243
|
+
html += \`<button class="abtn \${a.cls}" data-taskid="\${esc(task.taskId)}" data-action="\${a.action}">\${a.label}</button>\`;
|
|
244
|
+
}
|
|
245
|
+
html += "</div>";
|
|
246
|
+
}
|
|
247
|
+
html += "</div>";
|
|
248
|
+
return html;
|
|
347
249
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
html += '<
|
|
250
|
+
function renderColumns(tasks2) {
|
|
251
|
+
let html = "";
|
|
252
|
+
for (const status of COLUMN_STATUSES) {
|
|
253
|
+
const rows = tasks2.filter((t) => columnOf(t.status) === status);
|
|
254
|
+
html += \`<div class="col"><div class="col-hdr"><span>\${COLUMN_LABELS[status]}</span><span>\${rows.length}</span></div><div class="col-body">\`;
|
|
255
|
+
html += rows.length === 0 ? '<div class="empty">No tasks</div>' : rows.map(renderCard).join("");
|
|
256
|
+
html += "</div></div>";
|
|
354
257
|
}
|
|
355
|
-
html
|
|
258
|
+
return html;
|
|
356
259
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function render() {
|
|
362
|
-
document.getElementById('board-id').textContent = boardId || '\u2014';
|
|
363
|
-
if (!document.getElementById('board-input').value) {
|
|
364
|
-
document.getElementById('board-input').value = boardId || '';
|
|
260
|
+
function getEl(id) {
|
|
261
|
+
const el = document.getElementById(id);
|
|
262
|
+
if (!el) throw new Error(\`work board: missing #\${id}\`);
|
|
263
|
+
return el;
|
|
365
264
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
265
|
+
function getInput(id) {
|
|
266
|
+
const el = document.getElementById(id);
|
|
267
|
+
if (!(el instanceof HTMLInputElement)) throw new Error(\`work board: missing input #\${id}\`);
|
|
268
|
+
return el;
|
|
269
|
+
}
|
|
270
|
+
function isCardAction(value) {
|
|
271
|
+
switch (value) {
|
|
272
|
+
case "claim":
|
|
273
|
+
case "start":
|
|
274
|
+
case "done":
|
|
275
|
+
case "fail":
|
|
276
|
+
case "release":
|
|
277
|
+
case "cancel":
|
|
278
|
+
case "reopen":
|
|
279
|
+
return true;
|
|
280
|
+
default:
|
|
281
|
+
return false;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
let boardId = null;
|
|
285
|
+
let tasks = [];
|
|
286
|
+
let pollActive = false;
|
|
287
|
+
function boot() {
|
|
288
|
+
const columnsEl = getEl("columns");
|
|
289
|
+
const statusbarEl = getEl("statusbar");
|
|
290
|
+
const boardIdEl = getEl("board-id");
|
|
291
|
+
const boardInputEl = getInput("board-input");
|
|
292
|
+
const newTitleEl = getInput("new-title");
|
|
293
|
+
function setStatus(msg) {
|
|
294
|
+
statusbarEl.textContent = msg;
|
|
295
|
+
}
|
|
296
|
+
function render() {
|
|
297
|
+
boardIdEl.textContent = boardId ?? "\u2014";
|
|
298
|
+
if (!boardInputEl.value) boardInputEl.value = boardId ?? "";
|
|
299
|
+
columnsEl.innerHTML = renderColumns(tasks);
|
|
300
|
+
}
|
|
301
|
+
function findTask(taskId) {
|
|
302
|
+
return tasks.find((t) => t.taskId === taskId);
|
|
303
|
+
}
|
|
304
|
+
function loadBoard() {
|
|
305
|
+
const args = {
|
|
306
|
+
includeClosed: true,
|
|
307
|
+
full: true,
|
|
308
|
+
...boardId ? { boardId } : {}
|
|
309
|
+
};
|
|
310
|
+
return callTool("task_list", args).then((data) => {
|
|
311
|
+
boardId = data.boardId ?? boardId;
|
|
312
|
+
tasks = data.tasks ?? [];
|
|
313
|
+
render();
|
|
314
|
+
setStatus(\`\${tasks.length} task\${tasks.length === 1 ? "" : "s"} \xB7 \${(/* @__PURE__ */ new Date()).toLocaleTimeString()}\`);
|
|
315
|
+
}).catch((e) => {
|
|
316
|
+
setStatus(\`Error: \${e.message}\`);
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
function applyAction(taskId, action) {
|
|
320
|
+
const task = findTask(taskId);
|
|
321
|
+
if (!task) return;
|
|
322
|
+
const base = { taskId: task.taskId, rev: task.rev };
|
|
323
|
+
let promise;
|
|
324
|
+
if (action === "claim") {
|
|
325
|
+
promise = callTool("task_claim", base);
|
|
326
|
+
} else if (action === "start") {
|
|
327
|
+
promise = callTool("task_update", { ...base, status: "in_progress" });
|
|
328
|
+
} else if (action === "done") {
|
|
329
|
+
promise = callTool("task_update", { ...base, status: "done" });
|
|
330
|
+
} else if (action === "fail") {
|
|
331
|
+
promise = callTool("task_update", { ...base, status: "failed" });
|
|
332
|
+
} else if (action === "release") {
|
|
333
|
+
promise = callTool("task_update", { ...base, owner: null });
|
|
334
|
+
} else if (action === "cancel") {
|
|
335
|
+
promise = callTool("task_update", { ...base, status: "cancelled" });
|
|
336
|
+
} else {
|
|
337
|
+
promise = callTool("task_update", { ...base, status: "pending" });
|
|
338
|
+
}
|
|
339
|
+
promise.then((result) => {
|
|
340
|
+
if ("conflict" in result) {
|
|
341
|
+
setStatus(\`Someone else moved "\${task.title}" first \u2014 refreshed.\`);
|
|
342
|
+
} else if ("error" in result) {
|
|
343
|
+
setStatus(\`Action failed: \${result.error}\`);
|
|
344
|
+
} else {
|
|
345
|
+
setStatus(\`Updated "\${task.title}".\`);
|
|
346
|
+
}
|
|
347
|
+
return loadBoard();
|
|
348
|
+
}).catch((e) => {
|
|
349
|
+
setStatus(\`Action failed: \${e.message}\`);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
function doPoll() {
|
|
353
|
+
if (pollActive) return;
|
|
354
|
+
pollActive = true;
|
|
355
|
+
loadBoard().finally(() => {
|
|
356
|
+
pollActive = false;
|
|
357
|
+
setTimeout(doPoll, 4e3);
|
|
358
|
+
});
|
|
376
359
|
}
|
|
377
|
-
|
|
360
|
+
columnsEl.addEventListener("click", (evt) => {
|
|
361
|
+
if (!(evt.target instanceof Element)) return;
|
|
362
|
+
const btn = evt.target.closest("button[data-action]");
|
|
363
|
+
if (!(btn instanceof HTMLButtonElement)) return;
|
|
364
|
+
const taskId = btn.getAttribute("data-taskid");
|
|
365
|
+
const action = btn.getAttribute("data-action");
|
|
366
|
+
if (!taskId || !action || !isCardAction(action)) return;
|
|
367
|
+
applyAction(taskId, action);
|
|
368
|
+
});
|
|
369
|
+
getEl("refresh-btn").addEventListener("click", () => {
|
|
370
|
+
void loadBoard();
|
|
371
|
+
});
|
|
372
|
+
getEl("go-btn").addEventListener("click", () => {
|
|
373
|
+
const value = boardInputEl.value.trim();
|
|
374
|
+
if (!value) return;
|
|
375
|
+
boardId = value;
|
|
376
|
+
void loadBoard();
|
|
377
|
+
});
|
|
378
|
+
getEl("add-btn").addEventListener("click", () => {
|
|
379
|
+
const title = newTitleEl.value.trim();
|
|
380
|
+
if (!title) return;
|
|
381
|
+
const args = boardId ? { title, boardId } : { title };
|
|
382
|
+
callTool("task_create", args).then((result) => {
|
|
383
|
+
if (result.error) {
|
|
384
|
+
setStatus(\`Create failed: \${result.error}\`);
|
|
385
|
+
return void 0;
|
|
386
|
+
}
|
|
387
|
+
newTitleEl.value = "";
|
|
388
|
+
setStatus(\`Created "\${title}".\`);
|
|
389
|
+
return loadBoard();
|
|
390
|
+
}).catch((e) => {
|
|
391
|
+
setStatus(\`Create failed: \${e.message}\`);
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
initBridge().then(() => loadBoard()).then(() => {
|
|
395
|
+
setTimeout(doPoll, 4e3);
|
|
396
|
+
}).catch((e) => {
|
|
397
|
+
setStatus(\`Bridge error: \${e.message}\`);
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
if (document.readyState === "loading") {
|
|
401
|
+
document.addEventListener("DOMContentLoaded", boot);
|
|
402
|
+
} else {
|
|
403
|
+
boot();
|
|
378
404
|
}
|
|
379
|
-
|
|
405
|
+
})();</script>
|
|
406
|
+
<style rel="stylesheet" crossorigin>/* \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
|
|
407
|
+
Semantic tokens + runtime mapping sheets.
|
|
408
|
+
|
|
409
|
+
Every rule below the next section reads ONLY the --wb-* custom
|
|
410
|
+
properties. Each one resolves through TWO mapping sheets, chosen at
|
|
411
|
+
PAINT time via plain CSS var() fallback \u2014 no build step, no JS, so a
|
|
412
|
+
host that swaps its theme live (VS Code) is never frozen at whatever
|
|
413
|
+
theme happened to be active when this bundle was built:
|
|
414
|
+
|
|
415
|
+
1. embedded \u2014 VS Code injects a live --vscode-* custom-property set
|
|
416
|
+
into the webview and swaps it on theme change. Whenever the
|
|
417
|
+
relevant --vscode-* variable exists, it wins \u2014 in a VS Code
|
|
418
|
+
\`srcdoc\` relay panel AND (structurally identically) any other host
|
|
419
|
+
that happened to expose the same names, though none is known to.
|
|
420
|
+
2. standalone \u2014 the agentproto brand tokens (see
|
|
421
|
+
projects/agentproto/site/src/app/brand.css), used whenever no
|
|
422
|
+
--vscode-* variable is set \u2014 a plain MCP-Apps host or the daemon's
|
|
423
|
+
own \`/apps/.../ui\` tab. \`--phos\`/\`--amber\`/\`--crimson\` are
|
|
424
|
+
THEME-INVARIANT in brand.css (the phosphor terminal palette), so
|
|
425
|
+
they're identical in both blocks below; the rest follow brand.css's
|
|
426
|
+
light/dark split via \`prefers-color-scheme\` \u2014 a standalone tab has
|
|
427
|
+
no host to pick a theme for it, unlike VS Code's own.
|
|
428
|
+
\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550 */
|
|
429
|
+
|
|
430
|
+
:root {
|
|
431
|
+
--wb-bg: var(--vscode-editor-background, #f5f6f3);
|
|
432
|
+
--wb-surface: var(--vscode-sideBar-background, #ffffff);
|
|
433
|
+
--wb-ink: var(--vscode-editor-foreground, #171a1e);
|
|
434
|
+
--wb-ink-muted: var(--vscode-descriptionForeground, #5c6470);
|
|
435
|
+
--wb-border: var(--vscode-panel-border, #dde0da);
|
|
436
|
+
--wb-accent: var(--vscode-button-background, #0f62fe);
|
|
437
|
+
|
|
438
|
+
/* Status colors \u2014 phos/amber/crimson are the theme-invariant terminal
|
|
439
|
+
palette in brand.css, so light and dark standalone fallbacks match. */
|
|
440
|
+
--wb-status-pending: var(--vscode-descriptionForeground, #5c6470);
|
|
441
|
+
--wb-status-in-progress: var(--vscode-charts-yellow, #f0b429);
|
|
442
|
+
--wb-status-done: var(--vscode-charts-green, #3edc81);
|
|
443
|
+
--wb-status-failed: var(--vscode-charts-red, #fa4d56);
|
|
444
|
+
--wb-status-cancelled: var(--vscode-descriptionForeground, #5c6470);
|
|
445
|
+
--wb-status-cancelled-weak: color-mix(in srgb, var(--wb-status-cancelled) 55%, transparent);
|
|
380
446
|
}
|
|
381
447
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
448
|
+
@media (prefers-color-scheme: dark) {
|
|
449
|
+
:root {
|
|
450
|
+
--wb-bg: var(--vscode-editor-background, #101214);
|
|
451
|
+
--wb-surface: var(--vscode-sideBar-background, #16191d);
|
|
452
|
+
--wb-ink: var(--vscode-editor-foreground, #e8eaed);
|
|
453
|
+
--wb-ink-muted: var(--vscode-descriptionForeground, #99a2ad);
|
|
454
|
+
--wb-border: var(--vscode-panel-border, #272c33);
|
|
455
|
+
--wb-accent: var(--vscode-button-background, #4589ff);
|
|
456
|
+
|
|
457
|
+
--wb-status-pending: var(--vscode-descriptionForeground, #99a2ad);
|
|
458
|
+
--wb-status-in-progress: var(--vscode-charts-yellow, #f0b429);
|
|
459
|
+
--wb-status-done: var(--vscode-charts-green, #3edc81);
|
|
460
|
+
--wb-status-failed: var(--vscode-charts-red, #fa4d56);
|
|
461
|
+
--wb-status-cancelled: var(--vscode-descriptionForeground, #99a2ad);
|
|
462
|
+
--wb-status-cancelled-weak: color-mix(in srgb, var(--wb-status-cancelled) 55%, transparent);
|
|
463
|
+
}
|
|
397
464
|
}
|
|
398
465
|
|
|
399
|
-
|
|
400
|
-
if (pollActive) return;
|
|
401
|
-
pollActive = true;
|
|
402
|
-
loadBoard().then(function () {
|
|
403
|
-
pollActive = false;
|
|
404
|
-
pollTimer = setTimeout(doPoll, 4000);
|
|
405
|
-
}).catch(function () {
|
|
406
|
-
pollActive = false;
|
|
407
|
-
pollTimer = setTimeout(doPoll, 4000);
|
|
408
|
-
});
|
|
409
|
-
}
|
|
466
|
+
/* \u2500\u2500 Base \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
410
467
|
|
|
411
|
-
|
|
412
|
-
// Toolbar wiring
|
|
413
|
-
// ============================================================
|
|
468
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
414
469
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
470
|
+
html, body {
|
|
471
|
+
height: 100%;
|
|
472
|
+
font-family: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
473
|
+
font-size: 13px;
|
|
474
|
+
background: var(--wb-bg);
|
|
475
|
+
color: var(--wb-ink);
|
|
476
|
+
overflow: hidden;
|
|
477
|
+
}
|
|
420
478
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
}
|
|
479
|
+
.mono {
|
|
480
|
+
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, "Courier New", monospace;
|
|
481
|
+
}
|
|
424
482
|
|
|
425
|
-
|
|
426
|
-
var v = document.getElementById('board-input').value.trim();
|
|
427
|
-
if (!v) return;
|
|
428
|
-
boardId = v;
|
|
429
|
-
loadBoard();
|
|
430
|
-
});
|
|
483
|
+
#app { display: flex; flex-direction: column; height: 100%; }
|
|
431
484
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
485
|
+
#toolbar {
|
|
486
|
+
padding: 8px 12px;
|
|
487
|
+
border-bottom: 1px solid var(--wb-border);
|
|
488
|
+
display: flex;
|
|
489
|
+
align-items: center;
|
|
490
|
+
gap: 8px;
|
|
491
|
+
background: var(--wb-surface);
|
|
492
|
+
flex-shrink: 0;
|
|
493
|
+
}
|
|
494
|
+
#board-label { font-size: 11px; color: var(--wb-ink-muted); }
|
|
495
|
+
#board-id { font-weight: 600; color: var(--wb-ink); font-size: 12px; font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, "Courier New", monospace; }
|
|
496
|
+
#board-input {
|
|
497
|
+
background: var(--wb-bg);
|
|
498
|
+
border: 1px solid var(--wb-border);
|
|
499
|
+
color: var(--wb-ink);
|
|
500
|
+
padding: 4px 8px;
|
|
501
|
+
border-radius: 4px;
|
|
502
|
+
font-size: 12px;
|
|
503
|
+
font-family: inherit;
|
|
504
|
+
width: 220px;
|
|
505
|
+
}
|
|
506
|
+
.tbtn {
|
|
507
|
+
background: var(--wb-bg);
|
|
508
|
+
border: 1px solid var(--wb-border);
|
|
509
|
+
color: var(--wb-ink);
|
|
510
|
+
padding: 4px 10px;
|
|
511
|
+
border-radius: 4px;
|
|
512
|
+
cursor: pointer;
|
|
513
|
+
font-size: 12px;
|
|
514
|
+
font-family: inherit;
|
|
515
|
+
}
|
|
516
|
+
.tbtn:hover { background: var(--wb-border); }
|
|
517
|
+
#new-title {
|
|
518
|
+
flex: 1;
|
|
519
|
+
min-width: 120px;
|
|
520
|
+
background: var(--wb-bg);
|
|
521
|
+
border: 1px solid var(--wb-border);
|
|
522
|
+
color: var(--wb-ink);
|
|
523
|
+
padding: 4px 8px;
|
|
524
|
+
border-radius: 4px;
|
|
525
|
+
font-size: 12px;
|
|
526
|
+
font-family: inherit;
|
|
527
|
+
}
|
|
450
528
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
529
|
+
#columns { flex: 1; display: flex; overflow-x: auto; overflow-y: hidden; }
|
|
530
|
+
.col {
|
|
531
|
+
width: 260px;
|
|
532
|
+
min-width: 220px;
|
|
533
|
+
flex-shrink: 0;
|
|
534
|
+
display: flex;
|
|
535
|
+
flex-direction: column;
|
|
536
|
+
border-right: 1px solid var(--wb-border);
|
|
537
|
+
}
|
|
538
|
+
.col-hdr {
|
|
539
|
+
padding: 8px 10px;
|
|
540
|
+
border-bottom: 1px solid var(--wb-border);
|
|
541
|
+
background: var(--wb-surface);
|
|
542
|
+
font-size: 11px;
|
|
543
|
+
font-weight: 600;
|
|
544
|
+
color: var(--wb-ink-muted);
|
|
545
|
+
text-transform: uppercase;
|
|
546
|
+
letter-spacing: 0.05em;
|
|
547
|
+
display: flex;
|
|
548
|
+
justify-content: space-between;
|
|
549
|
+
}
|
|
550
|
+
.col-body { flex: 1; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 8px; }
|
|
454
551
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
}
|
|
462
|
-
|
|
552
|
+
.card {
|
|
553
|
+
background: var(--wb-surface);
|
|
554
|
+
border: 1px solid var(--wb-border);
|
|
555
|
+
border-radius: 6px;
|
|
556
|
+
padding: 8px 10px;
|
|
557
|
+
}
|
|
558
|
+
.c-title { font-size: 12px; font-weight: 500; margin-bottom: 4px; word-break: break-word; }
|
|
559
|
+
.c-id {
|
|
560
|
+
font-size: 10px;
|
|
561
|
+
color: var(--wb-ink-muted);
|
|
562
|
+
margin-bottom: 6px;
|
|
563
|
+
font-family: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, "Courier New", monospace;
|
|
564
|
+
}
|
|
565
|
+
.c-row { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-bottom: 6px; }
|
|
566
|
+
|
|
567
|
+
.tag { display: inline-block; padding: 1px 6px; border-radius: 10px; font-size: 10px; font-weight: 600; white-space: nowrap; }
|
|
568
|
+
.t-unclaimed { background: color-mix(in srgb, var(--wb-ink-muted) 15%, transparent); color: var(--wb-ink-muted); border: 1px dashed var(--wb-ink-muted); }
|
|
569
|
+
.t-owner { background: color-mix(in srgb, var(--wb-accent) 15%, transparent); color: var(--wb-accent); }
|
|
570
|
+
|
|
571
|
+
/* Verification tell: gate solid green, self-report amber outline, human
|
|
572
|
+
blue, a declared verify with no verification yet grey "gated" \u2014 never
|
|
573
|
+
render an unverified done as gate-passed (see render.ts's verificationTag). */
|
|
574
|
+
.t-gate { background: color-mix(in srgb, var(--wb-status-done) 18%, transparent); color: var(--wb-status-done); }
|
|
575
|
+
.t-self { background: transparent; color: var(--wb-status-in-progress); border: 1px solid var(--wb-status-in-progress); }
|
|
576
|
+
.t-human { background: color-mix(in srgb, var(--wb-accent) 18%, transparent); color: var(--wb-accent); }
|
|
577
|
+
.t-gated { background: color-mix(in srgb, var(--wb-ink-muted) 12%, transparent); color: var(--wb-ink-muted); }
|
|
578
|
+
.t-cancelled {
|
|
579
|
+
background: color-mix(in srgb, var(--wb-status-cancelled) 10%, transparent);
|
|
580
|
+
color: var(--wb-status-cancelled-weak);
|
|
581
|
+
border: 1px dashed color-mix(in srgb, var(--wb-status-cancelled) 40%, transparent);
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.c-err { font-size: 10px; color: var(--wb-status-failed); margin-bottom: 6px; word-break: break-word; }
|
|
585
|
+
.c-actions { display: flex; flex-wrap: wrap; gap: 4px; }
|
|
586
|
+
.abtn {
|
|
587
|
+
background: var(--wb-bg);
|
|
588
|
+
border: 1px solid var(--wb-border);
|
|
589
|
+
color: var(--wb-ink);
|
|
590
|
+
padding: 3px 8px;
|
|
591
|
+
border-radius: 4px;
|
|
592
|
+
cursor: pointer;
|
|
593
|
+
font-size: 11px;
|
|
594
|
+
font-family: inherit;
|
|
595
|
+
}
|
|
596
|
+
.abtn:hover { background: var(--wb-border); }
|
|
597
|
+
.abtn.danger { border-color: var(--wb-status-failed); color: var(--wb-status-failed); }
|
|
598
|
+
.abtn.primary { border-color: var(--wb-status-done); color: var(--wb-status-done); }
|
|
599
|
+
|
|
600
|
+
#statusbar {
|
|
601
|
+
padding: 4px 12px;
|
|
602
|
+
font-size: 11px;
|
|
603
|
+
color: var(--wb-ink-muted);
|
|
604
|
+
border-top: 1px solid var(--wb-border);
|
|
605
|
+
background: var(--wb-surface);
|
|
606
|
+
flex-shrink: 0;
|
|
607
|
+
}
|
|
608
|
+
.empty { padding: 16px 8px; color: var(--wb-ink-muted); font-size: 11px; text-align: center; }</style>
|
|
609
|
+
</head>
|
|
610
|
+
<body>
|
|
611
|
+
<div id="app">
|
|
612
|
+
<div id="toolbar">
|
|
613
|
+
<span id="board-label">Board:</span>
|
|
614
|
+
<span id="board-id">\u2014</span>
|
|
615
|
+
<input id="board-input" type="text" placeholder="tree:<sessionId> or ws:<slug>">
|
|
616
|
+
<button class="tbtn" id="go-btn">Go</button>
|
|
617
|
+
<button class="tbtn" id="refresh-btn" title="Refresh">↻</button>
|
|
618
|
+
<input id="new-title" type="text" placeholder="New task title…">
|
|
619
|
+
<button class="tbtn" id="add-btn">+ Add</button>
|
|
620
|
+
</div>
|
|
621
|
+
<div id="columns"></div>
|
|
622
|
+
<div id="statusbar">Connecting to bridge…</div>
|
|
623
|
+
</div>
|
|
463
624
|
</body>
|
|
464
|
-
</html
|
|
625
|
+
</html>
|
|
626
|
+
`;
|
|
627
|
+
|
|
628
|
+
// src/work-board/panel.ts
|
|
629
|
+
var WORK_BOARD_APP_ID = "@agentproto/work-board";
|
|
630
|
+
var WORK_BOARD_TOOL_ID = "agentproto_work_board";
|
|
631
|
+
var WORK_BOARD_UI_TOOLS = [
|
|
632
|
+
"task_list",
|
|
633
|
+
"task_claim",
|
|
634
|
+
"task_update",
|
|
635
|
+
"task_create"
|
|
636
|
+
];
|
|
637
|
+
var WORK_BOARD_HTML = WORK_BOARD_HTML_GENERATED;
|
|
465
638
|
|
|
466
639
|
// src/work-board/index.ts
|
|
467
640
|
var workBoardInputSchema = z.object({
|
|
@@ -471,7 +644,7 @@ var workBoardInputSchema = z.object({
|
|
|
471
644
|
});
|
|
472
645
|
function makeWorkBoardApp(ops) {
|
|
473
646
|
return {
|
|
474
|
-
id:
|
|
647
|
+
id: WORK_BOARD_TOOL_ID,
|
|
475
648
|
title: "Work Board",
|
|
476
649
|
description: "Open the agentproto work board \u2014 a kanban over the daemon's Task ledger (columns: pending/in_progress/done/failed, cancelled folded into failed). Swimlane is the ledger's own board id (`tree:<root>` or `ws:<slug>`). Each card shows its owner (or \"Unclaimed\") and the verification tell \u2014 a gate-passed done reads visually distinct from a self-reported one. Pass `boardId` to open a specific board.",
|
|
477
650
|
inputSchema: workBoardInputSchema,
|
|
@@ -480,14 +653,14 @@ function makeWorkBoardApp(ops) {
|
|
|
480
653
|
};
|
|
481
654
|
}
|
|
482
655
|
var workBoardApp = defineApp({
|
|
483
|
-
id:
|
|
656
|
+
id: WORK_BOARD_APP_ID,
|
|
484
657
|
name: "Work Board",
|
|
485
658
|
description: "Open the agentproto work board \u2014 a kanban over the daemon's Task ledger, scoped by board id (`tree:<rootSessionId>` or `ws:<slug>`), with an explicit status action per card.",
|
|
486
659
|
agents: [],
|
|
487
660
|
ui: {
|
|
488
661
|
html: WORK_BOARD_HTML,
|
|
489
662
|
title: "Work Board",
|
|
490
|
-
tools: [
|
|
663
|
+
tools: [...WORK_BOARD_UI_TOOLS]
|
|
491
664
|
}
|
|
492
665
|
});
|
|
493
666
|
|