@oh-my-pi/pi-coding-agent 9.3.1 → 9.6.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 +98 -0
- package/examples/hooks/snake.ts +5 -5
- package/package.json +9 -8
- package/src/capability/index.ts +7 -9
- package/src/cli/config-cli.ts +86 -73
- package/src/cli/update-cli.ts +45 -3
- package/src/commit/agentic/agent.ts +4 -4
- package/src/commit/agentic/index.ts +6 -5
- package/src/commit/agentic/tools/analyze-file.ts +5 -7
- package/src/commit/agentic/tools/index.ts +3 -3
- package/src/commit/model-selection.ts +13 -17
- package/src/commit/pipeline.ts +5 -5
- package/src/config/model-registry.ts +7 -0
- package/src/config/settings-schema.ts +836 -0
- package/src/config/settings.ts +702 -0
- package/src/discovery/helpers.ts +55 -11
- package/src/exa/index.ts +1 -1
- package/src/exec/bash-executor.ts +13 -13
- package/src/exec/shell-session.ts +15 -3
- package/src/export/ttsr.ts +1 -1
- package/src/extensibility/skills.ts +40 -9
- package/src/index.ts +2 -10
- package/src/ipy/gateway-coordinator.ts +5 -159
- package/src/ipy/kernel.ts +6 -171
- package/src/ipy/runtime.ts +198 -0
- package/src/lsp/client.ts +14 -1
- package/src/lsp/defaults.json +0 -6
- package/src/lsp/index.ts +1 -1
- package/src/lsp/types.ts +2 -0
- package/src/main.ts +26 -48
- package/src/modes/components/armin.ts +7 -7
- package/src/modes/components/extensions/extension-dashboard.ts +33 -13
- package/src/modes/components/extensions/extension-list.ts +2 -2
- package/src/modes/components/footer.ts +5 -5
- package/src/modes/components/history-search.ts +2 -1
- package/src/modes/components/hook-selector.ts +2 -2
- package/src/modes/components/index.ts +1 -1
- package/src/modes/components/model-selector.ts +7 -7
- package/src/modes/components/session-selector.ts +2 -1
- package/src/modes/components/settings-defs.ts +210 -915
- package/src/modes/components/settings-selector.ts +80 -106
- package/src/modes/components/status-line/types.ts +2 -8
- package/src/modes/components/status-line-segment-editor.ts +4 -4
- package/src/modes/components/status-line.ts +28 -5
- package/src/modes/components/welcome.ts +3 -3
- package/src/modes/controllers/command-controller.ts +2 -2
- package/src/modes/controllers/event-controller.ts +9 -8
- package/src/modes/controllers/input-controller.ts +19 -15
- package/src/modes/controllers/selector-controller.ts +30 -14
- package/src/modes/interactive-mode.ts +10 -10
- package/src/modes/rpc/rpc-mode.ts +10 -0
- package/src/modes/rpc/rpc-types.ts +3 -0
- package/src/modes/types.ts +2 -2
- package/src/modes/utils/ui-helpers.ts +4 -3
- package/src/patch/index.ts +7 -7
- package/src/patch/normalize.ts +3 -1
- package/src/prompts/system/plan-mode-active.md +5 -4
- package/src/prompts/system/system-prompt.md +0 -1
- package/src/prompts/tools/bash.md +12 -2
- package/src/prompts/tools/task.md +180 -73
- package/src/sdk.ts +38 -61
- package/src/session/agent-session.ts +66 -55
- package/src/session/agent-storage.ts +1 -1
- package/src/session/session-manager.ts +10 -10
- package/src/system-prompt.ts +2 -2
- package/src/task/executor.ts +9 -9
- package/src/task/index.ts +2 -2
- package/src/tools/ask.ts +5 -6
- package/src/tools/bash-interceptor.ts +39 -1
- package/src/tools/bash-normalize.ts +126 -0
- package/src/tools/bash.ts +31 -5
- package/src/tools/find.ts +51 -33
- package/src/tools/gemini-image.ts +7 -8
- package/src/tools/index.ts +5 -23
- package/src/tools/plan-mode-guard.ts +1 -6
- package/src/tools/python.ts +29 -4
- package/src/tools/read.ts +2 -2
- package/src/tools/write.ts +2 -2
- package/src/tui/output-block.ts +2 -2
- package/src/tui/utils.ts +2 -2
- package/src/utils/ignore-files.ts +119 -0
- package/src/web/search/auth.ts +6 -58
- package/src/web/search/index.ts +2 -6
- package/src/web/search/providers/anthropic.ts +6 -6
- package/src/web/search/providers/exa.ts +2 -62
- package/src/web/search/providers/perplexity.ts +7 -53
- package/examples/sdk/10-settings.ts +0 -37
- package/src/config/settings-manager.ts +0 -2015
|
@@ -1,22 +1,183 @@
|
|
|
1
1
|
# Task
|
|
2
2
|
|
|
3
|
-
Launch
|
|
3
|
+
Launch agents to handle complex, multi-step tasks autonomously.
|
|
4
4
|
|
|
5
5
|
<critical>
|
|
6
|
-
|
|
6
|
+
## Context is everything
|
|
7
7
|
|
|
8
|
-
Subagents
|
|
9
|
-
1.
|
|
10
|
-
2.
|
|
11
|
-
3.
|
|
8
|
+
Subagents fail when context is vague. They cannot read your mind or infer project conventions. Every task needs:
|
|
9
|
+
1. **Goal** - What this accomplishes (one sentence)
|
|
10
|
+
2. **Constraints** - Hard requirements, banned approaches, naming conventions
|
|
11
|
+
3. **Existing Code** - File paths and function signatures to use as patterns
|
|
12
|
+
4. **API Contract** - If the task produces or consumes an interface, spell it out
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
Subagents CAN grep the parent conversation file for supplementary details. They CANNOT grep for:
|
|
15
|
+
- Decisions you made but didn't write down
|
|
16
|
+
- Conventions that exist only in your head
|
|
17
|
+
- Which of 50 possible approaches you want
|
|
18
|
+
**Rule of thumb:** If you'd need to answer a clarifying question for a junior dev to do this task, that information belongs in context.
|
|
19
|
+
</critical>
|
|
14
20
|
|
|
15
|
-
|
|
21
|
+
<context-structure>
|
|
22
|
+
## Required context structure
|
|
16
23
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
24
|
+
Use this template. Sections can be omitted only if truly N/A.
|
|
25
|
+
|
|
26
|
+
````
|
|
27
|
+
## Goal
|
|
28
|
+
[One sentence: what this task accomplishes]
|
|
29
|
+
|
|
30
|
+
## Constraints
|
|
31
|
+
- [Hard requirements - MUST/MUST NOT style]
|
|
32
|
+
- [API conventions, naming patterns, error handling]
|
|
33
|
+
- [What already exists vs what to create]
|
|
34
|
+
|
|
35
|
+
## Existing Code
|
|
36
|
+
Reference files the agent MUST read or use as patterns:
|
|
37
|
+
- `path/to/file.ts` - [what pattern it demonstrates]
|
|
38
|
+
- `path/to/other.rs` - [what to reuse from it]
|
|
39
|
+
|
|
40
|
+
## API Contract (if applicable)
|
|
41
|
+
```language
|
|
42
|
+
// Exact signatures the agent must implement or consume
|
|
43
|
+
fn example(input: Type) -> Result<Output>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Task
|
|
47
|
+
{{description}}
|
|
48
|
+
|
|
49
|
+
## Files
|
|
50
|
+
{{files}}
|
|
51
|
+
````
|
|
52
|
+
|
|
53
|
+
### Bad context (agent will fail or guess wrong)
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
N-API migration. Keep highlight sync. Use JsString. No WASM.
|
|
57
|
+
Task: {{description}} Files: {{files}}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Why it fails:
|
|
61
|
+
- No existing code to reference - agent doesn't know your patterns
|
|
62
|
+
- No API contract - agent will invent signatures that don't match consumers
|
|
63
|
+
- No goal - agent doesn't know what success looks like
|
|
64
|
+
- "Keep highlight sync" is meaningless without knowing what highlight is or where it lives
|
|
65
|
+
|
|
66
|
+
### Good context (agent can act confidently)
|
|
67
|
+
|
|
68
|
+
````
|
|
69
|
+
## Goal
|
|
70
|
+
Port grep module from WASM to N-API, matching existing text module patterns.
|
|
71
|
+
|
|
72
|
+
## Constraints
|
|
73
|
+
- Use `#[napi]` attribute macro on all exports (not `#[napi(js_name = "...")]`)
|
|
74
|
+
- Return `napi::Result<T>` for fallible ops, never panic
|
|
75
|
+
- Use `spawn_blocking` for any operation that touches filesystem or runs >1ms
|
|
76
|
+
- Accept `JsString` for string params (NOT JsStringUtf8 - it has lifetime issues)
|
|
77
|
+
- Keep all existing function names - TS bindings depend on them
|
|
78
|
+
- No new crate dependencies
|
|
79
|
+
|
|
80
|
+
## Existing Code
|
|
81
|
+
- `crates/pi-natives/src/text.rs` - reference N-API pattern: see how `visible_width` uses JsString
|
|
82
|
+
- `crates/pi-natives/src/lib.rs` - module registration pattern
|
|
83
|
+
- `crates/pi-natives/Cargo.toml` - available dependencies (ignore, regex already present)
|
|
84
|
+
|
|
85
|
+
## API Contract
|
|
86
|
+
Current sync API to convert to async:
|
|
87
|
+
```rust
|
|
88
|
+
// BEFORE (sync, blocks event loop)
|
|
89
|
+
#[napi]
|
|
90
|
+
pub fn search(pattern: String, path: String) -> Vec<Match>
|
|
91
|
+
|
|
92
|
+
// AFTER (async, uses spawn_blocking)
|
|
93
|
+
#[napi]
|
|
94
|
+
pub async fn search(pattern: JsString, path: JsString, env: Env) -> napi::Result<Vec<Match>>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Task
|
|
98
|
+
{{description}}
|
|
99
|
+
|
|
100
|
+
## Files
|
|
101
|
+
{{files}}
|
|
102
|
+
````
|
|
103
|
+
</context-structure>
|
|
104
|
+
|
|
105
|
+
<parallelization>
|
|
106
|
+
## When to parallelize vs sequence
|
|
107
|
+
**The test:** Can agent B write correct code without seeing agent A's output?
|
|
108
|
+
- If YES → parallelize
|
|
109
|
+
- If NO → sequence (A completes, then B runs with A's output in context)
|
|
110
|
+
|
|
111
|
+
### Dependency patterns that MUST be sequential
|
|
112
|
+
|
|
113
|
+
|First|Then|Why|
|
|
114
|
+
|---|---|---|
|
|
115
|
+
|Create Rust API|Update TS bindings|Bindings need to know export names and signatures|
|
|
116
|
+
|Define interface/types|Implement consumers|Consumers need the contract|
|
|
117
|
+
|Scaffold with signatures|Implement bodies|Implementations need the shape|
|
|
118
|
+
|Core module|Dependent modules|Dependents import from core|
|
|
119
|
+
|
|
120
|
+
### Safe to parallelize
|
|
121
|
+
- Independent modules that don't import each other
|
|
122
|
+
- Tests for already-implemented code
|
|
123
|
+
- Documentation for stable APIs
|
|
124
|
+
- Refactors in isolated file scopes
|
|
125
|
+
|
|
126
|
+
### Phased execution pattern
|
|
127
|
+
|
|
128
|
+
For migrations/refactors with layers:
|
|
129
|
+
**Phase 1 - Foundation (do yourself or single task):**
|
|
130
|
+
Create the scaffold, define interfaces, establish API shape. Never fan out until the contract is known.
|
|
131
|
+
**Phase 2 - Parallel implementation:**
|
|
132
|
+
Fan out to independent tasks that all consume the same known interface. Include the API contract from Phase 1 in every task's context.
|
|
133
|
+
**Phase 3 - Integration (do yourself):**
|
|
134
|
+
Wire things together, update build/CI, fix any mismatches.
|
|
135
|
+
**Phase 4 - Dependent layer:**
|
|
136
|
+
Fan out again for work that consumes Phase 2 outputs.
|
|
137
|
+
|
|
138
|
+
### Example: WASM to N-API migration
|
|
139
|
+
**WRONG** (launched together, will fail):
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
tasks: [
|
|
143
|
+
{ id: "RustApi", description: "Implement N-API exports" },
|
|
144
|
+
{ id: "TsBindings", description: "Update TS to use N-API" }, // ← needs RustApi output!
|
|
145
|
+
]
|
|
146
|
+
```
|
|
147
|
+
**RIGHT** (phased):
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
// Phase 1: You create scaffold with signatures in lib.rs
|
|
151
|
+
|
|
152
|
+
// Phase 2: Fan out Rust implementation
|
|
153
|
+
tasks: [
|
|
154
|
+
{ id: "Grep", description: "Implement grep module", args: { files: "src/grep.rs" } },
|
|
155
|
+
{ id: "Text", description: "Implement text module", args: { files: "src/text.rs" } },
|
|
156
|
+
// Each task gets the API contract you defined in Phase 1
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
// Phase 3: You verify Rust compiles, exports are correct
|
|
160
|
+
|
|
161
|
+
// Phase 4: Fan out TS bindings (now they know what Rust exports)
|
|
162
|
+
tasks: [
|
|
163
|
+
{ id: "GrepBindings", description: "Update grep TS", args: { files: "src/grep/index.ts" } },
|
|
164
|
+
// Context includes actual export names from Phase 2
|
|
165
|
+
]
|
|
166
|
+
```
|
|
167
|
+
</parallelization>
|
|
168
|
+
|
|
169
|
+
<parameters>
|
|
170
|
+
- `agent`: Agent type for all tasks
|
|
171
|
+
- `context`: Template with `{{placeholders}}`. **Must follow the structure above.** Include Goal, Constraints, Existing Code references. Subagents can search parent context for background, but core requirements must be explicit here.
|
|
172
|
+
- `isolated`: (optional) Run in git worktree, return patches
|
|
173
|
+
- `tasks`: Array of `{id, description, args}`
|
|
174
|
+
- `id`: CamelCase identifier (max 32 chars)
|
|
175
|
+
- `description`: What the task does (for logging)
|
|
176
|
+
- `args`: Object with keys matching `{{placeholders}}` in context
|
|
177
|
+
- `skills`: (optional) Skill names to preload
|
|
178
|
+
- `schema`: JTD schema for response structure. **Required.** Use typed properties, not `{ "type": "string" }`.
|
|
179
|
+
**Schema goes in `schema` parameter. Never describe output format in `context`.**
|
|
180
|
+
</parameters>
|
|
20
181
|
|
|
21
182
|
<agents>
|
|
22
183
|
{{#list agents join="\n"}}
|
|
@@ -27,66 +188,12 @@ Agents with `output="structured"` enforce their own schema; the `schema` paramet
|
|
|
27
188
|
{{/list}}
|
|
28
189
|
</agents>
|
|
29
190
|
|
|
30
|
-
<instruction>
|
|
31
|
-
This matters. Be thorough.
|
|
32
|
-
1. Plan before acting. Define the goal, acceptance criteria, and scope per task.
|
|
33
|
-
2. Put shared constraints and decisions in `context`; keep each task request short and unambiguous. **Do not describe response format here.**
|
|
34
|
-
3. State whether each task is research-only or should modify files.
|
|
35
|
-
4. **Always provide a `schema`** with typed properties. Avoid `{ "type": "string" }`—if data has any structure (list, fields, categories), model it. Plain text is almost never the right choice.
|
|
36
|
-
5. Assign distinct file scopes per task to avoid conflicts.
|
|
37
|
-
6. Trust the returned data, then verify with tools when correctness matters.
|
|
38
|
-
7. The `context` must be self-contained. Paste relevant file contents, quote user requirements verbatim, include data from prior tool results. "The output user showed" means nothing to a subagent.
|
|
39
|
-
</instruction>
|
|
40
|
-
|
|
41
|
-
<parameters>
|
|
42
|
-
- `agent`: Agent type to use for all tasks
|
|
43
|
-
- `context`: Template with `\{{placeholders}}` for multi-task. Must be self-contained—include all information the subagent needs. Subagents cannot see conversation history, images, or prior tool results. Reproduce relevant content directly: paste file snippets, quote user requirements, embed data. Each placeholder is filled from task args. `\{{id}}` and `\{{description}}` are always available.
|
|
44
|
-
- `isolated`: (optional) Run each task in its own git worktree and return patches; patches are applied only if all apply cleanly.
|
|
45
|
-
- `tasks`: Array of `{id, description, args}` - tasks to run in parallel
|
|
46
|
-
- `id`: Short CamelCase identifier (max 32 chars, e.g., "SessionStore", "LspRefactor")
|
|
47
|
-
- `description`: Short human-readable description of what the task does
|
|
48
|
-
- `args`: Object with keys matching `\{{placeholders}}` in context (always include this, even if empty)
|
|
49
|
-
- `skills`: (optional) Array of skill names to preload into this task's system prompt. When set, the skills index section is omitted and the full SKILL.md contents are embedded.
|
|
50
|
-
- `schema`: JTD schema defining expected response structure. **Required.** Use objects with typed properties—e.g., `{ "properties": { "items": { "elements": { "type": "string" } } } }` for lists.
|
|
51
|
-
</parameters>
|
|
52
|
-
|
|
53
|
-
<output>
|
|
54
|
-
Returns task results for each spawned agent:
|
|
55
|
-
- Truncated preview of agent output (use `read agent://<id>` for full content if truncated)
|
|
56
|
-
- Summary with line/character counts
|
|
57
|
-
- For agents with `schema`: structured JSON accessible via `agent://<id>?q=<query>` or `agent://<id>/<path>`
|
|
58
|
-
|
|
59
|
-
Results are keyed by task `id` (e.g., "AuthProvider", "AuthApi").
|
|
60
|
-
</output>
|
|
61
|
-
|
|
62
|
-
<example>
|
|
63
|
-
user: "Looks good, execute the plan"
|
|
64
|
-
assistant: I'll execute the refactoring plan.
|
|
65
|
-
assistant: Uses the Task tool:
|
|
66
|
-
{
|
|
67
|
-
"agent": "task",
|
|
68
|
-
"context": "Refactoring the auth module into separate concerns.\n\nPlan:\n1. AuthProvider - Extract React context and provider from src/auth/index.tsx\n2. AuthApi - Extract API calls to src/auth/api.ts, use existing fetchJson helper\n3. AuthTypes - Move types to types.ts, re-export from index\n\nConstraints:\n- Preserve all existing exports from src/auth/index.tsx\n- Use project's fetchJson (src/utils/http.ts), don't use raw fetch\n- No new dependencies\n\nTask: \{{step}}\n\nFiles: \{{files}}",
|
|
69
|
-
"schema": {
|
|
70
|
-
"properties": {
|
|
71
|
-
"summary": { "type": "string" },
|
|
72
|
-
"decisions": { "elements": { "type": "string" } },
|
|
73
|
-
"concerns": { "elements": { "type": "string" } }
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
"tasks": [
|
|
77
|
-
{ "id": "AuthProvider", "description": "Extract React context", "args": { "step": "Execute step 1: Extract AuthProvider and AuthContext", "files": "src/auth/index.tsx" } },
|
|
78
|
-
{ "id": "AuthApi", "description": "Extract API layer", "args": { "step": "Execute step 2: Extract API calls to api.ts", "files": "src/auth/api.ts" } },
|
|
79
|
-
{ "id": "AuthTypes", "description": "Extract types", "args": { "step": "Execute step 3: Move types to types.ts", "files": "src/auth/types.ts" } }
|
|
80
|
-
]
|
|
81
|
-
}
|
|
82
|
-
</example>
|
|
83
|
-
|
|
84
191
|
<avoid>
|
|
85
|
-
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
|
|
92
|
-
|
|
192
|
+
- Terse context that requires agents to guess conventions
|
|
193
|
+
- Launching dependent tasks in parallel (bindings + API, consumer + producer)
|
|
194
|
+
- Missing "Existing Code" references - agents need patterns to follow
|
|
195
|
+
- Assuming agents know your codebase - they start fresh each time
|
|
196
|
+
- Describing output format in context instead of schema
|
|
197
|
+
- Single tasks doing too much - prefer focused, file-scoped tasks
|
|
198
|
+
</avoid>
|
|
199
|
+
````
|
package/src/sdk.ts
CHANGED
|
@@ -40,7 +40,7 @@ import { getAgentDir, getConfigDirPaths } from "./config";
|
|
|
40
40
|
import { ModelRegistry } from "./config/model-registry";
|
|
41
41
|
import { formatModelString, parseModelString } from "./config/model-resolver";
|
|
42
42
|
import { loadPromptTemplates as loadPromptTemplatesInternal, type PromptTemplate } from "./config/prompt-templates";
|
|
43
|
-
import {
|
|
43
|
+
import { Settings, type SkillsSettings } from "./config/settings";
|
|
44
44
|
import { CursorExecHandlers } from "./cursor";
|
|
45
45
|
import "./discovery";
|
|
46
46
|
import { initializeWithSettings } from "./discovery";
|
|
@@ -184,8 +184,8 @@ export interface CreateAgentSessionOptions {
|
|
|
184
184
|
/** Session manager. Default: SessionManager.create(cwd) */
|
|
185
185
|
sessionManager?: SessionManager;
|
|
186
186
|
|
|
187
|
-
/** Settings
|
|
188
|
-
|
|
187
|
+
/** Settings instance. Default: Settings.init({ cwd, agentDir }) */
|
|
188
|
+
settingsInstance?: Settings;
|
|
189
189
|
|
|
190
190
|
/** Whether UI is available (enables interactive tools like ask). Default: false */
|
|
191
191
|
hasUI?: boolean;
|
|
@@ -210,7 +210,7 @@ export interface CreateAgentSessionResult {
|
|
|
210
210
|
// Re-exports
|
|
211
211
|
|
|
212
212
|
export type { PromptTemplate } from "./config/prompt-templates";
|
|
213
|
-
export
|
|
213
|
+
export { Settings, type SkillsSettings } from "./config/settings";
|
|
214
214
|
export type { CustomCommand, CustomCommandFactory } from "./extensibility/custom-commands/types";
|
|
215
215
|
export type { CustomTool, CustomToolFactory } from "./extensibility/custom-tools/types";
|
|
216
216
|
export type {
|
|
@@ -430,33 +430,6 @@ export async function buildSystemPrompt(options: BuildSystemPromptOptions = {}):
|
|
|
430
430
|
});
|
|
431
431
|
}
|
|
432
432
|
|
|
433
|
-
// Settings
|
|
434
|
-
|
|
435
|
-
/**
|
|
436
|
-
* Load settings from agentDir/settings.json merged with cwd/.omp/settings.json.
|
|
437
|
-
*/
|
|
438
|
-
export async function loadSettings(cwd?: string, agentDir?: string): Promise<Settings> {
|
|
439
|
-
const manager = await SettingsManager.create(cwd ?? process.cwd(), agentDir ?? getDefaultAgentDir());
|
|
440
|
-
return {
|
|
441
|
-
modelRoles: manager.getModelRoles(),
|
|
442
|
-
defaultThinkingLevel: manager.getDefaultThinkingLevel(),
|
|
443
|
-
steeringMode: manager.getSteeringMode(),
|
|
444
|
-
followUpMode: manager.getFollowUpMode(),
|
|
445
|
-
interruptMode: manager.getInterruptMode(),
|
|
446
|
-
theme: manager.getTheme(),
|
|
447
|
-
compaction: manager.getCompactionSettings(),
|
|
448
|
-
retry: manager.getRetrySettings(),
|
|
449
|
-
hideThinkingBlock: manager.getHideThinkingBlock(),
|
|
450
|
-
shellPath: manager.getShellPath(),
|
|
451
|
-
shellForceBasic: manager.getShellForceBasic(),
|
|
452
|
-
collapseChangelog: manager.getCollapseChangelog(),
|
|
453
|
-
extensions: manager.getExtensionPaths(),
|
|
454
|
-
skills: manager.getSkillsSettings(),
|
|
455
|
-
terminal: { showImages: manager.getShowImages() },
|
|
456
|
-
images: { autoResize: manager.getImageAutoResize(), blockImages: manager.getBlockImages() },
|
|
457
|
-
};
|
|
458
|
-
}
|
|
459
|
-
|
|
460
433
|
// Internal Helpers
|
|
461
434
|
|
|
462
435
|
function createCustomToolContext(ctx: ExtensionContext): CustomToolContext {
|
|
@@ -610,14 +583,14 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
610
583
|
const modelRegistry = options.modelRegistry ?? discoverModels(authStorage, agentDir);
|
|
611
584
|
time("discoverModels");
|
|
612
585
|
|
|
613
|
-
const
|
|
614
|
-
time("
|
|
615
|
-
initializeWithSettings(
|
|
586
|
+
const settingsInstance = options.settingsInstance ?? (await Settings.init({ cwd, agentDir }));
|
|
587
|
+
time("settings");
|
|
588
|
+
initializeWithSettings(settingsInstance);
|
|
616
589
|
time("initializeWithSettings");
|
|
617
590
|
|
|
618
591
|
// Initialize provider preferences from settings
|
|
619
|
-
setPreferredWebSearchProvider(
|
|
620
|
-
setPreferredImageProvider(
|
|
592
|
+
setPreferredWebSearchProvider(settingsInstance.get("providers.webSearch") ?? "auto");
|
|
593
|
+
setPreferredImageProvider(settingsInstance.get("providers.image") ?? "auto");
|
|
621
594
|
|
|
622
595
|
const sessionManager = options.sessionManager ?? SessionManager.create(cwd);
|
|
623
596
|
time("sessionManager");
|
|
@@ -649,7 +622,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
649
622
|
|
|
650
623
|
// If still no model, try settings default
|
|
651
624
|
if (!model) {
|
|
652
|
-
const settingsDefaultModel =
|
|
625
|
+
const settingsDefaultModel = settingsInstance.getModelRole("default");
|
|
653
626
|
if (settingsDefaultModel) {
|
|
654
627
|
const parsedModel = parseModelString(settingsDefaultModel);
|
|
655
628
|
if (parsedModel) {
|
|
@@ -689,7 +662,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
689
662
|
|
|
690
663
|
// Fall back to settings default
|
|
691
664
|
if (thinkingLevel === undefined) {
|
|
692
|
-
thinkingLevel =
|
|
665
|
+
thinkingLevel = settingsInstance.get("defaultThinkingLevel") ?? "off";
|
|
693
666
|
}
|
|
694
667
|
|
|
695
668
|
// Clamp to model capabilities
|
|
@@ -705,14 +678,16 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
705
678
|
skills = options.skills;
|
|
706
679
|
skillWarnings = [];
|
|
707
680
|
} else {
|
|
708
|
-
const
|
|
681
|
+
const skillsSettings = settingsInstance.getGroup("skills") as SkillsSettings;
|
|
682
|
+
const discovered = await discoverSkills(cwd, agentDir, skillsSettings);
|
|
709
683
|
skills = discovered.skills;
|
|
710
684
|
skillWarnings = discovered.warnings;
|
|
711
685
|
}
|
|
712
686
|
time("discoverSkills");
|
|
713
687
|
|
|
714
688
|
// Discover rules
|
|
715
|
-
const
|
|
689
|
+
const ttsrSettings = settingsInstance.getGroup("ttsr");
|
|
690
|
+
const ttsrManager = new TtsrManager(ttsrSettings);
|
|
716
691
|
const rulesResult = await loadCapability<Rule>(ruleCapability.id, { cwd });
|
|
717
692
|
for (const rule of rulesResult.items) {
|
|
718
693
|
if (rule.ttsrTrigger) {
|
|
@@ -761,8 +736,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
761
736
|
},
|
|
762
737
|
getPlanModeState: () => session.getPlanModeState(),
|
|
763
738
|
getCompactContext: () => session.formatCompactContext(),
|
|
764
|
-
settings:
|
|
765
|
-
settingsManager,
|
|
739
|
+
settings: settingsInstance,
|
|
766
740
|
authStorage,
|
|
767
741
|
modelRegistry,
|
|
768
742
|
};
|
|
@@ -777,7 +751,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
777
751
|
internalRouter.register(new ArtifactProtocolHandler({ getArtifactsDir }));
|
|
778
752
|
internalRouter.register(
|
|
779
753
|
new PlanProtocolHandler({
|
|
780
|
-
getPlansDirectory:
|
|
754
|
+
getPlansDirectory: () => settingsInstance.getPlansDirectory(),
|
|
781
755
|
cwd,
|
|
782
756
|
}),
|
|
783
757
|
);
|
|
@@ -814,10 +788,10 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
814
788
|
);
|
|
815
789
|
}
|
|
816
790
|
},
|
|
817
|
-
enableProjectConfig:
|
|
791
|
+
enableProjectConfig: settingsInstance.get("mcp.enableProjectConfig") ?? true,
|
|
818
792
|
// Always filter Exa - we have native integration
|
|
819
793
|
filterExa: true,
|
|
820
|
-
cacheStorage:
|
|
794
|
+
cacheStorage: settingsInstance.getStorage(),
|
|
821
795
|
});
|
|
822
796
|
time("discoverAndLoadMCPTools");
|
|
823
797
|
mcpManager = mcpResult.manager;
|
|
@@ -847,11 +821,11 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
847
821
|
time("getGeminiImageTools");
|
|
848
822
|
|
|
849
823
|
// Add specialized Exa web search tools if EXA_API_KEY is available
|
|
850
|
-
const exaSettings =
|
|
824
|
+
const exaSettings = settingsInstance.getGroup("exa");
|
|
851
825
|
if (exaSettings.enabled && exaSettings.enableSearch) {
|
|
852
826
|
const exaWebSearchTools = await getWebSearchTools({
|
|
853
|
-
enableLinkedin: exaSettings.enableLinkedin,
|
|
854
|
-
enableCompany: exaSettings.enableCompany,
|
|
827
|
+
enableLinkedin: exaSettings.enableLinkedin as boolean,
|
|
828
|
+
enableCompany: exaSettings.enableCompany as boolean,
|
|
855
829
|
});
|
|
856
830
|
// Filter out the base web_search (already in built-in tools), add specialized Exa tools
|
|
857
831
|
const specializedTools = exaWebSearchTools.filter(t => t.name !== "web_search");
|
|
@@ -879,12 +853,15 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
879
853
|
extensionsResult = options.preloadedExtensions;
|
|
880
854
|
} else {
|
|
881
855
|
// Merge CLI extension paths with settings extension paths
|
|
882
|
-
const configuredPaths = [
|
|
856
|
+
const configuredPaths = [
|
|
857
|
+
...(options.additionalExtensionPaths ?? []),
|
|
858
|
+
...((settingsInstance.get("extensions") as string[]) ?? []),
|
|
859
|
+
];
|
|
883
860
|
extensionsResult = await discoverAndLoadExtensions(
|
|
884
861
|
configuredPaths,
|
|
885
862
|
cwd,
|
|
886
863
|
eventBus,
|
|
887
|
-
|
|
864
|
+
(settingsInstance.get("disabledExtensions") as string[]) ?? [],
|
|
888
865
|
);
|
|
889
866
|
time("discoverAndLoadExtensions");
|
|
890
867
|
for (const { path, error } of extensionsResult.errors) {
|
|
@@ -1006,7 +983,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1006
983
|
tools,
|
|
1007
984
|
toolNames,
|
|
1008
985
|
rules: rulebookRules,
|
|
1009
|
-
skillsSettings:
|
|
986
|
+
skillsSettings: settingsInstance.getGroup("skills") as SkillsSettings,
|
|
1010
987
|
isCoordinator: options.hasUI,
|
|
1011
988
|
});
|
|
1012
989
|
|
|
@@ -1022,7 +999,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1022
999
|
tools,
|
|
1023
1000
|
toolNames,
|
|
1024
1001
|
rules: rulebookRules,
|
|
1025
|
-
skillsSettings:
|
|
1002
|
+
skillsSettings: settingsInstance.getGroup("skills") as SkillsSettings,
|
|
1026
1003
|
customPrompt: options.systemPrompt,
|
|
1027
1004
|
isCoordinator: options.hasUI,
|
|
1028
1005
|
});
|
|
@@ -1062,7 +1039,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1062
1039
|
const convertToLlmWithBlockImages = (messages: AgentMessage[]): Message[] => {
|
|
1063
1040
|
const converted = convertToLlm(messages);
|
|
1064
1041
|
// Check setting dynamically so mid-session changes take effect
|
|
1065
|
-
if (!
|
|
1042
|
+
if (!settingsInstance.get("images.blockImages")) {
|
|
1066
1043
|
return converted;
|
|
1067
1044
|
}
|
|
1068
1045
|
// Filter out ImageContent from all messages, replacing with text placeholder
|
|
@@ -1115,11 +1092,11 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1115
1092
|
return extensionRunner.emitContext(messages);
|
|
1116
1093
|
}
|
|
1117
1094
|
: undefined,
|
|
1118
|
-
steeringMode:
|
|
1119
|
-
followUpMode:
|
|
1120
|
-
interruptMode:
|
|
1121
|
-
thinkingBudgets:
|
|
1122
|
-
kimiApiFormat:
|
|
1095
|
+
steeringMode: settingsInstance.get("steeringMode") ?? "one-at-a-time",
|
|
1096
|
+
followUpMode: settingsInstance.get("followUpMode") ?? "one-at-a-time",
|
|
1097
|
+
interruptMode: settingsInstance.get("interruptMode") ?? "immediate",
|
|
1098
|
+
thinkingBudgets: settingsInstance.getGroup("thinkingBudgets"),
|
|
1099
|
+
kimiApiFormat: settingsInstance.get("providers.kimiApiFormat") ?? "anthropic",
|
|
1123
1100
|
getToolContext: tc => toolContextStore.getContext(tc),
|
|
1124
1101
|
getApiKey: async () => {
|
|
1125
1102
|
const currentModel = agent.state.model;
|
|
@@ -1151,7 +1128,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1151
1128
|
session = new AgentSession({
|
|
1152
1129
|
agent,
|
|
1153
1130
|
sessionManager,
|
|
1154
|
-
|
|
1131
|
+
settings: settingsInstance,
|
|
1155
1132
|
scopedModels: options.scopedModels,
|
|
1156
1133
|
promptTemplates,
|
|
1157
1134
|
slashCommands,
|
|
@@ -1159,7 +1136,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1159
1136
|
customCommands: customCommandsResult.commands,
|
|
1160
1137
|
skills,
|
|
1161
1138
|
skillWarnings,
|
|
1162
|
-
skillsSettings:
|
|
1139
|
+
skillsSettings: settingsInstance.getGroup("skills") as Required<SkillsSettings>,
|
|
1163
1140
|
modelRegistry,
|
|
1164
1141
|
toolRegistry,
|
|
1165
1142
|
rebuildSystemPrompt,
|
|
@@ -1169,7 +1146,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1169
1146
|
|
|
1170
1147
|
// Warm up LSP servers (connects to detected servers)
|
|
1171
1148
|
let lspServers: CreateAgentSessionResult["lspServers"];
|
|
1172
|
-
if (enableLsp &&
|
|
1149
|
+
if (enableLsp && settingsInstance.get("lsp.diagnosticsOnWrite")) {
|
|
1173
1150
|
try {
|
|
1174
1151
|
const result = await warmupLspServers(cwd, {
|
|
1175
1152
|
onConnecting: serverNames => {
|