Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,10 @@ test/perf/.generated
# Dependencies
node_modules/
**/.idea/

# Standalone tests (not ready for commit)
test/standalone/

# Additional ignores
node_modules/**
eval-logs/**
eval-logs/**
65 changes: 63 additions & 2 deletions config/gni/devtools_grd_files.gni
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,27 @@ grd_files_bundled_sources = [
"front_end/panels/ai_chat/ui/conversationHistoryStyles.js",
"front_end/panels/ai_chat/ui/CustomProviderDialog.js",
"front_end/panels/ai_chat/ui/customProviderStyles.js",
"front_end/panels/ai_chat/ui/settings/advanced/BrowsingHistorySettings.js",
"front_end/panels/ai_chat/ui/settings/advanced/EvaluationSettings.js",
"front_end/panels/ai_chat/ui/settings/advanced/MCPSettings.js",
"front_end/panels/ai_chat/ui/settings/advanced/MemorySettings.js",
"front_end/panels/ai_chat/ui/settings/advanced/TracingSettings.js",
"front_end/panels/ai_chat/ui/settings/advanced/VectorDBSettings.js",
"front_end/panels/ai_chat/ui/settings/components/AdvancedToggle.js",
"front_end/panels/ai_chat/ui/settings/components/ModelSelectorFactory.js",
"front_end/panels/ai_chat/ui/settings/components/SettingsFooter.js",
"front_end/panels/ai_chat/ui/settings/components/SettingsHeader.js",
"front_end/panels/ai_chat/ui/settings/constants.js",
"front_end/panels/ai_chat/ui/settings/i18n-strings.js",
"front_end/panels/ai_chat/ui/settings/providerConfigs.js",
"front_end/panels/ai_chat/ui/settings/providers/BaseProviderSettings.js",
"front_end/panels/ai_chat/ui/settings/providers/GenericProviderSettings.js",
"front_end/panels/ai_chat/ui/settings/providers/LiteLLMSettings.js",
"front_end/panels/ai_chat/ui/settings/providers/OpenRouterSettings.js",
"front_end/panels/ai_chat/ui/settings/types.js",
"front_end/panels/ai_chat/ui/settings/utils/storage.js",
"front_end/panels/ai_chat/ui/settings/utils/styles.js",
"front_end/panels/ai_chat/ui/settings/utils/validation.js",
"front_end/panels/ai_chat/persistence/ConversationTypes.js",
"front_end/panels/ai_chat/persistence/ConversationStorageManager.js",
"front_end/panels/ai_chat/persistence/ConversationManager.js",
Expand Down Expand Up @@ -740,6 +760,10 @@ grd_files_bundled_sources = [
"front_end/panels/ai_chat/LLM/GenericOpenAIProvider.js",
"front_end/panels/ai_chat/LLM/LLMClient.js",
"front_end/panels/ai_chat/LLM/MessageSanitizer.js",
"front_end/panels/ai_chat/LLM/AnthropicProvider.js",
"front_end/panels/ai_chat/LLM/CerebrasProvider.js",
"front_end/panels/ai_chat/LLM/GenericOpenAIProvider.js",
"front_end/panels/ai_chat/LLM/GoogleAIProvider.js",
"front_end/panels/ai_chat/tools/Tools.js",
"front_end/panels/ai_chat/tools/SequentialThinkingTool.js",
"front_end/panels/ai_chat/tools/CombinedExtractionTool.js",
Expand Down Expand Up @@ -821,8 +845,44 @@ grd_files_bundled_sources = [
"front_end/panels/ai_chat/mini_apps/MiniAppRegistry.js",
"front_end/panels/ai_chat/mini_apps/MiniAppStorageManager.js",
"front_end/panels/ai_chat/mini_apps/apps/agent_studio/AgentStudioMiniApp.js",
"front_end/panels/ai_chat/mini_apps/apps/data_studio/DataStudioMiniApp.js",
"front_end/panels/ai_chat/mini_apps/apps/data_studio/DataStudioSPA.js",
"front_end/panels/ai_chat/mini_apps/MiniAppPageMonitor.js",
"front_end/panels/ai_chat/mini_apps/types/MiniAppTypes.js",
"front_end/panels/ai_chat/models/ChatTypes.js",
"front_end/panels/ai_chat/sandbox_apps/bundler/bundler-utils.js",
"front_end/panels/ai_chat/sandbox_apps/controller/SandboxController.js",
"front_end/panels/ai_chat/sandbox_apps/index.js",
"front_end/panels/ai_chat/sandbox_apps/SandboxAppInitialization.js",
"front_end/panels/ai_chat/sandbox_apps/SandboxAppRegistry.js",
"front_end/panels/ai_chat/sandbox_apps/protocol/SandboxProtocol.js",
"front_end/panels/ai_chat/sandbox_apps/protocol/MessageBus.js",
"front_end/panels/ai_chat/sandbox_apps/runtime/previewHtml.js",
"front_end/panels/ai_chat/sandbox_apps/tools/ApplyPatchTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/BuildAppTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/CreateAppTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/DeleteFileTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/GetStateTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/RunAppTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/SendDataTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/StopAppTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/WriteFileTool.js",
"front_end/panels/ai_chat/sandbox_apps/tools/index.js",
"front_end/panels/ai_chat/sandbox_apps/tools/ExecuteSandboxAppActionTool.js",
"front_end/panels/ai_chat/sandbox_apps/types/SandboxTypes.js",
"front_end/panels/ai_chat/sandbox_apps/types/SandboxAppTypes.js",
"front_end/panels/ai_chat/sandbox_apps/vfs/VFSManager.js",
"front_end/panels/ai_chat/sandbox_apps/bridge/SandboxAppBridge.js",
"front_end/panels/ai_chat/sandbox_apps/components/shadcn/sources.js",
"front_end/panels/ai_chat/sandbox_apps/apps/index.js",
"front_end/panels/ai_chat/sandbox_apps/apps/data-studio/index.js",
"front_end/panels/ai_chat/sandbox_apps/apps/data-studio/sources.js",
"front_end/panels/ai_chat/sandbox_apps/apps/data-studio/DataStudioApp.js",
"front_end/panels/ai_chat/sandbox_apps/apps/data-studio/DataStudioController.js",
"front_end/panels/ai_chat/ui/MiniAppsLauncherSPA.js",
"front_end/panels/ai_chat/ui/MiniAppsLauncherView.js",
"front_end/panels/ai_chat/ui/SandboxAppsLauncherSPA.js",
"front_end/panels/ai_chat/ui/SandboxAppsLauncherView.js",
"front_end/panels/ai_chat/models/ChatTypes.js",
"front_end/panels/ai_chat/ui/input/ChatInput.js",
"front_end/panels/ai_chat/ui/input/InputBar.js",
"front_end/panels/ai_chat/ui/markdown/MarkdownRenderers.js",
Expand Down Expand Up @@ -867,7 +927,6 @@ grd_files_bundled_sources = [
"front_end/panels/ai_chat/agent_framework/implementation/agents/ScrollActionAgent.js",
"front_end/panels/ai_chat/agent_framework/implementation/agents/WebTaskAgent.js",
"front_end/panels/ai_chat/agent_framework/implementation/agents/SearchAgent.js",
"front_end/panels/ai_chat/agent_framework/implementation/agents/ActionAgentV0.js",
"front_end/panels/ai_chat/agent_framework/implementation/agents/ActionAgentV2.js",
"front_end/panels/ai_chat/common/MarkdownViewerUtil.js",
"front_end/panels/ai_chat/evaluation/runner/VisionAgentEvaluationRunner.js",
Expand Down Expand Up @@ -908,6 +967,8 @@ grd_files_bundled_sources = [
"front_end/panels/ai_chat/utils/ContentChunker.js",
"front_end/panels/ai_chat/vendor/readability-source.js",
"front_end/panels/ai_chat/tools/LLMTracingWrapper.js",
"front_end/panels/ai_chat/utils/ContentChunker.js",
"front_end/panels/ai_chat/vendor/readability-source.js",
"front_end/panels/animation/animation-meta.js",
"front_end/panels/animation/animation.js",
"front_end/panels/application/application-meta.js",
Expand Down
99 changes: 99 additions & 0 deletions front_end/panels/ai_chat/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("../../../scripts/build/ninja/copy.gni")
import("../../../scripts/build/ninja/devtools_entrypoint.gni")
import("../../../scripts/build/ninja/devtools_module.gni")
import("../../../scripts/build/ninja/generate_css.gni")
Expand All @@ -15,6 +16,9 @@ generate_css("css_files") {
]
}

# Note: Bundler now runs inside the iframe (see previewHtml.ts)
# No separate bundler worker file needed

devtools_module("ai_chat") {
sources = [
"core/AgentStorageManager.ts",
Expand Down Expand Up @@ -199,7 +203,40 @@ devtools_module("ai_chat") {
"mini_apps/MiniAppStorageManager.ts",
"mini_apps/MiniAppEventBus.ts",
"mini_apps/MiniAppInitialization.ts",
"mini_apps/MiniAppPageMonitor.ts",
"mini_apps/apps/agent_studio/AgentStudioMiniApp.ts",
"mini_apps/apps/data_studio/DataStudioMiniApp.ts",
"mini_apps/apps/data_studio/DataStudioSPA.ts",
"sandbox_apps/types/SandboxTypes.ts",
"sandbox_apps/types/SandboxAppTypes.ts",
"sandbox_apps/vfs/VFSManager.ts",
"sandbox_apps/bridge/SandboxAppBridge.ts",
"sandbox_apps/components/shadcn/sources.ts",
"sandbox_apps/apps/index.ts",
"sandbox_apps/apps/data-studio/index.ts",
"sandbox_apps/apps/data-studio/sources.ts",
"sandbox_apps/apps/data-studio/DataStudioApp.ts",
"sandbox_apps/apps/data-studio/DataStudioController.ts",
"sandbox_apps/controller/SandboxController.ts",
"sandbox_apps/protocol/SandboxProtocol.ts",
"sandbox_apps/protocol/MessageBus.ts",
"sandbox_apps/bundler/bundler-utils.ts",
"sandbox_apps/runtime/previewHtml.ts",
"sandbox_apps/tools/CreateAppTool.ts",
"sandbox_apps/tools/WriteFileTool.ts",
"sandbox_apps/tools/DeleteFileTool.ts",
"sandbox_apps/tools/BuildAppTool.ts",
"sandbox_apps/tools/RunAppTool.ts",
"sandbox_apps/tools/StopAppTool.ts",
"sandbox_apps/tools/SendDataTool.ts",
"sandbox_apps/tools/GetStateTool.ts",
"sandbox_apps/tools/ApplyPatchTool.ts",
"sandbox_apps/tools/ExecuteSandboxAppActionTool.ts",
"sandbox_apps/tools/index.ts",
"sandbox_apps/execution/DataStudioStorage.ts",
"sandbox_apps/execution/DataStudioExecutor.ts",
"sandbox_apps/execution/index.ts",
"sandbox_apps/index.ts",
"agent_framework/ConfigurableAgentTool.ts",
"agent_framework/AgentRunner.ts",
"agent_framework/AgentRunnerEventBus.ts",
Expand Down Expand Up @@ -276,7 +313,13 @@ devtools_module("ai_chat") {
"ui/AgentStudioView.ts",
"ui/AgentStudioController.ts",
"ui/AgentStudioBridge.ts",
"ui/MiniAppsLauncherSPA.ts",
"ui/MiniAppsLauncherView.ts",
"ui/SandboxAppsLauncherSPA.ts",
"ui/SandboxAppsLauncherView.ts",
"ui/agent_studio/AgentStudioSPA.ts",
"sandbox_apps/SandboxAppRegistry.ts",
"sandbox_apps/SandboxAppInitialization.ts",
]

deps = [
Expand Down Expand Up @@ -364,7 +407,13 @@ _ai_chat_sources = [
"ui/AgentStudioView.ts",
"ui/AgentStudioController.ts",
"ui/AgentStudioBridge.ts",
"ui/MiniAppsLauncherSPA.ts",
"ui/MiniAppsLauncherView.ts",
"ui/SandboxAppsLauncherSPA.ts",
"ui/SandboxAppsLauncherView.ts",
"ui/agent_studio/AgentStudioSPA.ts",
"sandbox_apps/SandboxAppRegistry.ts",
"sandbox_apps/SandboxAppInitialization.ts",
"ai_chat_impl.ts",
"models/ChatTypes.ts",
"persistence/ConversationTypes.ts",
Expand Down Expand Up @@ -490,7 +539,37 @@ _ai_chat_sources = [
"mini_apps/MiniAppStorageManager.ts",
"mini_apps/MiniAppEventBus.ts",
"mini_apps/MiniAppInitialization.ts",
"mini_apps/MiniAppPageMonitor.ts",
"mini_apps/apps/agent_studio/AgentStudioMiniApp.ts",
"mini_apps/apps/data_studio/DataStudioMiniApp.ts",
"mini_apps/apps/data_studio/DataStudioSPA.ts",
"sandbox_apps/types/SandboxTypes.ts",
"sandbox_apps/types/SandboxAppTypes.ts",
"sandbox_apps/vfs/VFSManager.ts",
"sandbox_apps/bridge/SandboxAppBridge.ts",
"sandbox_apps/components/shadcn/sources.ts",
"sandbox_apps/apps/index.ts",
"sandbox_apps/apps/data-studio/index.ts",
"sandbox_apps/apps/data-studio/sources.ts",
"sandbox_apps/apps/data-studio/DataStudioApp.ts",
"sandbox_apps/apps/data-studio/DataStudioController.ts",
"sandbox_apps/controller/SandboxController.ts",
"sandbox_apps/protocol/SandboxProtocol.ts",
"sandbox_apps/protocol/MessageBus.ts",
"sandbox_apps/bundler/bundler-utils.ts",
"sandbox_apps/runtime/previewHtml.ts",
"sandbox_apps/tools/CreateAppTool.ts",
"sandbox_apps/tools/WriteFileTool.ts",
"sandbox_apps/tools/DeleteFileTool.ts",
"sandbox_apps/tools/BuildAppTool.ts",
"sandbox_apps/tools/RunAppTool.ts",
"sandbox_apps/tools/StopAppTool.ts",
"sandbox_apps/tools/SendDataTool.ts",
"sandbox_apps/tools/GetStateTool.ts",
"sandbox_apps/tools/ApplyPatchTool.ts",
"sandbox_apps/tools/ExecuteSandboxAppActionTool.ts",
"sandbox_apps/tools/index.ts",
"sandbox_apps/index.ts",
"agent_framework/ConfigurableAgentTool.ts",
"agent_framework/AgentRunner.ts",
"agent_framework/AgentRunnerEventBus.ts",
Expand Down Expand Up @@ -682,10 +761,30 @@ ts_library("unittests") {
"tools/__tests__/ReadFileTool.test.ts",
"tools/__tests__/ListFilesTool.test.ts",
"tools/__tests__/FileStorageManager.test.ts",
"tools/__tests__/RenderWebAppTool.test.ts",
"tools/mini_app/__tests__/MiniAppTools.test.ts",
"mini_apps/__tests__/MiniAppRegistry.test.ts",
"mini_apps/__tests__/GenericMiniAppBridge.test.ts",
"mini_apps/__tests__/MiniAppEventBus.test.ts",
"mini_apps/__tests__/SPATestHarness.ts",
"mini_apps/__tests__/SPATestHarness.test.ts",
"sandbox_apps/__tests__/test-utils.ts",
"sandbox_apps/__tests__/MockBundler.test.ts",
"sandbox_apps/__tests__/VFSManager.test.ts",
"sandbox_apps/__tests__/SandboxController.test.ts",
"sandbox_apps/__tests__/ApplyPatchTool.test.ts",
"sandbox_apps/__tests__/Tools.test.ts",
"sandbox_apps/__tests__/SandboxProtocol.test.ts",
"sandbox_apps/__tests__/previewHtml.test.ts",
"sandbox_apps/__tests__/bundler-utils.test.ts",
"sandbox_apps/__tests__/MessageBus.test.ts",
"sandbox_apps/__tests__/shadcn.test.ts",
"sandbox_apps/__tests__/DataStudioV2.test.ts",
"sandbox_apps/__tests__/DataStudioExecution.test.ts",
"sandbox_apps/__tests__/DataStudioStorage.test.ts",
"sandbox_apps/__tests__/PromiseRaceTimeout.test.ts",
"sandbox_apps/__tests__/DataStudioController.test.ts",
"sandbox_apps/__tests__/DataStudioBridge.test.ts",
"dom/__tests__/ComposedTreeResolver.test.ts",
"common/EncodedId.test.ts",
"a11y/__tests__/FrameRegistry.test.ts",
Expand Down
9 changes: 9 additions & 0 deletions front_end/panels/ai_chat/LLM/AnthropicProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,15 @@ export class AnthropicProvider extends LLMBaseProvider {
if (options?.reasoningLevel) {
betaHeaders.push('interleaved-thinking-2025-05-14');
}
// Add structured outputs beta if outputSchema is provided
if (options?.outputSchema) {
betaHeaders.push('structured-outputs-2025-11-13');
payloadBody.output_format = {
type: 'json_schema',
schema: options.outputSchema
};
logger.debug('Using structured output with schema:', options.outputSchema);
}

logger.info('Request payload:', payloadBody);

Expand Down
13 changes: 13 additions & 0 deletions front_end/panels/ai_chat/LLM/BrowserOperatorProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,19 @@ export class BrowserOperatorProvider extends LLMBaseProvider {
payloadBody.tool_choice = options.tool_choice;
}

// Add structured output schema if provided (forces JSON response conforming to schema)
if (options?.outputSchema) {
payloadBody.response_format = {
type: 'json_schema',
json_schema: {
name: 'agent_response',
strict: true,
schema: options.outputSchema
}
};
logger.debug('Using structured output with schema:', options.outputSchema);
}

logger.info('Request payload:', payloadBody);

// Extract agent name from options (set by AgentRunner)
Expand Down
13 changes: 13 additions & 0 deletions front_end/panels/ai_chat/LLM/GenericOpenAIProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,19 @@ export class GenericOpenAIProvider extends LLMBaseProvider {
payloadBody.tool_choice = options.tool_choice;
}

// Add structured output schema if provided (forces JSON response conforming to schema)
if (options?.outputSchema) {
payloadBody.response_format = {
type: 'json_schema',
json_schema: {
name: 'agent_response',
strict: true,
schema: options.outputSchema
}
};
logger.debug('Using structured output with schema:', options.outputSchema);
}

logger.info('Request payload:', payloadBody);

const data = await this.makeAPIRequest(this.getChatEndpoint(), payloadBody);
Expand Down
6 changes: 6 additions & 0 deletions front_end/panels/ai_chat/LLM/GoogleAIProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,12 @@ export class GoogleAIProvider extends LLMBaseProvider {
if (options?.temperature !== undefined) {
generationConfig.temperature = options.temperature;
}
// Add structured output schema if provided (forces JSON response conforming to schema)
if (options?.outputSchema) {
generationConfig.responseMimeType = 'application/json';
generationConfig.responseJsonSchema = options.outputSchema;
logger.debug('Using structured output with schema:', options.outputSchema);
}
if (Object.keys(generationConfig).length > 0) {
payloadBody.generationConfig = generationConfig;
}
Expand Down
13 changes: 13 additions & 0 deletions front_end/panels/ai_chat/LLM/GroqProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,19 @@ export class GroqProvider extends LLMBaseProvider {
payloadBody.tool_choice = options.tool_choice;
}

// Add structured output schema if provided (forces JSON response conforming to schema)
if (options?.outputSchema) {
payloadBody.response_format = {
type: 'json_schema',
json_schema: {
name: 'agent_response',
strict: true,
schema: options.outputSchema
}
};
logger.debug('Using structured output with schema:', options.outputSchema);
}

logger.info('Request payload:', payloadBody);

const data = await this.makeAPIRequest(this.getChatEndpoint(), payloadBody);
Expand Down
8 changes: 7 additions & 1 deletion front_end/panels/ai_chat/LLM/LLMClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import type { LLMMessage, LLMResponse, LLMCallOptions, LLMProvider, ModelInfo, RetryConfig } from './LLMTypes.js';
import type { LLMMessage, LLMResponse, LLMCallOptions, LLMProvider, ModelInfo, RetryConfig, OutputSchema } from './LLMTypes.js';
import { isCustomProvider } from './LLMTypes.js';
import { LLMProviderRegistry } from './LLMProviderRegistry.js';
import { OpenAIProvider } from './OpenAIProvider.js';
Expand Down Expand Up @@ -49,6 +49,8 @@ export interface LLMCallRequest {
temperature?: number;
retryConfig?: Partial<RetryConfig>;
agentName?: string; // Name of the calling agent for provider-specific routing
/** JSON Schema for structured LLM output (uses native LLM response_format) */
outputSchema?: OutputSchema;
tracingMetadata?: Record<string, any>; // Explicit tracing metadata for Langfuse integration
}

Expand Down Expand Up @@ -208,6 +210,10 @@ export class LLMClient {
if ((request as any).agentName) {
options.agentName = (request as any).agentName;
}
// Forward structured output schema for native LLM response_format
if (request.outputSchema) {
options.outputSchema = request.outputSchema;
}

// Get tracing metadata - prefer explicit request metadata over global context
// This ensures metadata flows correctly even when async context is lost
Expand Down
Loading