Skip to content

fix: /version command + recover qwen tool calls from text content#41

Merged
Doorman11991 merged 1 commit into
masterfrom
fix/issues-36-40
May 23, 2026
Merged

fix: /version command + recover qwen tool calls from text content#41
Doorman11991 merged 1 commit into
masterfrom
fix/issues-36-40

Conversation

@Doorman11991

Copy link
Copy Markdown
Owner

Summary

Closes #40, closes #36.

#40/version returns "Unknown"

Reporter ran /version and got Unknown: /version. Type /help. The command was advertised by the command palette and the help table but never had a handler.

Added case '/version': case '/v': to bin/commands.js. Reads package.json so the value can never drift, prints the description and Node X on platform/arch for support context. /version is now in /help and the README command table.

#36 — qwen2.5-coder:14b spills tool JSON into chat

Reporter pointed Ollama at qwen2.5-coder:14b and asked “what files are in this directory?”. Instead of the tool running, the raw <tool_call>{"name":"shell",...}</tool_call> blob landed in chat.

Root cause: some local-model + Ollama OpenAI-compat combinations emit the tool invocation as text in message.content rather than populating the structured tool_calls field. The agent loop in bin/smallcode.js only checks message.tool_calls, so the call is treated as plain prose.

Added src/tools/tool_call_extractor.js — a defensive recovery layer that runs immediately after the model response is decoded. It detects four shapes and lifts them into the proper tool_calls field:

  • <tool_call>{...}</tool_call> — Hermes / qwen2.5 native template
  • ```json ... ``` and ```tool_call ... ``` fenced blocks
  • A bare leading JSON object/array (whole content is JSON)
  • { "function": { "name", "arguments" } }, { "name", "arguments" }, and { "tool", "args" } body forms

Other niceties:

  • Tolerates trailing-comma JSON (qwen quirk).
  • Filters out calls that reference unknown tool names — the chat output is preferred over inventing calls.
  • Strips the lifted JSON from message.content so the user doesn't see it twice.

Wired into the three response-handling sites that exist today: bin/smallcode.js (interactive agent loop), src/api/index.js (programmatic SDK), and src/session/parallel_executor.js (parallel-step planner). All three already-structured-tool_calls paths continue working unchanged.

Verification

E2E tests in .test-workspace/ (workspace-local, gitignored):

  • tool_call_extractor_test.js — 10 cases including all four shapes, multiple calls per message, unknown-tool rejection, prose passthrough, trailing-comma repair, and the OpenAI-shaped variant. 10/10 pass.
  • version_command_test.js — verifies /version, /v, and that unknown slashes still report "Unknown:". 3/3 pass.

Existing tui_unit_test.js still passes 11/11.

Files

  • src/tools/tool_call_extractor.js — new (168 lines)
  • bin/commands.js/version + /v cases, /help line
  • bin/smallcode.js — extractor call after response.choices[0].message
  • src/api/index.js — same wiring for the SDK path
  • src/session/parallel_executor.js — same wiring for parallel steps
  • README.md/version row in the command table
  • CHANGELOG.md — Unreleased entry

Closes #40, closes #36.

/version (#40): /version and /v slashes now print SmallCode version, description, Node and platform info, sourced from package.json.

Tool extractor (#36): when a model emits a tool invocation as JSON inside message.content (qwen2.5-coder:14b on Ollama, hermes, llama3 GGUFs) instead of structured tool_calls, lift it out automatically. Recognises tool_call tags, fenced JSON, bare JSON, and OpenAI/named-tool/named-args shapes. Tolerates qwen trailing-comma JSON. Conservative — unknown tool names are not extracted. Wired into bin/smallcode.js, src/api/index.js, and src/session/parallel_executor.js.

README + CHANGELOG updated. 13 new E2E test cases (.test-workspace, gitignored).
@Doorman11991
Doorman11991 merged commit 2db8379 into master May 23, 2026
6 checks passed
@Doorman11991
Doorman11991 deleted the fix/issues-36-40 branch May 23, 2026 11:07
Doorman11991 added a commit that referenced this pull request May 23, 2026
Bundles two merged fixes since 1.0.2:

* PR #41 (closes #36, #40): tool-call extractor for qwen2.5-coder + /version slash command

* PR #39: SSRF guard hardening — IPv4-mapped IPv6 alias bypass + browser redirect re-validation
Kothulhu94 pushed a commit to Kothulhu94/smallcode that referenced this pull request May 29, 2026
…orman11991#41)

Closes Doorman11991#40, closes Doorman11991#36.

/version (Doorman11991#40): /version and /v slashes now print SmallCode version, description, Node and platform info, sourced from package.json.

Tool extractor (Doorman11991#36): when a model emits a tool invocation as JSON inside message.content (qwen2.5-coder:14b on Ollama, hermes, llama3 GGUFs) instead of structured tool_calls, lift it out automatically. Recognises tool_call tags, fenced JSON, bare JSON, and OpenAI/named-tool/named-args shapes. Tolerates qwen trailing-comma JSON. Conservative — unknown tool names are not extracted. Wired into bin/smallcode.js, src/api/index.js, and src/session/parallel_executor.js.

README + CHANGELOG updated. 13 new E2E test cases (.test-workspace, gitignored).

Co-authored-by: DanTheMan181 <283874042+Doorman11991@users.noreply.github.com>
Kothulhu94 pushed a commit to Kothulhu94/smallcode that referenced this pull request May 29, 2026
Bundles two merged fixes since 1.0.2:

* PR Doorman11991#41 (closes Doorman11991#36, Doorman11991#40): tool-call extractor for qwen2.5-coder + /version slash command

* PR Doorman11991#39: SSRF guard hardening — IPv4-mapped IPv6 alias bypass + browser redirect re-validation
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The '/version' command in smallcode is not working. Tool use trouble

1 participant