c82f5994 — fix(openai): stop_reason null, zero usage fields, max_tokens forwarding
- streamAdapter: defer message_delta/message_stop to after stream loop
so trailing usage chunks are captured; fill all 4 usage fields
- index.ts: assemble final AssistantMessage at message_stop (not per-block);
apply stop_reason from message_delta; reset partialMessage; post-loop
safety fallback for partial messages
- buildOpenAIRequestBody: accept and forward maxTokens → max_tokens
901628b4 — fix: OpenAI provider deferred MCP tool visibility
- index.ts: prepend deferred MCP tool text list so OpenAI model can discover
and request them via ToolSearchTool
- claude.ts: pass full tools (not filteredTools) to OpenAI path so deferred
tools are searchable
- index.ts: include already-discovered deferred tools in filteredTools so
their schemas are available after ToolSearchTool loads them
Tests added:
- queryModelOpenAI.isolated.ts (674 lines): stop_reason assembly, partialMessage
reset, max_tokens truncation warning, usage tracking, cost tracking
- queryModelOpenAI.runner.ts + .test.ts: isolated subprocess runner (CCP pattern)
- streamAdapter.test.ts: 665→130 lines expanded — deferred finish, trailing
usage, length→max_tokens mapping, full usage field assertions
- formatBriefTimestamp.test.ts: beforeAll/afterAll env save/restore
3602 pass, 0 fail
c82f5994 — fix(openai): stop_reason null, zero usage fields, max_tokens forwarding
- streamAdapter: defer message_delta/message_stop to after stream loop
so trailing usage chunks are captured; fill all 4 usage fields
- index.ts: assemble final AssistantMessage at message_stop (not per-block);
apply stop_reason from message_delta; reset partialMessage; post-loop
safety fallback for partial messages
- buildOpenAIRequestBody: accept and forward maxTokens → max_tokens
901628b4 — fix: OpenAI provider deferred MCP tool visibility
- index.ts: prepend deferred MCP tool text list so OpenAI model can discover
and request them via ToolSearchTool
- claude.ts: pass full tools (not filteredTools) to OpenAI path so deferred
tools are searchable
- index.ts: include already-discovered deferred tools in filteredTools so
their schemas are available after ToolSearchTool loads them
Tests added:
- queryModelOpenAI.isolated.ts (674 lines): stop_reason assembly, partialMessage
reset, max_tokens truncation warning, usage tracking, cost tracking
- queryModelOpenAI.runner.ts + .test.ts: isolated subprocess runner (CCP pattern)
- streamAdapter.test.ts: 665→130 lines expanded — deferred finish, trailing
usage, length→max_tokens mapping, full usage field assertions
- formatBriefTimestamp.test.ts: beforeAll/afterAll env save/restore
3602 pass, 0 fail
loadedGetLanguage 返回类型中 name 字段改为可选,匹配 highlight.js
Language 类型中 name 为 string | undefined 的定义。
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add ImageLimits type and plumb optional limits through the chain:
callMCPTool/callMCPToolWithUrlElicitationRetry -> processMCPResult ->
transformMCPResult -> transformResultContent -> maybeResizeAndDownsampleImageBuffer.
When provided, limits override the module-level defaults
(IMAGE_TARGET_RAW_SIZE, IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT,
API_IMAGE_MAX_BASE64_SIZE) inside maybeResizeAndDownsampleImageBuffer.
When undefined, behavior is unchanged for current callers.
Add _meta preservation in the text-block case of transformResultContent
(only when the caller opts in via includeMeta=true). transformMCPResult
passes includeMeta=true on the tool-result path; the prompt-handler call
site keeps the default false, preserving prior behavior.
Add skipLargeOutput early-return in processMCPResult after the IDE check:
when the caller passes skipLargeOutput=true and the content has no images,
the function returns content directly without large-output handling.
Add unwrap-to-text in processMCPResult for the persisted-content path:
when the large-string format gate is enabled
(MCP_TRUNCATION_PROMPT_OVERRIDE env var, or
tengu_mcp_subagent_prompt Statsig gate), and the content is a single
bare text block (no annotations, no _meta), unwrap to raw text and
switch the format description to 'Plain text'. Default-off; gate-off
behavior is unchanged.
Verified structurally against the 2.1.128 binary: function signatures,
the IDE check, gate logic, _meta-unwrap pattern, and imageLimits
plumbing match this implementation.