Skip to content

Recover mixed DeepSeek DSML tool calls - #37

Merged
senamakel merged 5 commits into
mainfrom
issue/204
Sep 30, 2026
Merged

senamakel merged 5 commits into
mainfrom
issue/204

Conversation

@senamakel

Copy link
Copy Markdown
Member

Summary

Recover tool calls in unterminated text <tool_call> blocks when DeepSeek emits JSON arguments followed by DSML parameter metadata, and preserve calls whose name remains in their JSON object. JSON is parsed before DSML framing is inspected, so tag-like strings inside arguments remain data. Regression coverage includes the reported </script> payload and a following DSML invoke.

Closes tinyhumansai/tinyagents#204

Validation

  • cargo test --manifest-path vendor/tinytools/Cargo.toml -p tinytools-agent — passed (374 tests)
  • cargo fmt --manifest-path vendor/tinytools/Cargo.toml --all -- --check — passed
  • cargo clippy --manifest-path vendor/tinytools/Cargo.toml -p tinytools-agent --lib --all-features -- -D warnings — passed
  • cargo clippy --manifest-path vendor/tinytools/Cargo.toml -p tinytools-agent --all-targets --all-features -- -D warnings — blocked by the pre-existing manual_assert_eq lint in crates/tinytools-agent/src/parse/test/regressions.rs:130

Co-authored-by: Medulla <medulla@tinyhumans.ai>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-30T07:13:55.765891Z 0e1f94c New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

  • Run on-demand review

This review includes 2 billable files and costs up to $0.50.

Or wait 28 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 415d81f5-64a4-43b8-bd22-7d5141c41874

📥 Commits

Reviewing files that changed from the base of the PR and between 15ad9df and 0e1f94c.

📒 Files selected for processing (2)
  • crates/tinytools-agent/src/parse/grammar/tagged.rs
  • crates/tinytools-agent/src/parse/test/tagged.rs

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e03cef21f6

ℹ️ 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".

Comment thread crates/tinytools-agent/src/parse/grammar/tagged.rs
Comment thread crates/tinytools-agent/src/parse/grammar/tagged.rs Outdated
@tinysweeper

tinysweeper Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

Tiny Sweeper reviewed this change across 6 lane(s) and found 0 active actionable finding(s). Detailed lane evidence and any incomplete work are listed below.

State: Incomplete
Priority: none
Reviewed head: 0e1f94c7a38e
Updated: 1790753461 (Unix time)

Review snapshot

Change surface Files Review signal Count
Production 1 Active findings 0
Tests 1 Noted findings 0
Documentation 0 Resolved findings 0
Configuration 0 Pending checks/questions 5

Completeness: Incomplete
Test assessment: No supported feature-to-test mapping was available; this does not mean tests are absent or passed.

What changed

The review could not produce a supported behavioral summary; inspect the cited changed surface and lane details below.

Features

None identified with supported citations.

Tests

No supported feature-to-test mapping was produced. Test execution is not inferred.

  • Unreviewed: tinysweeper/tests

Findings

No active actionable findings.

Could not review: crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs, tinysweeper/tests

Before merge

  • Complete the critique review for crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs.
  • Complete the security review for crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs.
  • Complete the tests review for tinysweeper/tests.

How this fits together

flowchart LR
  n0["..._dsml_invoke_carries_its_name_in_the_body<br/>changed"]:::changed
  n1["..._block_does_not_swallow_the_call_after_it<br/>changed"]:::changed
  n2["...ed_invoke_after_a_complete_malformed_body<br/>changed"]:::changed
  n3["...sed_tag_with_balanced_json_still_recovers<br/>changed"]:::changed
  n4["parse_known"]:::impacted
  n5["parse_tool_calls"]:::impacted
  n6["probe_decided"]:::impacted
  n7["parse"]:::impacted
  n8["next_opener"]:::impacted
  n9["ParsedToolCall"]:::impacted
  n0 -->|calls| n5
  n0 -->|tests| n5
  n0 -->|uses| n7
  n1 -->|calls| n4
  n2 -->|calls| n4
  n3 -->|calls| n7
  n4 -->|uses| n7
  n5 -->|uses| n9
  n6 -->|calls| n8
  n7 -->|calls| n5
  n7 -->|tests| n5
  n7 -->|uses| n9
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading
Agent review details

