@pi-archimedes/subagent 2.1.0 → 2.2.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/package.json +2 -2
- package/src/agent-manager.ts +9 -100
- package/src/index.ts +2 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-archimedes/subagent",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package"
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
],
|
|
12
12
|
"main": "./src/index.ts",
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@pi-archimedes/core": "2.
|
|
14
|
+
"@pi-archimedes/core": "2.2.0"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
17
|
"@earendil-works/pi-ai": ">=0.1.0",
|
package/src/agent-manager.ts
CHANGED
|
@@ -24,6 +24,15 @@ import {
|
|
|
24
24
|
setLocalConfig,
|
|
25
25
|
type LocalConfig,
|
|
26
26
|
} from "./local-config.js";
|
|
27
|
+
import {
|
|
28
|
+
visibleWidth,
|
|
29
|
+
padEnd,
|
|
30
|
+
wrapText,
|
|
31
|
+
hardTruncate,
|
|
32
|
+
renderHeader,
|
|
33
|
+
renderFooter,
|
|
34
|
+
wrapWithBorder,
|
|
35
|
+
} from "@pi-archimedes/core/overlay";
|
|
27
36
|
|
|
28
37
|
// ── Screen constants ────────────────────────────────────────────────────────
|
|
29
38
|
|
|
@@ -151,55 +160,6 @@ function fuzzyFilter(items: AgentConfig[], query: string): AgentConfig[] {
|
|
|
151
160
|
);
|
|
152
161
|
}
|
|
153
162
|
|
|
154
|
-
function wrapText(text: string, width: number): string[] {
|
|
155
|
-
if (width <= 0) return [];
|
|
156
|
-
const lines: string[] = [];
|
|
157
|
-
const paragraphs = text.split("\n");
|
|
158
|
-
for (const para of paragraphs) {
|
|
159
|
-
if (para.length === 0) {
|
|
160
|
-
lines.push("");
|
|
161
|
-
continue;
|
|
162
|
-
}
|
|
163
|
-
const words = para.split(/(\s+)/).filter(Boolean);
|
|
164
|
-
let current = "";
|
|
165
|
-
for (const word of words) {
|
|
166
|
-
const test = current === "" ? word : current + word;
|
|
167
|
-
if (test.length > width && current.length > 0) {
|
|
168
|
-
lines.push(current);
|
|
169
|
-
current = word;
|
|
170
|
-
} else {
|
|
171
|
-
current = test;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
if (current) lines.push(current);
|
|
175
|
-
}
|
|
176
|
-
return lines;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
function padEnd(text: string, width: number): string {
|
|
180
|
-
if (width <= 0) return "";
|
|
181
|
-
const vw = visibleWidth(text);
|
|
182
|
-
if (vw >= width) return text;
|
|
183
|
-
return text + " ".repeat(width - vw);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function visibleWidth(text: string): number {
|
|
187
|
-
// Strip ANSI escape sequences for width calculation
|
|
188
|
-
return text.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function row(text: string, width: number, theme: Theme): string {
|
|
192
|
-
return padEnd(text, width);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function renderHeader(text: string, width: number, theme: Theme): string {
|
|
196
|
-
return theme.fg("accent", padEnd(text, width));
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
function renderFooter(text: string, width: number, theme: Theme): string {
|
|
200
|
-
return theme.fg("dim", padEnd(text, width));
|
|
201
|
-
}
|
|
202
|
-
|
|
203
163
|
function scopeLabel(source: "global" | "user" | "project"): string {
|
|
204
164
|
if (source === "global") return "home";
|
|
205
165
|
return source === "user" ? "user" : "proj";
|
|
@@ -220,57 +180,6 @@ function filterModels(models: ModelInfo[], query: string): ModelInfo[] {
|
|
|
220
180
|
);
|
|
221
181
|
}
|
|
222
182
|
|
|
223
|
-
|
|
224
|
-
// ── Border wrapper ────────────────────────────────────────────────────────────
|
|
225
|
-
|
|
226
|
-
/** Hard-truncate by visible width — no "..." suffix. Strips ANSI, truncates, rebuilds. */
|
|
227
|
-
function hardTruncate(text: string, maxVisible: number): string {
|
|
228
|
-
if (visibleWidth(text) <= maxVisible) return text;
|
|
229
|
-
// Strip ANSI codes, truncate, then re-apply any trailing reset codes
|
|
230
|
-
const plain = text.replace(/\x1b\[[0-9;]*m/g, "");
|
|
231
|
-
const truncated = plain.slice(0, maxVisible);
|
|
232
|
-
// Restore any ANSI codes that were in the original up to this point
|
|
233
|
-
let result = "";
|
|
234
|
-
let plainPos = 0;
|
|
235
|
-
let i = 0;
|
|
236
|
-
let copiedSgr = false;
|
|
237
|
-
while (i < text.length && plainPos < maxVisible) {
|
|
238
|
-
if (text[i] === "\x1b" && text[i + 1] === "[") {
|
|
239
|
-
// Copy the escape sequence
|
|
240
|
-
let j = i;
|
|
241
|
-
while (j < text.length && text[j] !== "m") j++;
|
|
242
|
-
result += text.slice(i, j + 1);
|
|
243
|
-
copiedSgr = true;
|
|
244
|
-
i = j + 1;
|
|
245
|
-
} else {
|
|
246
|
-
result += text[i];
|
|
247
|
-
plainPos++;
|
|
248
|
-
i++;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
// Ensure styling doesn't bleed: append reset if we copied SGR and result doesn't end with one
|
|
252
|
-
if (copiedSgr && !/\x1b\[0?m$/.test(result)) {
|
|
253
|
-
result += "\x1b[0m";
|
|
254
|
-
}
|
|
255
|
-
return result;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
function wrapWithBorder(lines: string[], width: number, theme: Theme): string[] {
|
|
259
|
-
const innerWidth = Math.max(1, width - 2);
|
|
260
|
-
const contentWidth = Math.max(1, innerWidth - 2); // minus 1 space padding each side
|
|
261
|
-
const left = theme.fg("dim", "│");
|
|
262
|
-
const right = theme.fg("dim", "│");
|
|
263
|
-
const top = theme.fg("dim", `┌${"─".repeat(innerWidth)}┐`);
|
|
264
|
-
const bottom = theme.fg("dim", `└${"─".repeat(innerWidth)}┘`);
|
|
265
|
-
const result: string[] = [top];
|
|
266
|
-
for (const line of lines) {
|
|
267
|
-
const clamped = hardTruncate(line, contentWidth);
|
|
268
|
-
const padded = " " + padEnd(clamped, contentWidth) + " ";
|
|
269
|
-
result.push(left + padded + right);
|
|
270
|
-
}
|
|
271
|
-
result.push(bottom);
|
|
272
|
-
return result;
|
|
273
|
-
}
|
|
274
183
|
// ── List screen ─────────────────────────────────────────────────────────────
|
|
275
184
|
|
|
276
185
|
function renderList(state: ManagerState, width: number, theme: Theme): string[] {
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { Type } from "typebox";
|
|
|
4
4
|
import { executeSubagent, executeParallel } from "./execute.js";
|
|
5
5
|
// agent-manager.js lazy-loaded below to keep subagent tool registration fast
|
|
6
6
|
import { renderSubagentResult } from "./render.js";
|
|
7
|
+
import { OVERLAY_CHROME } from "@pi-archimedes/core/overlay";
|
|
7
8
|
import { discoverAgents, discoverAgentsAll, findAgent, formatAgentList } from "./agents.js";
|
|
8
9
|
import { validateModel, firstError } from "./model-validation.js";
|
|
9
10
|
import type {
|
|
@@ -346,7 +347,7 @@ export function registerAgentsCommand(pi: ExtensionAPI): void {
|
|
|
346
347
|
(tui: TUI, theme: Theme, _keybindings, done: () => void) => {
|
|
347
348
|
return createAgentManager(globalAgents, user, project, globalDir, userDir, projectDir, tui, theme, done, availableModels, availableTools);
|
|
348
349
|
},
|
|
349
|
-
{ overlay: true, overlayOptions:
|
|
350
|
+
{ overlay: true, overlayOptions: OVERLAY_CHROME },
|
|
350
351
|
);
|
|
351
352
|
},
|
|
352
353
|
});
|