Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
f8db04c
fix(core): preserve prompt cache across deferred tool discovery
DragonnZhang Aug 1, 2026
b57a42e
Merge remote-tracking branch 'origin/main' into dragon/deferred-tools…
DragonnZhang Aug 1, 2026
b0af6a3
Merge upstream main into deferred tools fix
DragonnZhang Aug 1, 2026
39bc677
fix(core): harden deferred tool proxy lifecycle
DragonnZhang Aug 1, 2026
4aa15f2
Merge remote-tracking branch 'fork/dragon/deferred-tools-stable-cache…
DragonnZhang Aug 1, 2026
7a40611
chore: merge upstream main into deferred tool cache fix
DragonnZhang Aug 1, 2026
4530c12
chore: merge upstream main into deferred tool cache fix
DragonnZhang Aug 1, 2026
1a37dd4
chore: merge latest upstream main
DragonnZhang Aug 1, 2026
2a52e9f
fix(cli): preserve ACP history cleanup side effects
DragonnZhang Aug 1, 2026
6a8d8a0
Merge branch 'main' into dragon/deferred-tools-stable-cache
yiliang114 Aug 1, 2026
eb41a3f
Merge branch 'main' into dragon/deferred-tools-stable-cache
wenshao Aug 2, 2026
8250af4
test(sdk): align MCP E2E with deferred proxy
DragonnZhang Aug 2, 2026
92996b9
fix(core): harden deferred tool delivery
DragonnZhang Aug 2, 2026
366954b
Merge branch 'main' into dragon/deferred-tools-stable-cache
wenshao Aug 2, 2026
294e4b1
fix(core): restore resumed MCP presentations
DragonnZhang Aug 2, 2026
33c8be5
fix(tools): preserve deferred presentation state
DragonnZhang Aug 2, 2026
b14df23
fix(core): close deferred-presentation review gaps
DragonnZhang Aug 3, 2026
419ac7a
chore: merge main into deferred tool cache branch
DragonnZhang Aug 3, 2026
7acca02
Merge branch 'dragon/deferred-tools-stable-cache' of https://github.c…
qwen-code-dev-bot Aug 3, 2026
d7ac12f
chore: merge main into dragon/deferred-tools-stable-cache
qwen-code-dev-bot Aug 3, 2026
5051be7
chore: resolve latest main conflict
DragonnZhang Aug 3, 2026
0bf42bf
Merge branch 'main' into dragon/deferred-tools-stable-cache
qwen-code-dev-bot Aug 3, 2026
40d0508
Merge branch 'main' into dragon/deferred-tools-stable-cache
wenshao Aug 3, 2026
23e0373
Merge remote-tracking branch 'upstream/main' into HEAD
DragonnZhang Aug 4, 2026
2498b95
chore: merge main to resolve conflicts
DragonnZhang Aug 5, 2026
7a262a7
fix(core): preserve deferred tool identities
DragonnZhang Aug 6, 2026
2019aa4
fix(core): bound deferred schema fallback
DragonnZhang Aug 6, 2026
8152672
Merge branch 'main' into dragon/deferred-tools-stable-cache
qwen-code-dev-bot Aug 6, 2026
dd80709
fix(core): restore deferred schemas after compression
DragonnZhang Aug 7, 2026
8e453b1
chore: merge latest main into deferred tools branch
DragonnZhang Aug 7, 2026
4aff150
Merge remote-tracking branch 'origin/main' into dragon/deferred-tools…
qwen-code-dev-bot Aug 7, 2026
618d799
Merge branch 'dragon/deferred-tools-stable-cache' of https://github.c…
qwen-code-dev-bot Aug 7, 2026
70b6bf7
fix(tools): fail closed on undelivered context
DragonnZhang Aug 7, 2026
7b97d10
Merge main into dragon/deferred-tools-stable-cache
DragonnZhang Aug 7, 2026
76582c1
fix(tools): address deferred proxy review round findings
DragonnZhang Aug 7, 2026
f7a51ab
Merge remote-tracking branch 'origin/main' into dragon/deferred-tools…
Aug 9, 2026
ee4a004
fix(tools): address review round 5 critical findings
Aug 10, 2026
ebb7504
fix(cli): fail closed after reactive compression
DragonnZhang Aug 11, 2026
93739ed
fix(core): keep deferred tool state consistent
DragonnZhang Aug 11, 2026
79d98dc
Merge remote-tracking branch 'upstream/main' into dragon/deferred-too…
DragonnZhang Aug 11, 2026
14e9310
fix(core): preserve resume interruption detection
DragonnZhang Aug 12, 2026
25a6550
chore: merge main into deferred tools branch
DragonnZhang Aug 12, 2026
5922c53
merge: sync upstream main
DragonnZhang Aug 14, 2026
7f82881
fix(core): preserve deferred resume diagnostics
DragonnZhang Aug 14, 2026
1a6a419
merge: sync upstream main
DragonnZhang Aug 16, 2026
be46196
test(cli): align stopped batch loop expectation
DragonnZhang Aug 16, 2026
8b5445a
Merge upstream main into deferred tools cache
DragonnZhang Aug 17, 2026
332a0a5
refactor(core): move deferred catalog into tool search
DragonnZhang Aug 18, 2026
405cc01
Merge branch 'main' into dragon/deferred-tools-stable-cache
DragonnZhang Aug 18, 2026
1a80209
Merge branch 'main' into dragon/deferred-tools-stable-cache
DragonnZhang Aug 18, 2026
e93a3c8
fix(cli): restore client history wrapper for daemon retry strip
DragonnZhang Aug 18, 2026
f039e00
test(cli): retarget settle-gate no-mutation assertions to the client …
DragonnZhang Aug 19, 2026
3475a10
fix(cli): only fail acceptance closed on payload-mutating compression
DragonnZhang Aug 19, 2026
6fb6277
Merge remote-tracking branch 'origin/main' into dragon/deferred-tools…
DragonnZhang Aug 19, 2026
ee5c8bd
fix(core): close the three latest review findings on the deferred proxy
DragonnZhang Aug 19, 2026
c30cac5
fix(core): address the standing review suggestions on the deferred proxy
DragonnZhang Aug 19, 2026
94b297f
fix(core): address remaining standing suggestions on the deferred proxy
DragonnZhang Aug 19, 2026
1ce8cfe
fix(core): settle deferred schema presentations on delivery, not at e…
DragonnZhang Aug 20, 2026
f1fe462
fix(cli): enforce the deferred proxy contract on daemon and headless …
DragonnZhang Aug 20, 2026
b3dc50f
Merge remote-tracking branch 'origin/main' into wt-pr-8276
DragonnZhang Aug 20, 2026
0278e09
fix: tag rebuilt-payload retries and commit presentations only for de…
DragonnZhang Aug 20, 2026
b427953
fix(core): clear proxy-schema ledger when stripping a mixed tool-resu…
DragonnZhang Aug 21, 2026
a211e70
fix: roll back proxy-schema ledger when a tool batch's carrying send …
DragonnZhang Aug 21, 2026
8bc6818
fix: roll back proxy-schema ledger on #executePromptInner send-failur…
DragonnZhang Aug 21, 2026
a473d43
fix(core): make proxy-schema ledger rollback generation-aware across …
DragonnZhang Aug 21, 2026
e9161db
fix(core): roll back proxy-schema ledger on cron and background-notif…
DragonnZhang Aug 21, 2026
7892cbb
fix(cli): strip dropped calls' presentations before batch-level settl…
DragonnZhang Aug 21, 2026
0a33a98
fix: close round-23 proxy-schema presentation gaps on all delivery su…
DragonnZhang Aug 21, 2026
f092355
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 22, 2026
6595384
fix(core): exclude error responses from duplicate provider-id replay …
DragonnZhang Aug 22, 2026
b21f9b1
fix(cli): release replay record on the daemon sequential tool path
DragonnZhang Aug 22, 2026
1bc0373
fix(cli): settle headless presentation ledger at each carrying send b…
DragonnZhang Aug 22, 2026
44608a8
fix(core): let subagent select: re-inspect declared hidden deferred t…
DragonnZhang Aug 22, 2026
cbd2c90
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 22, 2026
a4b8772
fix(core): persist declared tool names across woken agent frames
DragonnZhang Aug 22, 2026
4008c6e
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 23, 2026
6c7007a
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 23, 2026
01de8a9
test(core): pin deferred-retry dedup id-keying that refutes R26-1
DragonnZhang Aug 23, 2026
2607f23
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 23, 2026
cd4e0ce
ci: record cd-cua-driver.yml size growth in .size-baseline
DragonnZhang Aug 23, 2026
d66219d
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 24, 2026
7cba7ed
fix(core): key history replay reseed on the raw provider id of suffix…
DragonnZhang Aug 24, 2026
21088e5
fix(core): gate every deferred tool on the recorded agent declaration…
DragonnZhang Aug 24, 2026
911435b
fix(cli): decode the deferred-batch flush delivery contract like the …
DragonnZhang Aug 24, 2026
8eb61f7
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 24, 2026
7b33238
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 24, 2026
2b2a0c0
Merge remote-tracking branch 'origin/main' into pr-8276
DragonnZhang Aug 25, 2026
95ecc2f
fix(cli): drop merge-duplicated mock properties in session-swap-telem…
DragonnZhang Aug 25, 2026
42eedf3
docs: describe the presentation ledger this branch actually ships
DragonnZhang Aug 26, 2026
2daeed3
fix(core): keep the tool_call bridge reachable under a permissions al…
DragonnZhang Aug 26, 2026
43e6d3e
Merge remote-tracking branch 'origin/main' into dragon/deferred-tools…
DragonnZhang Aug 26, 2026
b204767
Merge upstream/main into dragon/deferred-tools-stable-cache
DragonnZhang Aug 26, 2026
1bb9b90
Merge remote-tracking branch 'origin/main' into dragon/deferred-tools…
DragonnZhang Aug 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/design/2026-07-06-session-start-profiler.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The profiler is enabled only when `QWEN_CODE_PROFILE_SESSION_START=1`.

