📐 feat: Add @librechat/dev-tools Package for Coding Tool Definitions - #262
lia-by-librechat[bot] wants to merge 1 commit into
Conversation
Port the LLM-visible surface of the harness-native coding tools from @librechat/agents into packages/dev-tools, published as @librechat/dev-tools: canonical tool names, the JSON schemas and descriptions for the remote-engine tools (execute_code, bash_tool, run_tools_with_code, run_tools_with_bash, read_file) and the local-engine tools (read_file, write_file, edit_file, grep_search, glob_search, list_directory, compile_check), the intent-label contract embedded in every schema, the /mnt/data and bash guidance, and the timeout schema with its environment-resolved defaults. The package has zero runtime dependencies: everything is plain data and pure functions, so the agent harness and BYOM provisioning consume the definitions without the harness owning them. Execution stays harness-native in @librechat/agents; the definitions describe the execution environments this service provides. Ported with export-name parity so the agents-side swap is mechanical; every ported string was verified byte-for-byte against the harness source. Tests pin the canonical names, intent-first property ordering, required properties, and the stateful/attached description builders. CI runs the package tests on Node 22.21.0.
|
@codex review the latest head |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f51a8aedc3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } as const; | ||
| } | ||
|
|
||
| export const LocalProgrammaticToolCallingDescription = `${ProgrammaticToolCallingDescription}\n\nLocal engine: runs bash by default, or Python when \`lang\` is \`py\` or \`python\`, on the host machine and calls tools through an in-process localhost bridge.`; |
There was a problem hiding this comment.
Match the local default to the inherited Python prompt
When a model omits the optional lang argument, this definition defaults execution to bash, but the inherited ProgrammaticToolCallingDescription and code-parameter description instruct it to emit Python using await, asyncio, and print(). The resulting Python is then interpreted as bash and fails; use runtime-neutral instructions, default to Python, or require an explicit runtime choice.
Useful? React with 👍 / 👎.
| ```ts | ||
| import { | ||
| CodeExecutionToolDefinition, | ||
| LocalCodingBundleNames, |
There was a problem hiding this comment.
Use the exported bundle-name identifier in the example
The documented root import names LocalCodingBundleNames, but the package exports only LOCAL_CODING_BUNDLE_NAMES. Copying this primary usage example therefore produces a missing-export error instead of compiling; update the example to use the actual exported identifier.
Useful? React with 👍 / 👎.
| - For payloads that may contain quotes, parentheses, backticks, or arbitrary bytes (random/binary data, JSON with embedded quotes, multi-line strings), prefer a quoted-delimiter heredoc over \`echo '…'\`. The heredoc body is not interpreted by the shell, so substituted payloads pass through unchanged. | ||
| - Heredoc example: \`wc -c << 'EOF'\\n{{tool0turn0}}\\nEOF\` (the quotes around \`'EOF'\` disable interpolation inside the body). |
There was a problem hiding this comment.
Avoid fixed heredoc delimiters for substituted tool output
When tool-output references are enabled and a referenced result contains a line equal to EOF, the recommended fixed-delimiter heredoc terminates at that line even though the delimiter is quoted; the remaining result is then parsed as shell commands. Because prior tool output can be untrusted and this guide is also appended for attached workspaces, such a payload can execute unintended commands or modify persistent project files. Do not describe this form as safe for arbitrary data; use an encoding or a delimiter guaranteed not to occur in the substituted payload.
Useful? React with 👍 / 👎.
| 'c', | ||
| 'cpp', | ||
| 'java', | ||
| 'php', | ||
| 'rs', |
There was a problem hiding this comment.
Restrict the schema to deployed execution runtimes
On the repository's default service deployment, the runtime registry accepts only bash, js, node, py, and ts (service/src/enum/service.ts and service/src/config.ts), while this schema advertises C, C++, Java, PHP, Rust, Go, D, Fortran, and R and omits the available Node runtime. Selecting one of the advertised-but-unregistered values therefore reaches the service as an unknown runtime; derive this enum from the deployed runtime surface or limit it to the supported aliases.
Useful? React with 👍 / 👎.
| * The local engine reuses the remote schemas (`../execute-code.js`, | ||
| * `../bash-tool.js`) and swaps only the descriptions, because the schema | ||
| * shape is identical while the semantics (local machine, configured |
There was a problem hiding this comment.
Replace remote path guidance in local execution schemas
When consumers combine these local descriptions with the reused remote schemas as directed here, the model still receives parameter-level instructions that prior /mnt/data files are available and that anything needed later must be written under /mnt/data. That conflicts with the local descriptions' persistent project working directory and can cause generated or edited files to be written outside the project instead of into the repository. Provide local schema variants that replace the remote /mnt/data guidance along with the descriptions.
Useful? React with 👍 / 👎.
| ...ProgrammaticToolCallingSchema, | ||
| properties: { | ||
| ...ProgrammaticToolCallingSchema.properties, |
There was a problem hiding this comment.
Return independent nested objects from schema builders
This builder copies only the outer properties map, so its intent, code, and tool_manifest subschemas are the same objects held by ProgrammaticToolCallingSchema and by every other builder result; the bash builder has the same problem. Registering multiple variants can therefore leak validator-added metadata or consumer mutations from one schema into the remote definition and subsequent schemas—the package already notes that LangChain mutates dereferenced subschemas. Clone the nested property schemas when constructing each result.
Useful? React with 👍 / 👎.
Summary
Port the LLM-visible surface of the harness-native coding tools from
@librechat/agentsinto this repository as a new package,@librechat/dev-tools— the code-interpreter side of moving the coding tool definitions next to the Code API that provides their execution environments.The package holds exactly what the LLM sees:
ToolNames) and theCODE_EXECUTION_TOOLS/LOCAL_CODING_TOOL_NAMES/LOCAL_CODING_BUNDLE_NAMESsetsexecute_code,bash_tool,run_tools_with_code,run_tools_with_bash,read_file— including the stateful, attached-workspace, and tool-output-reference description/schema buildersread_file,write_file,edit_file,grep_search,glob_search,list_directory,compile_checkINTENT_PROPERTY,withIntent/withoutIntent, arg readers/strippers, and outcome resolution/mnt/dataand bash guidancetimeoutschema with environment-resolved defaults and clampingWhy
The schemas describe the execution environments this service provides, so they live here rather than inside the agent harness:
@librechat/agentsand LibreChat (BYOM provisioning) consume the definitions without the harness owning them. Zero runtime dependencies — everything is plain data and pure functions.Execution stays harness-native in
@librechat/agents(Code API client,ToolNodeevent dispatch, the local engine, result replay, and output shaping). The sibling@librechat/codepackage covers the worker side of provisioning.Provenance and fidelity
Ported from
@librechat/agentssrc/tools/with export-name parity so the agents-side swap is mechanical. Intentional differences:Constantstool-name members becameToolNames(the harness enum mixes orchestration constants; only the coding-tool members moved)CompileCheckSchema, the local programmatic tool calling schema builders) are exported here — sharing them is the package's purposeLocal*ToolDescriptionconstantsJsonSchemaTypeis widened with the JSON-Schema keywords these schemas use (minLength,minimum,maximum,default,uniqueItems)Every ported string was verified byte-for-byte against the harness source at port time — full-file diffs for the intent and timeout modules, block diffs for the schema builders, extraction-and-compare for every description constant. Descriptions are prompt surface, so drift is behavior change.
Verification
npm testinpackages/dev-tools: 42 tests pass — canonical names and sets, intent-first property ordering, required properties, timeout bounds and env resolution, and the stateful/attached description and schema buildersnpx tsc --noEmitcleandev-tools-package-testsjob on Node 22.21.0 — pure TypeScript with zero runtime deps, so no matrix and no native toolingNot in this PR
The agents-side swap (importing
@librechat/dev-toolsfrom the harness) comes in a follow-up against the agents repository.