@ridit/lens 0.3.0 → 0.3.2

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 CHANGED
@@ -270896,85 +270896,64 @@ They are stripped before display — the user will not see the raw tags.
270896
270896
  ### memory-delete — delete a memory by its ID (shown in brackets like [abc123])
270897
270897
  <memory-delete>abc123</memory-delete>
270898
270898
 
270899
- Use memory-add when:
270900
- - The user explicitly asks you to remember something ("remember that...", "don't forget...")
270901
- - You learn something project-specific that would be useful in future sessions
270902
- (e.g. preferred patterns, architecture decisions, known gotchas, user preferences)
270903
-
270904
- Use memory-delete when:
270905
- - The user asks you to forget something
270906
- - A memory is outdated or wrong and you are replacing it with a new one
270907
-
270908
- You may emit multiple memory operations in a single response alongside normal content.
270899
+ 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.
270900
+ Use memory-delete when the user asks you to forget something or a memory is outdated.
270909
270901
 
270910
270902
  ## RULES
270911
270903
 
270912
- 1. When you need to use a tool, output ONLY the XML tag nothing before or after it in that response
270913
- 2. ONE tool per response emit the tag, then stop completely
270914
- 3. After the user approves and you get the result, continue your analysis in the next response
270915
- 4. NEVER print a URL, command, filename, or JSON blob as plain text when you should be using a tool
270916
- 5. NEVER say "I'll fetch" / "run this command" / "here's the write-file" — just emit the tag
270917
- 6. NEVER use shell to run git clone always use the clone tag instead
270918
- 7. NEVER use shell to list files or folders (no ls, dir, find, git ls-files, tree) — ALWAYS use read-folder instead
270919
- 8. NEVER use shell to read a file (no cat, type, Get-Content) ALWAYS use read-file instead
270920
- 9. NEVER use shell grep, findstr, or Select-String to search file contentsALWAYS use grep instead
270921
- 10. shell is ONLY for running code, installing packages, building, testing not for filesystem inspection
270922
- 11. write-file content field must be the COMPLETE file content, never empty or placeholder
270923
- 12. After a write-file succeeds, do NOT repeat it — trust the result and move on
270924
- 13. After a write-file succeeds, tell the user it is done immediately do NOT auto-read the file back to verify
270925
- 13a. NEVER read a file you just wrote the write output confirms success. Reading back is a wasted tool call and will confuse you.
270926
- 14. NEVER apologize and redo a tool call you already made if write-file or shell ran and returned a result, it worked, do not run it again
270927
- 15. NEVER say "I made a mistake" and repeat the same tool one attempt is enough, trust the output
270928
- 16. NEVER second-guess yourself mid-response commit to your answer
270929
- 17. If a read-folder or read-file returns "not found", accept it and move on — do NOT retry the same path
270930
- 18. If you have already retrieved a result for a path in this conversation, do NOT request it again — use the result you already have
270931
- 19. Every shell command runs from the repo root — \`cd\` has NO persistent effect. NEVER use \`cd\` alone. Use full paths or combine with && e.g. \`cd list && bun run index.ts\`
270932
- 20. write-file paths are relative to the repo root if creating files in a subfolder write the full relative path e.g. \`list/src/index.tsx\` NOT \`src/index.tsx\`
270933
- 21. When scaffolding a new project in a subfolder, ALL write-file paths must start with that subfolder name e.g. \`list/package.json\`, \`list/src/index.tsx\`
270934
- 22. When scaffolding a multi-file project, after each write-file succeeds, immediately proceed to writing the NEXT file — NEVER rewrite a file you already wrote in this session. Each file is written ONCE and ONLY ONCE.
270935
- 23. For JSX/TSX files always use \`.tsx\` extension and include \`/** @jsxImportSource react */\` or ensure tsconfig has jsx set — bun needs this to parse JSX
270936
- 24. When explaining how to use a tool in text, use [tag] bracket notation or a fenced code block — NEVER emit a real XML tool tag as part of an explanation or example
270937
- 25. NEVER read files, list folders, or run tools that were not asked for in the current user message
270938
- 26. NEVER use markdown formatting in plain text responses — no **bold**, no *italics*, no # headings, no bullet points with -, *, or +, no numbered lists, no backtick inline code. Write in plain prose. Only use fenced \`\`\` code blocks when showing actual code.
270939
- 27. When the user asks you to CREATE a new file (e.g. "write a README", "create a config", "add a license", "this codebase doesn't have X"), write it IMMEDIATELY — do NOT read first, even if a stub exists.
270940
- 28. When a tool result is returned, your response must be directly based on that result — never invent or hallucinate content unrelated to the tool output.
270941
- 29. When scaffolding multiple files, emit ONE write-file tag per response — wait for each result before emitting the next. Never chain multiple write-file tags in a single response when file content is complex (more than 20 lines).
270942
-
270943
- ## SCAFFOLDING CHAINING WRITE-FILE CALLS
270944
-
270945
- When creating multiple files (e.g. scaffolding a project or creating 10 files), emit ALL of them
270946
- in a single response by chaining the tags back-to-back with no text between them:
270947
-
270948
- <write-file>
270949
- {"path": "test/file1.txt", "content": "File 1 content"}
270950
- </write-file>
270951
- <write-file>
270952
- {"path": "test/file2.txt", "content": "File 2 content"}
270953
- </write-file>
270954
- <write-file>
270955
- {"path": "test/file3.txt", "content": "File 3 content"}
270956
- </write-file>
270904
+ 1. ONE tool per response emit the XML tag, then stop. Never chain tools in one response except when scaffolding (see below).
270905
+ 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.
270906
+ 3. NEVER write the same file twice in one session. One write per file, period. If you already wrote it, it is done.
270907
+ 4. shell is ONLY for running code, installing packages, building, and testing. NEVER use shell to inspect the filesystem or read files — use read-file, read-folder, or grep instead.
270908
+ 5. write-file content must be the COMPLETE file content, never a placeholder or partial.
270909
+ 6. NEVER read a file you just wrote. The write output confirms success.
270910
+ 7. NEVER apologize and redo a tool call one attempt is enough, trust the output.
270911
+ 8. NEVER use shell to run git clone use the clone tag instead.
270912
+ 9. When the user asks you to CREATE a new file, write it immediately do NOT read first.
270913
+ 10. When the user asks you to MODIFY or FIX an existing file, read it first, then write the complete updated version ONCE.
270914
+ 11. When fixing multiple files, use read-files to read ALL of them first, then write each one ONCE sequentially — never rewrite a file already written this session.
270915
+ 12. If a read-folder or read-file returns not found, accept it and move on do NOT retry the same path.
270916
+ 13. Every shell command runs from the repo root cd has no persistent effect. Use full paths or combine with && e.g. cd myapp && bun run index.ts
270917
+ 14. write-file paths are relative to the repo root use full relative paths e.g. myapp/src/index.tsx not src/index.tsx
270918
+ 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.
270919
+ 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.
270920
+ 17. When scaffolding multiple files, emit ONE write-file tag per response and wait for the result before writing the next file.
270921
+
270922
+ ## ADDON FORMAT
270923
+
270924
+ All addons use defineTool from @ridit/lens-sdk. The ONLY correct format is:
270925
+
270926
+ \`\`\`js
270927
+ const { defineTool } = require("@ridit/lens-sdk");
270928
+ const { execSync } = require("child_process");
270929
+
270930
+ defineTool({
270931
+ name: "tool-name",
270932
+ description: "what it does",
270933
+ safe: false,
270934
+ permissionLabel: "label shown to user",
270935
+ systemPromptEntry: () => "<tool-name>{}</tool-name> — description",
270936
+ parseInput: (body) => JSON.parse(body.trim() || "{}"),
270937
+ summariseInput: (input) => "summary",
270938
+ execute: async (input, ctx) => {
270939
+ // ctx.repoPath is the current repo path
270940
+ // use execSync from child_process for shell commands, NOT ctx.tools.shell
270941
+ return { kind: "text", value: "result" };
270942
+ },
270943
+ });
270944
+ \`\`\`
270957
270945
 
270958
- The system processes each tag sequentially and automatically continues to the next one.
270959
- Do NOT wait for a user message between files — emit all tags at once.
270946
+ NEVER use module.exports, registerTool, ctx.tools.shell, or any other format. See addons/run-tests.js for a full working example.
270960
270947
 
270961
- ## WHEN TO READ BEFORE WRITING
270948
+ ## SCAFFOLDING
270962
270949
 
270963
- Only read a file before writing if ALL of these are true:
270964
- - The file already exists AND has content you need to preserve
270965
- - The user explicitly asked you to modify, edit, or update it (not create it)
270966
- - You do not already have the file content in this conversation
270950
+ When creating multiple files, emit ONE write-file per response and wait for each result:
270967
270951
 
270968
- Never read before writing when:
270969
- - The user asked you to create, write, or add a new file
270970
- - The file is empty, missing, or a stub
270971
- - You already read it earlier in this conversation
270952
+ <write-file>
270953
+ {"path": "myapp/package.json", "content": "..."}
270954
+ </write-file>
270972
270955
 
270973
- When modifying an existing file:
270974
- 1. Use read-file on the exact file first
270975
- 2. Preserve ALL existing content — do not remove anything that was not part of the request
270976
- 3. Your write-file must contain EVERYTHING the original had, PLUS your additions
270977
- 4. NEVER produce a file shorter than the original unless explicitly asked to delete things
270956
+ Wait for result, then emit the next file. Never chain write-file tags when content is complex.
270978
270957
 
270979
270958
  ## CODEBASE
270980
270959
 
@@ -270984,59 +270963,59 @@ ${memorySummary}`;
270984
270963
  }
