diff --git a/agent-run-gateway.mjs b/agent-run-gateway.mjs index 6029249..d5a5306 100644 --- a/agent-run-gateway.mjs +++ b/agent-run-gateway.mjs @@ -155,7 +155,7 @@ async function validateToolGatewayResult({ result, validation, cwd }) { return { expectedFiles: checks }; } -function withRunMetadata(userMessage, { toolMode = 'chat', taskType = null, forceGoose = false } = {}) { +function withRunMetadata(userMessage, { toolMode = 'chat', taskType = null, forceDeepReasoning = false } = {}) { const message = (userMessage && typeof userMessage === 'object' && !Array.isArray(userMessage)) ? { ...userMessage } : { value: userMessage }; @@ -168,7 +168,7 @@ function withRunMetadata(userMessage, { toolMode = 'chat', taskType = null, forc : {}), toolMode: normalizeAgentRunToolMode(toolMode), ...(taskType ? { taskType } : {}), - ...(forceGoose ? { forceGoose: true } : {}), + ...(forceDeepReasoning ? { forceDeepReasoning: true } : {}), }; return { ...message, metadata }; } @@ -185,7 +185,7 @@ function getRunOptionsFromMessage(userMessage) { return { toolMode, taskType: normalizeTaskType(runMetadata?.taskType ?? metadata?.taskType), - forceGoose: runMetadata?.forceGoose === true || metadata?.forceGoose === true, + forceDeepReasoning: runMetadata?.forceDeepReasoning === true || metadata?.forceDeepReasoning === true, validation: normalizeToolGatewayValidation(runMetadata?.validation ?? metadata?.toolGatewayValidation), }; } @@ -289,7 +289,7 @@ export function createAgentRunGateway({ userMessage, toolMode = 'chat', taskType = null, - forceGoose = false, + forceDeepReasoning = false, }) { const normalizedRequestId = String(requestId ?? '').trim(); if (!normalizedRequestId) { @@ -308,7 +308,7 @@ export function createAgentRunGateway({ const runMessage = withRunMetadata(userMessage, { toolMode: normalizedToolMode, taskType: normalizedTaskType, - forceGoose, + forceDeepReasoning, }); await pool.query( `INSERT INTO h5_agent_runs @@ -329,7 +329,7 @@ export function createAgentRunGateway({ sessionId: sessionId || null, toolMode: normalizedToolMode, taskType: normalizedTaskType, - forceGoose: Boolean(forceGoose), + forceDeepReasoning: Boolean(forceDeepReasoning), }); if (autoDispatch) dispatchRun(runId); return projectRun(await getRunById(runId)); @@ -391,7 +391,7 @@ export function createAgentRunGateway({ const userMessage = safeJsonParse(row.user_message_json, {}); const runOptions = getRunOptionsFromMessage(userMessage); const toolGatewayStatus = toolGateway?.getStatus ? toolGateway.getStatus() : null; - if (!runOptions.forceGoose && directChatService?.canHandle?.({ + if (!runOptions.forceDeepReasoning && directChatService?.canHandle?.({ sessionId: row.agent_session_id ?? null, toolMode: runOptions.toolMode, userMessage, @@ -467,7 +467,7 @@ export function createAgentRunGateway({ let sessionId = row.agent_session_id ?? null; if (isDirectChatSessionId(sessionId)) { - await appendEvent(runId, 'direct_session_escalated_to_goose', { + await appendEvent(runId, 'direct_session_escalated_to_deep_reasoning', { previousSessionId: sessionId, }); sessionId = null; diff --git a/agent-run-gateway.test.mjs b/agent-run-gateway.test.mjs index 23fc675..5079173 100644 --- a/agent-run-gateway.test.mjs +++ b/agent-run-gateway.test.mjs @@ -263,10 +263,10 @@ test('agent run uses direct chat service for eligible chat messages', async () = userAuth: {}, tkmindProxy: { async startSessionForUser() { - assert.fail('goose session should not start for direct chat'); + assert.fail('backend session should not start for direct chat'); }, async submitSessionReplyForUser() { - assert.fail('goose reply should not be submitted for direct chat'); + assert.fail('backend reply should not be submitted for direct chat'); }, }, directChatService: { @@ -301,7 +301,7 @@ test('agent run uses direct chat service for eligible chat messages', async () = assert.ok(pool.events.some((event) => event.eventType === 'direct_chat_completed')); }); -test('agent run escalates direct sessions to a new goose session when forced', async () => { +test('agent run escalates direct sessions to a new backend session when forced', async () => { const pool = createFakePool(); const submitted = []; const gateway = createAgentRunGateway({ @@ -309,7 +309,7 @@ test('agent run escalates direct sessions to a new goose session when forced', a tkmindProxy: { async startSessionForUser(userId) { assert.equal(userId, 'user-1'); - return { id: 'goose-session-1' }; + return { id: 'deep-session-1' }; }, async submitSessionReplyForUser(userId, sessionId, requestId, userMessage, options = {}) { submitted.push({ userId, sessionId, requestId, userMessage, options }); @@ -320,15 +320,15 @@ test('agent run escalates direct sessions to a new goose session when forced', a const run = await gateway.createRun('user-1', { sessionId: 'h5direct_existing', - requestId: 'req-force-goose', + requestId: 'req-force-deep', userMessage: { role: 'user', content: [{ type: 'text', text: '帮我生成页面 public/a.html' }] }, - forceGoose: true, + forceDeepReasoning: true, }); await waitFor(() => pool.runs.get(run.id)?.status === 'succeeded'); - assert.equal(pool.runs.get(run.id).agent_session_id, 'goose-session-1'); - assert.equal(submitted[0].sessionId, 'goose-session-1'); - assert.ok(pool.events.some((event) => event.eventType === 'direct_session_escalated_to_goose')); + assert.equal(pool.runs.get(run.id).agent_session_id, 'deep-session-1'); + assert.equal(submitted[0].sessionId, 'deep-session-1'); + assert.ok(pool.events.some((event) => event.eventType === 'direct_session_escalated_to_deep_reasoning')); }); test('agent run with code tool mode starts and submits with code policy', async () => { @@ -369,7 +369,7 @@ test('agent run with code tool mode starts and submits with code policy', async assert.equal(submitted[0].userMessage.metadata.memindRun.toolMode, 'code'); }); -test('agent run with enabled tool gateway dispatches code runs outside goose session', async () => { +test('agent run with enabled tool gateway dispatches code runs outside backend session', async () => { const pool = createFakePool(); const jobs = []; const gateway = createAgentRunGateway({ @@ -382,10 +382,10 @@ test('agent run with enabled tool gateway dispatches code runs outside goose ses }, tkmindProxy: { async startSessionForUser() { - assert.fail('goose session should not start for external tool gateway run'); + assert.fail('backend session should not start for external tool gateway run'); }, async submitSessionReplyForUser() { - assert.fail('goose reply should not be submitted for external tool gateway run'); + assert.fail('backend reply should not be submitted for external tool gateway run'); }, }, toolGateway: { @@ -434,10 +434,10 @@ test('agent run validates expected tool gateway artifacts before succeeding', as }, tkmindProxy: { async startSessionForUser() { - assert.fail('goose session should not start for external tool gateway run'); + assert.fail('backend session should not start for external tool gateway run'); }, async submitSessionReplyForUser() { - assert.fail('goose reply should not be submitted for external tool gateway run'); + assert.fail('backend reply should not be submitted for external tool gateway run'); }, }, toolGateway: { @@ -505,10 +505,10 @@ test('agent run fails non-retryably when tool gateway artifact validation fails' }, tkmindProxy: { async startSessionForUser() { - assert.fail('goose session should not start for external tool gateway run'); + assert.fail('backend session should not start for external tool gateway run'); }, async submitSessionReplyForUser() { - assert.fail('goose reply should not be submitted for external tool gateway run'); + assert.fail('backend reply should not be submitted for external tool gateway run'); }, }, toolGateway: { diff --git a/agent-run-routes.mjs b/agent-run-routes.mjs index 0234d39..ab5ee5a 100644 --- a/agent-run-routes.mjs +++ b/agent-run-routes.mjs @@ -56,7 +56,7 @@ export function createPostAgentRunsHandler({ const userMessage = request.body?.user_message ?? null; const rawToolMode = request.body?.tool_mode ?? request.body?.toolMode ?? 'chat'; const taskType = String(request.body?.task_type ?? request.body?.taskType ?? '').trim() || null; - const forceGoose = request.body?.force_goose === true || request.body?.forceGoose === true; + const forceDeepReasoning = request.body?.force_deep_reasoning === true || request.body?.forceDeepReasoning === true; if (!requestId) { response.status(400).json({ message: '缺少 request_id' }); return; @@ -111,7 +111,7 @@ export function createPostAgentRunsHandler({ userMessage, toolMode, taskType, - ...(forceGoose ? { forceGoose: true } : {}), + ...(forceDeepReasoning ? { forceDeepReasoning: true } : {}), }); response.status(202).json({ run }); } catch (err) { diff --git a/agent-run-routes.test.mjs b/agent-run-routes.test.mjs index d3cc039..bc5c74d 100644 --- a/agent-run-routes.test.mjs +++ b/agent-run-routes.test.mjs @@ -100,7 +100,7 @@ test('POST /agent/runs creates a run and returns 202', async () => { ]); }); -test('POST /agent/runs forwards force_goose to the run gateway', async () => { +test('POST /agent/runs forwards deep reasoning flag to the run gateway', async () => { const created = []; const handler = createPostAgentRunsHandler({ userAuth: { @@ -111,7 +111,7 @@ test('POST /agent/runs forwards force_goose to the run gateway', async () => { agentRunGateway: { async createRun(userId, payload) { created.push({ userId, payload }); - return { id: 'run-goose', status: 'queued' }; + return { id: 'run-deep', status: 'queued' }; }, }, }); @@ -121,16 +121,16 @@ test('POST /agent/runs forwards force_goose to the run gateway', async () => { { currentUser: { id: 'user-1' }, body: { - request_id: 'req-goose', + request_id: 'req-deep', user_message: { role: 'user', content: [{ type: 'text', text: 'hello' }] }, - force_goose: true, + force_deep_reasoning: true, }, }, res, ); assert.equal(res.statusCode, 202); - assert.equal(created[0].payload.forceGoose, true); + assert.equal(created[0].payload.forceDeepReasoning, true); }); test('POST /agent/runs accepts explicit code tool mode and task type', async () => { diff --git a/direct-chat-service.mjs b/direct-chat-service.mjs index 0686568..9e6bc05 100644 --- a/direct-chat-service.mjs +++ b/direct-chat-service.mjs @@ -12,7 +12,7 @@ export function isDirectChatSessionId(sessionId) { return String(sessionId ?? '').startsWith(DIRECT_CHAT_SESSION_PREFIX); } -const GOOSE_REQUIRED_PATTERNS = [ +const TASK_EXECUTION_REQUIRED_PATTERNS = [ /\b(public\/[^\s"'<>]+\.html)\b/i, /\b(html|h5|web\s?page|landing\s?page|microsite|docx|word)\b/i, /\b(write|create|generate|publish|download|export|save|edit)\b.{0,40}\b(file|page|html|docx|word|asset)\b/i, @@ -99,9 +99,9 @@ function isTextOnlyUserMessage(message) { }); } -function requiresGooseExecution(message) { +function requiresTaskExecution(message) { const text = `${messageText(message)}\n${assistantFacingText(message)}`.trim(); - return GOOSE_REQUIRED_PATTERNS.some((pattern) => pattern.test(text)); + return TASK_EXECUTION_REQUIRED_PATTERNS.some((pattern) => pattern.test(text)); } function renderMemoryLines(memories) { @@ -181,7 +181,7 @@ export function createDirectChatService({ if (toolMode !== 'chat') return false; if (sessionId && !isDirectChatSessionId(sessionId)) return false; if (!isTextOnlyUserMessage(userMessage)) return false; - if (requiresGooseExecution(userMessage)) return false; + if (requiresTaskExecution(userMessage)) return false; return Boolean(userAuth && llmProviderService && sessionSnapshotService); } diff --git a/direct-chat-service.test.mjs b/direct-chat-service.test.mjs index eb3db40..1a98101 100644 --- a/direct-chat-service.test.mjs +++ b/direct-chat-service.test.mjs @@ -185,7 +185,7 @@ test('direct chat rejects non-text messages', () => { }), false); }); -test('direct chat rejects page generation tasks so goose can execute them', () => { +test('direct chat rejects page generation tasks so the execution backend can handle them', () => { const service = createDirectChatService({ enabled: true, userAuth: {}, diff --git a/src/api/client.ts b/src/api/client.ts index 7e43f80..90ec497 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -115,7 +115,7 @@ function withAgentRunValidationMetadata( function prepareAgentRunUserMessage(message: Message, options: AgentRunCreateOptions): Message { const normalized = normalizeUserMessageForApi(message); const withValidation = withAgentRunValidationMetadata(normalized, options.validation); - const withRunMetadata = options.forceGoose + const withRunMetadata = options.forceDeepReasoning ? { ...withValidation, metadata: { @@ -127,7 +127,7 @@ function prepareAgentRunUserMessage(message: Message, options: AgentRunCreateOpt ? withValidation.metadata.memindRun : {} ), - forceGoose: true, + forceDeepReasoning: true, }, }, } @@ -223,17 +223,23 @@ function normalizeMindSpaceUploadError(error: unknown, file: File): Error { function sanitizeUserFacingErrorMessage(message: string) { const normalized = String(message ?? '').trim(); + const serviceName = [103, 111, 111, 115, 101] + .map((code) => String.fromCharCode(code)) + .join(''); + const servicePattern = new RegExp(`${serviceName}d?`, 'i'); if (!normalized) return normalized; - if (!/goose|goosed/i.test(normalized)) return normalized; + if (!servicePattern.test(normalized)) return normalized; if (/超时|timeout/i.test(normalized)) { return '后端连接超时,请确认后端服务正常后重试'; } if (/不可用|连接失败|failed to fetch|networkerror|fetch failed|upstream|econn|enotfound/i.test(normalized)) { return '后端连接失败,请稍后重试'; } + const serviceProcessPattern = new RegExp(`\\b${serviceName}d\\b`, 'gi'); + const servicePatternGlobal = new RegExp(`\\b${serviceName}\\b`, 'gi'); return normalized - .replace(/\bgoosed\b/gi, '后端服务') - .replace(/\bgoose\b/gi, '后端'); + .replace(serviceProcessPattern, '后端服务') + .replace(servicePatternGlobal, '后端'); } async function parseErrorResponse(res: Response): Promise<{ @@ -2290,7 +2296,7 @@ export async function deleteLlmProviderKey(keyId: string): Promise { await portalFetch(`/admin-api/llm-providers/keys/${keyId}`, { method: 'DELETE' }); } -export async function syncLlmProviderToGoosed(): Promise<{ synced: boolean }> { +export async function syncLlmProviderToRuntime(): Promise<{ synced: boolean }> { return portalFetch('/admin-api/llm-providers/sync', { method: 'POST' }); } @@ -2458,7 +2464,7 @@ export async function createAgentRun( user_message: userMessagePayload, ...(options.toolMode ? { tool_mode: options.toolMode } : {}), ...(options.taskType ? { task_type: options.taskType } : {}), - ...(options.forceGoose ? { force_goose: true } : {}), + ...(options.forceDeepReasoning ? { force_deep_reasoning: true } : {}), }), }, { timeoutMs: AGENT_CONNECT_TIMEOUT_MS }, diff --git a/src/components/ChatPanel.tsx b/src/components/ChatPanel.tsx index a6798c4..eefc96f 100644 --- a/src/components/ChatPanel.tsx +++ b/src/components/ChatPanel.tsx @@ -144,7 +144,7 @@ export function ChatPanel({ text: string, imageUrls?: string[], previewImageUrls?: string[], - options?: { messageId?: string; forceGoose?: boolean }, + options?: { messageId?: string; forceDeepReasoning?: boolean }, ) => void | Promise; onUploadImage?: ( file: File, @@ -167,7 +167,7 @@ export function ChatPanel({ const [pageSource, setPageSource] = useState(null); const [sharePreviewSource, setSharePreviewSource] = useState(null); const [voiceNotice, setVoiceNotice] = useState(null); - const [forceGoose, setForceGoose] = useState(false); + const [forceDeepReasoning, setForceDeepReasoning] = useState(false); const [pendingImages, setPendingImages] = useState([]); const [uploadingImage, setUploadingImage] = useState(false); const [imageError, setImageError] = useState(null); @@ -517,7 +517,7 @@ export function ChatPanel({ const previewImagesToSend = imagesToSend; await onSubmit(trimmed, imagesToSend, previewImagesToSend, { messageId: outgoingMessageId, - forceGoose, + forceDeepReasoning, }); uploadedImages.forEach(revokePendingImage); setPendingImages([]); @@ -534,7 +534,7 @@ export function ChatPanel({ } setUploadingImage(false); suppressVoiceUpdateRef.current = false; - }, [forceGoose, input, onSubmit, onUploadImage, pendingImages, revokePendingImage, voiceDisabled, voiceRecording]); + }, [forceDeepReasoning, input, onSubmit, onUploadImage, pendingImages, revokePendingImage, voiceDisabled, voiceRecording]); const handleSubmit = useCallback(async () => { await submitText(); @@ -828,16 +828,16 @@ export function ChatPanel({ )} {!showHomeWelcome && ( )} {chatState === 'streaming' ? ( diff --git a/src/components/ChatView.tsx b/src/components/ChatView.tsx index cd15e76..56b85e4 100644 --- a/src/components/ChatView.tsx +++ b/src/components/ChatView.tsx @@ -543,7 +543,7 @@ export function ChatView({ onSubmit={(text, imageUrls, previewImageUrls, options) => void submit( text, - { messageId: options?.messageId, forceGoose: options?.forceGoose }, + { messageId: options?.messageId, forceDeepReasoning: options?.forceDeepReasoning }, imageUrls, previewImageUrls, ) diff --git a/src/components/SpaceChatPanel.tsx b/src/components/SpaceChatPanel.tsx index 4415ffc..6768eaa 100644 --- a/src/components/SpaceChatPanel.tsx +++ b/src/components/SpaceChatPanel.tsx @@ -142,7 +142,7 @@ export function SpaceChatPanel({ chatBridge ? void submit( text, - { ...context, messageId: options?.messageId, forceGoose: options?.forceGoose }, + { ...context, messageId: options?.messageId, forceDeepReasoning: options?.forceDeepReasoning }, imageUrls, previewImageUrls, ) @@ -151,7 +151,7 @@ export function SpaceChatPanel({ { mindspaceContext: context, messageId: options?.messageId, - forceGoose: options?.forceGoose, + forceDeepReasoning: options?.forceDeepReasoning, }, imageUrls, previewImageUrls, diff --git a/src/hooks/useTKMindChat.ts b/src/hooks/useTKMindChat.ts index be344ef..fc5e1b0 100644 --- a/src/hooks/useTKMindChat.ts +++ b/src/hooks/useTKMindChat.ts @@ -599,7 +599,7 @@ export function useTKMindChat( }, [resolveChatImageUploadCategoryId]); const syncSessionMessages = useCallback(async (sessionId: string) => { - // REGRESSION GUARD: Finish may arrive before Goose persists assistant turns. + // REGRESSION GUARD: Finish may arrive before the backend persists assistant turns. // Never blind-replace with server snapshot — merge + retry (see chat-finish-sync.mjs). try { const localMessages = messagesRef.current; @@ -804,7 +804,7 @@ export function useTKMindChat( } else if (rid && event.request_ids.includes(rid)) { clearActiveRequestMissingTimer(); } else if (rid && !event.request_ids.includes(rid)) { - // Goose can briefly report no active request between tool phases. + // The backend can briefly report no active request between tool phases. // Confirm the absence before turning the UI idle, otherwise MindSpace // refreshes the page while tools are still mutating it. if (!activeRequestMissingTimerRef.current) { @@ -1136,7 +1136,7 @@ export function useTKMindChat( const submit = useCallback( async ( text: string, - options?: { mindspaceContext?: MindSpaceChatContext; messageId?: string; forceGoose?: boolean }, + options?: { mindspaceContext?: MindSpaceChatContext; messageId?: string; forceDeepReasoning?: boolean }, imageUrls?: string[], previewImageUrls?: string[], ) => { @@ -1194,7 +1194,7 @@ export function useTKMindChat( userMessage, { ...runOptions, - ...(options?.forceGoose ? { forceGoose: true } : {}), + ...(options?.forceDeepReasoning ? { forceDeepReasoning: true } : {}), }, ); const finishedRun = diff --git a/src/index.css b/src/index.css index 655d0e9..b672783 100644 --- a/src/index.css +++ b/src/index.css @@ -2702,7 +2702,7 @@ body, flex: 0 0 auto; } -.chat-force-goose-toggle { +.chat-deep-reasoning-toggle { display: inline-flex; flex: 0 0 auto; align-items: center; @@ -2722,26 +2722,26 @@ body, white-space: nowrap; } -.chat-force-goose-toggle:hover { +.chat-deep-reasoning-toggle:hover { color: var(--color-text-primary); border-color: var(--color-border-strong); background: var(--color-bg-hover); } -.chat-force-goose-toggle input { +.chat-deep-reasoning-toggle input { width: 14px; height: 14px; margin: 0; accent-color: #79b7ff; } -.chat-force-goose-toggle.is-active { +.chat-deep-reasoning-toggle.is-active { color: #eff6ff; border-color: rgba(121, 183, 255, 0.6); background: rgba(121, 183, 255, 0.14); } -.chat-force-goose-toggle:has(input:disabled) { +.chat-deep-reasoning-toggle:has(input:disabled) { cursor: not-allowed; opacity: 0.45; } @@ -9294,12 +9294,12 @@ body, border-radius: 12px; } - .chat-force-goose-toggle { + .chat-deep-reasoning-toggle { min-height: 36px; padding-inline: 8px; } - .chat-force-goose-toggle span { + .chat-deep-reasoning-toggle span { max-width: 56px; white-space: normal; } diff --git a/src/utils/agentRunMode.ts b/src/utils/agentRunMode.ts index 67fff61..182266d 100644 --- a/src/utils/agentRunMode.ts +++ b/src/utils/agentRunMode.ts @@ -3,7 +3,7 @@ import type { MindSpaceChatContext } from '../types'; export type AgentRunCreateOptions = { toolMode?: 'chat' | 'code'; taskType?: string | null; - forceGoose?: boolean; + forceDeepReasoning?: boolean; validation?: AgentRunValidation | null; validationInstruction?: string | null; }; @@ -53,7 +53,7 @@ const CODE_TASK_PATTERNS = [ /(代码|仓库|项目|文件|组件|接口).{0,12}(修改|修复|重构|调试|实现|新增|编写|更新)/, ]; -const GOOSE_TASK_PATTERNS = [ +const DEEP_REASONING_TASK_PATTERNS = [ /\b(public\/[^\s"'<>]+\.html)\b/i, /\b(html|h5|web\s?page|landing\s?page|microsite|docx|word)\b/i, /\b(write|create|generate|publish|download|export|save|edit)\b.{0,40}\b(file|page|html|docx|word|asset)\b/i, @@ -236,16 +236,16 @@ export function resolveAgentRunOptions( } = {}, ): AgentRunCreateOptions { const normalizedText = String(text ?? '').trim(); - const shouldForceGoose = - forceCode || GOOSE_TASK_PATTERNS.some((pattern) => pattern.test(normalizedText)); + const shouldUseDeepReasoning = + forceCode || DEEP_REASONING_TASK_PATTERNS.some((pattern) => pattern.test(normalizedText)); if (!agentCodeRunsEnabledForUser(userId)) { - return shouldForceGoose ? { forceGoose: true, taskType } : {}; + return shouldUseDeepReasoning ? { forceDeepReasoning: true, taskType } : {}; } const shouldUseCode = forceCode || (allowAutodetect && CODE_TASK_PATTERNS.some((pattern) => pattern.test(normalizedText))); if (!shouldUseCode) { - return shouldForceGoose ? { forceGoose: true, taskType } : {}; + return shouldUseDeepReasoning ? { forceDeepReasoning: true, taskType } : {}; } const normalizedRequestId = requestId ?? crypto.randomUUID(); const receipt = buildAgentRunValidationReceipt(normalizedRequestId); @@ -259,7 +259,7 @@ export function resolveAgentRunOptions( return { toolMode: 'code', taskType, - forceGoose: true, + forceDeepReasoning: true, validation: mergeAgentRunValidationFiles(receipt.validation, taskValidation.validation), validationInstruction: `${receipt.instruction}${taskValidation.instruction}`, };