When enabled, core writes JSONL records under `Storage.getRuntimeBaseDir()/session-start-perf/`. Daily JSONL filenames use the UTC date from the record timestamp. Each record includes a timestamp, `SessionStartSource`, success flag, total duration, bounded stage durations, and small aggregate counts such as history length and rendered snapshot count. The #4748 daemon profiling follow-up adds an optional opaque Session ID when the caller supplies one so this detail record can be joined to the cross-process trace.

The measured stages follow the existing `startChat()` sequence: tool registry warm, resumed deferred-tool reveal scan, deferred reminder setup, initial chat history build, skill reminder dedup seeding, agent reminder dedup seeding, system instruction build, `GeminiChat` construction, orphan tool-use repair, SessionStart hook, optional SessionStart context apply, and `setTools()`.
The measured stages follow the existing `startChat()` sequence: tool registry warm, resumed deferred-tool reveal scan, deferred-tool preload decision, deferred-tool catalog setup, initial chat history build, skill reminder dedup seeding, agent reminder dedup seeding, system instruction build, `GeminiChat` construction, orphan tool-use repair, SessionStart hook, optional SessionStart context apply, and `setTools()`.

## Safety Boundaries

Expand Down
4 changes: 2 additions & 2 deletions docs/design/fork-resume-live-capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ resume, rebuild its executable surface from the current parent session:
- use the current parent's rendered system instruction;
- take the current parent's advertised tool names and resolve their schemas
through the resumed agent's current registry;
- include current MCP, deferred-tool, and Skill reminders on the continuation
turn, while declaring earlier capability listings obsolete;
- include current MCP and Skill reminders on the continuation turn, while
declaring earlier capability listings obsolete;
- leave the task paused when the current parent prompt or tool surface cannot
be reconstructed.