270985
270964
  var BUILTIN_TOOLS_SECTION = `## TOOLS
270986
270965
 
270987
- You have exactly thirteen tools. To use a tool you MUST wrap it in the exact XML tags shown below — no other format will work.
270966
+ You have exactly fourteen tools. Use ONLY the XML tags shown below.
270988
270967
 
270989
270968
  ### 1. fetch — load a URL
270990
270969
  <fetch>https://example.com</fetch>
270991
270970
 
270992
- ### 2. shell — run a terminal command
270971
+ ### 2. shell — run a terminal command (NOT for filesystem inspection)
270993
270972
  <shell>node -v</shell>
270994
270973
 
270995
- ### 3. read-file — read a file from the repo
270974
+ ### 3. read-file — read a single file from the repo
270996
270975
  <read-file>src/foo.ts</read-file>
270997
270976
 
270998
- ### 4. read-folderlist contents of a folder (files + subfolders, one level deep)
270977
+ ### 4. read-filesread multiple files at once
270978
+ <read-files>
270979
+ ["src/foo.ts", "src/bar.ts"]
270980
+ </read-files>
270981
+
270982
+ ### 5. read-folder — list contents of a folder (one level deep)
270999
270983
  <read-folder>src/components</read-folder>
271000
270984
 
271001
- ### 5. grep — search for a pattern across files in the repo (cross-platform, no shell needed)
270985
+ ### 6. grep — search for a pattern across files
271002
270986
  <grep>
271003
270987
  {"pattern": "ChatRunner", "glob": "src/**/*.tsx"}
271004
270988
  </grep>
271005
270989
 
271006
- ### 6. write-file — create or overwrite a file
270990
+ ### 7. write-file — create or overwrite a file (COMPLETE content only)
271007
270991
  <write-file>
271008
270992
  {"path": "data/output.csv", "content": "col1,col2\\nval1,val2"}
271009
270993
  </write-file>
271010
270994
 
271011
- ### 7. delete-file — permanently delete a single file
270995
+ ### 8. delete-file — permanently delete a single file
271012
270996
  <delete-file>src/old-component.tsx</delete-file>
271013
270997
 
271014
- ### 8. delete-folder — permanently delete a folder and all its contents
270998
+ ### 9. delete-folder — permanently delete a folder and all its contents
271015
270999
  <delete-folder>src/legacy</delete-folder>
271016
271000
 
271017
- ### 9. open-url — open a URL in the user's default browser
271001
+ ### 10. open-url — open a URL in the user's default browser
271018
271002
  <open-url>https://github.com/owner/repo</open-url>
271019
271003
 
271020
- ### 10. generate-pdf — generate a PDF file from markdown-style content
271004
+ ### 11. generate-pdf — generate a PDF from markdown-style content
271021
271005
  <generate-pdf>
271022
- {"path": "output/report.pdf", "content": "# Title\\n\\nSome body text.\\n\\n## Section\\n\\nMore content."}
271006
+ {"path": "output/report.pdf", "content": "# Title\\n\\nBody text."}
271023
271007
  </generate-pdf>
271024
271008
 
271025
- ### 11. search — search the internet for anything you are unsure about
271026
- <search>how to use React useEffect cleanup function</search>
271009
+ ### 12. search — search the internet
271010
+ <search>how to use React useEffect cleanup</search>
271027
271011
 
271028
- ### 12. clone — clone a GitHub repo so you can explore and discuss it
271012
+ ### 13. clone — clone a GitHub repo
271029
271013
  <clone>https://github.com/owner/repo</clone>
271030
271014
 
271031
- ### 13. changes — propose code edits (shown as a diff for user approval)
271015
+ ### 14. changes — propose code edits shown as a diff for user approval
271032
271016
  <changes>
271033
271017
  {"summary": "what changed and why", "patches": [{"path": "src/foo.ts", "content": "COMPLETE file content", "isNew": false}]}
271034
271018
  </changes>
271035
-
271036
- ### 14. read-files — read multiple files from the repo at once
271037
- <read-files>
271038
- ["src/foo.ts", "src/bar.ts"]
271039
- </read-files>
271040
271019
  `;
