@gotgenes/pi-subagents 6.8.3 → 6.9.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/CHANGELOG.md +23 -0
- package/docs/architecture/architecture.md +39 -28
- package/docs/plans/0114-narrow-agent-tool-menu-deps.md +279 -0
- package/docs/plans/0115-decompose-agent-tool.md +337 -0
- package/docs/retro/0113-disambiguate-spawn-options.md +29 -0
- package/docs/retro/0114-narrow-agent-tool-menu-deps.md +38 -0
- package/package.json +1 -1
- package/src/agent-manager.ts +16 -3
- package/src/index.ts +9 -32
- package/src/tools/agent-tool.ts +48 -215
- package/src/tools/background-spawner.ts +116 -0
- package/src/tools/foreground-runner.ts +175 -0
- package/src/tools/helpers.ts +83 -1
- package/src/ui/agent-menu.ts +9 -2
package/src/tools/helpers.ts
CHANGED
|
@@ -1,6 +1,51 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { AgentConfigLookup } from "../agent-types.js";
|
|
2
|
+
import { AgentActivityTracker } from "../ui/agent-activity-tracker.js";
|
|
3
|
+
import { type AgentDetails, formatTokens } from "../ui/agent-widget.js";
|
|
2
4
|
import { getLifetimeTotal, type LifetimeUsage } from "../usage.js";
|
|
3
5
|
|
|
6
|
+
/** Parenthetical status note for completed agent result text. */
|
|
7
|
+
export function getStatusNote(status: string): string {
|
|
8
|
+
switch (status) {
|
|
9
|
+
case "aborted":
|
|
10
|
+
return " (aborted \u2014 max turns exceeded, output may be incomplete)";
|
|
11
|
+
case "steered":
|
|
12
|
+
return " (wrapped up \u2014 reached turn limit)";
|
|
13
|
+
case "stopped":
|
|
14
|
+
return " (stopped by user)";
|
|
15
|
+
default:
|
|
16
|
+
return "";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Build AgentDetails from a base + record-specific fields. */
|
|
21
|
+
export function buildDetails(
|
|
22
|
+
base: Pick<AgentDetails, "displayName" | "description" | "subagentType" | "modelName" | "tags">,
|
|
23
|
+
record: {
|
|
24
|
+
toolUses: number;
|
|
25
|
+
startedAt: number;
|
|
26
|
+
completedAt?: number;
|
|
27
|
+
status: string;
|
|
28
|
+
error?: string;
|
|
29
|
+
id?: string;
|
|
30
|
+
lifetimeUsage: LifetimeUsage;
|
|
31
|
+
},
|
|
32
|
+
activity?: AgentActivityTracker,
|
|
33
|
+
overrides?: Partial<AgentDetails>,
|
|
34
|
+
): AgentDetails {
|
|
35
|
+
return {
|
|
36
|
+
...base,
|
|
37
|
+
toolUses: record.toolUses,
|
|
38
|
+
tokens: formatLifetimeTokens(record),
|
|
39
|
+
turnCount: activity?.turnCount,
|
|
40
|
+
maxTurns: activity?.maxTurns,
|
|
41
|
+
durationMs: (record.completedAt ?? Date.now()) - record.startedAt,
|
|
42
|
+
status: record.status as AgentDetails["status"],
|
|
43
|
+
agentId: record.id,
|
|
44
|
+
error: record.error,
|
|
45
|
+
...overrides,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
4
49
|
/** Tool execute return value for a text response. */
|
|
5
50
|
export function textResult(msg: string, details?: unknown) {
|
|
6
51
|
return { content: [{ type: "text" as const, text: msg }], details: details as any };
|
|
@@ -12,6 +57,43 @@ export function formatLifetimeTokens(o: { lifetimeUsage: LifetimeUsage }): strin
|
|
|
12
57
|
return t > 0 ? formatTokens(t) : "";
|
|
13
58
|
}
|
|
14
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Narrow registry interface needed by buildTypeListText.
|
|
62
|
+
* Extends AgentConfigLookup with the two name-listing methods.
|
|
63
|
+
*/
|
|
64
|
+
export interface TypeListRegistry extends AgentConfigLookup {
|
|
65
|
+
getDefaultAgentNames(): string[];
|
|
66
|
+
getUserAgentNames(): string[];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Build the full agent-type list text for the Agent tool description.
|
|
71
|
+
* Extracted from index.ts so it can be called inside createAgentTool.
|
|
72
|
+
*/
|
|
73
|
+
export function buildTypeListText(registry: TypeListRegistry, agentDir: string): string {
|
|
74
|
+
const defaultNames = registry.getDefaultAgentNames();
|
|
75
|
+
const userNames = registry.getUserAgentNames();
|
|
76
|
+
|
|
77
|
+
const defaultDescs = defaultNames.map((name) => {
|
|
78
|
+
const cfg = registry.resolveAgentConfig(name);
|
|
79
|
+
const modelSuffix = cfg.model ? ` (${getModelLabelFromConfig(cfg.model)})` : "";
|
|
80
|
+
return `- ${name}: ${cfg.description}${modelSuffix}`;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const customDescs = userNames.map((name) => {
|
|
84
|
+
const cfg = registry.resolveAgentConfig(name);
|
|
85
|
+
return `- ${name}: ${cfg.description}`;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
return [
|
|
89
|
+
"Default agents:",
|
|
90
|
+
...defaultDescs,
|
|
91
|
+
...(customDescs.length > 0 ? ["", "Custom agents:", ...customDescs] : []),
|
|
92
|
+
"",
|
|
93
|
+
`Custom agents can be defined in .pi/agents/<name>.md (project) or ${agentDir}/agents/<name>.md (global) — they are picked up automatically. Project-level agents override global ones. Creating a .md file with the same name as a default agent overrides it.`,
|
|
94
|
+
].join("\n");
|
|
95
|
+
}
|
|
96
|
+
|
|
15
97
|
/** Derive a short model label from a model string. */
|
|
16
98
|
export function getModelLabelFromConfig(model: string): string {
|
|
17
99
|
// Strip provider prefix (e.g. "anthropic/claude-sonnet-4-6" → "claude-sonnet-4-6")
|
package/src/ui/agent-menu.ts
CHANGED
|
@@ -32,15 +32,22 @@ export interface AgentMenuSettings {
|
|
|
32
32
|
applyGraceTurns(n: number): { message: string; level: "info" | "warning" };
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Read-only interface for the agent-menu's agentActivity access.
|
|
37
|
+
* Only the conversation viewer needs to read a tracker by agent ID.
|
|
38
|
+
*/
|
|
39
|
+
export interface AgentActivityReader {
|
|
40
|
+
get(id: string): AgentActivityTracker | undefined;
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
export interface AgentMenuDeps {
|
|
36
44
|
manager: AgentMenuManager;
|
|
37
45
|
registry: AgentTypeRegistry;
|
|
38
|
-
agentActivity:
|
|
46
|
+
agentActivity: AgentActivityReader;
|
|
39
47
|
/** Resolve model label for a given agent type + registry. */
|
|
40
48
|
getModelLabel: (type: string, registry?: ModelRegistry) => string;
|
|
41
49
|
/** Settings manager — owns in-memory values and persistence. */
|
|
42
50
|
settings: AgentMenuSettings;
|
|
43
|
-
emitEvent: (name: string, data: unknown) => void;
|
|
44
51
|
personalAgentsDir: string;
|
|
45
52
|
projectAgentsDir: string;
|
|
46
53
|
}
|