@pi-unipi/subagents 2.4.0 → 2.4.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.
Files changed (66) hide show
  1. package/README.md +3 -1
  2. package/dist/agent-manager.d.ts +81 -0
  3. package/dist/agent-manager.d.ts.map +1 -0
  4. package/dist/agent-manager.js +292 -0
  5. package/dist/agent-manager.js.map +1 -0
  6. package/dist/agent-runner.d.ts +51 -0
  7. package/dist/agent-runner.d.ts.map +1 -0
  8. package/dist/agent-runner.js +262 -0
  9. package/dist/agent-runner.js.map +1 -0
  10. package/dist/config.d.ts +24 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +132 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/conversation-viewer.d.ts +40 -0
  15. package/dist/conversation-viewer.d.ts.map +1 -0
  16. package/dist/conversation-viewer.js +276 -0
  17. package/dist/conversation-viewer.js.map +1 -0
  18. package/dist/core-compat.d.ts +14 -0
  19. package/dist/core-compat.d.ts.map +1 -0
  20. package/dist/core-compat.js +24 -0
  21. package/dist/core-compat.js.map +1 -0
  22. package/dist/custom-agents.d.ts +14 -0
  23. package/dist/custom-agents.d.ts.map +1 -0
  24. package/dist/custom-agents.js +106 -0
  25. package/dist/custom-agents.js.map +1 -0
  26. package/dist/file-lock.d.ts +42 -0
  27. package/dist/file-lock.d.ts.map +1 -0
  28. package/dist/file-lock.js +91 -0
  29. package/dist/file-lock.js.map +1 -0
  30. package/dist/index.d.ts +10 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +751 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/model-resolver.d.ts +19 -0
  35. package/dist/model-resolver.d.ts.map +1 -0
  36. package/dist/model-resolver.js +61 -0
  37. package/dist/model-resolver.js.map +1 -0
  38. package/dist/types.d.ts +96 -0
  39. package/dist/types.d.ts.map +1 -0
  40. package/dist/types.js +47 -0
  41. package/dist/types.js.map +1 -0
  42. package/dist/widget.d.ts +56 -0
  43. package/dist/widget.d.ts.map +1 -0
  44. package/dist/widget.js +396 -0
  45. package/dist/widget.js.map +1 -0
  46. package/package.json +10 -6
  47. package/src/__tests__/badge-generation.test.ts +0 -315
  48. package/src/__tests__/config.test.ts +0 -240
  49. package/src/__tests__/esc-propagation.test.ts +0 -162
  50. package/src/__tests__/file-lock.test.ts +0 -244
  51. package/src/__tests__/shutdown-stale-ctx.test.ts +0 -185
  52. package/src/__tests__/workflow-integration.test.ts +0 -334
  53. package/src/agent-manager.ts +0 -334
  54. package/src/agent-runner.ts +0 -329
  55. package/src/config.ts +0 -147
  56. package/src/conversation-viewer.ts +0 -299
  57. package/src/custom-agents.ts +0 -118
  58. package/src/file-lock.ts +0 -102
  59. package/src/index.ts +0 -862
  60. package/src/model-resolver.ts +0 -79
  61. package/src/prompts.ts +0 -39
  62. package/src/skills/explore/SKILL.md +0 -32
  63. package/src/skills/work/SKILL.md +0 -40
  64. package/src/types.ts +0 -146
  65. package/src/widget.ts +0 -454
  66. package/tsconfig.json +0 -19
