@ridit/lens 0.3.5 → 0.3.6
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/dist/index.mjs +144 -24
- package/package.json +2 -2
- package/src/components/chat/hooks/useChat.ts +10 -1
- package/src/prompts/system.ts +141 -20
- package/src/tools/git.ts +26 -0
- package/src/utils/intentClassifier.ts +58 -0
- package/src/utils/tools/builtins.ts +15 -0
- package/src/utils/tools/registry.ts +65 -9
package/dist/index.mjs
CHANGED
|
@@ -258398,6 +258398,12 @@ var require_asciichart = __commonJS((exports) => {
|
|
|
258398
258398
|
});
|
|
258399
258399
|
|
|
258400
258400
|
// src/utils/tools/registry.ts
|
|
258401
|
+
var INTENT_ALLOWED = {
|
|
258402
|
+
readonly: ["read", "net"],
|
|
258403
|
+
mutating: ["read", "net", "write", "delete", "shell"],
|
|
258404
|
+
any: ["read", "net", "write", "delete", "shell"]
|
|
258405
|
+
};
|
|
258406
|
+
|
|
258401
258407
|
class ToolRegistry {
|
|
258402
258408
|
tools = new Map;
|
|
258403
258409
|
register(tool) {
|
|
@@ -258418,13 +258424,34 @@ class ToolRegistry {
|
|
|
258418
258424
|
names() {
|
|
258419
258425
|
return Array.from(this.tools.keys());
|
|
258420
258426
|
}
|
|
258421
|
-
|
|
258427
|
+
namesForIntent(intent) {
|
|
258428
|
+
const allowed = new Set(INTENT_ALLOWED[intent]);
|
|
258429
|
+
return Array.from(this.tools.values()).filter((t) => {
|
|
258430
|
+
const tag = t.tag;
|
|
258431
|
+
if (!tag)
|
|
258432
|
+
return true;
|
|
258433
|
+
return allowed.has(tag);
|
|
258434
|
+
}).map((t) => t.name);
|
|
258435
|
+
}
|
|
258436
|
+
buildSystemPromptSection(intent = "any") {
|
|
258437
|
+
const allowed = new Set(INTENT_ALLOWED[intent]);
|
|
258438
|
+
const visible = Array.from(this.tools.values()).filter((t) => {
|
|
258439
|
+
const tag = t.tag;
|
|
258440
|
+
if (!tag)
|
|
258441
|
+
return true;
|
|
258442
|
+
return allowed.has(tag);
|
|
258443
|
+
});
|
|
258422
258444
|
const lines = [`## TOOLS
|
|
258423
258445
|
`];
|
|
258424
|
-
|
|
258446
|
+
if (intent === "readonly") {
|
|
258447
|
+
lines.push(`You have ${visible.length} tools available for this read-only request. ` + `Do NOT attempt to write, delete, or run shell commands — ` + `those tools are not available right now.
|
|
258425
258448
|
`);
|
|
258449
|
+
} else {
|
|
258450
|
+
lines.push(`You have exactly ${visible.length} tools. To use a tool you MUST wrap it ` + `in the exact XML tags shown below — no other format will work.
|
|
258451
|
+
`);
|
|
258452
|
+
}
|
|
258426
258453
|
let i = 1;
|
|
258427
|
-
for (const tool of
|
|
258454
|
+
for (const tool of visible) {
|
|
258428
258455
|
lines.push(tool.systemPromptEntry(i++));
|
|
258429
258456
|
}
|
|
258430
258457
|
return lines.join(`
|
|
@@ -268627,25 +268654,25 @@ ${f.content.slice(0, 2000)}
|
|
|
268627
268654
|
`);
|
|
268628
268655
|
const tools = toolsSection ?? BUILTIN_TOOLS_SECTION;
|
|
268629
268656
|
return `You are an expert software engineer assistant with access to the user's codebase and tools.
|
|
268630
|
-
|
|
268657
|
+
|
|
268631
268658
|
${tools}
|
|
268632
|
-
|
|
268659
|
+
|
|
268633
268660
|
## MEMORY OPERATIONS
|
|
268634
|
-
|
|
268661
|
+
|
|
268635
268662
|
You can save and delete memories at any time by emitting these tags alongside your normal response.
|
|
268636
268663
|
They are stripped before display — the user will not see the raw tags.
|
|
268637
|
-
|
|
268664
|
+
|
|
268638
268665
|
### memory-add — save something important to long-term memory for this repo
|
|
268639
268666
|
<memory-add>User prefers TypeScript strict mode in all new files</memory-add>
|
|
268640
|
-
|
|
268667
|
+
|
|
268641
268668
|
### memory-delete — delete a memory by its ID (shown in brackets like [abc123])
|
|
268642
268669
|
<memory-delete>abc123</memory-delete>
|
|
268643
|
-
|
|
268670
|
+
|
|
268644
268671
|
Use memory-add when the user asks you to remember something, or when you learn something project-specific that would be useful in future sessions.
|
|
268645
268672
|
Use memory-delete when the user asks you to forget something or a memory is outdated.
|
|
268646
|
-
|
|
268673
|
+
|
|
268647
268674
|
## RULES
|
|
268648
|
-
|
|
268675
|
+
|
|
268649
268676
|
1. ONE tool per response — emit the XML tag, then stop. Never chain tools in one response except when scaffolding (see below).
|
|
268650
268677
|
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.
|
|
268651
268678
|
3. NEVER write the same file twice in one session. One write per file, period. If you already wrote it, it is done.
|
|
@@ -268663,15 +268690,15 @@ Use memory-delete when the user asks you to forget something or a memory is outd
|
|
|
268663
268690
|
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.
|
|
268664
268691
|
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.
|
|
268665
268692
|
17. When scaffolding multiple files, emit ONE write-file tag per response and wait for the result before writing the next file.
|
|
268666
|
-
|
|
268693
|
+
|
|
268667
268694
|
## ADDON FORMAT
|
|
268668
|
-
|
|
268695
|
+
|
|
268669
268696
|
All addons use defineTool from @ridit/lens-sdk. The ONLY correct format is:
|
|
268670
|
-
|
|
268697
|
+
|
|
268671
268698
|
\`\`\`js
|
|
268672
268699
|
const { defineTool } = require("@ridit/lens-sdk");
|
|
268673
268700
|
const { execSync } = require("child_process");
|
|
268674
|
-
|
|
268701
|
+
|
|
268675
268702
|
defineTool({
|
|
268676
268703
|
name: "tool-name",
|
|
268677
268704
|
description: "what it does",
|
|
@@ -268687,23 +268714,23 @@ defineTool({
|
|
|
268687
268714
|
},
|
|
268688
268715
|
});
|
|
268689
268716
|
\`\`\`
|
|
268690
|
-
|
|
268717
|
+
|
|
268691
268718
|
NEVER use module.exports, registerTool, ctx.tools.shell, or any other format. See addons/run-tests.js for a full working example.
|
|
268692
|
-
|
|
268719
|
+
|
|
268693
268720
|
## SCAFFOLDING
|
|
268694
|
-
|
|
268721
|
+
|
|
268695
268722
|
When creating multiple files, emit ONE write-file per response and wait for each result:
|
|
268696
|
-
|
|
268723
|
+
|
|
268697
268724
|
<write-file>
|
|
268698
268725
|
{"path": "myapp/package.json", "content": "..."}
|
|
268699
268726
|
</write-file>
|
|
268700
|
-
|
|
268727
|
+
|
|
268701
268728
|
Wait for result, then emit the next file. Never chain write-file tags when content is complex.
|
|
268702
|
-
|
|
268729
|
+
|
|
268703
268730
|
## CODEBASE
|
|
268704
|
-
|
|
268731
|
+
|
|
268705
268732
|
${fileList.length > 0 ? fileList : "(no files indexed)"}
|
|
268706
|
-
|
|
268733
|
+
|
|
268707
268734
|
${memorySummary}`;
|
|
268708
268735
|
}
|
|
268709
268736
|
var BUILTIN_TOOLS_SECTION = `## TOOLS
|
|
@@ -272908,6 +272935,7 @@ function parseArgs(body) {
|
|
|
272908
272935
|
var gitStatusTool = {
|
|
272909
272936
|
name: "git-status",
|
|
272910
272937
|
description: "show working tree status",
|
|
272938
|
+
tag: "git",
|
|
272911
272939
|
safe: true,
|
|
272912
272940
|
permissionLabel: "git status",
|
|
272913
272941
|
systemPromptEntry: (i) => `### ${i}. git-status — show working tree status (staged, unstaged, untracked)
|
|
@@ -272925,6 +272953,7 @@ var gitStatusTool = {
|
|
|
272925
272953
|
var gitLogTool = {
|
|
272926
272954
|
name: "git-log",
|
|
272927
272955
|
description: "show commit log",
|
|
272956
|
+
tag: "git",
|
|
272928
272957
|
safe: true,
|
|
272929
272958
|
permissionLabel: "git log",
|
|
272930
272959
|
systemPromptEntry: (i) => `### ${i}. git-log — show commit log with optional flags
|
|
@@ -272941,6 +272970,7 @@ var gitLogTool = {
|
|
|
272941
272970
|
var gitDiffTool = {
|
|
272942
272971
|
name: "git-diff",
|
|
272943
272972
|
description: "show changes between commits, working tree, or staged files",
|
|
272973
|
+
tag: "git",
|
|
272944
272974
|
safe: true,
|
|
272945
272975
|
permissionLabel: "git diff",
|
|
272946
272976
|
systemPromptEntry: (i) => `### ${i}. git-diff — show changes
|
|
@@ -272958,6 +272988,7 @@ var gitDiffTool = {
|
|
|
272958
272988
|
var gitShowTool = {
|
|
272959
272989
|
name: "git-show",
|
|
272960
272990
|
description: "show a commit's details and stat",
|
|
272991
|
+
tag: "git",
|
|
272961
272992
|
safe: true,
|
|
272962
272993
|
permissionLabel: "git show",
|
|
272963
272994
|
systemPromptEntry: (i) => `### ${i}. git-show — show a commit's details
|
|
@@ -272973,6 +273004,7 @@ var gitShowTool = {
|
|
|
272973
273004
|
var gitBranchTool = {
|
|
272974
273005
|
name: "git-branch",
|
|
272975
273006
|
description: "list branches",
|
|
273007
|
+
tag: "git",
|
|
272976
273008
|
safe: true,
|
|
272977
273009
|
permissionLabel: "git branch",
|
|
272978
273010
|
systemPromptEntry: (i) => `### ${i}. git-branch — list branches
|
|
@@ -272989,6 +273021,7 @@ var gitBranchTool = {
|
|
|
272989
273021
|
var gitRemoteTool = {
|
|
272990
273022
|
name: "git-remote",
|
|
272991
273023
|
description: "list or inspect remotes",
|
|
273024
|
+
tag: "git",
|
|
272992
273025
|
safe: true,
|
|
272993
273026
|
permissionLabel: "git remote",
|
|
272994
273027
|
systemPromptEntry: (i) => `### ${i}. git-remote — list remotes
|
|
@@ -273003,6 +273036,7 @@ var gitRemoteTool = {
|
|
|
273003
273036
|
var gitTagTool = {
|
|
273004
273037
|
name: "git-tag",
|
|
273005
273038
|
description: "list tags",
|
|
273039
|
+
tag: "git",
|
|
273006
273040
|
safe: true,
|
|
273007
273041
|
permissionLabel: "git tag",
|
|
273008
273042
|
systemPromptEntry: (i) => `### ${i}. git-tag — list tags
|
|
@@ -273018,6 +273052,7 @@ var gitTagTool = {
|
|
|
273018
273052
|
var gitBlameTool = {
|
|
273019
273053
|
name: "git-blame",
|
|
273020
273054
|
description: "show who last modified each line of a file",
|
|
273055
|
+
tag: "git",
|
|
273021
273056
|
safe: true,
|
|
273022
273057
|
permissionLabel: "git blame",
|
|
273023
273058
|
systemPromptEntry: (i) => `### ${i}. git-blame — show per-line authorship
|
|
@@ -273053,6 +273088,7 @@ var gitBlameTool = {
|
|
|
273053
273088
|
var gitStashListTool = {
|
|
273054
273089
|
name: "git-stash-list",
|
|
273055
273090
|
description: "list stashed changes",
|
|
273091
|
+
tag: "git",
|
|
273056
273092
|
safe: true,
|
|
273057
273093
|
permissionLabel: "git stash list",
|
|
273058
273094
|
systemPromptEntry: (i) => `### ${i}. git-stash-list — list stashes
|
|
@@ -273067,6 +273103,7 @@ var gitStashListTool = {
|
|
|
273067
273103
|
var gitAddTool = {
|
|
273068
273104
|
name: "git-add",
|
|
273069
273105
|
description: "stage files for commit",
|
|
273106
|
+
tag: "git",
|
|
273070
273107
|
safe: false,
|
|
273071
273108
|
permissionLabel: "git add",
|
|
273072
273109
|
systemPromptEntry: (i) => `### ${i}. git-add — stage files
|
|
@@ -273087,6 +273124,7 @@ var gitAddTool = {
|
|
|
273087
273124
|
var gitCommitTool = {
|
|
273088
273125
|
name: "git-commit",
|
|
273089
273126
|
description: "commit staged changes with a message",
|
|
273127
|
+
tag: "git",
|
|
273090
273128
|
safe: false,
|
|
273091
273129
|
permissionLabel: "git commit",
|
|
273092
273130
|
systemPromptEntry: (i) => `### ${i}. git-commit — commit staged changes (stage with git-add first)
|
|
@@ -273107,6 +273145,7 @@ var gitCommitTool = {
|
|
|
273107
273145
|
var gitCommitAmendTool = {
|
|
273108
273146
|
name: "git-commit-amend",
|
|
273109
273147
|
description: "amend the last commit message",
|
|
273148
|
+
tag: "git",
|
|
273110
273149
|
safe: false,
|
|
273111
273150
|
permissionLabel: "git commit --amend",
|
|
273112
273151
|
systemPromptEntry: (i) => `### ${i}. git-commit-amend — amend the last commit message
|
|
@@ -273127,6 +273166,7 @@ var gitCommitAmendTool = {
|
|
|
273127
273166
|
var gitRevertTool = {
|
|
273128
273167
|
name: "git-revert",
|
|
273129
273168
|
description: "revert a commit by hash (creates a new revert commit, history preserved)",
|
|
273169
|
+
tag: "git",
|
|
273130
273170
|
safe: false,
|
|
273131
273171
|
permissionLabel: "git revert",
|
|
273132
273172
|
systemPromptEntry: (i) => `### ${i}. git-revert — revert a commit (safe, creates new commit)
|
|
@@ -273146,6 +273186,7 @@ var gitRevertTool = {
|
|
|
273146
273186
|
var gitResetTool = {
|
|
273147
273187
|
name: "git-reset",
|
|
273148
273188
|
description: "reset HEAD or unstage files",
|
|
273189
|
+
tag: "git",
|
|
273149
273190
|
safe: false,
|
|
273150
273191
|
permissionLabel: "git reset",
|
|
273151
273192
|
systemPromptEntry: (i) => `### ${i}. git-reset — reset HEAD or unstage files
|
|
@@ -273166,6 +273207,7 @@ var gitResetTool = {
|
|
|
273166
273207
|
var gitCheckoutTool = {
|
|
273167
273208
|
name: "git-checkout",
|
|
273168
273209
|
description: "switch branches or restore files",
|
|
273210
|
+
tag: "git",
|
|
273169
273211
|
safe: false,
|
|
273170
273212
|
permissionLabel: "git checkout",
|
|
273171
273213
|
systemPromptEntry: (i) => `### ${i}. git-checkout — switch branch or restore file
|
|
@@ -273186,6 +273228,7 @@ var gitCheckoutTool = {
|
|
|
273186
273228
|
var gitSwitchTool = {
|
|
273187
273229
|
name: "git-switch",
|
|
273188
273230
|
description: "switch or create branches",
|
|
273231
|
+
tag: "git",
|
|
273189
273232
|
safe: false,
|
|
273190
273233
|
permissionLabel: "git switch",
|
|
273191
273234
|
systemPromptEntry: (i) => `### ${i}. git-switch — switch or create branches
|
|
@@ -273206,6 +273249,7 @@ var gitSwitchTool = {
|
|
|
273206
273249
|
var gitMergeTool = {
|
|
273207
273250
|
name: "git-merge",
|
|
273208
273251
|
description: "merge a branch into the current branch",
|
|
273252
|
+
tag: "git",
|
|
273209
273253
|
safe: false,
|
|
273210
273254
|
permissionLabel: "git merge",
|
|
273211
273255
|
systemPromptEntry: (i) => `### ${i}. git-merge — merge a branch into HEAD
|
|
@@ -273225,6 +273269,7 @@ var gitMergeTool = {
|
|
|
273225
273269
|
var gitPullTool = {
|
|
273226
273270
|
name: "git-pull",
|
|
273227
273271
|
description: "pull from remote",
|
|
273272
|
+
tag: "git",
|
|
273228
273273
|
safe: false,
|
|
273229
273274
|
permissionLabel: "git pull",
|
|
273230
273275
|
systemPromptEntry: (i) => `### ${i}. git-pull — pull from remote
|
|
@@ -273243,6 +273288,7 @@ var gitPullTool = {
|
|
|
273243
273288
|
var gitPushTool = {
|
|
273244
273289
|
name: "git-push",
|
|
273245
273290
|
description: "push commits to remote",
|
|
273291
|
+
tag: "git",
|
|
273246
273292
|
safe: false,
|
|
273247
273293
|
permissionLabel: "git push",
|
|
273248
273294
|
systemPromptEntry: (i) => `### ${i}. git-push — push to remote
|
|
@@ -273262,6 +273308,7 @@ var gitPushTool = {
|
|
|
273262
273308
|
var gitStashTool = {
|
|
273263
273309
|
name: "git-stash",
|
|
273264
273310
|
description: "stash or apply stashed changes",
|
|
273311
|
+
tag: "git",
|
|
273265
273312
|
safe: false,
|
|
273266
273313
|
permissionLabel: "git stash",
|
|
273267
273314
|
systemPromptEntry: (i) => `### ${i}. git-stash — stash/apply/pop/drop changes
|
|
@@ -273283,6 +273330,7 @@ var gitStashTool = {
|
|
|
273283
273330
|
var gitBranchCreateTool = {
|
|
273284
273331
|
name: "git-branch-create",
|
|
273285
273332
|
description: "create a new branch without switching to it",
|
|
273333
|
+
tag: "git",
|
|
273286
273334
|
safe: false,
|
|
273287
273335
|
permissionLabel: "git branch (create)",
|
|
273288
273336
|
systemPromptEntry: (i) => `### ${i}. git-branch-create — create a branch
|
|
@@ -273302,6 +273350,7 @@ var gitBranchCreateTool = {
|
|
|
273302
273350
|
var gitBranchDeleteTool = {
|
|
273303
273351
|
name: "git-branch-delete",
|
|
273304
273352
|
description: "delete a branch",
|
|
273353
|
+
tag: "git",
|
|
273305
273354
|
safe: false,
|
|
273306
273355
|
permissionLabel: "git branch -d",
|
|
273307
273356
|
systemPromptEntry: (i) => `### ${i}. git-branch-delete — delete a branch
|
|
@@ -273325,6 +273374,7 @@ var gitBranchDeleteTool = {
|
|
|
273325
273374
|
var gitCherryPickTool = {
|
|
273326
273375
|
name: "git-cherry-pick",
|
|
273327
273376
|
description: "apply a specific commit from another branch",
|
|
273377
|
+
tag: "git",
|
|
273328
273378
|
safe: false,
|
|
273329
273379
|
permissionLabel: "git cherry-pick",
|
|
273330
273380
|
systemPromptEntry: (i) => `### ${i}. git-cherry-pick — apply a commit by hash
|
|
@@ -273344,6 +273394,7 @@ var gitCherryPickTool = {
|
|
|
273344
273394
|
var gitTagCreateTool = {
|
|
273345
273395
|
name: "git-tag-create",
|
|
273346
273396
|
description: "create a lightweight or annotated tag",
|
|
273397
|
+
tag: "git",
|
|
273347
273398
|
safe: false,
|
|
273348
273399
|
permissionLabel: "git tag (create)",
|
|
273349
273400
|
systemPromptEntry: (i) => `### ${i}. git-tag-create — create a tag
|
|
@@ -273364,6 +273415,7 @@ var gitTagCreateTool = {
|
|
|
273364
273415
|
var gitRestoreTool = {
|
|
273365
273416
|
name: "git-restore",
|
|
273366
273417
|
description: "discard working directory changes for a file (cannot be undone)",
|
|
273418
|
+
tag: "git",
|
|
273367
273419
|
safe: false,
|
|
273368
273420
|
permissionLabel: "git restore",
|
|
273369
273421
|
systemPromptEntry: (i) => `### ${i}. git-restore — discard changes in a file (irreversible)
|
|
@@ -273383,6 +273435,7 @@ var gitRestoreTool = {
|
|
|
273383
273435
|
var gitCleanTool = {
|
|
273384
273436
|
name: "git-clean",
|
|
273385
273437
|
description: "remove untracked files (cannot be undone)",
|
|
273438
|
+
tag: "git",
|
|
273386
273439
|
safe: false,
|
|
273387
273440
|
permissionLabel: "git clean",
|
|
273388
273441
|
systemPromptEntry: (i) => `### ${i}. git-clean — remove untracked files (irreversible)
|
|
@@ -274736,6 +274789,43 @@ function TimelineRunner({
|
|
|
274736
274789
|
// src/components/chat/hooks/useChat.ts
|
|
274737
274790
|
var import_react48 = __toESM(require_react(), 1);
|
|
274738
274791
|
var import_react49 = __toESM(require_react(), 1);
|
|
274792
|
+
|
|
274793
|
+
// src/utils/intentClassifier.ts
|
|
274794
|
+
var READONLY_PATTERNS = [
|
|
274795
|
+
/\b(list|ls|dir|show|display|print|dump)\b/i,
|
|
274796
|
+
/\bwhat(('?s| is| are| does)\b| files| folder)/i,
|
|
274797
|
+
/\b(folder|directory|file) (structure|tree|layout|contents?)\b/i,
|
|
274798
|
+
/\bexplore\b/i,
|
|
274799
|
+
/\b(read|open|view|look at|check out|inspect|peek)\b/i,
|
|
274800
|
+
/\b(explain|describe|summarize|summarise|tell me about|walk me through)\b/i,
|
|
274801
|
+
/\bhow does\b/i,
|
|
274802
|
+
/\bwhat('?s| is) (in|inside|this|that|the)\b/i,
|
|
274803
|
+
/\b(find|search|grep|locate|where is|where are)\b/i,
|
|
274804
|
+
/\b(look for|scan|trace)\b/i,
|
|
274805
|
+
/\bunderstand\b/i,
|
|
274806
|
+
/\bshow me (how|what|where|why)\b/i
|
|
274807
|
+
];
|
|
274808
|
+
var MUTATING_PATTERNS = [
|
|
274809
|
+
/\b(write|create|make|generate|add|build|scaffold|init|initialize|setup|set up)\b/i,
|
|
274810
|
+
/\b(new file|new folder|new component|new page|new route)\b/i,
|
|
274811
|
+
/\b(edit|modify|update|change|refactor|rename|move|migrate)\b/i,
|
|
274812
|
+
/\b(fix|patch|resolve|correct|debug|repair)\b/i,
|
|
274813
|
+
/\b(implement|add .+ to|insert|inject|append|prepend)\b/i,
|
|
274814
|
+
/\b(delete|remove|drop|clean ?up|purge|wipe)\b/i,
|
|
274815
|
+
/\b(run|execute|install|deploy|build|test|start|launch|compile|lint|format)\b/i
|
|
274816
|
+
];
|
|
274817
|
+
function classifyIntent(userMessage) {
|
|
274818
|
+
const text = userMessage.trim();
|
|
274819
|
+
const mutatingScore = MUTATING_PATTERNS.filter((p) => p.test(text)).length;
|
|
274820
|
+
const readonlyScore = READONLY_PATTERNS.filter((p) => p.test(text)).length;
|
|
274821
|
+
if (mutatingScore === 0 && readonlyScore > 0)
|
|
274822
|
+
return "readonly";
|
|
274823
|
+
if (mutatingScore > 0)
|
|
274824
|
+
return "mutating";
|
|
274825
|
+
return "any";
|
|
274826
|
+
}
|
|
274827
|
+
|
|
274828
|
+
// src/components/chat/hooks/useChat.ts
|
|
274739
274829
|
function useChat(repoPath) {
|
|
274740
274830
|
const [stage, setStage] = import_react48.useState({ type: "picking-provider" });
|
|
274741
274831
|
const [committed, setCommitted] = import_react48.useState([]);
|
|
@@ -275052,8 +275142,13 @@ function useChat(repoPath) {
|
|
|
275052
275142
|
}
|
|
275053
275143
|
const abort = new AbortController;
|
|
275054
275144
|
abortControllerRef.current = abort;
|
|
275145
|
+
const intent = classifyIntent(text);
|
|
275146
|
+
const scopedToolsSection = registry.buildSystemPromptSection(intent);
|
|
275147
|
+
const scopedSystemPrompt = currentSystemPrompt.replace(/## TOOLS[\s\S]*?(?=\n## (?!TOOLS))/, scopedToolsSection + `
|
|
275148
|
+
|
|
275149
|
+
`);
|
|
275055
275150
|
setStage({ type: "thinking" });
|
|
275056
|
-
callChat(currentProvider,
|
|
275151
|
+
callChat(currentProvider, scopedSystemPrompt, nextAll, abort.signal).then((raw) => processResponse(raw, nextAll, abort.signal)).catch(handleError(nextAll));
|
|
275057
275152
|
};
|
|
275058
275153
|
const handleProviderDone = (p) => {
|
|
275059
275154
|
setProvider(p);
|
|
@@ -278000,6 +278095,17 @@ function CommitCommand({
|
|
|
278000
278095
|
confirm
|
|
278001
278096
|
}, undefined, false, undefined, this);
|
|
278002
278097
|
}
|
|
278098
|
+
|
|
278099
|
+
// node_modules/@ridit/lens-sdk/dist/index.mjs
|
|
278100
|
+
var TOOL_TAGS = {
|
|
278101
|
+
read: "read",
|
|
278102
|
+
net: "net",
|
|
278103
|
+
write: "write",
|
|
278104
|
+
delete: "delete",
|
|
278105
|
+
shell: "shell",
|
|
278106
|
+
git: "git",
|
|
278107
|
+
find: "find"
|
|
278108
|
+
};
|
|
278003
278109
|
// src/tools/view-image.ts
|
|
278004
278110
|
import path26 from "path";
|
|
278005
278111
|
import { existsSync as existsSync20, readFileSync as readFileSync14 } from "fs";
|
|
@@ -278571,6 +278677,7 @@ var fetchTool = {
|
|
|
278571
278677
|
name: "fetch",
|
|
278572
278678
|
description: "load a URL",
|
|
278573
278679
|
safe: true,
|
|
278680
|
+
tag: TOOL_TAGS.net,
|
|
278574
278681
|
permissionLabel: "fetch",
|
|
278575
278682
|
systemPromptEntry: (i) => `### ${i}. fetch — load a URL
|
|
278576
278683
|
<fetch>https://example.com</fetch>`,
|
|
@@ -278592,6 +278699,7 @@ var shellTool = {
|
|
|
278592
278699
|
name: "shell",
|
|
278593
278700
|
description: "run a terminal command",
|
|
278594
278701
|
safe: false,
|
|
278702
|
+
tag: TOOL_TAGS.shell,
|
|
278595
278703
|
permissionLabel: "run",
|
|
278596
278704
|
systemPromptEntry: (i) => `### ${i}. shell — run a terminal command
|
|
278597
278705
|
<shell>node -v</shell>`,
|
|
@@ -278606,6 +278714,7 @@ var readFileTool = {
|
|
|
278606
278714
|
name: "read-file",
|
|
278607
278715
|
description: "read a file from the repo",
|
|
278608
278716
|
safe: true,
|
|
278717
|
+
tag: TOOL_TAGS.read,
|
|
278609
278718
|
permissionLabel: "read",
|
|
278610
278719
|
systemPromptEntry: (i) => `### ${i}. read-file — read a file from the repo
|
|
278611
278720
|
<read-file>src/foo.ts</read-file>`,
|
|
@@ -278619,6 +278728,7 @@ var readFileTool = {
|
|
|
278619
278728
|
var readFolderTool = {
|
|
278620
278729
|
name: "read-folder",
|
|
278621
278730
|
description: "list contents of a folder (files + subfolders, one level deep)",
|
|
278731
|
+
tag: TOOL_TAGS.read,
|
|
278622
278732
|
safe: true,
|
|
278623
278733
|
permissionLabel: "folder",
|
|
278624
278734
|
systemPromptEntry: (i) => `### ${i}. read-folder — list contents of a folder (files + subfolders, one level deep)
|
|
@@ -278633,6 +278743,7 @@ var readFolderTool = {
|
|
|
278633
278743
|
var grepTool = {
|
|
278634
278744
|
name: "grep",
|
|
278635
278745
|
description: "search for a pattern across files in the repo",
|
|
278746
|
+
tag: TOOL_TAGS.find,
|
|
278636
278747
|
safe: true,
|
|
278637
278748
|
permissionLabel: "grep",
|
|
278638
278749
|
systemPromptEntry: (i) => `### ${i}. grep — search for a pattern across files in the repo (cross-platform, no shell needed)
|
|
@@ -278656,6 +278767,7 @@ var grepTool = {
|
|
|
278656
278767
|
var writeFileTool = {
|
|
278657
278768
|
name: "write-file",
|
|
278658
278769
|
description: "create or overwrite a file",
|
|
278770
|
+
tag: TOOL_TAGS.write,
|
|
278659
278771
|
safe: false,
|
|
278660
278772
|
permissionLabel: "write",
|
|
278661
278773
|
systemPromptEntry: (i) => `### ${i}. write-file — create or overwrite a file
|
|
@@ -278681,6 +278793,7 @@ var writeFileTool = {
|
|
|
278681
278793
|
var deleteFileTool = {
|
|
278682
278794
|
name: "delete-file",
|
|
278683
278795
|
description: "permanently delete a single file",
|
|
278796
|
+
tag: TOOL_TAGS.delete,
|
|
278684
278797
|
safe: false,
|
|
278685
278798
|
permissionLabel: "delete",
|
|
278686
278799
|
systemPromptEntry: (i) => `### ${i}. delete-file — permanently delete a single file
|
|
@@ -278695,6 +278808,7 @@ var deleteFileTool = {
|
|
|
278695
278808
|
var deleteFolderTool = {
|
|
278696
278809
|
name: "delete-folder",
|
|
278697
278810
|
description: "permanently delete a folder and all its contents",
|
|
278811
|
+
tag: TOOL_TAGS.delete,
|
|
278698
278812
|
safe: false,
|
|
278699
278813
|
permissionLabel: "delete folder",
|
|
278700
278814
|
systemPromptEntry: (i) => `### ${i}. delete-folder — permanently delete a folder and all its contents
|
|
@@ -278709,6 +278823,7 @@ var deleteFolderTool = {
|
|
|
278709
278823
|
var openUrlTool = {
|
|
278710
278824
|
name: "open-url",
|
|
278711
278825
|
description: "open a URL in the user's default browser",
|
|
278826
|
+
tag: TOOL_TAGS.net,
|
|
278712
278827
|
safe: true,
|
|
278713
278828
|
permissionLabel: "open",
|
|
278714
278829
|
systemPromptEntry: (i) => `### ${i}. open-url — open a URL in the user's default browser
|
|
@@ -278720,6 +278835,7 @@ var openUrlTool = {
|
|
|
278720
278835
|
var generatePdfTool = {
|
|
278721
278836
|
name: "generate-pdf",
|
|
278722
278837
|
description: "generate a PDF file from markdown-style content",
|
|
278838
|
+
tag: TOOL_TAGS.write,
|
|
278723
278839
|
safe: false,
|
|
278724
278840
|
permissionLabel: "pdf",
|
|
278725
278841
|
systemPromptEntry: (i) => `### ${i}. generate-pdf — generate a PDF file from markdown-style content
|
|
@@ -278745,6 +278861,7 @@ var generatePdfTool = {
|
|
|
278745
278861
|
};
|
|
278746
278862
|
var searchTool = {
|
|
278747
278863
|
name: "search",
|
|
278864
|
+
tag: TOOL_TAGS.net,
|
|
278748
278865
|
description: "search the internet for anything you are unsure about",
|
|
278749
278866
|
safe: true,
|
|
278750
278867
|
permissionLabel: "search",
|
|
@@ -278767,6 +278884,7 @@ var searchTool = {
|
|
|
278767
278884
|
var cloneTool = {
|
|
278768
278885
|
name: "clone",
|
|
278769
278886
|
description: "clone a GitHub repo so you can explore and discuss it",
|
|
278887
|
+
tag: TOOL_TAGS.write,
|
|
278770
278888
|
safe: false,
|
|
278771
278889
|
permissionLabel: "clone",
|
|
278772
278890
|
systemPromptEntry: (i) => `### ${i}. clone — clone a GitHub repo so you can explore and discuss it
|
|
@@ -278781,6 +278899,7 @@ var cloneTool = {
|
|
|
278781
278899
|
var changesTool = {
|
|
278782
278900
|
name: "changes",
|
|
278783
278901
|
description: "propose code edits (shown as a diff for user approval)",
|
|
278902
|
+
tag: TOOL_TAGS.write,
|
|
278784
278903
|
safe: false,
|
|
278785
278904
|
permissionLabel: "changes",
|
|
278786
278905
|
systemPromptEntry: (i) => `### ${i}. changes — propose code edits (shown as a diff for user approval)
|
|
@@ -278803,6 +278922,7 @@ var changesTool = {
|
|
|
278803
278922
|
var readFilesTool = {
|
|
278804
278923
|
name: "read-files",
|
|
278805
278924
|
description: "read multiple files from the repo at once",
|
|
278925
|
+
tag: TOOL_TAGS.read,
|
|
278806
278926
|
safe: true,
|
|
278807
278927
|
permissionLabel: "read",
|
|
278808
278928
|
systemPromptEntry: (i) => `### ${i}. read-files — read multiple files from the repo at once
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ridit/lens",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"description": "Know Your Codebase.",
|
|
5
5
|
"author": "Ridit Jangra <riditjangra09@gmail.com> (https://ridit.space)",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"prepublishOnly": "npm run build && npm run tag"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@ridit/lens-sdk": "0.
|
|
22
|
+
"@ridit/lens-sdk": "^0.2.0",
|
|
23
23
|
"asciichart": "^1.5.25",
|
|
24
24
|
"bun": "^1.3.11",
|
|
25
25
|
"commander": "^14.0.3",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useState, useRef } from "react";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import type { Provider } from "../../../types/config";
|
|
4
|
+
import { classifyIntent } from "../../../utils/intentClassifier";
|
|
4
5
|
import type { Message, ChatStage } from "../../../types/chat";
|
|
5
6
|
import {
|
|
6
7
|
saveChat,
|
|
@@ -421,8 +422,16 @@ export function useChat(repoPath: string) {
|
|
|
421
422
|
const abort = new AbortController();
|
|
422
423
|
abortControllerRef.current = abort;
|
|
423
424
|
|
|
425
|
+
const intent = classifyIntent(text);
|
|
426
|
+
const scopedToolsSection = registry.buildSystemPromptSection(intent);
|
|
427
|
+
|
|
428
|
+
const scopedSystemPrompt = currentSystemPrompt.replace(
|
|
429
|
+
/## TOOLS[\s\S]*?(?=\n## (?!TOOLS))/,
|
|
430
|
+
scopedToolsSection + "\n\n",
|
|
431
|
+
);
|
|
432
|
+
|
|
424
433
|
setStage({ type: "thinking" });
|
|
425
|
-
callChat(currentProvider,
|
|
434
|
+
callChat(currentProvider, scopedSystemPrompt, nextAll, abort.signal)
|
|
426
435
|
.then((raw: string) => processResponse(raw, nextAll, abort.signal))
|
|
427
436
|
.catch(handleError(nextAll));
|
|
428
437
|
};
|
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,25 @@ 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
|
+
|
|
23
24
|
### memory-add — save something important to long-term memory for this repo
|
|
24
25
|
<memory-add>User prefers TypeScript strict mode in all new files</memory-add>
|
|
25
|
-
|
|
26
|
+
|
|
26
27
|
### memory-delete — delete a memory by its ID (shown in brackets like [abc123])
|
|
27
28
|
<memory-delete>abc123</memory-delete>
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
Use memory-add when the user asks you to remember something, or when you learn something project-specific that would be useful in future sessions.
|
|
30
31
|
Use memory-delete when the user asks you to forget something or a memory is outdated.
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
## RULES
|
|
33
|
-
|
|
34
|
+
|
|
34
35
|
1. ONE tool per response — emit the XML tag, then stop. Never chain tools in one response except when scaffolding (see below).
|
|
35
36
|
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
37
|
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 +49,15 @@ Use memory-delete when the user asks you to forget something or a memory is outd
|
|
|
48
49
|
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
50
|
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
51
|
17. When scaffolding multiple files, emit ONE write-file tag per response and wait for the result before writing the next file.
|
|
51
|
-
|
|
52
|
+
|
|
52
53
|
## ADDON FORMAT
|
|
53
|
-
|
|
54
|
+
|
|
54
55
|
All addons use defineTool from @ridit/lens-sdk. The ONLY correct format is:
|
|
55
|
-
|
|
56
|
+
|
|
56
57
|
\`\`\`js
|
|
57
58
|
const { defineTool } = require("@ridit/lens-sdk");
|
|
58
59
|
const { execSync } = require("child_process");
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
defineTool({
|
|
61
62
|
name: "tool-name",
|
|
62
63
|
description: "what it does",
|
|
@@ -72,26 +73,146 @@ defineTool({
|
|
|
72
73
|
},
|
|
73
74
|
});
|
|
74
75
|
\`\`\`
|
|
75
|
-
|
|
76
|
+
|
|
76
77
|
NEVER use module.exports, registerTool, ctx.tools.shell, or any other format. See addons/run-tests.js for a full working example.
|
|
77
|
-
|
|
78
|
+
|
|
78
79
|
## SCAFFOLDING
|
|
79
|
-
|
|
80
|
+
|
|
80
81
|
When creating multiple files, emit ONE write-file per response and wait for each result:
|
|
81
|
-
|
|
82
|
+
|
|
82
83
|
<write-file>
|
|
83
84
|
{"path": "myapp/package.json", "content": "..."}
|
|
84
85
|
</write-file>
|
|
85
|
-
|
|
86
|
+
|
|
86
87
|
Wait for result, then emit the next file. Never chain write-file tags when content is complex.
|
|
87
|
-
|
|
88
|
+
|
|
88
89
|
## CODEBASE
|
|
89
|
-
|
|
90
|
+
|
|
90
91
|
${fileList.length > 0 ? fileList : "(no files indexed)"}
|
|
91
|
-
|
|
92
|
+
|
|
92
93
|
${memorySummary}`;
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
export function buildBuiltinToolsSection(intent: Intent = "any"): string {
|
|
97
|
+
const isReadonly = intent === "readonly";
|
|
98
|
+
|
|
99
|
+
const readTools = `### 1. fetch — load a URL
|
|
100
|
+
<fetch>https://example.com</fetch>
|
|
101
|
+
|
|
102
|
+
### 2. read-file — read a single file from the repo
|
|
103
|
+
<read-file>src/foo.ts</read-file>
|
|
104
|
+
|
|
105
|
+
### 3. read-files — read multiple files at once
|
|
106
|
+
<read-files>
|
|
107
|
+
["src/foo.ts", "src/bar.ts"]
|
|
108
|
+
</read-files>
|
|
109
|
+
|
|
110
|
+
### 4. read-folder — list contents of a folder (one level deep)
|
|
111
|
+
<read-folder>src/components</read-folder>
|
|
112
|
+
|
|
113
|
+
### 5. grep — search for a pattern across files
|
|
114
|
+
<grep>
|
|
115
|
+
{"pattern": "ChatRunner", "glob": "src/**/*.tsx"}
|
|
116
|
+
</grep>
|
|
117
|
+
|
|
118
|
+
### 6. search — search the internet
|
|
119
|
+
<search>how to use React useEffect cleanup</search>`;
|
|
120
|
+
|
|
121
|
+
const writeTools = `### 7. shell — run a terminal command (NOT for filesystem inspection)
|
|
122
|
+
<shell>node -v</shell>
|
|
123
|
+
|
|
124
|
+
### 8. write-file — create or overwrite a file (COMPLETE content only)
|
|
125
|
+
<write-file>
|
|
126
|
+
{"path": "data/output.csv", "content": "col1,col2\\nval1,val2"}
|
|
127
|
+
</write-file>
|
|
128
|
+
|
|
129
|
+
### 9. delete-file — permanently delete a single file
|
|
130
|
+
<delete-file>src/old-component.tsx</delete-file>
|
|
131
|
+
|
|
132
|
+
### 10. delete-folder — permanently delete a folder and all its contents
|
|
133
|
+
<delete-folder>src/legacy</delete-folder>
|
|
134
|
+
|
|
135
|
+
### 11. open-url — open a URL in the user's default browser
|
|
136
|
+
<open-url>https://github.com/owner/repo</open-url>
|
|
137
|
+
|
|
138
|
+
### 12. generate-pdf — generate a PDF from markdown-style content
|
|
139
|
+
<generate-pdf>
|
|
140
|
+
{"path": "output/report.pdf", "content": "# Title\\n\\nBody text."}
|
|
141
|
+
</generate-pdf>
|
|
142
|
+
|
|
143
|
+
### 13. clone — clone a GitHub repo
|
|
144
|
+
<clone>https://github.com/owner/repo</clone>
|
|
145
|
+
|
|
146
|
+
### 14. changes — propose code edits shown as a diff for user approval
|
|
147
|
+
<changes>
|
|
148
|
+
{"summary": "what changed and why", "patches": [{"path": "src/foo.ts", "content": "COMPLETE file content", "isNew": false}]}
|
|
149
|
+
</changes>`;
|
|
150
|
+
|
|
151
|
+
if (isReadonly) {
|
|
152
|
+
return `## TOOLS
|
|
153
|
+
|
|
154
|
+
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.
|
|
155
|
+
|
|
156
|
+
${readTools}`;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return `## TOOLS
|
|
160
|
+
|
|
161
|
+
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.
|
|
162
|
+
|
|
163
|
+
### 1. fetch — load a URL
|
|
164
|
+
<fetch>https://example.com</fetch>
|
|
165
|
+
|
|
166
|
+
### 2. shell — run a terminal command (NOT for filesystem inspection)
|
|
167
|
+
<shell>node -v</shell>
|
|
168
|
+
|
|
169
|
+
### 3. read-file — read a single file from the repo
|
|
170
|
+
<read-file>src/foo.ts</read-file>
|
|
171
|
+
|
|
172
|
+
### 4. read-files — read multiple files at once
|
|
173
|
+
<read-files>
|
|
174
|
+
["src/foo.ts", "src/bar.ts"]
|
|
175
|
+
</read-files>
|
|
176
|
+
|
|
177
|
+
### 5. read-folder — list contents of a folder (one level deep)
|
|
178
|
+
<read-folder>src/components</read-folder>
|
|
179
|
+
|
|
180
|
+
### 6. grep — search for a pattern across files
|
|
181
|
+
<grep>
|
|
182
|
+
{"pattern": "ChatRunner", "glob": "src/**/*.tsx"}
|
|
183
|
+
</grep>
|
|
184
|
+
|
|
185
|
+
### 7. write-file — create or overwrite a file (COMPLETE content only)
|
|
186
|
+
<write-file>
|
|
187
|
+
{"path": "data/output.csv", "content": "col1,col2\\nval1,val2"}
|
|
188
|
+
</write-file>
|
|
189
|
+
|
|
190
|
+
### 8. delete-file — permanently delete a single file
|
|
191
|
+
<delete-file>src/old-component.tsx</delete-file>
|
|
192
|
+
|
|
193
|
+
### 9. delete-folder — permanently delete a folder and all its contents
|
|
194
|
+
<delete-folder>src/legacy</delete-folder>
|
|
195
|
+
|
|
196
|
+
### 10. open-url — open a URL in the user's default browser
|
|
197
|
+
<open-url>https://github.com/owner/repo</open-url>
|
|
198
|
+
|
|
199
|
+
### 11. generate-pdf — generate a PDF from markdown-style content
|
|
200
|
+
<generate-pdf>
|
|
201
|
+
{"path": "output/report.pdf", "content": "# Title\\n\\nBody text."}
|
|
202
|
+
</generate-pdf>
|
|
203
|
+
|
|
204
|
+
### 12. search — search the internet
|
|
205
|
+
<search>how to use React useEffect cleanup</search>
|
|
206
|
+
|
|
207
|
+
### 13. clone — clone a GitHub repo
|
|
208
|
+
<clone>https://github.com/owner/repo</clone>
|
|
209
|
+
|
|
210
|
+
### 14. changes — propose code edits shown as a diff for user approval
|
|
211
|
+
<changes>
|
|
212
|
+
{"summary": "what changed and why", "patches": [{"path": "src/foo.ts", "content": "COMPLETE file content", "isNew": false}]}
|
|
213
|
+
</changes>`;
|
|
214
|
+
}
|
|
215
|
+
|
|
95
216
|
const BUILTIN_TOOLS_SECTION = `## TOOLS
|
|
96
217
|
|
|
97
218
|
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) =>
|
|
@@ -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
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Tool, ToolContext } from "@ridit/lens-sdk";
|
|
2
|
+
import { TOOL_TAGS } from "@ridit/lens-sdk";
|
|
2
3
|
import {
|
|
3
4
|
fetchUrl,
|
|
4
5
|
searchWeb,
|
|
@@ -23,6 +24,7 @@ export const fetchTool: Tool<string> = {
|
|
|
23
24
|
name: "fetch",
|
|
24
25
|
description: "load a URL",
|
|
25
26
|
safe: true,
|
|
27
|
+
tag: TOOL_TAGS.net,
|
|
26
28
|
permissionLabel: "fetch",
|
|
27
29
|
systemPromptEntry: (i) =>
|
|
28
30
|
`### ${i}. fetch — load a URL\n<fetch>https://example.com</fetch>`,
|
|
@@ -45,6 +47,7 @@ export const shellTool: Tool<string> = {
|
|
|
45
47
|
name: "shell",
|
|
46
48
|
description: "run a terminal command",
|
|
47
49
|
safe: false,
|
|
50
|
+
tag: TOOL_TAGS.shell,
|
|
48
51
|
permissionLabel: "run",
|
|
49
52
|
systemPromptEntry: (i) =>
|
|
50
53
|
`### ${i}. shell — run a terminal command\n<shell>node -v</shell>`,
|
|
@@ -60,6 +63,7 @@ export const readFileTool: Tool<string> = {
|
|
|
60
63
|
name: "read-file",
|
|
61
64
|
description: "read a file from the repo",
|
|
62
65
|
safe: true,
|
|
66
|
+
tag: TOOL_TAGS.read,
|
|
63
67
|
permissionLabel: "read",
|
|
64
68
|
systemPromptEntry: (i) =>
|
|
65
69
|
`### ${i}. read-file — read a file from the repo\n<read-file>src/foo.ts</read-file>`,
|
|
@@ -74,6 +78,7 @@ export const readFileTool: Tool<string> = {
|
|
|
74
78
|
export const readFolderTool: Tool<string> = {
|
|
75
79
|
name: "read-folder",
|
|
76
80
|
description: "list contents of a folder (files + subfolders, one level deep)",
|
|
81
|
+
tag: TOOL_TAGS.read,
|
|
77
82
|
safe: true,
|
|
78
83
|
permissionLabel: "folder",
|
|
79
84
|
systemPromptEntry: (i) =>
|
|
@@ -94,6 +99,7 @@ interface GrepInput {
|
|
|
94
99
|
export const grepTool: Tool<GrepInput> = {
|
|
95
100
|
name: "grep",
|
|
96
101
|
description: "search for a pattern across files in the repo",
|
|
102
|
+
tag: TOOL_TAGS.find,
|
|
97
103
|
safe: true,
|
|
98
104
|
permissionLabel: "grep",
|
|
99
105
|
systemPromptEntry: (i) =>
|
|
@@ -124,6 +130,7 @@ interface WriteFileInput {
|
|
|
124
130
|
export const writeFileTool: Tool<WriteFileInput> = {
|
|
125
131
|
name: "write-file",
|
|
126
132
|
description: "create or overwrite a file",
|
|
133
|
+
tag: TOOL_TAGS.write,
|
|
127
134
|
safe: false,
|
|
128
135
|
permissionLabel: "write",
|
|
129
136
|
systemPromptEntry: (i) =>
|
|
@@ -147,6 +154,7 @@ export const writeFileTool: Tool<WriteFileInput> = {
|
|
|
147
154
|
export const deleteFileTool: Tool<string> = {
|
|
148
155
|
name: "delete-file",
|
|
149
156
|
description: "permanently delete a single file",
|
|
157
|
+
tag: TOOL_TAGS.delete,
|
|
150
158
|
safe: false,
|
|
151
159
|
permissionLabel: "delete",
|
|
152
160
|
systemPromptEntry: (i) =>
|
|
@@ -162,6 +170,7 @@ export const deleteFileTool: Tool<string> = {
|
|
|
162
170
|
export const deleteFolderTool: Tool<string> = {
|
|
163
171
|
name: "delete-folder",
|
|
164
172
|
description: "permanently delete a folder and all its contents",
|
|
173
|
+
tag: TOOL_TAGS.delete,
|
|
165
174
|
safe: false,
|
|
166
175
|
permissionLabel: "delete folder",
|
|
167
176
|
systemPromptEntry: (i) =>
|
|
@@ -177,6 +186,7 @@ export const deleteFolderTool: Tool<string> = {
|
|
|
177
186
|
export const openUrlTool: Tool<string> = {
|
|
178
187
|
name: "open-url",
|
|
179
188
|
description: "open a URL in the user's default browser",
|
|
189
|
+
tag: TOOL_TAGS.net,
|
|
180
190
|
safe: true,
|
|
181
191
|
permissionLabel: "open",
|
|
182
192
|
systemPromptEntry: (i) =>
|
|
@@ -194,6 +204,7 @@ interface GeneratePdfInput {
|
|
|
194
204
|
export const generatePdfTool: Tool<GeneratePdfInput> = {
|
|
195
205
|
name: "generate-pdf",
|
|
196
206
|
description: "generate a PDF file from markdown-style content",
|
|
207
|
+
tag: TOOL_TAGS.write,
|
|
197
208
|
safe: false,
|
|
198
209
|
permissionLabel: "pdf",
|
|
199
210
|
systemPromptEntry: (i) =>
|
|
@@ -222,6 +233,7 @@ export const generatePdfTool: Tool<GeneratePdfInput> = {
|
|
|
222
233
|
|
|
223
234
|
export const searchTool: Tool<string> = {
|
|
224
235
|
name: "search",
|
|
236
|
+
tag: TOOL_TAGS.net,
|
|
225
237
|
description: "search the internet for anything you are unsure about",
|
|
226
238
|
safe: true,
|
|
227
239
|
permissionLabel: "search",
|
|
@@ -245,6 +257,7 @@ export const searchTool: Tool<string> = {
|
|
|
245
257
|
export const cloneTool: Tool<string> = {
|
|
246
258
|
name: "clone",
|
|
247
259
|
description: "clone a GitHub repo so you can explore and discuss it",
|
|
260
|
+
tag: TOOL_TAGS.write,
|
|
248
261
|
safe: false,
|
|
249
262
|
permissionLabel: "clone",
|
|
250
263
|
systemPromptEntry: (i) =>
|
|
@@ -265,6 +278,7 @@ export interface ChangesInput {
|
|
|
265
278
|
export const changesTool: Tool<ChangesInput> = {
|
|
266
279
|
name: "changes",
|
|
267
280
|
description: "propose code edits (shown as a diff for user approval)",
|
|
281
|
+
tag: TOOL_TAGS.write,
|
|
268
282
|
safe: false,
|
|
269
283
|
permissionLabel: "changes",
|
|
270
284
|
systemPromptEntry: (i) =>
|
|
@@ -290,6 +304,7 @@ interface ReadFilesInput {
|
|
|
290
304
|
export const readFilesTool: Tool<ReadFilesInput> = {
|
|
291
305
|
name: "read-files",
|
|
292
306
|
description: "read multiple files from the repo at once",
|
|
307
|
+
tag: TOOL_TAGS.read,
|
|
293
308
|
safe: true,
|
|
294
309
|
permissionLabel: "read",
|
|
295
310
|
systemPromptEntry: (i) =>
|
|
@@ -1,4 +1,23 @@
|
|
|
1
|
-
import type { Tool } from "@ridit/lens-sdk";
|
|
1
|
+
import type { Tool, ToolTag } from "@ridit/lens-sdk";
|
|
2
|
+
import type { Intent } from "../intentClassifier";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Broad capability category for a tool.
|
|
6
|
+
* Used to filter the system prompt based on classified user intent.
|
|
7
|
+
*
|
|
8
|
+
* "read" — safe, purely observational (read-file, read-folder, grep, etc.)
|
|
9
|
+
* "net" — outbound network (fetch, search, clone, open-url)
|
|
10
|
+
* "write" — creates or overwrites file content (write-file, changes, generate-pdf)
|
|
11
|
+
* "delete" — destructive removal (delete-file, delete-folder)
|
|
12
|
+
* "shell" — arbitrary shell execution
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Tools allowed for each intent level */
|
|
16
|
+
const INTENT_ALLOWED: Record<Intent, ToolTag[]> = {
|
|
17
|
+
readonly: ["read", "net"],
|
|
18
|
+
mutating: ["read", "net", "write", "delete", "shell"],
|
|
19
|
+
any: ["read", "net", "write", "delete", "shell"],
|
|
20
|
+
};
|
|
2
21
|
|
|
3
22
|
class ToolRegistry {
|
|
4
23
|
private tools = new Map<string, Tool<unknown>>();
|
|
@@ -27,17 +46,54 @@ class ToolRegistry {
|
|
|
27
46
|
}
|
|
28
47
|
|
|
29
48
|
/**
|
|
30
|
-
*
|
|
49
|
+
* Returns tool names that are allowed for the given intent.
|
|
50
|
+
* Falls back to all names when a tool has no tag (legacy / addons).
|
|
51
|
+
*/
|
|
52
|
+
namesForIntent(intent: Intent): string[] {
|
|
53
|
+
const allowed = new Set(INTENT_ALLOWED[intent]);
|
|
54
|
+
return Array.from(this.tools.values())
|
|
55
|
+
.filter((t) => {
|
|
56
|
+
const tag = (t as any).tag as ToolTag | undefined;
|
|
57
|
+
// No tag = addon / unknown → always allow (conservative)
|
|
58
|
+
if (!tag) return true;
|
|
59
|
+
return allowed.has(tag);
|
|
60
|
+
})
|
|
61
|
+
.map((t) => t.name);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Build the TOOLS section of the system prompt from all registered tools,
|
|
66
|
+
* optionally scoped to a specific intent.
|
|
67
|
+
*
|
|
68
|
+
* When intent is "readonly", write/delete/shell tools are omitted entirely
|
|
69
|
+
* so the LLM never sees them and can't hallucinate calls to them.
|
|
31
70
|
*/
|
|
32
|
-
buildSystemPromptSection(): string {
|
|
71
|
+
buildSystemPromptSection(intent: Intent = "any"): string {
|
|
72
|
+
const allowed = new Set(INTENT_ALLOWED[intent]);
|
|
73
|
+
|
|
74
|
+
const visible = Array.from(this.tools.values()).filter((t) => {
|
|
75
|
+
const tag = (t as any).tag as ToolTag | undefined;
|
|
76
|
+
if (!tag) return true; // addon without tag → always show
|
|
77
|
+
return allowed.has(tag);
|
|
78
|
+
});
|
|
79
|
+
|
|
33
80
|
const lines: string[] = ["## TOOLS\n"];
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
81
|
+
|
|
82
|
+
if (intent === "readonly") {
|
|
83
|
+
lines.push(
|
|
84
|
+
`You have ${visible.length} tools available for this read-only request. ` +
|
|
85
|
+
`Do NOT attempt to write, delete, or run shell commands — ` +
|
|
86
|
+
`those tools are not available right now.\n`,
|
|
87
|
+
);
|
|
88
|
+
} else {
|
|
89
|
+
lines.push(
|
|
90
|
+
`You have exactly ${visible.length} tools. To use a tool you MUST wrap it ` +
|
|
91
|
+
`in the exact XML tags shown below — no other format will work.\n`,
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
39
95
|
let i = 1;
|
|
40
|
-
for (const tool of
|
|
96
|
+
for (const tool of visible) {
|
|
41
97
|
lines.push(tool.systemPromptEntry(i++));
|
|
42
98
|
}
|
|
43
99
|
return lines.join("\n");
|