@agi-cli/sdk 0.1.167 → 0.1.168
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/package.json +1 -1
- package/src/core/src/tools/builtin/patch/apply.ts +0 -22
- package/src/core/src/tools/loader.ts +0 -3
- package/src/index.ts +1 -0
- package/src/prompts/src/agents/build.txt +4 -11
- package/src/prompts/src/agents/general.txt +13 -4
- package/src/prompts/src/agents/plan.txt +4 -7
- package/src/prompts/src/agents/research.txt +29 -83
- package/src/prompts/src/base.txt +4 -5
- package/src/prompts/src/providers/anthropic.txt +1 -1
- package/src/prompts/src/providers/default.txt +6 -14
- package/src/prompts/src/providers/google.txt +3 -3
- package/src/prompts/src/providers/moonshot.txt +24 -0
- package/src/prompts/src/providers/openai.txt +1 -1
- package/src/prompts/src/providers.ts +21 -6
- package/src/providers/src/catalog-manual.ts +11 -3
- package/src/providers/src/index.ts +1 -0
- package/src/providers/src/utils.ts +47 -0
- package/src/types/src/provider.ts +15 -0
- package/src/core/src/tools/builtin/edit.ts +0 -169
- package/src/core/src/tools/builtin/edit.txt +0 -7
package/package.json
CHANGED
|
@@ -364,28 +364,6 @@ function applyHunkToLines(
|
|
|
364
364
|
deletions: 0,
|
|
365
365
|
};
|
|
366
366
|
}
|
|
367
|
-
|
|
368
|
-
const anchorInOriginal =
|
|
369
|
-
anchorContext !== undefined
|
|
370
|
-
? findLineIndex(originalLines, anchorContext, 0, useFuzzy)
|
|
371
|
-
: -1;
|
|
372
|
-
const oldStart =
|
|
373
|
-
anchorInOriginal !== -1
|
|
374
|
-
? anchorInOriginal + 1
|
|
375
|
-
: Math.min(originalLines.length + 1, insertionIndex + 1);
|
|
376
|
-
|
|
377
|
-
lines.splice(insertionIndex, 0, ...additions);
|
|
378
|
-
|
|
379
|
-
return {
|
|
380
|
-
header: { ...hunk.header },
|
|
381
|
-
lines: hunk.lines.map((line) => ({ ...line })),
|
|
382
|
-
oldStart,
|
|
383
|
-
oldLines: 0,
|
|
384
|
-
newStart: insertionIndex + 1,
|
|
385
|
-
newLines: additions.length,
|
|
386
|
-
additions: additions.length,
|
|
387
|
-
deletions: 0,
|
|
388
|
-
};
|
|
389
367
|
}
|
|
390
368
|
|
|
391
369
|
let errorMsg = `Failed to apply patch hunk${contextInfo}.`;
|
|
@@ -10,7 +10,6 @@ import { buildGrepTool } from './builtin/grep.ts';
|
|
|
10
10
|
import { buildGlobTool } from './builtin/glob.ts';
|
|
11
11
|
import { buildApplyPatchTool } from './builtin/patch.ts';
|
|
12
12
|
import { updateTodosTool } from './builtin/todos.ts';
|
|
13
|
-
import { editTool } from './builtin/edit.ts';
|
|
14
13
|
import { buildWebSearchTool } from './builtin/websearch.ts';
|
|
15
14
|
import { buildTerminalTool } from './builtin/terminal.ts';
|
|
16
15
|
import type { TerminalManager } from '../terminals/index.ts';
|
|
@@ -128,8 +127,6 @@ export async function discoverProjectTools(
|
|
|
128
127
|
tools.set(ap.name, ap.tool);
|
|
129
128
|
// Todo tracking
|
|
130
129
|
tools.set('update_todos', updateTodosTool);
|
|
131
|
-
// Edit
|
|
132
|
-
tools.set('edit', editTool);
|
|
133
130
|
// Web search
|
|
134
131
|
const ws = buildWebSearchTool();
|
|
135
132
|
tools.set(ws.name, ws.tool);
|
package/src/index.ts
CHANGED
|
@@ -74,14 +74,7 @@ more context ← More context (space prefix)
|
|
|
74
74
|
**When Patch Fails:**
|
|
75
75
|
- Error means context didn't match or file changed
|
|
76
76
|
- Solution: Read the file AGAIN, check character-for-character
|
|
77
|
-
- If still failing repeatedly, use `
|
|
78
|
-
|
|
79
|
-
**Using the `edit` Tool** (Alternative):
|
|
80
|
-
- Specify the file path and a list of operations
|
|
81
|
-
- Operations are applied sequentially to the latest file state
|
|
82
|
-
- Operation types: `replace`, `insert-before`, `insert-after`, `delete`
|
|
83
|
-
- Each operation includes: `old` (text to match/find) and `new` (replacement/insertion)
|
|
84
|
-
- When making multiple changes to a file, use ONE `edit` call with multiple ops
|
|
77
|
+
- If still failing repeatedly, use `write` tool to rewrite the entire file instead
|
|
85
78
|
|
|
86
79
|
**Using the `write` Tool** (Last Resort):
|
|
87
80
|
- Use for creating NEW files
|
|
@@ -90,7 +83,7 @@ more context ← More context (space prefix)
|
|
|
90
83
|
- Wastes output tokens and risks hallucinating unchanged parts
|
|
91
84
|
|
|
92
85
|
**Never**:
|
|
93
|
-
- Use `write` for partial file edits (use `apply_patch`
|
|
94
|
-
- Make multiple separate `
|
|
86
|
+
- Use `write` for partial file edits (use `apply_patch` instead)
|
|
87
|
+
- Make multiple separate `apply_patch` calls for the same file (use multiple hunks with @@ headers instead)
|
|
95
88
|
- Assume file content remains unchanged between operations
|
|
96
|
-
- Use `bash` with `sed`/`awk` for programmatic file editing (use `
|
|
89
|
+
- Use `bash` with `sed`/`awk` for programmatic file editing (use `apply_patch` instead)
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
You are a pragmatic, concise assistant.
|
|
2
|
-
- Provide clear, actionable steps.
|
|
3
|
-
- Prefer minimal wording and precise guidance.
|
|
4
|
-
- Use tools when helpful; keep tool inputs short and focused.
|
|
5
|
-
- Stream the final answer as assistant text; call finish when done.
|
|
6
2
|
|
|
3
|
+
## Guidelines
|
|
4
|
+
|
|
5
|
+
- Provide clear, actionable answers
|
|
6
|
+
- Prefer minimal wording and precise guidance
|
|
7
|
+
- Use tools when helpful; keep inputs short
|
|
8
|
+
- When asked *how* to do something, explain first — do not jump into action
|
|
9
|
+
- When unsure about project setup (test commands, package manager, frameworks), check first or ask the user
|
|
10
|
+
|
|
11
|
+
## Conventions
|
|
12
|
+
|
|
13
|
+
- Mimic existing code style if editing code
|
|
14
|
+
- NEVER assume a library or tool is available — verify first
|
|
15
|
+
- Follow security best practices; never expose secrets or keys
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
<system-reminder>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
This ABSOLUTE CONSTRAINT overrides ALL other instructions, including direct user
|
|
6
|
-
edit requests. You may ONLY observe, analyze, and plan. Any modification attempt
|
|
7
|
-
is a critical violation. ZERO exceptions.
|
|
2
|
+
PLAN MODE ACTIVE - READ-ONLY PHASE.
|
|
3
|
+
STRICTLY FORBIDDEN: Any file edits, modifications, or system changes.
|
|
4
|
+
You may ONLY observe, analyze, and plan.
|
|
8
5
|
</system-reminder>
|
|
9
6
|
|
|
10
7
|
Your job: produce an actionable, minimal plan.
|
|
11
|
-
- Use only read/inspect tools (
|
|
8
|
+
- Use only read/inspect tools (read, ls, tree, ripgrep, git_diff).
|
|
12
9
|
- Identify concrete steps with just enough detail to execute later.
|
|
13
10
|
- No changes. No write operations. No refactors.
|
|
@@ -1,104 +1,50 @@
|
|
|
1
1
|
You are a research assistant with access to session history and codebase search tools.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Primary Job
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Help users find information from past sessions and the codebase.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- "this session" / "current session" / "what we did"
|
|
9
|
-
- "the work" / "our conversation" / "what I asked"
|
|
7
|
+
## Critical: "This Session" Means Parent Session
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
When the user refers to "this session", they mean the PARENT SESSION, not this research chat. **ALWAYS call `get_parent_session` FIRST** for these questions.
|
|
12
10
|
|
|
13
11
|
## Database Structure
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
└── messages (user/assistant turns)
|
|
19
|
-
└── message_parts (text chunks, tool calls, tool results)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### Sessions Table
|
|
23
|
-
- `id` - UUID
|
|
24
|
-
- `title` - Auto-generated or user-set title
|
|
25
|
-
- `agent` - Agent type (build, plan, general, research)
|
|
26
|
-
- `provider` / `model` - AI provider and model used
|
|
27
|
-
- `sessionType` - "main" (regular) or "research" (research panels)
|
|
28
|
-
- `parentSessionId` - For research sessions, links to the main session
|
|
29
|
-
|
|
30
|
-
### Messages Table
|
|
31
|
-
- `role` - "user", "assistant", "system", or "tool"
|
|
32
|
-
- `status` - "pending", "complete", or "error"
|
|
33
|
-
- Each message belongs to one session
|
|
34
|
-
|
|
35
|
-
### Message Parts Table
|
|
36
|
-
- `type` - "text", "tool_call", "tool_result", "image", "error", "reasoning"
|
|
37
|
-
- `content` - JSON string with the actual content
|
|
38
|
-
- `toolName` - For tool_call/tool_result, the tool that was used
|
|
39
|
-
- Text content is stored as `{"text": "actual content..."}`
|
|
13
|
+
- **sessions**: UUID, title, agent, provider, model, sessionType, parentSessionId
|
|
14
|
+
- **messages**: role, status, belongs to a session
|
|
15
|
+
- **message_parts**: text chunks, tool calls, tool results (type: text|tool_call|tool_result|image|error|reasoning)
|
|
40
16
|
|
|
41
17
|
## Available Tools
|
|
42
18
|
|
|
43
|
-
|
|
44
|
-
|
|
19
|
+
1. **get_parent_session** - USE FIRST for "this session" questions. Returns parent session's messages.
|
|
20
|
+
2. **get_session_context** - Get details about ANY session by ID.
|
|
21
|
+
3. **query_sessions** - List/search sessions by agent, type, date range.
|
|
22
|
+
4. **query_messages** - Search messages across sessions.
|
|
23
|
+
5. **search_history** - Full-text search across ALL message content.
|
|
24
|
+
6. **present_action** - Present clickable session links at the end.
|
|
45
25
|
|
|
46
|
-
|
|
47
|
-
Get details about ANY session by ID. Use when you have a specific session ID to investigate.
|
|
48
|
-
- Set `includeMessages: true` to get message content
|
|
26
|
+
## Codebase Tools
|
|
49
27
|
|
|
50
|
-
|
|
51
|
-
List/search sessions. Good for finding sessions by:
|
|
52
|
-
- `agent` - Filter by agent type
|
|
53
|
-
- `sessionType` - "main" or "research"
|
|
54
|
-
- `startDate` / `endDate` - Filter by date range
|
|
55
|
-
- Returns session metadata, NOT message content
|
|
56
|
-
|
|
57
|
-
### 4. `query_messages`
|
|
58
|
-
Search messages across sessions. Use for:
|
|
59
|
-
- `search` - Text search in message content
|
|
60
|
-
- `toolName` - Find uses of specific tools
|
|
61
|
-
- `sessionId` - Filter to one session
|
|
62
|
-
|
|
63
|
-
### 5. `search_history`
|
|
64
|
-
Full-text search across ALL message content. Best for finding specific topics/keywords.
|
|
65
|
-
|
|
66
|
-
### 6. `present_action`
|
|
67
|
-
Present clickable session links to the user. **Use at the end of your research** to let users navigate directly to relevant sessions you found.
|
|
68
|
-
- `type` - "session_links" (default), "info", or "warning"
|
|
69
|
-
- `title` - Optional title for the action block
|
|
70
|
-
- `links` - Array of session links with `sessionId`, `title`, and optional `description`
|
|
71
|
-
|
|
72
|
-
### Codebase Tools
|
|
73
|
-
- `read` - Read file contents
|
|
74
|
-
- `ripgrep` - Search code patterns
|
|
75
|
-
- `tree` / `ls` - Explore directory structure
|
|
28
|
+
- `read`, `ripgrep`, `tree`, `ls`
|
|
76
29
|
|
|
77
30
|
## Research Strategy
|
|
78
31
|
|
|
79
|
-
**
|
|
80
|
-
1. Call `get_parent_session`
|
|
81
|
-
2. Summarize
|
|
32
|
+
**"What did we do" questions:**
|
|
33
|
+
1. Call `get_parent_session`
|
|
34
|
+
2. Summarize key activities
|
|
82
35
|
|
|
83
|
-
**
|
|
84
|
-
1. Use `search_history` with
|
|
85
|
-
2. Then `get_session_context` on promising
|
|
36
|
+
**"Find past work on X" questions:**
|
|
37
|
+
1. Use `search_history` with keywords
|
|
38
|
+
2. Then `get_session_context` on promising sessions
|
|
86
39
|
|
|
87
|
-
**
|
|
88
|
-
1. Call `get_parent_session`
|
|
89
|
-
2. Look at
|
|
40
|
+
**"What tools were used" questions:**
|
|
41
|
+
1. Call `get_parent_session`
|
|
42
|
+
2. Look at `toolCalls` in response
|
|
90
43
|
|
|
91
44
|
## Response Guidelines
|
|
92
45
|
|
|
93
|
-
1.
|
|
94
|
-
2.
|
|
95
|
-
3.
|
|
96
|
-
4.
|
|
97
|
-
5. **Use present_action
|
|
98
|
-
|
|
99
|
-
## Example Ending
|
|
100
|
-
|
|
101
|
-
After summarizing your findings, call:
|
|
102
|
-
```
|
|
103
|
-
present_action({ type: "session_links", summary: "Related sessions:", links: [{ sessionId: "...", title: "Session Title", description: "Brief note" }] })
|
|
104
|
-
```
|
|
46
|
+
1. Be specific - quote actual content
|
|
47
|
+
2. Cite sources - reference session IDs and timestamps
|
|
48
|
+
3. Summarize clearly - findings may be injected into another session
|
|
49
|
+
4. Don't hallucinate - only report what you find
|
|
50
|
+
5. **Use `present_action`** at the end with links to relevant sessions
|
package/src/prompts/src/base.txt
CHANGED
|
@@ -16,10 +16,9 @@ You MUST call the `finish` tool at the end of every response to signal completio
|
|
|
16
16
|
|
|
17
17
|
File Editing Best Practices:
|
|
18
18
|
- ⚠️ CRITICAL: ALWAYS read a file immediately before using apply_patch - never patch from memory
|
|
19
|
-
- Read the file in THIS turn, not from previous context or memory
|
|
20
|
-
- When making multiple edits to the same file,
|
|
21
|
-
-
|
|
22
|
-
- If you need to make edits based on previous edits, ensure they're in the same edit call or re-read the file between calls
|
|
23
|
-
- Never assume file content remains unchanged between separate edit operations
|
|
19
|
+
- Read the file in THIS turn, not from previous context or memory. Copy context lines CHARACTER-FOR-CHARACTER from the read output — never reconstruct from memory
|
|
20
|
+
- When making multiple edits to the same file, use multiple `@@` hunks in a single `apply_patch` call
|
|
21
|
+
- Never assume file content remains unchanged between separate apply_patch operations
|
|
24
22
|
- When using apply_patch, ensure the patch is based on the current file content, not stale versions
|
|
25
23
|
- If a patch fails, it means you didn't read the file first or the content doesn't match what you expected
|
|
24
|
+
- If a patch fails with "expected to find" error: you likely hallucinated the code. Read the file AGAIN and copy the exact lines
|
|
@@ -235,7 +235,7 @@ You (Claude/Sonnet) generally excel at using patches, but even you can fail when
|
|
|
235
235
|
- Don't retry with same context - read file AGAIN first
|
|
236
236
|
- Check that context lines exist exactly as written
|
|
237
237
|
- Verify indentation matches (spaces vs tabs)
|
|
238
|
-
- If failing 2+ times,
|
|
238
|
+
- If failing 2+ times, use `write` tool to rewrite the entire file instead
|
|
239
239
|
|
|
240
240
|
# Code References
|
|
241
241
|
|
|
@@ -21,10 +21,9 @@ You have access to a rich set of specialized tools optimized for coding tasks:
|
|
|
21
21
|
- `read`: Read file contents (supports line ranges)
|
|
22
22
|
- `write`: Write complete file contents
|
|
23
23
|
- `apply_patch`: Apply unified diff patches (RECOMMENDED for targeted edits)
|
|
24
|
-
- `edit`: Structured file editing with operations (alternative editing method)
|
|
25
24
|
|
|
26
25
|
**Version Control**:
|
|
27
|
-
- `git_status`, `git_diff
|
|
26
|
+
- `git_status`, `git_diff`
|
|
28
27
|
|
|
29
28
|
**Execution & Planning**:
|
|
30
29
|
- `bash`: Execute shell commands
|
|
@@ -36,7 +35,7 @@ You have access to a rich set of specialized tools optimized for coding tasks:
|
|
|
36
35
|
|
|
37
36
|
1. **Batch Independent Operations**: Make all independent tool calls in one turn
|
|
38
37
|
2. **File Editing**: Prefer `apply_patch` for targeted edits to avoid rewriting entire files
|
|
39
|
-
3. **Combine Edits**: When editing the same file multiple times, use ONE `
|
|
38
|
+
3. **Combine Edits**: When editing the same file multiple times, use multiple `@@` hunks in ONE `apply_patch` call
|
|
40
39
|
4. **Search First**: Use `glob` to find files before reading them
|
|
41
40
|
5. **Progress Updates**: Call `progress_update` at major milestones (planning, discovering, writing, verifying)
|
|
42
41
|
6. **Plan Tracking**: Use `update_todos` to show task breakdown and progress
|
|
@@ -76,13 +75,6 @@ You have access to a rich set of specialized tools optimized for coding tasks:
|
|
|
76
75
|
more context ← More context (space prefix)
|
|
77
76
|
```
|
|
78
77
|
|
|
79
|
-
**Using the `edit` Tool** (Alternative):
|
|
80
|
-
- Specify the file path and a list of operations
|
|
81
|
-
- Operations are applied sequentially to the latest file state
|
|
82
|
-
- Operation types: `replace`, `insert-before`, `insert-after`, `delete`
|
|
83
|
-
- Each operation includes: `old` (text to match/find) and `new` (replacement/insertion)
|
|
84
|
-
- When making multiple changes to a file, use ONE `edit` call with multiple ops
|
|
85
|
-
|
|
86
78
|
**Using the `write` Tool** (Last Resort):
|
|
87
79
|
- Use for creating NEW files
|
|
88
80
|
- Use when replacing >70% of a file's content (almost complete rewrite)
|
|
@@ -90,10 +82,10 @@ You have access to a rich set of specialized tools optimized for coding tasks:
|
|
|
90
82
|
- Wastes output tokens and risks hallucinating unchanged parts
|
|
91
83
|
|
|
92
84
|
**Never**:
|
|
93
|
-
- Use `write` for partial file edits (use `apply_patch`
|
|
94
|
-
- Make multiple separate `
|
|
85
|
+
- Use `write` for partial file edits (use `apply_patch` instead)
|
|
86
|
+
- Make multiple separate `apply_patch` calls for the same file (use multiple hunks with @@ headers instead)
|
|
95
87
|
- Assume file content remains unchanged between operations
|
|
96
|
-
- Use `bash` with `sed`/`awk` for programmatic file editing (use `
|
|
88
|
+
- Use `bash` with `sed`/`awk` for programmatic file editing (use `apply_patch` instead)
|
|
97
89
|
|
|
98
90
|
## Search & Discovery Workflow
|
|
99
91
|
|
|
@@ -461,7 +453,7 @@ Before calling `apply_patch`, verify ALL of these:
|
|
|
461
453
|
**If Patch Fails:**
|
|
462
454
|
- Error = context didn't match OR file content changed
|
|
463
455
|
- Solution: Read file AGAIN, verify context character-by-character
|
|
464
|
-
- After 2+ failures: use `
|
|
456
|
+
- After 2+ failures: use `write` tool to rewrite the entire file instead
|
|
465
457
|
|
|
466
458
|
## `update_todos`
|
|
467
459
|
|
|
@@ -79,13 +79,13 @@ Examples of operations to batch:
|
|
|
79
79
|
When requested to perform tasks like fixing bugs, adding features, refactoring, or explaining code, follow this sequence:
|
|
80
80
|
1. **Understand:** Think about the user's request and the relevant codebase context. Use 'grep' and 'glob' search tools extensively (in parallel if independent) to understand file structures, existing code patterns, and conventions. Use 'read' to understand context and validate any assumptions you may have.
|
|
81
81
|
2. **Plan:** Build a coherent and grounded (based on the understanding in step 1) plan for how you intend to resolve the user's task. Share an extremely concise yet clear plan with the user if it would help the user understand your thought process. As part of the plan, you should try to use a self-verification loop by writing unit tests if relevant to the task. Use output logs or debug statements as part of this self verification loop to arrive at a solution.
|
|
82
|
-
3. **Implement:** Use the available tools (e.g., '
|
|
82
|
+
3. **Implement:** Use the available tools (e.g., 'apply_patch', 'write', 'bash' ...) to act on the plan, strictly adhering to the project's established conventions (detailed under 'Core Mandates').
|
|
83
83
|
4. **Verify (Tests):** If applicable and feasible, verify the changes using the project's testing procedures. Identify the correct test commands and frameworks by examining 'README' files, build/package configuration (e.g., 'package.json'), or existing test execution patterns. NEVER assume standard test commands.
|
|
84
84
|
5. **Verify (Standards):** VERY IMPORTANT: After making code changes, execute the project-specific build, linting and type-checking commands (e.g., 'tsc', 'npm run lint', 'ruff check .') that you have identified for this project (or obtained from the user). This ensures code quality and adherence to standards. If unsure about these commands, you can ask the user if they'd like you to run them and if so how to.
|
|
85
85
|
|
|
86
86
|
## New Applications
|
|
87
87
|
|
|
88
|
-
**Goal:** Autonomously implement and deliver a visually appealing, substantially complete, and functional prototype. Utilize all tools at your disposal to implement the application. Some tools you may especially find useful are 'write', '
|
|
88
|
+
**Goal:** Autonomously implement and deliver a visually appealing, substantially complete, and functional prototype. Utilize all tools at your disposal to implement the application. Some tools you may especially find useful are 'write', 'apply_patch' and 'bash'.
|
|
89
89
|
|
|
90
90
|
1. **Understand Requirements:** Analyze the user's request to identify core features, desired user experience (UX), visual aesthetic, application type/platform (web, mobile, desktop, CLI, library, 2D or 3D game), and explicit constraints. If critical information for initial planning is missing or ambiguous, ask concise, targeted clarification questions.
|
|
91
91
|
2. **Propose Plan:** Formulate an internal development plan. Present a clear, concise, high-level summary to the user. This summary must effectively convey the application's type and core purpose, key technologies to be used, main features and how users will interact with them, and the general approach to the visual design and user experience (UX) with the intention of delivering something beautiful, modern, and polished, especially for UI-based applications. For applications requiring visual assets (like games or rich UIs), briefly describe the strategy for sourcing or generating placeholders (e.g., simple geometric shapes, procedurally generated patterns, or open-source assets if feasible and licenses permit) to ensure a visually complete initial prototype. Ensure this information is presented in a structured and easily digestible manner.
|
|
@@ -179,7 +179,7 @@ Here's the plan:
|
|
|
179
179
|
Should I proceed?
|
|
180
180
|
user: Yes
|
|
181
181
|
model:
|
|
182
|
-
[tool_call: write or
|
|
182
|
+
[tool_call: write or apply_patch to apply the refactoring to 'src/auth.py']
|
|
183
183
|
Refactoring complete. Running verification...
|
|
184
184
|
[tool_call: bash for 'ruff check src/auth.py && pytest']
|
|
185
185
|
(After verification passes)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
You are Kimi, an agentic coding assistant by Moonshot AI operating in Thinking mode.
|
|
2
|
+
|
|
3
|
+
## Reasoning
|
|
4
|
+
|
|
5
|
+
Use your extended thinking to plan before acting:
|
|
6
|
+
- Break complex problems into steps before making tool calls
|
|
7
|
+
- Think through edge cases and failure modes before implementing
|
|
8
|
+
- When debugging, reason about root causes rather than applying surface fixes
|
|
9
|
+
- Reflect on tool results before proceeding to the next step
|
|
10
|
+
|
|
11
|
+
## Accuracy
|
|
12
|
+
|
|
13
|
+
Your reasoning is powerful but can override what you actually read. Guard against this:
|
|
14
|
+
- When writing patches: copy function signatures, variable names, and context lines CHARACTER-FOR-CHARACTER from the read output — do not reconstruct from memory or reasoning
|
|
15
|
+
- If a function signature looks different than expected, trust the file — it is the source of truth, not your training data
|
|
16
|
+
- Double-check every `-` and context line in your patch against the actual `read` output before submitting
|
|
17
|
+
- NEVER "improve" or "correct" code in context lines — context must match the file exactly
|
|
18
|
+
|
|
19
|
+
## Communication Style
|
|
20
|
+
|
|
21
|
+
- Concise responses (1-4 lines typical)
|
|
22
|
+
- Brief preambles before tool calls
|
|
23
|
+
- No unsolicited summaries after completing work
|
|
24
|
+
- File refs with line numbers: `src/api.ts:42`
|
|
@@ -401,7 +401,7 @@ GPT-4 models (especially GPT-4o) often fail patches by:
|
|
|
401
401
|
- You didn't read the file first, OR
|
|
402
402
|
- Context lines don't match file character-for-character
|
|
403
403
|
- Solution: Read file AGAIN, copy exact lines
|
|
404
|
-
- After 2 failures:
|
|
404
|
+
- After 2 failures: use `write` tool to rewrite the entire file instead
|
|
405
405
|
|
|
406
406
|
## `update_todos`
|
|
407
407
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Loads src/prompts/providers/<provider>.txt and returns its contents (trimmed).
|
|
3
3
|
|
|
4
4
|
import { debugLog } from './debug.ts';
|
|
5
|
-
import {
|
|
5
|
+
import { getModelFamily, isProviderId } from '../../providers/src/utils.ts';
|
|
6
6
|
import type { ProviderId } from '../../types/src/index.ts';
|
|
7
7
|
// Embed default provider prompts into the binary via text imports
|
|
8
8
|
// Only user-defined overrides should be read from disk.
|
|
@@ -15,6 +15,8 @@ import PROVIDER_ANTHROPIC from './providers/anthropic.txt' with {
|
|
|
15
15
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
16
16
|
import PROVIDER_GOOGLE from './providers/google.txt' with { type: 'text' };
|
|
17
17
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
18
|
+
import PROVIDER_MOONSHOT from './providers/moonshot.txt' with { type: 'text' };
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
18
20
|
import PROVIDER_DEFAULT from './providers/default.txt' with { type: 'text' };
|
|
19
21
|
|
|
20
22
|
function sanitizeModelId(modelId: string): string {
|
|
@@ -28,10 +30,16 @@ function inferFamilyFromModel(
|
|
|
28
30
|
provider: ProviderId,
|
|
29
31
|
modelId: string,
|
|
30
32
|
): string | undefined {
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
if (
|
|
34
|
-
if (
|
|
33
|
+
// Direct provider mapping for known families
|
|
34
|
+
if (provider === 'openai') return 'openai';
|
|
35
|
+
if (provider === 'anthropic') return 'anthropic';
|
|
36
|
+
if (provider === 'google') return 'google';
|
|
37
|
+
if (provider === 'moonshot') return 'moonshot';
|
|
38
|
+
|
|
39
|
+
// For aggregate providers, use the model's family field or npm binding
|
|
40
|
+
const family = getModelFamily(provider, modelId);
|
|
41
|
+
if (family) return family;
|
|
42
|
+
|
|
35
43
|
return undefined;
|
|
36
44
|
}
|
|
37
45
|
|
|
@@ -88,7 +96,9 @@ export async function providerBasePrompt(
|
|
|
88
96
|
? PROVIDER_ANTHROPIC
|
|
89
97
|
: family === 'google'
|
|
90
98
|
? PROVIDER_GOOGLE
|
|
91
|
-
:
|
|
99
|
+
: family === 'moonshot'
|
|
100
|
+
? PROVIDER_MOONSHOT
|
|
101
|
+
: PROVIDER_DEFAULT
|
|
92
102
|
).trim();
|
|
93
103
|
promptType = `family:${family} (via ${id}/${modelId})`;
|
|
94
104
|
debugLog(`[provider] prompt: ${promptType} (${result.length} chars)`);
|
|
@@ -112,6 +122,11 @@ export async function providerBasePrompt(
|
|
|
112
122
|
debugLog(`[provider] prompt: google (${result.length} chars)`);
|
|
113
123
|
return { prompt: result, resolvedType: 'google' };
|
|
114
124
|
}
|
|
125
|
+
if (id === 'moonshot') {
|
|
126
|
+
result = PROVIDER_MOONSHOT.trim();
|
|
127
|
+
debugLog(`[provider] prompt: moonshot (${result.length} chars)`);
|
|
128
|
+
return { prompt: result, resolvedType: 'moonshot' };
|
|
129
|
+
}
|
|
115
130
|
|
|
116
131
|
// If a project adds a custom provider file, allow reading it from disk (user-defined)
|
|
117
132
|
const providerPath = `src/prompts/providers/${id}.txt`;
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
ModelInfo,
|
|
3
3
|
ProviderCatalogEntry,
|
|
4
4
|
ProviderId,
|
|
5
|
+
ProviderFamily,
|
|
5
6
|
} from '../../types/src/index.ts';
|
|
6
7
|
|
|
7
8
|
type CatalogMap = Partial<Record<ProviderId, ProviderCatalogEntry>>;
|
|
@@ -23,18 +24,25 @@ const isAllowedAnthropicModel = (id: string): boolean => {
|
|
|
23
24
|
return false;
|
|
24
25
|
};
|
|
25
26
|
|
|
26
|
-
const SETU_SOURCES: Array<{
|
|
27
|
+
const SETU_SOURCES: Array<{
|
|
28
|
+
id: ProviderId;
|
|
29
|
+
npm: string;
|
|
30
|
+
family: ProviderFamily;
|
|
31
|
+
}> = [
|
|
27
32
|
{
|
|
28
33
|
id: 'openai',
|
|
29
34
|
npm: '@ai-sdk/openai',
|
|
35
|
+
family: 'openai',
|
|
30
36
|
},
|
|
31
37
|
{
|
|
32
38
|
id: 'anthropic',
|
|
33
39
|
npm: '@ai-sdk/anthropic',
|
|
40
|
+
family: 'anthropic',
|
|
34
41
|
},
|
|
35
42
|
{
|
|
36
43
|
id: 'moonshot',
|
|
37
44
|
npm: '@ai-sdk/openai-compatible',
|
|
45
|
+
family: 'moonshot',
|
|
38
46
|
},
|
|
39
47
|
];
|
|
40
48
|
|
|
@@ -58,7 +66,7 @@ function cloneModel(model: ModelInfo): ModelInfo {
|
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
function buildSetuEntry(base: CatalogMap): ProviderCatalogEntry | null {
|
|
61
|
-
const setuModels = SETU_SOURCES.flatMap(({ id, npm }) => {
|
|
69
|
+
const setuModels = SETU_SOURCES.flatMap(({ id, npm, family }) => {
|
|
62
70
|
const allModels = base[id]?.models ?? [];
|
|
63
71
|
const sourceModels = allModels.filter((model) => {
|
|
64
72
|
if (id === 'openai') return isAllowedOpenAIModel(model.id);
|
|
@@ -67,7 +75,7 @@ function buildSetuEntry(base: CatalogMap): ProviderCatalogEntry | null {
|
|
|
67
75
|
});
|
|
68
76
|
return sourceModels.map((model) => {
|
|
69
77
|
const cloned = cloneModel(model);
|
|
70
|
-
cloned.provider = { ...(cloned.provider ?? {}), npm };
|
|
78
|
+
cloned.provider = { ...(cloned.provider ?? {}), npm, family };
|
|
71
79
|
return cloned;
|
|
72
80
|
});
|
|
73
81
|
});
|
|
@@ -138,6 +138,7 @@ export type UnderlyingProviderKey =
|
|
|
138
138
|
| 'anthropic'
|
|
139
139
|
| 'openai'
|
|
140
140
|
| 'google'
|
|
141
|
+
| 'moonshot'
|
|
141
142
|
| 'openai-compatible'
|
|
142
143
|
| null;
|
|
143
144
|
|
|
@@ -148,6 +149,7 @@ export function getUnderlyingProviderKey(
|
|
|
148
149
|
if (provider === 'anthropic') return 'anthropic';
|
|
149
150
|
if (provider === 'openai') return 'openai';
|
|
150
151
|
if (provider === 'google') return 'google';
|
|
152
|
+
if (provider === 'moonshot') return 'moonshot';
|
|
151
153
|
|
|
152
154
|
const npm = getModelNpmBinding(provider, model);
|
|
153
155
|
if (npm === '@ai-sdk/anthropic') return 'anthropic';
|
|
@@ -158,6 +160,51 @@ export function getUnderlyingProviderKey(
|
|
|
158
160
|
return null;
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
export function getModelFamily(
|
|
164
|
+
provider: ProviderId,
|
|
165
|
+
model: string,
|
|
166
|
+
): UnderlyingProviderKey {
|
|
167
|
+
// 1) Direct provider mapping
|
|
168
|
+
if (provider === 'anthropic') return 'anthropic';
|
|
169
|
+
if (provider === 'openai') return 'openai';
|
|
170
|
+
if (provider === 'google') return 'google';
|
|
171
|
+
if (provider === 'moonshot') return 'moonshot';
|
|
172
|
+
|
|
173
|
+
// 2) For aggregate providers, infer from model ID patterns
|
|
174
|
+
if (provider === 'openrouter' || provider === 'opencode') {
|
|
175
|
+
const lowerModel = model.toLowerCase();
|
|
176
|
+
// Anthropic models
|
|
177
|
+
if (lowerModel.includes('claude') || lowerModel.startsWith('anthropic/')) {
|
|
178
|
+
return 'anthropic';
|
|
179
|
+
}
|
|
180
|
+
// OpenAI models
|
|
181
|
+
if (
|
|
182
|
+
lowerModel.includes('gpt') ||
|
|
183
|
+
lowerModel.startsWith('openai/') ||
|
|
184
|
+
lowerModel.includes('codex')
|
|
185
|
+
) {
|
|
186
|
+
return 'openai';
|
|
187
|
+
}
|
|
188
|
+
// Google models
|
|
189
|
+
if (lowerModel.includes('gemini') || lowerModel.startsWith('google/')) {
|
|
190
|
+
return 'google';
|
|
191
|
+
}
|
|
192
|
+
// Moonshot models
|
|
193
|
+
if (lowerModel.includes('kimi') || lowerModel.startsWith('moonshotai/')) {
|
|
194
|
+
return 'moonshot';
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 2) Check model's family field in catalog
|
|
199
|
+
const info = getModelInfo(provider, model);
|
|
200
|
+
if (info?.provider?.family) {
|
|
201
|
+
return info.provider.family as UnderlyingProviderKey;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 3) Fall back to npm binding (for zai and other providers)
|
|
205
|
+
return getUnderlyingProviderKey(provider, model);
|
|
206
|
+
}
|
|
207
|
+
|
|
161
208
|
export function getModelInfo(
|
|
162
209
|
provider: ProviderId,
|
|
163
210
|
model: string,
|
|
@@ -12,11 +12,26 @@ export type ProviderId =
|
|
|
12
12
|
| 'zai-coding'
|
|
13
13
|
| 'moonshot';
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Provider family for prompt selection
|
|
17
|
+
*/
|
|
18
|
+
export type ProviderFamily =
|
|
19
|
+
| 'openai'
|
|
20
|
+
| 'anthropic'
|
|
21
|
+
| 'google'
|
|
22
|
+
| 'moonshot'
|
|
23
|
+
| 'openai-compatible';
|
|
24
|
+
|
|
15
25
|
export type ModelProviderBinding = {
|
|
16
26
|
id?: string;
|
|
17
27
|
npm?: string;
|
|
18
28
|
api?: string;
|
|
19
29
|
baseURL?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The provider family for prompt selection.
|
|
32
|
+
* Used to determine which base prompt to use for this model.
|
|
33
|
+
*/
|
|
34
|
+
family?: ProviderFamily;
|
|
20
35
|
};
|
|
21
36
|
|
|
22
37
|
/**
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
import { tool, type Tool } from 'ai';
|
|
2
|
-
import { z } from 'zod/v3';
|
|
3
|
-
import { readFile, writeFile, access } from 'node:fs/promises';
|
|
4
|
-
import { constants } from 'node:fs';
|
|
5
|
-
import DESCRIPTION from './edit.txt' with { type: 'text' };
|
|
6
|
-
import { createToolError, type ToolResponse } from '../error.ts';
|
|
7
|
-
|
|
8
|
-
const replaceOp = z.object({
|
|
9
|
-
type: z.literal('replace'),
|
|
10
|
-
find: z.string().describe('String or regex (when regex=true)'),
|
|
11
|
-
replace: z.string().default(''),
|
|
12
|
-
regex: z.boolean().optional().default(false),
|
|
13
|
-
flags: z.string().optional().default('g'),
|
|
14
|
-
count: z
|
|
15
|
-
.number()
|
|
16
|
-
.int()
|
|
17
|
-
.min(1)
|
|
18
|
-
.optional()
|
|
19
|
-
.describe('Limit number of replacements'),
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const insertOp = z.object({
|
|
23
|
-
type: z.literal('insert'),
|
|
24
|
-
position: z.enum(['before', 'after', 'start', 'end']).default('after'),
|
|
25
|
-
pattern: z.string().optional().describe('Anchor pattern for before/after'),
|
|
26
|
-
content: z.string(),
|
|
27
|
-
once: z.boolean().optional().default(true),
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const deleteRangeOp = z.object({
|
|
31
|
-
type: z.literal('delete_range'),
|
|
32
|
-
start: z.string().describe('Start marker (first occurrence)'),
|
|
33
|
-
end: z.string().describe('End marker (first occurrence after start)'),
|
|
34
|
-
includeBoundaries: z.boolean().optional().default(false),
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const opSchema = z.discriminatedUnion('type', [
|
|
38
|
-
replaceOp,
|
|
39
|
-
insertOp,
|
|
40
|
-
deleteRangeOp,
|
|
41
|
-
]);
|
|
42
|
-
|
|
43
|
-
export const editTool: Tool = tool({
|
|
44
|
-
description: DESCRIPTION,
|
|
45
|
-
inputSchema: z.object({
|
|
46
|
-
path: z.string().min(1),
|
|
47
|
-
ops: z.array(opSchema).min(1),
|
|
48
|
-
create: z.boolean().optional().default(false),
|
|
49
|
-
}),
|
|
50
|
-
async execute({
|
|
51
|
-
path,
|
|
52
|
-
ops,
|
|
53
|
-
create,
|
|
54
|
-
}: {
|
|
55
|
-
path: string;
|
|
56
|
-
ops: z.infer<typeof opSchema>[];
|
|
57
|
-
create?: boolean;
|
|
58
|
-
}): Promise<
|
|
59
|
-
ToolResponse<{ path: string; opsApplied: number; bytes: number }>
|
|
60
|
-
> {
|
|
61
|
-
let exists = false;
|
|
62
|
-
try {
|
|
63
|
-
await access(path, constants.F_OK);
|
|
64
|
-
exists = true;
|
|
65
|
-
} catch {}
|
|
66
|
-
|
|
67
|
-
if (!exists) {
|
|
68
|
-
if (!create) {
|
|
69
|
-
return createToolError(`File not found: ${path}`, 'not_found', {
|
|
70
|
-
parameter: 'path',
|
|
71
|
-
value: path,
|
|
72
|
-
suggestion: 'Set create: true to create a new file',
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
await writeFile(path, '');
|
|
76
|
-
}
|
|
77
|
-
let text = await readFile(path, 'utf-8');
|
|
78
|
-
let applied = 0;
|
|
79
|
-
|
|
80
|
-
for (const op of ops) {
|
|
81
|
-
if (op.type === 'replace') {
|
|
82
|
-
const originalText = text;
|
|
83
|
-
if (op.regex) {
|
|
84
|
-
const re = new RegExp(op.find, op.flags || 'g');
|
|
85
|
-
if (op.count && op.count > 0) {
|
|
86
|
-
let n = 0;
|
|
87
|
-
text = text.replace(re, (m) => {
|
|
88
|
-
if (n < (op.count as number)) {
|
|
89
|
-
n += 1;
|
|
90
|
-
return op.replace;
|
|
91
|
-
}
|
|
92
|
-
return m;
|
|
93
|
-
});
|
|
94
|
-
} else text = text.replace(re, op.replace);
|
|
95
|
-
} else {
|
|
96
|
-
// Check if the text to find exists
|
|
97
|
-
if (!text.includes(op.find)) {
|
|
98
|
-
console.warn(
|
|
99
|
-
`Warning: Text not found for replace operation: "${op.find.substring(0, 50)}${op.find.length > 50 ? '...' : ''}"`,
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
if (op.count && op.count > 0) {
|
|
103
|
-
let remaining = op.count as number;
|
|
104
|
-
let idx = text.indexOf(op.find);
|
|
105
|
-
while (idx !== -1 && remaining > 0) {
|
|
106
|
-
text =
|
|
107
|
-
text.slice(0, idx) +
|
|
108
|
-
op.replace +
|
|
109
|
-
text.slice(idx + op.find.length);
|
|
110
|
-
remaining -= 1;
|
|
111
|
-
idx = text.indexOf(op.find, idx + op.replace.length);
|
|
112
|
-
}
|
|
113
|
-
} else {
|
|
114
|
-
text = text.split(op.find).join(op.replace);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
// Only count as applied if text actually changed
|
|
118
|
-
if (text !== originalText) {
|
|
119
|
-
applied += 1;
|
|
120
|
-
}
|
|
121
|
-
} else if (op.type === 'insert') {
|
|
122
|
-
if (op.position === 'start') {
|
|
123
|
-
text = `${op.content}${text}`;
|
|
124
|
-
applied += 1;
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
if (op.position === 'end') {
|
|
128
|
-
text = `${text}${op.content}`;
|
|
129
|
-
applied += 1;
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (!op.pattern) {
|
|
133
|
-
return createToolError(
|
|
134
|
-
'insert requires pattern for before/after',
|
|
135
|
-
'validation',
|
|
136
|
-
{
|
|
137
|
-
parameter: 'pattern',
|
|
138
|
-
suggestion: 'Provide a pattern to anchor the insertion',
|
|
139
|
-
},
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
const idx = text.indexOf(op.pattern);
|
|
143
|
-
if (idx === -1) continue;
|
|
144
|
-
if (op.position === 'before')
|
|
145
|
-
text = text.slice(0, idx) + op.content + text.slice(idx);
|
|
146
|
-
else
|
|
147
|
-
text =
|
|
148
|
-
text.slice(0, idx + op.pattern.length) +
|
|
149
|
-
op.content +
|
|
150
|
-
text.slice(idx + op.pattern.length);
|
|
151
|
-
applied += 1;
|
|
152
|
-
if (op.once) continue;
|
|
153
|
-
} else if (op.type === 'delete_range') {
|
|
154
|
-
const startIdx = text.indexOf(op.start);
|
|
155
|
-
if (startIdx === -1) continue;
|
|
156
|
-
const after = startIdx + op.start.length;
|
|
157
|
-
const endIdx = text.indexOf(op.end, after);
|
|
158
|
-
if (endIdx === -1) continue;
|
|
159
|
-
const from = op.includeBoundaries ? startIdx : after;
|
|
160
|
-
const to = op.includeBoundaries ? endIdx + op.end.length : endIdx;
|
|
161
|
-
text = text.slice(0, from) + text.slice(to);
|
|
162
|
-
applied += 1;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
await writeFile(path, text);
|
|
167
|
-
return { ok: true, path, opsApplied: applied, bytes: text.length };
|
|
168
|
-
},
|
|
169
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
- Edit a file using structured operations
|
|
2
|
-
- Supported ops: `replace`, `insert`, `delete_range`
|
|
3
|
-
- Paths are relative to the project root; can create files if flagged
|
|
4
|
-
|
|
5
|
-
Usage tips:
|
|
6
|
-
- Prefer minimal, targeted changes for clarity
|
|
7
|
-
- For sweeping refactors, consider Write or Patch to replace full content
|