@agentproto/apps 0.9.1 → 0.10.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 +12 -10
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +442 -1
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-app-types.d.ts +4 -0
- package/dist/mcp-app-types.d.ts.map +1 -1
- package/dist/session-chat/index.d.ts +72 -0
- package/dist/session-chat/index.d.ts.map +1 -0
- package/dist/session-chat/panel.d.ts +28 -0
- package/dist/session-chat/panel.d.ts.map +1 -0
- package/dist/session-chat/panel.mjs +65 -0
- package/dist/session-chat/panel.mjs.map +1 -0
- package/dist/session-chat.mjs +113 -0
- package/dist/session-chat.mjs.map +1 -0
- package/dist/work-board/index.d.ts +67 -0
- package/dist/work-board/index.d.ts.map +1 -0
- package/dist/work-board/panel.d.ts +39 -0
- package/dist/work-board/panel.d.ts.map +1 -0
- package/dist/work-board/panel.mjs +464 -0
- package/dist/work-board/panel.mjs.map +1 -0
- package/dist/work-board.mjs +496 -0
- package/dist/work-board.mjs.map +1 -0
- package/package.json +28 -8
package/README.md
CHANGED
|
@@ -60,10 +60,10 @@ panels" above), independent of this file and of `~/.agentproto/apps.json`.
|
|
|
60
60
|
|
|
61
61
|
## Builtin daemon panels
|
|
62
62
|
|
|
63
|
-
|
|
64
|
-
as house-app-quality code — but they are **not** `AppHandle`s
|
|
65
|
-
requires a non-empty `agents` array, and these are pure
|
|
66
|
-
no agent of their own):
|
|
63
|
+
Several of `@agentproto/runtime`'s daemon-builtin MCP-Apps widgets live here
|
|
64
|
+
too, as house-app-quality code — but they are **not** `AppHandle`s
|
|
65
|
+
(`defineApp` requires a non-empty `agents` array, and these are pure
|
|
66
|
+
read-only viewers/actuators with no agent of their own):
|
|
67
67
|
|
|
68
68
|
| Panel | Import | MCP tool id |
|
|
69
69
|
| --- | --- | --- |
|
|
@@ -72,15 +72,17 @@ no agent of their own):
|
|
|
72
72
|
| `bureau-sessions` | `@agentproto/apps/bureau-sessions` | `agentproto_bureau_sessions` |
|
|
73
73
|
| `session-story` | `@agentproto/apps/session-story` | `agentproto_session_story` |
|
|
74
74
|
| `live-session` | `@agentproto/apps/live-session` | `live_session` |
|
|
75
|
+
| `session-chat` | `@agentproto/apps/session-chat` | `agentproto_session_chat` |
|
|
76
|
+
| `work-board` | `@agentproto/apps/work-board` | `agentproto_work_board` |
|
|
75
77
|
|
|
76
78
|
Each exports a `make<Name>App(ops)` factory producing an `AgnoMcpApp` — the
|
|
77
79
|
shape `@agentproto/runtime`'s `mcp-apps-adapter.ts` mounts on the daemon's MCP
|
|
78
|
-
server. `@agentproto/runtime`'s `builtin-apps.ts` wraps these
|
|
79
|
-
daemon's own session registry and
|
|
80
|
-
`app_install` step, and they're
|
|
81
|
-
`category: "builtin"`.
|
|
82
|
-
`@agentproto/runtime` (`terminal-panel-app.ts`)
|
|
83
|
-
WebSocket, not a portable tool-call-driven `AgnoMcpApp`.
|
|
80
|
+
server. `@agentproto/runtime`'s `builtin-apps.ts` wraps these with the
|
|
81
|
+
daemon's own session registry (and, for `work-board`, its Task ledger) and
|
|
82
|
+
mounts them at boot, unconditionally — no `app_install` step, and they're
|
|
83
|
+
always listed in `app_catalog` under `category: "builtin"`. One more builtin
|
|
84
|
+
panel, the terminal, stays in `@agentproto/runtime` (`terminal-panel-app.ts`)
|
|
85
|
+
— it needs a live PTY WebSocket, not a portable tool-call-driven `AgnoMcpApp`.
|
|
84
86
|
|
|
85
87
|
## Generic by design
|
|
86
88
|
|
package/dist/index.d.ts
CHANGED
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
* folder (`code-team/`, `content-team/`) with `agents/` + `workflows/`, and is
|
|
17
17
|
* re-exported here + as a subpath (`@agentproto/apps/<team>`).
|
|
18
18
|
*
|
|
19
|
-
* This package also carries
|
|
20
|
-
* `agents-overview`, `bureau-sessions`, `session-story`, `live-session
|
|
21
|
-
* @agentproto/runtime's house-app-quality UI
|
|
19
|
+
* This package also carries the daemon-builtin panels (`sessions-panel`,
|
|
20
|
+
* `agents-overview`, `bureau-sessions`, `session-story`, `live-session`,
|
|
21
|
+
* `session-chat`, `work-board`) — @agentproto/runtime's house-app-quality UI
|
|
22
|
+
* widgets. Each ships in two
|
|
22
23
|
* forms: a real `AppHandle` (`agents: []`, UI-only — the catalog/emit/
|
|
23
24
|
* `app_install` path, e.g. `sessionsPanelApp`) AND a separate
|
|
24
25
|
* `make<Name>App(ops)` factory producing the `AgnoMcpApp` shape
|
|
@@ -46,4 +47,8 @@ export { makeSessionStoryPanelApp, sessionStoryApp } from "./session-story/index
|
|
|
46
47
|
export type { SessionStoryOps, SessionStoryInput, SessionStoryOutput } from "./session-story/index.js";
|
|
47
48
|
export { makeLiveSessionApp, liveSessionApp } from "./live-session/index.js";
|
|
48
49
|
export type { LiveSessionOps, LiveSessionInput, LiveSessionOutput } from "./live-session/index.js";
|
|
50
|
+
export { makeSessionChatApp, sessionChatApp, sessionChatAppUrl, SESSION_CHAT_APP_ID, SESSION_CHAT_FALLBACK_HTML, sessionChatEmbedHtml, } from "./session-chat/index.js";
|
|
51
|
+
export type { SessionChatOps, SessionChatInput, SessionChatOutput, } from "./session-chat/index.js";
|
|
52
|
+
export { makeWorkBoardApp, workBoardApp } from "./work-board/index.js";
|
|
53
|
+
export type { WorkBoardOps, WorkBoardInput, WorkBoardOutput } from "./work-board/index.js";
|
|
49
54
|
//# 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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;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;AAClG,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,yBAAyB,CAAA;AAChC,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACtE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -5490,6 +5490,447 @@ var liveSessionApp = defineApp({
|
|
|
5490
5490
|
}
|
|
5491
5491
|
});
|
|
5492
5492
|
|
|
5493
|
-
|
|
5493
|
+
// src/session-chat/panel.ts
|
|
5494
|
+
function escapeAttr(text) {
|
|
5495
|
+
return text.replace(/&/g, "&").replace(/"/g, """);
|
|
5496
|
+
}
|
|
5497
|
+
function sessionChatEmbedHtml(initData) {
|
|
5498
|
+
const url = initData.url;
|
|
5499
|
+
const link = url != null ? `<a href="${escapeAttr(url)}" target="_blank" rel="noreferrer">open in a tab</a>` : "app not installed";
|
|
5500
|
+
const iframe = url != null ? `<iframe id="chat" title="Session Chat" src="${escapeAttr(url)}"></iframe>` : "";
|
|
5501
|
+
return `<!DOCTYPE html>
|
|
5502
|
+
<html lang="en">
|
|
5503
|
+
<head>
|
|
5504
|
+
<meta charset="UTF-8">
|
|
5505
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5506
|
+
<title>Session Chat</title>
|
|
5507
|
+
<style>
|
|
5508
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
5509
|
+
html,body{height:100%;font-family:system-ui,-apple-system,sans-serif;background:#0d1117;color:#e6edf3;overflow:hidden}
|
|
5510
|
+
#bar{padding:6px 12px;font-size:12px;color:#8b949e;background:#161b22;border-bottom:1px solid #30363d}
|
|
5511
|
+
#bar a{color:#58a6ff}
|
|
5512
|
+
#chat{border:0;display:block;width:100%;height:calc(100% - 29px)}
|
|
5513
|
+
</style>
|
|
5514
|
+
</head>
|
|
5515
|
+
<body>
|
|
5516
|
+
<div id="bar">Session Chat · ${link}</div>
|
|
5517
|
+
${iframe}
|
|
5518
|
+
</body>
|
|
5519
|
+
</html>`;
|
|
5520
|
+
}
|
|
5521
|
+
var SESSION_CHAT_FALLBACK_HTML = `<!DOCTYPE html>
|
|
5522
|
+
<html lang="en">
|
|
5523
|
+
<head>
|
|
5524
|
+
<meta charset="UTF-8">
|
|
5525
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5526
|
+
<title>Session Chat \u2014 not installed</title>
|
|
5527
|
+
<style>
|
|
5528
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
5529
|
+
html,body{height:100%;font-family:system-ui,-apple-system,sans-serif;background:#0d1117;color:#e6edf3}
|
|
5530
|
+
#wrap{max-width:560px;margin:0 auto;padding:48px 24px;line-height:1.6}
|
|
5531
|
+
h1{font-size:18px;margin-bottom:12px}
|
|
5532
|
+
code{background:#161b22;border:1px solid #30363d;border-radius:4px;padding:2px 6px;font-size:13px}
|
|
5533
|
+
p{margin:8px 0;color:#8b949e;font-size:13px}
|
|
5534
|
+
</style>
|
|
5535
|
+
</head>
|
|
5536
|
+
<body>
|
|
5537
|
+
<div id="wrap">
|
|
5538
|
+
<h1>Session Chat is not installed</h1>
|
|
5539
|
+
<p>This panel is a thin launcher for the <code>@agentik/session-chat</code> app —
|
|
5540
|
+
it does not bundle the chat UI itself.</p>
|
|
5541
|
+
<p>To use it, install the app into this daemon:</p>
|
|
5542
|
+
<p><code>agentproto app install @agentik/session-chat</code></p>
|
|
5543
|
+
<p>Once installed, call <code>agentproto_session_chat</code> again (optionally with a
|
|
5544
|
+
<code>sessionId</code>) and the panel will embed the app's chat UI deep-linked to that
|
|
5545
|
+
session.</p>
|
|
5546
|
+
</div>
|
|
5547
|
+
</body>
|
|
5548
|
+
</html>`;
|
|
5549
|
+
|
|
5550
|
+
// src/session-chat/index.ts
|
|
5551
|
+
var SESSION_CHAT_APP_ID = "@agentik/session-chat";
|
|
5552
|
+
var sessionChatInputSchema = z.object({
|
|
5553
|
+
sessionId: z.string().optional().describe(
|
|
5554
|
+
"Deep-link the chat to an existing session by id (e.g. `sess_xxx`). Omit to open the app with its session picker."
|
|
5555
|
+
)
|
|
5556
|
+
});
|
|
5557
|
+
function sessionChatAppUrl(httpBaseUrl, sessionId) {
|
|
5558
|
+
const base = `${httpBaseUrl.replace(/\/+$/, "")}/apps/${SESSION_CHAT_APP_ID}/ui`;
|
|
5559
|
+
const params = new URLSearchParams();
|
|
5560
|
+
if (sessionId) params.set("session", sessionId);
|
|
5561
|
+
params.set("embed", "1");
|
|
5562
|
+
return `${base}?${params.toString()}`;
|
|
5563
|
+
}
|
|
5564
|
+
function frameOrigin(httpBaseUrl) {
|
|
5565
|
+
return new URL(httpBaseUrl).origin;
|
|
5566
|
+
}
|
|
5567
|
+
function makeSessionChatApp(ops) {
|
|
5568
|
+
const installed = ops.isSessionChatInstalled?.() ?? false;
|
|
5569
|
+
return {
|
|
5570
|
+
id: "agentproto_session_chat",
|
|
5571
|
+
title: "Session Chat",
|
|
5572
|
+
description: "Open the Session Chat app \u2014 a chat-thread view of any agentproto daemon session: full transcript replay, live follow-over SSE, and a composer that sends prompts into the same session. Requires the `@agentik/session-chat` app to be installed; without it the panel shows install instructions. Pass `sessionId` to deep-link straight into a known session.",
|
|
5573
|
+
inputSchema: sessionChatInputSchema,
|
|
5574
|
+
execute: async (input) => ({
|
|
5575
|
+
installed,
|
|
5576
|
+
url: installed ? sessionChatAppUrl(ops.httpBaseUrl, input.sessionId) : null
|
|
5577
|
+
}),
|
|
5578
|
+
html: (initData) => sessionChatEmbedHtml(initData),
|
|
5579
|
+
csp: { frameDomains: [frameOrigin(ops.httpBaseUrl)] }
|
|
5580
|
+
};
|
|
5581
|
+
}
|
|
5582
|
+
var sessionChatApp = defineApp({
|
|
5583
|
+
id: "@agentproto/session-chat-widget",
|
|
5584
|
+
name: "Session Chat",
|
|
5585
|
+
description: "Open the Session Chat app \u2014 a chat-thread view of any agentproto daemon session, deep-linked by sessionId. A thin builtin launcher for the installed @agentik/session-chat app.",
|
|
5586
|
+
agents: [],
|
|
5587
|
+
ui: {
|
|
5588
|
+
html: SESSION_CHAT_FALLBACK_HTML,
|
|
5589
|
+
title: "Session Chat",
|
|
5590
|
+
tools: ["session_list", "agent_start", "adapter_list", "conversation_read"]
|
|
5591
|
+
}
|
|
5592
|
+
});
|
|
5593
|
+
|
|
5594
|
+
// src/work-board/panel.ts
|
|
5595
|
+
var WORK_BOARD_HTML = `<!DOCTYPE html>
|
|
5596
|
+
<html lang="en">
|
|
5597
|
+
<head>
|
|
5598
|
+
<meta charset="UTF-8">
|
|
5599
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
5600
|
+
<title>agentproto work board</title>
|
|
5601
|
+
<style>
|
|
5602
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
5603
|
+
:root{
|
|
5604
|
+
--bg:#0d1117;--bg2:#161b22;--bg3:#21262d;--border:#30363d;
|
|
5605
|
+
--text:#e6edf3;--text2:#8b949e;
|
|
5606
|
+
--green:#3fb950;--yellow:#d29922;--red:#f85149;--blue:#58a6ff;--purple:#bc8cff;
|
|
5607
|
+
}
|
|
5608
|
+
html,body{height:100%;font-family:Menlo,Monaco,'Courier New',monospace;font-size:13px;background:var(--bg);color:var(--text);overflow:hidden}
|
|
5609
|
+
#app{display:flex;flex-direction:column;height:100%}
|
|
5610
|
+
#toolbar{padding:8px 12px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:8px;background:var(--bg2);flex-shrink:0}
|
|
5611
|
+
#board-label{font-size:11px;color:var(--text2)}
|
|
5612
|
+
#board-id{font-weight:600;color:var(--text);font-size:12px}
|
|
5613
|
+
#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}
|
|
5614
|
+
.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}
|
|
5615
|
+
.tbtn:hover{background:var(--border)}
|
|
5616
|
+
#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}
|
|
5617
|
+
#columns{flex:1;display:flex;overflow-x:auto;overflow-y:hidden}
|
|
5618
|
+
.col{width:260px;min-width:220px;flex-shrink:0;display:flex;flex-direction:column;border-right:1px solid var(--border)}
|
|
5619
|
+
.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}
|
|
5620
|
+
.col-body{flex:1;overflow-y:auto;padding:8px;display:flex;flex-direction:column;gap:8px}
|
|
5621
|
+
.card{background:var(--bg2);border:1px solid var(--border);border-radius:6px;padding:8px 10px}
|
|
5622
|
+
.c-title{font-size:12px;font-weight:500;margin-bottom:4px;word-break:break-word}
|
|
5623
|
+
.c-id{font-size:10px;color:var(--text2);margin-bottom:6px}
|
|
5624
|
+
.c-row{display:flex;flex-wrap:wrap;gap:4px;align-items:center;margin-bottom:6px}
|
|
5625
|
+
.tag{display:inline-block;padding:1px 6px;border-radius:10px;font-size:10px;font-weight:600;white-space:nowrap}
|
|
5626
|
+
.t-unclaimed{background:rgba(139,148,158,.15);color:var(--text2);border:1px dashed var(--text2)}
|
|
5627
|
+
.t-owner{background:rgba(88,166,255,.15);color:var(--blue)}
|
|
5628
|
+
.t-gate{background:rgba(63,185,80,.18);color:var(--green)}
|
|
5629
|
+
.t-self{background:rgba(210,153,34,.18);color:var(--yellow)}
|
|
5630
|
+
.t-human{background:rgba(88,166,255,.18);color:var(--blue)}
|
|
5631
|
+
.t-gated{background:rgba(139,148,158,.12);color:var(--text2)}
|
|
5632
|
+
.t-cancelled{background:rgba(139,148,158,.12);color:var(--text2)}
|
|
5633
|
+
.c-err{font-size:10px;color:var(--red);margin-bottom:6px;word-break:break-word}
|
|
5634
|
+
.c-actions{display:flex;flex-wrap:wrap;gap:4px}
|
|
5635
|
+
.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}
|
|
5636
|
+
.abtn:hover{background:var(--border)}
|
|
5637
|
+
.abtn.danger{border-color:var(--red);color:var(--red)}
|
|
5638
|
+
.abtn.primary{border-color:var(--green);color:var(--green)}
|
|
5639
|
+
#statusbar{padding:4px 12px;font-size:11px;color:var(--text2);border-top:1px solid var(--border);background:var(--bg2);flex-shrink:0}
|
|
5640
|
+
.empty{padding:16px 8px;color:var(--text2);font-size:11px;text-align:center}
|
|
5641
|
+
</style>
|
|
5642
|
+
</head>
|
|
5643
|
+
<body>
|
|
5644
|
+
<div id="app">
|
|
5645
|
+
<div id="toolbar">
|
|
5646
|
+
<span id="board-label">Board:</span>
|
|
5647
|
+
<span id="board-id">\u2014</span>
|
|
5648
|
+
<input id="board-input" type="text" placeholder="tree:<sessionId> or ws:<slug>">
|
|
5649
|
+
<button class="tbtn" id="go-btn">Go</button>
|
|
5650
|
+
<button class="tbtn" id="refresh-btn" title="Refresh">↻</button>
|
|
5651
|
+
<input id="new-title" type="text" placeholder="New task title…">
|
|
5652
|
+
<button class="tbtn" id="add-btn">+ Add</button>
|
|
5653
|
+
</div>
|
|
5654
|
+
<div id="columns"></div>
|
|
5655
|
+
<div id="statusbar">Connecting to bridge…</div>
|
|
5656
|
+
</div>
|
|
5657
|
+
<script>
|
|
5658
|
+
${panelBridgeScript("agentproto-work-board-panel")}
|
|
5659
|
+
|
|
5660
|
+
// ============================================================
|
|
5661
|
+
// State
|
|
5662
|
+
// ============================================================
|
|
5663
|
+
|
|
5664
|
+
var COLUMNS = [
|
|
5665
|
+
{key: 'pending', label: 'Pending'},
|
|
5666
|
+
{key: 'in_progress', label: 'In Progress'},
|
|
5667
|
+
{key: 'done', label: 'Done'},
|
|
5668
|
+
{key: 'failed', label: 'Failed'}
|
|
5669
|
+
];
|
|
5670
|
+
|
|
5671
|
+
var boardId = null;
|
|
5672
|
+
var tasks = [];
|
|
5673
|
+
var pollTimer = null;
|
|
5674
|
+
var pollActive = false;
|
|
5675
|
+
|
|
5676
|
+
function setStatus(msg) {
|
|
5677
|
+
document.getElementById('statusbar').textContent = msg;
|
|
5678
|
+
}
|
|
5679
|
+
|
|
5680
|
+
function esc(s) {
|
|
5681
|
+
return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
5682
|
+
}
|
|
5683
|
+
|
|
5684
|
+
// A cancelled task folds into the Failed column, tagged distinctly \u2014 v1
|
|
5685
|
+
// treats both as terminal scrap, and a fifth column for a rarely-used
|
|
5686
|
+
// status isn't worth the width.
|
|
5687
|
+
function columnOf(status) {
|
|
5688
|
+
if (status === 'cancelled') return 'failed';
|
|
5689
|
+
return status;
|
|
5690
|
+
}
|
|
5691
|
+
|
|
5692
|
+
// ============================================================
|
|
5693
|
+
// Verification tell \u2014 never render an unverified done as gate-passed.
|
|
5694
|
+
// ============================================================
|
|
5695
|
+
|
|
5696
|
+
function verificationTag(t) {
|
|
5697
|
+
var v = t.verification;
|
|
5698
|
+
if (v) {
|
|
5699
|
+
if (v.kind === 'gate') return '<span class="tag t-gate">✓ gate</span>';
|
|
5700
|
+
if (v.kind === 'self-report') return '<span class="tag t-self">self-report</span>';
|
|
5701
|
+
if (v.kind === 'human') return '<span class="tag t-human">human</span>';
|
|
5702
|
+
}
|
|
5703
|
+
if (t.status === 'in_progress' && t.verify) {
|
|
5704
|
+
return '<span class="tag t-gated">gated</span>';
|
|
5705
|
+
}
|
|
5706
|
+
return '';
|
|
5707
|
+
}
|
|
5708
|
+
|
|
5709
|
+
function ownerTag(t) {
|
|
5710
|
+
if (!t.owner) return '<span class="tag t-unclaimed">Unclaimed</span>';
|
|
5711
|
+
return '<span class="tag t-owner">' + esc(t.owner) + '</span>';
|
|
5712
|
+
}
|
|
5713
|
+
|
|
5714
|
+
// ============================================================
|
|
5715
|
+
// Card actions \u2014 explicit status moves, no drag-and-drop (read-only-safe
|
|
5716
|
+
// first: see module docblock).
|
|
5717
|
+
// ============================================================
|
|
5718
|
+
|
|
5719
|
+
function actionsFor(t) {
|
|
5720
|
+
var a = [];
|
|
5721
|
+
if (t.status === 'pending') {
|
|
5722
|
+
if (!t.owner) a.push({label: 'Claim', action: 'claim', cls: 'primary'});
|
|
5723
|
+
else a.push({label: 'Start', action: 'start', cls: 'primary'});
|
|
5724
|
+
a.push({label: 'Cancel', action: 'cancel', cls: 'danger'});
|
|
5725
|
+
} else if (t.status === 'in_progress') {
|
|
5726
|
+
a.push({label: 'Done', action: 'done', cls: 'primary'});
|
|
5727
|
+
a.push({label: 'Fail', action: 'fail', cls: 'danger'});
|
|
5728
|
+
a.push({label: 'Release', action: 'release', cls: ''});
|
|
5729
|
+
a.push({label: 'Cancel', action: 'cancel', cls: 'danger'});
|
|
5730
|
+
} else if (t.status === 'done') {
|
|
5731
|
+
a.push({label: 'Reopen', action: 'reopen', cls: ''});
|
|
5732
|
+
}
|
|
5733
|
+
return a;
|
|
5734
|
+
}
|
|
5735
|
+
|
|
5736
|
+
function applyAction(taskId, action) {
|
|
5737
|
+
var t = null;
|
|
5738
|
+
for (var i = 0; i < tasks.length; i++) {
|
|
5739
|
+
if (tasks[i].taskId === taskId) { t = tasks[i]; break; }
|
|
5740
|
+
}
|
|
5741
|
+
if (!t) return;
|
|
5742
|
+
var p;
|
|
5743
|
+
if (action === 'claim') {
|
|
5744
|
+
p = callTool('task_claim', {taskId: t.taskId, rev: t.rev});
|
|
5745
|
+
} else if (action === 'start') {
|
|
5746
|
+
p = callTool('task_update', {taskId: t.taskId, rev: t.rev, status: 'in_progress'});
|
|
5747
|
+
} else if (action === 'done') {
|
|
5748
|
+
p = callTool('task_update', {taskId: t.taskId, rev: t.rev, status: 'done'});
|
|
5749
|
+
} else if (action === 'fail') {
|
|
5750
|
+
p = callTool('task_update', {taskId: t.taskId, rev: t.rev, status: 'failed'});
|
|
5751
|
+
} else if (action === 'release') {
|
|
5752
|
+
p = callTool('task_update', {taskId: t.taskId, rev: t.rev, owner: null});
|
|
5753
|
+
} else if (action === 'cancel') {
|
|
5754
|
+
p = callTool('task_update', {taskId: t.taskId, rev: t.rev, status: 'cancelled'});
|
|
5755
|
+
} else if (action === 'reopen') {
|
|
5756
|
+
p = callTool('task_update', {taskId: t.taskId, rev: t.rev, status: 'pending'});
|
|
5757
|
+
} else {
|
|
5758
|
+
return;
|
|
5759
|
+
}
|
|
5760
|
+
p.then(function (result) {
|
|
5761
|
+
if (result && result.conflict) {
|
|
5762
|
+
setStatus('Someone else moved "' + t.title + '" first \u2014 refreshed.');
|
|
5763
|
+
} else if (result && result.error) {
|
|
5764
|
+
setStatus('Action failed: ' + result.error);
|
|
5765
|
+
} else {
|
|
5766
|
+
setStatus('Updated "' + t.title + '".');
|
|
5767
|
+
}
|
|
5768
|
+
return loadBoard();
|
|
5769
|
+
}).catch(function (e) {
|
|
5770
|
+
setStatus('Action failed: ' + e.message);
|
|
5771
|
+
});
|
|
5772
|
+
}
|
|
5773
|
+
|
|
5774
|
+
// ============================================================
|
|
5775
|
+
// Render
|
|
5776
|
+
// ============================================================
|
|
5777
|
+
|
|
5778
|
+
function renderCard(t) {
|
|
5779
|
+
var html = '<div class="card" data-taskid="' + esc(t.taskId) + '">';
|
|
5780
|
+
html += '<div class="c-title">' + esc(t.title) + '</div>';
|
|
5781
|
+
html += '<div class="c-id">#' + esc(t.taskId) + '</div>';
|
|
5782
|
+
html += '<div class="c-row">' + ownerTag(t) + verificationTag(t);
|
|
5783
|
+
if (t.status === 'cancelled') html += '<span class="tag t-cancelled">cancelled</span>';
|
|
5784
|
+
html += '</div>';
|
|
5785
|
+
if (t.lastVerifyError) {
|
|
5786
|
+
html += '<div class="c-err">verify failed: ' + esc(t.lastVerifyError) + '</div>';
|
|
5787
|
+
}
|
|
5788
|
+
var actions = actionsFor(t);
|
|
5789
|
+
if (actions.length > 0) {
|
|
5790
|
+
html += '<div class="c-actions">';
|
|
5791
|
+
for (var i = 0; i < actions.length; i++) {
|
|
5792
|
+
var a = actions[i];
|
|
5793
|
+
html += '<button class="abtn ' + a.cls + '" data-taskid="' + esc(t.taskId) + '" data-action="' + a.action + '">' + a.label + '</button>';
|
|
5794
|
+
}
|
|
5795
|
+
html += '</div>';
|
|
5796
|
+
}
|
|
5797
|
+
html += '</div>';
|
|
5798
|
+
return html;
|
|
5799
|
+
}
|
|
5800
|
+
|
|
5801
|
+
function render() {
|
|
5802
|
+
document.getElementById('board-id').textContent = boardId || '\u2014';
|
|
5803
|
+
if (!document.getElementById('board-input').value) {
|
|
5804
|
+
document.getElementById('board-input').value = boardId || '';
|
|
5805
|
+
}
|
|
5806
|
+
var el = document.getElementById('columns');
|
|
5807
|
+
var html = '';
|
|
5808
|
+
for (var c = 0; c < COLUMNS.length; c++) {
|
|
5809
|
+
var col = COLUMNS[c];
|
|
5810
|
+
var rows = tasks.filter(function (t) { return columnOf(t.status) === col.key; });
|
|
5811
|
+
html += '<div class="col"><div class="col-hdr"><span>' + col.label + '</span><span>' + rows.length + '</span></div><div class="col-body">';
|
|
5812
|
+
if (rows.length === 0) {
|
|
5813
|
+
html += '<div class="empty">No tasks</div>';
|
|
5814
|
+
} else {
|
|
5815
|
+
for (var i = 0; i < rows.length; i++) html += renderCard(rows[i]);
|
|
5816
|
+
}
|
|
5817
|
+
html += '</div></div>';
|
|
5818
|
+
}
|
|
5819
|
+
el.innerHTML = html;
|
|
5820
|
+
}
|
|
5821
|
+
|
|
5822
|
+
// ============================================================
|
|
5823
|
+
// Data
|
|
5824
|
+
// ============================================================
|
|
5825
|
+
|
|
5826
|
+
function loadBoard() {
|
|
5827
|
+
var args = {includeClosed: true, full: true};
|
|
5828
|
+
if (boardId) args.boardId = boardId;
|
|
5829
|
+
return callTool('task_list', args).then(function (data) {
|
|
5830
|
+
boardId = data.boardId || boardId;
|
|
5831
|
+
tasks = data.tasks || [];
|
|
5832
|
+
render();
|
|
5833
|
+
setStatus(tasks.length + ' task' + (tasks.length === 1 ? '' : 's') + ' \xB7 ' + new Date().toLocaleTimeString());
|
|
5834
|
+
}).catch(function (e) {
|
|
5835
|
+
setStatus('Error: ' + e.message);
|
|
5836
|
+
});
|
|
5837
|
+
}
|
|
5838
|
+
|
|
5839
|
+
function doPoll() {
|
|
5840
|
+
if (pollActive) return;
|
|
5841
|
+
pollActive = true;
|
|
5842
|
+
loadBoard().then(function () {
|
|
5843
|
+
pollActive = false;
|
|
5844
|
+
pollTimer = setTimeout(doPoll, 4000);
|
|
5845
|
+
}).catch(function () {
|
|
5846
|
+
pollActive = false;
|
|
5847
|
+
pollTimer = setTimeout(doPoll, 4000);
|
|
5848
|
+
});
|
|
5849
|
+
}
|
|
5850
|
+
|
|
5851
|
+
// ============================================================
|
|
5852
|
+
// Toolbar wiring
|
|
5853
|
+
// ============================================================
|
|
5854
|
+
|
|
5855
|
+
document.getElementById('columns').addEventListener('click', function (evt) {
|
|
5856
|
+
var btn = evt.target.closest ? evt.target.closest('button[data-action]') : null;
|
|
5857
|
+
if (!btn) return;
|
|
5858
|
+
applyAction(btn.getAttribute('data-taskid'), btn.getAttribute('data-action'));
|
|
5859
|
+
});
|
|
5860
|
+
|
|
5861
|
+
document.getElementById('refresh-btn').addEventListener('click', function () {
|
|
5862
|
+
loadBoard();
|
|
5863
|
+
});
|
|
5864
|
+
|
|
5865
|
+
document.getElementById('go-btn').addEventListener('click', function () {
|
|
5866
|
+
var v = document.getElementById('board-input').value.trim();
|
|
5867
|
+
if (!v) return;
|
|
5868
|
+
boardId = v;
|
|
5869
|
+
loadBoard();
|
|
5870
|
+
});
|
|
5871
|
+
|
|
5872
|
+
document.getElementById('add-btn').addEventListener('click', function () {
|
|
5873
|
+
var input = document.getElementById('new-title');
|
|
5874
|
+
var title = input.value.trim();
|
|
5875
|
+
if (!title) return;
|
|
5876
|
+
var args = {title: title};
|
|
5877
|
+
if (boardId) args.boardId = boardId;
|
|
5878
|
+
callTool('task_create', args).then(function (result) {
|
|
5879
|
+
if (result && result.error) {
|
|
5880
|
+
setStatus('Create failed: ' + result.error);
|
|
5881
|
+
return;
|
|
5882
|
+
}
|
|
5883
|
+
input.value = '';
|
|
5884
|
+
setStatus('Created "' + title + '".');
|
|
5885
|
+
return loadBoard();
|
|
5886
|
+
}).catch(function (e) {
|
|
5887
|
+
setStatus('Create failed: ' + e.message);
|
|
5888
|
+
});
|
|
5889
|
+
});
|
|
5890
|
+
|
|
5891
|
+
// ============================================================
|
|
5892
|
+
// Boot
|
|
5893
|
+
// ============================================================
|
|
5894
|
+
|
|
5895
|
+
initBridge().then(function () {
|
|
5896
|
+
return loadBoard();
|
|
5897
|
+
}).then(function () {
|
|
5898
|
+
pollTimer = setTimeout(doPoll, 4000);
|
|
5899
|
+
}).catch(function (e) {
|
|
5900
|
+
setStatus('Bridge error: ' + e.message);
|
|
5901
|
+
});
|
|
5902
|
+
</script>
|
|
5903
|
+
</body>
|
|
5904
|
+
</html>`;
|
|
5905
|
+
|
|
5906
|
+
// src/work-board/index.ts
|
|
5907
|
+
var workBoardInputSchema = z.object({
|
|
5908
|
+
boardId: z.string().optional().describe(
|
|
5909
|
+
"Board to open \u2014 `tree:<rootSessionId>` (a supervisor and its executors) or `ws:<slug>` (an operator workspace). Omit \u2192 the caller's default board."
|
|
5910
|
+
)
|
|
5911
|
+
});
|
|
5912
|
+
function makeWorkBoardApp(ops) {
|
|
5913
|
+
return {
|
|
5914
|
+
id: "agentproto_work_board",
|
|
5915
|
+
title: "Work Board",
|
|
5916
|
+
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.",
|
|
5917
|
+
inputSchema: workBoardInputSchema,
|
|
5918
|
+
execute: async (input) => ops.listTasks(input.boardId),
|
|
5919
|
+
html: WORK_BOARD_HTML
|
|
5920
|
+
};
|
|
5921
|
+
}
|
|
5922
|
+
var workBoardApp = defineApp({
|
|
5923
|
+
id: "@agentproto/work-board",
|
|
5924
|
+
name: "Work Board",
|
|
5925
|
+
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.",
|
|
5926
|
+
agents: [],
|
|
5927
|
+
ui: {
|
|
5928
|
+
html: WORK_BOARD_HTML,
|
|
5929
|
+
title: "Work Board",
|
|
5930
|
+
tools: ["task_list", "task_claim", "task_update", "task_create"]
|
|
5931
|
+
}
|
|
5932
|
+
});
|
|
5933
|
+
|
|
5934
|
+
export { SESSION_CHAT_APP_ID, SESSION_CHAT_FALLBACK_HTML, agentsOverviewApp, bureauSessionsApp, codeTeam, contentTeam, liveSessionApp, mailTriage, makeAgentsOverviewApp, makeBureauSessionsApp, makeLiveSessionApp, makeSessionChatApp, makeSessionStoryPanelApp, makeSessionsPanelApp, makeWorkBoardApp, mediaViewer, opsPanel, panelBridgeScript, sessionChatApp, sessionChatAppUrl, sessionChatEmbedHtml, sessionStoryApp, sessionViewer, sessionsPanelApp, workBoardApp };
|
|
5494
5935
|
//# sourceMappingURL=index.mjs.map
|
|
5495
5936
|
//# sourceMappingURL=index.mjs.map
|