271041
271020
  // src/prompts/fewshot.ts
271042
271021
  var FEW_SHOT_MESSAGES = [
@@ -271046,7 +271025,7 @@ var FEW_SHOT_MESSAGES = [
271046
271025
  },
271047
271026
  {
271048
271027
  role: "assistant",
271049
- content: '<write-file>\n{"path": "README.md", "content": "# Project\\n\\nA brief description of what this project does.\\n\\n## Getting Started\\n\\n```bash\\nbun install\\nbun run dev\\n```"}\n</write-file>'
271028
+ content: '<write-file>\n{"path": "README.md", "content": "# Project\\n\\nA brief description.\\n\\n## Getting Started\\n\\n```bash\\nbun install\\nbun run dev\\n```"}\n</write-file>'
271050
271029
  },
271051
271030
  {
271052
271031
  role: "user",
@@ -271062,259 +271041,184 @@ Please continue your response based on this output.`
271062
271041
  },
271063
271042
  {
271064
271043
  role: "user",
271065
- content: "add more information to the README"
271044
+ content: "fix the bug in addons/clean-cache.js"
271066
271045
  },
271067
271046
  {
271068
271047
  role: "assistant",
271069
- content: "<read-file>README.md</read-file>"
271048
+ content: "<read-file>addons/clean-cache.js</read-file>"
271070
271049
  },
271071
271050
  {
271072
271051
  role: "user",
271073
- content: `Here is the output from read-file of README.md:
271074
-
271075
- File: README.md (10 lines)
271052
+ content: `Here is the output from read-file of addons/clean-cache.js:
271076
271053
 
271077
- # Project
271054
+ File: addons/clean-cache.js (42 lines)
271078
271055
 
271079
- A brief description.
271080
-
271081
- ## Getting Started
271082
-
271083
- \`\`\`bash
271084
- bun install
271085
- \`\`\`
271056
+ const { defineTool } = require("@ridit/lens-sdk");
271057
+ defineTool({ name: "clean-cache", execute: async (_, ctx) => { const { shell } = ctx.tools; await shell("rm -rf node_modules"); } });
271086
271058
 
271087
271059
  Please continue your response based on this output.`
271088
271060
  },
271089
271061
  {
271090
271062
  role: "assistant",
271091
- content: '<write-file>\n{"path": "README.md", "content": "# Project\\n\\nA brief description.\\n\\n## Getting Started\\n\\n```bash\\nbun install\\nbun run dev\\n```\\n\\n## Features\\n\\n- Feature one\\n- Feature two\\n\\n## Contributing\\n\\nPull requests welcome."}\n</write-file>'
271063
+ content: `<write-file>
271064
+ {"path": "addons/clean-cache.js", "content": "const { defineTool } = require(\\"@ridit/lens-sdk\\");\\nconst { execSync } = require(\\"child_process\\");\\n\\ndefineTool({\\n name: \\"clean-cache\\",\\n description: \\"Clean node_modules and bun cache\\",\\n safe: false,\\n permissionLabel: \\"Clean cache\\",\\n systemPromptEntry: () => \\"<clean-cache>{}</clean-cache> — clean node_modules and bun cache\\",\\n parseInput: () => ({}),\\n summariseInput: () => \\"clean cache\\",\\n execute: async (_, ctx) => {\\n try {\\n execSync(\\"rm -rf node_modules\\", { cwd: ctx.repoPath, stdio: \\"pipe\\" });\\n return { kind: \\"text\\", value: \\"Cache cleaned!\\" };\\n } catch (err) {\\n return { kind: \\"error\\", value: err.message };\\n }\\n },\\n});"}
271065
+ </write-file>`
271092
271066
  },
271093
271067
  {
271094
271068
  role: "user",
271095
- content: `Here is the output from write-file to README.md:
271069
+ content: `Here is the output from write-file to addons/clean-cache.js:
271096
271070
 
271097
- Written: /repo/README.md (20 lines, 280 bytes)
271071
+ Written: /repo/addons/clean-cache.js (20 lines, 480 bytes)
271098
271072
 
271099
271073
  Please continue your response based on this output.`
271100
271074
  },
271101
271075
  {
271102
271076
  role: "assistant",
271103
- content: "Done — README.md updated with more detail."
271077
+ content: "Done — clean-cache.js fixed. Now uses execSync instead of ctx.tools.shell."
271104
271078
  },
271105
271079
  {
271106
271080
  role: "user",
271107
- content: "update LENS.md"
271081
+ content: "add a logout button to src/components/Header.tsx"
271108
271082
  },
271109
271083
  {
271110
271084
  role: "assistant",
271111
- content: "<read-file>LENS.md</read-file>"
271085
+ content: "<read-file>src/components/Header.tsx</read-file>"
271112
271086
  },
271113
271087
  {
271114
271088
  role: "user",
271115
- content: `Here is the output from read-file of LENS.md:
271116
-
271117
- File: LENS.md (33 lines)
271118
-
271119
- # Lens Analysis
271120
-
271121
- ## Overview
271122
- A CLI tool for codebase analysis.
271089
+ content: `Here is the output from read-file of src/components/Header.tsx:
271123
271090
 
271124
- ## Important Folders
271125
- - src/components
271126
- - src/utils
271091
+ File: src/components/Header.tsx (42 lines)
271127
271092
 
271128
- ## Suggestions
271129
- - Add tests
271093
+ import React from 'react';
271094
+ // ... existing content ...
271130
271095
 
271131
271096
  Please continue your response based on this output.`
271132
271097
  },
271133
271098
  {
271134
271099
  role: "assistant",
271135
- content: `<write-file>
271136
- {"path": "LENS.md", "content": "# Lens Analysis\\n\\n## Overview\\nA CLI tool for AI-powered codebase analysis, built with React and Ink.\\n\\n## Important Folders\\n- src/components — UI components rendered in the terminal\\n- src/utils — tools, chat, memory, and registry utilities\\n\\n## Suggestions\\n- Add tests\\n- Add more providers\\n- Improve error handling"}
271137
- </write-file>`
271100
+ content: `<changes>
271101
+ {"summary": "Add logout button to Header preserves all existing content", "patches": [{"path": "src/components/Header.tsx", "content": "// complete file with logout button added", "isNew": false}]}
271102
+ </changes>`
271138
271103
  },
271139
271104
  {
271140
271105
  role: "user",
271141
- content: `Here is the output from write-file to LENS.md:
271106
+ content: `Here is the output from changes:
271142
271107
 
271143
- Written: /repo/LENS.md (15 lines, 420 bytes)
271108
+ Changes applied.
271144
271109
 
271145
271110
  Please continue your response based on this output.`
271146
271111
  },
271147
271112
  {
271148
271113
  role: "assistant",
271149
- content: "Done — LENS.md updated."
271114
+ content: "Done — logout button added to Header.tsx."
271150
271115
  },
271151
271116
  {
271152
271117
  role: "user",
271153
- content: "write a contributing guide"
271118
+ content: "fix addons/a.js, addons/b.js and addons/c.js"
271154
271119
  },
271155
271120
  {
271156
271121
  role: "assistant",
271157
- content: `<write-file>
271158
- {"path": "CONTRIBUTING.md", "content": "# Contributing\\n\\nPull requests welcome. Please open an issue first to discuss major changes."}
271159
- </write-file>`
271122
+ content: `<read-files>
271123
+ ["addons/a.js", "addons/b.js", "addons/c.js"]
271124
+ </read-files>`
271160
271125
  },
271161
271126
  {
271162
271127
  role: "user",
271163
- content: `Here is the output from write-file to CONTRIBUTING.md:
271128
+ content: `Here is the output from read-files:
271164
271129
 
271165
- Written: /repo/CONTRIBUTING.md (4 lines, 96 bytes)
271130
+ === addons/a.js ===
271131
+ module.exports = { name: 'a', run: async () => {} }
271166
271132
 
271167
- Please continue your response based on this output.`
271168
- },
271169
- {
271170
- role: "assistant",
271171
- content: "Done — CONTRIBUTING.md has been written."
271172
- },
271173
- {
271174
- role: "user",
271175
- content: "scaffold a new project called myapp with package.json and src/index.tsx"
271176
- },
271177
- {
271178
- role: "assistant",
271179
- content: `<write-file>
271180
- {"path": "myapp/package.json", "content": "{\\n \\"name\\": \\"myapp\\",\\n \\"version\\": \\"1.0.0\\",\\n \\"scripts\\": { \\"dev\\": \\"bun run src/index.tsx\\" },\\n \\"dependencies\\": { \\"react\\": \\"^18.2.0\\", \\"ink\\": \\"^4.4.1\\" },\\n \\"devDependencies\\": { \\"@types/react\\": \\"^18.2.0\\" }\\n}"}
271181
- </write-file>`
271182
- },
271183
- {
271184
- role: "user",
271185
- content: `Here is the output from write-file to myapp/package.json:
271133
+ === addons/b.js ===
271134
+ module.exports = { name: 'b', run: async () => {} }
271186
271135
 
271187
- Written: /repo/myapp/package.json (10 lines, 220 bytes)
271136
+ === addons/c.js ===
271137
+ module.exports = { name: 'c', run: async () => {} }
271188
271138
 
271189
271139
  Please continue your response based on this output.`
271190
271140
  },
271191
271141
  {
271192
271142
  role: "assistant",
271193
271143
  content: `<write-file>
271194
- {"path": "myapp/src/index.tsx", "content": "/** @jsxImportSource react */\\nimport React from 'react';\\nimport { render, Text } from 'ink';\\n\\nfunction App() {\\n return <Text>Hello from myapp!</Text>;\\n}\\n\\nrender(<App />);"}
271144
+ {"path": "addons/a.js", "content": "const { defineTool } = require(\\"@ridit/lens-sdk\\");\\n\\ndefineTool({\\n name: \\"a\\",\\n description: \\"Does A\\",\\n safe: true,\\n permissionLabel: \\"Run A\\",\\n systemPromptEntry: () => \\"<a>{}</a> run A\\",\\n parseInput: () => ({}),\\n summariseInput: () => \\"a\\",\\n execute: async (_, ctx) => ({ kind: \\"text\\", value: \\"A done!\\" }),\\n});"}
271195
271145
  </write-file>`
271196
271146
  },
271197
271147
  {
271198
271148
  role: "user",
271199
- content: `Here is the output from write-file to myapp/src/index.tsx:
271200
-
271201
- Written: /repo/myapp/src/index.tsx (9 lines, 210 bytes)
271202
-
271203
- Please continue your response based on this output.`
271204
- },
271205
- {
271206
- role: "assistant",
271207
- content: "Done — scaffolded myapp/package.json and myapp/src/index.tsx. Run `cd myapp && bun install` to get started."
271208
- },
271209
- {
271210
- role: "user",
271211
- content: "delete src/old-component.tsx"
271212
- },
271213
- {
271214
- role: "assistant",
271215
- content: "<delete-file>src/old-component.tsx</delete-file>"
271216
- },
271217
- {
271218
- role: "user",
271219
- content: `Here is the output from delete-file of src/old-component.tsx:
271149
+ content: `Here is the output from write-file to addons/a.js:
271220
271150
 
271221
- Deleted: /repo/src/old-component.tsx
271151
+ Written: /repo/addons/a.js (12 lines, 280 bytes)
271222
271152
 
271223
271153
  Please continue your response based on this output.`
271224
271154
  },
271225
271155
  {
271226
271156
  role: "assistant",
271227
- content: "Done — src/old-component.tsx has been deleted."
271228
- },
271229
- {
271230
- role: "user",
271231
- content: "delete the legacy folder"
271232
- },
271233
- {
271234
- role: "assistant",
271235
- content: "<delete-folder>src/legacy</delete-folder>"
271157
+ content: `<write-file>
271158
+ {"path": "addons/b.js", "content": "const { defineTool } = require(\\"@ridit/lens-sdk\\");\\n\\ndefineTool({\\n name: \\"b\\",\\n description: \\"Does B\\",\\n safe: true,\\n permissionLabel: \\"Run B\\",\\n systemPromptEntry: () => \\"<b>{}</b> — run B\\",\\n parseInput: () => ({}),\\n summariseInput: () => \\"b\\",\\n execute: async (_, ctx) => ({ kind: \\"text\\", value: \\"B done!\\" }),\\n});"}
271159
+ </write-file>`
271236
271160
  },
271237
271161
  {
271238
271162
  role: "user",
271239
- content: `Here is the output from delete-folder of src/legacy:
271163
+ content: `Here is the output from write-file to addons/b.js:
271240
271164
 
271241
- Deleted folder: /repo/src/legacy
271165
+ Written: /repo/addons/b.js (12 lines, 280 bytes)
271242
271166
 
271243
271167
  Please continue your response based on this output.`
271244
271168
  },
271245
271169
  {
271246
271170
  role: "assistant",
271247
- content: "Done — src/legacy and all its contents have been deleted."
271248
- },
271249
- {
271250
- role: "user",
271251
- content: "open https://github.com/microsoft/typescript"
271252
- },
271253
- {
271254
- role: "assistant",
271255
- content: "<open-url>https://github.com/microsoft/typescript</open-url>"
271171
+ content: `<write-file>
271172
+ {"path": "addons/c.js", "content": "const { defineTool } = require(\\"@ridit/lens-sdk\\");\\n\\ndefineTool({\\n name: \\"c\\",\\n description: \\"Does C\\",\\n safe: true,\\n permissionLabel: \\"Run C\\",\\n systemPromptEntry: () => \\"<c>{}</c> — run C\\",\\n parseInput: () => ({}),\\n summariseInput: () => \\"c\\",\\n execute: async (_, ctx) => ({ kind: \\"text\\", value: \\"C done!\\" }),\\n});"}
271173
+ </write-file>`
271256
271174
  },
271257
271175
  {
271258
271176
  role: "user",
271259
- content: `Here is the output from open-url https://github.com/microsoft/typescript:
271177
+ content: `Here is the output from write-file to addons/c.js:
271260
271178
 
271261
- Opened: https://github.com/microsoft/typescript
271179
+ Written: /repo/addons/c.js (12 lines, 280 bytes)
271262
271180
 
271263
271181
  Please continue your response based on this output.`
271264
271182
  },
271265
271183
  {
271266
271184
  role: "assistant",
271267
- content: "Opened the TypeScript GitHub page in your browser."
271185
+ content: "Done fixed all three addons. Each now uses defineTool from @ridit/lens-sdk correctly."
271268
271186
  },
271269
271187
  {
271270
271188
  role: "user",
271271
- content: "generate a PDF report about the project and save it to docs/report.pdf"
271189
+ content: "scaffold a new project called myapp with package.json and src/index.tsx"
271272
271190
  },
271273
271191
  {
271274
271192
  role: "assistant",
271275
- content: `<generate-pdf>
271276
- {"path": "docs/report.pdf", "content": "# Project Report\\n\\n## Overview\\n\\nThis document summarizes the project.\\n\\n## Details\\n\\nMore content here."}
271277
- </generate-pdf>`
271193
+ content: `<write-file>
271194
+ {"path": "myapp/package.json", "content": "{\\n \\"name\\": \\"myapp\\",\\n \\"version\\": \\"1.0.0\\",\\n \\"scripts\\": { \\"dev\\": \\"bun run src/index.tsx\\" },\\n \\"dependencies\\": { \\"react\\": \\"^18.2.0\\", \\"ink\\": \\"^4.4.1\\" }\\n}"}
271195
+ </write-file>`
271278
271196
  },
271279
271197
  {
271280
271198
  role: "user",
271281
- content: `Here is the output from generate-pdf to docs/report.pdf:
271199
+ content: `Here is the output from write-file to myapp/package.json:
271282
271200
 
271283
- PDF generated: /repo/docs/report.pdf
271201
+ Written: /repo/myapp/package.json (8 lines, 180 bytes)
271284
271202
 
271285
271203
  Please continue your response based on this output.`
271286
271204
  },
271287
271205
  {
271288
271206
  role: "assistant",
271289
- content: "Done — docs/report.pdf has been generated."
271290
- },
271291
- {
271292
- role: "user",
271293
- content: 'grep -R "ChatRunner" -n src'
271294
- },
271295
- {
271296
- role: "assistant",
271297
- content: `<grep>
271298
- {"pattern": "ChatRunner", "glob": "src/**/*"}
271299
- </grep>`
271207
+ content: `<write-file>
271208
+ {"path": "myapp/src/index.tsx", "content": "/** @jsxImportSource react */\\nimport React from 'react';\\nimport { render, Text } from 'ink';\\n\\nfunction App() {\\n return <Text>Hello from myapp!</Text>;\\n}\\n\\nrender(<App />);"}
271209
+ </write-file>`
271300
271210
  },
271301
271211
  {
271302
271212
  role: "user",
271303
- content: `Here is the output from grep for "ChatRunner":
271304
-
271305
- grep /ChatRunner/ src/**/* — 3 match(es) in 2 file(s)
271306
-
271307
- src/index.tsx
271308
- 12: import { ChatRunner } from "./components/chat/ChatRunner";
271213
+ content: `Here is the output from write-file to myapp/src/index.tsx:
271309
271214
 
271310
- src/components/chat/ChatRunner.tsx
271311
- 1: export const ChatRunner = ...
271215
+ Written: /repo/myapp/src/index.tsx (9 lines, 210 bytes)
271312
271216
 
271313
271217
  Please continue your response based on this output.`
271314
271218
  },
271315
271219
  {
271316
271220
  role: "assistant",
271317
- content: "ChatRunner is defined in src/components/chat/ChatRunner.tsx and imported in src/index.tsx."
271221
+ content: "Done scaffolded myapp/package.json and myapp/src/index.tsx. Run cd myapp && bun install to get started."
271318
271222
  },
271319
271223
  {
271320
271224
  role: "user",
@@ -271342,197 +271246,6 @@ Please continue your response based on this output.`
271342
271246
  role: "assistant",
271343
271247
  content: "useInput is used in src/components/chat/ChatRunner.tsx — imported on line 5 and called on line 210."
271344
271248
  },
271345
- {
271346
- role: "user",
271347
- content: "show me how to use the read-file tool"
271348
- },
271349
- {
271350
- role: "assistant",
271351
- content: "To read a file, emit the tag alone in your response — nothing else on that turn:\n\n```text\n[read-file]src/components/Header.tsx[/read-file]\n```\n\nThe result comes back as the next user message and you can then analyze it."
271352
- },
271353
- {
271354
- role: "user",
271355
- content: "show me an example of the shell tool"
271356
- },
271357
- {
271358
- role: "assistant",
271359
- content: "To run a shell command, emit only the tag:\n\n```text\n[shell]node -v[/shell]\n```\n\nThe stdout/stderr is returned and you can read it in the next turn."
271360
- },
271361
- {
271362
- role: "user",
271363
- content: "read src folder"
271364
- },
271365
- {
271366
- role: "assistant",
271367
- content: "<read-folder>src</read-folder>"
271368
- },
271369
- {
271370
- role: "user",
271371
- content: `Here is the output from read-folder of src:
271372
-
271373
- Folder: src (4 entries)
271374
-
271375
- Files:
271376
- index.ts
271377
- App.tsx
271378
-
271379
- Subfolders:
271380
- components/
271381
- utils/
271382
-
271383
- Please continue your response based on this output.`
271384
- },
271385
- {
271386
- role: "assistant",
271387
- content: "The src folder contains index.ts, App.tsx, plus subfolders components/ and utils/."
271388
- },
271389
- {
271390
- role: "user",
271391
- content: "what files are in src/components?"
271392
- },
271393
- {
271394
- role: "assistant",
271395
- content: "<read-folder>src/components</read-folder>"
271396
- },
271397
- {
271398
- role: "user",
271399
- content: `Here is the output from read-folder of src/components:
271400
-
271401
- Folder: src/components (5 entries)
271402
-
271403
- Files:
271404
- Header.tsx
271405
- Footer.tsx
271406
- Button.tsx
271407
-
271408
- Subfolders:
271409
- ui/
271410
- forms/
271411
-
271412
- Please continue your response based on this output.`
271413
- },
271414
- {
271415
- role: "assistant",
271416
- content: "src/components has 3 files — Header.tsx, Footer.tsx, Button.tsx — plus two subfolders: ui/ and forms/."
271417
- },
271418
- {
271419
- role: "user",
271420
- content: "show me the project structure"
271421
- },
271422
- {
271423
- role: "assistant",
271424
- content: "<read-folder>.</read-folder>"
271425
- },
271426
- {
271427
- role: "user",
271428
- content: `Here is the output from read-folder of .:
271429
-
271430
- Folder: . (5 entries)
271431
-
271432
- Files:
271433
- package.json
271434
- tsconfig.json
271435
- README.md
271436
-
271437
- Subfolders:
271438
- src/
271439
- node_modules/
271440
-
271441
- Please continue your response based on this output.`
271442
- },
271443
- {
271444
- role: "assistant",
271445
- content: "The project root has package.json, tsconfig.json, README.md and the src/ folder for source code."
271446
- },
271447
- {
271448
- role: "user",
271449
- content: "fetch https://api.github.com/repos/microsoft/typescript"
271450
- },
271451
- {
271452
- role: "assistant",
271453
- content: "<fetch>https://api.github.com/repos/microsoft/typescript</fetch>"
271454
- },
271455
- {
271456
- role: "user",
271457
- content: `Here is the output from fetch of https://api.github.com/repos/microsoft/typescript:
271458
-
271459
- {"name":"TypeScript","stargazers_count":100000}
271460
-
271461
- Please continue your response based on this output.`
271462
- },
271463
- {
271464
- role: "assistant",
271465
- content: "Found 1 object with fields: name, stargazers_count. Writing to ts-info.json now."
271466
- },
271467
- {
271468
- role: "user",
271469
- content: "ok go ahead"
271470
- },
271471
- {
271472
- role: "assistant",
271473
- content: `<write-file>
271474
- {"path": "ts-info.json", "content": "{"name":"TypeScript","stars":100000}"}
271475
- </write-file>`
271476
- },
271477
- {
271478
- role: "user",
271479
- content: `Here is the output from write-file to ts-info.json:
271480
-
271481
- Written: /repo/ts-info.json (1 lines, 44 bytes)
271482
-
271483
- Please continue your response based on this output.`
271484
- },
271485
- {
271486
- role: "assistant",
271487
- content: "Done — ts-info.json has been saved."
271488
- },
271489
- {
271490
- role: "user",
271491
- content: "write it to a file called hello.py"
271492
- },
271493
- {
271494
- role: "assistant",
271495
- content: `<write-file>
271496
- {"path": "hello.py", "content": "# hello.py\\nprint('hello')"}
271497
- </write-file>`
271498
- },
271499
- {
271500
- role: "user",
271501
- content: `Here is the output from write-file to hello.py:
271502
-
271503
- Written: /repo/hello.py (2 lines, 32 bytes)
271504
-
271505
- Please continue your response based on this output.`
271506
- },
271507
- {
271508
- role: "assistant",
271509
- content: "Done — hello.py has been written."
271510
- },
271511
- {
271512
- role: "user",
271513
- content: "add a logout button to src/components/Header.tsx"
271514
- },
271515
- {
271516
- role: "assistant",
271517
- content: "<read-file>src/components/Header.tsx</read-file>"
271518
- },
271519
- {
271520
- role: "user",
271521
- content: `Here is the output from read-file of src/components/Header.tsx:
271522
-
271523
- File: src/components/Header.tsx (42 lines)
271524
-
271525
- import React from 'react';
271526
- // ... full file content ...
271527
-
271528
- Please continue your response based on this output.`
271529
- },
271530
- {
271531
- role: "assistant",
271532
- content: `<changes>
271533
- {"summary": "Add logout button to Header — preserves all existing nav items and imports", "patches": [{"path": "src/components/Header.tsx", "content": "// complete file with logout button added", "isNew": false}]}
271534
- </changes>`
271535
- },
271536
271249
  {
271537
271250
  role: "user",
271538
271251
  content: "what node version am I on"
@@ -271551,63 +271264,39 @@ Please continue your response based on this output.`
271551
271264
  },
271552
271265
  {
271553
271266
  role: "assistant",
271554
- content: "You're running Node.js v20.11.0."
271267
+ content: "You're on Node.js v20.11.0."
271555
271268
  },
271556
271269
  {
271557
271270
  role: "user",
271558
- content: "clone https://github.com/facebook/react"
271559
- },
271560
- {
271561
- role: "assistant",
271562
- content: "<clone>https://github.com/facebook/react</clone>"
271563
- },
271564
- {
271565
- role: "user",
271566
- content: "Cloned react to /tmp/react — 2847 files available. You can now read files from this repo using read-file with paths relative to /tmp/react."
271271
+ content: "remember that we always use bun in this project"
271567
271272
  },
271568
271273
  {
271569
271274
  role: "assistant",
271570
- content: "Cloned! The React repo has 2847 files. I can read source files, explain how it works, or suggest improvements — just ask."
271275
+ content: `<memory-add>Project uses bun as the package manager and runtime, not npm or node</memory-add>
271276
+
271277
+ Got it — I'll always use bun for this project.`
271571
271278
  },
271572
271279
  {
271573
271280
  role: "user",
271574
- content: "what does the ?? operator do in typescript"
271281
+ content: "add a new addon that prints hello world"
271575
271282
  },
271576
271283
  {
271577
271284
  role: "assistant",
271578
- content: "<search>nullish coalescing operator ?? TypeScript</search>"
271285
+ content: `<write-file>
271286
+ {"path": "addons/hello-world.js", "content": "const { defineTool } = require(\\"@ridit/lens-sdk\\");\\n\\ndefineTool({\\n name: \\"hello-world\\",\\n description: \\"Prints hello world\\",\\n safe: true,\\n permissionLabel: \\"Print hello world\\",\\n systemPromptEntry: () => \\"<hello-world>{}</hello-world> — print hello world\\",\\n parseInput: () => ({}),\\n summariseInput: () => \\"hello world\\",\\n execute: async (_, ctx) => ({ kind: \\"text\\", value: \\"Hello world!\\" }),\\n});"}
271287
+ </write-file>`
271579
271288
  },
271580
271289
  {
271581
271290
  role: "user",
271582
- content: `Here is the output from web search for "nullish coalescing operator ?? TypeScript":
271291
+ content: `Here is the output from write-file to addons/hello-world.js:
271583
271292
 
271584
- Answer: The ?? operator returns the right-hand side when the left-hand side is null or undefined.
271293
+ Written: /repo/addons/hello-world.js (14 lines, 320 bytes)
271585
271294
 
271586
271295
  Please continue your response based on this output.`
271587
271296
  },
271588
271297
  {
271589
271298
  role: "assistant",
271590
- content: "The ?? operator is the nullish coalescing operator. It returns the right side only when the left side is null or undefined."
271591
- },
271592
- {
271593
- role: "user",
271594
- content: "remember that we always use bun in this project"
271595
- },
271596
- {
271597
- role: "assistant",
271598
- content: `<memory-add>Project uses bun as the package manager and runtime, not npm or node</memory-add>
271599
-
271600
- Got it — I'll always use bun for this project.`
271601
- },
271602
- {
271603
- role: "user",
271604
- content: "forget the bun preference"
271605
- },
271606
- {
271607
- role: "assistant",
271608
- content: `<memory-delete>MEMORY_ID</memory-delete>
271609
-
271610
- Done — removed that memory.`
271299
+ content: "Done addons/hello-world.js created using defineTool from @ridit/lens-sdk."
271611
271300
  }
271612
271301
  ];
