@opencode-cockpit/subagents 0.7.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 +21 -0
- package/README.md +107 -0
- package/dist/agent/plugin.js +134 -0
- package/dist/cli/preview.js +99 -0
- package/dist/core/adapt/v1.js +341 -0
- package/dist/core/adapt/v2.js +379 -0
- package/dist/core/model/changes.js +17 -0
- package/dist/core/model/model.js +301 -0
- package/dist/core/sample.js +261 -0
- package/dist/core/view/markdown.js +211 -0
- package/dist/core/view/report.js +58 -0
- package/dist/core/view/rows.js +146 -0
- package/dist/core/view/screen.js +767 -0
- package/dist/core/view/sidebar.js +151 -0
- package/dist/server.js +2 -0
- package/dist/tui/index.js +991 -0
- package/dist/tui/render.js +103 -0
- package/dist/tui/source.js +228 -0
- package/dist/tui/view/overlay.js +87 -0
- package/dist/tui/view/sidebar.js +78 -0
- package/package.json +64 -0
- package/server.js +6 -0
- package/tui.js +6 -0
- package/types/agent/plugin.d.ts +32 -0
- package/types/cli/preview.d.ts +10 -0
- package/types/core/adapt/v1.d.ts +33 -0
- package/types/core/adapt/v2.d.ts +22 -0
- package/types/core/model/changes.d.ts +98 -0
- package/types/core/model/model.d.ts +99 -0
- package/types/core/sample.d.ts +8 -0
- package/types/core/view/markdown.d.ts +22 -0
- package/types/core/view/report.d.ts +15 -0
- package/types/core/view/rows.d.ts +43 -0
- package/types/core/view/screen.d.ts +101 -0
- package/types/core/view/sidebar.d.ts +30 -0
- package/types/server.d.ts +2 -0
- package/types/tui/index.d.ts +26 -0
- package/types/tui/render.d.ts +27 -0
- package/types/tui/source.d.ts +45 -0
- package/types/tui/view/overlay.d.ts +30 -0
- package/types/tui/view/sidebar.d.ts +22 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sidebar block: a heading with counts, then two lines per subagent — who it is, and what it is
|
|
3
|
+
* doing now. Every line of a subagent carries its id, so a click on either opens it.
|
|
4
|
+
*
|
|
5
|
+
* The sidebar is a narrow column shared with Context, Shells and the statusline; rows are exactly
|
|
6
|
+
* its width, and a subagent's lines stay two however long its task or target is.
|
|
7
|
+
*
|
|
8
|
+
* Subagents 2 running
|
|
9
|
+
* ⠙ explore Map the auth flow
|
|
10
|
+
* └ grep "session" 9 calls · 51s
|
|
11
|
+
* ● general Update README
|
|
12
|
+
* └ done 3 calls · 28s
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { activityOf, countsOf } from "../model/model.js";
|
|
16
|
+
import { elapsed, fit, spin, spread } from "./rows.js";
|
|
17
|
+
/** The mark before a subagent's name: its state, at a glance. */
|
|
18
|
+
function mark(activity, frame) {
|
|
19
|
+
switch (activity.kind) {
|
|
20
|
+
/** A dot, coloured by how it ended — a check mark drew as a thin "√" in many terminal fonts. */
|
|
21
|
+
case "done":
|
|
22
|
+
return {
|
|
23
|
+
text: "●",
|
|
24
|
+
tone: "success"
|
|
25
|
+
};
|
|
26
|
+
case "failed":
|
|
27
|
+
return {
|
|
28
|
+
text: "●",
|
|
29
|
+
tone: "error"
|
|
30
|
+
};
|
|
31
|
+
case "waiting":
|
|
32
|
+
return {
|
|
33
|
+
text: "○",
|
|
34
|
+
tone: "warning"
|
|
35
|
+
};
|
|
36
|
+
default:
|
|
37
|
+
return {
|
|
38
|
+
text: spin(frame),
|
|
39
|
+
tone: "accent"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** The second line: the current call and its target, or thinking/writing/waiting/done/failed. */
|
|
45
|
+
function doing(activity) {
|
|
46
|
+
switch (activity.kind) {
|
|
47
|
+
case "tool":
|
|
48
|
+
return [{
|
|
49
|
+
text: `${activity.tool ?? "tool"} `,
|
|
50
|
+
tone: "tool"
|
|
51
|
+
}, {
|
|
52
|
+
text: activity.text,
|
|
53
|
+
tone: "text"
|
|
54
|
+
}];
|
|
55
|
+
case "failed":
|
|
56
|
+
/** Stopped — by you, or with the main agent — is not broken. */
|
|
57
|
+
return /abort|interrupt|cancel/i.test(activity.text) ? [{
|
|
58
|
+
text: "cancelled",
|
|
59
|
+
tone: "warning"
|
|
60
|
+
}] : [{
|
|
61
|
+
text: `failed: ${activity.text}`,
|
|
62
|
+
tone: "error"
|
|
63
|
+
}];
|
|
64
|
+
case "done":
|
|
65
|
+
return [{
|
|
66
|
+
text: "done",
|
|
67
|
+
tone: "success"
|
|
68
|
+
}];
|
|
69
|
+
default:
|
|
70
|
+
return [{
|
|
71
|
+
text: activity.text,
|
|
72
|
+
tone: "muted"
|
|
73
|
+
}];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
export function sidebarLines(input) {
|
|
77
|
+
const {
|
|
78
|
+
nodes,
|
|
79
|
+
width,
|
|
80
|
+
now,
|
|
81
|
+
frame
|
|
82
|
+
} = input;
|
|
83
|
+
/** Silence is the rule: no subagents, no block. */
|
|
84
|
+
if (nodes.length === 0 || width < 8) return [];
|
|
85
|
+
const counts = countsOf(nodes);
|
|
86
|
+
/** What needs your eye: how many are working, else how it ended. */
|
|
87
|
+
const summary = counts.running ? `${counts.running} running` : counts.failed ? `${counts.failed} failed` : `${counts.done} done`;
|
|
88
|
+
const lines = [{
|
|
89
|
+
row: spread([{
|
|
90
|
+
text: "Subagents",
|
|
91
|
+
tone: "text",
|
|
92
|
+
bold: true
|
|
93
|
+
}], [{
|
|
94
|
+
text: summary,
|
|
95
|
+
tone: counts.running ? "accent" : counts.failed ? "error" : "muted"
|
|
96
|
+
}], width)
|
|
97
|
+
}];
|
|
98
|
+
|
|
99
|
+
/** Working ones first, so the one you are wondering about is never folded away. */
|
|
100
|
+
const limit = Math.max(1, input.limit ?? 6);
|
|
101
|
+
const active = nodes.filter(node => node.session.status !== "done" && node.session.status !== "failed");
|
|
102
|
+
const shown = active.length >= limit ? active.slice(0, limit) : [...active, ...nodes.filter(node => !active.includes(node)).slice(-(limit - active.length))];
|
|
103
|
+
const visible = nodes.filter(node => shown.includes(node));
|
|
104
|
+
for (const {
|
|
105
|
+
session,
|
|
106
|
+
depth
|
|
107
|
+
} of visible) {
|
|
108
|
+
const activity = activityOf(session);
|
|
109
|
+
const indent = " ".repeat(Math.min(depth, 3));
|
|
110
|
+
const id = session.id;
|
|
111
|
+
lines.push({
|
|
112
|
+
id,
|
|
113
|
+
row: fit([{
|
|
114
|
+
text: indent
|
|
115
|
+
}, mark(activity, frame), {
|
|
116
|
+
text: ` ${session.agent} `,
|
|
117
|
+
tone: "info"
|
|
118
|
+
}, {
|
|
119
|
+
text: session.title || session.task || "subagent",
|
|
120
|
+
tone: "text"
|
|
121
|
+
}], width)
|
|
122
|
+
});
|
|
123
|
+
const since = activity.kind === "done" || activity.kind === "failed" ? (session.ended ?? now) - session.started : now - activity.since;
|
|
124
|
+
const calls = session.entries.filter(entry => entry.kind === "tool").length;
|
|
125
|
+
/** Continued by the main agent, or messaged by you: each is a round. */
|
|
126
|
+
const rounds = session.entries.filter(entry => entry.kind === "prompt").length;
|
|
127
|
+
lines.push({
|
|
128
|
+
id,
|
|
129
|
+
row: spread([{
|
|
130
|
+
text: `${indent} └ `,
|
|
131
|
+
tone: "border"
|
|
132
|
+
}, ...doing(activity), ...(rounds > 1 ? [{
|
|
133
|
+
text: ` · ${rounds} rounds`,
|
|
134
|
+
tone: "muted"
|
|
135
|
+
}] : [])], /** Right-aligned, so the target gives way and the numbers stay whole. */
|
|
136
|
+
/** Said in words: a bare "157 · 34m" read as a puzzle. */
|
|
137
|
+
[{
|
|
138
|
+
text: calls > 0 ? `${calls} call${calls === 1 ? "" : "s"} · ${elapsed(since)}` : elapsed(since),
|
|
139
|
+
tone: "muted"
|
|
140
|
+
}], width)
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
const hidden = nodes.length - visible.length;
|
|
144
|
+
if (hidden > 0) lines.push({
|
|
145
|
+
row: fit([{
|
|
146
|
+
text: ` + ${hidden} more`,
|
|
147
|
+
tone: "muted"
|
|
148
|
+
}], width)
|
|
149
|
+
});
|
|
150
|
+
return lines;
|
|
151
|
+
}
|
package/dist/server.js
ADDED