Expand Down
119 changes: 119 additions & 0 deletions docs/design/prompt-cache/deferred-tool-call-stable-schema.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Deferred Tool Catalog in `tool_search`

## Problem

Deferred tools were advertised through startup and lifecycle
`<system-reminder>` messages. That makes the catalog ordinary conversation
history: it can be diluted by a long context, removed by compression, or require
special restoration during resume and compaction. Keeping the deferred set
reachable therefore meant re-injecting catalog text into history whenever a
lifecycle event evicted it.

## Design

The main session exposes two stable bridge tools:

- `tool_search` advertises the current deferred-tool catalog in its dynamic
function description and returns full schemas for selected tools.
- `tool_call` accepts a target tool name and target arguments, then hands the
request to the normal scheduler as that real target.

The catalog is built from the live `ToolRegistry` whenever the provider-facing
`tool_search` declaration is read. Bundled tools and MCP tools are grouped and
sorted. Names and one-line descriptions are JSON quoted; MCP metadata is
explicitly labelled as untrusted data rather than instructions.

`tool_search` remains the schema lookup mechanism. Search results contain the
matched declarations in the existing `<functions>` format, but discovering a
normal deferred tool does not add that tool to the provider declaration list.
An individually oversized schema may still use the existing direct-declaration
fallback, and the search result tells the model to call that tool directly.