@@ -0,0 +1,276 @@
1
+ /**
2
+ * @pi-unipi/subagents — Conversation Viewer
3
+ *
4
+ * Live-scrolling overlay for viewing agent conversations.
5
+ * Subscribes to session events for real-time streaming updates.
6
+ * Supports keyboard navigation: ↑↓, PgUp/PgDn, Home/End, Esc/q to close.
7
+ */
8
+ import { matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "@earendil-works/pi-tui";
9
+ /** Lines consumed by chrome: top border + header + header sep + footer sep + footer + bottom border. */
10
+ const CHROME_LINES = 6;
11
+ const MIN_VIEWPORT = 3;
12
+ /** Extract text from content array. */
13
+ function extractText(content) {
14
+ if (typeof content === "string")
15
+ return content;
16
+ return content
17
+ .filter((p) => p.type === "text" && typeof p.text === "string")
18
+ .map((p) => p.text)
19
+ .join("");
20
+ }
21
+ /** Format duration. */
22
+ function formatMs(ms) {
23
+ if (ms >= 60_000)
24
+ return `${(ms / 60_000).toFixed(1)}m`;
25
+ if (ms >= 1_000)
26
+ return `${(ms / 1_000).toFixed(1)}s`;
27
+ return `${ms}ms`;
28
+ }
29
+ /** Format tokens compactly. */
30
+ function formatTokens(count) {
31
+ if (count >= 1_000_000)
32
+ return `${(count / 1_000_000).toFixed(1)}M token`;
33
+ if (count >= 1_000)
34
+ return `${(count / 1_000).toFixed(1)}k token`;
35
+ return `${count} token`;
36
+ }
37
+ /** Describe current activity from active tools. */
38
+ function describeActivity(activeTools, responseText) {
39
+ if (activeTools.size > 0) {
40
+ const names = [...new Set(activeTools.values())];
41
+ return names.join(", ") + "…";
42
+ }
43
+ if (responseText && responseText.trim().length > 0) {
44
+ const lastLine = responseText.split("\n").find((l) => l.trim())?.trim() ?? "";
45
+ if (lastLine.length > 60)
46
+ return lastLine.slice(0, 60) + "…";
47
+ if (lastLine.length > 0)
48
+ return lastLine;
49
+ }
50
+ return "thinking…";
51
+ }
52
+ export class ConversationViewer {
53
+ tui;
54
+ session;
55
+ record;
56
+ activity;
57
+ theme;
58
+ done;
59
+ scrollOffset = 0;
60
+ autoScroll = true;
61
+ unsubscribe;
62
+ lastInnerW = 0;
63
+ closed = false;
64
+ constructor(tui, session, record, activity, theme, done) {
65
+ this.tui = tui;
66
+ this.session = session;
67
+ this.record = record;
68
+ this.activity = activity;
69
+ this.theme = theme;
70
+ this.done = done;
71
+ this.unsubscribe = session.subscribe(() => {
72
+ if (this.closed)
73
+ return;
74
+ this.tui.requestRender();
75
+ });
76
+ }
77
+ handleInput(data) {
78
+ if (matchesKey(data, "escape") || matchesKey(data, "q")) {
79
+ this.closed = true;
80
+ this.done(undefined);
81
+ return;
82
+ }
83
+ const totalLines = this.buildContentLines(this.lastInnerW).length;
84
+ const viewportHeight = this.viewportHeight();
85
+ const maxScroll = Math.max(0, totalLines - viewportHeight);
86
+ if (matchesKey(data, "up") || matchesKey(data, "k")) {
87
+ this.scrollOffset = Math.max(0, this.scrollOffset - 1);
88
+ this.autoScroll = this.scrollOffset >= maxScroll;
89
+ }
90
+ else if (matchesKey(data, "down") || matchesKey(data, "j")) {
91
+ this.scrollOffset = Math.min(maxScroll, this.scrollOffset + 1);
92
+ this.autoScroll = this.scrollOffset >= maxScroll;
93
+ }
94
+ else if (matchesKey(data, "pageUp")) {
95
+ this.scrollOffset = Math.max(0, this.scrollOffset - viewportHeight);
96
+ this.autoScroll = false;
97
+ }
98
+ else if (matchesKey(data, "pageDown")) {
99
+ this.scrollOffset = Math.min(maxScroll, this.scrollOffset + viewportHeight);
100
+ this.autoScroll = this.scrollOffset >= maxScroll;
101
+ }
102
+ else if (matchesKey(data, "home")) {
103
+ this.scrollOffset = 0;
104
+ this.autoScroll = false;
105
+ }
106
+ else if (matchesKey(data, "end")) {
107
+ this.scrollOffset = maxScroll;
108
+ this.autoScroll = true;
109
+ }
110
+ }
111
+ render(width) {
112
+ if (width < 6)
113
+ return [];
114
+ const th = this.theme;
115
+ const innerW = width - 4; // border + padding
116
+ this.lastInnerW = innerW;
117
+ const lines = [];
118
+ const pad = (s, len) => {
119
+ const vis = visibleWidth(s);
120
+ return s + " ".repeat(Math.max(0, len - vis));
121
+ };
122
+ const row = (content) => th.fg("border", "│") + " " + truncateToWidth(pad(content, innerW), innerW) + " " + th.fg("border", "│");
123
+ const hrTop = th.fg("border", `╭${"─".repeat(width - 2)}╮`);
124
+ const hrBot = th.fg("border", `╰${"─".repeat(width - 2)}╯`);
125
+ const hrMid = row(th.fg("dim", "─".repeat(innerW)));
126
+ // Header
127
+ lines.push(hrTop);
128
+ const name = this.record.type;
129
+ const statusIcon = this.record.status === "running"
130
+ ? th.fg("accent", "●")
131
+ : this.record.status === "completed"
132
+ ? th.fg("success", "✓")
133
+ : this.record.status === "error"
134
+ ? th.fg("error", "✗")
135
+ : th.fg("dim", "○");
136
+ const duration = this.record.completedAt
137
+ ? formatMs(this.record.completedAt - this.record.startedAt)
138
+ : `${formatMs(Date.now() - this.record.startedAt)} (running)`;
139
+ const headerParts = [duration];
140
+ const toolUses = this.activity?.toolUses ?? this.record.toolUses;
141
+ if (toolUses > 0)
142
+ headerParts.unshift(`${toolUses} tool${toolUses === 1 ? "" : "s"}`);
143
+ if (this.activity?.session) {
144
+ try {
145
+ const tokens = this.activity.session.getSessionStats().tokens.total;
146
+ if (tokens > 0)
147
+ headerParts.push(formatTokens(tokens));
148
+ }
149
+ catch {
150
+ /* */
151
+ }
152
+ }
153
+ lines.push(row(`${statusIcon} ${th.bold(name)} ${th.fg("muted", this.record.description)} ${th.fg("dim", "·")} ${th.fg("dim", headerParts.join(" · "))}`));
154
+ lines.push(hrMid);
155
+ // Content area
156
+ const contentLines = this.buildContentLines(innerW);
157
+ const viewportHeight = this.viewportHeight();
158
+ const maxScroll = Math.max(0, contentLines.length - viewportHeight);
159
+ if (this.autoScroll) {
160
+ this.scrollOffset = maxScroll;
161
+ }
162
+ const visibleStart = Math.min(this.scrollOffset, maxScroll);
163
+ const visible = contentLines.slice(visibleStart, visibleStart + viewportHeight);
164
+ for (let i = 0; i < viewportHeight; i++) {
165
+ lines.push(row(visible[i] ?? ""));
166
+ }
167
+ // Footer
168
+ lines.push(hrMid);
169
+ const scrollPct = contentLines.length <= viewportHeight
170
+ ? "100%"
171
+ : `${Math.round(((visibleStart + viewportHeight) / contentLines.length) * 100)}%`;
172
+ const footerLeft = th.fg("dim", `${contentLines.length} lines · ${scrollPct}`);
173
+ const footerRight = th.fg("dim", "↑↓ scroll · PgUp/PgDn · Esc close");
174
+ const footerGap = Math.max(1, innerW - visibleWidth(footerLeft) - visibleWidth(footerRight));
175
+ lines.push(row(footerLeft + " ".repeat(footerGap) + footerRight));
176
+ lines.push(hrBot);
177
+ return lines;
178
+ }
179
+ invalidate() {
180
+ /* no cached state to clear */
181
+ }
182
+ dispose() {
183
+ this.closed = true;
184
+ if (this.unsubscribe) {
185
+ this.unsubscribe();
186
+ this.unsubscribe = undefined;
187
+ }
188
+ }
189
+ // ---- Private ----
190
+ viewportHeight() {
191
+ return Math.max(MIN_VIEWPORT, this.tui.terminal.rows - CHROME_LINES);
192
+ }
193
+ buildContentLines(width) {
194
+ if (width <= 0)
195
+ return [];
196
+ const th = this.theme;
197
+ const messages = this.session.messages;
198
+ const lines = [];
199
+ if (!messages || messages.length === 0) {
200
+ lines.push(th.fg("dim", "(waiting for first message...)"));
201
+ return lines;
202
+ }
203
+ let needsSeparator = false;
204
+ for (const msg of messages) {
205
+ if (msg.role === "user") {
206
+ const text = typeof msg.content === "string" ? msg.content : extractText(msg.content);
207
+ if (!text.trim())
208
+ continue;
209
+ if (needsSeparator)
210
+ lines.push(th.fg("dim", "───"));
211
+ lines.push(th.fg("accent", "[User]"));
212
+ for (const line of wrapTextWithAnsi(text.trim(), width)) {
213
+ lines.push(line);
214
+ }
215
+ }
216
+ else if (msg.role === "assistant") {
217
+ const textParts = [];
218
+ const toolCalls = [];
219
+ for (const c of msg.content) {
220
+ if (c.type === "text" && c.text)
221
+ textParts.push(c.text);
222
+ else if (c.type === "tool_use" || c.type === "toolCall") {
223
+ toolCalls.push(c.name ?? c.toolName ?? "unknown");
224
+ }
225
+ }
226
+ if (needsSeparator)
227
+ lines.push(th.fg("dim", "───"));
228
+ lines.push(th.bold("[Assistant]"));
229
+ if (textParts.length > 0) {
230
+ for (const line of wrapTextWithAnsi(textParts.join("\n").trim(), width)) {
231
+ lines.push(line);
232
+ }
233
+ }
234
+ for (const name of toolCalls) {
235
+ lines.push(truncateToWidth(th.fg("muted", ` [Tool: ${name}]`), width));
236
+ }
237
+ }
238
+ else if (msg.role === "toolResult") {
239
+ const text = extractText(msg.content);
240
+ const truncated = text.length > 500 ? text.slice(0, 500) + "... (truncated)" : text;
241
+ if (!truncated.trim())
242
+ continue;
243
+ if (needsSeparator)
244
+ lines.push(th.fg("dim", "───"));
245
+ lines.push(th.fg("dim", "[Result]"));
246
+ for (const line of wrapTextWithAnsi(truncated.trim(), width)) {
247
+ lines.push(th.fg("dim", line));
248
+ }
249
+ }
250
+ else if (msg.role === "bashExecution") {
251
+ const bash = msg;
252
+ if (needsSeparator)
253
+ lines.push(th.fg("dim", "───"));
254
+ lines.push(truncateToWidth(th.fg("muted", ` $ ${bash.command}`), width));
255
+ if (bash.output?.trim()) {
256
+ const out = bash.output.length > 500 ? bash.output.slice(0, 500) + "... (truncated)" : bash.output;
257
+ for (const line of wrapTextWithAnsi(out.trim(), width)) {
258
+ lines.push(th.fg("dim", line));
259
+ }
260
+ }
261
+ }
262
+ else {
263
+ continue;
264
+ }
265
+ needsSeparator = true;
266
+ }
267
+ // Streaming indicator for running agents
268
+ if (this.record.status === "running" && this.activity) {
269
+ const act = describeActivity(this.activity.activeTools, this.activity.responseText);
270
+ lines.push("");
271
+ lines.push(truncateToWidth(th.fg("accent", "▍ ") + th.fg("dim", act), width));
272
+ }
273
+ return lines.map((l) => truncateToWidth(l, width));
274
+ }
275
+ }
276
+ //# sourceMappingURL=conversation-viewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conversation-viewer.js","sourceRoot":"","sources":["../src/conversation-viewer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
2
+ export declare const MODULES: {
3
+ readonly SUBAGENTS: "subagents";
4
+ };
5
+ export declare const UNIPI_EVENTS: {
6
+ readonly MODULE_READY: "unipi:module:ready";
7
+ readonly BADGE_GENERATE_REQUEST: "unipi:badge:generate:request";
8
+ };
9
+ export interface UnipiBadgeGenerateRequestEvent {
10
+ conversationSummary?: string;
11
+ }
12
+ export declare function emitEvent(pi: Pick<ExtensionAPI, "events">, eventName: string, payload: unknown): boolean;
13
+ export declare function withHerdrBlocked<T>(pi: Pick<ExtensionAPI, "events">, label: string, fn: () => Promise<T>): Promise<T>;
14
+ //# sourceMappingURL=core-compat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-compat.d.ts","sourceRoot":"","sources":["../src/core-compat.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAEpE,eAAO,MAAM,OAAO;;CAAsC,CAAC;AAE3D,eAAO,MAAM,YAAY;;;CAGf,CAAC;AAEX,MAAM,WAAW,8BAA8B;IAC7C,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,wBAAgB,SAAS,CACvB,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,GACf,OAAO,CAOT;AAED,wBAAsB,gBAAgB,CAAC,CAAC,EACtC,EAAE,EAAE,IAAI,CAAC,YAAY,EAAE,QAAQ,CAAC,EAChC,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAOZ"}
@@ -0,0 +1,24 @@
1
+ export const MODULES = { SUBAGENTS: "subagents" };
2
+ export const UNIPI_EVENTS = {
3
+ MODULE_READY: "unipi:module:ready",
4
+ BADGE_GENERATE_REQUEST: "unipi:badge:generate:request",
5
+ };
6
+ export function emitEvent(pi, eventName, payload) {
7
+ try {
8
+ pi.events.emit(eventName, payload);
9
+ return true;
10
+ }
11
+ catch {
12
+ return false;
13
+ }
14
+ }
15
+ export async function withHerdrBlocked(pi, label, fn) {
16
+ emitEvent(pi, "herdr:blocked", { active: true, label });
17
+ try {
18
+ return await fn();
19
+ }
20
+ finally {
21
+ emitEvent(pi, "herdr:blocked", { active: false, label });
22
+ }
23
+ }
24
+ //# sourceMappingURL=core-compat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-compat.js","sourceRoot":"","sources":["../src/core-compat.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,OAAO,GAAG,EAAE,SAAS,EAAE,WAAW,EAAW,CAAC;AAE3D,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,YAAY,EAAE,oBAAoB;IAClC,sBAAsB,EAAE,8BAA8B;CAC9C,CAAC;AAMX,MAAM,UAAU,SAAS,CACvB,EAAgC,EAChC,SAAiB,EACjB,OAAgB;IAEhB,IAAI,CAAC;QACH,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACnC,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,EAAgC,EAChC,KAAa,EACb,EAAoB;IAEpB,SAAS,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,EAAE,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @pi-unipi/subagents — Custom agent loader
3
+ *
4
+ * Discovers agent types from:
5
+ * - <workspace>/.unipi/config/agents/*.md (project, highest priority)
6
+ * - ~/.unipi/config/agents/*.md (global)
7
+ */
8
+ import type { AgentConfig } from "./types.js";
9
+ /**
10
+ * Load all custom agents from project and global directories.
11
+ * Project agents override global agents with the same name.
12
+ */
13
+ export declare function loadCustomAgents(cwd: string): Map<string, AgentConfig>;
14
+ //# sourceMappingURL=custom-agents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-agents.d.ts","sourceRoot":"","sources":["../src/custom-agents.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAyE9C;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CA4BtE"}
@@ -0,0 +1,106 @@
1
+ /**
2
+ * @pi-unipi/subagents — Custom agent loader
3
+ *
4
+ * Discovers agent types from:
5
+ * - <workspace>/.unipi/config/agents/*.md (project, highest priority)
6
+ * - ~/.unipi/config/agents/*.md (global)
7
+ */
8
+ import { existsSync, readdirSync, readFileSync, renameSync } from "node:fs";
9
+ import { join } from "node:path";
10
+ import { homedir } from "node:os";
11
+ import { parseFrontmatter } from "@earendil-works/pi-coding-agent";
12
+ /** Backup a corrupted file by renaming to .bak */
13
+ function backupCorrupted(filePath) {
14
+ const backupPath = filePath + ".bak";
15
+ try {
16
+ renameSync(filePath, backupPath);
17
+ }
18
+ catch {
19
+ // If backup fails, just leave it
20
+ }
21
+ }
22
+ /** Get project agents directory. */
23
+ function getProjectAgentsDir(cwd) {
24
+ return join(cwd, ".unipi", "config", "agents");
25
+ }
26
+ /** Get global agents directory. */
27
+ function getGlobalAgentsDir() {
28
+ return join(homedir(), ".unipi", "config", "agents");
29
+ }
30
+ /** All known built-in tool names. */
31
+ const BUILTIN_TOOL_NAMES = ["read", "bash", "edit", "write", "grep", "find", "ls"];
32
+ /**
33
+ * Load a single agent from a .md file.
34
+ */
35
+ function loadAgentFromFile(filePath, source) {
36
+ try {
37
+ const content = readFileSync(filePath, "utf-8");
38
+ const { frontmatter, body } = parseFrontmatter(content);
39
+ if (!frontmatter || typeof frontmatter !== "object") {
40
+ return null;
41
+ }
42
+ const name = filePath.split("/").pop()?.replace(/\.md$/, "") ?? "unknown";
43
+ // Parse tools from comma-separated string
44
+ const toolsStr = frontmatter.tools;
45
+ const builtinToolNames = toolsStr
46
+ ? toolsStr.split(",").map((t) => t.trim()).filter((t) => BUILTIN_TOOL_NAMES.includes(t))
47
+ : [...BUILTIN_TOOL_NAMES];
48
+ return {
49
+ name,
50
+ displayName: frontmatter.display_name,
51
+ description: frontmatter.description ?? `${name} agent`,
52
+ builtinToolNames,
53
+ disallowedTools: frontmatter.disallowed_tools
54
+ ?.split(",")
55
+ .map((t) => t.trim()),
56
+ extensions: frontmatter.extensions !== false,
57
+ skills: frontmatter.skills !== false,
58
+ model: frontmatter.model,
59
+ thinking: frontmatter.thinking,
60
+ maxTurns: frontmatter.max_turns,
61
+ systemPrompt: body.trim(),
62
+ promptMode: frontmatter.prompt_mode ?? "replace",
63
+ inheritContext: frontmatter.inherit_context,
64
+ runInBackground: frontmatter.run_in_background,
65
+ isolated: frontmatter.isolated,
66
+ enabled: frontmatter.enabled !== false,
67
+ source,
68
+ };
69
+ }
70
+ catch {
71
+ // Corrupted file — backup and skip
72
+ backupCorrupted(filePath);
73
+ return null;
74
+ }
75
+ }
76
+ /**
77
+ * Load all custom agents from project and global directories.
78
+ * Project agents override global agents with the same name.
79
+ */
80
+ export function loadCustomAgents(cwd) {
81
+ const agents = new Map();
82
+ // Load global agents first
83
+ const globalDir = getGlobalAgentsDir();
84
+ if (existsSync(globalDir)) {
85
+ const files = readdirSync(globalDir).filter((f) => f.endsWith(".md"));
86
+ for (const file of files) {
87
+ const agent = loadAgentFromFile(join(globalDir, file), "global");
88
+ if (agent) {
89
+ agents.set(agent.name, agent);
90
+ }
91
+ }
92
+ }
93
+ // Load project agents (overrides global)
94
+ const projectDir = getProjectAgentsDir(cwd);
95
+ if (existsSync(projectDir)) {
96
+ const files = readdirSync(projectDir).filter((f) => f.endsWith(".md"));
97
+ for (const file of files) {
98
+ const agent = loadAgentFromFile(join(projectDir, file), "project");
99
+ if (agent) {
100
+ agents.set(agent.name, agent);
101
+ }
102
+ }
103
+ }
104
+ return agents;
105
+ }
106
+ //# sourceMappingURL=custom-agents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-agents.js","sourceRoot":"","sources":["../src/custom-agents.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @pi-unipi/subagents — Per-file transparent locking
3
+ *
4
+ * Agents never see lock errors. Write tool queues internally.
5
+ * Per-file granularity: locking src/auth.ts doesn't block src/login.ts.
6
+ */
7
+ export declare class FileLock {
8
+ /** Active locks by file path. */
9
+ private locks;
10
+ /** Queue of waiting acquires per file path. */
11
+ private queues;
12
+ /**
13
+ * Acquire a lock on a file. Blocks until available.
14
+ * Returns a release function.
15
+ *
16
+ * @param filePath - Absolute path to the file
17
+ * @param agentId - ID of the agent requesting the lock
18
+ * @returns Release function — call when done writing
19
+ */
20
+ acquire(filePath: string, agentId: string): Promise<() => void>;
21
+ /**
22
+ * Check if a file is currently locked.
23
+ */
24
+ isLocked(filePath: string): boolean;
25
+ /**
26
+ * Get the agent that holds a lock on a file.
27
+ */
28
+ getHolder(filePath: string): string | undefined;
29
+ /**
30
+ * Get count of locked files.
31
+ */
32
+ get lockCount(): number;
33
+ /**
34
+ * Release all locks held by an agent (on abort).
35
+ */
36
+ releaseAll(agentId: string): void;
37
+ /**
38
+ * Clear all locks (on shutdown).
39
+ */
40
+ clear(): void;
41
+ }
42
+ //# sourceMappingURL=file-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-lock.d.ts","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,qBAAa,QAAQ;IACnB,iCAAiC;IACjC,OAAO,CAAC,KAAK,CAAoC;IACjD,+CAA+C;IAC/C,OAAO,CAAC,MAAM,CAAwC;IAEtD;;;;;;;OAOG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC;IAoCrE;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAInC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI/C;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;IAED;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQjC;;OAEG;IACH,KAAK,IAAI,IAAI;CAOd"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * @pi-unipi/subagents — Per-file transparent locking
3
+ *
4
+ * Agents never see lock errors. Write tool queues internally.
5
+ * Per-file granularity: locking src/auth.ts doesn't block src/login.ts.
6
+ */
7
+ export class FileLock {
8
+ /** Active locks by file path. */
9
+ locks = new Map();
10
+ /** Queue of waiting acquires per file path. */
11
+ queues = new Map();
12
+ /**
13
+ * Acquire a lock on a file. Blocks until available.
14
+ * Returns a release function.
15
+ *
16
+ * @param filePath - Absolute path to the file
17
+ * @param agentId - ID of the agent requesting the lock
18
+ * @returns Release function — call when done writing
19
+ */
20
+ async acquire(filePath, agentId) {
21
+ // Wait for existing lock
22
+ while (this.locks.has(filePath)) {
23
+ await new Promise((resolve) => {
24
+ const queue = this.queues.get(filePath) ?? [];
25
+ queue.push(resolve);
26
+ this.queues.set(filePath, queue);
27
+ });
28
+ }
29
+ // Create lock entry
30
+ let releaseFn;
31
+ const promise = new Promise((resolve) => {
32
+ releaseFn = () => {
33
+ this.locks.delete(filePath);
34
+ resolve();
35
+ // Wake next waiter
36
+ const queue = this.queues.get(filePath);
37
+ if (queue && queue.length > 0) {
38
+ const next = queue.shift();
39
+ next();
40
+ }
41
+ };
42
+ });
43
+ const entry = {
44
+ agentId,
45
+ filePath,
46
+ promise,
47
+ release: releaseFn,
48
+ };
49
+ this.locks.set(filePath, entry);
50
+ return releaseFn;
51
+ }
52
+ /**
53
+ * Check if a file is currently locked.
54
+ */
55
+ isLocked(filePath) {
56
+ return this.locks.has(filePath);
57
+ }
58
+ /**
59
+ * Get the agent that holds a lock on a file.
60
+ */
61
+ getHolder(filePath) {
62
+ return this.locks.get(filePath)?.agentId;
63
+ }
64
+ /**
65
+ * Get count of locked files.
66
+ */
67
+ get lockCount() {
68
+ return this.locks.size;
69
+ }
70
+ /**
71
+ * Release all locks held by an agent (on abort).
72
+ */
73
+ releaseAll(agentId) {
74
+ for (const [filePath, entry] of this.locks) {
75
+ if (entry.agentId === agentId) {
76
+ entry.release();
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Clear all locks (on shutdown).
82
+ */
83
+ clear() {
84
+ for (const entry of this.locks.values()) {
85
+ entry.release();
86
+ }
87
+ this.locks.clear();
88
+ this.queues.clear();
89
+ }
90
+ }
91
+ //# sourceMappingURL=file-lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../src/file-lock.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,OAAO,QAAQ;IACnB,iCAAiC;IACzB,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IACjD,+CAA+C;IACvC,MAAM,GAAG,IAAI,GAAG,EAA6B,CAAC;IAEtD;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAC,QAAgB,EAAE,OAAe;QAC7C,yBAAyB;QACzB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;gBAClC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC9C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;YACnC,CAAC,CAAC,CAAC;QACL,CAAC;QAED,oBAAoB;QACpB,IAAI,SAAqB,CAAC;QAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5C,SAAS,GAAG,GAAG,EAAE;gBACf,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC5B,OAAO,EAAE,CAAC;gBACV,mBAAmB;gBACnB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBACxC,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;oBAC5B,IAAI,EAAE,CAAC;gBACT,CAAC;YACH,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAkB;YAC3B,OAAO;YACP,QAAQ;YACR,OAAO;YACP,OAAO,EAAE,SAAU;SACpB,CAAC;QAEF,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChC,OAAO,SAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACH,QAAQ,CAAC,QAAgB;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,SAAS,CAAC,QAAgB;QACxB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC3C,CAAC;IAED;;OAEG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,OAAe;QACxB,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC3C,IAAI,KAAK,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;gBAC9B,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK;QACH,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,KAAK,CAAC,OAAO,EAAE,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @pi-unipi/subagents — Extension entry
3
+ *
4
+ * Tools: spawn_helper, get_helper_result
5
+ * Features: renderCall/renderResult, message renderer, conversation viewer
6
+ * ESC propagation: all children abort on parent ESC
7
+ */
8
+ import { type ExtensionAPI } from "@earendil-works/pi-coding-agent";
9
+ export default function (pi: ExtensionAPI): void;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAqHhF,MAAM,CAAC,OAAO,WAAW,EAAE,EAAE,YAAY,QAmuBxC"}