@cjhyy/code-shell-core 0.8.11 → 0.8.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/capabilities/index.d.ts +5 -54
  2. package/dist/capabilities/index.js +1 -80
  3. package/dist/cli/agent-server-stdio.js +21 -21
  4. package/dist/composition/compiler.d.ts +7 -0
  5. package/dist/composition/compiler.js +247 -0
  6. package/dist/composition/core-module.d.ts +10 -0
  7. package/dist/composition/core-module.js +19 -0
  8. package/dist/composition/index.d.ts +5 -0
  9. package/dist/composition/index.js +5 -0
  10. package/dist/composition/protocol-attach.d.ts +15 -0
  11. package/dist/composition/protocol-attach.js +21 -0
  12. package/dist/composition/resolve-preset.d.ts +35 -0
  13. package/dist/composition/resolve-preset.js +58 -0
  14. package/dist/composition/snapshot.d.ts +9 -0
  15. package/dist/composition/snapshot.js +48 -0
  16. package/dist/composition/types.d.ts +169 -0
  17. package/dist/composition/types.js +1 -0
  18. package/dist/engine/engine.d.ts +2 -1
  19. package/dist/engine/engine.js +54 -56
  20. package/dist/engine/subagent-spawner.js +2 -2
  21. package/dist/engine/types.d.ts +9 -6
  22. package/dist/exceptions.d.ts +8 -0
  23. package/dist/exceptions.js +11 -0
  24. package/dist/index.d.ts +8 -8
  25. package/dist/index.extension.d.ts +3 -3
  26. package/dist/index.extension.js +0 -1
  27. package/dist/index.js +6 -6
  28. package/dist/preset/index.d.ts +19 -26
  29. package/dist/preset/index.js +26 -66
  30. package/dist/product/define.js +8 -2
  31. package/dist/prompt/section-loader.d.ts +2 -8
  32. package/dist/prompt/section-loader.js +4 -17
  33. package/dist/protocol/client.d.ts +1 -0
  34. package/dist/protocol/server.d.ts +10 -11
  35. package/dist/protocol/server.js +33 -28
  36. package/dist/protocol/types.d.ts +5 -0
  37. package/dist/run/EngineRunner.d.ts +3 -2
  38. package/dist/run/EngineRunner.js +1 -1
  39. package/dist/run/RunManager.d.ts +3 -3
  40. package/dist/run/RunManager.js +6 -8
  41. package/dist/run/factory.d.ts +3 -3
  42. package/dist/run/factory.js +2 -2
  43. package/dist/session/session-manager.d.ts +1 -1
  44. package/dist/session/session-manager.js +3 -6
  45. package/dist/tool-system/capability-module.d.ts +0 -34
  46. package/dist/tool-system/capability-module.js +1 -53
  47. package/package.json +1 -1
package/dist/index.d.ts CHANGED
@@ -3,10 +3,12 @@
3
3
  *
4
4
  * Public API exports.
5
5
  */
6
- export declare const VERSION = "0.8.11";
6
+ export declare const VERSION = "0.8.12";
7
7
  export type { Message, ContentBlock, ToolDefinition, ToolCall, ToolResult, RegisteredTool, TranscriptEvent, TranscriptEventType, SessionState, SessionKind, SessionWorkspace, SessionForkLineage, ContextUsageAnchor, SessionStatus, TokenUsage, CompiledInput, PermissionDecision, PermissionMode, PermissionRule, TurnPhase, TurnResult, TerminalReason, TurnCompletionKind, StreamEvent, StreamCallback, LLMConfig, ClientDefaults, LLMResponse, Settings, MCPServerConfig, } from "./types.js";
8
8
  export type { GoalConfig, GoalLifecycleConfig, GoalLifecyclePhase, GoalLifecycleTerminalReason, GoalLifecycleV1, } from "./goal/lifecycle.js";
9
- export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, SandboxUnavailableError, } from "./exceptions.js";
9
+ export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, CompositionError, SandboxUnavailableError, } from "./exceptions.js";
10
+ export { compileComposition, toCompositionSnapshot, computeCompositionDigest, compositionToolCatalog, resolvePresetFromComposition, } from "./composition/index.js";
11
+ export type { AgentModule, AgentEngineContributions, AgentProtocolContributions, AgentModuleToolContribution, ResolvedComposition, CompositionSnapshot, } from "./composition/types.js";
10
12
  export { Engine, loadAgentDefinitionsForCwd } from "./engine/engine.js";
11
13
  export type { EngineConfig, EngineHookConfig, EngineResult } from "./engine/types.js";
12
14
  export type { RunBehaviorMode, RunBehaviorProfile } from "./engine/run-types.js";
@@ -43,13 +45,11 @@ export type { ConnectorAdapter } from "./sources/adapter.js";
43
45
  export type { SourceAccessStatus, CredentialStatusFn, EffectiveSourceAccess, ResolveSourceAccessInput, } from "./sources/resolve.js";
44
46
  export type { BuildSourcesContextSummaryInput } from "./sources/context-summary.js";
45
47
  export { createFakeToolContext, createToolRegistryHarness, type FakeToolContextOptions, type ToolRegistryHarness, type ToolRegistryHarnessOptions, } from "./tool-system/testing/tool-registry-harness.js";