271613
271302
  // src/utils/chat.ts
@@ -276213,12 +275902,10 @@ ${missing.map((f) => ` ${f}`).join(`
276213
275902
  }, undefined, false, undefined, this),
276214
275903
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276215
275904
  color: "gray",
276216
- dimColor: true,
276217
275905
  children: cwd2
276218
275906
  }, undefined, false, undefined, this),
276219
275907
  files.length > 0 && /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276220
275908
  color: CYAN,
276221
- dimColor: true,
276222
275909
  children: [
276223
275910
  files.length,
276224
275911
  " file",
@@ -276235,7 +275922,6 @@ ${missing.map((f) => ` ${f}`).join(`
276235
275922
  children: [
276236
275923
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276237
275924
  color: "gray",
276238
- dimColor: true,
276239
275925
  children: " ·"
276240
275926
  }, undefined, false, undefined, this),
276241
275927
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
@@ -276247,7 +275933,6 @@ ${missing.map((f) => ` ${f}`).join(`
276247
275933
  }, undefined, false, undefined, this),
276248
275934
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276249
275935
  color: "gray",
276250
- dimColor: true,
276251
275936
  children: div
276252
275937
  }, undefined, false, undefined, this),
276253
275938
  phase.type === "checking" && /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
@@ -276260,7 +275945,6 @@ ${missing.map((f) => ` ${f}`).join(`
276260
275945
  }, undefined, false, undefined, this),
276261
275946
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276262
275947
  color: "gray",
276263
- dimColor: true,
276264
275948
  children: "checking changes…"
276265
275949
  }, undefined, false, undefined, this)