```mermaid
flowchart LR
A["tool_search description"] --> B["Live deferred-tool catalog"]
B --> C["tool_search returns selected full schema"]
C --> D["tool_call(name, arguments)"]
D --> E["Resolve live target in ToolRegistry"]
E --> F["Existing scheduler pipeline"]
F --> G["Permissions, validation, hooks, execution, telemetry"]
```

## Lifecycle

The deferred catalog is no longer copied into startup, MCP-change, resume, or
post-compression reminder messages. Compression can discard prior search
results without making the catalog disappear because the current catalog is
part of the `tool_search` declaration on every request. If the model needs a
full schema again, it calls `tool_search` again.

MCP connection changes update the registry. The next declaration read therefore
contains the new catalog without appending synthetic user-history entries or
rewriting the system instruction.

The presentation ledger, unlike the catalog, does follow the active model
context. A delivery surface commits a mark only after the carrying `tool_search`
result enters active history, and rolls that commit back if the send fails
before the push. Surfaces that execute a batch sequentially gate the whole batch
against a snapshot taken before it starts, so a `tool_search` earlier in the
same batch cannot self-authorize a sibling `tool_call`. Every history mutation
that can evict a tool result — compression, `/clear`, resume reload,
rewind/truncation, and stripping an orphaned turn that carried a tool result —
clears the ledger, so an affected tool must be searched again before it can be
routed. Revealed (directly declared) tools are unaffected: their schemas stay in
the function-declaration list regardless of history.

## Execution and safety

`tool_call` is a transport bridge, not a separate executor. Before scheduling,
Qwen Code:

1. validates the bridge envelope;
2. canonicalizes and loads the current target;
3. rejects self-targeting, removed, replaced, directly visible, or otherwise
ineligible targets;
4. retains the resolved target instance; and
5. schedules the request under the real target identity.

The real target continues to own argument validation, permission policy,
confirmation, hooks, cancellation, result truncation, telemetry, and UI
identity. The provider-facing response keeps the original `tool_call` name and
call ID so request/response pairing remains valid.

Reaching the catalog no longer depends on reminder text surviving in history, so
nothing is re-injected after compression or resume. Execution still requires
that the target schema was actually presented to the model: the registry keeps a
session-scoped presentation ledger mapping each proxied tool to the schema
fingerprint `tool_search` delivered, and `tool_call` rejects a target whose mark
is missing or whose fingerprint no longer matches the live schema — issue
#6721's fail-closed gate against routing guessed or stale arguments. This does
not grant access to arbitrary tools: only live, hidden, proxy-eligible deferred
tools with a current presented schema may be targeted.

Subagents and teammates keep their existing direct declaration surface and do
not receive `tool_call`, preserving their tool restrictions. If `tool_search`
is unavailable in the main session, deferred tools continue to use the existing
direct-declaration fallback.

## Cache behavior

Ordinary discovery no longer mutates the provider's function-declaration set:
`tool_search` and `tool_call` remain stable bridge entries. The
`tool_search.description` catalog changes only when the live deferred catalog
changes, which is the intended capability change. Searching for or calling a
tool does not itself rewrite the catalog into conversation history.

## Verification

Tests cover:

