mirror of
https://github.com/wu736139669/hapi.git
synced 2026-08-05 06:24:37 +00:00
fix: omit reasoning summary for codex spark subagents (#594)
This commit is contained in:
@@ -214,7 +214,7 @@ describe('AcpSdkBackend', () => {
|
||||
});
|
||||
|
||||
it('emits turn_complete after trailing tool updates from the same turn', async () => {
|
||||
backendStatics.UPDATE_QUIET_PERIOD_MS = 8;
|
||||
backendStatics.UPDATE_QUIET_PERIOD_MS = 25;
|
||||
backendStatics.UPDATE_DRAIN_TIMEOUT_MS = 200;
|
||||
backendStatics.PRE_PROMPT_UPDATE_QUIET_PERIOD_MS = 1;
|
||||
backendStatics.PRE_PROMPT_UPDATE_DRAIN_TIMEOUT_MS = 50;
|
||||
@@ -254,7 +254,7 @@ describe('AcpSdkBackend', () => {
|
||||
status: 'in_progress'
|
||||
}
|
||||
});
|
||||
}, 3);
|
||||
}, 1);
|
||||
|
||||
setTimeout(() => {
|
||||
backendInternal.handleSessionUpdate({
|
||||
@@ -266,7 +266,7 @@ describe('AcpSdkBackend', () => {
|
||||
rawOutput: { ok: true }
|
||||
}
|
||||
});
|
||||
}, 6);
|
||||
}, 2);
|
||||
|
||||
return { stopReason: 'end_turn' };
|
||||
},
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { EnhancedMode } from '../loop';
|
||||
import {
|
||||
buildThreadStartParams,
|
||||
buildTurnStartParams,
|
||||
codexCollaborationSpawnAgentInstructions
|
||||
codexCollaborationSpawnAgentInstructions,
|
||||
supportsReasoningSummary
|
||||
} from './appServerConfig';
|
||||
import { codexSystemPrompt } from './systemPrompt';
|
||||
|
||||
@@ -123,18 +125,100 @@ describe('appServerConfig', () => {
|
||||
expect(params.approvalPolicy).toBe('never');
|
||||
expect(params.sandboxPolicy).toEqual({ type: 'readOnly' });
|
||||
expect(params.effort).toBe('high');
|
||||
expect(params.summary).toBe('detailed');
|
||||
expect(params.summary).toBeUndefined();
|
||||
expect(params.collaborationMode).toEqual({
|
||||
mode: 'default',
|
||||
settings: {
|
||||
model: 'o3',
|
||||
reasoning_effort: 'high',
|
||||
developer_instructions: withCollaborationInstructions(codexSystemPrompt)
|
||||
}
|
||||
});
|
||||
expect(params.model).toBeUndefined();
|
||||
});
|
||||
|
||||
it('omits reasoning summary for models that do not support it', () => {
|
||||
const params = buildTurnStartParams({
|
||||
threadId: 'thread-1',
|
||||
message: 'hello',
|
||||
cwd: '/workspace/project',
|
||||
mode: {
|
||||
permissionMode: 'default',
|
||||
model: 'gpt-5.3-codex-spark',
|
||||
modelReasoningEffort: 'high',
|
||||
collaborationMode: 'default'
|
||||
}
|
||||
});
|
||||
|
||||
expect(params.effort).toBe('high');
|
||||
expect(params.summary).toBeUndefined();
|
||||
expect(params.collaborationMode).toEqual({
|
||||
mode: 'default',
|
||||
settings: {
|
||||
model: 'gpt-5.3-codex-spark',
|
||||
developer_instructions: withCollaborationInstructions(codexSystemPrompt)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('detects namespaced models that do not support reasoning summary', () => {
|
||||
const params = buildTurnStartParams({
|
||||
threadId: 'thread-1',
|
||||
message: 'hello',
|
||||
cwd: '/workspace/project',
|
||||
mode: {
|
||||
permissionMode: 'default',
|
||||
model: 'codex/gpt-5.3-codex-spark',
|
||||
modelReasoningEffort: 'high',
|
||||
collaborationMode: 'default'
|
||||
}
|
||||
});
|
||||
|
||||
expect(params.effort).toBe('high');
|
||||
expect(params.summary).toBeUndefined();
|
||||
});
|
||||
|
||||
it('normalizes reasoning summary model support checks', () => {
|
||||
expect(supportsReasoningSummary(' Codex/GPT-5.3-CODEX-SPARK ')).toBe(false);
|
||||
expect(supportsReasoningSummary('gpt-5.5')).toBe(true);
|
||||
expect(supportsReasoningSummary(undefined)).toBe(true);
|
||||
});
|
||||
|
||||
it('omits reasoning summary for non-collaboration turns on unsupported models', () => {
|
||||
const params = buildTurnStartParams({
|
||||
threadId: 'thread-1',
|
||||
message: 'hello',
|
||||
cwd: '/workspace/project',
|
||||
mode: {
|
||||
permissionMode: 'default',
|
||||
model: 'gpt-5.3-codex-spark',
|
||||
modelReasoningEffort: 'high'
|
||||
} as EnhancedMode
|
||||
});
|
||||
|
||||
expect(params.effort).toBe('high');
|
||||
expect(params.summary).toBeUndefined();
|
||||
expect(params.model).toBe('gpt-5.3-codex-spark');
|
||||
expect(params.collaborationMode).toBeUndefined();
|
||||
});
|
||||
|
||||
it('keeps reasoning summary for non-collaboration turns on supported models', () => {
|
||||
const params = buildTurnStartParams({
|
||||
threadId: 'thread-1',
|
||||
message: 'hello',
|
||||
cwd: '/workspace/project',
|
||||
mode: {
|
||||
permissionMode: 'default',
|
||||
model: 'o3',
|
||||
modelReasoningEffort: 'high'
|
||||
} as EnhancedMode
|
||||
});
|
||||
|
||||
expect(params.effort).toBe('high');
|
||||
expect(params.summary).toBe('detailed');
|
||||
expect(params.model).toBe('o3');
|
||||
expect(params.collaborationMode).toBeUndefined();
|
||||
});
|
||||
|
||||
it('puts collaboration mode in turn params with model settings', () => {
|
||||
const params = buildTurnStartParams({
|
||||
threadId: 'thread-1',
|
||||
@@ -152,7 +236,6 @@ describe('appServerConfig', () => {
|
||||
mode: 'plan',
|
||||
settings: {
|
||||
model: 'o3',
|
||||
reasoning_effort: 'high',
|
||||
developer_instructions: withCollaborationInstructions(codexSystemPrompt)
|
||||
}
|
||||
});
|
||||
@@ -189,6 +272,7 @@ describe('appServerConfig', () => {
|
||||
expect(instructions).toContain('If you call spawn_agent with fork_context: true');
|
||||
expect(instructions).toContain('do not set agent_type, model, or reasoning_effort');
|
||||
expect(instructions).toContain('omit fork_context or set fork_context: false');
|
||||
expect(instructions).toContain('Do not rely on parent turn reasoning settings for spawned agents');
|
||||
});
|
||||
|
||||
it('rejects collaboration mode payloads without a resolved model', () => {
|
||||
|
||||
@@ -14,9 +14,14 @@ import { resolveCodexPermissionModeConfig } from './permissionModeConfig';
|
||||
export const codexCollaborationSpawnAgentInstructions = [
|
||||
'Codex sub-agent spawning rules:',
|
||||
'- If you call spawn_agent with fork_context: true, do not set agent_type, model, or reasoning_effort; full-history forked agents inherit these values from the parent.',
|
||||
'- If you need a specific agent_type, model, or reasoning_effort, omit fork_context or set fork_context: false, and include only the necessary context in the message.'
|
||||
'- If you need a specific agent_type, model, or reasoning_effort, omit fork_context or set fork_context: false, and include only the necessary context in the message.',
|
||||
'- Do not rely on parent turn reasoning settings for spawned agents; only set reasoning_effort on spawn_agent when the chosen child model supports it.'
|
||||
].join('\n');
|
||||
|
||||
const MODELS_WITHOUT_REASONING_SUMMARY = new Set([
|
||||
'gpt-5.3-codex-spark'
|
||||
]);
|
||||
|
||||
function resolveApprovalPolicy(mode: EnhancedMode): ApprovalPolicy {
|
||||
return resolveCodexPermissionModeConfig(mode.permissionMode).approvalPolicy;
|
||||
}
|
||||
@@ -42,6 +47,13 @@ function resolveSandboxPolicyOverride(value: CodexCliOverrides['sandbox'] | unde
|
||||
}
|
||||
}
|
||||
|
||||
export function supportsReasoningSummary(model: string | undefined): boolean {
|
||||
const normalized = model?.trim().toLowerCase();
|
||||
if (!normalized) return true;
|
||||
const modelName = normalized.split('/').pop() ?? normalized;
|
||||
return !MODELS_WITHOUT_REASONING_SUMMARY.has(modelName);
|
||||
}
|
||||
|
||||
function buildMcpServerConfig(mcpServers: McpServersConfig): Record<string, unknown> {
|
||||
const config: Record<string, unknown> = {};
|
||||
|
||||
@@ -151,13 +163,16 @@ export function buildTurnStartParams(args: {
|
||||
params.sandboxPolicy = sandboxPolicy;
|
||||
}
|
||||
|
||||
if (args.mode?.modelReasoningEffort) {
|
||||
params.effort = args.mode.modelReasoningEffort;
|
||||
params.summary = 'detailed';
|
||||
}
|
||||
|
||||
const collaborationMode = args.mode?.collaborationMode;
|
||||
const model = args.overrides?.model ?? args.mode?.model;
|
||||
|
||||
if (args.mode?.modelReasoningEffort) {
|
||||
params.effort = args.mode.modelReasoningEffort;
|
||||
if (!collaborationMode && supportsReasoningSummary(model)) {
|
||||
params.summary = 'detailed';
|
||||
}
|
||||
}
|
||||
|
||||
if (collaborationMode) {
|
||||
if (!model) {
|
||||
throw new Error(`Collaboration mode '${collaborationMode}' requires a resolved model`);
|
||||
@@ -167,7 +182,6 @@ export function buildTurnStartParams(args: {
|
||||
mode: collaborationMode,
|
||||
settings: {
|
||||
model,
|
||||
...(args.mode?.modelReasoningEffort ? { reasoning_effort: args.mode.modelReasoningEffort } : {}),
|
||||
developer_instructions: appendCollaborationInstructions(developerInstructions)
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user