@tintinweb/pi-subagents 0.4.9 → 0.4.11

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 (44) hide show
  1. package/.github/workflows/ci.yml +21 -0
  2. package/CHANGELOG.md +18 -0
  3. package/README.md +11 -11
  4. package/biome.json +26 -0
  5. package/dist/agent-manager.d.ts +18 -4
  6. package/dist/agent-manager.js +111 -9
  7. package/dist/agent-runner.d.ts +10 -6
  8. package/dist/agent-runner.js +80 -26
  9. package/dist/agent-types.d.ts +10 -0
  10. package/dist/agent-types.js +23 -1
  11. package/dist/cross-extension-rpc.d.ts +30 -0
  12. package/dist/cross-extension-rpc.js +33 -0
  13. package/dist/custom-agents.js +36 -8
  14. package/dist/index.js +335 -66
  15. package/dist/memory.d.ts +49 -0
  16. package/dist/memory.js +151 -0
  17. package/dist/output-file.d.ts +17 -0
  18. package/dist/output-file.js +66 -0
  19. package/dist/prompts.d.ts +12 -1
  20. package/dist/prompts.js +15 -3
  21. package/dist/skill-loader.d.ts +19 -0
  22. package/dist/skill-loader.js +67 -0
  23. package/dist/types.d.ts +45 -1
  24. package/dist/ui/agent-widget.d.ts +21 -0
  25. package/dist/ui/agent-widget.js +205 -127
  26. package/dist/ui/conversation-viewer.d.ts +2 -2
  27. package/dist/ui/conversation-viewer.js +2 -2
  28. package/dist/ui/conversation-viewer.test.d.ts +1 -0
  29. package/dist/ui/conversation-viewer.test.js +254 -0
  30. package/dist/worktree.d.ts +36 -0
  31. package/dist/worktree.js +139 -0
  32. package/package.json +7 -2
  33. package/src/agent-manager.ts +7 -5
  34. package/src/agent-runner.ts +24 -19
  35. package/src/agent-types.ts +5 -5
  36. package/src/custom-agents.ts +4 -4
  37. package/src/index.ts +54 -33
  38. package/src/memory.ts +2 -2
  39. package/src/output-file.ts +1 -1
  40. package/src/skill-loader.ts +1 -1
  41. package/src/types.ts +3 -1
  42. package/src/ui/agent-widget.ts +18 -2
  43. package/src/ui/conversation-viewer.ts +4 -4
  44. package/src/worktree.ts +2 -2
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Cross-extension RPC handlers for the subagents extension.
3
+ *
4
+ * Exposes ping and spawn RPCs over the pi.events event bus,
5
+ * using per-request scoped reply channels.
6
+ */
7
+ /** Minimal event bus interface needed by the RPC handlers. */
8
+ export interface EventBus {
9
+ on(event: string, handler: (data: unknown) => void): () => void;
10
+ emit(event: string, data: unknown): void;
11
+ }
12
+ /** Minimal AgentManager interface needed by the spawn RPC. */
13
+ export interface SpawnCapable {
14
+ spawn(pi: unknown, ctx: unknown, type: string, prompt: string, options: any): string;
15
+ }
16
+ export interface RpcDeps {
17
+ events: EventBus;
18
+ pi: unknown;
19
+ getCtx: () => unknown | undefined;
20
+ manager: SpawnCapable;
21
+ }
22
+ export interface RpcHandle {
23
+ unsubPing: () => void;
24
+ unsubSpawn: () => void;
25
+ }
26
+ /**
27
+ * Register ping and spawn RPC handlers on the event bus.
28
+ * Returns unsub functions for cleanup.
29
+ */
30
+ export declare function registerRpcHandlers(deps: RpcDeps): RpcHandle;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Cross-extension RPC handlers for the subagents extension.
3
+ *
4
+ * Exposes ping and spawn RPCs over the pi.events event bus,
5
+ * using per-request scoped reply channels.
6
+ */
7
+ /**
8
+ * Register ping and spawn RPC handlers on the event bus.
9
+ * Returns unsub functions for cleanup.
10
+ */
11
+ export function registerRpcHandlers(deps) {
12
+ const { events, pi, getCtx, manager } = deps;
13
+ const unsubPing = events.on("subagents:rpc:ping", (raw) => {
14
+ const { requestId } = raw;
15
+ events.emit(`subagents:rpc:ping:reply:${requestId}`, {});
16
+ });
17
+ const unsubSpawn = events.on("subagents:rpc:spawn", async (raw) => {
18
+ const { requestId, type, prompt, options } = raw;
19
+ const ctx = getCtx();
20
+ if (!ctx) {
21
+ events.emit(`subagents:rpc:spawn:reply:${requestId}`, { error: "No active session" });
22
+ return;
23
+ }
24
+ try {
25
+ const id = manager.spawn(pi, ctx, type, prompt, options ?? {});
26
+ events.emit(`subagents:rpc:spawn:reply:${requestId}`, { id });
27
+ }
28
+ catch (err) {
29
+ events.emit(`subagents:rpc:spawn:reply:${requestId}`, { error: err.message });
30
+ }
31
+ });
32
+ return { unsubPing, unsubSpawn };
33
+ }
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * custom-agents.ts — Load user-defined agents from project (.pi/agents/) and global (~/.pi/agent/agents/) locations.
3
3
  */
