feat: Introduce DetermineCaller for auth without account pooling and make wide_input_strict_output configurable.

This commit is contained in:
CJACK
2026-02-18 23:53:50 +08:00
parent 51c543631b
commit 2dcc230852
9 changed files with 257 additions and 31 deletions

View File

@@ -85,7 +85,8 @@ module.exports = async function handler(req, res) {
const finalPrompt = asString(prep.body.final_prompt);
const thinkingEnabled = toBool(prep.body.thinking_enabled);
const searchEnabled = toBool(prep.body.search_enabled);
const toolNames = extractToolNames(payload.tools);
const toolPolicy = resolveToolcallPolicy(prep.body, payload.tools);
const toolNames = toolPolicy.toolNames;
if (!model || !leaseID || !deepseekToken || !powHeader || !completionPayload) {
writeOpenAIError(res, 500, 'invalid vercel prepare response');
@@ -156,7 +157,8 @@ module.exports = async function handler(req, res) {
let currentType = thinkingEnabled ? 'thinking' : 'text';
let thinkingText = '';
let outputText = '';
const toolSieveEnabled = toolNames.length > 0;
const toolSieveEnabled = toolPolicy.toolSieveEnabled;
const emitEarlyToolDeltas = toolPolicy.emitEarlyToolDeltas;
const toolSieveState = createToolSieveState();
let toolCallsEmitted = false;
const streamToolCallIDs = new Map();
@@ -297,6 +299,9 @@ module.exports = async function handler(req, res) {
const events = processToolSieveChunk(toolSieveState, p.text, toolNames);
for (const evt of events) {
if (evt.type === 'tool_call_deltas' && Array.isArray(evt.deltas) && evt.deltas.length > 0) {
if (!emitEarlyToolDeltas) {
continue;
}
toolCallsEmitted = true;
sendDeltaFrame({ tool_calls: formatIncrementalToolCallDeltas(evt.deltas, streamToolCallIDs) });
continue;
@@ -407,6 +412,37 @@ function relayPreparedFailure(res, prep) {
writeOpenAIError(res, prep.status || 500, 'vercel prepare failed');
}
function resolveToolcallPolicy(prepBody, payloadTools) {
const preparedToolNames = normalizePreparedToolNames(prepBody && prepBody.tool_names);
const toolNames = preparedToolNames.length > 0 ? preparedToolNames : extractToolNames(payloadTools);
const featureMatchEnabled = boolDefaultTrue(prepBody && prepBody.toolcall_feature_match);
const emitEarlyToolDeltas = boolDefaultTrue(prepBody && prepBody.toolcall_early_emit_high);
return {
toolNames,
toolSieveEnabled: toolNames.length > 0 && featureMatchEnabled,
emitEarlyToolDeltas,
};
}
function normalizePreparedToolNames(v) {
if (!Array.isArray(v) || v.length === 0) {
return [];
}
const out = [];
for (const item of v) {
const name = asString(item);
if (!name) {
continue;
}
out.push(name);
}
return out;
}
function boolDefaultTrue(v) {
return v !== false;
}
async function safeReadText(resp) {
if (!resp) {
return '';
@@ -933,4 +969,7 @@ module.exports.__test = {
extractContentRecursive,
shouldSkipPath,
asString,
resolveToolcallPolicy,
normalizePreparedToolNames,
boolDefaultTrue,
};

View File

@@ -10,10 +10,50 @@ const {
flushToolSieve,
} = require('./helpers/stream-tool-sieve');
const { parseChunkForContent } = handler.__test;
const {
parseChunkForContent,
resolveToolcallPolicy,
normalizePreparedToolNames,
boolDefaultTrue,
} = handler.__test;
test('chat-stream exposes parser test hooks', () => {
assert.equal(typeof parseChunkForContent, 'function');
assert.equal(typeof resolveToolcallPolicy, 'function');
});
test('resolveToolcallPolicy defaults to feature-match + early emit when prepare flags missing', () => {
const policy = resolveToolcallPolicy(
{},
[{ type: 'function', function: { name: 'read_file', parameters: { type: 'object' } } }],
);
assert.deepEqual(policy.toolNames, ['read_file']);
assert.equal(policy.toolSieveEnabled, true);
assert.equal(policy.emitEarlyToolDeltas, true);
});
test('resolveToolcallPolicy respects prepare flags and prepared tool names', () => {
const policy = resolveToolcallPolicy(
{
tool_names: [' prepped_tool ', '', null],
toolcall_feature_match: false,
toolcall_early_emit_high: false,
},
[{ type: 'function', function: { name: 'fallback_tool', parameters: { type: 'object' } } }],
);
assert.deepEqual(policy.toolNames, ['prepped_tool']);
assert.equal(policy.toolSieveEnabled, false);
assert.equal(policy.emitEarlyToolDeltas, false);
});
test('normalizePreparedToolNames filters empty values', () => {
assert.deepEqual(normalizePreparedToolNames([' a ', '', null, 'b']), ['a', 'b']);
});
test('boolDefaultTrue keeps false only when explicitly false', () => {
assert.equal(boolDefaultTrue(false), false);
assert.equal(boolDefaultTrue(true), true);
assert.equal(boolDefaultTrue(undefined), true);
});
test('parseChunkForContent keeps split response/content fragments inside response array', () => {