46
- export { registerCapability, unregisterCapability, listRegisteredCapabilities, } from "./capabilities/index.js";
47
- export type { CapabilityArtifact, CapabilityArtifactDetectionContext, CapabilityArtifactDetector, CapabilityDynamicContext, CapabilityDynamicContextProvider, CapabilityFileHistoryContribution, CapabilityEngineHookContribution, CapabilityInstructionBoundaryFinder, CapabilityModule, CapabilityToolServiceHost, CapabilityToolSelectionContext, SessionWorkspaceCapability, } from "./capabilities/index.js";
48
+ export type { CapabilityArtifact, CapabilityArtifactDetectionContext, CapabilityArtifactDetector, CapabilityDynamicContext, CapabilityDynamicContextProvider, CapabilityFileHistoryContribution, CapabilityEngineHookContribution, CapabilityInstructionBoundaryFinder, CapabilityToolServiceHost, CapabilityToolSelectionContext, SessionWorkspaceCapability, } from "./capabilities/index.js";
48
49
  export { makeUpdateAutomationMemoryTool } from "./tool-system/builtin/update-automation-memory.js";
49
50
  export { MCPManager, buildHttpHeaders, buildStdioEnv, createMcpAuthenticatedFetch, } from "./tool-system/mcp-manager.js";
50
51
  export type { AskUserFn } from "./tool-system/builtin/ask-user.js";
51
- export type { ExtensionModule, ExtensionQueryHandler, ExtensionTool, ProtocolLiveSession, ProtocolObserver, ProtocolObserverHost, } from "./tool-system/capability-module.js";
52
- export { registerExtensionModules, queryExtensionModules, } from "./tool-system/capability-module.js";
52
+ export type { ExtensionQueryHandler, ExtensionTool, ProtocolLiveSession, ProtocolObserver, ProtocolObserverHost, } from "./tool-system/capability-module.js";
53
53
  export type { Task, TaskStatus } from "./tool-system/builtin/task.js";
54
54
  export { HookRegistry } from "./hooks/registry.js";
55
55
  export type { HookHandler } from "./hooks/registry.js";
@@ -77,9 +77,9 @@ export { authorize, refreshToken, generatePKCE, createHardenedOAuthFetch, type O
77
77
  export { PromptComposer } from "./prompt/composer.js";
78
78
  export { SectionCache } from "./prompt/section-cache.js";
79
79
  export { scanInstructions, combineInstructions } from "./prompt/instruction-scanner.js";
80
- export { BUILTIN_AGENT_PRESETS, DEFAULT_AGENT_PRESET, DEFAULT_CLI_PRESET, resolveAgentPreset, resolveBuiltinToolNames, buildPresetSystemPrompt, registerPreset, listPresetNames, } from "./preset/index.js";
80
+ export { BUILTIN_AGENT_PRESETS, DEFAULT_AGENT_PRESET, DEFAULT_CLI_PRESET, resolveAgentPreset, resolveBuiltinToolNames, resolveToolNamesForPreset, buildPresetSystemPrompt, listPresetNames, } from "./preset/index.js";
81
81
  export type { AgentPreset, AgentPresetName } from "./preset/index.js";
82
- export { loadSection, loadSections, availableSections, registerSection, } from "./prompt/section-loader.js";
82
+ export { loadSection, loadSections, availableSections } from "./prompt/section-loader.js";
83
83
  export { ContextManager } from "./context/manager.js";
84
84
  export { estimateTokens, microcompact, windowCompact, truncateToolResult, buildSummarizationPrompt, applySummaryCompaction, COMPACTABLE_TOOL_NAMES, } from "./context/compaction.js";
85
85
  export type { MicrocompactOptions } from "./context/compaction.js";
@@ -26,10 +26,10 @@ export type { ExposureRationale } from "./tool-system/external-tool-exposure.js"
26
26
  export { webSearchTool } from "./tool-system/builtin/web-search.js";
27
27
  export { webFetchTool } from "./tool-system/builtin/web-fetch.js";
28
28
  export { extractJSON, extractJSONArray } from "./utils/json.js";
29
- export type { ExtensionModule, ExtensionQueryHandler, ExtensionTool, } from "./tool-system/capability-module.js";
29
+ export type { ExtensionQueryHandler, ExtensionTool, } from "./tool-system/capability-module.js";
30
30
  export type { SessionWorkspace } from "./types.js";
31
- export { registerCapability } from "./capabilities/index.js";
32
- export type { CapabilityArtifactDetector, CapabilityDynamicContextProvider, CapabilityModule, CapabilityToolServiceHost, } from "./capabilities/index.js";
31
+ export type { CapabilityArtifactDetector, CapabilityDynamicContextProvider, CapabilityToolServiceHost, } from "./capabilities/index.js";
32
+ export type { AgentModule, AgentEngineContributions, AgentProtocolContributions, AgentModuleToolContribution, ResolvedComposition, } from "./composition/types.js";
33
33
  export { BUILTIN_AGENT_PRESETS } from "./preset/index.js";
34
34
  export type { AgentPreset } from "./preset/index.js";
35
35
  export { BUILTIN_TOOLS, derivePresetExposure } from "./tool-system/builtin/index.js";
@@ -25,7 +25,6 @@ export { FIRST_PHASE_EXPOSURE, FIRST_PHASE_EXPOSURE_RATIONALE, } from "./tool-sy
25
25
  export { webSearchTool } from "./tool-system/builtin/web-search.js";
26
26
  export { webFetchTool } from "./tool-system/builtin/web-fetch.js";
27
27
  export { extractJSON, extractJSONArray } from "./utils/json.js";
28
- export { registerCapability } from "./capabilities/index.js";
29
28
  export { BUILTIN_AGENT_PRESETS } from "./preset/index.js";
30
29
  export { BUILTIN_TOOLS, derivePresetExposure } from "./tool-system/builtin/index.js";
31
30
  export { SessionManager, codeShellHome } from "./session/session-manager.js";
package/dist/index.js CHANGED
@@ -3,9 +3,11 @@
3
3
  *
4
4
  * Public API exports.
5
5
  */
6
- export const VERSION = "0.8.11";
6
+ export const VERSION = "0.8.12";
7
7
  // ─── Exceptions ──────────────────────────────────────────────────
8
- export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, SandboxUnavailableError, } from "./exceptions.js";
8
+ export { FrameworkError, LLMError, LLMRateLimitError, ContextLimitError, ToolError, ToolNotFoundError, ToolExecutionError, ToolTimeoutError, PermissionDeniedError, SessionError, TranscriptError, ConfigError, CompositionError, SandboxUnavailableError, } from "./exceptions.js";
9
+ // ─── Composition (AgentModule / ResolvedComposition) ─────────────
10
+ export { compileComposition, toCompositionSnapshot, computeCompositionDigest, compositionToolCatalog, resolvePresetFromComposition, } from "./composition/index.js";
9
11
  // ─── Engine (primary API) ────────────────────────────────────────
