@pi-unipi/subagents 0.1.0 → 0.1.1
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/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/custom-agents.d.ts +2 -2
- package/dist/custom-agents.js +4 -4
- package/dist/widget.d.ts +6 -2
- package/dist/widget.d.ts.map +1 -1
- package/dist/widget.js +83 -21
- package/dist/widget.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +1 -1
- package/src/custom-agents.ts +4 -4
- package/src/widget.ts +97 -22
package/dist/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @pi-unipi/subagents — Config management
|
|
3
3
|
*
|
|
4
|
-
* Loads config from ~/.
|
|
4
|
+
* Loads config from ~/.unipi/config/subagents.json (global)
|
|
5
5
|
* and <workspace>/.unipi/config/subagents.json (override).
|
|
6
6
|
* Auto-generates on first run. Repairs corrupted files.
|
|
7
7
|
*/
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @pi-unipi/subagents — Config management
|
|
3
3
|
*
|
|
4
|
-
* Loads config from ~/.
|
|
4
|
+
* Loads config from ~/.unipi/config/subagents.json (global)
|
|
5
5
|
* and <workspace>/.unipi/config/subagents.json (override).
|
|
6
6
|
* Auto-generates on first run. Repairs corrupted files.
|
|
7
7
|
*/
|
package/dist/custom-agents.d.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @pi-unipi/subagents — Custom agent loader
|
|
3
3
|
*
|
|
4
4
|
* Discovers agent types from:
|
|
5
|
-
* - <workspace>/.
|
|
6
|
-
* - ~/.
|
|
5
|
+
* - <workspace>/.unipi/config/agents/*.md (project, highest priority)
|
|
6
|
+
* - ~/.unipi/config/agents/*.md (global)
|
|
7
7
|
*/
|
|
8
8
|
import type { AgentConfig } from "./types.js";
|
|
9
9
|
/**
|
package/dist/custom-agents.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @pi-unipi/subagents — Custom agent loader
|
|
3
3
|
*
|
|
4
4
|
* Discovers agent types from:
|
|
5
|
-
* - <workspace>/.
|
|
6
|
-
* - ~/.
|
|
5
|
+
* - <workspace>/.unipi/config/agents/*.md (project, highest priority)
|
|
6
|
+
* - ~/.unipi/config/agents/*.md (global)
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
9
9
|
import { join } from "node:path";
|
|
@@ -11,11 +11,11 @@ import { homedir } from "node:os";
|
|
|
11
11
|
import { parseFrontmatter } from "@mariozechner/pi-coding-agent";
|
|
12
12
|
/** Get project agents directory. */
|
|
13
13
|
function getProjectAgentsDir(cwd) {
|
|
14
|
-
return join(cwd, ".
|
|
14
|
+
return join(cwd, ".unipi", "config", "agents");
|
|
15
15
|
}
|
|
16
16
|
/** Get global agents directory. */
|
|
17
17
|
function getGlobalAgentsDir() {
|
|
18
|
-
return join(homedir(), ".
|
|
18
|
+
return join(homedir(), ".unipi", "config", "agents");
|
|
19
19
|
}
|
|
20
20
|
/** All known built-in tool names. */
|
|
21
21
|
const BUILTIN_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls"];
|
package/dist/widget.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @pi-unipi/subagents — Live widget
|
|
3
3
|
*
|
|
4
4
|
* Shows running agents above the editor.
|
|
5
|
-
*
|
|
5
|
+
* Uses setWidget API for proper rendering.
|
|
6
6
|
*/
|
|
7
7
|
import type { AgentManager } from "./agent-manager.js";
|
|
8
8
|
import type { AgentActivity } from "./types.js";
|
|
@@ -12,11 +12,15 @@ export declare class AgentWidget {
|
|
|
12
12
|
private spinnerFrame;
|
|
13
13
|
private timer?;
|
|
14
14
|
private uiCtx?;
|
|
15
|
+
private widgetRegistered;
|
|
16
|
+
private tui?;
|
|
15
17
|
constructor(manager: AgentManager, activity: Map<string, AgentActivity>);
|
|
16
18
|
setUICtx(ctx: any): void;
|
|
17
19
|
ensureTimer(): void;
|
|
18
20
|
markFinished(_id: string): void;
|
|
19
21
|
update(): void;
|
|
20
|
-
private
|
|
22
|
+
private requestRender;
|
|
23
|
+
private renderWidget;
|
|
24
|
+
dispose(): void;
|
|
21
25
|
}
|
|
22
26
|
//# sourceMappingURL=widget.d.ts.map
|
package/dist/widget.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAqChD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAC,CAAM;
|
|
1
|
+
{"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAqChD,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,KAAK,CAAC,CAAiC;IAC/C,OAAO,CAAC,KAAK,CAAC,CAAM;IACpB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,GAAG,CAAC,CAAM;gBAEN,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC;IAKvE,QAAQ,CAAC,GAAG,EAAE,GAAG;IAQjB,WAAW;IAQX,YAAY,CAAC,GAAG,EAAE,MAAM;IASxB,MAAM;IAIN,OAAO,CAAC,aAAa;IAwCrB,OAAO,CAAC,YAAY;IA0DpB,OAAO;CAWR"}
|
package/dist/widget.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @pi-unipi/subagents — Live widget
|
|
3
3
|
*
|
|
4
4
|
* Shows running agents above the editor.
|
|
5
|
-
*
|
|
5
|
+
* Uses setWidget API for proper rendering.
|
|
6
6
|
*/
|
|
7
7
|
/** Spinner frames (braille). */
|
|
8
8
|
const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
@@ -45,23 +45,28 @@ export class AgentWidget {
|
|
|
45
45
|
spinnerFrame = 0;
|
|
46
46
|
timer;
|
|
47
47
|
uiCtx;
|
|
48
|
+
widgetRegistered = false;
|
|
49
|
+
tui;
|
|
48
50
|
constructor(manager, activity) {
|
|
49
51
|
this.manager = manager;
|
|
50
52
|
this.activity = activity;
|
|
51
53
|
}
|
|
52
54
|
setUICtx(ctx) {
|
|
53
|
-
this.uiCtx
|
|
55
|
+
if (ctx !== this.uiCtx) {
|
|
56
|
+
this.uiCtx = ctx;
|
|
57
|
+
this.widgetRegistered = false;
|
|
58
|
+
this.tui = undefined;
|
|
59
|
+
}
|
|
54
60
|
}
|
|
55
61
|
ensureTimer() {
|
|
56
62
|
if (this.timer)
|
|
57
63
|
return;
|
|
58
64
|
this.timer = setInterval(() => {
|
|
59
65
|
this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER.length;
|
|
60
|
-
this.
|
|
66
|
+
this.requestRender();
|
|
61
67
|
}, 80);
|
|
62
68
|
}
|
|
63
69
|
markFinished(_id) {
|
|
64
|
-
// Check if any agents still running
|
|
65
70
|
if (!this.manager.hasRunning()) {
|
|
66
71
|
if (this.timer) {
|
|
67
72
|
clearInterval(this.timer);
|
|
@@ -70,23 +75,65 @@ export class AgentWidget {
|
|
|
70
75
|
}
|
|
71
76
|
}
|
|
72
77
|
update() {
|
|
73
|
-
this.
|
|
78
|
+
this.requestRender();
|
|
74
79
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
requestRender() {
|
|
81
|
+
if (!this.uiCtx)
|
|
82
|
+
return;
|
|
83
|
+
const allAgents = this.manager.listAgents();
|
|
84
|
+
const running = allAgents.filter((a) => a.status === "running" || a.status === "queued");
|
|
85
|
+
const hasActive = running.length > 0;
|
|
86
|
+
// Nothing to show — clear widget
|
|
87
|
+
if (!hasActive) {
|
|
88
|
+
if (this.widgetRegistered) {
|
|
89
|
+
this.uiCtx.setWidget("unipi-agents", undefined);
|
|
90
|
+
this.widgetRegistered = false;
|
|
91
|
+
this.tui = undefined;
|
|
92
|
+
}
|
|
81
93
|
return;
|
|
82
94
|
}
|
|
95
|
+
// Register widget callback once, then request re-render
|
|
96
|
+
if (!this.widgetRegistered) {
|
|
97
|
+
this.uiCtx.setWidget("unipi-agents", (tui, theme) => {
|
|
98
|
+
this.tui = tui;
|
|
99
|
+
return {
|
|
100
|
+
render: () => this.renderWidget(tui, theme),
|
|
101
|
+
invalidate: () => {
|
|
102
|
+
this.widgetRegistered = false;
|
|
103
|
+
this.tui = undefined;
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}, { placement: "aboveEditor" });
|
|
107
|
+
this.widgetRegistered = true;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Widget already registered — request re-render
|
|
111
|
+
this.tui?.requestRender?.();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
renderWidget(tui, theme) {
|
|
115
|
+
const allAgents = this.manager.listAgents();
|
|
116
|
+
const running = allAgents.filter((a) => a.status === "running");
|
|
117
|
+
const queued = allAgents.filter((a) => a.status === "queued");
|
|
118
|
+
if (running.length === 0 && queued.length === 0)
|
|
119
|
+
return [];
|
|
120
|
+
const w = tui.terminal?.columns ?? 80;
|
|
121
|
+
const truncate = (line) => {
|
|
122
|
+
if (line.length <= w)
|
|
123
|
+
return line;
|
|
124
|
+
return line.slice(0, w - 1) + "…";
|
|
125
|
+
};
|
|
126
|
+
const frame = SPINNER[this.spinnerFrame % SPINNER.length];
|
|
83
127
|
const lines = [];
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
128
|
+
// Heading
|
|
129
|
+
lines.push(truncate(theme.fg("accent", "●") + " " + theme.fg("accent", "Agents")));
|
|
130
|
+
// Running agents (2 lines each: header + activity)
|
|
131
|
+
for (let i = 0; i < running.length; i++) {
|
|
132
|
+
const a = running[i];
|
|
133
|
+
const act = this.activity.get(a.id);
|
|
134
|
+
const toolCount = a.toolUses;
|
|
88
135
|
const tokens = act?.tokens ?? "";
|
|
89
|
-
const duration = formatMs(Date.now() -
|
|
136
|
+
const duration = formatMs(Date.now() - a.startedAt);
|
|
90
137
|
const activity = act ? describeActivity(act.activeTools, act.responseText) : "starting…";
|
|
91
138
|
const parts = [];
|
|
92
139
|
if (act?.turnCount)
|
|
@@ -96,13 +143,28 @@ export class AgentWidget {
|
|
|
96
143
|
if (tokens)
|
|
97
144
|
parts.push(tokens);
|
|
98
145
|
parts.push(duration);
|
|
99
|
-
|
|
146
|
+
const connector = i === running.length - 1 && queued.length === 0 ? "└─" : "├─";
|
|
147
|
+
const activityConnector = i === running.length - 1 && queued.length === 0 ? " " : "│ ";
|
|
148
|
+
lines.push(truncate(theme.fg("dim", connector) +
|
|
149
|
+
` ${theme.fg("accent", frame)} ${theme.bold(a.type)} ${theme.fg("dim", a.description)} · ${theme.fg("dim", parts.join(" · "))}`));
|
|
150
|
+
lines.push(truncate(theme.fg("dim", activityConnector) + theme.fg("dim", ` ⎿ ${activity}`)));
|
|
151
|
+
}
|
|
152
|
+
// Queued
|
|
153
|
+
if (queued.length > 0) {
|
|
154
|
+
lines.push(truncate(theme.fg("dim", "└─") + ` ${theme.fg("muted", "◦")} ${theme.fg("dim", `${queued.length} queued`)}`));
|
|
155
|
+
}
|
|
156
|
+
return lines;
|
|
157
|
+
}
|
|
158
|
+
dispose() {
|
|
159
|
+
if (this.timer) {
|
|
160
|
+
clearInterval(this.timer);
|
|
161
|
+
this.timer = undefined;
|
|
100
162
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
163
|
+
if (this.uiCtx && this.widgetRegistered) {
|
|
164
|
+
this.uiCtx.setWidget("unipi-agents", undefined);
|
|
165
|
+
this.widgetRegistered = false;
|
|
166
|
+
this.tui = undefined;
|
|
104
167
|
}
|
|
105
|
-
this.uiCtx?.setIndicator?.(lines.join("\n"));
|
|
106
168
|
}
|
|
107
169
|
}
|
|
108
170
|
//# sourceMappingURL=widget.js.map
|
package/dist/widget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,gCAAgC;AAChC,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEnE,0BAA0B;AAC1B,SAAS,YAAY,CAAC,CAAS;IAC7B,IAAI,CAAC,IAAI,SAAS;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5D,IAAI,CAAC,IAAI,KAAK;QAAE,OAAO,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACpD,OAAO,GAAG,CAAC,EAAE,CAAC;AAChB,CAAC;AAED,uBAAuB;AACvB,SAAS,QAAQ,CAAC,EAAU;IAC1B,IAAI,EAAE,IAAI,MAAM;QAAE,OAAO,GAAG,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACxD,IAAI,EAAE,IAAI,KAAK;QAAE,OAAO,GAAG,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IACtD,OAAO,GAAG,EAAE,IAAI,CAAC;AACnB,CAAC;AAED,oBAAoB;AACpB,SAAS,WAAW,CAAC,IAAY,EAAE,GAAY;IAC7C,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;AAC9C,CAAC;AAED,mDAAmD;AACnD,SAAS,gBAAgB,CAAC,WAAgC,EAAE,YAAoB;IAC9E,IAAI,WAAW,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC;IAChC,CAAC;IACD,IAAI,YAAY,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QAC9D,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,OAAO,WAAW;IACd,OAAO,CAAe;IACtB,QAAQ,CAA6B;IACrC,YAAY,GAAG,CAAC,CAAC;IACjB,KAAK,CAAkC;IACvC,KAAK,CAAO;
|
|
1
|
+
{"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @pi-unipi/subagents — Config management
|
|
3
3
|
*
|
|
4
|
-
* Loads config from ~/.
|
|
4
|
+
* Loads config from ~/.unipi/config/subagents.json (global)
|
|
5
5
|
* and <workspace>/.unipi/config/subagents.json (override).
|
|
6
6
|
* Auto-generates on first run. Repairs corrupted files.
|
|
7
7
|
*/
|
package/src/custom-agents.ts
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @pi-unipi/subagents — Custom agent loader
|
|
3
3
|
*
|
|
4
4
|
* Discovers agent types from:
|
|
5
|
-
* - <workspace>/.
|
|
6
|
-
* - ~/.
|
|
5
|
+
* - <workspace>/.unipi/config/agents/*.md (project, highest priority)
|
|
6
|
+
* - ~/.unipi/config/agents/*.md (global)
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
@@ -14,12 +14,12 @@ import type { AgentConfig } from "./types.js";
|
|
|
14
14
|
|
|
15
15
|
/** Get project agents directory. */
|
|
16
16
|
function getProjectAgentsDir(cwd: string): string {
|
|
17
|
-
return join(cwd, ".
|
|
17
|
+
return join(cwd, ".unipi", "config", "agents");
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
/** Get global agents directory. */
|
|
21
21
|
function getGlobalAgentsDir(): string {
|
|
22
|
-
return join(homedir(), ".
|
|
22
|
+
return join(homedir(), ".unipi", "config", "agents");
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/** All known built-in tool names. */
|
package/src/widget.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @pi-unipi/subagents — Live widget
|
|
3
3
|
*
|
|
4
4
|
* Shows running agents above the editor.
|
|
5
|
-
*
|
|
5
|
+
* Uses setWidget API for proper rendering.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { AgentManager } from "./agent-manager.js";
|
|
@@ -49,6 +49,8 @@ export class AgentWidget {
|
|
|
49
49
|
private spinnerFrame = 0;
|
|
50
50
|
private timer?: ReturnType<typeof setInterval>;
|
|
51
51
|
private uiCtx?: any;
|
|
52
|
+
private widgetRegistered = false;
|
|
53
|
+
private tui?: any;
|
|
52
54
|
|
|
53
55
|
constructor(manager: AgentManager, activity: Map<string, AgentActivity>) {
|
|
54
56
|
this.manager = manager;
|
|
@@ -56,19 +58,22 @@ export class AgentWidget {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
setUICtx(ctx: any) {
|
|
59
|
-
this.uiCtx
|
|
61
|
+
if (ctx !== this.uiCtx) {
|
|
62
|
+
this.uiCtx = ctx;
|
|
63
|
+
this.widgetRegistered = false;
|
|
64
|
+
this.tui = undefined;
|
|
65
|
+
}
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
ensureTimer() {
|
|
63
69
|
if (this.timer) return;
|
|
64
70
|
this.timer = setInterval(() => {
|
|
65
71
|
this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER.length;
|
|
66
|
-
this.
|
|
72
|
+
this.requestRender();
|
|
67
73
|
}, 80);
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
markFinished(_id: string) {
|
|
71
|
-
// Check if any agents still running
|
|
72
77
|
if (!this.manager.hasRunning()) {
|
|
73
78
|
if (this.timer) {
|
|
74
79
|
clearInterval(this.timer);
|
|
@@ -78,27 +83,75 @@ export class AgentWidget {
|
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
update() {
|
|
81
|
-
this.
|
|
86
|
+
this.requestRender();
|
|
82
87
|
}
|
|
83
88
|
|
|
84
|
-
private
|
|
85
|
-
|
|
86
|
-
|
|
89
|
+
private requestRender() {
|
|
90
|
+
if (!this.uiCtx) return;
|
|
91
|
+
|
|
92
|
+
const allAgents = this.manager.listAgents();
|
|
93
|
+
const running = allAgents.filter((a) => a.status === "running" || a.status === "queued");
|
|
94
|
+
const hasActive = running.length > 0;
|
|
87
95
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
this.
|
|
96
|
+
// Nothing to show — clear widget
|
|
97
|
+
if (!hasActive) {
|
|
98
|
+
if (this.widgetRegistered) {
|
|
99
|
+
this.uiCtx.setWidget("unipi-agents", undefined);
|
|
100
|
+
this.widgetRegistered = false;
|
|
101
|
+
this.tui = undefined;
|
|
102
|
+
}
|
|
91
103
|
return;
|
|
92
104
|
}
|
|
93
105
|
|
|
106
|
+
// Register widget callback once, then request re-render
|
|
107
|
+
if (!this.widgetRegistered) {
|
|
108
|
+
this.uiCtx.setWidget(
|
|
109
|
+
"unipi-agents",
|
|
110
|
+
(tui: any, theme: any) => {
|
|
111
|
+
this.tui = tui;
|
|
112
|
+
return {
|
|
113
|
+
render: () => this.renderWidget(tui, theme),
|
|
114
|
+
invalidate: () => {
|
|
115
|
+
this.widgetRegistered = false;
|
|
116
|
+
this.tui = undefined;
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
{ placement: "aboveEditor" },
|
|
121
|
+
);
|
|
122
|
+
this.widgetRegistered = true;
|
|
123
|
+
} else {
|
|
124
|
+
// Widget already registered — request re-render
|
|
125
|
+
this.tui?.requestRender?.();
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private renderWidget(tui: any, theme: any): string[] {
|
|
130
|
+
const allAgents = this.manager.listAgents();
|
|
131
|
+
const running = allAgents.filter((a) => a.status === "running");
|
|
132
|
+
const queued = allAgents.filter((a) => a.status === "queued");
|
|
133
|
+
|
|
134
|
+
if (running.length === 0 && queued.length === 0) return [];
|
|
135
|
+
|
|
136
|
+
const w = tui.terminal?.columns ?? 80;
|
|
137
|
+
const truncate = (line: string) => {
|
|
138
|
+
if (line.length <= w) return line;
|
|
139
|
+
return line.slice(0, w - 1) + "…";
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const frame = SPINNER[this.spinnerFrame % SPINNER.length];
|
|
94
143
|
const lines: string[] = [];
|
|
95
|
-
const frame = SPINNER[this.spinnerFrame];
|
|
96
144
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
145
|
+
// Heading
|
|
146
|
+
lines.push(truncate(theme.fg("accent", "●") + " " + theme.fg("accent", "Agents")));
|
|
147
|
+
|
|
148
|
+
// Running agents (2 lines each: header + activity)
|
|
149
|
+
for (let i = 0; i < running.length; i++) {
|
|
150
|
+
const a = running[i];
|
|
151
|
+
const act = this.activity.get(a.id);
|
|
152
|
+
const toolCount = a.toolUses;
|
|
100
153
|
const tokens = act?.tokens ?? "";
|
|
101
|
-
const duration = formatMs(Date.now() -
|
|
154
|
+
const duration = formatMs(Date.now() - a.startedAt);
|
|
102
155
|
const activity = act ? describeActivity(act.activeTools, act.responseText) : "starting…";
|
|
103
156
|
|
|
104
157
|
const parts: string[] = [];
|
|
@@ -107,17 +160,39 @@ export class AgentWidget {
|
|
|
107
160
|
if (tokens) parts.push(tokens);
|
|
108
161
|
parts.push(duration);
|
|
109
162
|
|
|
163
|
+
const connector = i === running.length - 1 && queued.length === 0 ? "└─" : "├─";
|
|
164
|
+
const activityConnector = i === running.length - 1 && queued.length === 0 ? " " : "│ ";
|
|
165
|
+
|
|
110
166
|
lines.push(
|
|
111
|
-
|
|
112
|
-
|
|
167
|
+
truncate(
|
|
168
|
+
theme.fg("dim", connector) +
|
|
169
|
+
` ${theme.fg("accent", frame)} ${theme.bold(a.type)} ${theme.fg("dim", a.description)} · ${theme.fg("dim", parts.join(" · "))}`,
|
|
170
|
+
),
|
|
171
|
+
);
|
|
172
|
+
lines.push(
|
|
173
|
+
truncate(theme.fg("dim", activityConnector) + theme.fg("dim", ` ⎿ ${activity}`)),
|
|
113
174
|
);
|
|
114
175
|
}
|
|
115
176
|
|
|
116
|
-
|
|
117
|
-
if (queued > 0) {
|
|
118
|
-
lines.push(
|
|
177
|
+
// Queued
|
|
178
|
+
if (queued.length > 0) {
|
|
179
|
+
lines.push(
|
|
180
|
+
truncate(theme.fg("dim", "└─") + ` ${theme.fg("muted", "◦")} ${theme.fg("dim", `${queued.length} queued`)}`),
|
|
181
|
+
);
|
|
119
182
|
}
|
|
120
183
|
|
|
121
|
-
|
|
184
|
+
return lines;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
dispose() {
|
|
188
|
+
if (this.timer) {
|
|
189
|
+
clearInterval(this.timer);
|
|
190
|
+
this.timer = undefined;
|
|
191
|
+
}
|
|
192
|
+
if (this.uiCtx && this.widgetRegistered) {
|
|
193
|
+
this.uiCtx.setWidget("unipi-agents", undefined);
|
|
194
|
+
this.widgetRegistered = false;
|
|
195
|
+
this.tui = undefined;
|
|
196
|
+
}
|
|
122
197
|
}
|
|
123
198
|
}
|