@ridit/lens 0.3.5 → 0.3.7
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/CLAUDE.md +50 -0
- package/dist/index.mjs +1484 -1058
- package/package.json +2 -2
- package/src/components/chat/ChatOverlays.tsx +12 -13
- package/src/components/chat/ChatRunner.tsx +2 -2
- package/src/components/chat/TextArea.tsx +176 -0
- package/src/components/chat/hooks/useChat.ts +160 -60
- package/src/components/repo/RepoAnalysis.tsx +2 -2
- package/src/components/timeline/TimelineRunner.tsx +2 -2
- package/src/components/watch/RunRunner.tsx +2 -1
- package/src/prompts/fewshot.ts +18 -0
- package/src/prompts/system.ts +157 -22
- package/src/tools/git.ts +26 -0
- package/src/utils/chat.ts +16 -4
- package/src/utils/intentClassifier.ts +58 -0
- package/src/utils/memory.ts +103 -26
- package/src/utils/tools/builtins.ts +46 -5
- package/src/utils/tools/registry.ts +65 -9
package/src/prompts/system.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ImportantFile } from "../types/repo";
|
|
2
|
+
import type { Intent } from "../utils/intentClassifier";
|
|
2
3
|
|
|
3
4
|
export function buildSystemPrompt(
|
|
4
5
|
files: ImportantFile[],
|
|
@@ -12,25 +13,37 @@ export function buildSystemPrompt(
|
|
|
12
13
|
const tools = toolsSection ?? BUILTIN_TOOLS_SECTION;
|
|
13
14
|
|
|
14
15
|
return `You are an expert software engineer assistant with access to the user's codebase and tools.
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
${tools}
|
|
17
|
-
|
|
18
|
+
|
|
18
19
|
## MEMORY OPERATIONS
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
You can save and delete memories at any time by emitting these tags alongside your normal response.
|
|
21
22
|
They are stripped before display — the user will not see the raw tags.
|
|
22
|
-
|
|
23
|
-
### memory-add — save something important to long-term memory
|
|
23
|
+
|
|
24
|
+
### memory-add — save something important to long-term memory
|
|
24
25
|
<memory-add>User prefers TypeScript strict mode in all new files</memory-add>
|
|
25
|
-
|
|
26
|
+
|
|
27
|
+
Use [global] prefix for things that apply across ALL repos (user preferences, name, coding style):
|
|
28
|
+
<memory-add>[global] User prefers bun over npm for all projects</memory-add>
|
|
29
|
+
|
|
30
|
+
Omit [global] for repo-specific memories (architecture decisions, patterns, agreed conventions):
|
|
31
|
+
<memory-add>This repo uses path aliases defined in tsconfig.json</memory-add>
|
|
32
|
+
|
|
26
33
|
### memory-delete — delete a memory by its ID (shown in brackets like [abc123])
|
|
27
34
|
<memory-delete>abc123</memory-delete>
|
|
28
|
-
|
|
29
|
-
Use memory-add
|
|
35
|
+
|
|
36
|
+
Use memory-add ONLY for information that cannot be inferred by reading the codebase:
|
|
37
|
+
- User preferences and coding conventions
|
|
38
|
+
- Decisions made during the session (e.g. "user chose bun over npm")
|
|
39
|
+
- Things the user explicitly asked you to remember
|
|
40
|
+
- Cross-session context that would otherwise be lost
|
|
41
|
+
|
|
42
|
+
NEVER save memories that just describe what files exist or what the project does — that can be read directly from the codebase.
|
|
30
43
|
Use memory-delete when the user asks you to forget something or a memory is outdated.
|
|
31
|
-
|
|
44
|
+
|
|
32
45
|
## RULES
|
|
33
|
-
|
|
46
|
+
|
|
34
47
|
1. ONE tool per response — emit the XML tag, then stop. Never chain tools in one response except when scaffolding (see below).
|
|
35
48
|
2. NEVER call a tool more than once for the same path in a session. If write-file or shell returned a result, it succeeded. Move on immediately.
|
|
36
49
|
3. NEVER write the same file twice in one session. One write per file, period. If you already wrote it, it is done.
|
|
@@ -48,15 +61,17 @@ Use memory-delete when the user asks you to forget something or a memory is outd
|
|
|
48
61
|
15. When explaining how to use a tool in text, use [tag] bracket notation — NEVER emit a real XML tool tag as part of an explanation.
|
|
49
62
|
16. NEVER use markdown formatting in plain text responses — no bold, no headings, no bullet points. Only use fenced code blocks when showing actual code.
|
|
50
63
|
17. When scaffolding multiple files, emit ONE write-file tag per response and wait for the result before writing the next file.
|
|
51
|
-
|
|
64
|
+
18. When you identify a bug or error, ALWAYS write the fix immediately using write-file or changes. Never describe the fix without writing it.
|
|
65
|
+
19. NEVER use shell for filesystem inspection or searching — always use grep, read-file, or read-folder instead.
|
|
66
|
+
|
|
52
67
|
## ADDON FORMAT
|
|
53
|
-
|
|
68
|
+
|
|
54
69
|
All addons use defineTool from @ridit/lens-sdk. The ONLY correct format is:
|
|
55
|
-
|
|
70
|
+
|
|
56
71
|
\`\`\`js
|
|
57
72
|
const { defineTool } = require("@ridit/lens-sdk");
|
|
58
73
|
const { execSync } = require("child_process");
|
|
59
|
-
|
|
74
|
+
|
|
60
75
|
defineTool({
|
|
61
76
|
name: "tool-name",
|
|
62
77
|
description: "what it does",
|
|
@@ -72,26 +87,146 @@ defineTool({
|
|
|
72
87
|
},
|
|
73
88
|
});
|
|
74
89
|
\`\`\`
|
|
75
|
-
|
|
90
|
+
|
|
76
91
|
NEVER use module.exports, registerTool, ctx.tools.shell, or any other format. See addons/run-tests.js for a full working example.
|
|
77
|
-
|
|
92
|
+
|
|
78
93
|
## SCAFFOLDING
|
|
79
|
-
|
|
94
|
+
|
|
80
95
|
When creating multiple files, emit ONE write-file per response and wait for each result:
|
|
81
|
-
|
|
96
|
+
|
|
82
97
|
<write-file>
|
|
83
98
|
{"path": "myapp/package.json", "content": "..."}
|
|
84
99
|
</write-file>
|
|
85
|
-
|
|
100
|
+
|
|
86
101
|
Wait for result, then emit the next file. Never chain write-file tags when content is complex.
|
|
87
|
-
|
|
102
|
+
|
|
88
103
|
## CODEBASE
|
|
89
|
-
|
|
104
|
+
|
|
90
105
|
${fileList.length > 0 ? fileList : "(no files indexed)"}
|
|
91
|
-
|
|
106
|
+
|
|
92
107
|
${memorySummary}`;
|
|
93
108
|
}
|
|
94
109
|
|
|
110
|
+
export function buildBuiltinToolsSection(intent: Intent = "any"): string {
|
|
111
|
+
const isReadonly = intent === "readonly";
|
|
112
|
+
|
|
113
|
+
const readTools = `### 1. fetch — load a URL
|
|
114
|
+
<fetch>https://example.com</fetch>
|
|
115
|
+
|
|
116
|
+
### 2. read-file — read a single file from the repo
|
|
117
|
+
<read-file>src/foo.ts</read-file>
|
|
118
|
+
|
|
119
|
+
### 3. read-files — read multiple files at once
|
|
120
|
+
<read-files>
|
|
121
|
+
["src/foo.ts", "src/bar.ts"]
|
|
122
|
+
</read-files>
|
|
123
|
+
|
|
124
|
+
### 4. read-folder — list contents of a folder (one level deep)
|
|
125
|
+
<read-folder>src/components</read-folder>
|
|
126
|
+
|
|
127
|
+
### 5. grep — search for a pattern across files
|
|
128
|
+
<grep>
|
|
129
|
+
{"pattern": "ChatRunner", "glob": "src/**/*.tsx"}
|
|
130
|
+
</grep>
|
|
131
|
+
|
|
132
|
+
### 6. search — search the internet
|
|
133
|
+
<search>how to use React useEffect cleanup</search>`;
|
|
134
|
+
|
|
135
|
+
const writeTools = `### 7. shell — run a terminal command (NOT for filesystem inspection)
|
|
136
|
+
<shell>node -v</shell>
|
|
137
|
+
|
|
138
|
+
### 8. write-file — create or overwrite a file (COMPLETE content only)
|
|
139
|
+
<write-file>
|
|
140
|
+
{"path": "data/output.csv", "content": "col1,col2\\nval1,val2"}
|
|
141
|
+
</write-file>
|
|
142
|
+
|
|
143
|
+
### 9. delete-file — permanently delete a single file
|
|
144
|
+
<delete-file>src/old-component.tsx</delete-file>
|
|
145
|
+
|
|
146
|
+
### 10. delete-folder — permanently delete a folder and all its contents
|
|
147
|
+
<delete-folder>src/legacy</delete-folder>
|
|
148
|
+
|
|
149
|
+
### 11. open-url — open a URL in the user's default browser
|
|
150
|
+
<open-url>https://github.com/owner/repo</open-url>
|
|
151
|
+
|
|
152
|
+
### 12. generate-pdf — generate a PDF from markdown-style content
|
|
153
|
+
<generate-pdf>
|
|
154
|
+
{"path": "output/report.pdf", "content": "# Title\\n\\nBody text."}
|
|
155
|
+
</generate-pdf>
|
|
156
|
+
|
|
157
|
+
### 13. clone — clone a GitHub repo
|
|
158
|
+
<clone>https://github.com/owner/repo</clone>
|
|
159
|
+
|
|
160
|
+
### 14. changes — propose code edits shown as a diff for user approval
|
|
161
|
+
<changes>
|
|
162
|
+
{"summary": "what changed and why", "patches": [{"path": "src/foo.ts", "content": "COMPLETE file content", "isNew": false}]}
|
|
163
|
+
</changes>`;
|
|
164
|
+
|
|
165
|
+
if (isReadonly) {
|
|
166
|
+
return `## TOOLS
|
|
167
|
+
|
|
168
|
+
You have 6 tools available for this read-only request. Do NOT attempt to write, delete, or run shell commands — those tools are not available right now.
|
|
169
|
+
|
|
170
|
+
${readTools}`;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return `## TOOLS
|
|
174
|
+
|
|
175
|
+
You have exactly 14 tools. To use a tool you MUST wrap it in the exact XML tags shown below — no other format will work.
|
|
176
|
+
|
|
177
|
+
### 1. fetch — load a URL
|
|
178
|
+
<fetch>https://example.com</fetch>
|
|
179
|
+
|
|
180
|
+
### 2. shell — run a terminal command (NOT for filesystem inspection)
|
|
181
|
+
<shell>node -v</shell>
|
|
182
|
+
|
|
183
|
+
### 3. read-file — read a single file from the repo
|
|
184
|
+
<read-file>src/foo.ts</read-file>
|
|
185
|
+
|
|
186
|
+
### 4. read-files — read multiple files at once
|
|
187
|
+
<read-files>
|
|
188
|
+
["src/foo.ts", "src/bar.ts"]
|
|
189
|
+
</read-files>
|
|
190
|
+
|
|
191
|
+
### 5. read-folder — list contents of a folder (one level deep)
|
|
192
|
+
<read-folder>src/components</read-folder>
|
|
193
|
+
|
|
194
|
+
### 6. grep — search for a pattern across files
|
|
195
|
+
<grep>
|
|
196
|
+
{"pattern": "ChatRunner", "glob": "src/**/*.tsx"}
|
|
197
|
+
</grep>
|
|
198
|
+
|
|
199
|
+
### 7. write-file — create or overwrite a file (COMPLETE content only)
|
|
200
|
+
<write-file>
|
|
201
|
+
{"path": "data/output.csv", "content": "col1,col2\\nval1,val2"}
|
|
202
|
+
</write-file>
|
|
203
|
+
|
|
204
|
+
### 8. delete-file — permanently delete a single file
|
|
205
|
+
<delete-file>src/old-component.tsx</delete-file>
|
|
206
|
+
|
|
207
|
+
### 9. delete-folder — permanently delete a folder and all its contents
|
|
208
|
+
<delete-folder>src/legacy</delete-folder>
|
|
209
|
+
|
|
210
|
+
### 10. open-url — open a URL in the user's default browser
|
|
211
|
+
<open-url>https://github.com/owner/repo</open-url>
|
|
212
|
+
|
|
213
|
+
### 11. generate-pdf — generate a PDF from markdown-style content
|
|
214
|
+
<generate-pdf>
|
|
215
|
+
{"path": "output/report.pdf", "content": "# Title\\n\\nBody text."}
|
|
216
|
+
</generate-pdf>
|
|
217
|
+
|
|
218
|
+
### 12. search — search the internet
|
|
219
|
+
<search>how to use React useEffect cleanup</search>
|
|
220
|
+
|
|
221
|
+
### 13. clone — clone a GitHub repo
|
|
222
|
+
<clone>https://github.com/owner/repo</clone>
|
|
223
|
+
|
|
224
|
+
### 14. changes — propose code edits shown as a diff for user approval
|
|
225
|
+
<changes>
|
|
226
|
+
{"summary": "what changed and why", "patches": [{"path": "src/foo.ts", "content": "COMPLETE file content", "isNew": false}]}
|
|
227
|
+
</changes>`;
|
|
228
|
+
}
|
|
229
|
+
|
|
95
230
|
const BUILTIN_TOOLS_SECTION = `## TOOLS
|
|
96
231
|
|
|
97
232
|
You have exactly fourteen tools. Use ONLY the XML tags shown below.
|
package/src/tools/git.ts
CHANGED
|
@@ -27,6 +27,7 @@ function parseArgs(body: string): GitArgs | null {
|
|
|
27
27
|
export const gitStatusTool: Tool<GitArgs> = {
|
|
28
28
|
name: "git-status",
|
|
29
29
|
description: "show working tree status",
|
|
30
|
+
tag: "git",
|
|
30
31
|
safe: true,
|
|
31
32
|
permissionLabel: "git status",
|
|
32
33
|
systemPromptEntry: (i) =>
|
|
@@ -45,6 +46,7 @@ export const gitStatusTool: Tool<GitArgs> = {
|
|
|
45
46
|
export const gitLogTool: Tool<GitArgs> = {
|
|
46
47
|
name: "git-log",
|
|
47
48
|
description: "show commit log",
|
|
49
|
+
tag: "git",
|
|
48
50
|
safe: true,
|
|
49
51
|
permissionLabel: "git log",
|
|
50
52
|
systemPromptEntry: (i) =>
|
|
@@ -60,6 +62,7 @@ export const gitLogTool: Tool<GitArgs> = {
|
|
|
60
62
|
export const gitDiffTool: Tool<GitArgs> = {
|
|
61
63
|
name: "git-diff",
|
|
62
64
|
description: "show changes between commits, working tree, or staged files",
|
|
65
|
+
tag: "git",
|
|
63
66
|
safe: true,
|
|
64
67
|
permissionLabel: "git diff",
|
|
65
68
|
systemPromptEntry: (i) =>
|
|
@@ -75,6 +78,7 @@ export const gitDiffTool: Tool<GitArgs> = {
|
|
|
75
78
|
export const gitShowTool: Tool<GitArgs> = {
|
|
76
79
|
name: "git-show",
|
|
77
80
|
description: "show a commit's details and stat",
|
|
81
|
+
tag: "git",
|
|
78
82
|
safe: true,
|
|
79
83
|
permissionLabel: "git show",
|
|
80
84
|
systemPromptEntry: (i) =>
|
|
@@ -90,6 +94,7 @@ export const gitShowTool: Tool<GitArgs> = {
|
|
|
90
94
|
export const gitBranchTool: Tool<GitArgs> = {
|
|
91
95
|
name: "git-branch",
|
|
92
96
|
description: "list branches",
|
|
97
|
+
tag: "git",
|
|
93
98
|
safe: true,
|
|
94
99
|
permissionLabel: "git branch",
|
|
95
100
|
systemPromptEntry: (i) =>
|
|
@@ -105,6 +110,7 @@ export const gitBranchTool: Tool<GitArgs> = {
|
|
|
105
110
|
export const gitRemoteTool: Tool<GitArgs> = {
|
|
106
111
|
name: "git-remote",
|
|
107
112
|
description: "list or inspect remotes",
|
|
113
|
+
tag: "git",
|
|
108
114
|
safe: true,
|
|
109
115
|
permissionLabel: "git remote",
|
|
110
116
|
systemPromptEntry: (i) =>
|
|
@@ -120,6 +126,7 @@ export const gitRemoteTool: Tool<GitArgs> = {
|
|
|
120
126
|
export const gitTagTool: Tool<GitArgs> = {
|
|
121
127
|
name: "git-tag",
|
|
122
128
|
description: "list tags",
|
|
129
|
+
tag: "git",
|
|
123
130
|
safe: true,
|
|
124
131
|
permissionLabel: "git tag",
|
|
125
132
|
systemPromptEntry: (i) =>
|
|
@@ -135,6 +142,7 @@ export const gitTagTool: Tool<GitArgs> = {
|
|
|
135
142
|
export const gitBlameTool: Tool<GitArgs> = {
|
|
136
143
|
name: "git-blame",
|
|
137
144
|
description: "show who last modified each line of a file",
|
|
145
|
+
tag: "git",
|
|
138
146
|
safe: true,
|
|
139
147
|
permissionLabel: "git blame",
|
|
140
148
|
systemPromptEntry: (i) =>
|
|
@@ -168,6 +176,7 @@ export const gitBlameTool: Tool<GitArgs> = {
|
|
|
168
176
|
export const gitStashListTool: Tool<GitArgs> = {
|
|
169
177
|
name: "git-stash-list",
|
|
170
178
|
description: "list stashed changes",
|
|
179
|
+
tag: "git",
|
|
171
180
|
safe: true,
|
|
172
181
|
permissionLabel: "git stash list",
|
|
173
182
|
systemPromptEntry: (i) =>
|
|
@@ -183,6 +192,7 @@ export const gitStashListTool: Tool<GitArgs> = {
|
|
|
183
192
|
export const gitAddTool: Tool<GitArgs> = {
|
|
184
193
|
name: "git-add",
|
|
185
194
|
description: "stage files for commit",
|
|
195
|
+
tag: "git",
|
|
186
196
|
safe: false,
|
|
187
197
|
permissionLabel: "git add",
|
|
188
198
|
systemPromptEntry: (i) =>
|
|
@@ -202,6 +212,7 @@ export const gitAddTool: Tool<GitArgs> = {
|
|
|
202
212
|
export const gitCommitTool: Tool<GitArgs> = {
|
|
203
213
|
name: "git-commit",
|
|
204
214
|
description: "commit staged changes with a message",
|
|
215
|
+
tag: "git",
|
|
205
216
|
safe: false,
|
|
206
217
|
permissionLabel: "git commit",
|
|
207
218
|
systemPromptEntry: (i) =>
|
|
@@ -222,6 +233,7 @@ export const gitCommitTool: Tool<GitArgs> = {
|
|
|
222
233
|
export const gitCommitAmendTool: Tool<GitArgs> = {
|
|
223
234
|
name: "git-commit-amend",
|
|
224
235
|
description: "amend the last commit message",
|
|
236
|
+
tag: "git",
|
|
225
237
|
safe: false,
|
|
226
238
|
permissionLabel: "git commit --amend",
|
|
227
239
|
systemPromptEntry: (i) =>
|
|
@@ -246,6 +258,7 @@ export const gitRevertTool: Tool<GitArgs> = {
|
|
|
246
258
|
name: "git-revert",
|
|
247
259
|
description:
|
|
248
260
|
"revert a commit by hash (creates a new revert commit, history preserved)",
|
|
261
|
+
tag: "git",
|
|
249
262
|
safe: false,
|
|
250
263
|
permissionLabel: "git revert",
|
|
251
264
|
systemPromptEntry: (i) =>
|
|
@@ -266,6 +279,7 @@ export const gitRevertTool: Tool<GitArgs> = {
|
|
|
266
279
|
export const gitResetTool: Tool<GitArgs> = {
|
|
267
280
|
name: "git-reset",
|
|
268
281
|
description: "reset HEAD or unstage files",
|
|
282
|
+
tag: "git",
|
|
269
283
|
safe: false,
|
|
270
284
|
permissionLabel: "git reset",
|
|
271
285
|
systemPromptEntry: (i) =>
|
|
@@ -285,6 +299,7 @@ export const gitResetTool: Tool<GitArgs> = {
|
|
|
285
299
|
export const gitCheckoutTool: Tool<GitArgs> = {
|
|
286
300
|
name: "git-checkout",
|
|
287
301
|
description: "switch branches or restore files",
|
|
302
|
+
tag: "git",
|
|
288
303
|
safe: false,
|
|
289
304
|
permissionLabel: "git checkout",
|
|
290
305
|
systemPromptEntry: (i) =>
|
|
@@ -305,6 +320,7 @@ export const gitCheckoutTool: Tool<GitArgs> = {
|
|
|
305
320
|
export const gitSwitchTool: Tool<GitArgs> = {
|
|
306
321
|
name: "git-switch",
|
|
307
322
|
description: "switch or create branches",
|
|
323
|
+
tag: "git",
|
|
308
324
|
safe: false,
|
|
309
325
|
permissionLabel: "git switch",
|
|
310
326
|
systemPromptEntry: (i) =>
|
|
@@ -325,6 +341,7 @@ export const gitSwitchTool: Tool<GitArgs> = {
|
|
|
325
341
|
export const gitMergeTool: Tool<GitArgs> = {
|
|
326
342
|
name: "git-merge",
|
|
327
343
|
description: "merge a branch into the current branch",
|
|
344
|
+
tag: "git",
|
|
328
345
|
safe: false,
|
|
329
346
|
permissionLabel: "git merge",
|
|
330
347
|
systemPromptEntry: (i) =>
|
|
@@ -345,6 +362,7 @@ export const gitMergeTool: Tool<GitArgs> = {
|
|
|
345
362
|
export const gitPullTool: Tool<GitArgs> = {
|
|
346
363
|
name: "git-pull",
|
|
347
364
|
description: "pull from remote",
|
|
365
|
+
tag: "git",
|
|
348
366
|
safe: false,
|
|
349
367
|
permissionLabel: "git pull",
|
|
350
368
|
systemPromptEntry: (i) =>
|
|
@@ -363,6 +381,7 @@ export const gitPullTool: Tool<GitArgs> = {
|
|
|
363
381
|
export const gitPushTool: Tool<GitArgs> = {
|
|
364
382
|
name: "git-push",
|
|
365
383
|
description: "push commits to remote",
|
|
384
|
+
tag: "git",
|
|
366
385
|
safe: false,
|
|
367
386
|
permissionLabel: "git push",
|
|
368
387
|
systemPromptEntry: (i) =>
|
|
@@ -381,6 +400,7 @@ export const gitPushTool: Tool<GitArgs> = {
|
|
|
381
400
|
export const gitStashTool: Tool<GitArgs> = {
|
|
382
401
|
name: "git-stash",
|
|
383
402
|
description: "stash or apply stashed changes",
|
|
403
|
+
tag: "git",
|
|
384
404
|
safe: false,
|
|
385
405
|
permissionLabel: "git stash",
|
|
386
406
|
systemPromptEntry: (i) =>
|
|
@@ -401,6 +421,7 @@ export const gitStashTool: Tool<GitArgs> = {
|
|
|
401
421
|
export const gitBranchCreateTool: Tool<GitArgs> = {
|
|
402
422
|
name: "git-branch-create",
|
|
403
423
|
description: "create a new branch without switching to it",
|
|
424
|
+
tag: "git",
|
|
404
425
|
safe: false,
|
|
405
426
|
permissionLabel: "git branch (create)",
|
|
406
427
|
systemPromptEntry: (i) =>
|
|
@@ -421,6 +442,7 @@ export const gitBranchCreateTool: Tool<GitArgs> = {
|
|
|
421
442
|
export const gitBranchDeleteTool: Tool<GitArgs> = {
|
|
422
443
|
name: "git-branch-delete",
|
|
423
444
|
description: "delete a branch",
|
|
445
|
+
tag: "git",
|
|
424
446
|
safe: false,
|
|
425
447
|
permissionLabel: "git branch -d",
|
|
426
448
|
systemPromptEntry: (i) =>
|
|
@@ -444,6 +466,7 @@ export const gitBranchDeleteTool: Tool<GitArgs> = {
|
|
|
444
466
|
export const gitCherryPickTool: Tool<GitArgs> = {
|
|
445
467
|
name: "git-cherry-pick",
|
|
446
468
|
description: "apply a specific commit from another branch",
|
|
469
|
+
tag: "git",
|
|
447
470
|
safe: false,
|
|
448
471
|
permissionLabel: "git cherry-pick",
|
|
449
472
|
systemPromptEntry: (i) =>
|
|
@@ -466,6 +489,7 @@ export const gitCherryPickTool: Tool<GitArgs> = {
|
|
|
466
489
|
export const gitTagCreateTool: Tool<GitArgs> = {
|
|
467
490
|
name: "git-tag-create",
|
|
468
491
|
description: "create a lightweight or annotated tag",
|
|
492
|
+
tag: "git",
|
|
469
493
|
safe: false,
|
|
470
494
|
permissionLabel: "git tag (create)",
|
|
471
495
|
systemPromptEntry: (i) =>
|
|
@@ -486,6 +510,7 @@ export const gitRestoreTool: Tool<GitArgs> = {
|
|
|
486
510
|
name: "git-restore",
|
|
487
511
|
description:
|
|
488
512
|
"discard working directory changes for a file (cannot be undone)",
|
|
513
|
+
tag: "git",
|
|
489
514
|
safe: false,
|
|
490
515
|
permissionLabel: "git restore",
|
|
491
516
|
systemPromptEntry: (i) =>
|
|
@@ -505,6 +530,7 @@ export const gitRestoreTool: Tool<GitArgs> = {
|
|
|
505
530
|
export const gitCleanTool: Tool<GitArgs> = {
|
|
506
531
|
name: "git-clean",
|
|
507
532
|
description: "remove untracked files (cannot be undone)",
|
|
533
|
+
tag: "git",
|
|
508
534
|
safe: false,
|
|
509
535
|
permissionLabel: "git clean",
|
|
510
536
|
systemPromptEntry: (i) =>
|
package/src/utils/chat.ts
CHANGED
|
@@ -19,6 +19,11 @@ import { FEW_SHOT_MESSAGES } from "../prompts";
|
|
|
19
19
|
import { registry } from "../utils/tools/registry";
|
|
20
20
|
import type { FilePatch } from "../components/repo/DiffViewer";
|
|
21
21
|
|
|
22
|
+
export type ChatResult = {
|
|
23
|
+
text: string;
|
|
24
|
+
truncated: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
22
27
|
export type ParsedResponse =
|
|
23
28
|
| { kind: "text"; content: string; remainder?: string }
|
|
24
29
|
| {
|
|
@@ -219,7 +224,7 @@ export async function callChat(
|
|
|
219
224
|
messages: Message[],
|
|
220
225
|
abortSignal?: AbortSignal,
|
|
221
226
|
retries = 2,
|
|
222
|
-
): Promise<
|
|
227
|
+
): Promise<ChatResult> {
|
|
223
228
|
const apiMessages = [
|
|
224
229
|
...buildFewShotMessages(),
|
|
225
230
|
...buildApiMessages(messages),
|
|
@@ -288,13 +293,20 @@ export async function callChat(
|
|
|
288
293
|
|
|
289
294
|
if (provider.type === "anthropic") {
|
|
290
295
|
const content = data.content as { type: string; text: string }[];
|
|
291
|
-
|
|
296
|
+
const text = content
|
|
292
297
|
.filter((b) => b.type === "text")
|
|
293
298
|
.map((b) => b.text)
|
|
294
299
|
.join("");
|
|
300
|
+
const truncated = (data as any).stop_reason === "max_tokens";
|
|
301
|
+
return { text, truncated };
|
|
295
302
|
} else {
|
|
296
|
-
const choices = data.choices as {
|
|
297
|
-
|
|
303
|
+
const choices = data.choices as {
|
|
304
|
+
message: { content: string };
|
|
305
|
+
finish_reason?: string;
|
|
306
|
+
}[];
|
|
307
|
+
const text = choices[0]?.message.content ?? "";
|
|
308
|
+
const truncated = choices[0]?.finish_reason === "length";
|
|
309
|
+
return { text, truncated };
|
|
298
310
|
}
|
|
299
311
|
} catch (err) {
|
|
300
312
|
clearTimeout(timer);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classifies user message intent to scope which tools the LLM is allowed to use.
|
|
3
|
+
*
|
|
4
|
+
* readonly → only read/search/fetch tools exposed (no write, delete, shell)
|
|
5
|
+
* mutating → all tools exposed
|
|
6
|
+
* any → all tools exposed (ambiguous / can't tell)
|
|
7
|
+
*/
|
|
8
|
+
export type Intent = "readonly" | "mutating" | "any";
|
|
9
|
+
|
|
10
|
+
const READONLY_PATTERNS: RegExp[] = [
|
|
11
|
+
// listing / exploring
|
|
12
|
+
/\b(list|ls|dir|show|display|print|dump)\b/i,
|
|
13
|
+
/\bwhat(('?s| is| are| does)\b| files| folder)/i,
|
|
14
|
+
/\b(folder|directory|file) (structure|tree|layout|contents?)\b/i,
|
|
15
|
+
/\bexplore\b/i,
|
|
16
|
+
|
|
17
|
+
// reading / explaining
|
|
18
|
+
/\b(read|open|view|look at|check out|inspect|peek)\b/i,
|
|
19
|
+
/\b(explain|describe|summarize|summarise|tell me about|walk me through)\b/i,
|
|
20
|
+
/\bhow does\b/i,
|
|
21
|
+
/\bwhat('?s| is) (in|inside|this|that|the)\b/i,
|
|
22
|
+
|
|
23
|
+
// searching
|
|
24
|
+
/\b(find|search|grep|locate|where is|where are)\b/i,
|
|
25
|
+
/\b(look for|scan|trace)\b/i,
|
|
26
|
+
|
|
27
|
+
// understanding
|
|
28
|
+
/\bunderstand\b/i,
|
|
29
|
+
/\bshow me (how|what|where|why)\b/i,
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const MUTATING_PATTERNS: RegExp[] = [
|
|
33
|
+
// writing
|
|
34
|
+
/\b(write|create|make|generate|add|build|scaffold|init|initialize|setup|set up)\b/i,
|
|
35
|
+
/\b(new file|new folder|new component|new page|new route)\b/i,
|
|
36
|
+
|
|
37
|
+
// editing
|
|
38
|
+
/\b(edit|modify|update|change|refactor|rename|move|migrate)\b/i,
|
|
39
|
+
/\b(fix|patch|resolve|correct|debug|repair)\b/i,
|
|
40
|
+
/\b(implement|add .+ to|insert|inject|append|prepend)\b/i,
|
|
41
|
+
|
|
42
|
+
// deleting
|
|
43
|
+
/\b(delete|remove|drop|clean ?up|purge|wipe)\b/i,
|
|
44
|
+
|
|
45
|
+
// running
|
|
46
|
+
/\b(run|execute|install|deploy|build|test|start|launch|compile|lint|format)\b/i,
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
export function classifyIntent(userMessage: string): Intent {
|
|
50
|
+
const text = userMessage.trim();
|
|
51
|
+
|
|
52
|
+
const mutatingScore = MUTATING_PATTERNS.filter((p) => p.test(text)).length;
|
|
53
|
+
const readonlyScore = READONLY_PATTERNS.filter((p) => p.test(text)).length;
|
|
54
|
+
|
|
55
|
+
if (mutatingScore === 0 && readonlyScore > 0) return "readonly";
|
|
56
|
+
if (mutatingScore > 0) return "mutating";
|
|
57
|
+
return "any";
|
|
58
|
+
}
|