- deterministic catalog rendering and live registry updates;
- absence of deferred catalog reminders from startup and lifecycle paths;
- repeated search after a prior schema result;
- `tool_call` normalization, including the presentation-ledger gate, its
batch snapshot, delivery rollback, and ledger clearing across history
mutations;
- rejection of malformed, missing, replaced, or ineligible targets;
- preservation of real-target permissions, hooks, validation, telemetry, and
provider response identity; and
- direct-declaration behavior for subagents and oversized schemas.
22 changes: 10 additions & 12 deletions docs/design/toolsearch-preload-threshold.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ the equivalent gate.

New setting `tools.toolSearch.threshold` (number, percent, default `10`).

At session start (`GeminiClient.startChat`, before the deferred-tools reminder
is resolved), when ToolSearch is registered and the threshold is > 0:
At session start (`GeminiClient.startChat`, before the initial declarations are
built), when ToolSearch is registered and the threshold is > 0:

- Estimate the combined token footprint of every deferred tool schema —
bundled built-ins and MCP alike
Expand All @@ -37,18 +37,16 @@ is resolved), when ToolSearch is registered and the threshold is > 0:
restores the old behavior unconditionally.

Preloaded tools therefore land in the initial declaration list, are filtered
out of the startup deferred-tools reminder, and the declaration list stays
stable for the whole session.
out of the `tool_search` catalog (they are already directly callable), and the
declaration list stays stable for the whole session.

## Decisions

- **Session start only, never `setTools()`.** Revealing a tool the startup
reminder already announced would make `queueAddedMcpToolsReminder` flag it
as "removed", and a mid-session declaration change busts the very cache the
preload exists to protect. Tools from servers that connect later stay
deferred (announced via the added-tools reminder, reachable through
ToolSearch) until the next session start. `/clear` clears the revealed set
and re-runs the decision.
- **Session start only, never `setTools()`.** A mid-session reveal changes the
declaration list and busts the very cache the preload exists to protect.
Tools from servers that connect later stay deferred (advertised in the
`tool_search` catalog, reachable through ToolSearch) until the next session
start. `/clear` clears the revealed set and re-runs the decision.
- **One budget over the whole deferred set, bundled included.** Claude Code's
auto threshold covers MCP/SDK tools only (its built-ins are managed
separately), but it can afford that split: deferred tools are stripped from
Expand All @@ -72,4 +70,4 @@ stable for the whole session.
starts (compression also passes through `startChat`) cannot ratchet the
revealed set past the budget as servers come and go.
- **No preload when ToolSearch is unavailable** — the existing eager-reveal
branch in `resolveDeferredToolsForReminder` already exposes everything.
branch in `resolveDeferredToolsForCatalog` already exposes everything.
68 changes: 52 additions & 16 deletions integration-tests/sdk-typescript/sdk-mcp-server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const MCP_CALCULATE_SUM = 'mcp__sdk-calculator__calculate_sum';
const MCP_REVERSE_STRING = 'mcp__sdk-calculator__reverse_string';
const MCP_MAYBE_FAIL = 'mcp__sdk-error-test__maybe_fail';
const MCP_DELAYED_RESPONSE = 'mcp__sdk-async__delayed_response';
const DEFERRED_TOOL_CALL = 'tool_call';

