@gotgenes/pi-subagents 12.0.0 → 13.0.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 +22 -0
- package/dist/public.d.ts +1 -3
- package/docs/architecture/architecture.md +28 -32
- package/docs/plans/0264-remove-extension-lifecycle-control.md +275 -0
- package/docs/plans/0272-export-workspace-collaborator-types.md +147 -0
- package/docs/retro/0264-remove-extension-lifecycle-control.md +48 -0
- package/docs/retro/0272-export-workspace-collaborator-types.md +38 -0
- package/package.json +1 -1
- package/src/config/agent-types.ts +0 -2
- package/src/config/custom-agents.ts +0 -30
- package/src/config/default-agents.ts +1 -7
- package/src/config/invocation-config.ts +0 -3
- package/src/index.ts +0 -2
- package/src/lifecycle/agent-manager.ts +0 -2
- package/src/lifecycle/agent-runner.ts +6 -14
- package/src/lifecycle/agent.ts +0 -4
- package/src/service/service-adapter.ts +0 -1
- package/src/service/service.ts +20 -9
- package/src/session/prompts.ts +2 -23
- package/src/session/session-config.ts +2 -37
- package/src/tools/agent-tool.ts +0 -5
- package/src/tools/background-spawner.ts +0 -1
- package/src/tools/foreground-runner.ts +0 -1
- package/src/tools/spawn-config.ts +0 -4
- package/src/types.ts +0 -7
- package/src/ui/agent-config-editor.ts +0 -5
- package/src/ui/agent-creation-wizard.ts +0 -4
- package/src/ui/display.ts +1 -2
- package/src/session/safe-fs.ts +0 -45
- package/src/session/skill-loader.ts +0 -104
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 264
|
|
3
|
+
issue_title: "Remove isolated / extensions:false / noSkills from core"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Retro: #264 — Remove isolated / extensions:false / noSkills from core
|
|
7
|
+
|
|
8
|
+
## Stage: Planning (2026-05-30T00:09:21Z)
|
|
9
|
+
|
|
10
|
+
### Session summary
|
|
11
|
+
|
|
12
|
+
Planned Phase 16, Step 4: removing the extension-lifecycle-control axis (`isolated`, `extensions: false`, `noSkills`) from the pi-subagents core per ADR 0002.
|
|
13
|
+
Confirmed all three prerequisite Phase 16 steps (#261, #262, #263) are closed, so the explicit "deny-at-use" dependency is satisfied.
|
|
14
|
+
Produced a four-cycle TDD plan (`isolated` → `extensions` → `skills`/`noSkills`/preload → docs) and committed it.
|
|
15
|
+
|
|
16
|
+
### Observations
|
|
17
|
+
|
|
18
|
+
- Scope expansion decided with the user: the issue names only `isolated` / `extensions: false` / `noSkills`, but `noSkills` is the single mechanism behind **both** skill-restriction modes (`skills: false` and `skills: string[]` preload).
|
|
19
|
+
Removing `noSkills` without also removing `AgentConfig.skills` would leave a field that silently stops restricting.
|
|
20
|
+
Chose the **collapse-skills-fully** option (symmetric with `extensions`): retire `AgentConfig.skills`, `skill-loader.ts`, `safe-fs.ts` (sole consumer was the skill loader), `preloadSkills`, `PromptExtras`, and `extras.skillBlocks`.
|
|
21
|
+
Children always inherit Pi's full skill system — the `skills: true` path.
|
|
22
|
+
- The recursion guard's `if (cfg.extensions)` gate is removed in the `extensions` cycle (cycle 2), since `SessionConfig.extensions` disappears there.
|
|
23
|
+
A guard-always-runs assertion replaces the deleted "extensions: false skips the filter entirely" test.
|
|
24
|
+
- This is a **breaking** change (`feat!:`): public `SpawnOptions.isolated` and the `isolated:` / `extensions:` / `skills:` custom-agent frontmatter keys are removed.
|
|
25
|
+
Custom agents with legacy frontmatter will silently ignore those keys (matches the Phase 14 precedent for `disallowed_tools`).
|
|
26
|
+
- Sequencing note surfaced to the user: some `isolated`-threading removed here (`RunOptions.isolated`, `Agent.run()` plumbing) is structure that Step 5 (#265, dissolve the runner) will delete anyway — small, unavoidable, and #265 depends on this step, so no reordering benefit.
|
|
27
|
+
- Helper-file churn accepted: `test/helpers/runner-io.ts` is touched in all three removal cycles (one field per cycle); ordering is fixed (`isolated` → `extensions` → `skills`) so no cycle leaves a dangling reference.
|
|
28
|
+
- Doc updates identified: `docs/architecture/architecture.md` (Mermaid session subgraph, directory tree, `SpawnOptions`/`RunOptions` field lists, roadmap status) and the `package-pi-subagents` SKILL.md session-domain row (8 → 6 modules).
|
|
29
|
+
|
|
30
|
+
## Stage: Implementation — TDD (2026-05-30T00:38:00Z)
|
|
31
|
+
|
|
32
|
+
### Session summary
|
|
33
|
+
|
|
34
|
+
Executed all four plan cycles (`isolated` → `extensions` + unconditional guard → `skills`/`noSkills`/preload → docs) as three `feat!:` commits plus one `docs:` commit.
|
|
35
|
+
The extension-lifecycle-control axis and the `skills` curation axis are gone; children always inherit the parent's extensions and full skill system, and the recursion guard is unconditional.
|
|
36
|
+
Test count went 1016 → 951 (−65): deleted `skill-loader.test.ts` and `safe-fs.test.ts`, plus removed isolated/extensions/skills/preload-specific cases; `check`, `lint`, `fallow dead-code`, and `verify:public-types` all green.
|
|
37
|
+
|
|
38
|
+
### Observations
|
|
39
|
+
|
|
40
|
+
- The plan's cycle split held up cleanly.
|
|
41
|
+
The only interleaving friction was `test/config/custom-agents.test.ts`, where `extensions` and `skills` assertions shared the same `it` blocks.
|
|
42
|
+
Handled it by retitling the shared tests to skills-only in cycle 2 (keeping skills compiling/passing), then deleting them in cycle 3 — no dangling references between commits.
|
|
43
|
+
- BSD `sed` (macOS) does not support `\|` alternation in basic regex; the standalone-fixture-line deletions needed `sed -E`.
|
|
44
|
+
Worth remembering for future bulk fixture removals.
|
|
45
|
+
- Two in-scope judgment calls beyond the literal plan: (1) kept the generic tag-rendering test in `result-renderer.test.ts` by swapping the example tag `"isolated"` → `"inherit context"` rather than deleting coverage; (2) removed the now-unused `vi` import from `custom-agents.test.ts` after dropping the extensions-deprecation-warning test.
|
|
46
|
+
- The `spawn-config.test.ts` `agentInvocation` snapshot carried a stale `isolation: undefined` leftover (from the #263 worktree eviction) that `toEqual` had been silently ignoring; removed it alongside `isolated: false` for a clean exact-match assertion.
|
|
47
|
+
- `verify:public-types` confirmed the breaking `SpawnOptions.isolated` removal type-checks against an external consumer; no lockfile changes; `dist/` correctly gitignored after the type-bundle build.
|
|
48
|
+
- Pre-completion reviewer: **PASS** — both acceptance criteria code-verified, all deterministic checks green, 6 Mermaid diagrams render, docs accurate, zero dead code.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
issue: 272
|
|
3
|
+
issue_title: "Export WorkspaceProvider collaborator types by name from the public surface"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Retro: #272 — Export `WorkspaceProvider` collaborator types by name from the public surface
|
|
7
|
+
|
|
8
|
+
## Stage: Planning (2026-05-29T23:23:37Z)
|
|
9
|
+
|
|
10
|
+
### Session summary
|
|
11
|
+
|
|
12
|
+
Planned a purely additive, type-only change to `@gotgenes/pi-subagents`'s public surface: re-export `Workspace`, `WorkspacePrepareContext`, `WorkspaceDisposeOutcome`, and `WorkspaceDisposeResult` by name from `src/service/service.ts`, alongside the already-exported `WorkspaceProvider`.
|
|
13
|
+
The plan bundles the source change with extending the `verify:public-types` harness (symbol guard + probe consumer) into a single `feat:` commit, since a packaged-tarball probe cannot import names the entry does not yet export.
|
|
14
|
+
|
|
15
|
+
### Observations
|
|
16
|
+
|
|
17
|
+
- The issue's "Proposed change" was unambiguous, so the `ask-user` design gate was skipped.
|
|
18
|
+
|
|
19
|
+
## Stage: Implementation — Build (2026-05-29T23:30:13Z)
|
|
20
|
+
|
|
21
|
+
### Session summary
|
|
22
|
+
|
|
23
|
+
Implemented the single plan step: widened the `#src/lifecycle/workspace` import in `src/service/service.ts` to include all four collaborator types and added them to the `export type { … }` block, updating the standing comment from a future-tracking reference to a present-tense description.
|
|
24
|
+
Extended `scripts/verify-public-types.sh` — the symbol guard loop and inline `probe.ts` — to assert all four new names, confirmed the harness fails (red) before the source change and passes (green) after.
|
|
25
|
+
Also updated two stale forward-references to #272 in `docs/architecture/architecture.md` (flagged by the pre-completion reviewer).
|
|
26
|
+
|
|
27
|
+
### Observations
|
|
28
|
+
|
|
29
|
+
- Red→green cycle through the type-level harness (`verify:public-types`) rather than vitest, exactly as planned.
|
|
30
|
+
- No rollup config change was needed — `rollup-plugin-dts` carries through whatever the entry exports; the symbol guard and `#src` self-containment guard both stayed green.
|
|
31
|
+
- The symbol guard already found the names present in the bundle (declared but not exported); the probe's type-check was the real red signal.
|
|
32
|
+
- Pre-completion reviewer: WARN — two stale forward-references to #272 in `docs/architecture/architecture.md`; both fixed in a follow-up `docs:` commit before shipping.
|
|
33
|
+
- No new vitest cycle: the re-exports are type-only and erase at runtime.
|
|
34
|
+
The red→green loop lives in the type-level `verify:public-types` harness, not the runtime suite — this is closer to a `/build-plan` shape than a code TDD cycle, but it still has a clean red→green via the probe consumer.
|
|
35
|
+
- The four interfaces already exist in `src/lifecycle/workspace.ts` with correct shapes; only re-exporting is in scope.
|
|
36
|
+
- `rollup.dts.config.mjs` needs no change — `WorkspaceProvider` already pulls the four collaborator declarations into the bundle by reference, so adding named exports keeps the `grep '#src'` self-containment guard green.
|
|
37
|
+
- A standing comment in `service.ts` ("Named re-exports … tracked in #272") goes stale on landing — the plan updates it in the same step.
|
|
38
|
+
- The downstream simplification in `@gotgenes/pi-subagents-worktrees` (swap indexed-access aliases for named imports, bump the dependency) is deferred until a `pi-subagents` release carries these exports — consistent with the registry-consumption model settled in #270.
|
package/package.json
CHANGED
|
@@ -114,8 +114,6 @@ export class AgentTypeRegistry implements AgentConfigLookup {
|
|
|
114
114
|
displayName: "Agent",
|
|
115
115
|
description: "General-purpose agent for complex, multi-step tasks",
|
|
116
116
|
builtinToolNames: BUILTIN_TOOL_NAMES,
|
|
117
|
-
extensions: true,
|
|
118
|
-
skills: true,
|
|
119
117
|
systemPrompt: "",
|
|
120
118
|
promptMode: "append",
|
|
121
119
|
};
|
|
@@ -58,8 +58,6 @@ function loadFromDir(dir: string, agents: Map<string, AgentConfig>, source: "pro
|
|
|
58
58
|
displayName: str(fm.display_name),
|
|
59
59
|
description: str(fm.description) ?? name,
|
|
60
60
|
builtinToolNames: csvList(fm.tools, BUILTIN_TOOL_NAMES),
|
|
61
|
-
extensions: resolveBoolExtensions(fm.extensions ?? fm.inherit_extensions),
|
|
62
|
-
skills: inheritField(fm.skills ?? fm.inherit_skills),
|
|
63
61
|
model: str(fm.model),
|
|
64
62
|
thinking: str(fm.thinking) as ThinkingLevel | undefined,
|
|
65
63
|
maxTurns: nonNegativeInt(fm.max_turns),
|
|
@@ -67,7 +65,6 @@ function loadFromDir(dir: string, agents: Map<string, AgentConfig>, source: "pro
|
|
|
67
65
|
promptMode: fm.prompt_mode === "append" ? "append" : "replace",
|
|
68
66
|
inheritContext: fm.inherit_context != null ? fm.inherit_context === true : undefined,
|
|
69
67
|
runInBackground: fm.run_in_background != null ? fm.run_in_background === true : undefined,
|
|
70
|
-
isolated: fm.isolated != null ? fm.isolated === true : undefined,
|
|
71
68
|
enabled: fm.enabled !== false, // default true; explicitly false disables
|
|
72
69
|
source,
|
|
73
70
|
});
|
|
@@ -107,30 +104,3 @@ function csvList(val: unknown, defaults: string[]): string[] {
|
|
|
107
104
|
if (val === undefined || val === null) return defaults;
|
|
108
105
|
return parseCsvField(val) ?? [];
|
|
109
106
|
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Resolve the `extensions` field to a boolean.
|
|
113
|
-
* CSV/array values (legacy allowlist syntax) are coerced to `true` with a warning.
|
|
114
|
-
*/
|
|
115
|
-
function resolveBoolExtensions(val: unknown): boolean {
|
|
116
|
-
const result = inheritField(val);
|
|
117
|
-
if (Array.isArray(result)) {
|
|
118
|
-
console.warn(
|
|
119
|
-
"[pi-subagents] extensions allowlist syntax is deprecated — treating as \"true\" (inherit all).\n" +
|
|
120
|
-
"Use \"permission:\" frontmatter in pi-permission-system for per-tool access control.",
|
|
121
|
-
);
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
return result;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* Parse an inherit field (extensions, skills).
|
|
129
|
-
* omitted/true → true (inherit all); false/"none"/empty → false; csv → listed names.
|
|
130
|
-
*/
|
|
131
|
-
function inheritField(val: unknown): true | string[] | false {
|
|
132
|
-
if (val === undefined || val === null || val === true) return true;
|
|
133
|
-
if (val === false || val === "none") return false;
|
|
134
|
-
const items = csvList(val, []);
|
|
135
|
-
return items.length > 0 ? items : false;
|
|
136
|
-
}
|
|
@@ -16,10 +16,8 @@ export const DEFAULT_AGENTS: Map<string, AgentConfig> = new Map([
|
|
|
16
16
|
displayName: "Agent",
|
|
17
17
|
description: "General-purpose agent for complex, multi-step tasks",
|
|
18
18
|
// builtinToolNames omitted — means "all available tools" (resolved at lookup time)
|
|
19
|
-
// inheritContext / runInBackground
|
|
19
|
+
// inheritContext / runInBackground omitted — strategy fields, callers decide per-call.
|
|
20
20
|
// Setting them to false would lock callsite intent (see resolveAgentInvocationConfig in invocation-config.ts).
|
|
21
|
-
extensions: true,
|
|
22
|
-
skills: true,
|
|
23
21
|
systemPrompt: "",
|
|
24
22
|
promptMode: "append",
|
|
25
23
|
isDefault: true,
|
|
@@ -32,8 +30,6 @@ export const DEFAULT_AGENTS: Map<string, AgentConfig> = new Map([
|
|
|
32
30
|
displayName: "Explore",
|
|
33
31
|
description: "Fast codebase exploration agent (read-only)",
|
|
34
32
|
builtinToolNames: READ_ONLY_TOOLS,
|
|
35
|
-
extensions: true,
|
|
36
|
-
skills: true,
|
|
37
33
|
model: "anthropic/claude-haiku-4-5-20251001",
|
|
38
34
|
systemPrompt: `# CRITICAL: READ-ONLY MODE - NO FILE MODIFICATIONS
|
|
39
35
|
You are a file search specialist. You excel at thoroughly navigating and exploring codebases.
|
|
@@ -74,8 +70,6 @@ Use Bash ONLY for read-only operations: ls, git status, git log, git diff, find,
|
|
|
74
70
|
displayName: "Plan",
|
|
75
71
|
description: "Software architect for implementation planning (read-only)",
|
|
76
72
|
builtinToolNames: READ_ONLY_TOOLS,
|
|
77
|
-
extensions: true,
|
|
78
|
-
skills: true,
|
|
79
73
|
systemPrompt: `# CRITICAL: READ-ONLY MODE - NO FILE MODIFICATIONS
|
|
80
74
|
You are a software architect and planning specialist.
|
|
81
75
|
Your role is EXCLUSIVELY to explore the codebase and design implementation plans.
|
|
@@ -6,7 +6,6 @@ interface AgentInvocationParams {
|
|
|
6
6
|
max_turns?: number;
|
|
7
7
|
run_in_background?: boolean;
|
|
8
8
|
inherit_context?: boolean;
|
|
9
|
-
isolated?: boolean;
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
export function resolveAgentInvocationConfig(
|
|
@@ -19,7 +18,6 @@ export function resolveAgentInvocationConfig(
|
|
|
19
18
|
maxTurns?: number;
|
|
20
19
|
inheritContext: boolean;
|
|
21
20
|
runInBackground: boolean;
|
|
22
|
-
isolated: boolean;
|
|
23
21
|
} {
|
|
24
22
|
return {
|
|
25
23
|
modelInput: agentConfig?.model ?? params.model,
|
|
@@ -28,6 +26,5 @@ export function resolveAgentInvocationConfig(
|
|
|
28
26
|
maxTurns: agentConfig?.maxTurns ?? params.max_turns,
|
|
29
27
|
inheritContext: agentConfig?.inheritContext ?? params.inherit_context ?? false,
|
|
30
28
|
runInBackground: agentConfig?.runInBackground ?? params.run_in_background ?? false,
|
|
31
|
-
isolated: agentConfig?.isolated ?? params.isolated ?? false,
|
|
32
29
|
};
|
|
33
30
|
}
|
package/src/index.ts
CHANGED
|
@@ -38,7 +38,6 @@ import { detectEnv } from "#src/session/env";
|
|
|
38
38
|
import { resolveModel } from "#src/session/model-resolver";
|
|
39
39
|
import { buildAgentPrompt } from "#src/session/prompts";
|
|
40
40
|
import { deriveSubagentSessionDir } from "#src/session/session-dir";
|
|
41
|
-
import { preloadSkills } from "#src/session/skill-loader";
|
|
42
41
|
import { SettingsManager } from "#src/settings";
|
|
43
42
|
import { AgentTool } from "#src/tools/agent-tool";
|
|
44
43
|
import { GetResultTool } from "#src/tools/get-result-tool";
|
|
@@ -143,7 +142,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
143
142
|
createSettingsManager: (cwd, dir) => SdkSettingsManager.create(cwd, dir),
|
|
144
143
|
createSession: (opts) => createAgentSession(opts as any),
|
|
145
144
|
assemblerIO: {
|
|
146
|
-
preloadSkills,
|
|
147
145
|
buildAgentPrompt,
|
|
148
146
|
},
|
|
149
147
|
},
|
|
@@ -41,7 +41,6 @@ export interface AgentSpawnConfig {
|
|
|
41
41
|
description: string;
|
|
42
42
|
model?: Model<any>;
|
|
43
43
|
maxTurns?: number;
|
|
44
|
-
isolated?: boolean;
|
|
45
44
|
inheritContext?: boolean;
|
|
46
45
|
thinkingLevel?: ThinkingLevel;
|
|
47
46
|
isBackground?: boolean;
|
|
@@ -149,7 +148,6 @@ export class AgentManager {
|
|
|
149
148
|
prompt,
|
|
150
149
|
model: options.model,
|
|
151
150
|
maxTurns: options.maxTurns,
|
|
152
|
-
isolated: options.isolated,
|
|
153
151
|
thinkingLevel: options.thinkingLevel,
|
|
154
152
|
parentSession: options.parentSession,
|
|
155
153
|
signal: options.signal,
|
|
@@ -55,8 +55,6 @@ export interface SessionManagerLike {
|
|
|
55
55
|
export interface ResourceLoaderOptions {
|
|
56
56
|
cwd: string;
|
|
57
57
|
agentDir: string;
|
|
58
|
-
noExtensions?: boolean;
|
|
59
|
-
noSkills?: boolean;
|
|
60
58
|
noPromptTemplates?: boolean;
|
|
61
59
|
noThemes?: boolean;
|
|
62
60
|
noContextFiles?: boolean;
|
|
@@ -148,7 +146,6 @@ export interface RunOptions {
|
|
|
148
146
|
model?: Model<any>;
|
|
149
147
|
maxTurns?: number;
|
|
150
148
|
signal?: AbortSignal;
|
|
151
|
-
isolated?: boolean;
|
|
152
149
|
thinkingLevel?: ThinkingLevel;
|
|
153
150
|
/** Called once after session creation - session delivery mechanism. */
|
|
154
151
|
onSessionCreated?: (session: AgentSession) => void;
|
|
@@ -283,7 +280,6 @@ export async function runAgent(
|
|
|
283
280
|
},
|
|
284
281
|
{
|
|
285
282
|
cwd: options.context.cwd,
|
|
286
|
-
isolated: options.isolated,
|
|
287
283
|
model: options.model,
|
|
288
284
|
thinkingLevel: options.thinkingLevel,
|
|
289
285
|
},
|
|
@@ -294,17 +290,15 @@ export async function runAgent(
|
|
|
294
290
|
|
|
295
291
|
const agentDir = deps.io.getAgentDir();
|
|
296
292
|
|
|
297
|
-
//
|
|
293
|
+
// Children always load the parent's extensions and skills.
|
|
298
294
|
// Suppress AGENTS.md/CLAUDE.md and APPEND_SYSTEM.md - upstream's
|
|
299
295
|
// buildSystemPrompt() re-appends both AFTER systemPromptOverride, which
|
|
300
|
-
// would defeat prompt_mode: replace
|
|
296
|
+
// would defeat prompt_mode: replace. Parent context, if
|
|
301
297
|
// wanted, reaches the subagent via prompt_mode: append (parentSystemPrompt
|
|
302
298
|
// is embedded in systemPromptOverride) or inherit_context (conversation).
|
|
303
299
|
const loader = deps.io.createResourceLoader({
|
|
304
300
|
cwd: cfg.effectiveCwd,
|
|
305
301
|
agentDir,
|
|
306
|
-
noExtensions: !cfg.extensions,
|
|
307
|
-
noSkills: cfg.noSkills,
|
|
308
302
|
noPromptTemplates: true,
|
|
309
303
|
noThemes: true,
|
|
310
304
|
noContextFiles: true,
|
|
@@ -348,12 +342,10 @@ export async function runAgent(
|
|
|
348
342
|
|
|
349
343
|
// Apply recursion guard: remove our own tools from the child's active set.
|
|
350
344
|
// Runs after bindExtensions so extension-registered tools are included in the
|
|
351
|
-
// post-bind active set.
|
|
352
|
-
//
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
session.setActiveToolsByName(filtered);
|
|
356
|
-
}
|
|
345
|
+
// post-bind active set. Unconditional: children always load the parent's
|
|
346
|
+
// extensions, so the guard must always strip our dispatch tools.
|
|
347
|
+
const filtered = filterActiveTools(session.getActiveToolNames());
|
|
348
|
+
session.setActiveToolsByName(filtered);
|
|
357
349
|
|
|
358
350
|
options.onSessionCreated?.(session);
|
|
359
351
|
|
package/src/lifecycle/agent.ts
CHANGED
|
@@ -81,7 +81,6 @@ export interface AgentInit {
|
|
|
81
81
|
prompt?: string;
|
|
82
82
|
model?: Model<any>;
|
|
83
83
|
maxTurns?: number;
|
|
84
|
-
isolated?: boolean;
|
|
85
84
|
thinkingLevel?: ThinkingLevel;
|
|
86
85
|
parentSession?: ParentSessionInfo;
|
|
87
86
|
isBackground?: boolean;
|
|
@@ -140,7 +139,6 @@ export class Agent {
|
|
|
140
139
|
private readonly _prompt?: string;
|
|
141
140
|
private readonly _model?: Model<any>;
|
|
142
141
|
private readonly _maxTurns?: number;
|
|
143
|
-
private readonly _isolated?: boolean;
|
|
144
142
|
private readonly _thinkingLevel?: ThinkingLevel;
|
|
145
143
|
private readonly _parentSession?: ParentSessionInfo;
|
|
146
144
|
private readonly _signal?: AbortSignal;
|
|
@@ -198,7 +196,6 @@ export class Agent {
|
|
|
198
196
|
this._prompt = init.prompt;
|
|
199
197
|
this._model = init.model;
|
|
200
198
|
this._maxTurns = init.maxTurns;
|
|
201
|
-
this._isolated = init.isolated;
|
|
202
199
|
this._thinkingLevel = init.thinkingLevel;
|
|
203
200
|
this._parentSession = init.parentSession;
|
|
204
201
|
this._signal = init.signal;
|
|
@@ -261,7 +258,6 @@ export class Agent {
|
|
|
261
258
|
maxTurns: this._maxTurns,
|
|
262
259
|
defaultMaxTurns: runConfig?.defaultMaxTurns,
|
|
263
260
|
graceTurns: runConfig?.graceTurns,
|
|
264
|
-
isolated: this._isolated,
|
|
265
261
|
thinkingLevel: this._thinkingLevel,
|
|
266
262
|
signal: this.abortController.signal,
|
|
267
263
|
onSessionCreated: (session) => {
|
|
@@ -66,7 +66,6 @@ export class SubagentsServiceAdapter implements SubagentsService {
|
|
|
66
66
|
model,
|
|
67
67
|
maxTurns: options?.maxTurns,
|
|
68
68
|
thinkingLevel: options?.thinkingLevel,
|
|
69
|
-
isolated: options?.isolated,
|
|
70
69
|
inheritContext: options?.inheritContext,
|
|
71
70
|
bypassQueue: options?.bypassQueue,
|
|
72
71
|
isBackground,
|
package/src/service/service.ts
CHANGED
|
@@ -10,14 +10,26 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { LifetimeUsage } from "#src/lifecycle/usage";
|
|
13
|
-
import type {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
import type {
|
|
14
|
+
Workspace,
|
|
15
|
+
WorkspaceDisposeOutcome,
|
|
16
|
+
WorkspaceDisposeResult,
|
|
17
|
+
WorkspacePrepareContext,
|
|
18
|
+
WorkspaceProvider,
|
|
19
|
+
} from "#src/lifecycle/workspace";
|
|
20
|
+
|
|
21
|
+
// Generative extension seam (ADR 0002, Phase 16 Step 2). The provider type
|
|
22
|
+
// and all four collaborator types it references are re-exported by name so
|
|
23
|
+
// consumers can import them directly rather than recovering them via
|
|
24
|
+
// indexed-access inference (e.g. `Parameters<WorkspaceProvider["prepare"]>[0]`).
|
|
25
|
+
export type {
|
|
26
|
+
LifetimeUsage,
|
|
27
|
+
Workspace,
|
|
28
|
+
WorkspaceDisposeOutcome,
|
|
29
|
+
WorkspaceDisposeResult,
|
|
30
|
+
WorkspacePrepareContext,
|
|
31
|
+
WorkspaceProvider,
|
|
32
|
+
};
|
|
21
33
|
|
|
22
34
|
export type SubagentStatus =
|
|
23
35
|
| "queued"
|
|
@@ -49,7 +61,6 @@ export interface SpawnOptions {
|
|
|
49
61
|
model?: string;
|
|
50
62
|
maxTurns?: number;
|
|
51
63
|
thinkingLevel?: string;
|
|
52
|
-
isolated?: boolean;
|
|
53
64
|
inheritContext?: boolean;
|
|
54
65
|
foreground?: boolean;
|
|
55
66
|
bypassQueue?: boolean;
|
package/src/session/prompts.ts
CHANGED
|
@@ -5,12 +5,6 @@
|
|
|
5
5
|
import type { EnvInfo } from "#src/session/env";
|
|
6
6
|
import type { AgentPromptConfig } from "#src/types";
|
|
7
7
|
|
|
8
|
-
/** Extra sections to inject into the system prompt (skills, etc.). */
|
|
9
|
-
export interface PromptExtras {
|
|
10
|
-
/** Preloaded skill contents to inject. */
|
|
11
|
-
skillBlocks?: { name: string; content: string }[];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
8
|
/**
|
|
15
9
|
* Build the system prompt for an agent from its config.
|
|
16
10
|
*
|
|
@@ -25,14 +19,12 @@ export interface PromptExtras {
|
|
|
25
19
|
* inherited content so the stable prefix is cacheable by the LLM's KV cache.
|
|
26
20
|
*
|
|
27
21
|
* @param parentSystemPrompt The parent agent's effective system prompt (for append mode).
|
|
28
|
-
* @param extras Optional extra sections to inject (memory, preloaded skills).
|
|
29
22
|
*/
|
|
30
23
|
export function buildAgentPrompt(
|
|
31
24
|
config: AgentPromptConfig,
|
|
32
25
|
cwd: string,
|
|
33
26
|
env: EnvInfo,
|
|
34
27
|
parentSystemPrompt?: string,
|
|
35
|
-
extras?: PromptExtras,
|
|
36
28
|
): string {
|
|
37
29
|
const activeAgentTag = `<active_agent name="${config.name}"/>\n\n`;
|
|
38
30
|
|
|
@@ -41,18 +33,6 @@ Working directory: ${cwd}
|
|
|
41
33
|
${env.isGitRepo ? `Git repository: yes\nBranch: ${env.branch}` : "Not a git repository"}
|
|
42
34
|
Platform: ${env.platform}`;
|
|
43
35
|
|
|
44
|
-
// Build optional extras suffix
|
|
45
|
-
const extraSections: string[] = [];
|
|
46
|
-
if (extras?.skillBlocks?.length) {
|
|
47
|
-
for (const skill of extras.skillBlocks) {
|
|
48
|
-
extraSections.push(
|
|
49
|
-
`\n# Preloaded Skill: ${skill.name}\n${skill.content}`,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
const extrasSuffix =
|
|
54
|
-
extraSections.length > 0 ? "\n\n" + extraSections.join("\n") : "";
|
|
55
|
-
|
|
56
36
|
if (config.promptMode === "append") {
|
|
57
37
|
const identity = parentSystemPrompt ?? genericBase;
|
|
58
38
|
|
|
@@ -85,8 +65,7 @@ You are operating as a sub-agent invoked to handle a specific task.
|
|
|
85
65
|
"\n\n" +
|
|
86
66
|
activeAgentTag +
|
|
87
67
|
envBlock +
|
|
88
|
-
customSection
|
|
89
|
-
extrasSuffix
|
|
68
|
+
customSection
|
|
90
69
|
);
|
|
91
70
|
}
|
|
92
71
|
|
|
@@ -97,7 +76,7 @@ You have been invoked to handle a specific task autonomously.
|
|
|
97
76
|
${envBlock}`;
|
|
98
77
|
|
|
99
78
|
return (
|
|
100
|
-
activeAgentTag + replaceHeader + "\n\n" + config.systemPrompt
|
|
79
|
+
activeAgentTag + replaceHeader + "\n\n" + config.systemPrompt
|
|
101
80
|
);
|
|
102
81
|
}
|
|
103
82
|
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
|
|
13
13
|
import type { AgentConfigLookup } from "#src/config/agent-types";
|
|
14
14
|
import type { EnvInfo } from "#src/session/env";
|
|
15
|
-
import type { PromptExtras } from "#src/session/prompts";
|
|
16
|
-
import type { PreloadedSkill } from "#src/session/skill-loader";
|
|
17
15
|
import type { AgentPromptConfig, SubagentType, ThinkingLevel } from "#src/types";
|
|
18
16
|
|
|
19
17
|
// ── Public interfaces ────────────────────────────────────────────────────────
|
|
@@ -21,19 +19,17 @@ import type { AgentPromptConfig, SubagentType, ThinkingLevel } from "#src/types"
|
|
|
21
19
|
/**
|
|
22
20
|
* IO collaborators injected into `assembleSessionConfig`.
|
|
23
21
|
*
|
|
24
|
-
* Bundling the
|
|
22
|
+
* Bundling the IO-touching (or promptly testable) function into a single
|
|
25
23
|
* interface keeps the assembler free of direct module imports and makes it
|
|
26
24
|
* trivially testable without `vi.mock()` — callers inject real implementations
|
|
27
25
|
* at the edge (`agent-runner.ts`) or stubs in tests.
|
|
28
26
|
*/
|
|
29
27
|
export interface AssemblerIO {
|
|
30
|
-
preloadSkills: (skills: string[], cwd: string) => PreloadedSkill[];
|
|
31
28
|
buildAgentPrompt: (
|
|
32
29
|
config: AgentPromptConfig,
|
|
33
30
|
cwd: string,
|
|
34
31
|
env: EnvInfo,
|
|
35
32
|
parentPrompt?: string,
|
|
36
|
-
extras?: PromptExtras,
|
|
37
33
|
) => string;
|
|
38
34
|
}
|
|
39
35
|
|
|
@@ -67,8 +63,6 @@ export interface AssemblerContext {
|
|
|
67
63
|
export interface AssemblerOptions {
|
|
68
64
|
/** Override working directory (e.g. for worktree isolation). */
|
|
69
65
|
cwd?: string;
|
|
70
|
-
/** When true, forces extensions and skills to false. */
|
|
71
|
-
isolated?: boolean;
|
|
72
66
|
/** Explicit model override — wins over agentConfig.model and parent model. */
|
|
73
67
|
model?: unknown;
|
|
74
68
|
/** Explicit thinking level — wins over agentConfig.thinking. */
|
|
@@ -87,8 +81,6 @@ export interface SessionConfig {
|
|
|
87
81
|
systemPrompt: string;
|
|
88
82
|
/** Built-in tool name allowlist for this agent type. */
|
|
89
83
|
toolNames: string[];
|
|
90
|
-
/** Resolved extensions setting: true = inherit all, false = none. */
|
|
91
|
-
extensions: boolean;
|
|
92
84
|
/**
|
|
93
85
|
* Resolved model instance (undefined → use parent model as passed to SDK).
|
|
94
86
|
* Opaque handle — the assembler passes it through without inspection.
|
|
@@ -97,10 +89,6 @@ export interface SessionConfig {
|
|
|
97
89
|
model: unknown;
|
|
98
90
|
/** Resolved thinking level (undefined → inherit from session). */
|
|
99
91
|
thinkingLevel: ThinkingLevel | undefined;
|
|
100
|
-
/** Whether to skip skill loading in the resource loader (`noSkills` flag). */
|
|
101
|
-
noSkills: boolean;
|
|
102
|
-
/** Prompt extras (memory block, preloaded skill blocks) — for transparency. */
|
|
103
|
-
extras: PromptExtras;
|
|
104
92
|
/** Per-agent configured max turns (from agentConfig.maxTurns). */
|
|
105
93
|
agentMaxTurns: number | undefined;
|
|
106
94
|
}
|
|
@@ -150,7 +138,7 @@ function resolveDefaultModel(
|
|
|
150
138
|
*
|
|
151
139
|
* @param type The subagent type name (case-insensitive registry lookup).
|
|
152
140
|
* @param ctx Narrow context from the parent session.
|
|
153
|
-
* @param options Per-call overrides (cwd,
|
|
141
|
+
* @param options Per-call overrides (cwd, model, thinkingLevel).
|
|
154
142
|
* @param env Pre-resolved environment info from `detectEnv()`.
|
|
155
143
|
* @param registry Agent config lookup — provides resolveAgentConfig and getToolNamesForType.
|
|
156
144
|
* @param io IO collaborators (skill loader, memory builder, prompt builder).
|
|
@@ -167,21 +155,6 @@ export function assembleSessionConfig(
|
|
|
167
155
|
|
|
168
156
|
const effectiveCwd = options.cwd ?? ctx.cwd;
|
|
169
157
|
|
|
170
|
-
// Resolve extensions/skills: isolated overrides to false
|
|
171
|
-
const extensions = options.isolated ? false : agentConfig.extensions;
|
|
172
|
-
const skills = options.isolated ? false : agentConfig.skills;
|
|
173
|
-
|
|
174
|
-
// Build prompt extras (memory, preloaded skills)
|
|
175
|
-
const extras: PromptExtras = {};
|
|
176
|
-
|
|
177
|
-
// Skill preloading: when skills is string[], preload their content into the prompt
|
|
178
|
-
if (Array.isArray(skills)) {
|
|
179
|
-
const loaded = io.preloadSkills(skills, effectiveCwd);
|
|
180
|
-
if (loaded.length > 0) {
|
|
181
|
-
extras.skillBlocks = loaded;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
158
|
const toolNames = registry.getToolNamesForType(type);
|
|
186
159
|
|
|
187
160
|
// Build system prompt from the resolved agent config
|
|
@@ -190,13 +163,8 @@ export function assembleSessionConfig(
|
|
|
190
163
|
effectiveCwd,
|
|
191
164
|
env,
|
|
192
165
|
ctx.parentSystemPrompt,
|
|
193
|
-
extras,
|
|
194
166
|
);
|
|
195
167
|
|
|
196
|
-
// noSkills: when we've already preloaded skills into the prompt, or skills = false,
|
|
197
|
-
// tell the resource loader not to load them again.
|
|
198
|
-
const noSkills = skills === false || Array.isArray(skills);
|
|
199
|
-
|
|
200
168
|
// Model resolution: explicit option > config model string > parent model
|
|
201
169
|
const model =
|
|
202
170
|
options.model ??
|
|
@@ -212,11 +180,8 @@ export function assembleSessionConfig(
|
|
|
212
180
|
effectiveCwd,
|
|
213
181
|
systemPrompt,
|
|
214
182
|
toolNames,
|
|
215
|
-
extensions,
|
|
216
183
|
model,
|
|
217
184
|
thinkingLevel,
|
|
218
|
-
noSkills,
|
|
219
|
-
extras,
|
|
220
185
|
agentMaxTurns,
|
|
221
186
|
};
|
|
222
187
|
}
|
package/src/tools/agent-tool.ts
CHANGED
|
@@ -220,11 +220,6 @@ Guidelines:
|
|
|
220
220
|
description: "Optional agent ID to resume from. Continues from previous context.",
|
|
221
221
|
}),
|
|
222
222
|
),
|
|
223
|
-
isolated: Type.Optional(
|
|
224
|
-
Type.Boolean({
|
|
225
|
-
description: "If true, agent gets no extension/MCP tools — only built-in tools.",
|
|
226
|
-
}),
|
|
227
|
-
),
|
|
228
223
|
inherit_context: Type.Optional(
|
|
229
224
|
Type.Boolean({
|
|
230
225
|
description:
|
|
@@ -48,7 +48,6 @@ export function spawnBackground(
|
|
|
48
48
|
description: execution.description,
|
|
49
49
|
model: execution.model,
|
|
50
50
|
maxTurns: execution.effectiveMaxTurns,
|
|
51
|
-
isolated: execution.isolated,
|
|
52
51
|
inheritContext: execution.inheritContext,
|
|
53
52
|
thinkingLevel: execution.thinking,
|
|
54
53
|
isBackground: true,
|
|
@@ -102,7 +102,6 @@ export async function runForeground(
|
|
|
102
102
|
description: execution.description,
|
|
103
103
|
model: execution.model,
|
|
104
104
|
maxTurns: execution.effectiveMaxTurns,
|
|
105
|
-
isolated: execution.isolated,
|
|
106
105
|
inheritContext: execution.inheritContext,
|
|
107
106
|
thinkingLevel: execution.thinking,
|
|
108
107
|
invocation: execution.agentInvocation,
|
|
@@ -43,7 +43,6 @@ export interface SpawnExecution {
|
|
|
43
43
|
thinking: ThinkingLevel | undefined;
|
|
44
44
|
inheritContext: boolean;
|
|
45
45
|
runInBackground: boolean;
|
|
46
|
-
isolated: boolean;
|
|
47
46
|
agentInvocation: AgentInvocation;
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -102,7 +101,6 @@ export function resolveSpawnConfig(
|
|
|
102
101
|
const thinking = resolvedConfig.thinking;
|
|
103
102
|
const inheritContext = resolvedConfig.inheritContext;
|
|
104
103
|
const runInBackground = resolvedConfig.runInBackground;
|
|
105
|
-
const isolated = resolvedConfig.isolated;
|
|
106
104
|
|
|
107
105
|
// Compute display model name (only shown when different from parent)
|
|
108
106
|
const parentModelId = modelInfo.parentModel?.id;
|
|
@@ -120,7 +118,6 @@ export function resolveSpawnConfig(
|
|
|
120
118
|
modelName,
|
|
121
119
|
thinking,
|
|
122
120
|
maxTurns: normalizeMaxTurns(resolvedConfig.maxTurns),
|
|
123
|
-
isolated,
|
|
124
121
|
inheritContext,
|
|
125
122
|
runInBackground,
|
|
126
123
|
};
|
|
@@ -147,7 +144,6 @@ export function resolveSpawnConfig(
|
|
|
147
144
|
thinking,
|
|
148
145
|
inheritContext,
|
|
149
146
|
runInBackground,
|
|
150
|
-
isolated,
|
|
151
147
|
agentInvocation,
|
|
152
148
|
},
|
|
153
149
|
presentation: { modelName, agentTags, detailBase },
|
package/src/types.ts
CHANGED
|
@@ -39,10 +39,6 @@ export interface AgentPromptConfig {
|
|
|
39
39
|
/** Unified agent configuration — used for both default and user-defined agents. */
|
|
40
40
|
export interface AgentConfig extends AgentIdentity, AgentPromptConfig {
|
|
41
41
|
builtinToolNames?: string[];
|
|
42
|
-
/** true = inherit all extensions, false = none */
|
|
43
|
-
extensions: boolean;
|
|
44
|
-
/** true = inherit all, string[] = only listed, false = none */
|
|
45
|
-
skills: true | string[] | false;
|
|
46
42
|
model?: string;
|
|
47
43
|
thinking?: ThinkingLevel;
|
|
48
44
|
maxTurns?: number;
|
|
@@ -50,8 +46,6 @@ export interface AgentConfig extends AgentIdentity, AgentPromptConfig {
|
|
|
50
46
|
inheritContext?: boolean;
|
|
51
47
|
/** Default for spawn: run in background. undefined = caller decides. */
|
|
52
48
|
runInBackground?: boolean;
|
|
53
|
-
/** Default for spawn: no extension tools. undefined = caller decides. */
|
|
54
|
-
isolated?: boolean;
|
|
55
49
|
/** true = this is an embedded default agent (informational) */
|
|
56
50
|
isDefault?: boolean;
|
|
57
51
|
/** false = agent is hidden from the registry */
|
|
@@ -65,7 +59,6 @@ export interface AgentInvocation {
|
|
|
65
59
|
modelName?: string;
|
|
66
60
|
thinking?: ThinkingLevel;
|
|
67
61
|
maxTurns?: number;
|
|
68
|
-
isolated?: boolean;
|
|
69
62
|
inheritContext?: boolean;
|
|
70
63
|
runInBackground?: boolean;
|
|
71
64
|
}
|