4
- import { parseFrontmatter } from "@mariozechner/pi-coding-agent";
5
- import { readFileSync, readdirSync, existsSync } from "node:fs";
6
- import { join, basename } from "node:path";
4
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
7
5
  import { homedir } from "node:os";
6
+ import { basename, join } from "node:path";
7
+ import { parseFrontmatter } from "@mariozechner/pi-coding-agent";
8
8
  import { BUILTIN_TOOL_NAMES } from "./agent-types.js";
9
9
  /**
10
10
  * Scan for custom agent .md files from multiple locations.
@@ -49,6 +49,7 @@ function loadFromDir(dir, agents, source) {
49
49
  displayName: str(fm.display_name),
50
50
  description: str(fm.description) ?? name,
51
51
  builtinToolNames: csvList(fm.tools, BUILTIN_TOOL_NAMES),
52
+ disallowedTools: csvListOptional(fm.disallowed_tools),
52
53
  extensions: inheritField(fm.extensions ?? fm.inherit_extensions),
53
54
  skills: inheritField(fm.skills ?? fm.inherit_skills),
54
55
  model: str(fm.model),
@@ -59,6 +60,8 @@ function loadFromDir(dir, agents, source) {
59
60
  inheritContext: fm.inherit_context === true,
60
61
  runInBackground: fm.run_in_background === true,
61
62
  isolated: fm.isolated === true,
63
+ memory: parseMemory(fm.memory),
64
+ isolation: fm.isolation === "worktree" ? "worktree" : undefined,
62
65
  enabled: fm.enabled !== false, // default true; explicitly false disables
63
66
  source,
64
67
  });
@@ -75,16 +78,41 @@ function positiveInt(val) {
75
78
  return typeof val === "number" && val >= 1 ? val : undefined;
76
79
  }
77
80
  /**
78
- * Parse a comma-separated list field.
81
+ * Parse a raw CSV field value into items, or undefined if absent/empty/"none".
82
+ */
83
+ function parseCsvField(val) {
84
+ if (val === undefined || val === null)
85
+ return undefined;
86
+ const s = String(val).trim();
87
+ if (!s || s === "none")
88
+ return undefined;
89
+ const items = s.split(",").map(t => t.trim()).filter(Boolean);
90
+ return items.length > 0 ? items : undefined;
91
+ }
92
+ /**
93
+ * Parse a comma-separated list field with defaults.
79
94
  * omitted → defaults; "none"/empty → []; csv → listed items.
80
95
  */
81
96
  function csvList(val, defaults) {
82
97
  if (val === undefined || val === null)
83
98
  return defaults;
84
- const s = String(val).trim();
85
- if (!s || s === "none")
86
- return [];
87
- return s.split(",").map(t => t.trim()).filter(Boolean);
99
+ return parseCsvField(val) ?? [];
100
+ }
101
+ /**
102
+ * Parse an optional comma-separated list field.
103
+ * omitted → undefined; "none"/empty → undefined; csv → listed items.
104
+ */
105
+ function csvListOptional(val) {
106
+ return parseCsvField(val);
107
+ }
108
+ /**
109
+ * Parse a memory scope field.
110
+ * omitted → undefined; "user"/"project"/"local" → MemoryScope.
111
+ */
112
+ function parseMemory(val) {
113
+ if (val === "user" || val === "project" || val === "local")
114
+ return val;
115
+ return undefined;
88
116
  }
89
117
  /**
90
118
  * Parse an inherit field (extensions, skills).