pi-subagents 0.14.0 → 0.15.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/CHANGELOG.md +30 -4
- package/README.md +88 -7
- package/agent-management.ts +28 -7
- package/agent-manager-detail.ts +5 -2
- package/agent-manager-edit.ts +46 -6
- package/agent-manager-list.ts +3 -3
- package/agent-manager.ts +28 -2
- package/agent-serializer.ts +6 -0
- package/agents/context-builder.md +24 -26
- package/agents/delegate.md +4 -1
- package/agents/planner.md +21 -15
- package/agents/researcher.md +23 -25
- package/agents/reviewer.md +22 -14
- package/agents/scout.md +24 -19
- package/agents/worker.md +20 -8
- package/agents.ts +121 -13
- package/async-execution.ts +18 -12
- package/async-job-tracker.ts +3 -3
- package/async-status.ts +3 -3
- package/chain-clarify.ts +4 -4
- package/chain-execution.ts +19 -17
- package/execution.ts +3 -3
- package/formatters.ts +14 -12
- package/index.ts +1 -1
- package/install.mjs +3 -3
- package/package.json +1 -1
- package/parallel-utils.ts +9 -20
- package/pi-args.ts +13 -6
- package/prompt-template-bridge.ts +19 -8
- package/render.ts +23 -50
- package/schemas.ts +1 -1
- package/settings.ts +2 -2
- package/single-output.ts +2 -2
- package/slash-commands.ts +8 -8
- package/subagent-executor.ts +40 -27
- package/subagent-prompt-runtime.ts +67 -0
- package/subagent-runner.ts +7 -12
- package/types.ts +1 -1
- package/utils.ts +53 -12
- package/worktree.ts +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,32 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.15.0] - 2026-04-16
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Added `systemPromptMode` so subagents can replace Pi's base prompt with `--system-prompt` instead of always appending with `--append-system-prompt`, shipping the core of issue `#85` from @isvlasov.
|
|
9
|
+
- Added `inheritProjectContext` and `inheritSkills` so child runs can keep or strip inherited project instruction files (`AGENTS.md`, `CLAUDE.md`, etc.) and Pi's discovered skills block.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- Builtin subagents now default to `systemPromptMode: replace`, with builtin `delegate` staying on `append`.
|
|
13
|
+
- Builtin agents now inherit project-level instruction files by default unless the user overrides them.
|
|
14
|
+
- Builtin agent prompts were rewritten for the new prompt-assembly model, and builtin `reviewer` / `context-builder` tool lists now match their documented behaviors. This rounds out the prompt-assembly work merged in PR `#92`, which closed issue `#85`. Thanks @isvlasov.
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Cross-platform tests now avoid machine-specific Pi install paths, align homedir-sensitive settings discovery on Windows CI, and use deterministic async config-write failure fixtures.
|
|
18
|
+
- Request-level `cwd` handling is now consistent across management and execution paths. `subagent` requests that target a worktree or nested checkout now resolve project agents, project settings, and builtin agent overrides from the requested `cwd` instead of accidentally inheriting the parent session's repo. This fixes issue `#83`. Thanks @hakin19 for the report.
|
|
19
|
+
- Relative child `cwd` values now resolve from the already-selected request/shared `cwd` across sync runs, async/background runs, chain steps, and top-level parallel tasks. This fixes cases where values like `packages/app` were interpreted from the wrong base directory, which could break skill lookup, output paths, and child process spawning.
|
|
20
|
+
- Worktree parallel-mode validation now compares task-level `cwd` overrides after relative-path resolution, so equivalent paths like `.` no longer trigger false conflict errors against the shared worktree base.
|
|
21
|
+
- Internal TypeScript source imports in the touched runtime paths now consistently use `.ts` local specifiers, matching the repo's direct TypeScript runtime loading conventions and reducing drift between adjacent modules.
|
|
22
|
+
|
|
23
|
+
## [0.14.1] - 2026-04-14
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Completed foreground subagent results now return compact payloads instead of inlining full raw message histories and per-result progress objects, preventing long tool-heavy sync runs from overwhelming the parent agent return path.
|
|
27
|
+
- Prompt-template delegation now rebuilds minimal assistant messages from compact foreground results when raw message arrays are intentionally omitted.
|
|
28
|
+
- UI/status wording now uses plain text labels instead of glyph-heavy markers across foreground rendering, parallel summaries, save-result receipts, installer output, agent manager views, clarify screens, and the corresponding README/CHANGELOG examples.
|
|
29
|
+
- Added a realistic foreground integration repro for issue `#80` and cleaned up the touched tests to remove the remaining blunt `as any` fixture casts.
|
|
30
|
+
|
|
5
31
|
## [0.14.0] - 2026-04-14
|
|
6
32
|
|
|
7
33
|
### Added
|
|
@@ -496,7 +522,7 @@
|
|
|
496
522
|
- Pre-selects current thinking level if already set
|
|
497
523
|
- **Model selector in chain TUI** - Press `[m]` to select a different model for any step
|
|
498
524
|
- Fuzzy search through all available models
|
|
499
|
-
- Shows current model with
|
|
525
|
+
- Shows the current model with a `current` badge
|
|
500
526
|
- Provider/model format (e.g., `anthropic/claude-haiku-4-5`)
|
|
501
527
|
- Override indicator (✎) when model differs from agent default
|
|
502
528
|
- **Model visibility in chain execution** - Shows which model each step is using
|
|
@@ -534,8 +560,8 @@
|
|
|
534
560
|
|
|
535
561
|
### Improved
|
|
536
562
|
- **Per-step progress indicators** - When progress is enabled, each step shows its role:
|
|
537
|
-
- Step 1:
|
|
538
|
-
- Step 2+:
|
|
563
|
+
- Step 1: `writes progress.md`
|
|
564
|
+
- Step 2+: `reads progress.md`
|
|
539
565
|
- Clear visualization of progress.md data flow through the chain
|
|
540
566
|
- **Comprehensive tool descriptions** - Better documentation of chain variables:
|
|
541
567
|
- Tool description now explains `{task}`, `{previous}`, `{chain_dir}` in detail
|
|
@@ -591,7 +617,7 @@
|
|
|
591
617
|
### Improved
|
|
592
618
|
- **Tool description now explicitly shows the three modes** (SINGLE, CHAIN, PARALLEL) with syntax - helps agents pick the right mode when user says "scout → planner"
|
|
593
619
|
- **Chain execution observability** - Now shows:
|
|
594
|
-
- Chain visualization with status
|
|
620
|
+
- Chain visualization with status labels: `done scout → running planner` (`done`, `running`, `pending`, `failed`) - sequential chains only
|
|
595
621
|
- Accurate step counter: "step 1/2" instead of misleading "1/1"
|
|
596
622
|
- Current tool and recent output for running step
|
|
597
623
|
|
package/README.md
CHANGED
|
@@ -51,10 +51,44 @@ You can also override selected builtin fields without copying the whole agent. B
|
|
|
51
51
|
- User scope: `~/.pi/agent/settings.json`
|
|
52
52
|
- Project scope: `.pi/settings.json`
|
|
53
53
|
|
|
54
|
-
Supported builtin override fields are `model`, `fallbackModels`, `thinking`, `skills`, `tools`, and `systemPrompt`. Project overrides beat user overrides.
|
|
54
|
+
Supported builtin override fields are `model`, `fallbackModels`, `thinking`, `systemPromptMode`, `inheritProjectContext`, `inheritSkills`, `skills`, `tools`, and `systemPrompt`. Project overrides beat user overrides.
|
|
55
|
+
|
|
56
|
+
**Overriding builtin defaults:**
|
|
57
|
+
|
|
58
|
+
All builtin agents inherit project instruction files (`AGENTS.md`, `CLAUDE.md`, etc.) by default. To make a builtin agent run without those project instructions:
|
|
59
|
+
|
|
60
|
+
**Via settings file** — add to `~/.pi/agent/settings.json` (user scope) or `.pi/settings.json` (project scope):
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"subagents": {
|
|
64
|
+
"agentOverrides": {
|
|
65
|
+
"reviewer": {
|
|
66
|
+
"inheritProjectContext": false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Via `/agents` UI** — press `e` on any builtin agent (like `reviewer`), then toggle `inheritProjectContext` to `false` and save. This creates an override that you can edit or remove later without modifying the builtin definition itself.
|
|
74
|
+
|
|
75
|
+
Overridden builtins show badges like `[builtin+user]` or `[builtin+project]` to indicate they have customizations applied.
|
|
55
76
|
|
|
56
77
|
> **Note:** The `researcher` agent uses `web_search`, `fetch_content`, and `get_search_content` tools which require the [pi-web-access](https://github.com/nicobailon/pi-web-access) extension. Install it with `pi install npm:pi-web-access`.
|
|
57
78
|
|
|
79
|
+
### Prompt Assembly Philosophy
|
|
80
|
+
|
|
81
|
+
Subagents are designed to be **narrow and intentional**. Custom subagents default to seeing only what you explicitly give them — not Pi's entire base prompt, not your repo's `AGENTS.md`, and not the parent's discovered skills.
|
|
82
|
+
|
|
83
|
+
This prevents subtle bugs where a "simple" code review agent starts making decisions based on project architecture rules it shouldn't know about, or a focused research agent gets distracted by tool descriptions meant for the orchestrator.
|
|
84
|
+
|
|
85
|
+
Use inheritance flags to selectively add back context when you actually want it:
|
|
86
|
+
- **`inheritProjectContext: true`** — Keep Pi's inherited project-instructions block from project-level files like `AGENTS.md` and `CLAUDE.md`
|
|
87
|
+
- **`inheritSkills: true`** — Let the child use Pi's discovered skills catalog
|
|
88
|
+
- **`systemPromptMode: append`** — Add the agent's prompt to Pi's base instead of replacing it
|
|
89
|
+
|
|
90
|
+
Builtin agents ship a little differently: they all inherit project instruction files by default so they follow repo-specific rules out of the box. `delegate` is still the exception for `systemPromptMode` — it stays on `append` because its job is orchestration within the parent workflow, not isolated task execution.
|
|
91
|
+
|
|
58
92
|
**Agent frontmatter:**
|
|
59
93
|
|
|
60
94
|
```yaml
|
|
@@ -66,6 +100,9 @@ extensions: # absent=all, empty=none, csv=allowlist
|
|
|
66
100
|
model: claude-haiku-4-5
|
|
67
101
|
fallbackModels: openai/gpt-5-mini, anthropic/claude-sonnet-4 # optional ordered fallbacks
|
|
68
102
|
thinking: high # off, minimal, low, medium, high, xhigh
|
|
103
|
+
systemPromptMode: replace # replace by default, except builtin delegate
|
|
104
|
+
inheritProjectContext: false # custom agents default false; builtins opt into true
|
|
105
|
+
inheritSkills: false # strip Pi's discovered skills section
|
|
69
106
|
skill: safe-bash, chrome-devtools # comma-separated skills to inject
|
|
70
107
|
output: context.md # writes to {chain_dir}/context.md
|
|
71
108
|
defaultReads: context.md # comma-separated files to read
|
|
@@ -81,10 +118,51 @@ The `thinking` field sets a default extended thinking level for the agent. At ru
|
|
|
81
118
|
|
|
82
119
|
`fallbackModels` is an optional ordered list of backup models to try when the primary model fails with a provider/model-style error such as quota, auth, timeout, or provider/model unavailable. In markdown frontmatter, declare it as a comma-separated string. In management `config` objects, you can pass either a comma-separated string or a string array.
|
|
83
120
|
|
|
121
|
+
`systemPromptMode` — How the agent markdown body is passed to Pi:
|
|
122
|
+
- **`replace`** (default) — The agent's markdown body becomes the system prompt. Clean slate, no Pi base prompt baggage.
|
|
123
|
+
- **`append`** — The agent's prompt is appended to Pi's normal base prompt. Use this when you want Pi's full capabilities plus your extra instructions.
|
|
124
|
+
|
|
125
|
+
`inheritProjectContext` — Whether the child keeps Pi's inherited project-instructions block, built from project-level instruction files like `AGENTS.md` and `CLAUDE.md`:
|
|
126
|
+
- **`false`** (default) — Strip those inherited project-level instructions from the child's final system prompt. This does not remove repo access, cwd, tools, or the task itself; it only removes those inherited instructions.
|
|
127
|
+
- **`true`** — Keep those inherited project-level instructions. Use for specialists that should follow project-specific constraints and conventions.
|
|
128
|
+
|
|
129
|
+
`inheritSkills` — Whether the child keeps Pi's discovered skills section:
|
|
130
|
+
- **`false`** (default) — Skills catalog is stripped. Good for focused agents that shouldn't browse unrelated skills.
|
|
131
|
+
- **`true`** — Child sees the full skills list. Use for general-purpose assistants that might need varied tools.
|
|
132
|
+
|
|
133
|
+
The `skills` field still works independently — it injects specific skills directly into the agent prompt regardless of `inheritSkills`.
|
|
134
|
+
|
|
135
|
+
**Common Recipes**
|
|
136
|
+
|
|
137
|
+
| Goal | `systemPromptMode` | `inheritProjectContext` | `inheritSkills` |
|
|
138
|
+
|------|-------------------|------------------------|-----------------|
|
|
139
|
+
| Fully isolated specialist (custom-agent default) | `replace` | `false` | `false` |
|
|
140
|
+
| Specialist that should follow project instruction files | `replace` | `true` | `false` |
|
|
141
|
+
| Pi-plus-extensions | `append` | `true` | `true` |
|
|
142
|
+
|
|
143
|
+
- **Security auditor**: Fully isolated so it objectively checks for vulnerabilities without being biased by project conventions.
|
|
144
|
+
- **Architecture planner**: Repo-aware so it respects `AGENTS.md` constraints when making design decisions.
|
|
145
|
+
- **Generic helper**: Append mode with full inheritance so it behaves like a slightly-customized Pi.
|
|
146
|
+
|
|
84
147
|
Fallback resolution follows the same conservative model lookup as normal execution. Explicit `provider/model` values are used as-is. Bare model IDs first prefer the current session provider when that provider actually exposes the model, then fall back to a unique registry match. If a bare ID is still ambiguous, it stays bare.
|
|
85
148
|
|
|
86
149
|
Fallback is only used for provider/model availability failures. Ordinary task failures such as bad `bash` commands, missing files, or other tool/runtime errors do not trigger a model hop.
|
|
87
150
|
|
|
151
|
+
**Tool selection semantics**
|
|
152
|
+
|
|
153
|
+
The `tools` field controls builtin-tool allowlisting and a couple of related extension behaviors:
|
|
154
|
+
|
|
155
|
+
- `tools` **omitted** → `pi-subagents` does not pass `--tools`, so the child gets Pi's normal default builtin tools.
|
|
156
|
+
- `tools` **present** → listed builtin tool names become an explicit allowlist passed via `--tools`.
|
|
157
|
+
- `mcp:...` entries are split out of `tools` and forwarded as direct MCP tool selections.
|
|
158
|
+
- Path-like entries in `tools` (extension paths or file paths ending in `.ts` / `.js`) are treated as tool-extension paths, not builtin tool names.
|
|
159
|
+
|
|
160
|
+
This means:
|
|
161
|
+
|
|
162
|
+
- `tools` omitted + `extensions` omitted → child gets Pi's normal builtin tools and normal extension set.
|
|
163
|
+
- `tools: mcp:chrome-devtools` → child still gets Pi's default builtin tools, plus direct MCP tools from `chrome-devtools`.
|
|
164
|
+
- `tools: read, bash, mcp:chrome-devtools` → child is restricted to `read` and `bash` for builtin tools, plus direct MCP tools from `chrome-devtools`.
|
|
165
|
+
|
|
88
166
|
**Extension sandboxing**
|
|
89
167
|
|
|
90
168
|
Use `extensions` in frontmatter to control which extensions a subagent can access:
|
|
@@ -229,7 +307,7 @@ Press **Ctrl+Shift+A** or type `/agents` to open the Agents Manager overlay —
|
|
|
229
307
|
|--------|-------------|
|
|
230
308
|
| List | Browse all agents and chains with search/filter, scope badges, chain badges |
|
|
231
309
|
| Detail | View resolved prompt, frontmatter fields, recent run history, and active builtin override path |
|
|
232
|
-
| Edit | Edit fields with specialized pickers (model, thinking, skills, prompt editor) |
|
|
310
|
+
| Edit | Edit fields with specialized pickers and toggles (model, thinking, prompt mode, inherited context, inherited skills, prompt editor) |
|
|
233
311
|
| Chain Detail | View chain steps with flow visualization and dependency map |
|
|
234
312
|
| Parallel Builder | Build parallel execution slots, add same agent multiple times, per-slot task overrides |
|
|
235
313
|
| Task Input | Enter task and launch with optional skip-clarify toggle |
|
|
@@ -573,6 +651,9 @@ Agent definitions are not loaded into LLM context by default. Management actions
|
|
|
573
651
|
description: "Scans codebases for patterns and issues",
|
|
574
652
|
scope: "user",
|
|
575
653
|
systemPrompt: "You are a code scout...",
|
|
654
|
+
systemPromptMode: "replace",
|
|
655
|
+
inheritProjectContext: false,
|
|
656
|
+
inheritSkills: false,
|
|
576
657
|
model: "anthropic/claude-sonnet-4",
|
|
577
658
|
fallbackModels: ["openai/gpt-5-mini", "anthropic/claude-haiku-4-5"],
|
|
578
659
|
tools: "read, bash, mcp:github/search_repositories",
|
|
@@ -613,7 +694,7 @@ Agent definitions are not loaded into LLM context by default. Management actions
|
|
|
613
694
|
Notes:
|
|
614
695
|
- `create` uses `config.scope` (`"user"` or `"project"`), not `agentScope`.
|
|
615
696
|
- `update`/`delete` use `agentScope` only for scope disambiguation when the same name exists in both scopes.
|
|
616
|
-
- Agent config mapping: `reads -> defaultReads`, `progress -> defaultProgress`, `extensions` controls extension sandboxing, `maxSubagentDepth`
|
|
697
|
+
- Agent config mapping: `reads -> defaultReads`, `progress -> defaultProgress`, `extensions` controls extension sandboxing, `maxSubagentDepth`, `fallbackModels`, `systemPromptMode`, `inheritProjectContext`, and `inheritSkills` map directly to agent frontmatter, and `tools` supports `mcp:` entries that map to direct MCP tools.
|
|
617
698
|
- To clear any optional field, set it to `false` or `""` (e.g., `{ model: false }` or `{ skills: "" }`). Both work for all string-typed fields.
|
|
618
699
|
|
|
619
700
|
## Parameters
|
|
@@ -624,7 +705,7 @@ Notes:
|
|
|
624
705
|
| `task` | string | - | Task string (single mode) |
|
|
625
706
|
| `action` | string | - | Management action: `list`, `get`, `create`, `update`, `delete` |
|
|
626
707
|
| `chainName` | string | - | Chain name for management get/update/delete |
|
|
627
|
-
| `config` | object | - | Agent or chain config for management create/update. Agent configs also accept `fallbackModels` (comma-separated string or string array). |
|
|
708
|
+
| `config` | object | - | Agent or chain config for management create/update. Agent configs also accept `fallbackModels` (comma-separated string or string array), `systemPromptMode` (`append` or `replace`), `inheritProjectContext` (boolean), and `inheritSkills` (boolean). |
|
|
628
709
|
| `output` | `string \| false` | agent default | Override output file for single agent (absolute path as-is, relative path resolved against cwd) |
|
|
629
710
|
| `skill` | `string \| string[] \| false` | agent default | Override skills (comma-separated string, array, or false to disable) |
|
|
630
711
|
| `model` | string | agent default | Override model for single agent |
|
|
@@ -921,8 +1002,8 @@ Requirements:
|
|
|
921
1002
|
During sync execution, the collapsed view shows real-time progress for single, chain, and parallel modes.
|
|
922
1003
|
|
|
923
1004
|
**Chains:**
|
|
924
|
-
- Header:
|
|
925
|
-
- Chain visualization with status:
|
|
1005
|
+
- Header: `running chain 1/2 | 8 tools, 1.4k tok, 38s`
|
|
1006
|
+
- Chain visualization with status: `done scout → running planner` (`done`, `running`, `pending`, `failed`)
|
|
926
1007
|
- Current tool: `> read: packages/tui/src/...`
|
|
927
1008
|
- Recent output lines (last 2-3 lines)
|
|
928
1009
|
|
|
@@ -933,7 +1014,7 @@ During sync execution, the collapsed view shows real-time progress for single, c
|
|
|
933
1014
|
|
|
934
1015
|
Press **Ctrl+O** to expand the full streaming view with complete output per step.
|
|
935
1016
|
|
|
936
|
-
> **Note:** Chain visualization (the
|
|
1017
|
+
> **Note:** Chain visualization (the `done scout → running planner` line) is only shown for sequential chains. Chains with parallel steps show per-step cards instead.
|
|
937
1018
|
|
|
938
1019
|
## Nested subagent recursion guard
|
|
939
1020
|
|
package/agent-management.ts
CHANGED
|
@@ -8,6 +8,9 @@ import {
|
|
|
8
8
|
type AgentSource,
|
|
9
9
|
type ChainConfig,
|
|
10
10
|
type ChainStepConfig,
|
|
11
|
+
defaultInheritProjectContext,
|
|
12
|
+
defaultInheritSkills,
|
|
13
|
+
defaultSystemPromptMode,
|
|
11
14
|
discoverAgentsAll,
|
|
12
15
|
} from "./agents.ts";
|
|
13
16
|
import { serializeAgent } from "./agent-serializer.ts";
|
|
@@ -244,6 +247,18 @@ function applyAgentConfig(target: AgentConfig, cfg: Record<string, unknown>): st
|
|
|
244
247
|
else if (typeof cfg.thinking === "string") target.thinking = cfg.thinking.trim() || undefined;
|
|
245
248
|
else return "config.thinking must be a string or false when provided.";
|
|
246
249
|
}
|
|
250
|
+
if (hasKey(cfg, "systemPromptMode")) {
|
|
251
|
+
if (cfg.systemPromptMode === "append" || cfg.systemPromptMode === "replace") target.systemPromptMode = cfg.systemPromptMode;
|
|
252
|
+
else return "config.systemPromptMode must be 'append' or 'replace' when provided.";
|
|
253
|
+
}
|
|
254
|
+
if (hasKey(cfg, "inheritProjectContext")) {
|
|
255
|
+
if (typeof cfg.inheritProjectContext !== "boolean") return "config.inheritProjectContext must be a boolean when provided.";
|
|
256
|
+
target.inheritProjectContext = cfg.inheritProjectContext;
|
|
257
|
+
}
|
|
258
|
+
if (hasKey(cfg, "inheritSkills")) {
|
|
259
|
+
if (typeof cfg.inheritSkills !== "boolean") return "config.inheritSkills must be a boolean when provided.";
|
|
260
|
+
target.inheritSkills = cfg.inheritSkills;
|
|
261
|
+
}
|
|
247
262
|
if (hasKey(cfg, "output")) {
|
|
248
263
|
if (cfg.output === false || cfg.output === "") target.output = undefined;
|
|
249
264
|
else if (typeof cfg.output === "string") target.output = cfg.output;
|
|
@@ -320,6 +335,9 @@ export function formatAgentDetail(agent: AgentConfig): string {
|
|
|
320
335
|
if (agent.fallbackModels?.length) lines.push(`Fallback models: ${agent.fallbackModels.join(", ")}`);
|
|
321
336
|
if (tools.length) lines.push(`Tools: ${tools.join(", ")}`);
|
|
322
337
|
if (agent.skills?.length) lines.push(`Skills: ${agent.skills.join(", ")}`);
|
|
338
|
+
lines.push(`System prompt mode: ${agent.systemPromptMode}`);
|
|
339
|
+
lines.push(`Inherit project context: ${agent.inheritProjectContext ? "true" : "false"}`);
|
|
340
|
+
lines.push(`Inherit skills: ${agent.inheritSkills ? "true" : "false"}`);
|
|
323
341
|
if (agent.extensions !== undefined) lines.push(`Extensions: ${agent.extensions.length ? agent.extensions.join(", ") : "(none)"}`);
|
|
324
342
|
if (agent.thinking) lines.push(`Thinking: ${agent.thinking}`);
|
|
325
343
|
if (agent.output) lines.push(`Output: ${agent.output}`);
|
|
@@ -418,7 +436,16 @@ export function handleCreate(params: ManagementParams, ctx: ManagementContext):
|
|
|
418
436
|
warnings.push(...chainStepWarnings(ctx, chain.steps));
|
|
419
437
|
return result([`Created chain '${name}' at ${targetPath}.`, ...warnings].join("\n"));
|
|
420
438
|
}
|
|
421
|
-
const agent: AgentConfig = {
|
|
439
|
+
const agent: AgentConfig = {
|
|
440
|
+
name,
|
|
441
|
+
description: cfg.description.trim(),
|
|
442
|
+
source: scope,
|
|
443
|
+
filePath: targetPath,
|
|
444
|
+
systemPrompt: "",
|
|
445
|
+
systemPromptMode: defaultSystemPromptMode(name),
|
|
446
|
+
inheritProjectContext: defaultInheritProjectContext(name),
|
|
447
|
+
inheritSkills: defaultInheritSkills(),
|
|
448
|
+
};
|
|
422
449
|
const applyError = applyAgentConfig(agent, cfg);
|
|
423
450
|
if (applyError) return result(applyError, true);
|
|
424
451
|
const mw = modelWarning(ctx, agent.model);
|
|
@@ -446,7 +473,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
446
473
|
const target = targetOrError;
|
|
447
474
|
const updated: AgentConfig = { ...target };
|
|
448
475
|
const oldName = target.name;
|
|
449
|
-
// Validate all fields before any filesystem mutation
|
|
450
476
|
if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim())) return result("config.name must be a non-empty string when provided.", true);
|
|
451
477
|
if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim())) return result("config.description must be a non-empty string when provided.", true);
|
|
452
478
|
let newName: string | undefined;
|
|
@@ -456,7 +482,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
456
482
|
}
|
|
457
483
|
const applyError = applyAgentConfig(updated, cfg);
|
|
458
484
|
if (applyError) return result(applyError, true);
|
|
459
|
-
// Apply name/description (validated above)
|
|
460
485
|
if (newName !== undefined) updated.name = newName;
|
|
461
486
|
if (hasKey(cfg, "description")) updated.description = (cfg.description as string).trim();
|
|
462
487
|
if (hasKey(cfg, "model")) {
|
|
@@ -471,7 +496,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
471
496
|
const sw = skillsWarning(ctx.cwd, updated.skills);
|
|
472
497
|
if (sw) warnings.push(sw);
|
|
473
498
|
}
|
|
474
|
-
// Filesystem mutations last
|
|
475
499
|
if (updated.name !== oldName) {
|
|
476
500
|
const renamed = renamePath("agent", target.filePath, updated.name, target.source, ctx.cwd);
|
|
477
501
|
if (renamed.error) return result(renamed.error, true);
|
|
@@ -493,7 +517,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
493
517
|
const target = targetOrError;
|
|
494
518
|
const updated: ChainConfig = { ...target, steps: [...target.steps] };
|
|
495
519
|
const oldName = target.name;
|
|
496
|
-
// Validate all fields before any filesystem mutation
|
|
497
520
|
if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim())) return result("config.name must be a non-empty string when provided.", true);
|
|
498
521
|
if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim())) return result("config.description must be a non-empty string when provided.", true);
|
|
499
522
|
let newName: string | undefined;
|
|
@@ -507,7 +530,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
507
530
|
if (parsed.error) return result(parsed.error, true);
|
|
508
531
|
parsedSteps = parsed.steps!;
|
|
509
532
|
}
|
|
510
|
-
// Apply validated changes to in-memory object
|
|
511
533
|
if (newName !== undefined) updated.name = newName;
|
|
512
534
|
if (hasKey(cfg, "description")) updated.description = (cfg.description as string).trim();
|
|
513
535
|
if (parsedSteps) {
|
|
@@ -516,7 +538,6 @@ export function handleUpdate(params: ManagementParams, ctx: ManagementContext):
|
|
|
516
538
|
if (missing.length) warnings.push(`Warning: chain steps reference unknown agents: ${missing.join(", ")}.`);
|
|
517
539
|
warnings.push(...chainStepWarnings(ctx, updated.steps));
|
|
518
540
|
}
|
|
519
|
-
// Filesystem mutations last
|
|
520
541
|
if (updated.name !== oldName) {
|
|
521
542
|
const renamed = renamePath("chain", target.filePath, updated.name, target.source, ctx.cwd);
|
|
522
543
|
if (renamed.error) return result(renamed.error, true);
|
package/agent-manager-detail.ts
CHANGED
|
@@ -27,7 +27,7 @@ function renderFieldLine(
|
|
|
27
27
|
width: number,
|
|
28
28
|
theme: Theme,
|
|
29
29
|
): string {
|
|
30
|
-
const labelWidth =
|
|
30
|
+
const labelWidth = 12;
|
|
31
31
|
const labelText = theme.fg("dim", pad(label, labelWidth));
|
|
32
32
|
const available = Math.max(0, width - labelWidth);
|
|
33
33
|
return `${labelText}${truncateToWidth(value, available)}`;
|
|
@@ -61,6 +61,9 @@ function buildDetailLines(
|
|
|
61
61
|
const maxSubagentDepth = agent.maxSubagentDepth !== undefined ? String(agent.maxSubagentDepth) : "(default)";
|
|
62
62
|
|
|
63
63
|
lines.push(renderFieldLine("Model:", agent.model ?? "default", contentWidth, theme));
|
|
64
|
+
lines.push(renderFieldLine("Prompt mode:", agent.systemPromptMode, contentWidth, theme));
|
|
65
|
+
lines.push(renderFieldLine("Project ctx:", agent.inheritProjectContext ? "on" : "off", contentWidth, theme));
|
|
66
|
+
lines.push(renderFieldLine("Skills ctx:", agent.inheritSkills ? "on" : "off", contentWidth, theme));
|
|
64
67
|
if (agent.override) {
|
|
65
68
|
const overrideLabel = `${agent.override.scope} · ${formatPath(agent.override.path)}`;
|
|
66
69
|
lines.push(renderFieldLine("Override:", overrideLabel, contentWidth, theme));
|
|
@@ -106,7 +109,7 @@ function buildDetailLines(
|
|
|
106
109
|
|
|
107
110
|
for (const run of recentRuns) {
|
|
108
111
|
const when = pad(formatRelativeTime(run.ts), 8);
|
|
109
|
-
const status = run.status
|
|
112
|
+
const status = run.status;
|
|
110
113
|
const task = truncateToWidth(`"${run.task}"`, 34);
|
|
111
114
|
const tail = run.status === "ok" ? formatDuration(run.duration) : `exit ${run.exit ?? 1}`;
|
|
112
115
|
lines.push(truncateToWidth(` ${when} ${status} ${task} ${tail}`, contentWidth));
|
package/agent-manager-edit.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Theme } from "@mariozechner/pi-coding-agent";
|
|
2
2
|
import { matchesKey, truncateToWidth } from "@mariozechner/pi-tui";
|
|
3
|
-
import type
|
|
3
|
+
import { defaultSystemPromptMode, type AgentConfig, type BuiltinAgentOverrideBase } from "./agents.ts";
|
|
4
4
|
import { createEditorState, ensureCursorVisible, getCursorDisplayPos, handleEditorInput, renderEditor, wrapText } from "./text-editor.ts";
|
|
5
5
|
import type { TextEditorState } from "./text-editor.ts";
|
|
6
6
|
import { pad, row, renderHeader, renderFooter, formatScrollInfo } from "./render-helpers.ts";
|
|
@@ -26,7 +26,7 @@ export interface CreateEditStateOptions {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"] as const;
|
|
29
|
-
const FIELD_ORDER = ["name", "description", "model", "fallbackModels", "thinking", "tools", "extensions", "skills", "output", "reads", "progress", "interactive", "prompt"] as const;
|
|
29
|
+
const FIELD_ORDER = ["name", "description", "model", "fallbackModels", "thinking", "systemPromptMode", "inheritProjectContext", "inheritSkills", "tools", "extensions", "skills", "output", "reads", "progress", "interactive", "prompt"] as const;
|
|
30
30
|
type ThinkingLevel = typeof THINKING_LEVELS[number];
|
|
31
31
|
const PROMPT_VIEWPORT_HEIGHT = 16;
|
|
32
32
|
const MODEL_SELECTOR_HEIGHT = 10;
|
|
@@ -45,6 +45,9 @@ function fieldValueMatchesBase(field: EditField, state: EditState): boolean {
|
|
|
45
45
|
case "model": return state.draft.model === base.model;
|
|
46
46
|
case "fallbackModels": return arraysEqual(state.draft.fallbackModels, base.fallbackModels);
|
|
47
47
|
case "thinking": return state.draft.thinking === base.thinking;
|
|
48
|
+
case "systemPromptMode": return state.draft.systemPromptMode === base.systemPromptMode;
|
|
49
|
+
case "inheritProjectContext": return state.draft.inheritProjectContext === base.inheritProjectContext;
|
|
50
|
+
case "inheritSkills": return state.draft.inheritSkills === base.inheritSkills;
|
|
48
51
|
case "tools": return arraysEqual(toolList(state.draft), toolList(base));
|
|
49
52
|
case "skills": return arraysEqual(state.draft.skills, base.skills);
|
|
50
53
|
case "prompt": return state.draft.systemPrompt === base.systemPrompt;
|
|
@@ -59,6 +62,9 @@ function resetFieldToBase(field: EditField, state: EditState): void {
|
|
|
59
62
|
case "model": state.draft.model = base.model; break;
|
|
60
63
|
case "fallbackModels": state.draft.fallbackModels = base.fallbackModels ? [...base.fallbackModels] : undefined; break;
|
|
61
64
|
case "thinking": state.draft.thinking = base.thinking; break;
|
|
65
|
+
case "systemPromptMode": state.draft.systemPromptMode = base.systemPromptMode; break;
|
|
66
|
+
case "inheritProjectContext": state.draft.inheritProjectContext = base.inheritProjectContext; break;
|
|
67
|
+
case "inheritSkills": state.draft.inheritSkills = base.inheritSkills; break;
|
|
62
68
|
case "tools": state.draft.tools = base.tools ? [...base.tools] : undefined; state.draft.mcpDirectTools = base.mcpDirectTools ? [...base.mcpDirectTools] : undefined; break;
|
|
63
69
|
case "skills": state.draft.skills = base.skills ? [...base.skills] : undefined; break;
|
|
64
70
|
case "prompt": state.draft.systemPrompt = base.systemPrompt; state.promptEditor = createEditorState(base.systemPrompt); break;
|
|
@@ -83,6 +89,9 @@ function renderFieldValue(field: EditField, state: EditState): string {
|
|
|
83
89
|
case "model": return draft.model ?? "default";
|
|
84
90
|
case "fallbackModels": return draft.fallbackModels && draft.fallbackModels.length > 0 ? draft.fallbackModels.join(", ") : "";
|
|
85
91
|
case "thinking": return draft.thinking ?? "off";
|
|
92
|
+
case "systemPromptMode": return draft.systemPromptMode ?? defaultSystemPromptMode(draft.name);
|
|
93
|
+
case "inheritProjectContext": return draft.inheritProjectContext ? "on" : "off";
|
|
94
|
+
case "inheritSkills": return draft.inheritSkills ? "on" : "off";
|
|
86
95
|
case "tools": return formatTools(draft);
|
|
87
96
|
case "extensions": return draft.extensions !== undefined ? (draft.extensions.length > 0 ? draft.extensions.join(", ") : "") : "(all)";
|
|
88
97
|
case "skills": return draft.skills && draft.skills.length > 0 ? draft.skills.join(", ") : "";
|
|
@@ -101,12 +110,28 @@ function applyFieldValue(field: EditField, state: EditState, value: string): voi
|
|
|
101
110
|
case "description": draft.description = value.trim(); break;
|
|
102
111
|
case "model": draft.model = value.trim() || undefined; break;
|
|
103
112
|
case "fallbackModels": draft.fallbackModels = parseCommaList(value); break;
|
|
113
|
+
case "systemPromptMode": {
|
|
114
|
+
const trimmed = value.trim();
|
|
115
|
+
if (trimmed === "") {
|
|
116
|
+
draft.systemPromptMode = defaultSystemPromptMode(draft.name);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
if (trimmed === "append" || trimmed === "replace") {
|
|
120
|
+
draft.systemPromptMode = trimmed;
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
104
124
|
case "tools": { const parsed = parseTools(value); draft.tools = parsed.tools; draft.mcpDirectTools = parsed.mcp; break; }
|
|
105
125
|
case "extensions": { const trimmed = value.trim(); draft.extensions = trimmed === "(all)" ? undefined : parseCommaList(trimmed) ?? []; break; }
|
|
106
126
|
case "skills": draft.skills = parseCommaList(value); break;
|
|
107
127
|
case "output": { const trimmed = value.trim(); draft.output = trimmed.length > 0 ? trimmed : undefined; break; }
|
|
108
128
|
case "reads": draft.defaultReads = parseCommaList(value); break;
|
|
109
|
-
case "
|
|
129
|
+
case "inheritProjectContext":
|
|
130
|
+
case "inheritSkills":
|
|
131
|
+
case "progress":
|
|
132
|
+
case "interactive":
|
|
133
|
+
case "prompt":
|
|
134
|
+
break;
|
|
110
135
|
}
|
|
111
136
|
}
|
|
112
137
|
|
|
@@ -231,13 +256,19 @@ export function handleEditInput(screen: EditScreen, state: EditState, data: stri
|
|
|
231
256
|
if (data === "m") { openModelPicker(state, models); return { nextScreen: "edit-field" }; }
|
|
232
257
|
if (data === "t") { openThinkingPicker(state); return { nextScreen: "edit-field" }; }
|
|
233
258
|
if (data === "s") { openSkillPicker(state, skills); return { nextScreen: "edit-field" }; }
|
|
234
|
-
if (data === " " && (field === "
|
|
259
|
+
if (data === " " && (field === "inheritProjectContext" || field === "inheritSkills" || field === "progress" || field === "interactive")) {
|
|
260
|
+
if (field === "inheritProjectContext") state.draft.inheritProjectContext = !state.draft.inheritProjectContext;
|
|
261
|
+
if (field === "inheritSkills") state.draft.inheritSkills = !state.draft.inheritSkills;
|
|
262
|
+
if (field === "progress") state.draft.defaultProgress = !state.draft.defaultProgress;
|
|
263
|
+
if (field === "interactive") state.draft.interactive = !state.draft.interactive;
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
235
266
|
if (matchesKey(data, "return")) {
|
|
236
267
|
if (field === "model") { openModelPicker(state, models); return { nextScreen: "edit-field" }; }
|
|
237
268
|
if (field === "thinking") { openThinkingPicker(state); return { nextScreen: "edit-field" }; }
|
|
238
269
|
if (field === "skills") { openSkillPicker(state, skills); return { nextScreen: "edit-field" }; }
|
|
239
270
|
if (field === "prompt") { state.promptEditor = createEditorState(state.draft.systemPrompt ?? ""); return { nextScreen: "edit-prompt" }; }
|
|
240
|
-
if (field === "progress" || field === "interactive") return;
|
|
271
|
+
if (field === "inheritProjectContext" || field === "inheritSkills" || field === "progress" || field === "interactive") return;
|
|
241
272
|
state.fieldMode = "text"; state.fieldEditor = createEditorState(renderFieldValue(field, state)); return { nextScreen: "edit-field" };
|
|
242
273
|
}
|
|
243
274
|
return;
|
|
@@ -304,8 +335,17 @@ export function renderEdit(screen: EditScreen, state: EditState, width: number,
|
|
|
304
335
|
for (let i = 0; i < state.fields.length; i++) {
|
|
305
336
|
const field = state.fields[i]!; if (field === "prompt") break;
|
|
306
337
|
const isFocused = i === state.fieldIndex; const prefix = isFocused ? theme.fg("accent", "▸ ") : " ";
|
|
307
|
-
const
|
|
338
|
+
const fieldLabel = field === "systemPromptMode"
|
|
339
|
+
? "Prompt Mode"
|
|
340
|
+
: field === "inheritProjectContext"
|
|
341
|
+
? "Project Ctx"
|
|
342
|
+
: field === "inheritSkills"
|
|
343
|
+
? "Skills Ctx"
|
|
344
|
+
: `${field[0]!.toUpperCase()}${field.slice(1)}`;
|
|
345
|
+
const rawLabel = pad(`${fieldLabel}:`, labelWidth);
|
|
308
346
|
const labelText = state.overrideBase && !fieldValueMatchesBase(field, state) ? theme.fg("accent", rawLabel) : rawLabel; let valueText = renderFieldValue(field, state);
|
|
347
|
+
if (field === "inheritProjectContext") { const toggle = state.draft.inheritProjectContext ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.inheritProjectContext ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
348
|
+
if (field === "inheritSkills") { const toggle = state.draft.inheritSkills ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.inheritSkills ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
309
349
|
if (field === "progress") { const toggle = state.draft.defaultProgress ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.defaultProgress ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
310
350
|
if (field === "interactive") { const toggle = state.draft.interactive ? theme.fg("success", "[x]") : "[ ]"; valueText = `${toggle} ${state.draft.interactive ? "on" : "off"}`; lines.push(row(` ${prefix}${labelText} ${pad(truncateToWidth(valueText, valueWidth), valueWidth)}`, width, theme)); continue; }
|
|
311
351
|
let displayValue = truncateToWidth(valueText, valueWidth);
|
package/agent-manager-list.ts
CHANGED
|
@@ -200,9 +200,9 @@ export function renderList(
|
|
|
200
200
|
const count = selectionCount(state.selected, agent.id);
|
|
201
201
|
const isShadowed = agent.kind === "agent" && agent.source === "project" && userNames.has(agent.name);
|
|
202
202
|
|
|
203
|
-
const cursorChar = isCursor ? theme.fg("accent", "
|
|
204
|
-
const selectBadge = count >
|
|
205
|
-
const shadowMarker = isShadowed ? theme.fg("warning", "
|
|
203
|
+
const cursorChar = isCursor ? theme.fg("accent", ">") : " ";
|
|
204
|
+
const selectBadge = count > 0 ? theme.fg("accent", String(count).padStart(2)) : " ";
|
|
205
|
+
const shadowMarker = isShadowed ? theme.fg("warning", "!") : " ";
|
|
206
206
|
const prefix = `${cursorChar}${selectBadge}${shadowMarker} `;
|
|
207
207
|
|
|
208
208
|
const modelRaw = agent.kind === "chain" ? `${agent.stepCount ?? 0} steps` : (agent.model ?? "default");
|
package/agent-manager.ts
CHANGED
|
@@ -5,6 +5,9 @@ import type { Component, TUI } from "@mariozechner/pi-tui";
|
|
|
5
5
|
import { matchesKey, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
|
|
6
6
|
import {
|
|
7
7
|
buildBuiltinOverrideConfig,
|
|
8
|
+
defaultInheritProjectContext,
|
|
9
|
+
defaultInheritSkills,
|
|
10
|
+
defaultSystemPromptMode,
|
|
8
11
|
discoverAgentsAll,
|
|
9
12
|
removeBuiltinAgentOverride,
|
|
10
13
|
saveBuiltinAgentOverride,
|
|
@@ -40,7 +43,7 @@ interface NameInputState { mode: "new-agent" | "clone-agent" | "clone-chain" | "
|
|
|
40
43
|
interface StatusMessage { text: string; type: "error" | "info"; }
|
|
41
44
|
interface OverrideScopeState { selectedScope: "user" | "project"; allowProject: boolean; }
|
|
42
45
|
|
|
43
|
-
const BUILTIN_OVERRIDE_FIELDS: EditField[] = ["model", "fallbackModels", "thinking", "tools", "skills", "prompt"];
|
|
46
|
+
const BUILTIN_OVERRIDE_FIELDS: EditField[] = ["model", "fallbackModels", "thinking", "systemPromptMode", "inheritProjectContext", "inheritSkills", "tools", "skills", "prompt"];
|
|
44
47
|
|
|
45
48
|
function cloneConfig(config: AgentConfig): AgentConfig {
|
|
46
49
|
return {
|
|
@@ -130,6 +133,9 @@ export class AgentManagerComponent implements Component {
|
|
|
130
133
|
model: entry.config.model,
|
|
131
134
|
fallbackModels: entry.config.fallbackModels ? [...entry.config.fallbackModels] : undefined,
|
|
132
135
|
thinking: entry.config.thinking,
|
|
136
|
+
systemPromptMode: entry.config.systemPromptMode,
|
|
137
|
+
inheritProjectContext: entry.config.inheritProjectContext,
|
|
138
|
+
inheritSkills: entry.config.inheritSkills,
|
|
133
139
|
systemPrompt: entry.config.systemPrompt,
|
|
134
140
|
skills: entry.config.skills ? [...entry.config.skills] : undefined,
|
|
135
141
|
tools: entry.config.tools ? [...entry.config.tools] : undefined,
|
|
@@ -233,6 +239,16 @@ export class AgentManagerComponent implements Component {
|
|
|
233
239
|
filePath = path.join(dir, `${edit.draft.name}.md`);
|
|
234
240
|
if (fs.existsSync(filePath)) { edit.error = "An agent with that name already exists."; return false; }
|
|
235
241
|
fs.mkdirSync(dir, { recursive: true });
|
|
242
|
+
} else if (edit.draft.name !== entry.config.name) {
|
|
243
|
+
const nextPath = path.join(path.dirname(filePath), `${edit.draft.name}.md`);
|
|
244
|
+
if (nextPath !== filePath && fs.existsSync(nextPath)) {
|
|
245
|
+
edit.error = "An agent with that name already exists.";
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
if (nextPath !== filePath) {
|
|
249
|
+
fs.renameSync(filePath, nextPath);
|
|
250
|
+
filePath = nextPath;
|
|
251
|
+
}
|
|
236
252
|
}
|
|
237
253
|
try { const toSave: AgentConfig = { ...edit.draft, filePath }; fs.writeFileSync(filePath, serializeAgent(toSave), "utf-8"); entry.config = cloneConfig(toSave); entry.isNew = false; edit.error = undefined; return true; }
|
|
238
254
|
catch (err) { edit.error = err instanceof Error ? err.message : "Failed to save agent."; return false; }
|
|
@@ -349,7 +365,17 @@ export class AgentManagerComponent implements Component {
|
|
|
349
365
|
baseConfig = cloneConfig(sourceEntry.config);
|
|
350
366
|
} else {
|
|
351
367
|
const templateConfig = state.template?.config ?? {};
|
|
352
|
-
baseConfig = {
|
|
368
|
+
baseConfig = {
|
|
369
|
+
name,
|
|
370
|
+
description: "Describe this agent",
|
|
371
|
+
systemPrompt: "",
|
|
372
|
+
systemPromptMode: defaultSystemPromptMode(name),
|
|
373
|
+
inheritProjectContext: defaultInheritProjectContext(name),
|
|
374
|
+
inheritSkills: defaultInheritSkills(),
|
|
375
|
+
source: state.scope,
|
|
376
|
+
filePath: "",
|
|
377
|
+
...templateConfig,
|
|
378
|
+
};
|
|
353
379
|
}
|
|
354
380
|
const dir = state.scope === "project" ? this.agentData.projectDir : this.agentData.userDir;
|
|
355
381
|
if (!dir) { state.error = "Project agents directory not found."; this.tui.requestRender(); return; }
|
package/agent-serializer.ts
CHANGED
|
@@ -8,6 +8,9 @@ export const KNOWN_FIELDS = new Set([
|
|
|
8
8
|
"model",
|
|
9
9
|
"fallbackModels",
|
|
10
10
|
"thinking",
|
|
11
|
+
"systemPromptMode",
|
|
12
|
+
"inheritProjectContext",
|
|
13
|
+
"inheritSkills",
|
|
11
14
|
"skill",
|
|
12
15
|
"skills",
|
|
13
16
|
"extensions",
|
|
@@ -40,6 +43,9 @@ export function serializeAgent(config: AgentConfig): string {
|
|
|
40
43
|
const fallbackModelsValue = joinComma(config.fallbackModels);
|
|
41
44
|
if (fallbackModelsValue) lines.push(`fallbackModels: ${fallbackModelsValue}`);
|
|
42
45
|
if (config.thinking && config.thinking !== "off") lines.push(`thinking: ${config.thinking}`);
|
|
46
|
+
lines.push(`systemPromptMode: ${config.systemPromptMode}`);
|
|
47
|
+
lines.push(`inheritProjectContext: ${config.inheritProjectContext ? "true" : "false"}`);
|
|
48
|
+
lines.push(`inheritSkills: ${config.inheritSkills ? "true" : "false"}`);
|
|
43
49
|
|
|
44
50
|
const skillsValue = joinComma(config.skills);
|
|
45
51
|
if (skillsValue) lines.push(`skills: ${skillsValue}`);
|