10
12
  export { Engine, loadAgentDefinitionsForCwd } from "./engine/engine.js";
11
13
  export { resolveLLMConfigForTag } from "./engine/resolve-llm-config.js";
@@ -34,10 +36,8 @@ export { SKILL_REPO_RE, WORKSPACE_PROFILE_NAME_RE, WorkspaceProfileSchema, Works
34
36
  // ─── Workspace data sources ─────────────────────────────────────
35
37
  export { SOURCE_ID_RE, SOURCE_KINDS, SourceDefinitionSchema, WorkspaceSourceBindingSchema, } from "./sources/types.js";
36
38
  export { createFakeToolContext, createToolRegistryHarness, } from "./tool-system/testing/tool-registry-harness.js";
37
- export { registerCapability, unregisterCapability, listRegisteredCapabilities, } from "./capabilities/index.js";
38
39
  export { makeUpdateAutomationMemoryTool } from "./tool-system/builtin/update-automation-memory.js";
39
40
  export { MCPManager, buildHttpHeaders, buildStdioEnv, createMcpAuthenticatedFetch, } from "./tool-system/mcp-manager.js";
40
- export { registerExtensionModules, queryExtensionModules, } from "./tool-system/capability-module.js";
41
41
  // ─── Hooks ───────────────────────────────────────────────────────
42
42
  export { HookRegistry } from "./hooks/registry.js";
43
43
  export { wrapHookMessages } from "./hooks/inject.js";
@@ -66,8 +66,8 @@ export { PromptComposer } from "./prompt/composer.js";
66
66
  export { SectionCache } from "./prompt/section-cache.js";
67
67
  export { scanInstructions, combineInstructions } from "./prompt/instruction-scanner.js";
68
68
  // ─── Presets ─────────────────────────────────────────────────────
69
- export { BUILTIN_AGENT_PRESETS, DEFAULT_AGENT_PRESET, DEFAULT_CLI_PRESET, resolveAgentPreset, resolveBuiltinToolNames, buildPresetSystemPrompt, registerPreset, listPresetNames, } from "./preset/index.js";
70
- export { loadSection, loadSections, availableSections, registerSection, } from "./prompt/section-loader.js";
69
+ export { BUILTIN_AGENT_PRESETS, DEFAULT_AGENT_PRESET, DEFAULT_CLI_PRESET, resolveAgentPreset, resolveBuiltinToolNames, resolveToolNamesForPreset, buildPresetSystemPrompt, listPresetNames, } from "./preset/index.js";
70
+ export { loadSection, loadSections, availableSections } from "./prompt/section-loader.js";
71
71
  // ─── Context ─────────────────────────────────────────────────────
72
72
  export { ContextManager } from "./context/manager.js";
73
73
  export { estimateTokens, microcompact, windowCompact, truncateToolResult, buildSummarizationPrompt, applySummaryCompaction, COMPACTABLE_TOOL_NAMES, } from "./context/compaction.js";
@@ -9,11 +9,11 @@
9
9
  */
10
10
  import type { PermissionRule } from "../types.js";
11
11
  import { type BuiltinTool } from "../tool-system/builtin/index.js";
12
- import type { CapabilityModule } from "../capabilities/index.js";
12
+ import type { CapabilityToolSelectionContext } from "../capabilities/index.js";
13
13
  export declare const AGENT_PRESET_NAMES: readonly ["harness-min", "general"];
14
- /** Built-in preset names. Custom presets use arbitrary strings via registerPreset(). */
14
+ /** Built-in preset names. Module presets use arbitrary strings via AgentModule.engine.presets. */
15
15
  export type BuiltinPresetName = (typeof AGENT_PRESET_NAMES)[number];
16
- /** Any preset name — built-in or custom-registered. */
16
+ /** Any preset name — built-in or module-contributed. */
17
17
  export type AgentPresetName = BuiltinPresetName | (string & {});
18
18
  export interface AgentPreset {
19
19
  name: AgentPresetName;
@@ -26,29 +26,11 @@ export interface AgentPreset {
26
26
  }
27
27
  export declare const BUILTIN_AGENT_PRESETS: Record<BuiltinPresetName, AgentPreset>;
28
28
  export declare const DEFAULT_AGENT_PRESET: AgentPresetName;
29
- /** @deprecated Product hosts should install a capability with `defaultPreset`. */
29
+ /** @deprecated Product hosts should ship a module declaring `defaultPreset`. */
30
30
  export declare const DEFAULT_CLI_PRESET: AgentPresetName;
31
- /**
32
- * Register a custom agent preset.
33
- *
34
- * External repos can call this to add their own presets:
35
- * ```ts
36
- * import { registerPreset } from "code-shell";
37
- *
38
- * registerPreset({
39
- * name: "data-pipeline" as AgentPresetName,
40
- * label: "Data Pipeline Orchestrator",
41
- * description: "Manages ETL workflows and data quality checks.",
42
- * promptSections: ["base", "orchestration"],
43
- * builtinTools: ["Read", "Write", "Bash", "Glob", "Grep", "Agent"],
44
- * defaultPermissionRules: [{ tool: "Read", decision: "allow" }],
45
- * });
46
- * ```
47
- */
48
- export declare function registerPreset(preset: AgentPreset): void;
49
- /** List all available preset names (built-in + custom). */
50
- export declare function listPresetNames(capabilities?: readonly CapabilityModule[]): string[];
51
- export declare function resolveAgentPreset(name?: string, capabilities?: readonly CapabilityModule[]): AgentPreset;
31
+ /** List the built-in preset names. Module-contributed presets live in the composition. */
32
+ export declare function listPresetNames(): string[];
33
+ export declare function resolveAgentPreset(name?: string): AgentPreset;
52
34
  export interface BuildPresetSystemPromptOptions {
53
35
  activeToolNames?: readonly string[];
54
36
  platform?: NodeJS.Platform;
@@ -65,10 +47,21 @@ export interface BuildPresetSystemPromptOptions {
65
47
  * include all sections (e.g. when assembling a generic/preview prompt).
66
48
  */
67
49
  export declare function buildPresetSystemPrompt(preset: AgentPreset, optionsOrActiveToolNames?: BuildPresetSystemPromptOptions | readonly string[]): string;
50
+ /**
51
+ * Composition-era tool-name resolution: the caller resolves the preset
52
+ * object first (resolvePresetFromComposition) and passes explicit
53
+ * adjusters instead of whole capability modules.
54
+ */
55
+ export declare function resolveToolNamesForPreset(options: {
56
+ preset: AgentPreset;
57
+ host?: string;
58
+ enabledBuiltinTools?: readonly string[];
59
+ disabledBuiltinTools?: readonly string[];
60
+ adjusters?: readonly ((names: Set<string>, context: CapabilityToolSelectionContext) => void)[];
61
+ }): string[];
68
62
  export declare function resolveBuiltinToolNames(options?: {
69
63
  preset?: string;
70
64
  host?: string;
71
65
  enabledBuiltinTools?: string[];
72
66
  disabledBuiltinTools?: string[];
73
- capabilities?: readonly CapabilityModule[];
74
67
  }): string[];
@@ -32,67 +32,18 @@ export const BUILTIN_AGENT_PRESETS = {
32
32
  },
33
33
  };
34
34
  export const DEFAULT_AGENT_PRESET = "harness-min";
35
- /** @deprecated Product hosts should install a capability with `defaultPreset`. */
35
+ /** @deprecated Product hosts should ship a module declaring `defaultPreset`. */
36
36
  export const DEFAULT_CLI_PRESET = DEFAULT_AGENT_PRESET;
37
- /** Registry of custom presets registered by external consumers. */
38
- const _customPresets = new Map();
39
- /**
40
- * Register a custom agent preset.
41
- *
42
- * External repos can call this to add their own presets:
43
- * ```ts
44
- * import { registerPreset } from "code-shell";
45
- *
46
- * registerPreset({
47
- * name: "data-pipeline" as AgentPresetName,
48
- * label: "Data Pipeline Orchestrator",
49
- * description: "Manages ETL workflows and data quality checks.",
50
- * promptSections: ["base", "orchestration"],
51
- * builtinTools: ["Read", "Write", "Bash", "Glob", "Grep", "Agent"],
52
- * defaultPermissionRules: [{ tool: "Read", decision: "allow" }],
53
- * });
54
- * ```
55
- */
56
- export function registerPreset(preset) {
57
- _customPresets.set(preset.name, preset);
37
+ /** List the built-in preset names. Module-contributed presets live in the composition. */
38
+ export function listPresetNames() {
39
+ return [...AGENT_PRESET_NAMES];
58
40
  }
59
- /** List all available preset names (built-in + custom). */
60
- export function listPresetNames(capabilities = []) {
61
- return [
62
- ...new Set([
63
- ...AGENT_PRESET_NAMES,
64
- ..._customPresets.keys(),
65
- ...capabilities.flatMap((capability) => (capability.presets ?? []).map((preset) => preset.name)),
66
- ]),
67
- ];
68
- }
69
- export function resolveAgentPreset(name, capabilities = []) {
70
- let resolvedName = name;
71
- if (!resolvedName) {
72
- const defaults = [
73
- ...new Set(capabilities
74
- .map((capability) => capability.defaultPreset)
75
- .filter((preset) => Boolean(preset))),
76
- ];
77
- if (defaults.length > 1) {
78
- throw new Error(`Capabilities contributed conflicting default presets: ${defaults.join(", ")}`);
79
- }
80
- resolvedName = defaults[0] ?? DEFAULT_AGENT_PRESET;
81
- }
82
- const contributed = capabilities
83
- .flatMap((capability) => [...(capability.presets ?? [])])
84
- .find((preset) => preset.name === resolvedName);
85
- if (contributed)
86
- return contributed;
87
- // Check built-in first
41
+ export function resolveAgentPreset(name) {
42
+ const resolvedName = name ?? DEFAULT_AGENT_PRESET;
88
43
  const builtin = BUILTIN_AGENT_PRESETS[resolvedName];
89
44
  if (builtin)
90
45
  return builtin;
91
- // Check custom presets
92
- const custom = _customPresets.get(resolvedName);
93
- if (custom)
94
- return custom;
95
- const allowed = listPresetNames(capabilities).join(", ");
46
+ const allowed = listPresetNames().join(", ");
96
47
  throw new Error(`Unknown agent preset "${resolvedName}". Available presets: ${allowed}`);
97
48
  }
98
49
  /** Prompt-section capability links are contributed by builtin exposure metadata. */
@@ -141,20 +92,29 @@ export function buildPresetSystemPrompt(preset, optionsOrActiveToolNames) {
141
92
  .filter(Boolean)
142
93
  .join("\n\n");
143
94
  }
144
- export function resolveBuiltinToolNames(options) {
145
- const preset = resolveAgentPreset(options?.preset, options?.capabilities);
146
- const names = new Set(preset.builtinTools);
147
- for (const name of options?.enabledBuiltinTools ?? []) {
95
+ /**
96
+ * Composition-era tool-name resolution: the caller resolves the preset
97
+ * object first (resolvePresetFromComposition) and passes explicit
98
+ * adjusters instead of whole capability modules.
99
+ */
100
+ export function resolveToolNamesForPreset(options) {
101
+ const names = new Set(options.preset.builtinTools);
102
+ for (const name of options.enabledBuiltinTools ?? []) {
148
103
  names.add(name);
149
104
  }
150
- for (const capability of options?.capabilities ?? []) {
151
- capability.adjustToolSelection?.(names, {
152
- preset: preset.name,
153
- host: options?.host,
154
- });
105
+ for (const adjust of options.adjusters ?? []) {
106
+ adjust(names, { preset: options.preset.name, host: options.host });
155
107
  }
156
- for (const name of options?.disabledBuiltinTools ?? []) {
108
+ for (const name of options.disabledBuiltinTools ?? []) {
157
109
  names.delete(name);
158
110
  }
159
111
  return [...names];
160
112
  }
113
+ export function resolveBuiltinToolNames(options) {
114
+ return resolveToolNamesForPreset({
115
+ preset: resolveAgentPreset(options?.preset),
116
+ host: options?.host,
117
+ enabledBuiltinTools: options?.enabledBuiltinTools,
118
+ disabledBuiltinTools: options?.disabledBuiltinTools,
119
+ });
120
+ }
@@ -33,7 +33,6 @@
33
33
  * await manager.submit({ objective: "Audit auth module for SQL injection" });
34
34
  * ```
35
35
  */
36
- import { registerPreset } from "../preset/index.js";
37
36
  import { CompositeEvaluator, NoopEvaluator } from "../run/Evaluator.js";
38
37
  import { RunManager } from "../run/RunManager.js";
39
38
  import { FileRunStore } from "../run/FileRunStore.js";
@@ -81,7 +80,13 @@ export function defineProduct(definition, runtime) {
81
80
  builtinTools: [...enabledSet],
82
81
  defaultPermissionRules: permissionRules,
83
82
  };
84
- registerPreset(agentPreset);
83
+ // The product's preset travels as a synthesized AgentModule instead of a
84
+ // process-global registerPreset(): each Engine the runner builds resolves
85
+ // presets from its own compiled composition.
86
+ const productModule = {
87
+ id: "product",
88
+ engine: { presets: [agentPreset], defaultPreset: agentPreset.name },
89
+ };
85
90
  // ── 2. Build evaluator from contract ──────────────────────────
86
91
  let evaluator;
87
92
  if (!contract?.evaluator) {
@@ -118,6 +123,7 @@ export function defineProduct(definition, runtime) {
118
123
  appendSystemPrompt: presetDef.appendPrompt,
119
124
  hooks: adapter?.hooks,
120
125
  customTools: customToolEntries.length > 0 ? customToolEntries : undefined,
126
+ modules: [productModule],
121
127
  },
122
128
  concurrency: contract?.concurrency ?? 1,
123
129
  runsDir,
@@ -5,15 +5,9 @@
5
5
  * files to dist/prompt/sections so plain Node ESM can import core without a
6
6
  * custom .md loader.
7
7
  */
8
- /**
9
- * Register a custom prompt section at runtime.
10
- * This allows external presets to add their own sections.
11
- */
12
- export declare function registerSection(name: string, content: string): void;
13
8
  /**
14
9
  * Read a named prompt section. Returns the trimmed markdown content.
15
- * Looks up built-in sections first, then custom-registered sections.
16
- * Throws if the section name is not found.
10
+ * Contributed (module) sections win over built-ins; throws on unknown names.
17
11
  */
18
12
  export declare function loadSection(name: string, sections?: Readonly<Record<string, string>>): string;
19
13
  /**
@@ -21,6 +15,6 @@ export declare function loadSection(name: string, sections?: Readonly<Record<str
21
15
  */
22
16
  export declare function loadSections(names: readonly string[], sections?: Readonly<Record<string, string>>): string;
23
17
  /**
24
- * List all available section names (built-in + custom).
18
+ * List the built-in section names.
25
19
  */
26
20
  export declare function availableSections(): string[];
@@ -16,19 +16,9 @@ const BUILTIN_SECTIONS = {
16
16
  browser: readSectionFile("browser"),
17
17
  tone: readSectionFile("tone"),
18
18
  };
19
- /** Registry for custom sections added at runtime. */
20
- const _customSections = new Map();
21
- /**
22
- * Register a custom prompt section at runtime.
23
- * This allows external presets to add their own sections.
24
- */
25
- export function registerSection(name, content) {
26
- _customSections.set(name, content);
27
- }
28
19
  /**
29
20
  * Read a named prompt section. Returns the trimmed markdown content.
30
- * Looks up built-in sections first, then custom-registered sections.
31
- * Throws if the section name is not found.
21
+ * Contributed (module) sections win over built-ins; throws on unknown names.
32
22
  */
33
23
  export function loadSection(name, sections) {
34
24
  const contributed = sections?.[name];
@@ -37,10 +27,7 @@ export function loadSection(name, sections) {
37
27
  const builtin = BUILTIN_SECTIONS[name];
38
28
  if (builtin !== undefined)
39
29
  return builtin.trim();
40
- const custom = _customSections.get(name);
41
- if (custom !== undefined)
42
- return custom.trim();
43
- const available = [...Object.keys(BUILTIN_SECTIONS), ..._customSections.keys()].join(", ");
30
+ const available = Object.keys(BUILTIN_SECTIONS).join(", ");
44
31
  throw new Error(`Unknown prompt section "${name}". Available sections: ${available}`);
45
32
  }
46
33
  /**
@@ -50,8 +37,8 @@ export function loadSections(names, sections) {
50
37
  return names.map((name) => loadSection(name, sections)).join("\n\n");
51
38
  }
52
39
  /**
53
- * List all available section names (built-in + custom).
40
+ * List the built-in section names.
54
41
  */
55
42
  export function availableSections() {
56
- return [...Object.keys(BUILTIN_SECTIONS), ..._customSections.keys()];
43
+ return [...Object.keys(BUILTIN_SECTIONS)];
57
44
  }
@@ -31,6 +31,7 @@ export interface AgentRunOptions {
31
31
  model?: string;
32
32
  planMode?: boolean;
33
33
  behaviorMode?: RunBehaviorMode;
34
+ preset?: string;
34
35
  kind?: SessionKind;
35
36
  }
36
37
  export type BackgroundAgentCompletedHandler = (sessionId: string, event: BackgroundAgentCompletedEvent) => void;
@@ -18,7 +18,7 @@ import type { Engine } from "../engine/engine.js";
18
18
  import type { ValidatedSettings } from "../settings/schema.js";
19
19
  import { type ApprovalRouter } from "../tool-system/permission.js";
20
20
  import type { ChatSessionManager } from "./chat-session-manager.js";
21
- import type { ExtensionModule } from "../tool-system/capability-module.js";
21
+ import type { ResolvedComposition } from "../composition/types.js";
22
22
  /**
23
23
  * Why a host-loopback request (Panel / Browser / workspace / credential) ended
24
24
  * without a result. These four used to collapse into one string — "declined or
@@ -109,12 +109,11 @@ export interface AgentServerOptions {
109
109
  /** Shared owner router; injectable for hosts/tests, process singleton by default. */
110
110
  approvalRouter?: ApprovalRouter;
111
111
  /**
112
- * Extension modules whose protocol observers / run-param validators /
113
- * hidden session kinds this server applies. Defaults to core's built-in
114
- * pet extension so existing hosts keep the Pet projection channel.
115
- * TODO(pet-out-of-core): drop the default once hosts register it explicitly.
112
+ * Compiled composition from the host root. The server consumes its
113
+ * protocol surface: observers, run-param validators, queries, hidden
114
+ * session kinds. Omitted core-only (no protocol contributions).
116
115
  */
117
- extensionModules?: readonly ExtensionModule[];
116
+ composition?: ResolvedComposition;
118
117
  }
119
118
  export declare class AgentServer {
120
119
  /** Host-supplied manager; requests route through the `chatManager` getter. */
@@ -140,13 +139,13 @@ export declare class AgentServer {
140
139
  private approvalConnectionUnregister;
141
140
  private disconnected;
142
141
  private readonly pendingApprovalTargets;
143
- /** Extension modules this server consults for protocol-level hooks. */
144
- private readonly extensionModules;
145
- /** Protocol lifecycle observers created by extension modules (registration order). */
142
+ /** Module run-param validators from the resolved protocol composition. */
143
+ private readonly runValidators;
144
+ /** Protocol lifecycle observers created by module factories (module order). */
146
145
  private readonly protocolObservers;
147
146
  /** Extension-registered protocol method/query aliases (compat channel). */
148
147
  private readonly protocolQueryHandlers;
149
- /** Union of extension hiddenSessionKinds, excluded from generic session lists. */
148
+ /** Union of module hiddenSessionKinds, excluded from generic session lists. */
150
149
  private readonly hiddenSessionKinds;
151
150
  /**
152
151
  * Last per-session EngineConfigSlice supplied by agent/run. Kept even after
@@ -254,7 +253,7 @@ export declare class AgentServer {
254
253
  private observeApprovalTransition;
255
254
  private observeSessionClosed;
256
255
  private observeServerClose;
257
- /** Generic run-param shape checks plus each extension's domain validation. */
256
+ /** Generic run-param shape checks plus each module's domain validation. */
258
257
  private validateRunInput;
259
258
  private handleForkSession;
260
259
  private handleRun;
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import { Methods, ErrorCodes, createResponse, createErrorResponse, createNotification, isRequest, } from "./types.js";
17
17
  import { diskDefaultsFrom } from "../engine/engine.js";
18
+ import { ISOLATED_TASK_BEHAVIOR_MODE } from "../engine/run-types.js";
18
19
  import { isProtectedSettingKey, SettingsManager } from "../settings/manager.js";
19
20
  import { getApprovalRouter, getInteractiveApprovalBackend, } from "../tool-system/permission.js";
20
21
  import { agentNotificationBus, notificationQueue, buildNotificationMessage, notificationEnvelopeToLegacyStreamEvent, } from "../tool-system/builtin/agent-notifications.js";
@@ -26,6 +27,8 @@ import { nanoid } from "nanoid";
26
27
  import { assertSafeSessionId, SessionManager } from "../session/session-manager.js";
27
28
  import { redactLlmConfig, maskSecretValue } from "./redact.js";
28
29
  import { redactSecrets } from "../logging/sanitize-messages.js";
30
+ import { compileComposition } from "../composition/compiler.js";
31
+ import { attachProtocolContributions } from "../composition/protocol-attach.js";
29
32
  import { computeEffectiveDisabledLists } from "../capability-control/disabled-lists.js";
30
33
  import { describePluginCommands, expandPluginCommandBody, scanPluginCommands, MAX_PLUGIN_COMMAND_ARGUMENT_CHARS, } from "../plugins/pluginCommandsLoader.js";
31
34
  function isValidRunAttachment(value) {
@@ -87,6 +90,13 @@ function runInputError(params) {
87
90
  (typeof params.behaviorMode !== "string" || params.behaviorMode.length === 0)) {
88
91
  return `invalid behavior mode: ${String(params.behaviorMode)}`;
89
92
  }
93
+ if (params.preset !== undefined &&
94
+ (typeof params.preset !== "string" ||
95
+ params.preset.length === 0 ||
96
+ params.preset.length > 128 ||
97
+ /[\r\n]/.test(params.preset))) {
98
+ return "preset must be a bounded non-empty string";
99
+ }
90
100
  for (const [field, value, maxItems] of [
91
101
  ["toolAllowlist", params.toolAllowlist, 32],
92
102
  ["skillAllowlist", params.skillAllowlist, 8],
@@ -122,7 +132,7 @@ function runInputError(params) {
122
132
  return "profileParams must be an object";
123
133
  }
124
134
  // Domain-specific run-param validation (e.g. behavior-mode vocabularies and
125
- // extension-owned param shapes) lives in ExtensionModule.validateRunParams.
135
+ // extension-owned param shapes) lives in AgentModule protocol.validateRunParams.
126
136
  return null;
127
137
  }
128
138
  function goalExtensionInputError(params) {
@@ -303,13 +313,13 @@ export class AgentServer {
303
313
  approvalConnectionUnregister = null;
304
314
  disconnected = false;
305
315
  pendingApprovalTargets = new Map();
306
- /** Extension modules this server consults for protocol-level hooks. */
307
- extensionModules;
308
- /** Protocol lifecycle observers created by extension modules (registration order). */
316
+ /** Module run-param validators from the resolved protocol composition. */
317
+ runValidators;
318
+ /** Protocol lifecycle observers created by module factories (module order). */
309
319
  protocolObservers = [];
310
320
  /** Extension-registered protocol method/query aliases (compat channel). */
311
321
  protocolQueryHandlers = new Map();
312
- /** Union of extension hiddenSessionKinds, excluded from generic session lists. */
322
+ /** Union of module hiddenSessionKinds, excluded from generic session lists. */
313
323
  hiddenSessionKinds;
314
324
  /**
315
325
  * Last per-session EngineConfigSlice supplied by agent/run. Kept even after
@@ -408,14 +418,12 @@ export class AgentServer {
408
418
  throw new Error("AgentServer: either chatManager or engine must be supplied");
409
419
  }
410
420
  this.transport = options.transport;
411
- // Protocol lifecycle observers. Each configured extension module may
412
- // attach one; the server calls them at every lifecycle hook point and
413
- // isolates per-observer failures. Core default-loads the pet extension
414
- // until the pet domain moves out of core (see AgentServerOptions).
415
- this.extensionModules = options.extensionModules ?? [];
416
- this.hiddenSessionKinds = [
417
- ...new Set(this.extensionModules.flatMap((module) => module.hiddenSessionKinds ?? [])),
418
- ];
421
+ // Protocol surface from the compiled composition. Each contributing
422
+ // module may attach one observer; the server calls them at every
423
+ // lifecycle hook point and isolates per-observer failures.
424
+ const protocol = options.composition?.protocol ?? compileComposition({}).protocol;
425
+ this.runValidators = protocol.runValidators;
426
+ this.hiddenSessionKinds = protocol.hiddenSessionKinds.map((k) => k.key);
419
427
  const observerHost = {
420
428
  getLiveSessionSnapshot: () => this.chatManager?.getLiveSessionSnapshot().sessions ?? [],
421
429
  projectionGeneration: () => this.workerGeneration(),
@@ -433,16 +441,13 @@ export class AgentServer {
433
441
  this.protocolQueryHandlers.set(type, handler);
434
442
  },
435
443
  };
436
- for (const module of this.extensionModules) {
437
- if (!module.createProtocolObserver)
438
- continue;
439
- try {
440
- this.protocolObservers.push(module.createProtocolObserver(observerHost));
441
- }
442
- catch (err) {
443
- logger.warn(`protocol observer init failed for extension ${module.id}: ${err.message}`);
444
- }
445
- }
444
+ attachProtocolContributions({
445
+ protocol,
446
+ host: observerHost,
447
+ observers: this.protocolObservers,
448
+ queryHandlers: this.protocolQueryHandlers,
449
+ warn: (message) => logger.warn(message),
450
+ });
446
451
  // Wire up incoming messages
447
452
  this.transport.onMessage((msg) => {
448
453
  if (isRequest(msg)) {
@@ -936,15 +941,13 @@ export class AgentServer {
936
941
  observeServerClose() {
937
942
  this.forEachObserver("onServerClose", (observer) => observer.onServerClose?.());
938
943
  }
939
- /** Generic run-param shape checks plus each extension's domain validation. */
944
+ /** Generic run-param shape checks plus each module's domain validation. */
940
945
  validateRunInput(params) {
941
946
  const generic = runInputError(params);
942
947
  if (generic)
943
948
  return generic;
944
- for (const module of this.extensionModules) {
945
- if (!module.validateRunParams)
946
- continue;
947
- const error = module.validateRunParams(params);
949
+ for (const validator of this.runValidators) {
950
+ const error = validator.value(params);
948
951
  if (error)
949
952
  return error;
950
953
  }
@@ -1144,6 +1147,8 @@ export class AgentServer {
1144
1147
  const sessionConfig = {
1145
1148
  cwd: params.cwd,
1146
1149
  projectTrusted: params.projectTrusted,
1150
+ preset: params.preset ??
1151
+ (params.behaviorMode === ISOLATED_TASK_BEHAVIOR_MODE ? "general" : undefined),
1147
1152
  maxTurns: params.maxTurns,
1148
1153
  maxContextTokens: params.maxContextTokens,
1149
1154
  goal: typeof params.goal === "string" || (params.goal != null && typeof params.goal === "object")
@@ -126,6 +126,11 @@ export interface RunParams {
126
126
  planMode?: boolean;
127
127
  /** Named behavior profile for a product-specific per-run interaction mode. */
128
128
  behaviorMode?: RunBehaviorMode;
129
+ /**
130
+ * Preset used when creating this run's fresh Session. Host-owned bounded
131
+ * Tasks use this to avoid inheriting the interactive product default.
132
+ */
133
+ preset?: string;
129
134
  /** Host-authorized per-run hard tool allowlist. Empty means no tools. */
130
135
  toolAllowlist?: string[];
131
136
  /** Host-authorized per-run hard Skill allowlist. Empty means no Skills. */
@@ -13,7 +13,7 @@ import type { ClientDefaults, LLMConfig, RegisteredTool } from "../types.js";
13
13
  import type { RunSnapshot, RunExecutionContext, RunExecutionResult } from "./types.js";
14
14
  import { type RunLifecycleHooks } from "./RunApprovalBackend.js";
15
15
  import type { ApprovalBackend } from "../tool-system/permission.js";
16
- import type { CapabilityModule } from "../capabilities/index.js";
16
+ import type { AgentModule } from "../composition/types.js";
17
17
  /** Unattended runs (those with an injected approval backend) run headless so
18
18
  * the in-process AgentServer does not wire an interactive askUser. Exported
19
19
  * for unit testing the decision rule. */
@@ -73,7 +73,8 @@ export interface EngineRunnerConfig {
73
73
  permissionMode?: EngineConfig["permissionMode"];
74
74
  enabledBuiltinTools?: string[];
75
75
  disabledBuiltinTools?: string[];
76
- capabilities?: readonly CapabilityModule[];
76
+ /** AgentModules installed into each Engine this runner builds. */
77
+ modules?: readonly AgentModule[];
77
78
  customSystemPrompt?: string;
78
79
  appendSystemPrompt?: string;
79
80
  mcpServers?: EngineConfig["mcpServers"];
@@ -86,7 +86,7 @@ export class EngineRunner {
86
86
  preset: run.preset,
87
87
  enabledBuiltinTools: this.config.enabledBuiltinTools,
88
88
  disabledBuiltinTools: this.config.disabledBuiltinTools,
89
- capabilities: this.config.capabilities,
89
+ modules: this.config.modules,
90
90
  customSystemPrompt: this.config.customSystemPrompt,
91
91
  // NOTE: callers must not pass appendSystemPrompt in engineConfigOverrides
92
92
  // below, or it will clobber this composed (automation note + host) value.