@cerebriline/core 4.100.274 → 4.100.276
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/assets/prompt-templates/claude.md +7 -7
- package/assets/prompt-templates/deepseek.md +8 -8
- package/assets/prompt-templates/default.md +13 -13
- package/assets/prompt-templates/gemma.md +5 -5
- package/assets/prompt-templates/glm.md +9 -9
- package/assets/prompt-templates/kimi-k3.md +8 -8
- package/assets/prompt-templates/kimi.md +10 -10
- package/assets/prompt-templates/minimax-m3.1-flash.md +9 -8
- package/assets/prompt-templates/minimax.md +12 -10
- package/assets/prompt-templates/nemotron.md +9 -9
- package/assets/prompt-templates/qwen.md +9 -9
- package/dist/cloud/index.js +1 -1
- package/dist/document-reader-child.js +20 -20
- package/dist/extensions/config/prompt-template-review.d.ts +1 -1
- package/dist/extensions/tools/ask-lsp.d.ts +1 -1
- package/dist/extensions/tools/browser.d.ts +1 -1
- package/dist/extensions/tools/check-file.d.ts +18 -3
- package/dist/extensions/tools/command-guard.d.ts +4 -3
- package/dist/extensions/tools/delimiter-balance.d.ts +50 -0
- package/dist/extensions/tools/edit-verification.d.ts +13 -4
- package/dist/extensions/tools/error-locations.d.ts +1 -1
- package/dist/extensions/tools/executors/awk-parser.d.ts +5 -0
- package/dist/extensions/tools/executors/awk.d.ts +14 -2
- package/dist/extensions/tools/executors/bash.d.ts +2 -0
- package/dist/extensions/tools/executors/document/formats.d.ts +4 -0
- package/dist/extensions/tools/executors/document/images.d.ts +6 -1
- package/dist/extensions/tools/executors/document/legacy.d.ts +9 -0
- package/dist/extensions/tools/executors/file-read.d.ts +15 -0
- package/dist/extensions/tools/executors/read-receipts.d.ts +10 -0
- package/dist/extensions/tools/executors/search.d.ts +2 -2
- package/dist/extensions/tools/executors/sed.d.ts +40 -0
- package/dist/extensions/tools/executors/unchanged-reads.d.ts +6 -0
- package/dist/extensions/tools/executors/web-fetch.d.ts +12 -0
- package/dist/extensions/tools/executors/whole-file.d.ts +7 -2
- package/dist/extensions/tools/helpers.d.ts +15 -1
- package/dist/extensions/tools/jev.d.ts +1 -1
- package/dist/extensions/tools/list-files.d.ts +17 -1
- package/dist/extensions/tools/media-endpoint.d.ts +16 -0
- package/dist/extensions/tools/model-tool-routing.d.ts +6 -0
- package/dist/extensions/tools/task-progress.d.ts +2 -0
- package/dist/extensions/tools/team/agent-check.d.ts +15 -2
- package/dist/extensions/tools/team/agent-controls.d.ts +1 -1
- package/dist/extensions/tools/team/batch-report.d.ts +8 -0
- package/dist/extensions/tools/team/lead-agent-tools.d.ts +2 -2
- package/dist/hub/daemon/entry.js +718 -635
- package/dist/hub/index.js +703 -620
- package/dist/index.d.ts +1 -1
- package/dist/index.js +924 -838
- package/dist/remote/remote-helper-entry.js +1 -1
- package/dist/remote/remote-helper.js +1 -1
- package/dist/runtime/atomic/check-progress.d.ts +13 -0
- package/dist/runtime/atomic/file-revisions.d.ts +15 -1
- package/dist/runtime/atomic/oracle.d.ts +14 -0
- package/dist/runtime/atomic/page-check.d.ts +12 -2
- package/dist/runtime/atomic/plan-tool.d.ts +14 -2
- package/dist/runtime/atomic/protocol.d.ts +2 -0
- package/dist/runtime/atomic/restore-file-tool.d.ts +3 -3
- package/dist/runtime/atomic/snapshot.d.ts +15 -0
- package/dist/runtime/atomic/stalled-checks.d.ts +12 -4
- package/dist/runtime/atomic/transaction-controller.d.ts +10 -0
- package/dist/runtime/atomic/unparseable-change.d.ts +3 -1
- package/dist/runtime/safety/loop-detection.d.ts +15 -1
- package/dist/services/retrieval/memory.d.ts +9 -0
- package/dist/services/sdd/sdd-engine.d.ts +14 -1
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type PromptTemplate } from "@cerebriline/shared";
|
|
2
2
|
import { type CompactionPromptSources } from "./prompt-template-compaction";
|
|
3
3
|
export declare const DEFAULT_REQUIRED_REWRITES: readonly ["read_files", "search_codebase", "editor", "apply_patch", "run_commands", "fetch_web_content", "check_file", "ask_lsp", "grep", "sed", "awk"];
|
|
4
|
-
export declare const PROMPT_TEMPLATE_REVIEW_INSTRUCTIONS = "You are being shown the prompt Cline gives you when it uses you as a coding agent: a system prompt and a set of tool descriptions. You are the intended reader of this text. Rewrite it into the form you would rather receive.\n\nThis is not a copy-editing task. The prompt below was written by someone reasoning about how you read, and they may have been wrong. Where a section is phrased in a way you would skim, reorder or restate it. Where a rule matters and is buried, put it where you would be when you are about to break it. Where something is repeated to no effect, cut it.\n\nFour failures are observed in practice with models in your family, and the rewrite is judged on whether it prevents them:\n\n1. Reaching for shell commands to do file work \u2014 'cat' to read, 'sed -i' or 'echo >' to write, 'grep' to search \u2014 when dedicated tools exist and are always available.\n2. Serialising independent work across turns: one read, wait, one read, wait, when all of them were known at the start.\n3. Announcing an intention instead of acting on it, or claiming a task is finished without reading back what was written.\n4. Answering a question about a symbol with a text search. Asking where something is defined, what uses it, what implements it, or what a name means, and then grepping for it and reading several files to work out which hit was the real one \u2014 when the IDE's language servers already know the answer exactly and will give it in one call. The same failure in its other form: running a compiler or a linter through the shell to find out whether one file is valid, and waiting for a whole-project build to answer a one-file question.\n\nOne thing you must get right, and which prompts written for this get wrong in both directions:\n\nA coding agent is multi-turn, and the end of a turn is never in itself the end of the work. What is final is the completion of the assigned work \u2014 the task, the work package, the milestone, the request. An end of turn may be a milestone reached, a point where you need direction, guidance or a clarification from the user, or simply an intermediate step between two things the user asked for. So:\n\n- Do not treat \"I have stopped emitting tool calls\" as \"the work is done\". It is not a signal about the work at all.\n- Do not write a rule that makes stopping feel like failure, such as \"a response without a tool call is considered complete\". A rule like that buys one more unnecessary tool call on every finished task, and it teaches the wrong thing: that continuing is always correct.\n- Keep your attention on the long horizon of the assigned work rather than on the current turn. Ending a turn to ask a question is correct when you need the answer. Ending it while work you were asked to do remains untouched, and saying nothing about that, is not.\n\nFour more things are settled by measurement rather than by opinion, and a rewrite is judged on whether it keeps them:\n\n- The checker and the run belong in the same turn. Call 'check_file' and the thing that executes the code - 'run_commands', or 'browser' for a page - together, not one or the other. Running it says *that* something is broken and where the parser gave up; the checker says *which line* to edit. Each is half the answer, and the half you skip is the half the turn gets spent guessing at.\n- A tool's report outranks your own reasoning about the same question. Where a tool has measured something - a delimiter scan naming the line to edit, a diagnostic naming a type - that is the measurement, and re-deriving it yourself is an estimate. Where the two disagree, it is the estimate that is wrong. Measured twice: a model called a delimiter scan a false positive, counted brackets by hand instead, and was wrong both times, at over 30,000 thinking tokens a turn. If you doubt a report, do not re-derive it - act on it and run the result. That costs milliseconds and settles it either way.\n- Make the planned changes one at a time, and confirm each one before starting the next. The cheap check that does not execute the code goes after every edit; the thing that runs the code is what settles whether the change was right. Six edits made together and checked once leave six things to undo and no way to tell which one was wrong - measured across ten runs, the template that said otherwise drew 13.6 'restore_file' calls per run against 0.23 for the family that did not.\n- Do not re-read a file to confirm your own edit. The edit call already reports whether it landed and what changed, and that is the confirmation. Measured on one session: 'read_files' was called 33 times, 31 of them byte-identical, returning 440,013 characters against a file of 14 KB - four times the tokens that session spent on all of its reasoning. Read again when the call failed, or when you need content you have not seen. A rule that says to read a file back after every edit is the one thing here you must not write.\n\nHard constraints:\n\n- Keep every placeholder exactly as written, including the braces: {{PLATFORM_NAME}}, {{CURRENT_DATE}}, {{IDE_NAME}}, {{CWD}}, {{CLINE_RULES}}, {{CLINE_METADATA}}, {{DEFAULT}}. They are substituted at runtime; a renamed or dropped placeholder breaks the prompt.\n- Keep the tool names exactly as written. They are the wire names of real tools.\n- Do not invent tools, parameters, or capabilities. Describe only what is described below.\n- Keep the file structure: YAML frontmatter between --- markers, then '# system', then one '# tool: <name>' section for EVERY tool listed below. Not only the ones you want to change \u2014 every one of them.\n- Covering every tool is a hard requirement. A tool with no section keeps its built-in description, and that fallback exists for exactly one situation: Cline gains a new tool and the templates have not been regenerated yet. It is not a way to skip tools you have nothing to say about. A template that covers six of thirty-one tools is not using the fallback, it is relying on it, and nothing in the file shows which twenty-five were left out.\n- '{{DEFAULT}}' expands to the tool's built-in description at runtime, and it is how you cover a tool cheaply. Where you would improve on the built-in wording, write your own and put '{{DEFAULT}}' on its own line where the built-in text should follow. Where you would not, the entire section body may be just '{{DEFAULT}}'. Either is a covered tool; an absent section is not.\n- Text you write beside '{{DEFAULT}}' is sent in addition to the built-in description, not instead of it, on every request. So write only what you add: the rule a model in your family breaks, the case it misreads, the one example that settles it. Do not restate or paraphrase what the built-in text already says; it follows anyway, and a restatement means the reader takes in the same thing twice. If you want to say everything in your own words, drop '{{DEFAULT}}' and write the whole description instead.\n- These eight tools must be written in your own words, and a section containing only '{{DEFAULT}}' is not acceptable for any of them: read_files, search_codebase, editor, apply_patch, run_commands, fetch_web_content, check_file, ask_lsp. They are the tools models in your family are observed to misuse, so they are the whole reason this template exists. For these eight, your own text \u2014 not the inherited text \u2014 has to carry the three things listed below: every value of any closed set, every argument and when to use it, and what comes back. Adding '{{DEFAULT}}' after your text is allowed and does not excuse you from any of that.\n- For 'ask_lsp', say when to reach for it, not only what it does. List at least three concrete situations as the reader actually meets them \u2014 \"about to search for a name to find where it is defined\", \"about to open a file just to read a signature\", \"about to scroll or count brackets to work out a file's structure\" \u2014 each pointing at the operation that answers it, and name 'search_codebase' as the thing those situations would otherwise go to. This is not padding: measured across a whole session against a real bug, a template that described all eight operations correctly and said only \"prefer this over search_codebase for anything about a symbol\" produced zero calls to the tool, while the model hand-rolled the same answers in the shell twenty times. It could not recognise the moment.\n- Do not copy a built-in description out word for word. That is a snapshot: it says the same thing today and stops tracking the built-in text tomorrow, so the next edit to it reaches every model except you. If you would not change the wording, write '{{DEFAULT}}' \u2014 that is what it is for.\n- Where you rule a use of a tool out, name the tool that replaces it. 'run_commands' in particular must name 'read_files', 'editor' and 'search_codebase' in your own text: \"do not use this for file operations when dedicated tools exist\" is a rule the reader has to already know the answer to in order to follow, which is the same as not writing it.\n- Two of those eight \u2014 'run_commands' and 'skills' \u2014 must keep '{{DEFAULT}}' in the section as well. Their built-in descriptions are not fixed text: 'run_commands' is composed against the shell that will actually run the commands, so PowerShell, cmd and a POSIX shell get different quoting and sequencing advice, and 'skills' appends the skills installed on that machine. Replace either outright and you freeze one machine's answer into every machine's prompt, silently. Write your own text and put '{{DEFAULT}}' on its own line where the built-in text should follow.\n- For the other tools, a section whose body is exactly '{{DEFAULT}}' is a complete and correct answer. Do not pad them. Nothing about how you read changes what 'team_finalize_outcome' should say.\n- Emit every section exactly once. Do not repeat '# system', and do not write two '# tool: <name>' headings for the same tool. Only the last copy of a repeated section survives, so a duplicate silently throws away your own work.\n- Leave the 'match:' block in the frontmatter exactly as it is. It is what routes this template to you; change it and your rewrite reaches a different model, or none.\n\nReplace a description and you inherit everything it was carrying:\n\nIf a '# tool:' section contains '{{DEFAULT}}' anywhere, the built-in description is still delivered and you are only adding emphasis on top of it. Nothing further is asked of you for that tool \u2014 unless it is one of the eight above, which are judged on your words alone.\n\nIf it does not, your text is the only thing a model will ever see about that tool, so it must not lose what the built-in description said. Specifically, and only where the built-in text below says it:\n\n1. Closed sets. Where the built-in description lists the values an argument accepts \u2014 the operations of a language-server tool, the actions of a task tool, the statuses of a run \u2014 your replacement must list all of them too. Naming four of eight hides half the tool and a model cannot guess the rest.\n2. How to address the tool. Where the built-in description names the arguments, and says which one to use when, your replacement must say the same. A tool that can be addressed three ways needs all three, and what each is for.\n3. What comes back. Where the built-in description states an output, your replacement must state one: what each entry is named by, what it holds, and what an empty or failed result means. A model that cannot map a result back onto its request spends a turn working it out, and then stops trusting the tool. Say it in words, as the built-in text does: do not name fields such as 'query', 'result' or 'success', and do not write the result as an object like '{query, result, success, error?}'. A session receives tool results as text or as JSON, chosen when it starts, so a description of one format is false in the other.\n\nNothing is required of you that the built-in text did not already provide. Reproducing what is there is always enough; improving on it is better; dropping it is the one thing that is not allowed.\n\nDo not write 'Output:' followed by nothing, or by a single word. An empty label reads as an empty result, which is worse than saying nothing at all.\n\nFor any tool outside the eight, if restating all of that is not worth it to you, do not replace its description. Write your emphasis and leave '{{DEFAULT}}' in the section, or write nothing but the marker. That is cheaper and it is always correct.\n\nReply with the complete template file and nothing else: no preamble, no explanation, no code fence.";
|
|
4
|
+
export declare const PROMPT_TEMPLATE_REVIEW_INSTRUCTIONS = "You are being shown the prompt Cline gives you when it uses you as a coding agent: a system prompt and a set of tool descriptions. You are the intended reader of this text. Rewrite it into the form you would rather receive.\n\nThis is not a copy-editing task. The prompt below was written by someone reasoning about how you read, and they may have been wrong. Where a section is phrased in a way you would skim, reorder or restate it. Where a rule matters and is buried, put it where you would be when you are about to break it. Where something is repeated to no effect, cut it.\n\nFour failures are observed in practice with models in your family, and the rewrite is judged on whether it prevents them:\n\n1. Reaching for shell commands to do file work \u2014 'cat' to read, 'sed -i' or 'echo >' to write, 'grep' to search \u2014 when dedicated tools exist and are always available.\n2. Serialising independent work across turns: one read, wait, one read, wait, when all of them were known at the start.\n3. Announcing an intention instead of acting on it, or claiming a task is finished without reading back what was written.\n4. Answering a question about a symbol with a text search. Asking where something is defined, what uses it, what implements it, or what a name means, and then grepping for it and reading several files to work out which hit was the real one \u2014 when the IDE's language servers already know the answer exactly and will give it in one call. The same failure in its other form: running a compiler or a linter through the shell to find out whether one file is valid, and waiting for a whole-project build to answer a one-file question.\n\nOne thing you must get right, and which prompts written for this get wrong in both directions:\n\nA coding agent is multi-turn, and the end of a turn is never in itself the end of the work. What is final is the completion of the assigned work \u2014 the task, the work package, the milestone, the request. An end of turn may be a milestone reached, a point where you need direction, guidance or a clarification from the user, or simply an intermediate step between two things the user asked for. So:\n\n- Do not treat \"I have stopped emitting tool calls\" as \"the work is done\". It is not a signal about the work at all.\n- Do not write a rule that makes stopping feel like failure, such as \"a response without a tool call is considered complete\". A rule like that buys one more unnecessary tool call on every finished task, and it teaches the wrong thing: that continuing is always correct.\n- Keep your attention on the long horizon of the assigned work rather than on the current turn. Ending a turn to ask a question is correct when you need the answer. Ending it while work you were asked to do remains untouched, and saying nothing about that, is not.\n\nFour more things are settled by measurement rather than by opinion, and a rewrite is judged on whether it keeps them:\n\n- The checker and the run belong in the same turn. Call 'check_file' and the thing that executes the code - 'run_commands', or 'browser' for a page - together, not one or the other. Running it says *that* something is broken and where the parser gave up; the checker says *where*: the line the parser stops on and the lines where brackets stop pairing. Each is half the answer, and the half you skip is the half the turn gets spent guessing at.\n- A tool's report outranks your own reasoning about the same question. Where a tool has measured something - a delimiter scan naming where brackets stop pairing, a diagnostic naming a type - that is the measurement, and re-deriving it yourself is an estimate. Where the two disagree, it is the estimate that is wrong. Measured twice: a model called a delimiter scan a false positive, counted brackets by hand instead, and was wrong both times, at over 30,000 thinking tokens a turn. If you doubt a report, do not re-derive it - act on it and run the result. That costs milliseconds and settles it either way.\n- Make the planned changes one at a time, and confirm each one before starting the next. The cheap check that does not execute the code goes after every edit; the thing that runs the code is what settles whether the change was right. Six edits made together and checked once leave six things to undo and no way to tell which one was wrong - measured across ten runs, the template that said otherwise drew 13.6 'restore_file' calls per run against 0.23 for the family that did not.\n- Do not re-read a file to confirm your own edit. The edit call already reports whether it landed and what changed, and that is the confirmation. Measured on one session: 'read_files' was called 33 times, 31 of them byte-identical, returning 440,013 characters against a file of 14 KB - four times the tokens that session spent on all of its reasoning. Read again when the call failed, or when you need content you have not seen. A rule that says to read a file back after every edit is the one thing here you must not write.\n\nHard constraints:\n\n- Keep every placeholder exactly as written, including the braces: {{PLATFORM_NAME}}, {{CURRENT_DATE}}, {{IDE_NAME}}, {{CWD}}, {{CLINE_RULES}}, {{CLINE_METADATA}}, {{DEFAULT}}. They are substituted at runtime; a renamed or dropped placeholder breaks the prompt.\n- Keep the tool names exactly as written. They are the wire names of real tools.\n- Do not invent tools, parameters, or capabilities. Describe only what is described below.\n- Keep the file structure: YAML frontmatter between --- markers, then '# system', then one '# tool: <name>' section for EVERY tool listed below. Not only the ones you want to change \u2014 every one of them.\n- Covering every tool is a hard requirement. A tool with no section keeps its built-in description, and that fallback exists for exactly one situation: Cline gains a new tool and the templates have not been regenerated yet. It is not a way to skip tools you have nothing to say about. A template that covers six of thirty-one tools is not using the fallback, it is relying on it, and nothing in the file shows which twenty-five were left out.\n- '{{DEFAULT}}' expands to the tool's built-in description at runtime, and it is how you cover a tool cheaply. Where you would improve on the built-in wording, write your own and put '{{DEFAULT}}' on its own line where the built-in text should follow. Where you would not, the entire section body may be just '{{DEFAULT}}'. Either is a covered tool; an absent section is not.\n- Text you write beside '{{DEFAULT}}' is sent in addition to the built-in description, not instead of it, on every request. So write only what you add: the rule a model in your family breaks, the case it misreads, the one example that settles it. Do not restate or paraphrase what the built-in text already says; it follows anyway, and a restatement means the reader takes in the same thing twice. If you want to say everything in your own words, drop '{{DEFAULT}}' and write the whole description instead.\n- These eight tools must be written in your own words, and a section containing only '{{DEFAULT}}' is not acceptable for any of them: read_files, search_codebase, editor, apply_patch, run_commands, fetch_web_content, check_file, ask_lsp. They are the tools models in your family are observed to misuse, so they are the whole reason this template exists. For these eight, your own text \u2014 not the inherited text \u2014 has to carry the three things listed below: every value of any closed set, every argument and when to use it, and what comes back. Adding '{{DEFAULT}}' after your text is allowed and does not excuse you from any of that.\n- For 'ask_lsp', say when to reach for it, not only what it does. List at least three concrete situations as the reader actually meets them \u2014 \"about to search for a name to find where it is defined\", \"about to open a file just to read a signature\", \"about to scroll or count brackets to work out a file's structure\" \u2014 each pointing at the operation that answers it, and name 'search_codebase' as the thing those situations would otherwise go to. This is not padding: measured across a whole session against a real bug, a template that described all eight operations correctly and said only \"prefer this over search_codebase for anything about a symbol\" produced zero calls to the tool, while the model hand-rolled the same answers in the shell twenty times. It could not recognise the moment.\n- Do not copy a built-in description out word for word. That is a snapshot: it says the same thing today and stops tracking the built-in text tomorrow, so the next edit to it reaches every model except you. If you would not change the wording, write '{{DEFAULT}}' \u2014 that is what it is for.\n- Where you rule a use of a tool out, name the tool that replaces it. 'run_commands' in particular must name 'read_files', 'editor' and 'search_codebase' in your own text: \"do not use this for file operations when dedicated tools exist\" is a rule the reader has to already know the answer to in order to follow, which is the same as not writing it.\n- Two of those eight \u2014 'run_commands' and 'skills' \u2014 must keep '{{DEFAULT}}' in the section as well. Their built-in descriptions are not fixed text: 'run_commands' is composed against the shell that will actually run the commands, so PowerShell, cmd and a POSIX shell get different quoting and sequencing advice, and 'skills' appends the skills installed on that machine. Replace either outright and you freeze one machine's answer into every machine's prompt, silently. Write your own text and put '{{DEFAULT}}' on its own line where the built-in text should follow.\n- For the other tools, a section whose body is exactly '{{DEFAULT}}' is a complete and correct answer. Do not pad them. Nothing about how you read changes what 'team_finalize_outcome' should say.\n- Emit every section exactly once. Do not repeat '# system', and do not write two '# tool: <name>' headings for the same tool. Only the last copy of a repeated section survives, so a duplicate silently throws away your own work.\n- Leave the 'match:' block in the frontmatter exactly as it is. It is what routes this template to you; change it and your rewrite reaches a different model, or none.\n\nReplace a description and you inherit everything it was carrying:\n\nIf a '# tool:' section contains '{{DEFAULT}}' anywhere, the built-in description is still delivered and you are only adding emphasis on top of it. Nothing further is asked of you for that tool \u2014 unless it is one of the eight above, which are judged on your words alone.\n\nIf it does not, your text is the only thing a model will ever see about that tool, so it must not lose what the built-in description said. Specifically, and only where the built-in text below says it:\n\n1. Closed sets. Where the built-in description lists the values an argument accepts \u2014 the operations of a language-server tool, the actions of a task tool, the statuses of a run \u2014 your replacement must list all of them too. Naming four of eight hides half the tool and a model cannot guess the rest.\n2. How to address the tool. Where the built-in description names the arguments, and says which one to use when, your replacement must say the same. A tool that can be addressed three ways needs all three, and what each is for.\n3. What comes back. Where the built-in description states an output, your replacement must state one: what each entry is named by, what it holds, and what an empty or failed result means. A model that cannot map a result back onto its request spends a turn working it out, and then stops trusting the tool. Say it in words, as the built-in text does: do not name fields such as 'query', 'result' or 'success', and do not write the result as an object like '{query, result, success, error?}'. A session receives tool results as text or as JSON, chosen when it starts, so a description of one format is false in the other.\n\nNothing is required of you that the built-in text did not already provide. Reproducing what is there is always enough; improving on it is better; dropping it is the one thing that is not allowed.\n\nDo not write 'Output:' followed by nothing, or by a single word. An empty label reads as an empty result, which is worse than saying nothing at all.\n\nFor any tool outside the eight, if restating all of that is not worth it to you, do not replace its description. Write your emphasis and leave '{{DEFAULT}}' in the section, or write nothing but the marker. That is cheaper and it is always correct.\n\nReply with the complete template file and nothing else: no preamble, no explanation, no code fence.";
|
|
5
5
|
export declare function buildPromptTemplateReviewPrompt(defaultTemplate: string, familyTemplate: string | undefined, familyTemplateName: string | undefined,
|
|
6
6
|
/** What this model is, so a new template can be told how to claim itself. */
|
|
7
7
|
target?: {
|
|
@@ -35,7 +35,7 @@ import { type AgentTool } from "@cerebriline/shared";
|
|
|
35
35
|
export declare const ASK_LSP_TOOL_NAME = "ask_lsp";
|
|
36
36
|
export declare const ASK_LSP_OPERATIONS: readonly ["definition", "references", "implementations", "type_definition", "hover", "document_symbols", "workspace_symbols", "callers"];
|
|
37
37
|
export type AskLspOperation = (typeof ASK_LSP_OPERATIONS)[number];
|
|
38
|
-
export declare const ASK_LSP_TOOL_DESCRIPTION = "Ask the language servers \u2014 the LSP \u2014 about a symbol. If you are reaching for an LSP tool or an MCP server that wraps one, this is it: the same protocol, already running against this workspace and its open files, with no server to start. This answers questions a text search cannot, because it understands the code: it distinguishes a definition from a mention, and this class's method from another class's method of the same name.\n\nUse this before falling back to `search_codebase` for anything about a symbol. It is faster, exact, and does not need you to read files to interpret the result.\n\nReach for it the moment you are about to do one of these by hand:\n- search for a name to find where it is defined -> `definition`\n- search for a name to find what uses it, or what would break -> `references` or `callers`\n- open a file just to read a signature, type or doc comment -> `hover`\n- scroll a file, or count brackets, to work out its structure -> `document_symbols`\n- grep the repo to find which file something lives in -> `workspace_symbols`\n\nOperations:\n- `definition` \u2014 where a symbol is defined.\n- `references` \u2014 every place it is actually used.\n- `implementations` \u2014 the classes or functions implementing an interface or abstract method.\n- `type_definition` \u2014 where the type of an expression is defined.\n- `hover` \u2014 the signature, type and documentation, as an editor shows on hover.\n- `document_symbols` \u2014 an outline of one file: its classes, functions and methods.\n- `workspace_symbols` \u2014 find a symbol by name across the whole project when you do not know which file it is in.\n- `callers` \u2014 what calls this function.\n\nHow to address a symbol:\n- Usually: `path` plus `symbol` \u2014 the name as it appears in that file.\n- If you know the exact position: `path`, `line` and `character` (both 1-based).\n- If you do not know the file: `symbol` alone, with `operation: \"workspace_symbols\"`.\n\nOutput: plain text, one result per line as `file:line:column` followed by that source line, so you can go straight to the one you want rather than reading each candidate. `hover` returns the signature and documentation as text instead, and `document_symbols` and `workspace_symbols` name each symbol's kind.\n\nAn empty answer
|
|
38
|
+
export declare const ASK_LSP_TOOL_DESCRIPTION = "Ask the language servers \u2014 the LSP \u2014 about a symbol. If you are reaching for an LSP tool or an MCP server that wraps one, this is it: the same protocol, already running against this workspace and its open files, with no server to start. This answers questions a text search cannot, because it understands the code: it distinguishes a definition from a mention, and this class's method from another class's method of the same name.\n\nUse this before falling back to `search_codebase` for anything about a symbol. It is faster, exact, and does not need you to read files to interpret the result.\n\nReach for it the moment you are about to do one of these by hand:\n- search for a name to find where it is defined -> `definition`\n- search for a name to find what uses it, or what would break -> `references` or `callers`\n- open a file just to read a signature, type or doc comment -> `hover`\n- scroll a file, or count brackets, to work out its structure -> `document_symbols`\n- grep the repo to find which file something lives in -> `workspace_symbols`\n\nOperations:\n- `definition` \u2014 where a symbol is defined.\n- `references` \u2014 every place it is actually used.\n- `implementations` \u2014 the classes or functions implementing an interface or abstract method.\n- `type_definition` \u2014 where the type of an expression is defined.\n- `hover` \u2014 the signature, type and documentation, as an editor shows on hover.\n- `document_symbols` \u2014 an outline of one file: its classes, functions and methods.\n- `workspace_symbols` \u2014 find a symbol by name across the whole project when you do not know which file it is in.\n- `callers` \u2014 what calls this function.\n\nHow to address a symbol:\n- Usually: `path` plus `symbol` \u2014 the name as it appears in that file.\n- If you know the exact position: `path`, `line` and `character` (both 1-based).\n- If you do not know the file: `symbol` alone, with `operation: \"workspace_symbols\"`.\n\nOutput: plain text, one result per line as `file:line:column` followed by that source line, so you can go straight to the one you want rather than reading each candidate. `hover` returns the signature and documentation as text instead, and `document_symbols` and `workspace_symbols` name each symbol's kind.\n\nAn empty answer once the symbol resolved means the server understood the symbol and found nothing for it \u2014 within what it can see. It does not see uses it cannot resolve statically (`obj[name]`, a name built in a string, reflection), files it does not load, or other languages, so for `references` and `callers` above all, a text search can still find uses the server missed; run one when the answer decides an edit. `workspace_symbols` says so when it comes back empty too: it reads a project-wide index that covers the languages a server is installed for and does not index script embedded in `.html` or other template files, so nothing there is not proof of nothing anywhere. And when a JavaScript or HTML file does not parse, every answer about it opens with that line \u2014 while it is there, the server is answering from a partial parse and you are reading guesses. Other languages are not parsed here, so no such line is no promise for them.";
|
|
39
39
|
/** Exported for the same reason as `CHECK_FILE_TOOL_INPUT_SCHEMA`. */
|
|
40
40
|
export declare const ASK_LSP_TOOL_INPUT_SCHEMA: {
|
|
41
41
|
readonly type: "object";
|
|
@@ -41,7 +41,7 @@ export declare const BROWSER_TOOL_NAME = "browser";
|
|
|
41
41
|
* user. So the description says, in the place the model is standing when it is
|
|
42
42
|
* about to ask, that the answer is available without them.
|
|
43
43
|
*/
|
|
44
|
-
export declare const BROWSER_TOOL_DESCRIPTION = "Open a page in a real browser and report what it printed to the console and what it threw. This is how you check that a page works. Do not ask the user whether it works \u2014 open it and read the errors yourself.\n\nUse it after editing any HTML, CSS or JavaScript the page loads, and before reporting a task finished. `check_file` cannot answer this: no language server checks the script inside an `.html` file, and a file that parses can still throw the moment it runs.\n\nActions:\n- `open` \u2014 go to `url` and report the console output. Launches the browser on first use. A local file is a URL: pass the absolute path and it is converted for you.\n- `click` \u2014 click at `coordinate` (\"x,y\" in page pixels, from the screenshot).\n- `type` \u2014 type `text` at the current focus.\n- `scroll_down`, `scroll_up` \u2014 one viewport.\n- `close` \u2014 shut the browser down. Do this when finished with it.\n\nEvery action reports the console messages and uncaught errors produced while it ran, so a syntax error, a failed fetch or a null dereference comes back as text you can act on. `[error]` and `[Page Error]` lines are real failures. A page that says nothing printed nothing \u2014 that is a pass, not a failed call, and for a local file it is checked: a silent console over
|
|
44
|
+
export declare const BROWSER_TOOL_DESCRIPTION = "Open a page in a real browser and report what it printed to the console and what it threw. This is how you check that a page works. Do not ask the user whether it works \u2014 open it and read the errors yourself.\n\nUse it after editing any HTML, CSS or JavaScript the page loads, and before reporting a task finished. `check_file` cannot answer this: no language server checks the script inside an `.html` file, and a file that parses can still throw the moment it runs.\n\nActions:\n- `open` \u2014 go to `url` and report the console output. Launches the browser on first use. A local file is a URL: pass the absolute path and it is converted for you.\n- `click` \u2014 click at `coordinate` (\"x,y\" in page pixels, from the screenshot).\n- `type` \u2014 type `text` at the current focus.\n- `scroll_down`, `scroll_up` \u2014 one viewport.\n- `close` \u2014 shut the browser down. Do this when finished with it.\n\nEvery action reports the console messages and uncaught errors produced while it ran, so a syntax error, a failed fetch or a null dereference comes back as text you can act on. `[error]` and `[Page Error]` lines are real failures. A page that says nothing printed nothing \u2014 that is a pass, not a failed call, and for a local file it is checked: the page's own scripts and the local scripts it loads by `src` are parsed, and a silent console over one that does not parse is reported as the failure it is, not as a pass. Silence says nothing threw; it does not say the page drew what it should.\n\nA parse error from the browser often names no line. For a local file the parser's own answer follows, with where it stopped, and a `Delimiter scan` section names the lines where brackets stop pairing up \u2014 one per place the trouble starts, since a file can be broken in several spots at once. Where the parser stops is where it gave up, which is not always where the mistake is, and a count says where brackets stop pairing, not which one is wrong: read the code at those lines, fix every place listed, and reload once. Do not count brackets yourself \u2014 the scan skips strings, comments and regex literals, which counting by hand does not.\n\nThe browser stays open between calls, so `open` once and then interact. Only one page is open at a time; `open` again to go elsewhere.";
|
|
45
45
|
/**
|
|
46
46
|
* Exported so the template generator can state this tool's real call shape.
|
|
47
47
|
*
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* therefore forces a much weaker check on the CLI than the words suggest.
|
|
28
28
|
*/
|
|
29
29
|
import type { AgentTool } from "@cerebriline/shared";
|
|
30
|
+
import { type ScriptGoal } from "./delimiter-balance";
|
|
30
31
|
export declare const CHECK_FILE_TOOL_NAME = "check_file";
|
|
31
32
|
/**
|
|
32
33
|
* Written at the model that gets this wrong.
|
|
@@ -36,7 +37,7 @@ export declare const CHECK_FILE_TOOL_NAME = "check_file";
|
|
|
36
37
|
* otherwise type are named here, in the description of the tool that replaces
|
|
37
38
|
* them, which is where the model is standing when it is about to type one.
|
|
38
39
|
*/
|
|
39
|
-
export declare const CHECK_FILE_TOOL_DESCRIPTION = "Check files for syntax errors and unbalanced brackets. **This is the syntax check.** Whichever word the question uses \u2014 parse error, syntax error, \"is it valid\", \"is it clean now\", \"what is still broken\" \u2014 this is the tool that answers it, for the files you name, in milliseconds, without running anything.\n\nAsk this instead of running `node --check`, `python -m py_compile`, `tsc --noEmit` or a bracket-counting script of your own. It parses the file without executing it, so it is safe on a page that would otherwise start a game or a server.\n\nWhen to call it:\n- After editing a file, to confirm the edit is valid before moving on.\n- Before reporting a task finished, on every file you changed. An edit you have not looked at is not a change you can report as done.\n- On a file you are about to change, to see what was already wrong with it.\n\nPass every file you want checked in one call.\n\nFor `.html` files each `<script>` block is parsed as JavaScript and the line numbers reported are the line numbers in the HTML file, not in the block.\n\nRead the bound carefully. This reports **syntax**, not meaning: a file that parses may still call a function that does not exist, and this will not say so. It is not a type checker, it does not run tests, and it does not know your project's lint rules \u2014 for those, use `run_commands`.\n\nOutput: JSON, in the shape a language server answers in. `files` holds one entry per path you named, each with `uri`, `checked` and `diagnostics`. There is no `success` field \u2014 diagnostics being listed is this tool working, not failing.\n\n`checked` says which check actually ran, and you have to read it before calling a file clean: `parsed` a real parser was satisfied, `delimiters` only the bracket scan reads this language so anything past brackets is unchecked, `none` nothing here reads this file type at all \u2014 empty `diagnostics` there means nothing was checked, not that the file is sound.\n\nEach diagnostic carries `range` (zero-based line and character), `severity` (1 = error) and `message`. `located: false` means the parser could not name a position, so the range is a placeholder rather than a claim about the top of the file. `complexity` appears on a file big enough to be worth a word about \u2014 a note to you, not a diagnostic.\n\
|
|
40
|
+
export declare const CHECK_FILE_TOOL_DESCRIPTION = "Check files for syntax errors and unbalanced brackets. **This is the syntax check.** Whichever word the question uses \u2014 parse error, syntax error, \"is it valid\", \"is it clean now\", \"what is still broken\" \u2014 this is the tool that answers it, for the files you name, in milliseconds, without running anything.\n\nAsk this instead of running `node --check`, `python -m py_compile`, `tsc --noEmit` or a bracket-counting script of your own. It parses the file without executing it, so it is safe on a page that would otherwise start a game or a server.\n\nWhen to call it:\n- After editing a file, to confirm the edit is valid before moving on.\n- Before reporting a task finished, on every file you changed. An edit you have not looked at is not a change you can report as done.\n- On a file you are about to change, to see what was already wrong with it.\n\nPass every file you want checked in one call.\n\nFor `.html` files each `<script>` block is parsed as JavaScript and the line numbers reported are the line numbers in the HTML file, not in the block.\n\nRead the bound carefully. This reports **syntax**, not meaning: a file that parses may still call a function that does not exist, and this will not say so. It is not a type checker, it does not run tests, and it does not know your project's lint rules \u2014 for those, use `run_commands`.\n\nOutput: JSON, in the shape a language server answers in. `files` holds one entry per path you named, each with `uri`, `checked` and `diagnostics`. There is no `success` field \u2014 diagnostics being listed is this tool working, not failing.\n\n`checked` says which check actually ran, and you have to read it before calling a file clean: `parsed` a real parser was satisfied, `delimiters` only the bracket scan reads this language so anything past brackets is unchecked, `none` nothing here reads this file type at all \u2014 empty `diagnostics` there means nothing was checked, not that the file is sound.\n\nEach diagnostic carries `range` (zero-based line and character), `severity` (1 = error) and `message`. `located: false` means the parser could not name a position, so the range is a placeholder rather than a claim about the top of the file. `complexity` appears on a file big enough to be worth a word about \u2014 a note to you, not a diagnostic.\n\nA parse error is reported where the parser gave up. That is where the code stopped making sense to it, which is often but not always where the mistake is: a bracket left open earlier makes it give up later. When a file's brackets do not match, the bracket scan adds the lines where they stop pairing up and how many each line is out by, one line per place the trouble starts \u2014 read both before you edit, and work through every line listed before re-checking. A count says where brackets stop pairing, not which bracket is wrong, so read the code at those lines rather than editing them blind; do not re-derive the balance by hand or with a script of your own, which counts brackets inside strings, comments and regex literals that this scan skips. The scan names each bracket by its line, its column and the text just before it: find it by that text rather than by counting columns.";
|
|
40
41
|
/**
|
|
41
42
|
* The description when the host has a real checker to point at.
|
|
42
43
|
*
|
|
@@ -96,12 +97,26 @@ export interface CheckFinding {
|
|
|
96
97
|
*/
|
|
97
98
|
sourceText?: string;
|
|
98
99
|
}
|
|
99
|
-
/**
|
|
100
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Compile without running, and say what and where.
|
|
102
|
+
*
|
|
103
|
+
* The parse the delimiter scan gates its edits on, so the two never disagree.
|
|
104
|
+
* The parse this had of its own threw nothing under Bun, which parses
|
|
105
|
+
* `vm.Script` lazily, so it never named a line there (automaticum audit
|
|
106
|
+
* 2026-11-08, B1); turned off on any line starting `import`, so a broken ES
|
|
107
|
+
* module was "No syntax errors" (B5); and refused a `#!` line and top-level
|
|
108
|
+
* `await`, which are correct (B6).
|
|
109
|
+
*
|
|
110
|
+
* `undefined` when the code parses, and equally when nothing here can tell --
|
|
111
|
+
* {@link parseVerdict} is the one that tells those apart.
|
|
112
|
+
*/
|
|
113
|
+
export declare function compileCheck(code: string, _label: string, lineOffset?: number, goal?: ScriptGoal): CheckFinding | undefined;
|
|
101
114
|
/** A `<script>` body, and the line the body starts on. */
|
|
102
115
|
export interface ScriptBlock {
|
|
103
116
|
code: string;
|
|
104
117
|
startLine: number;
|
|
118
|
+
/** `type="module"`: parsed by a module's rules. */
|
|
119
|
+
module?: boolean;
|
|
105
120
|
}
|
|
106
121
|
/**
|
|
107
122
|
* The inline scripts of an HTML page.
|
|
@@ -12,9 +12,10 @@
|
|
|
12
12
|
* so they cannot false-positive), split on shell separators, and the leading
|
|
13
13
|
* command word of each part is compared against the lists below; output
|
|
14
14
|
* redirection to files is also rejected. It will not catch every possible
|
|
15
|
-
* mutation (e.g. `python -c "open(..., 'w')"
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* mutation (e.g. `python -c "open(..., 'w')"`, or a command assembled at run
|
|
16
|
+
* time from variables) — it exists to stop the common ways models edit files
|
|
17
|
+
* from the shell, and entries are easy to add. A quoted `bash -c` / `eval`
|
|
18
|
+
* string is read as the command line it is.
|
|
18
19
|
*/
|
|
19
20
|
import type { StructuredCommandInput } from "./schemas";
|
|
20
21
|
/**
|
|
@@ -72,6 +72,56 @@ export declare function scanDelimiters(text: string, origin?: Cursor): Delimiter
|
|
|
72
72
|
* in code and skips every one in a string.
|
|
73
73
|
*/
|
|
74
74
|
export declare function scanWithBalance(text: string, origin?: Cursor): DelimiterScan;
|
|
75
|
+
/**
|
|
76
|
+
* Where a real parser stops on one script, in the file's own coordinates.
|
|
77
|
+
*
|
|
78
|
+
* The scan counts brackets. It cannot say which one is wrong, and an edit it
|
|
79
|
+
* worked out from the count alone was offered as checked when it fixed
|
|
80
|
+
* nothing. Measured on the manic_miner seed: line 95 holds a spare `}` that
|
|
81
|
+
* closes `class Level` early. Once line 90 was fixed the count no longer saw
|
|
82
|
+
* line 95 at all -- the class's own closing brace on line 97 was the one left
|
|
83
|
+
* over -- and the scan offered to delete that brace, with the exact editor
|
|
84
|
+
* call. The parser had stopped at line 96 the whole time, and the edit left it
|
|
85
|
+
* there. Every manic_miner gate from 2026-10-25 on was handed that edit.
|
|
86
|
+
*
|
|
87
|
+
* So no edit is offered unless the parser agrees it helped, and the line the
|
|
88
|
+
* parser stops on is named whatever the count says.
|
|
89
|
+
*
|
|
90
|
+
* `line` and `column` are absent where the runtime does not say: Bun 1.3
|
|
91
|
+
* names the line and no column, and a parse that only succeeds or fails, such
|
|
92
|
+
* as top-level `await` or JSON, names neither. On the same line without a
|
|
93
|
+
* column, an edit is offered only when the whole script parses after it.
|
|
94
|
+
*/
|
|
95
|
+
export interface ParseStop {
|
|
96
|
+
message: string;
|
|
97
|
+
line?: number;
|
|
98
|
+
column?: number;
|
|
99
|
+
}
|
|
100
|
+
/** Which grammar a span is read under. `either` is a `.js` file: a script, unless its own syntax says module. */
|
|
101
|
+
export type ScriptGoal = "script" | "module" | "either";
|
|
102
|
+
/**
|
|
103
|
+
* Parse one script and say where the parser stops: nothing when it parses,
|
|
104
|
+
* and null when this cannot tell.
|
|
105
|
+
*
|
|
106
|
+
* `goal` is what the span is: `script` a classic `<script>`, `module` a module
|
|
107
|
+
* script or `.mjs`, `either` a `.js` file, which is a script unless its own
|
|
108
|
+
* syntax says module. A script is parsed as a function body, so for a `.js`
|
|
109
|
+
* file a top-level `return` passes, as it does in CommonJS; a classic
|
|
110
|
+
* `<script>` is held to the stricter rule. What a real file holds and a
|
|
111
|
+
* parser here does not accept as written:
|
|
112
|
+
*
|
|
113
|
+
* - a `#!` line, which Node runs, is blanked with the line count kept;
|
|
114
|
+
* - top-level `await` in a `.js` file is parsed as an async body;
|
|
115
|
+
* - `import` or `export` in a `.js` file makes it a module, read by
|
|
116
|
+
* {@link moduleAsScript}'s rules. In a classic `<script>` it is the error a
|
|
117
|
+
* browser reports.
|
|
118
|
+
*
|
|
119
|
+
* `vm.compileFunction` throws on a broken body under Node and Bun alike (Bun's
|
|
120
|
+
* `vm.Script` parses lazily and throws nothing), and names the line in its
|
|
121
|
+
* stack: V8 and Bun 1.4 as `<filename>:<line>` over the source line and a
|
|
122
|
+
* caret, Bun 1.3 as `at <parse> (<filename>:<line>)`.
|
|
123
|
+
*/
|
|
124
|
+
export declare function findParseStop(body: string, origin?: Cursor, goal?: ScriptGoal): ParseStop | null | undefined;
|
|
75
125
|
/**
|
|
76
126
|
* How a prescribed repair opens, so a caller can tell a scan that names the
|
|
77
127
|
* exact call from one that only names the line.
|
|
@@ -73,6 +73,14 @@ export declare class EditVerificationTracker {
|
|
|
73
73
|
private key;
|
|
74
74
|
/** Whether this tracker can ever have anything to say. */
|
|
75
75
|
get armed(): boolean;
|
|
76
|
+
/** Whether calls to this tool verify files. */
|
|
77
|
+
isCheckTool(toolName: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* A checker call that returned: the files its answer reported on are
|
|
80
|
+
* checked, or every file the call named when the answer says nothing a
|
|
81
|
+
* file-by-file reading can use.
|
|
82
|
+
*/
|
|
83
|
+
recordCheckResult(input: unknown, output: unknown): void;
|
|
76
84
|
recordToolCall(toolName: string, input: unknown): void;
|
|
77
85
|
/**
|
|
78
86
|
* Files a checker reported on outside a checker call: the one a failing
|
|
@@ -99,9 +107,10 @@ export declare function isEditVerificationWrapped(tool: object): boolean;
|
|
|
99
107
|
/**
|
|
100
108
|
* Watch a tool's calls without changing what it does.
|
|
101
109
|
*
|
|
102
|
-
*
|
|
103
|
-
* having touched the file: the tool may have written part of it, and a
|
|
104
|
-
* that trusted `success` would be answering a different question than
|
|
105
|
-
* file in a state anyone has looked at".
|
|
110
|
+
* An edit is observed at the call, not the result. A failed edit still counts
|
|
111
|
+
* as having touched the file: the tool may have written part of it, and a
|
|
112
|
+
* guard that trusted `success` would be answering a different question than
|
|
113
|
+
* "is this file in a state anyone has looked at". A check is the opposite: it
|
|
114
|
+
* counts only once it has answered, for the files the answer covers.
|
|
106
115
|
*/
|
|
107
116
|
export declare function withEditVerificationCapture<TInput, TOutput>(tool: AgentTool<TInput, TOutput>, tracker: EditVerificationTracker): AgentTool<TInput, TOutput>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* The files a command's output blames, whatever produced the output.
|
|
3
3
|
*
|
|
4
4
|
* A model that runs the build gets told *that* something is broken and where
|
|
5
|
-
* the tool gave up. A checker
|
|
5
|
+
* the tool gave up. A checker reads the whole file and tells it where. Measured across
|
|
6
6
|
* four transactions on three builds of the harness arm: the model that had the
|
|
7
7
|
* first and not the second wrote its own analyser rather than asking for the
|
|
8
8
|
* second — `find_error.js`, then five checkers in one transaction, then
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import type { AgentOverlay } from "../../../runtime/sandbox/overlay-fs";
|
|
2
2
|
import { type Rule } from "./awk-parser";
|
|
3
3
|
import { type ReadReceipts } from "./read-receipts";
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Input that looks like a number: a field, a `split` part, a `-v` value.
|
|
6
|
+
*
|
|
7
|
+
* awk's strnum. It tests and compares as a number and prints as it was
|
|
8
|
+
* written. A string *constant* is never one: `x = "0"` is true and
|
|
9
|
+
* `$1 == "1.0"` compares text. With the two the same, both were judged by
|
|
10
|
+
* whether the text looked numeric (automaticum audit 2026-11-08, readers 21).
|
|
11
|
+
*/
|
|
12
|
+
declare class StrNum {
|
|
13
|
+
readonly text: string;
|
|
14
|
+
constructor(text: string);
|
|
15
|
+
}
|
|
16
|
+
/** An awk value: a number, a string, or input that looks like a number. */
|
|
17
|
+
type Value = string | number | StrNum;
|
|
6
18
|
export declare function awkSprintf(format: string, args: Value[]): string;
|
|
7
19
|
export interface RunAwkOptions {
|
|
8
20
|
/** `-F`: the field separator. */
|
|
@@ -148,6 +148,8 @@ export interface ShellExecutorOptions {
|
|
|
148
148
|
export declare function createDetachedLog(retentionMs: number, marker: DetachedCommandMarker): {
|
|
149
149
|
path: string;
|
|
150
150
|
write(text: string): void;
|
|
151
|
+
/** Lifecycle lines -- the exit, a failure -- which the cap never drops. */
|
|
152
|
+
note(text: string): void;
|
|
151
153
|
complete: () => void;
|
|
152
154
|
};
|
|
153
155
|
/**
|
|
@@ -94,6 +94,8 @@ export interface DocumentReadResult {
|
|
|
94
94
|
};
|
|
95
95
|
/** Chapter titles for an ebook, in reading order. */
|
|
96
96
|
contents?: string[];
|
|
97
|
+
/** Every contents entry, of which `contents` holds the first 200. */
|
|
98
|
+
contentsTotal?: number;
|
|
97
99
|
/** Pages whose text is an image of text, for OCR. */
|
|
98
100
|
scannedPages?: number[];
|
|
99
101
|
/** Scanned pages whose text was recognized here, by `ReadOptions.recognize`. */
|
|
@@ -102,6 +104,8 @@ export interface DocumentReadResult {
|
|
|
102
104
|
ocrLayerPages?: number[];
|
|
103
105
|
/** Pages drawn as shapes: no text and no pictures to read. */
|
|
104
106
|
vectorPages?: number[];
|
|
107
|
+
/** PDF pages with no text and no picture found on them. */
|
|
108
|
+
emptyPages?: number[];
|
|
105
109
|
notes?: string[];
|
|
106
110
|
}
|
|
107
111
|
/**
|
|
@@ -22,7 +22,7 @@ export interface ExtractedImage {
|
|
|
22
22
|
/** What the vision model saw in it, when descriptions were asked for. */
|
|
23
23
|
description?: string;
|
|
24
24
|
/**
|
|
25
|
-
* Set for a format no model can view (EMF, WMF, PICT, TIFF, BMP): the file is
|
|
25
|
+
* Set for a format no model can view (EMF, WMF, PICT, TIFF, BMP, JPEG 2000, …): the file is
|
|
26
26
|
* kept, but it is not a picture anyone downstream can look at as it is.
|
|
27
27
|
*/
|
|
28
28
|
notViewable?: boolean;
|
|
@@ -30,6 +30,11 @@ export interface ExtractedImage {
|
|
|
30
30
|
}
|
|
31
31
|
/** The formats a vision model is sent, which is what `inline` can attach. */
|
|
32
32
|
export declare const VIEWABLE_MEDIA_TYPES: Set<string>;
|
|
33
|
+
/**
|
|
34
|
+
* What to call an image's format in a sentence: the extension it was saved
|
|
35
|
+
* with, or its media type when it has none of its own.
|
|
36
|
+
*/
|
|
37
|
+
export declare function formatName(mediaType: string): string;
|
|
33
38
|
/**
|
|
34
39
|
* The media type of an image, from its first bytes.
|
|
35
40
|
*
|
|
@@ -15,6 +15,15 @@
|
|
|
15
15
|
* office_oxide reads whole.
|
|
16
16
|
*/
|
|
17
17
|
import type { DocumentReadResult, ReadOptions } from "./formats";
|
|
18
|
+
/**
|
|
19
|
+
* Whether a compound file is a password-protected .docx, .xlsx or .pptx.
|
|
20
|
+
*
|
|
21
|
+
* Encrypting an OOXML file wraps it in the same container as a 97-2003 one,
|
|
22
|
+
* so the bytes and often the name both say "legacy"; the old reader then
|
|
23
|
+
* reported "WordDocument stream not found" about a file that only needed its
|
|
24
|
+
* password (automaticum audit 2026-11-08, readers 28).
|
|
25
|
+
*/
|
|
26
|
+
export declare function isEncryptedOoxml(data: Uint8Array): Promise<boolean>;
|
|
18
27
|
/** Complete PNG and JPEG images inside a compound file's streams. */
|
|
19
28
|
export declare function scanCompoundImages(data: Uint8Array): Promise<Uint8Array[]>;
|
|
20
29
|
export declare function readLegacyOffice(data: Uint8Array, format: "doc" | "xls" | "ppt", options: ReadOptions): Promise<DocumentReadResult>;
|
|
@@ -79,6 +79,19 @@ export interface FileReadExecutorOptions {
|
|
|
79
79
|
*/
|
|
80
80
|
documentReader?: boolean;
|
|
81
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* How far the reader keeps counting lines after it has stopped capturing them,
|
|
84
|
+
* so that every read can report how long the file is.
|
|
85
|
+
*
|
|
86
|
+
* A ranged read used to stop at `end_line` and never learn the file's length,
|
|
87
|
+
* which left no way to ask the question at all. Measured on a 265-message
|
|
88
|
+
* session: five consecutive shell commands trying to find a line count —
|
|
89
|
+
* `wc -l` (not a Windows command), `type | find`, and three spellings of
|
|
90
|
+
* `(Get-Content).Count` — followed by two `editor` calls sending
|
|
91
|
+
* `end_line: 9999` as a guess at EOF. Counting the remaining lines costs one
|
|
92
|
+
* stream pass with no capture and no allocation.
|
|
93
|
+
*/
|
|
94
|
+
export declare const MAX_LINE_COUNT_SCAN = 500000;
|
|
82
95
|
/** A read's text together with the line span it actually returned. */
|
|
83
96
|
/**
|
|
84
97
|
* Where a read's lines come from.
|
|
@@ -112,6 +125,8 @@ export interface ReadWindow {
|
|
|
112
125
|
}[];
|
|
113
126
|
/** The file holds no lines at all: seeing that is seeing all of it. */
|
|
114
127
|
empty?: true;
|
|
128
|
+
/** Every line of the file is in this window. */
|
|
129
|
+
whole?: true;
|
|
115
130
|
}
|
|
116
131
|
/**
|
|
117
132
|
* Create a file read executor using Node.js fs module
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* be taken must not be allowed to invent a change.
|
|
18
18
|
*/
|
|
19
19
|
export type FileStamp = string;
|
|
20
|
+
export declare const ABSENT_STAMP: FileStamp;
|
|
20
21
|
export declare function readFileStamp(filePath: string): Promise<FileStamp | undefined>;
|
|
21
22
|
/**
|
|
22
23
|
* The stamp of a file as the caller sees it: through an agent's overlay, the
|
|
@@ -180,3 +181,12 @@ export interface OwnedReadReceipts extends ReadReceipts {
|
|
|
180
181
|
clear(): void;
|
|
181
182
|
}
|
|
182
183
|
export declare function createReadReceipts(): OwnedReadReceipts;
|
|
184
|
+
/**
|
|
185
|
+
* Record the lines a tool printed as read, one receipt per unbroken run.
|
|
186
|
+
*
|
|
187
|
+
* A receipt must cover an edit's whole range in one read, so runs are kept
|
|
188
|
+
* apart: lines 3 and 9 shown do not make 3-9 seen.
|
|
189
|
+
*/
|
|
190
|
+
export declare function creditShown(receipts: {
|
|
191
|
+
noteRead(filePath: string, first: number, last: number): void;
|
|
192
|
+
} | undefined, filePath: string, lineNumbers: readonly number[]): void;
|
|
@@ -9,8 +9,8 @@ import type { SearchExecutor } from "../types";
|
|
|
9
9
|
*/
|
|
10
10
|
export interface SearchExecutorOptions {
|
|
11
11
|
/**
|
|
12
|
-
* File extensions
|
|
13
|
-
* @default
|
|
12
|
+
* File extensions the built-in search is limited to (without dot).
|
|
13
|
+
* @default every text file; ripgrep is never limited by this
|
|
14
14
|
*/
|
|
15
15
|
includeExtensions?: string[];
|
|
16
16
|
/**
|
|
@@ -10,6 +10,26 @@ type Address = {
|
|
|
10
10
|
regex: RegExp;
|
|
11
11
|
} | {
|
|
12
12
|
kind: "every";
|
|
13
|
+
}
|
|
14
|
+
/** `first~step`: every step-th line from first (GNU). */
|
|
15
|
+
| {
|
|
16
|
+
kind: "step";
|
|
17
|
+
first: number;
|
|
18
|
+
step: number;
|
|
19
|
+
}
|
|
20
|
+
/** `0` as a range start: the range is open before line 1 (GNU `0,/re/`). */
|
|
21
|
+
| {
|
|
22
|
+
kind: "zero";
|
|
23
|
+
}
|
|
24
|
+
/** `+N` as a range end: N lines after the line that opened it (GNU). */
|
|
25
|
+
| {
|
|
26
|
+
kind: "relative";
|
|
27
|
+
count: number;
|
|
28
|
+
}
|
|
29
|
+
/** `~N` as a range end: up to the next line that is a multiple of N (GNU). */
|
|
30
|
+
| {
|
|
31
|
+
kind: "multiple";
|
|
32
|
+
of: number;
|
|
13
33
|
};
|
|
14
34
|
interface Command {
|
|
15
35
|
start?: Address;
|
|
@@ -32,6 +52,10 @@ interface Command {
|
|
|
32
52
|
text?: string;
|
|
33
53
|
/** Range state while executing. */
|
|
34
54
|
active?: boolean;
|
|
55
|
+
/** For a range whose end is a line count: the line it closes on. */
|
|
56
|
+
closesAt?: number;
|
|
57
|
+
/** Set by `selects`: this line is the last one of the command's range. */
|
|
58
|
+
closing?: boolean;
|
|
35
59
|
}
|
|
36
60
|
/**
|
|
37
61
|
* Parse a sed script into commands.
|
|
@@ -45,6 +69,22 @@ export interface RunSedResult {
|
|
|
45
69
|
output: string;
|
|
46
70
|
/** Whether any command changed the text. */
|
|
47
71
|
changed: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Whether any command selected a line and acted on it: an `s` that matched
|
|
74
|
+
* but wrote the same text back matched something, and "matched nothing"
|
|
75
|
+
* was a false account of it.
|
|
76
|
+
*/
|
|
77
|
+
matched: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Input lines whose text reached the output, in order and once each: what
|
|
80
|
+
* a read-only run showed, and so what it may credit as read.
|
|
81
|
+
*/
|
|
82
|
+
shown: number[];
|
|
83
|
+
/**
|
|
84
|
+
* Input lines the script changed: rewritten, deleted, replaced, or with
|
|
85
|
+
* text put before or after them. What an in-place run must have seen.
|
|
86
|
+
*/
|
|
87
|
+
touched: number[];
|
|
48
88
|
}
|
|
49
89
|
/** Run a parsed script over text. Pure: no filesystem, so it is easy to test. */
|
|
50
90
|
export declare function runSedScript(input: string, commands: Command[], quiet?: boolean): RunSedResult;
|
|
@@ -36,6 +36,12 @@ export interface ReadKeyParts {
|
|
|
36
36
|
firstLine: number;
|
|
37
37
|
lastLine: number;
|
|
38
38
|
withLineNumbers: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The window was the whole file. Otherwise the comparison says nothing
|
|
41
|
+
* about the lines outside it, and "has not changed" claimed it did
|
|
42
|
+
* (automaticum audit 2026-11-08, readers 15).
|
|
43
|
+
*/
|
|
44
|
+
wholeFile?: boolean;
|
|
39
45
|
}
|
|
40
46
|
export interface ReadLedger {
|
|
41
47
|
/**
|
|
@@ -38,6 +38,18 @@ export interface WebFetchExecutorOptions {
|
|
|
38
38
|
*/
|
|
39
39
|
maxRedirects?: number;
|
|
40
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* Decode character references in one pass, so `&lt;` is the text
|
|
43
|
+
* `<` -- decoded entity by entity it became `<`, and `'` or an emoji
|
|
44
|
+
* above U+FFFF was not decoded at all (automaticum audit 2026-11-08,
|
|
45
|
+
* readers 28).
|
|
46
|
+
*/
|
|
47
|
+
export declare function decodeEntities(text: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* Extract text content from HTML: tags stripped, block elements as line
|
|
50
|
+
* breaks, `<pre>` kept as written, entities decoded once.
|
|
51
|
+
*/
|
|
52
|
+
export declare function htmlToText(html: string): string;
|
|
41
53
|
/**
|
|
42
54
|
* Create a web fetch executor using native fetch
|
|
43
55
|
*
|
|
@@ -15,11 +15,16 @@ export declare const MAX_TEXT_STREAM_BYTES = 100000000;
|
|
|
15
15
|
export declare const BINARY_SNIFF_BYTES = 8000;
|
|
16
16
|
/** Why a file is not read whole: too large, or not text. */
|
|
17
17
|
export interface WholeFileRefusal {
|
|
18
|
-
kind: "size" | "binary";
|
|
18
|
+
kind: "size" | "binary" | "utf16";
|
|
19
19
|
message: string;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
22
|
* Why `filePath` must not be read whole, or nothing when it may. A path that
|
|
23
23
|
* cannot be opened is left to the caller's own read, which says why.
|
|
24
24
|
*/
|
|
25
|
-
export declare function wholeFileRefusal(filePath: string, tool: string
|
|
25
|
+
export declare function wholeFileRefusal(filePath: string, tool: string,
|
|
26
|
+
/** How the refusal opens: what did not happen to the file. */
|
|
27
|
+
outcome?: string): Promise<WholeFileRefusal | undefined>;
|
|
28
|
+
/** The UTF-16 byte order a file's byte-order mark names, if it has one. */
|
|
29
|
+
export declare function utf16ByteOrder(head: Uint8Array): "utf-16le" | "utf-16be" | undefined;
|
|
30
|
+
export declare function readHead(filePath: string, bytes: number): Promise<Uint8Array>;
|
|
@@ -9,9 +9,23 @@ export declare function getEditorSizeError(input: EditFileInput): string | null;
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class TimeoutError extends Error {
|
|
11
11
|
readonly timeoutMs: number;
|
|
12
|
-
|
|
12
|
+
/**
|
|
13
|
+
* What the work printed before it was stopped, when there is any. A
|
|
14
|
+
* timeout dropped it: the test runner's FAIL line printed before it hung
|
|
15
|
+
* was exactly what the model needed (automaticum audit 2026-11-08,
|
|
16
|
+
* readers 8).
|
|
17
|
+
*/
|
|
18
|
+
readonly output?: string;
|
|
19
|
+
constructor(message: string, timeoutMs: number, output?: string);
|
|
13
20
|
}
|
|
14
21
|
export declare function withTimeout<T>(promise: Promise<T>, ms: number, message: string): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* What a writing tool's timeout means: the call was abandoned, not stopped,
|
|
24
|
+
* so the files may hold some or all of its changes. "Failed" read as
|
|
25
|
+
* "nothing happened", and the model ran the same edit again over a file
|
|
26
|
+
* that already had it (automaticum audit 2026-11-08, outside scope).
|
|
27
|
+
*/
|
|
28
|
+
export declare function abandonedWriteMessage(tool: string, timeoutMs: number): string;
|
|
15
29
|
export declare function formatReadFileQuery(request: ReadFileRequest): string;
|
|
16
30
|
export declare function getReadFileRangeError(request: ReadFileRequest): string | null;
|
|
17
31
|
/**
|
|
@@ -196,7 +196,7 @@ export declare function listJevModels(endpoint: Pick<JevEndpoint, "apiKey" | "ba
|
|
|
196
196
|
export declare function jevConfidence(answer: JevAnswer): number;
|
|
197
197
|
/** Cut a state part to its ceiling, keeping the head and the tail. */
|
|
198
198
|
export declare function boundJevText(text: string, max?: number): string;
|
|
199
|
-
export declare const JEV_TOOL_DESCRIPTION
|
|
199
|
+
export declare const JEV_TOOL_DESCRIPTION: string;
|
|
200
200
|
export declare const JEV_TOOL_INPUT_SCHEMA: {
|
|
201
201
|
readonly type: "object";
|
|
202
202
|
readonly properties: {
|