276266
275950
  ]
@@ -276275,7 +275959,6 @@ ${missing.map((f) => ` ${f}`).join(`
276275
275959
  }, undefined, false, undefined, this),
276276
275960
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276277
275961
  color: "gray",
276278
- dimColor: true,
276279
275962
  children: phase.files.length > 0 ? `staging ${phase.files.length} file${phase.files.length !== 1 ? "s" : ""}…` : "staging all changes…"
276280
275963
  }, undefined, false, undefined, this)
276281
275964
  ]
@@ -276323,12 +276006,10 @@ ${missing.map((f) => ` ${f}`).join(`
276323
276006
  children: [
276324
276007
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276325
276008
  color: "gray",
276326
- dimColor: true,
276327
276009
  children: "you have unstaged changes. try:"
276328
276010
  }, undefined, false, undefined, this),
276329
276011
  phase.files.length > 0 ? /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276330
276012
  color: "gray",
276331
- dimColor: true,
276332
276013
  children: [
276333
276014
  " ",
276334
276015
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
@@ -276343,7 +276024,6 @@ ${missing.map((f) => ` ${f}`).join(`
276343
276024
  ]
276344
276025
  }, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276345
276026
  color: "gray",
276346
- dimColor: true,
276347
276027
  children: [
276348
276028
  " ",
276349
276029
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
@@ -276409,7 +276089,6 @@ ${missing.map((f) => ` ${f}`).join(`
276409
276089
  children: [
276410
276090
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276411
276091
  color: "yellow",
276412
- dimColor: true,
276413
276092
  children: [
276414
276093
  "⚡ large diff — consider splitting into",
276415
276094
  " ",
@@ -276419,7 +276098,6 @@ ${missing.map((f) => ` ${f}`).join(`
276419
276098
  }, undefined, true, undefined, this),
276420
276099
  phase.splitGroups.map((g, i) => /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276421
276100
  color: "gray",
276422
- dimColor: true,
276423
276101
  children: [
276424
276102
  " · ",
276425
276103
  g
@@ -276429,7 +276107,6 @@ ${missing.map((f) => ` ${f}`).join(`
276429
276107
  }, undefined, true, undefined, this),
276430
276108
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276431
276109
  color: "gray",
276432
- dimColor: true,
276433
276110
  children: div
276434
276111
  }, undefined, false, undefined, this),
276435
276112
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
@@ -276446,7 +276123,6 @@ ${missing.map((f) => ` ${f}`).join(`
276446
276123
  }, undefined, false, undefined, this),
276447
276124
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276448
276125
  color: "gray",
276449
- dimColor: true,
276450
276126
  children: "n/esc cancel"
276451
276127
  }, undefined, false, undefined, this)
276452
276128
  ]
@@ -276481,7 +276157,6 @@ ${missing.map((f) => ` ${f}`).join(`
276481
276157
  }, undefined, false, undefined, this),
276482
276158
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276483
276159
  color: "gray",
276484
- dimColor: true,
276485
276160
  children: "enter confirm · esc back"
276486
276161
  }, undefined, false, undefined, this)
276487
276162
  ]
@@ -276498,7 +276173,6 @@ ${missing.map((f) => ` ${f}`).join(`
276498
276173
  }, undefined, false, undefined, this),
276499
276174
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276500
276175
  color: "gray",
276501
- dimColor: true,
276502
276176
  children: "committing…"
276503
276177
  }, undefined, false, undefined, this)
276504
276178
  ]
@@ -276536,7 +276210,6 @@ ${missing.map((f) => ` ${f}`).join(`
276536
276210
  }, undefined, false, undefined, this),
276537
276211
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276538
276212
  color: "gray",
276539
- dimColor: true,
276540
276213
  children: "pushing…"
276541
276214
  }, undefined, false, undefined, this)
