@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 CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @pi-unipi/subagents — Config management
3
3
  *
4
- * Loads config from ~/.unipc/config/subagents.json (global)
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 ~/.unipc/config/subagents.json (global)
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
  */
@@ -2,8 +2,8 @@
2
2
  * @pi-unipi/subagents — Custom agent loader
3
3
  *
4
4
  * Discovers agent types from:
5
- * - <workspace>/.unipc/config/agents/*.md (project, highest priority)
6
- * - ~/.unipc/config/agents/*.md (global)
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
  /**
@@ -2,8 +2,8 @@
2
2
  * @pi-unipi/subagents — Custom agent loader
3
3
  *
4
4
  * Discovers agent types from:
5
- * - <workspace>/.unipc/config/agents/*.md (project, highest priority)
6
- * - ~/.unipc/config/agents/*.md (global)
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, ".unipc", "config", "agents");
14
+ return join(cwd, ".unipi", "config", "agents");
15
15
  }
16
16
  /** Get global agents directory. */
17
17
  function getGlobalAgentsDir() {
18
- return join(homedir(), ".unipc", "config", "agents");
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
- * Adapted from pi-subagents.
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 render;
22
+ private requestRender;
23
+ private renderWidget;
24
+ dispose(): void;
21
25
  }
22
26
  //# sourceMappingURL=widget.d.ts.map
@@ -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;gBAER,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC;IAKvE,QAAQ,CAAC,GAAG,EAAE,GAAG;IAIjB,WAAW;IAQX,YAAY,CAAC,GAAG,EAAE,MAAM;IAUxB,MAAM;IAIN,OAAO,CAAC,MAAM;CAuCf"}
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
- * Adapted from pi-subagents.
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 = ctx;
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.render();
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.render();
78
+ this.requestRender();
74
79
  }
75
- render() {
76
- const agents = this.manager.listAgents();
77
- const running = agents.filter((a) => a.status === "running" || a.status === "queued");
78
- if (running.length === 0) {
79
- // Clear widget
80
- this.uiCtx?.setIndicator?.("");
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
- const frame = SPINNER[this.spinnerFrame];
85
- for (const agent of running) {
86
- const act = this.activity.get(agent.id);
87
- const toolCount = agent.toolUses;
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() - agent.startedAt);
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
- lines.push(`${frame} ${agent.type} ${agent.description} · ${parts.join(" · ")}`, ` ⎿ ${activity}`);
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
- const queued = agents.filter((a) => a.status === "queued").length;
102
- if (queued > 0) {
103
- lines.push(` ${queued} queued`);
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
@@ -1 +1 @@
1
- {"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"widget.js","sourceRoot":"","sources":["../src/widget.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/subagents",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Subagents for UniPi — parallel execution, file locking, workflow integration",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/config.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @pi-unipi/subagents — Config management
3
3
  *
4
- * Loads config from ~/.unipc/config/subagents.json (global)
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
  */
@@ -2,8 +2,8 @@
2
2
  * @pi-unipi/subagents — Custom agent loader
3
3
  *
4
4
  * Discovers agent types from:
5
- * - <workspace>/.unipc/config/agents/*.md (project, highest priority)
6
- * - ~/.unipc/config/agents/*.md (global)
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, ".unipc", "config", "agents");
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(), ".unipc", "config", "agents");
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
- * Adapted from pi-subagents.
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 = ctx;
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.render();
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.render();
86
+ this.requestRender();
82
87
  }
83
88
 
84
- private render() {
85
- const agents = this.manager.listAgents();
86
- const running = agents.filter((a) => a.status === "running" || a.status === "queued");
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
- if (running.length === 0) {
89
- // Clear widget
90
- this.uiCtx?.setIndicator?.("");
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
- for (const agent of running) {
98
- const act = this.activity.get(agent.id);
99
- const toolCount = agent.toolUses;
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() - agent.startedAt);
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
- `${frame} ${agent.type} ${agent.description} · ${parts.join(" · ")}`,
112
- ` ⎿ ${activity}`,
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
- const queued = agents.filter((a) => a.status === "queued").length;
117
- if (queued > 0) {
118
- lines.push(` ${queued} queued`);
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
- this.uiCtx?.setIndicator?.(lines.join("\n"));
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
  }