describe('SDK MCP Server Integration (E2E)', () => {
let helper: SDKTestHelper;
Expand Down Expand Up @@ -153,8 +154,14 @@ describe('SDK MCP Server Integration (E2E)', () => {
if (requestIndex === 1) {
return {
toolCalls: [
fakeToolCall(MCP_CALCULATE_SUM, { a: 25, b: 17 }),
fakeToolCall(MCP_REVERSE_STRING, { text: 'hello world' }),
fakeToolCall(DEFERRED_TOOL_CALL, {
name: MCP_CALCULATE_SUM,
arguments: { a: 25, b: 17 },
}),
fakeToolCall(DEFERRED_TOOL_CALL, {
name: MCP_REVERSE_STRING,
arguments: { text: 'hello world' },
}),
],
};
}
Expand Down Expand Up @@ -186,17 +193,24 @@ describe('SDK MCP Server Integration (E2E)', () => {
}

expect(advertisedToolNames(fakeServer, 1)).toEqual(
expect.arrayContaining([MCP_CALCULATE_SUM, MCP_REVERSE_STRING]),
advertisedToolNames(fakeServer, 0),
);
expect(advertisedToolNames(fakeServer, 1)).toContain(
DEFERRED_TOOL_CALL,
);
expect(advertisedToolNames(fakeServer, 1)).not.toContain(
MCP_CALCULATE_SUM,
);
expect(advertisedToolNames(fakeServer, 1)).not.toContain(
MCP_REVERSE_STRING,
);

const toolResults = findToolResults(messages, MCP_CALCULATE_SUM);
expect(toolResults).toHaveLength(1);
const toolResults = findToolResults(messages, DEFERRED_TOOL_CALL);
expect(toolResults).toHaveLength(2);
expect(toolResults[0]?.isError).toBe(false);
expect(toolResults[0]?.content).toContain('42');
const stringResults = findToolResults(messages, MCP_REVERSE_STRING);
expect(stringResults).toHaveLength(1);
expect(stringResults[0]?.isError).toBe(false);
expect(stringResults[0]?.content).toContain('dlrow olleh');
expect(toolResults[1]?.isError).toBe(false);
expect(toolResults[1]?.content).toContain('dlrow olleh');
expect(
systemMessage?.mcp_servers?.some(
(server) => server.name === 'sdk-calculator',
Expand Down Expand Up @@ -353,7 +367,12 @@ describe('SDK MCP Server Integration (E2E)', () => {
}
: requestIndex === 1
? {
toolCalls: [fakeToolCall(MCP_MAYBE_FAIL, { shouldFail: true })],
toolCalls: [
fakeToolCall(DEFERRED_TOOL_CALL, {
name: MCP_MAYBE_FAIL,
arguments: { shouldFail: true },
}),
],
}
: { content: 'Done.' };
};
Expand All @@ -378,8 +397,16 @@ describe('SDK MCP Server Integration (E2E)', () => {
messages.push(message);
}

expect(advertisedToolNames(fakeServer, 1)).toContain(MCP_MAYBE_FAIL);
const toolResults = findToolResults(messages, MCP_MAYBE_FAIL);
expect(advertisedToolNames(fakeServer, 1)).toEqual(
advertisedToolNames(fakeServer, 0),
);
expect(advertisedToolNames(fakeServer, 1)).toContain(
DEFERRED_TOOL_CALL,
);
expect(advertisedToolNames(fakeServer, 1)).not.toContain(
MCP_MAYBE_FAIL,
);
const toolResults = findToolResults(messages, DEFERRED_TOOL_CALL);
expect(toolResults).toHaveLength(1);
expect(toolResults[0]?.isError).toBe(true);
expect(toolResults[0]?.content).toContain('Tool intentionally failed');
Expand Down Expand Up @@ -432,9 +459,12 @@ describe('SDK MCP Server Integration (E2E)', () => {
: requestIndex === 1
? {
toolCalls: [
fakeToolCall(MCP_DELAYED_RESPONSE, {
delay: 50,
value: 'test_async',
fakeToolCall(DEFERRED_TOOL_CALL, {
name: MCP_DELAYED_RESPONSE,
arguments: {
delay: 50,
value: 'test_async',
},
}),
],
}
Expand All @@ -461,10 +491,16 @@ describe('SDK MCP Server Integration (E2E)', () => {
messages.push(message);
}

expect(advertisedToolNames(fakeServer, 1)).toEqual(
advertisedToolNames(fakeServer, 0),
);
expect(advertisedToolNames(fakeServer, 1)).toContain(
DEFERRED_TOOL_CALL,
);
expect(advertisedToolNames(fakeServer, 1)).not.toContain(
MCP_DELAYED_RESPONSE,
);
const toolResults = findToolResults(messages, MCP_DELAYED_RESPONSE);
const toolResults = findToolResults(messages, DEFERRED_TOOL_CALL);
expect(toolResults).toHaveLength(1);
expect(toolResults[0]?.isError).toBe(false);
expect(toolResults[0]?.content.toLowerCase()).toMatch(/test_async/i);
Expand Down
Loading
Loading