pi-subagents-lite 1.3.0 → 1.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.
- package/README.md +184 -235
- package/package.json +1 -1
- package/src/{agent-discovery.ts → agents/agent-discovery.ts} +10 -7
- package/src/{agent-manager.ts → agents/agent-manager.ts} +34 -74
- package/src/{agent-runner.ts → agents/agent-runner.ts} +130 -181
- package/src/{agent-status.ts → agents/agent-status.ts} +4 -4
- package/src/agents/agent-types.ts +339 -0
- package/src/{default-agents.ts → agents/default-agents.ts} +2 -5
- package/src/{output-file.ts → agents/output-file.ts} +68 -1
- package/src/{tool-execution.ts → agents/tool-execution.ts} +60 -222
- package/src/agents/types.ts +54 -0
- package/src/{usage.ts → agents/usage.ts} +7 -0
- package/src/{config-io.ts → config/config-io.ts} +20 -3
- package/src/config/config-store.ts +472 -0
- package/src/config/types.ts +26 -0
- package/src/events.ts +185 -0
- package/src/index.ts +8 -281
- package/src/{model-precedence.ts → models/model-precedence.ts} +33 -0
- package/src/{model-selector.ts → models/model-selector.ts} +1 -1
- package/src/{context.ts → prompt/context.ts} +1 -1
- package/src/prompt/prompts.ts +180 -0
- package/src/prompt/skill-loader.ts +195 -0
- package/src/registration.ts +101 -0
- package/src/shell.ts +101 -0
- package/src/spawn/spawn-coordinator.ts +232 -0
- package/src/status-note.ts +10 -0
- package/src/types.ts +47 -71
- package/src/ui/agent-widget.ts +61 -49
- package/src/{format.ts → ui/format.ts} +64 -26
- package/src/ui/menu/helpers.ts +93 -0
- package/src/ui/menu/menu-concurrency.ts +192 -0
- package/src/ui/menu/menu-debug.ts +125 -0
- package/src/ui/menu/menu-model-settings.ts +208 -0
- package/src/ui/menu/menu-running-agents.ts +224 -0
- package/src/ui/menu/menu-spawn-options.ts +87 -0
- package/src/ui/menu/menu-spawn-wizard.ts +418 -0
- package/src/ui/menu/menu-system-prompt.ts +109 -0
- package/src/ui/menu/menu-widget-settings.ts +130 -0
- package/src/ui/menu/menus.ts +101 -0
- package/src/ui/menu/submenus/confirm.ts +47 -0
- package/src/ui/menu/submenus/model-select.ts +70 -0
- package/src/ui/menu/submenus/numeric-input.ts +98 -0
- package/src/ui/menu/wrappers/settings-list.ts +205 -0
- package/src/{renderer.ts → ui/renderer.ts} +7 -6
- package/src/{result-viewer.ts → ui/result-viewer.ts} +7 -2
- package/src/ui/types.ts +11 -0
- package/src/agent-types.ts +0 -184
- package/src/config-mutator.ts +0 -183
- package/src/menus.ts +0 -1333
- package/src/prompts.ts +0 -94
- package/src/skill-loader.ts +0 -178
- package/src/state.ts +0 -83
- /package/src/{worktree-validator.ts → spawn/worktree-validator.ts} +0 -0
package/src/agent-types.ts
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* agent-types.ts — Unified agent type registry.
|
|
3
|
-
*
|
|
4
|
-
* Merges embedded default agents with user-defined agents from .pi/agents/*.md.
|
|
5
|
-
* User agents override defaults with the same name. Disabled agents are kept but excluded from spawning.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { scanAgentFilesInDir, mergeAgents } from "./agent-discovery.js";
|
|
9
|
-
import { DEFAULT_AGENTS } from "./default-agents.js";
|
|
10
|
-
import type { AgentConfig } from "./types.js";
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* All tool names that Pi can provide to a session.
|
|
14
|
-
*
|
|
15
|
-
* Note: only `read`, `bash`, `edit`, `write` are active by default.
|
|
16
|
-
* `grep` must be explicitly activated via setActiveToolsByName().
|
|
17
|
-
* `find` and `ls` were removed — they're thin wrappers over bash commands
|
|
18
|
-
* that add ~180 tokens/turn with no real benefit.
|
|
19
|
-
*/
|
|
20
|
-
export const BUILTIN_TOOL_NAMES: string[] = ["read", "bash", "edit", "write", "grep", "find"];
|
|
21
|
-
|
|
22
|
-
/** Unified runtime registry of all agents (defaults + user-defined). */
|
|
23
|
-
const agents = new Map<string, AgentConfig>();
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Directories to scan for agent .md files at startup and on-demand.
|
|
27
|
-
* Set by setAgentScanDirs() during session_start.
|
|
28
|
-
*/
|
|
29
|
-
let userAgentDir = "";
|
|
30
|
-
let projectAgentDir = "";
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Register agents into the unified registry.
|
|
34
|
-
* Starts with DEFAULT_AGENTS, then overlays user agents (overrides defaults with same name).
|
|
35
|
-
* Hidden agents (hidden === true) are kept in the registry but excluded from spawning.
|
|
36
|
-
*/
|
|
37
|
-
export function registerAgents(userAgents: Map<string, AgentConfig>): void {
|
|
38
|
-
agents.clear();
|
|
39
|
-
|
|
40
|
-
// Start with defaults
|
|
41
|
-
for (const [name, config] of DEFAULT_AGENTS) {
|
|
42
|
-
agents.set(name, config);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Overlay user agents (overrides defaults with same name)
|
|
46
|
-
for (const [name, config] of userAgents) {
|
|
47
|
-
agents.set(name, config);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Set the agent scan directories for on-demand discovery.
|
|
53
|
-
* Called during session_start alongside scanAndRegisterAgents.
|
|
54
|
-
*/
|
|
55
|
-
export function setAgentScanDirs(userDir: string, projectDir: string): void {
|
|
56
|
-
userAgentDir = userDir;
|
|
57
|
-
projectAgentDir = projectDir;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Scan the known agent directories and register any newly discovered agents
|
|
62
|
-
* that aren't already in the registry. Returns the number of new agents added.
|
|
63
|
-
*
|
|
64
|
-
* @param worktreeDir - Optional absolute path to a worktree's `.pi/agents/` directory.
|
|
65
|
-
* When set, agents from this directory are also scanned and added to the registry.
|
|
66
|
-
* Worktree-local types use "project" source attribution and follow the same
|
|
67
|
-
* parsing and name-uniqueness rules as the parent's project scan.
|
|
68
|
-
*/
|
|
69
|
-
export async function discoverNewAgents(worktreeDir?: string): Promise<number> {
|
|
70
|
-
const [userAgents, projectAgents] = await Promise.all([
|
|
71
|
-
scanAgentFilesInDir(userAgentDir, "user"),
|
|
72
|
-
scanAgentFilesInDir(projectAgentDir, "project"),
|
|
73
|
-
]);
|
|
74
|
-
|
|
75
|
-
const merged = mergeAgents(DEFAULT_AGENTS, userAgents, projectAgents);
|
|
76
|
-
|
|
77
|
-
let count = 0;
|
|
78
|
-
for (const [name, config] of merged) {
|
|
79
|
-
if (!agents.has(name)) {
|
|
80
|
-
agents.set(name, config);
|
|
81
|
-
count++;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Scan worktree-local agents (only when worktreeDir is provided)
|
|
86
|
-
if (worktreeDir) {
|
|
87
|
-
const worktreeAgents = await scanAgentFilesInDir(worktreeDir, "project");
|
|
88
|
-
// Use mergeAgents to convert AgentConfigFromMd to AgentConfig (applies fromMd
|
|
89
|
-
// and BASE_DEFAULTS), then add only names not already in the registry.
|
|
90
|
-
const wtMerged = mergeAgents(new Map(), [], worktreeAgents);
|
|
91
|
-
for (const [name, config] of wtMerged) {
|
|
92
|
-
if (!agents.has(name)) {
|
|
93
|
-
agents.set(name, config);
|
|
94
|
-
count++;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return count;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/** Resolve a type name case-insensitively. Also matches displayName. Returns the canonical key or undefined. */
|
|
103
|
-
export function resolveType(name: string): string | undefined {
|
|
104
|
-
if (!name) return undefined;
|
|
105
|
-
if (agents.has(name)) return name;
|
|
106
|
-
const lower = name.toLowerCase();
|
|
107
|
-
for (const [key, config] of agents.entries()) {
|
|
108
|
-
if (key.toLowerCase() === lower) return key;
|
|
109
|
-
if ((config.displayName ?? '').toLowerCase() === lower) return key;
|
|
110
|
-
}
|
|
111
|
-
return undefined;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/** Get the agent config for a type (case-insensitive). */
|
|
115
|
-
export function getAgentConfig(name: string): AgentConfig | undefined {
|
|
116
|
-
const key = resolveType(name);
|
|
117
|
-
return key ? agents.get(key) : undefined;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Get all visible type names (for spawning and tool descriptions). */
|
|
121
|
-
export function getAvailableTypes(): string[] {
|
|
122
|
-
return [...agents.entries()]
|
|
123
|
-
.filter(([_, config]) => config.hidden !== true)
|
|
124
|
-
.map(([name]) => name);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** Get all type names including hidden (for UI listing). */
|
|
128
|
-
export function getAllTypes(): string[] {
|
|
129
|
-
return [...agents.keys()];
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** Get built-in tool names for a type (case-insensitive). */
|
|
133
|
-
export function getToolNamesForType(type: string): string[] {
|
|
134
|
-
const config = getAgentConfig(type);
|
|
135
|
-
return config?.registeredTools?.length
|
|
136
|
-
? config.registeredTools
|
|
137
|
-
: [...BUILTIN_TOOL_NAMES];
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/** Resolved config shape returned by getConfig. */
|
|
141
|
-
export interface ResolvedAgentConfig {
|
|
142
|
-
displayName: string;
|
|
143
|
-
description: string;
|
|
144
|
-
registeredTools: string[];
|
|
145
|
-
/** Controls tool schema visibility. true = all, string[] = listed, false = none. */
|
|
146
|
-
tools?: true | string[] | false;
|
|
147
|
-
extensions: true | string[] | false;
|
|
148
|
-
skills: true | string[] | false;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function toResolved(config: AgentConfig): ResolvedAgentConfig {
|
|
152
|
-
return {
|
|
153
|
-
displayName: config.displayName ?? config.name,
|
|
154
|
-
description: config.description,
|
|
155
|
-
registeredTools: config.registeredTools ?? BUILTIN_TOOL_NAMES,
|
|
156
|
-
tools: config.tools,
|
|
157
|
-
extensions: config.extensions,
|
|
158
|
-
skills: config.skills,
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/** Get config for a type (case-insensitive). Falls back to general-purpose. */
|
|
163
|
-
export function getConfig(type: string): ResolvedAgentConfig {
|
|
164
|
-
const resolvedKey = resolveType(type);
|
|
165
|
-
const config = resolvedKey ? agents.get(resolvedKey) : undefined;
|
|
166
|
-
|
|
167
|
-
// If config exists and is not hidden, use it; otherwise fall back to general-purpose
|
|
168
|
-
const activeConfig = config?.hidden !== true
|
|
169
|
-
? config
|
|
170
|
-
: agents.get("general-purpose");
|
|
171
|
-
|
|
172
|
-
if (activeConfig && activeConfig.hidden !== true) {
|
|
173
|
-
return toResolved(activeConfig);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Absolute fallback — general-purpose was hidden or missing
|
|
177
|
-
return {
|
|
178
|
-
displayName: "Agent",
|
|
179
|
-
description: "General-purpose agent for complex, multi-step tasks",
|
|
180
|
-
registeredTools: BUILTIN_TOOL_NAMES,
|
|
181
|
-
extensions: true,
|
|
182
|
-
skills: true,
|
|
183
|
-
};
|
|
184
|
-
}
|
package/src/config-mutator.ts
DELETED
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* config-mutator.ts — Typed setters for all __config mutations.
|
|
3
|
-
*
|
|
4
|
-
* Every setter saves (saveConfigAtomic) and syncs internally.
|
|
5
|
-
* menus.ts calls setters instead of directly mutating __config.
|
|
6
|
-
*
|
|
7
|
-
* Sync responsibilities:
|
|
8
|
-
* - Widget settings (compact, maxLines, shortcut) → syncWidgetSettings
|
|
9
|
-
* - Cost display → setShowCostEnabled (syncs to widget)
|
|
10
|
-
* - Agent bulk replace → syncWidgetSettings
|
|
11
|
-
* - Concurrency → getManager().setConcurrency()
|
|
12
|
-
* - All others → saveConfigAtomic only
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
__config,
|
|
17
|
-
getManager,
|
|
18
|
-
setShowCostEnabled,
|
|
19
|
-
syncWidgetSettings,
|
|
20
|
-
} from "./state.js";
|
|
21
|
-
import { saveConfigAtomic, DEFAULT_CONFIG } from "./config-io.js";
|
|
22
|
-
import { CONFIG_AGENT_NON_MODEL_KEYS } from "./types.js";
|
|
23
|
-
|
|
24
|
-
// ============================================================================
|
|
25
|
-
// Local helpers
|
|
26
|
-
// ============================================================================
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Persist concurrency config to disk and apply to the running manager.
|
|
30
|
-
* Defined locally so concurrency setters don't double-save.
|
|
31
|
-
*/
|
|
32
|
-
function applyConcurrencyConfig(): void {
|
|
33
|
-
saveConfigAtomic(__config);
|
|
34
|
-
getManager()?.setConcurrency(__config.concurrency);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// ============================================================================
|
|
38
|
-
// Model override setters
|
|
39
|
-
// ============================================================================
|
|
40
|
-
|
|
41
|
-
/** Set or update a model override for a type (or "default" for global). */
|
|
42
|
-
export function setModelOverride(type: string, value: string | null): void {
|
|
43
|
-
__config.agent[type] = value;
|
|
44
|
-
saveConfigAtomic(__config);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/** Set the global default model. */
|
|
48
|
-
export function setDefaultModel(value: string | null): void {
|
|
49
|
-
__config.agent.default = value;
|
|
50
|
-
saveConfigAtomic(__config);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** Clear a single per-type model override. */
|
|
54
|
-
export function clearModelOverride(type: string): void {
|
|
55
|
-
delete __config.agent[type];
|
|
56
|
-
saveConfigAtomic(__config);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** Clear all model overrides, preserving non-model settings. */
|
|
60
|
-
export function clearAllModelOverrides(): void {
|
|
61
|
-
const preserved: Record<string, unknown> = {};
|
|
62
|
-
for (const key of CONFIG_AGENT_NON_MODEL_KEYS) {
|
|
63
|
-
const val = __config.agent[key];
|
|
64
|
-
if (val != null || key === "default" || key === "forceBackground") {
|
|
65
|
-
preserved[key] = val;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
__config.agent = preserved as typeof __config.agent;
|
|
69
|
-
saveConfigAtomic(__config);
|
|
70
|
-
syncWidgetSettings();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// ============================================================================
|
|
74
|
-
// Simple agent settings
|
|
75
|
-
// ============================================================================
|
|
76
|
-
|
|
77
|
-
/** Toggle force-background mode. */
|
|
78
|
-
export function setForceBackground(enabled: boolean): void {
|
|
79
|
-
__config.agent.forceBackground = enabled;
|
|
80
|
-
saveConfigAtomic(__config);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/** Set the cost display toggle (syncs to widget via setShowCostEnabled). */
|
|
84
|
-
export function setShowCost(enabled: boolean): void {
|
|
85
|
-
setShowCostEnabled(enabled);
|
|
86
|
-
saveConfigAtomic(__config);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
/** Set grace turns (number of turns after timeout before hard kill). */
|
|
90
|
-
export function setGraceTurns(n: number): void {
|
|
91
|
-
__config.agent.graceTurns = n;
|
|
92
|
-
saveConfigAtomic(__config);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ============================================================================
|
|
96
|
-
// Widget settings (sync via syncWidgetSettings)
|
|
97
|
-
// ============================================================================
|
|
98
|
-
|
|
99
|
-
/** Toggle force-compact widget mode. */
|
|
100
|
-
export function setWidgetCompact(enabled: boolean): void {
|
|
101
|
-
__config.agent.widgetCompact = enabled;
|
|
102
|
-
saveConfigAtomic(__config);
|
|
103
|
-
syncWidgetSettings();
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Set max lines for full widget mode.
|
|
108
|
-
* Auto-derives widgetMaxLinesCompact if not explicitly set.
|
|
109
|
-
*/
|
|
110
|
-
export function setWidgetMaxLines(lines: number): void {
|
|
111
|
-
__config.agent.widgetMaxLines = lines;
|
|
112
|
-
if (__config.agent.widgetMaxLinesCompact === undefined) {
|
|
113
|
-
__config.agent.widgetMaxLinesCompact = Math.floor(lines / 2);
|
|
114
|
-
}
|
|
115
|
-
saveConfigAtomic(__config);
|
|
116
|
-
syncWidgetSettings();
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/** Set max lines for compact widget mode. */
|
|
120
|
-
export function setWidgetMaxLinesCompact(lines: number): void {
|
|
121
|
-
__config.agent.widgetMaxLinesCompact = lines;
|
|
122
|
-
saveConfigAtomic(__config);
|
|
123
|
-
syncWidgetSettings();
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/** Toggle ctrl+o widget shortcut. */
|
|
127
|
-
export function setWidgetShortcut(enabled: boolean): void {
|
|
128
|
-
__config.agent.widgetShortcut = enabled;
|
|
129
|
-
saveConfigAtomic(__config);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/** Replace the entire agent config object (used by "clear all overrides"). */
|
|
133
|
-
export function setAgent(agent: typeof __config.agent): void {
|
|
134
|
-
__config.agent = agent;
|
|
135
|
-
saveConfigAtomic(__config);
|
|
136
|
-
syncWidgetSettings();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// ============================================================================
|
|
140
|
-
// Concurrency setters (save + sync via getManager().setConcurrency)
|
|
141
|
-
// ============================================================================
|
|
142
|
-
|
|
143
|
-
/** Set the global concurrency default. */
|
|
144
|
-
export function setConcurrencyDefault(n: number): void {
|
|
145
|
-
__config.concurrency.default = n;
|
|
146
|
-
applyConcurrencyConfig();
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/** Set or update a per-provider concurrency limit. */
|
|
150
|
-
export function setConcurrencyProvider(key: string, n: number): void {
|
|
151
|
-
const current = __config.concurrency.providers ?? {};
|
|
152
|
-
__config.concurrency.providers = { ...current, [key]: n };
|
|
153
|
-
applyConcurrencyConfig();
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/** Set or update a per-model concurrency limit. */
|
|
157
|
-
export function setConcurrencyModel(key: string, n: number): void {
|
|
158
|
-
const current = __config.concurrency.models ?? {};
|
|
159
|
-
__config.concurrency.models = { ...current, [key]: n };
|
|
160
|
-
applyConcurrencyConfig();
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/** Remove a per-provider concurrency limit. */
|
|
164
|
-
export function removeConcurrencyProvider(key: string): void {
|
|
165
|
-
if (__config.concurrency.providers) {
|
|
166
|
-
delete __config.concurrency.providers[key];
|
|
167
|
-
}
|
|
168
|
-
applyConcurrencyConfig();
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/** Remove a per-model concurrency limit. */
|
|
172
|
-
export function removeConcurrencyModel(key: string): void {
|
|
173
|
-
if (__config.concurrency.models) {
|
|
174
|
-
delete __config.concurrency.models[key];
|
|
175
|
-
}
|
|
176
|
-
applyConcurrencyConfig();
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** Reset all concurrency settings to defaults. */
|
|
180
|
-
export function resetConcurrency(): void {
|
|
181
|
-
__config.concurrency = { ...DEFAULT_CONFIG.concurrency };
|
|
182
|
-
applyConcurrencyConfig();
|
|
183
|
-
}
|