276542
276215
  ]
@@ -276570,7 +276243,6 @@ ${missing.map((f) => ` ${f}`).join(`
276570
276243
  phase.message.split(`
276571
276244
  `).slice(2).filter(Boolean).map((line, i) => /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276572
276245
  color: "gray",
276573
- dimColor: true,
276574
276246
  children: line
276575
276247
  }, i, false, undefined, this)),
276576
276248
  phase.pushed && /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Box_default, {
@@ -276583,14 +276255,12 @@ ${missing.map((f) => ` ${f}`).join(`
276583
276255
  }, undefined, false, undefined, this),
276584
276256
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276585
276257
  color: "gray",
276586
- dimColor: true,
276587
276258
  children: "pushed to remote"
276588
276259
  }, undefined, false, undefined, this)
276589
276260
  ]
276590
276261
  }, undefined, true, undefined, this),
276591
276262
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276592
276263
  color: "gray",
276593
- dimColor: true,
276594
276264
  children: "press any key to exit"
276595
276265
  }, undefined, false, undefined, this)
276596
276266
  ]
@@ -276618,7 +276288,6 @@ ${missing.map((f) => ` ${f}`).join(`
276618
276288
  }, undefined, false, undefined, this),
276619
276289
  /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276620
276290
  color: "gray",
276621
- dimColor: true,
276622
276291
  children: "(preview only — not committed)"
276623
276292
  }, undefined, false, undefined, this)
276624
276293
  ]
@@ -276645,7 +276314,6 @@ ${missing.map((f) => ` ${f}`).join(`
276645
276314
  phase.message.split(`
276646
276315
  `).slice(1).map((line, i) => /* @__PURE__ */ jsx_dev_runtime25.jsxDEV(Text, {
276647
276316
  color: "gray",
276648
- dimColor: true,
276649
276317
  children: line
276650
276318
  }, i, false, undefined, this))
276651
276319
  ]
@@ -277257,6 +276925,7 @@ var convertImageTool = {
277257
276925
  }
277258
276926
  };