critique

  • Conclusion: Neutral
  • Scope reviewed: incomplete; unanswered: crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs
  • Lane summary: Reviewed 0 files; 0 findings. 2 files could not be reviewed: crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs.

security

  • Conclusion: Neutral
  • Scope reviewed: incomplete; unanswered: crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs
  • Lane summary: Reviewed 0 files; 0 findings. 2 files could not be reviewed: crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs.

tests

  • Conclusion: Neutral
  • Scope reviewed: incomplete; unanswered: tinysweeper/tests
  • Lane summary: No reviewer could be consulted.

commits

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: Nothing sensitive found in what this pull request commits.

description

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: The PR description accurately describes the change: tinytools-agent's DSML parser now recovers tool calls from unterminated text `<tool_call>` blocks by parsing JSON before inspecting DSML framing, handles an inline name inside the JSON object, and adds regression tests including the reported `</script>` payload. The change looks sound and the reported test, fmt, and clippy results are consistent with the diff. _Memory was unavailable (model: cortex: v1/recall: timed out after 10s), so this review ran without it._

e2e

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: No end-to-end harness in this repository: no e2e test files and no e2e workflow.
Evidence and run details
  • Models: ladder/vectors, deepseek/deepseek-v4-flash
  • Spend: $0.001204
  • Tokens: 10540 input · 3827 output · 2526 cached · 612 embedding
Head State Pass summary
0e1f94c7a38e incomplete 0 active finding(s), 0 resolved finding(s) (at 1790753461)

tinysweeper 0.1.0

@senamakel senamakel self-assigned this Sep 30, 2026
senamakel and others added 4 commits September 30, 2026 09:54
When a DSML tool call uses an inline name but no explicit name parameter, the recovery loop was incorrectly advancing the cursor past the JSON value and scanning later narrative text for additional calls. This caused spurious extra calls to be extracted from prose that happened to contain JSON-like content. The fix stops the loop after the first call when no name match is present, and also applies the `from_call_object` helper to properly decode stringified and aliased arguments.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
The cursor offset was incorrectly split across two lines, causing a syntax error in the recovery logic for DSML tool calls. This change consolidates the expression onto a single line to ensure correct parsing and offset computation.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
@senamakel
senamakel merged commit 823d260 into main Sep 30, 2026
5 checks passed
@senamakel
senamakel deleted the issue/204 branch September 30, 2026 07:09

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0e1f94c7a3

ℹ️ 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".

let mut calls = Vec::new();
let mut cursor = 0;
while cursor < after.len() {
let Some((arguments, json_end)) = extract_first_json_value_with_end(&after[cursor..])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Stop DSML recovery at the group terminator

When a recovered call is followed by </|DSML| calls>, this loop does not treat that marker as a boundary: extract_first_json_value_with_end scans through it and any following narrative for another JSON value. If later prose or an example contains JSON followed by a matching DSML name-parameter fragment, that value is returned as another executable call and the intervening text is removed. Bound each extraction to the first DSML_CALLS_CLOSE_RE match so recovery cannot dispatch content outside the terminated call group.

Useful? React with 👍 / 👎.

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tinysweeper found nothing blocking, but could not review everything, so this is not an approval: crates/tinytools-agent/src/parse/grammar/tagged.rs, crates/tinytools-agent/src/parse/test/tagged.rs, tinysweeper/tests.

             $0.0012 · 10,540 in / 3,827 out · 2,526 cached (24%) · ladder/vectors, deepseek/deepseek-v4-flash · 612 embedded
description: $0.0002 · 5,980 in  / 99 out    · 2,014 cached (34%) · deepseek/deepseek-v4-flash

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DeepSeek DSML control tokens leak into text-dialect tool calls; the call is dropped without a diagnostic

1 participant