@onepointfour-packs/flaredeck-agent 0.1.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/LICENSE.md +14 -0
- package/README.md +102 -0
- package/dist/agent.d.ts +104 -0
- package/dist/agent.js +329 -0
- package/dist/agent.js.map +1 -0
- package/dist/approval.d.ts +72 -0
- package/dist/approval.js +161 -0
- package/dist/approval.js.map +1 -0
- package/dist/approvals.d.ts +2 -0
- package/dist/approvals.js +148 -0
- package/dist/approvals.js.map +1 -0
- package/dist/auth.d.ts +79 -0
- package/dist/auth.js +181 -0
- package/dist/auth.js.map +1 -0
- package/dist/automode.d.ts +33 -0
- package/dist/automode.js +69 -0
- package/dist/automode.js.map +1 -0
- package/dist/branches.d.ts +25 -0
- package/dist/branches.js +81 -0
- package/dist/branches.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +12 -0
- package/dist/cli.js.map +1 -0
- package/dist/codesearch.d.ts +27 -0
- package/dist/codesearch.js +111 -0
- package/dist/codesearch.js.map +1 -0
- package/dist/concurrency.d.ts +14 -0
- package/dist/concurrency.js +52 -0
- package/dist/concurrency.js.map +1 -0
- package/dist/config.d.ts +106 -0
- package/dist/config.js +119 -0
- package/dist/config.js.map +1 -0
- package/dist/engine-antigravity.d.ts +23 -0
- package/dist/engine-antigravity.js +357 -0
- package/dist/engine-antigravity.js.map +1 -0
- package/dist/engine-claude.d.ts +18 -0
- package/dist/engine-claude.js +64 -0
- package/dist/engine-claude.js.map +1 -0
- package/dist/engine.d.ts +122 -0
- package/dist/engine.js +36 -0
- package/dist/engine.js.map +1 -0
- package/dist/env.d.ts +1 -0
- package/dist/env.js +10 -0
- package/dist/env.js.map +1 -0
- package/dist/environment.d.ts +39 -0
- package/dist/environment.js +100 -0
- package/dist/environment.js.map +1 -0
- package/dist/flaredeck-check.d.ts +21 -0
- package/dist/flaredeck-check.js +12 -0
- package/dist/flaredeck-check.js.map +1 -0
- package/dist/flaredeck-proxy.d.ts +60 -0
- package/dist/flaredeck-proxy.js +186 -0
- package/dist/flaredeck-proxy.js.map +1 -0
- package/dist/flaredeck.d.ts +132 -0
- package/dist/flaredeck.js +106 -0
- package/dist/flaredeck.js.map +1 -0
- package/dist/gemini.d.ts +21 -0
- package/dist/gemini.js +59 -0
- package/dist/gemini.js.map +1 -0
- package/dist/gitguard.d.ts +2 -0
- package/dist/gitguard.js +90 -0
- package/dist/gitguard.js.map +1 -0
- package/dist/github.d.ts +38 -0
- package/dist/github.js +153 -0
- package/dist/github.js.map +1 -0
- package/dist/githubauth.d.ts +21 -0
- package/dist/githubauth.js +90 -0
- package/dist/githubauth.js.map +1 -0
- package/dist/intake.d.ts +124 -0
- package/dist/intake.js +383 -0
- package/dist/intake.js.map +1 -0
- package/dist/jam.d.ts +45 -0
- package/dist/jam.js +385 -0
- package/dist/jam.js.map +1 -0
- package/dist/jev.d.ts +31 -0
- package/dist/jev.js +75 -0
- package/dist/jev.js.map +1 -0
- package/dist/jevguard.d.ts +28 -0
- package/dist/jevguard.js +213 -0
- package/dist/jevguard.js.map +1 -0
- package/dist/mailbox.d.ts +22 -0
- package/dist/mailbox.js +51 -0
- package/dist/mailbox.js.map +1 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +764 -0
- package/dist/main.js.map +1 -0
- package/dist/markdown.d.ts +5 -0
- package/dist/markdown.js +81 -0
- package/dist/markdown.js.map +1 -0
- package/dist/oauth.d.ts +30 -0
- package/dist/oauth.js +216 -0
- package/dist/oauth.js.map +1 -0
- package/dist/permissions.d.ts +43 -0
- package/dist/permissions.js +57 -0
- package/dist/permissions.js.map +1 -0
- package/dist/preflight.d.ts +71 -0
- package/dist/preflight.js +116 -0
- package/dist/preflight.js.map +1 -0
- package/dist/providers.d.ts +26 -0
- package/dist/providers.js +27 -0
- package/dist/providers.js.map +1 -0
- package/dist/repopicker.d.ts +3 -0
- package/dist/repopicker.js +111 -0
- package/dist/repopicker.js.map +1 -0
- package/dist/runs.d.ts +59 -0
- package/dist/runs.js +211 -0
- package/dist/runs.js.map +1 -0
- package/dist/sandbox.d.ts +13 -0
- package/dist/sandbox.js +110 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/schedules.d.ts +11 -0
- package/dist/schedules.js +85 -0
- package/dist/schedules.js.map +1 -0
- package/dist/secretguard.d.ts +4 -0
- package/dist/secretguard.js +115 -0
- package/dist/secretguard.js.map +1 -0
- package/dist/secrets.d.ts +27 -0
- package/dist/secrets.js +51 -0
- package/dist/secrets.js.map +1 -0
- package/dist/serve.d.ts +17 -0
- package/dist/serve.js +1206 -0
- package/dist/serve.js.map +1 -0
- package/dist/status.d.ts +73 -0
- package/dist/status.js +98 -0
- package/dist/status.js.map +1 -0
- package/dist/stream.d.ts +91 -0
- package/dist/stream.js +103 -0
- package/dist/stream.js.map +1 -0
- package/dist/streamtoken.d.ts +2 -0
- package/dist/streamtoken.js +30 -0
- package/dist/streamtoken.js.map +1 -0
- package/dist/team.d.ts +61 -0
- package/dist/team.js +136 -0
- package/dist/team.js.map +1 -0
- package/dist/ui.d.ts +110 -0
- package/dist/ui.js +348 -0
- package/dist/ui.js.map +1 -0
- package/dist/updater.d.ts +15 -0
- package/dist/updater.js +178 -0
- package/dist/updater.js.map +1 -0
- package/dist/workspace.d.ts +115 -0
- package/dist/workspace.js +247 -0
- package/dist/workspace.js.map +1 -0
- package/dist/worktree.d.ts +42 -0
- package/dist/worktree.js +140 -0
- package/dist/worktree.js.map +1 -0
- package/package.json +52 -0
- package/python/sidecar.py +178 -0
package/dist/team.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/** The agents a lead is responsible for: its reports. Workers with no lead are shown too, marked. */
|
|
4
|
+
export function myTeam(team) {
|
|
5
|
+
const mine = team.agents.filter((a) => a.reportsTo === team.you.agentId);
|
|
6
|
+
const unled = team.agents.filter((a) => a.role !== 'lead' && !a.reportsTo && a.agentId !== team.you.agentId);
|
|
7
|
+
return { mine, unled };
|
|
8
|
+
}
|
|
9
|
+
export async function fetchTeam(baseUrl, token) {
|
|
10
|
+
const res = await fetch(`${baseUrl}/events/agents`, {
|
|
11
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
12
|
+
});
|
|
13
|
+
if (!res.ok)
|
|
14
|
+
throw new Error(`Could not read the team (${res.status})`);
|
|
15
|
+
return (await res.json());
|
|
16
|
+
}
|
|
17
|
+
/** How long quiet is worrying. Agents push at least every five minutes. */
|
|
18
|
+
const QUIET_S = 16 * 60;
|
|
19
|
+
function describe(a) {
|
|
20
|
+
const quiet = a.quietFor === null ? 'never started'
|
|
21
|
+
: a.quietFor > QUIET_S ? `NO WORD for ${Math.round(a.quietFor / 60)} min`
|
|
22
|
+
: `${a.quietFor}s ago`;
|
|
23
|
+
const plan = a.tasks?.total ? ` (${a.tasks.done}/${a.tasks.total} of its plan)` : '';
|
|
24
|
+
const waiting = a.queued > 0 ? ` · ${a.queued} queued${a.next ? `, next ${a.next}` : ''}` : '';
|
|
25
|
+
const work = (a.card ? `on ${a.card}${plan}` : a.state) + waiting;
|
|
26
|
+
const trouble = a.errorsInARow > 0 ? ` · ${a.errorsInARow} error(s) in a row` : '';
|
|
27
|
+
return `- **${a.name}** (${a.role}) — ${work}, last word ${quiet}${trouble}\n ${a.summary || '(nothing reported)'}`;
|
|
28
|
+
}
|
|
29
|
+
export function teamTools(baseUrl, token, deck = null, onReviewed = () => { }) {
|
|
30
|
+
return createSdkMcpServer({
|
|
31
|
+
name: 'team',
|
|
32
|
+
version: '1.0.0',
|
|
33
|
+
tools: [
|
|
34
|
+
tool('review_production_run', 'Your review of a worker\'s request to run a script against production. The request is a ' +
|
|
35
|
+
'comment on the card (get-card-details shows it, with its comment id, the script, and the ' +
|
|
36
|
+
'harness\'s own row-count preview). Endorse it and the people who can approve it are asked; ' +
|
|
37
|
+
'reject it and the worker is refused with your note. Read the script yourself: check the WHERE ' +
|
|
38
|
+
'clause matches the stated purpose and the preview count matches the expected effect. Never ' +
|
|
39
|
+
'endorse on the description alone.', {
|
|
40
|
+
comment_id: z.string().describe('The id of the request comment on the card.'),
|
|
41
|
+
verdict: z.enum(['endorse', 'reject']),
|
|
42
|
+
note: z.string().describe('One or two lines: what you checked, or why it is refused. Shown to the approver, or to the worker.'),
|
|
43
|
+
}, async ({ comment_id, verdict, note }) => {
|
|
44
|
+
if (!deck)
|
|
45
|
+
return { content: [{ type: 'text', text: 'This harness has no FlareDeck client of its own, so it cannot record a review.' }], isError: true };
|
|
46
|
+
try {
|
|
47
|
+
await deck.review(comment_id, verdict === 'endorse' ? 'endorsed' : 'rejected', note);
|
|
48
|
+
onReviewed({ commentId: comment_id, verdict, note });
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
return { content: [{ type: 'text', text: `Could not record the review: ${e instanceof Error ? e.message : String(e)}` }], isError: true };
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
content: [{
|
|
55
|
+
type: 'text',
|
|
56
|
+
text: verdict === 'endorse'
|
|
57
|
+
? 'Endorsed. The people who can approve it have been asked; the worker is still waiting on them, not on you.'
|
|
58
|
+
: 'Rejected. The worker has been refused with your note.',
|
|
59
|
+
}],
|
|
60
|
+
};
|
|
61
|
+
}),
|
|
62
|
+
tool('list_agents', 'Every agent on this workspace: what it is working on, what it last said it was doing, ' +
|
|
63
|
+
'and how long since it checked in. Read from what they reported themselves, so this ' +
|
|
64
|
+
'costs them nothing and does not interrupt anyone.', {}, async () => {
|
|
65
|
+
const team = await fetchTeam(baseUrl, await token());
|
|
66
|
+
const { mine, unled } = myTeam(team);
|
|
67
|
+
const lines = mine.map(describe).join('\n');
|
|
68
|
+
const quiet = mine.filter((a) => a.quietFor !== null && a.quietFor > QUIET_S);
|
|
69
|
+
const orphans = unled.length
|
|
70
|
+
? `\n\nNot on any team (no lead set — an admin fixes that on the agent's card): ${unled.map((a) => a.name).join(', ')}`
|
|
71
|
+
: '';
|
|
72
|
+
return {
|
|
73
|
+
content: [{
|
|
74
|
+
type: 'text',
|
|
75
|
+
text: `${mine.length} agent(s) report to you:\n\n${lines || '(nobody yet)'}${orphans}` +
|
|
76
|
+
(quiet.length
|
|
77
|
+
? `\n\n⚠ ${quiet.map((a) => a.name).join(', ')} ${quiet.length === 1 ? 'has' : 'have'} ` +
|
|
78
|
+
`not checked in. Their machine may be gone, in which case whatever they hold ` +
|
|
79
|
+
`is not being worked. Nothing has been taken off them — that is your call.`
|
|
80
|
+
: ''),
|
|
81
|
+
}],
|
|
82
|
+
};
|
|
83
|
+
}),
|
|
84
|
+
],
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
export const TEAM_TOOL_NAMES = ['mcp__team__list_agents', 'mcp__team__review_production_run'];
|
|
88
|
+
/** Added to the brief for a lead. Everything else about being one comes from its description. */
|
|
89
|
+
export const LEAD_BRIEF = [
|
|
90
|
+
'',
|
|
91
|
+
'You are the LEAD on this workspace. You do not work cards yourself — you have no checkout and',
|
|
92
|
+
'no publishing tools, on purpose. Your job is judgement: who gets what, whether anyone is stuck,',
|
|
93
|
+
'and what is ready.',
|
|
94
|
+
'',
|
|
95
|
+
'When a card is assigned to you, that is a request to dispatch it, not to do it. Read the card',
|
|
96
|
+
'and its components (api, ui, …), call `list_agents` to see who owns which repo and who is free,',
|
|
97
|
+
'then `assign-card` to the one worker whose repo it belongs in. Say on the card why it went there.',
|
|
98
|
+
'',
|
|
99
|
+
'A card that needs more than one repo — an API change and the screen that uses it — is not one',
|
|
100
|
+
'card. Create one card per repo, each naming the original and what the other half will need',
|
|
101
|
+
'(the API shape the screen will call), assign the API half first, and hold the UI half until it',
|
|
102
|
+
'lands. One card, one repo, one branch, one pull request.',
|
|
103
|
+
'',
|
|
104
|
+
'Some of your agents are JUNIORS. A junior has the same tools and the same repo knowledge as any',
|
|
105
|
+
'worker — it is not less trusted, it is given less at a time. Send it the contained cards: one',
|
|
106
|
+
'file, one query, a copy change, a clear reproduction with an obvious fix. Keep the cards that',
|
|
107
|
+
'cross layers, change data, or need a judgement call for the workers. If the only agent free for',
|
|
108
|
+
'a large card is a junior, say so on the card and let it wait rather than splitting a design',
|
|
109
|
+
'decision into pieces nobody owns.',
|
|
110
|
+
'',
|
|
111
|
+
'`list_agents` reads what the workers reported themselves, so asking costs them nothing. Do not',
|
|
112
|
+
'message a worker to ask how it is going: that interrupts it and tells you what it thinks of',
|
|
113
|
+
'itself rather than what it did. Read the card instead.',
|
|
114
|
+
'',
|
|
115
|
+
'A worker that calls `set-needs-human` is asking you first. Decide if you can — on the card —',
|
|
116
|
+
'and if you cannot, say so plainly and leave it for a person.',
|
|
117
|
+
'',
|
|
118
|
+
'A worker asking to run a script against production comes to you first, as an approval request',
|
|
119
|
+
'on its card. Nobody else sees it until you have. Read the card: the request comment carries',
|
|
120
|
+
'the script, the worker\'s own account of it, and the harness\'s row-count preview. Check that the',
|
|
121
|
+
'WHERE clause matches the purpose and the preview matches the expected effect, then',
|
|
122
|
+
'`review_production_run` with the comment id — endorse, and the people who can approve it are',
|
|
123
|
+
'asked; reject, and the worker is refused with your note. Your endorsement is what a person',
|
|
124
|
+
'relies on, so never give it on the description alone.',
|
|
125
|
+
'',
|
|
126
|
+
'The card\'s Environment decides which branch its work is cut from: a card in a production-fix',
|
|
127
|
+
'environment is cut from and merged into the fix branch, everything else the feature branch.',
|
|
128
|
+
'So set the Environment right before you dispatch — it is not decoration. And a fix that lands',
|
|
129
|
+
'on the fix branch is not finished until it is also merged down into the feature branch, or the',
|
|
130
|
+
'next release will undo it. Ask the worker for that pull request too.',
|
|
131
|
+
'',
|
|
132
|
+
'An agent that has not checked in may simply be gone — a machine asleep or killed. Nothing is',
|
|
133
|
+
'taken off it automatically, because a clock cannot tell a long job from a stuck one and moving',
|
|
134
|
+
'a card that is still being worked duplicates the work. Look, then decide.',
|
|
135
|
+
].join('\n');
|
|
136
|
+
//# sourceMappingURL=team.js.map
|
package/dist/team.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"team.js","sourceRoot":"","sources":["../src/team.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAyCxB,qGAAqG;AACrG,MAAM,UAAU,MAAM,CAAC,IAAU;IAC/B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAC7G,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,KAAa;IAC5D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,gBAAgB,EAAE;QAClD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;KAC9C,CAAC,CAAC;IACH,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACxE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAS,CAAC;AACpC,CAAC;AAED,2EAA2E;AAC3E,MAAM,OAAO,GAAG,EAAE,GAAG,EAAE,CAAC;AAExB,SAAS,QAAQ,CAAC,CAAa;IAC7B,MAAM,KAAK,GACT,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe;QACrC,CAAC,CAAC,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,eAAe,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,GAAG,EAAE,CAAC,MAAM;YACzE,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,OAAO,CAAC;IACzB,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,eAAe,CAAC,CAAC,CAAC,EAAE,CAAC;IACrF,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/F,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;IAClE,MAAM,OAAO,GAAG,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,YAAY,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC;IACnF,OAAO,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,OAAO,IAAI,eAAe,KAAK,GAAG,OAAO,OAAO,CAAC,CAAC,OAAO,IAAI,oBAAoB,EAAE,CAAC;AACvH,CAAC;AAKD,MAAM,UAAU,SAAS,CACvB,OAAe,EACf,KAA4B,EAC5B,OAAyB,IAAI,EAC7B,aAAoC,GAAG,EAAE,GAAE,CAAC;IAE5C,OAAO,kBAAkB,CAAC;QACxB,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE;YACL,IAAI,CACF,uBAAuB,EACvB,0FAA0F;gBACxF,2FAA2F;gBAC3F,6FAA6F;gBAC7F,gGAAgG;gBAChG,6FAA6F;gBAC7F,mCAAmC,EACrC;gBACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;gBAC7E,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;gBACtC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oGAAoG,CAAC;aAChI,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;gBACtC,IAAI,CAAC,IAAI;oBAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,gFAAgF,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBAClK,IAAI,CAAC;oBACH,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;oBACrF,UAAU,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvD,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,gCAAgC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBACrJ,CAAC;gBACD,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAe;4BACrB,IAAI,EAAE,OAAO,KAAK,SAAS;gCACzB,CAAC,CAAC,2GAA2G;gCAC7G,CAAC,CAAC,uDAAuD;yBAC5D,CAAC;iBACH,CAAC;YACJ,CAAC,CACF;YACD,IAAI,CACF,aAAa,EACb,wFAAwF;gBACtF,qFAAqF;gBACrF,mDAAmD,EACrD,EAAE,EACF,KAAK,IAAI,EAAE;gBACT,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE,MAAM,KAAK,EAAE,CAAC,CAAC;gBACrD,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC;gBAC9E,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM;oBAC1B,CAAC,CAAC,gFAAgF,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;oBACvH,CAAC,CAAC,EAAE,CAAC;gBACP,OAAO;oBACL,OAAO,EAAE,CAAC;4BACR,IAAI,EAAE,MAAM;4BACZ,IAAI,EACF,GAAG,IAAI,CAAC,MAAM,+BAA+B,KAAK,IAAI,cAAc,GAAG,OAAO,EAAE;gCAChF,CAAC,KAAK,CAAC,MAAM;oCACX,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,GAAG;wCACtF,8EAA8E;wCAC9E,2EAA2E;oCAC7E,CAAC,CAAC,EAAE,CAAC;yBACV,CAAC;iBACH,CAAC;YACJ,CAAC,CACF;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,wBAAwB,EAAE,kCAAkC,CAAC,CAAC;AAE9F,iGAAiG;AACjG,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,EAAE;IACF,+FAA+F;IAC/F,iGAAiG;IACjG,oBAAoB;IACpB,EAAE;IACF,+FAA+F;IAC/F,iGAAiG;IACjG,mGAAmG;IACnG,EAAE;IACF,+FAA+F;IAC/F,4FAA4F;IAC5F,gGAAgG;IAChG,0DAA0D;IAC1D,EAAE;IACF,iGAAiG;IACjG,+FAA+F;IAC/F,+FAA+F;IAC/F,iGAAiG;IACjG,6FAA6F;IAC7F,mCAAmC;IACnC,EAAE;IACF,gGAAgG;IAChG,6FAA6F;IAC7F,wDAAwD;IACxD,EAAE;IACF,8FAA8F;IAC9F,8DAA8D;IAC9D,EAAE;IACF,+FAA+F;IAC/F,6FAA6F;IAC7F,mGAAmG;IACnG,oFAAoF;IACpF,8FAA8F;IAC9F,4FAA4F;IAC5F,uDAAuD;IACvD,EAAE;IACF,+FAA+F;IAC/F,6FAA6F;IAC7F,+FAA+F;IAC/F,gGAAgG;IAChG,sEAAsE;IACtE,EAAE;IACF,8FAA8F;IAC9F,gGAAgG;IAChG,2EAA2E;CAC5E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC"}
|
package/dist/ui.d.ts
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* What an unattended agent looks like when someone IS watching.
|
|
4
|
+
*
|
|
5
|
+
* The daemon's job is to run without anyone here, so the display answers the question a person
|
|
6
|
+
* actually has when they glance at it — is it alive, what is it on, and can I say something? The
|
|
7
|
+
* scroll of tool calls is deliberately not the main event: a wall of `· Bash` tells you less than
|
|
8
|
+
* one line saying which card it is working and for how long.
|
|
9
|
+
*/
|
|
10
|
+
/** `answer` is what the agent says back to a question typed here: shown whole, never truncated. */
|
|
11
|
+
export type Line = {
|
|
12
|
+
kind: 'event' | 'say' | 'answer' | 'todo' | 'tool' | 'warn' | 'you';
|
|
13
|
+
text: string;
|
|
14
|
+
};
|
|
15
|
+
export type UiState = {
|
|
16
|
+
agent: string;
|
|
17
|
+
repo: string;
|
|
18
|
+
/** The card being worked, or '' when idle. */
|
|
19
|
+
working: string;
|
|
20
|
+
since: number;
|
|
21
|
+
queued: number;
|
|
22
|
+
connected: boolean;
|
|
23
|
+
lines: Line[];
|
|
24
|
+
/** The checkout this card is being worked in, and where its pull request will land. */
|
|
25
|
+
branch?: string;
|
|
26
|
+
base?: string;
|
|
27
|
+
/** The agent's own plan, counted from the stream. Absent until it writes one. */
|
|
28
|
+
tasks?: {
|
|
29
|
+
done: number;
|
|
30
|
+
total: number;
|
|
31
|
+
};
|
|
32
|
+
/** What it picks up the moment this card is finished. */
|
|
33
|
+
nextCard?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Every production run waiting on a person in this workspace — this agent's own and, on a
|
|
36
|
+
* lead's pane, its team's. Listed under the input like Claude Code's agent list; Tab moves
|
|
37
|
+
* into it, ↑↓ picks one, a/d answers it, Enter shows the script. Rows leave when answered.
|
|
38
|
+
*/
|
|
39
|
+
approvals?: Approval[];
|
|
40
|
+
/** An SDK update downloaded and waiting for the next start. */
|
|
41
|
+
update?: string | undefined;
|
|
42
|
+
/** Which model answers, when it is not the default one. You should never have to ask. */
|
|
43
|
+
engine?: string | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* A LEAD's reports, refreshed from FlareDeck: who is running and what each is on. Absent on a
|
|
46
|
+
* worker's pane. The point is that one pane answers "what is the team doing" without opening
|
|
47
|
+
* four more terminals, so this is their state as they themselves reported it — not this
|
|
48
|
+
* machine's guess about them.
|
|
49
|
+
*/
|
|
50
|
+
team?: TeamRow[];
|
|
51
|
+
};
|
|
52
|
+
export type TeamRow = {
|
|
53
|
+
name: string;
|
|
54
|
+
/** The card it is on, or '' when it is on nothing. */
|
|
55
|
+
card: string;
|
|
56
|
+
/** Its own word for what it is doing — 'idle', 'working', 'stopped'. */
|
|
57
|
+
state: string;
|
|
58
|
+
/** Its latest sentence about the work. */
|
|
59
|
+
summary: string;
|
|
60
|
+
/** Its own plan: tasks finished out of tasks written. */
|
|
61
|
+
tasks: {
|
|
62
|
+
done: number;
|
|
63
|
+
total: number;
|
|
64
|
+
};
|
|
65
|
+
/** Events waiting behind the current card, and what it starts next. */
|
|
66
|
+
queued: number;
|
|
67
|
+
next: string;
|
|
68
|
+
/** Seconds since it last checked in; null when it has never started. */
|
|
69
|
+
quietFor: number | null;
|
|
70
|
+
/** FlareDeck's own verdict that it has been quiet too long to believe. */
|
|
71
|
+
stale: boolean;
|
|
72
|
+
errorsInARow: number;
|
|
73
|
+
};
|
|
74
|
+
export type Approval = {
|
|
75
|
+
requestId: string;
|
|
76
|
+
commentId: string;
|
|
77
|
+
/** Who asked, and where. */
|
|
78
|
+
agent: string;
|
|
79
|
+
card: string;
|
|
80
|
+
name: string;
|
|
81
|
+
target: string;
|
|
82
|
+
purpose: string;
|
|
83
|
+
/** The harness's own row count, when it could derive one. */
|
|
84
|
+
preview?: string;
|
|
85
|
+
script: string;
|
|
86
|
+
/** 'lead' = still with the lead (no keys here); 'ready' = a person may answer; 'answered' = waiting for the agent to pick it up. */
|
|
87
|
+
stage: 'lead' | 'ready' | 'answered';
|
|
88
|
+
/** The lead's note, once endorsed. */
|
|
89
|
+
endorsedBy?: string;
|
|
90
|
+
verdict?: 'allow' | 'deny';
|
|
91
|
+
expiresAt?: number;
|
|
92
|
+
};
|
|
93
|
+
export declare function App({ state, onSteer, onQuit, onDecide }: {
|
|
94
|
+
state: () => UiState;
|
|
95
|
+
onSteer: (text: string) => void;
|
|
96
|
+
onQuit: () => void;
|
|
97
|
+
/** Answer the run the agent is asking about. Absent when this machine has no person's login. */
|
|
98
|
+
onDecide?: (requestId: string, verdict: 'allow' | 'deny') => void;
|
|
99
|
+
}): React.JSX.Element;
|
|
100
|
+
/** True only when a person is actually at a terminal. Under launchd or systemd, nobody is. */
|
|
101
|
+
export declare const interactive: () => boolean;
|
|
102
|
+
export declare function startUi(opts: {
|
|
103
|
+
state: () => UiState;
|
|
104
|
+
onSteer: (text: string) => void;
|
|
105
|
+
onQuit: () => void;
|
|
106
|
+
onDecide?: (requestId: string, verdict: 'allow' | 'deny') => void;
|
|
107
|
+
}): {
|
|
108
|
+
stop: () => void;
|
|
109
|
+
log: (line: Line) => void;
|
|
110
|
+
};
|
package/dist/ui.js
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import { Box, Text, render, useApp, useInput } from 'ink';
|
|
2
|
+
import TextInput from 'ink-text-input';
|
|
3
|
+
import React, { useEffect, useState } from 'react';
|
|
4
|
+
import { Markdown } from './markdown.js';
|
|
5
|
+
// Readability over prettiness. Ink's 'gray' is bright-black, which on a dark terminal is very
|
|
6
|
+
// nearly the background: the whole pane read as unlit. So secondary text is plain 'white' and
|
|
7
|
+
// emphasis comes from bold and colour instead — the least important thing on screen still has to
|
|
8
|
+
// be legible, because an unreadable log is the same as no log.
|
|
9
|
+
const COLOUR = {
|
|
10
|
+
event: 'cyan',
|
|
11
|
+
say: 'white',
|
|
12
|
+
answer: 'white',
|
|
13
|
+
todo: 'green',
|
|
14
|
+
tool: 'blueBright',
|
|
15
|
+
warn: 'yellow',
|
|
16
|
+
you: 'magenta',
|
|
17
|
+
};
|
|
18
|
+
const PREFIX = {
|
|
19
|
+
event: '→ ',
|
|
20
|
+
say: ' ',
|
|
21
|
+
answer: ' ',
|
|
22
|
+
todo: ' ☐ ',
|
|
23
|
+
tool: '· ',
|
|
24
|
+
warn: '⚠ ',
|
|
25
|
+
you: '» ',
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* What the terminal sends that is not typing.
|
|
29
|
+
*
|
|
30
|
+
* A mouse wheel in raw mode arrives as arrow-key escape sequences. Ink matches a whole chunk
|
|
31
|
+
* against one key, so a slow scroll reads as Up or Down — but a fast one delivers several
|
|
32
|
+
* sequences at once, matches nothing, and falls through as literal text. That is how "^[[B^[[B…"
|
|
33
|
+
* ends up typed into the steering box by someone who only scrolled back to read a line.
|
|
34
|
+
*
|
|
35
|
+
* Stripping here rather than handling particular keys covers whatever else a terminal decides to
|
|
36
|
+
* send: an escape sequence or a control character is never something a person meant to type into
|
|
37
|
+
* a one-line prompt.
|
|
38
|
+
*/
|
|
39
|
+
const NOT_TYPING = /\u001B\[[0-9;?]*[ -/]*[@-~]|\u001B[@-_]|[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g;
|
|
40
|
+
/** Frames for the working spinner, driven by the clock so no extra state is needed. */
|
|
41
|
+
const SPINNER = ['\u280b', '\u2819', '\u2839', '\u2838', '\u283c', '\u2834', '\u2826', '\u2827', '\u2807', '\u280f'];
|
|
42
|
+
/** The repo, not the path to it. Nobody reading this needs to be told where their own home is. */
|
|
43
|
+
function basename(path) {
|
|
44
|
+
return path.replace(/\/+$/, '').split('/').pop() || path;
|
|
45
|
+
}
|
|
46
|
+
/** Progress as a shape, so it reads at a glance rather than being counted. */
|
|
47
|
+
function bar(done, total, width = 10) {
|
|
48
|
+
const filled = total > 0 ? Math.round((done / total) * width) : 0;
|
|
49
|
+
return '\u2501'.repeat(filled) + '\u2500'.repeat(Math.max(0, width - filled));
|
|
50
|
+
}
|
|
51
|
+
/** "4 → completed" is bookkeeping, not a sentence. It tells a reader nothing on its own. */
|
|
52
|
+
const BOOKKEEPING = /^\S+\s*\u2192\s*\S+$/;
|
|
53
|
+
/**
|
|
54
|
+
* The most recent thing the agent SAID, as opposed to the most recent thing that happened.
|
|
55
|
+
* A run of tool calls scrolls its last sentence away within seconds, and that sentence is the
|
|
56
|
+
* only part of the log written for a person.
|
|
57
|
+
*/
|
|
58
|
+
function lastSaid(lines) {
|
|
59
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
60
|
+
const l = lines[i];
|
|
61
|
+
if (!l || (l.kind !== 'say' && l.kind !== 'todo'))
|
|
62
|
+
continue;
|
|
63
|
+
const text = l.text.trim();
|
|
64
|
+
if (text && !BOOKKEEPING.test(text))
|
|
65
|
+
return text;
|
|
66
|
+
}
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Tool names as a person would say them. "mcp__flaredeck__get-card-details" is most of a line
|
|
71
|
+
* spent on punctuation, and the log is the part of this screen that has to stay skimmable.
|
|
72
|
+
*/
|
|
73
|
+
function toolName(raw) {
|
|
74
|
+
const mcp = /^mcp__([^_]+(?:_[^_]+)*?)__(.+)$/.exec(raw);
|
|
75
|
+
return mcp ? `${mcp[1]}\u00b7${mcp[2]}` : raw;
|
|
76
|
+
}
|
|
77
|
+
function elapsed(since) {
|
|
78
|
+
const s = Math.floor((Date.now() - since) / 1000);
|
|
79
|
+
if (s < 60)
|
|
80
|
+
return `${s}s`;
|
|
81
|
+
const m = Math.floor(s / 60);
|
|
82
|
+
return m < 60 ? `${m}m ${s % 60}s` : `${Math.floor(m / 60)}h ${m % 60}m`;
|
|
83
|
+
}
|
|
84
|
+
export function App({ state, onSteer, onQuit, onDecide }) {
|
|
85
|
+
const { exit } = useApp();
|
|
86
|
+
const [, tick] = useState(0);
|
|
87
|
+
const [draft, setDraft] = useState('');
|
|
88
|
+
// The elapsed time has to move on its own, or a stuck turn looks the same as a fast one.
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
const id = setInterval(() => tick((n) => n + 1), 1000);
|
|
91
|
+
return () => clearInterval(id);
|
|
92
|
+
}, []);
|
|
93
|
+
// Where keys go: the text box, or the approvals list. Tab switches. While the list has focus
|
|
94
|
+
// the text box is inactive, so an 'a' is an approval and never a letter in the draft.
|
|
95
|
+
const [focus, setFocus] = useState('input');
|
|
96
|
+
const [selected, setSelected] = useState(0);
|
|
97
|
+
const [open, setOpen] = useState(false);
|
|
98
|
+
useInput((input, key) => {
|
|
99
|
+
if (key.escape) {
|
|
100
|
+
if (focus === 'list') {
|
|
101
|
+
setFocus('input');
|
|
102
|
+
setOpen(false);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
onQuit();
|
|
106
|
+
exit();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const list = state().approvals ?? [];
|
|
110
|
+
if (key.tab) {
|
|
111
|
+
if (list.length)
|
|
112
|
+
setFocus((f) => (f === 'input' ? 'list' : 'input'));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
// ↓ from an empty prompt walks into the list; ↑ off the top walks back out. The arrow is
|
|
116
|
+
// what a hand reaches for when it sees rows below.
|
|
117
|
+
if (focus !== 'list') {
|
|
118
|
+
if (key.downArrow && list.length && draft === '') {
|
|
119
|
+
setFocus('list');
|
|
120
|
+
setSelected(0);
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (!list.length) {
|
|
125
|
+
setFocus('input');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const i = Math.min(selected, list.length - 1);
|
|
129
|
+
const row = list[i];
|
|
130
|
+
if (key.upArrow || input === 'k') {
|
|
131
|
+
if (i === 0) {
|
|
132
|
+
setFocus('input');
|
|
133
|
+
setOpen(false);
|
|
134
|
+
}
|
|
135
|
+
else
|
|
136
|
+
setSelected(i - 1);
|
|
137
|
+
}
|
|
138
|
+
else if (key.downArrow || input === 'j')
|
|
139
|
+
setSelected(Math.min(list.length - 1, i + 1));
|
|
140
|
+
else if (key.return || input === 'v')
|
|
141
|
+
setOpen((o) => !o);
|
|
142
|
+
else if ((input === 'a' || input === 'd') && row.stage === 'ready' && onDecide)
|
|
143
|
+
onDecide(row.requestId, input === 'a' ? 'allow' : 'deny');
|
|
144
|
+
});
|
|
145
|
+
const s = state();
|
|
146
|
+
const approvals = s.approvals ?? [];
|
|
147
|
+
// Only the tail: a daemon runs for days and a terminal is not a log file.
|
|
148
|
+
const lines = s.lines.slice(-12);
|
|
149
|
+
const busy = !!s.working;
|
|
150
|
+
return (React.createElement(Box, { flexDirection: "column" },
|
|
151
|
+
React.createElement(Box, null,
|
|
152
|
+
React.createElement(Text, { color: s.connected ? 'green' : 'yellow' }, s.connected ? '●' : '○'),
|
|
153
|
+
React.createElement(Text, { bold: true },
|
|
154
|
+
" ",
|
|
155
|
+
s.agent),
|
|
156
|
+
React.createElement(Text, { color: "white" },
|
|
157
|
+
" \u00B7 ",
|
|
158
|
+
basename(s.repo)),
|
|
159
|
+
s.branch && React.createElement(Text, { color: "white" },
|
|
160
|
+
" \u00B7 ",
|
|
161
|
+
s.branch,
|
|
162
|
+
s.base ? ` → ${s.base}` : ''),
|
|
163
|
+
s.engine && s.engine !== 'claude' && React.createElement(Text, { color: "magenta" },
|
|
164
|
+
" \u00B7 ",
|
|
165
|
+
s.engine),
|
|
166
|
+
s.update && React.createElement(Text, { color: "yellow" },
|
|
167
|
+
" \u00B7 \u2191 SDK ",
|
|
168
|
+
s.update,
|
|
169
|
+
" ready \u2014 restart to apply")),
|
|
170
|
+
React.createElement(Box, { marginTop: 1, paddingX: 1, flexDirection: "column" },
|
|
171
|
+
React.createElement(Box, null,
|
|
172
|
+
busy ? (React.createElement(React.Fragment, null,
|
|
173
|
+
React.createElement(Text, { color: "cyan" },
|
|
174
|
+
SPINNER[Math.floor(Date.now() / 120) % SPINNER.length],
|
|
175
|
+
" "),
|
|
176
|
+
React.createElement(Text, { bold: true, color: "cyan" }, s.working),
|
|
177
|
+
React.createElement(Text, { color: "white" },
|
|
178
|
+
" ",
|
|
179
|
+
elapsed(s.since)))) : (React.createElement(Text, { color: "white" }, "waiting for work")),
|
|
180
|
+
React.createElement(Box, { flexGrow: 1 }),
|
|
181
|
+
s.tasks && s.tasks.total > 0 && (React.createElement(React.Fragment, null,
|
|
182
|
+
React.createElement(Text, { color: "white" },
|
|
183
|
+
bar(s.tasks.done, s.tasks.total),
|
|
184
|
+
" "),
|
|
185
|
+
React.createElement(Text, { color: s.tasks.done === s.tasks.total ? 'green' : 'white' },
|
|
186
|
+
s.tasks.done,
|
|
187
|
+
"/",
|
|
188
|
+
s.tasks.total)))),
|
|
189
|
+
busy && lastSaid(s.lines) && (React.createElement(Text, { color: "white", wrap: "truncate-end" }, lastSaid(s.lines)))),
|
|
190
|
+
(s.team?.length ?? 0) > 0 && (React.createElement(Box, { marginTop: 1, paddingX: 1, flexDirection: "column" },
|
|
191
|
+
React.createElement(Text, { color: "white" },
|
|
192
|
+
"team \u00B7 ",
|
|
193
|
+
s.team.filter(busyMember).length,
|
|
194
|
+
"/",
|
|
195
|
+
s.team.length,
|
|
196
|
+
" working"),
|
|
197
|
+
s.team.map((m) => {
|
|
198
|
+
const quiet = memberQuiet(m);
|
|
199
|
+
const doing = m.card || m.state || 'idle';
|
|
200
|
+
// The summary repeats the state word when an agent has nothing to say ("idle idle").
|
|
201
|
+
// Say it once: the column already says it.
|
|
202
|
+
const note = m.summary && m.summary !== m.state ? m.summary : '';
|
|
203
|
+
return (React.createElement(Box, { key: m.name },
|
|
204
|
+
React.createElement(Text, { color: quiet.colour }, quiet.mark),
|
|
205
|
+
React.createElement(Text, { color: "whiteBright" },
|
|
206
|
+
" ",
|
|
207
|
+
m.name.padEnd(12).slice(0, 12)),
|
|
208
|
+
React.createElement(Text, { color: m.card ? 'cyan' : 'white' },
|
|
209
|
+
" ",
|
|
210
|
+
doing.padEnd(12).slice(0, 12)),
|
|
211
|
+
React.createElement(Text, { color: "white" },
|
|
212
|
+
" ",
|
|
213
|
+
plan(m).padEnd(6)),
|
|
214
|
+
React.createElement(Text, { color: m.queued > 0 ? 'yellow' : 'white' }, waiting(m).padEnd(14)),
|
|
215
|
+
React.createElement(Text, { color: "white" },
|
|
216
|
+
" ",
|
|
217
|
+
quiet.since.padEnd(8)),
|
|
218
|
+
React.createElement(Text, { color: m.errorsInARow > 0 ? 'yellow' : 'white', wrap: "truncate-end" },
|
|
219
|
+
m.errorsInARow > 0 ? `${m.errorsInARow} error(s) in a row · ` : '',
|
|
220
|
+
note)));
|
|
221
|
+
}))),
|
|
222
|
+
s.queued > 0 && (React.createElement(Box, { paddingX: 1 },
|
|
223
|
+
React.createElement(Text, { color: "white" },
|
|
224
|
+
s.queued,
|
|
225
|
+
" waiting",
|
|
226
|
+
s.nextCard ? ` · next ${s.nextCard}` : ''))),
|
|
227
|
+
React.createElement(Box, { marginTop: 1, flexDirection: "column" }, lines.map((l, i) =>
|
|
228
|
+
// What the model SAYS is markdown and is rendered as such; the harness's own lines
|
|
229
|
+
// (tools, events, warnings) are plain and stay one line each.
|
|
230
|
+
l.kind === 'say' || l.kind === 'answer' ? (React.createElement(Box, { key: i, paddingLeft: PREFIX[l.kind].length },
|
|
231
|
+
React.createElement(Markdown, { text: l.text, color: COLOUR[l.kind] }))) : (React.createElement(Text, { key: i, color: COLOUR[l.kind], wrap: "truncate-end" },
|
|
232
|
+
PREFIX[l.kind],
|
|
233
|
+
l.kind === 'tool' ? toolName(l.text) : l.text)))),
|
|
234
|
+
React.createElement(Box, { marginTop: 1, borderStyle: "round", borderColor: focus === 'list' ? 'gray' : draft ? 'magenta' : 'gray', paddingX: 1 },
|
|
235
|
+
React.createElement(Text, { color: draft ? 'magenta' : 'white' }, '> '),
|
|
236
|
+
React.createElement(TextInput, { value: draft, focus: focus === 'input', onChange: (v) => setDraft(v.replace(NOT_TYPING, '')), placeholder: busy ? 'steer it' : 'ask it something', onSubmit: (v) => {
|
|
237
|
+
if (v.trim())
|
|
238
|
+
onSteer(v.trim());
|
|
239
|
+
setDraft('');
|
|
240
|
+
} })),
|
|
241
|
+
React.createElement(Box, { paddingX: 1 },
|
|
242
|
+
React.createElement(Text, { color: "white" }, focus === 'list'
|
|
243
|
+
? 'esc back to typing'
|
|
244
|
+
: draft
|
|
245
|
+
? 'enter to send'
|
|
246
|
+
: `${busy ? 'type to steer it mid-turn' : 'type a question — it answers here'}${approvals.length ? ' · ↓ for approvals' : ''} · esc to stop`)),
|
|
247
|
+
approvals.length > 0 && (React.createElement(Box, { marginTop: 1, paddingX: 1, flexDirection: "column" },
|
|
248
|
+
React.createElement(Text, null,
|
|
249
|
+
React.createElement(Text, { bold: true, color: focus === 'list' ? 'yellow' : undefined }, "Approvals"),
|
|
250
|
+
React.createElement(Text, { color: "white" },
|
|
251
|
+
" \u00B7 ",
|
|
252
|
+
approvals.length,
|
|
253
|
+
" waiting",
|
|
254
|
+
onDecide ? '' : ' · no person logged in here (login --me) — answer on the phone')),
|
|
255
|
+
approvals.map((a, i) => {
|
|
256
|
+
const sel = focus === 'list' && i === Math.min(selected, approvals.length - 1);
|
|
257
|
+
const stage = a.stage === 'answered' ? `${a.verdict === 'allow' ? 'approved' : 'denied'} — agent picking it up`
|
|
258
|
+
: a.stage === 'lead' ? 'with lead'
|
|
259
|
+
: a.endorsedBy ? 'endorsed ✓' : 'ready';
|
|
260
|
+
const left = a.expiresAt ? Math.max(0, Math.round((a.expiresAt - Date.now()) / 60000)) : null;
|
|
261
|
+
return (React.createElement(Box, { key: a.commentId, flexDirection: "column" },
|
|
262
|
+
React.createElement(Text, { wrap: "truncate-end" },
|
|
263
|
+
React.createElement(Text, { color: sel ? 'yellow' : 'white' }, sel ? '▸ ' : ' '),
|
|
264
|
+
React.createElement(Text, { bold: sel }, a.agent),
|
|
265
|
+
React.createElement(Text, { color: "white" },
|
|
266
|
+
" ",
|
|
267
|
+
a.card,
|
|
268
|
+
" "),
|
|
269
|
+
React.createElement(Text, { color: a.stage === 'answered' ? 'green' : sel ? 'yellow' : undefined },
|
|
270
|
+
a.name,
|
|
271
|
+
" on ",
|
|
272
|
+
a.target),
|
|
273
|
+
a.preview && React.createElement(Text, { color: "white" },
|
|
274
|
+
" ",
|
|
275
|
+
a.preview),
|
|
276
|
+
React.createElement(Text, { color: a.stage === 'answered' ? 'green' : a.stage === 'lead' ? 'white' : 'cyan' },
|
|
277
|
+
" ",
|
|
278
|
+
stage),
|
|
279
|
+
left !== null && React.createElement(Text, { color: "white" },
|
|
280
|
+
" ",
|
|
281
|
+
left,
|
|
282
|
+
"m left")),
|
|
283
|
+
open && sel && (React.createElement(Box, { marginLeft: 4, marginY: 0, borderStyle: "round", borderColor: "yellow", paddingX: 1, flexDirection: "column" },
|
|
284
|
+
a.script.split('\n').map((ln, k) => React.createElement(Text, { key: k, bold: true, color: "white", wrap: "wrap" }, ln)),
|
|
285
|
+
a.preview && React.createElement(Text, { color: "cyan" }, a.preview),
|
|
286
|
+
React.createElement(Text, { wrap: "wrap" },
|
|
287
|
+
React.createElement(Text, { color: "white" }, "why "),
|
|
288
|
+
a.purpose),
|
|
289
|
+
a.endorsedBy && React.createElement(Text, { wrap: "wrap" },
|
|
290
|
+
React.createElement(Text, { color: "white" }, "lead "),
|
|
291
|
+
React.createElement(Text, { color: "green" }, a.endorsedBy))))));
|
|
292
|
+
}),
|
|
293
|
+
focus === 'list' ? (React.createElement(Text, null,
|
|
294
|
+
React.createElement(Text, { color: "white" },
|
|
295
|
+
"\u2191\u2193 select \u00B7 enter ",
|
|
296
|
+
open ? 'hide' : 'show',
|
|
297
|
+
" script \u00B7 "),
|
|
298
|
+
onDecide && React.createElement(React.Fragment, null,
|
|
299
|
+
React.createElement(Text, { bold: true, color: "green" }, "a"),
|
|
300
|
+
React.createElement(Text, { color: "white" }, " approve \u00B7 "),
|
|
301
|
+
React.createElement(Text, { bold: true, color: "red" }, "d"),
|
|
302
|
+
React.createElement(Text, { color: "white" }, " deny \u00B7 ")),
|
|
303
|
+
React.createElement(Text, { color: "white" }, "esc back"))) : (React.createElement(Text, { color: "white" }, "\u2193 to select one"))))));
|
|
304
|
+
}
|
|
305
|
+
/** True only when a person is actually at a terminal. Under launchd or systemd, nobody is. */
|
|
306
|
+
export const interactive = () => !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
307
|
+
/** How far through its own plan, blank until it has written one. */
|
|
308
|
+
function plan(m) {
|
|
309
|
+
return m.tasks && m.tasks.total > 0 ? `${m.tasks.done}/${m.tasks.total}` : '';
|
|
310
|
+
}
|
|
311
|
+
/** What is stacked behind the card it is on. Blank when nothing is, so a clear queue is quiet. */
|
|
312
|
+
function waiting(m) {
|
|
313
|
+
if (!m.queued)
|
|
314
|
+
return '';
|
|
315
|
+
return m.next ? `+${m.queued} next ${m.next}` : `+${m.queued} queued`;
|
|
316
|
+
}
|
|
317
|
+
/** Working means holding a card. 'idle' with no card is a healthy agent waiting, not a busy one. */
|
|
318
|
+
function busyMember(m) {
|
|
319
|
+
return !!m.card;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* How a report reads at a glance. Agents check in at least every five minutes, so silence is the
|
|
323
|
+
* signal that matters most: a green dot means it spoke recently, yellow means it is late, red
|
|
324
|
+
* means FlareDeck has stopped believing it is there at all.
|
|
325
|
+
*/
|
|
326
|
+
function memberQuiet(m) {
|
|
327
|
+
if (m.quietFor === null)
|
|
328
|
+
return { mark: '○', colour: 'gray', since: 'never' };
|
|
329
|
+
if (m.stale)
|
|
330
|
+
return { mark: '●', colour: 'red', since: `${Math.round(m.quietFor / 60)}m ago` };
|
|
331
|
+
if (m.quietFor > 5 * 60)
|
|
332
|
+
return { mark: '●', colour: 'yellow', since: `${Math.round(m.quietFor / 60)}m ago` };
|
|
333
|
+
return { mark: '●', colour: 'green', since: m.quietFor < 60 ? `${m.quietFor}s ago` : `${Math.round(m.quietFor / 60)}m ago` };
|
|
334
|
+
}
|
|
335
|
+
export function startUi(opts) {
|
|
336
|
+
// Run as a service and there is no TTY, so Ink's raw mode throws on startup. A daemon must not
|
|
337
|
+
// fail to boot because nobody is watching it — fall back to plain lines, which is what a log
|
|
338
|
+
// file wants anyway.
|
|
339
|
+
if (!interactive()) {
|
|
340
|
+
return {
|
|
341
|
+
stop: () => { },
|
|
342
|
+
log: (l) => process.stdout.write(`${PREFIX[l.kind]}${l.text}\n`),
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
const instance = render(React.createElement(App, { state: opts.state, onSteer: opts.onSteer, onQuit: opts.onQuit, ...(opts.onDecide ? { onDecide: opts.onDecide } : {}) }));
|
|
346
|
+
return { stop: () => instance.unmount(), log: () => { } };
|
|
347
|
+
}
|
|
348
|
+
//# sourceMappingURL=ui.js.map
|
package/dist/ui.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.tsx"],"names":[],"mappings":"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"}
|