277259
276927
  // src/utils/tools/builtins.ts
276928
+ var cleanBody = (body) => body.trim().replace(/\\/g, "/");
277260
276929
  var fetchTool = {
277261
276930
  name: "fetch",
277262
276931
  description: "load a URL",
@@ -277299,7 +276968,7 @@ var readFileTool = {
277299
276968
  permissionLabel: "read",
277300
276969
  systemPromptEntry: (i) => `### ${i}. read-file — read a file from the repo
277301
276970
  <read-file>src/foo.ts</read-file>`,
277302
- parseInput: (body) => body || null,
276971
+ parseInput: (body) => cleanBody(body) || null,
277303
276972
  summariseInput: (p) => p,
277304
276973
  execute: (filePath, ctx) => ({
277305
276974
  kind: "text",
@@ -277313,7 +276982,7 @@ var readFolderTool = {
277313
276982
  permissionLabel: "folder",
277314
276983
  systemPromptEntry: (i) => `### ${i}. read-folder — list contents of a folder (files + subfolders, one level deep)
277315
276984
  <read-folder>src/components</read-folder>`,
277316
- parseInput: (body) => body || null,
276985
+ parseInput: (body) => cleanBody(body) || null,
277317
276986
  summariseInput: (p) => p,
277318
276987
  execute: (folderPath, ctx) => ({
277319
276988
  kind: "text",
@@ -277331,7 +277000,7 @@ var grepTool = {
277331
277000
  </grep>`,
277332
277001
  parseInput: (body) => {
277333
277002
  try {
277334
- const parsed = JSON.parse(body);
277003
+ const parsed = JSON.parse(cleanBody(body));
277335
277004
  return { pattern: parsed.pattern, glob: parsed.glob ?? "**/*" };
277336
277005
  } catch {
277337
277006
  return { pattern: body, glob: "**/*" };
@@ -277357,7 +277026,7 @@ var writeFileTool = {
277357
277026
  const parsed = JSON.parse(body);
277358
277027
  if (!parsed.path)
277359
277028
  return null;
277360
- return parsed;
277029
+ return { ...parsed, path: parsed.path.replace(/\\/g, "/") };
277361
277030
  } catch {
277362
277031
  return null;
277363
277032
  }
@@ -277375,7 +277044,7 @@ var deleteFileTool = {
277375
277044
  permissionLabel: "delete",
277376
277045
  systemPromptEntry: (i) => `### ${i}. delete-file — permanently delete a single file
277377
277046
  <delete-file>src/old-component.tsx</delete-file>`,
277378
- parseInput: (body) => body || null,
277047
+ parseInput: (body) => cleanBody(body) || null,
277379
277048
  summariseInput: (p) => p,
277380
277049
  execute: (filePath, ctx) => ({
277381
277050
  kind: "text",
@@ -277389,7 +277058,7 @@ var deleteFolderTool = {
277389
277058
  permissionLabel: "delete folder",
277390
277059
  systemPromptEntry: (i) => `### ${i}. delete-folder — permanently delete a folder and all its contents
277391
277060
  <delete-folder>src/legacy</delete-folder>`,
277392
- parseInput: (body) => body || null,
277061
+ parseInput: (body) => cleanBody(body) || null,
277393
277062
  summariseInput: (p) => p,
277394
277063
  execute: (folderPath, ctx) => ({
277395
277064
  kind: "text",
@@ -277418,7 +277087,7 @@ var generatePdfTool = {
277418
277087
  </generate-pdf>`,
277419
277088
  parseInput: (body) => {
277420
277089
  try {
277421
- const parsed = JSON.parse(body);
277090
+ const parsed = JSON.parse(cleanBody(body));
277422
277091
  return {
277423
277092
  filePath: parsed.path ?? parsed.filePath ?? "output.pdf",
277424
277093
  content: parsed.content ?? ""
@@ -277479,7 +277148,7 @@ var changesTool = {
277479
277148
  </changes>`,
277480
277149
  parseInput: (body) => {
277481
277150
  try {
277482
- return JSON.parse(body);
277151
+ return JSON.parse(cleanBody(body));
277483
277152
  } catch {
277484
277153
  return null;
277485
277154
  }
@@ -277501,7 +277170,7 @@ var readFilesTool = {
277501
277170
  </read-files>`,
277502
277171
  parseInput: (body) => {
277503
277172
  try {
277504
- const parsed = JSON.parse(body);
277173
+ const parsed = JSON.parse(cleanBody(body));
277505
277174
  if (!Array.isArray(parsed) || parsed.length === 0)
277506
277175
  return null;
277507
277176
  return { paths: parsed };
@@ -277543,6 +277212,7 @@ function registerBuiltins() {
277543
277212
  import path26 from "path";
277544
277213
  import os9 from "os";
277545
277214
  import { existsSync as existsSync20, readdirSync as readdirSync5 } from "fs";
277215
+ import { pathToFileURL } from "url";
277546
277216
  var ADDONS_DIR = path26.join(os9.homedir(), ".lens", "addons");
277547
277217
  async function loadAddons() {
277548
277218
  if (!existsSync20(ADDONS_DIR)) {
@@ -277554,9 +277224,10 @@ async function loadAddons() {
277554
277224
  if (!file)
277555
277225
  return;
277556
277226
  const fullPath = path26.join(ADDONS_DIR, file);
277227
+ const fileUrl = pathToFileURL(fullPath).href;
277557
277228
  const isLast = i === files.length - 1;
277558
277229
  try {
277559
- await import(fullPath);
277230
+ await import(fileUrl);
277560
277231
  console.log(`[addons] loaded: ${file}${isLast ? `
277561
277232
  ` : ""}`);
277562
277233
  } catch (err) {