mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-09-19 01:51:21 +08:00
Merge pull request #14049 from Kilo-Org/investigate-browser-automation-tool-exposure
fix(vscode): restore Playwright MCP browser tools
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"kilo-code": patch
|
||||
---
|
||||
|
||||
Restore built-in Playwright browser automation and its settings under Web Tools. Keep the experimental Integrated Browser independent and allow its panel to open before selecting a session.
|
||||
@@ -94,7 +94,9 @@ Set the `KILO_WEBSEARCH_PROVIDER` environment variable to force a provider:
|
||||
|
||||
### Browser Tools
|
||||
|
||||
The VS Code extension's experimental `browser_open` tool opens a local application in Agent Manager's Browser panel and returns a screenshot and diagnostics. Enable **Browser Automation** under **Settings > Experimental**. It requires installed Chrome or compatible Playwright Chromium.
|
||||
The VS Code extension has a built-in browser automation tool powered by [Playwright MCP](https://www.npmjs.com/package/@playwright/mcp). Enable it in **Settings → Web Tools → Browser Automation**. When enabled, it registers an MCP server named `kilo-playwright` and exposes browser tools that follow the same permission model as all MCP tools.
|
||||
|
||||
The VS Code extension's experimental `browser_open` tool opens a local application in Agent Manager's Integrated Browser panel and returns a screenshot and diagnostics. Enable **Integrated Browser** under **Settings > Experimental**. It requires installed Chrome or compatible Playwright Chromium. It is independent from Playwright MCP.
|
||||
|
||||
The `browser_open` automation browser accepts HTTP URLs on `localhost` or `127.0.0.1` only, and blocks resources from other origins. See [Browser previews](/docs/automate/agent-manager#browser-previews) for setup and element feedback.
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ Browser Use requires an advanced agentic model. It is typically most reliable wi
|
||||
|
||||
Browser automation is built into the extension and requires no manual setup. Enable it from **Settings → Web Tools → Browser Automation** and Kilo handles the rest automatically.
|
||||
|
||||
{% callout type="note" title="Integrated Browser Is Separate" %}
|
||||
The experimental **Integrated Browser** under **Settings → Experimental** is a different feature. It shows local application previews inside Agent Manager and does not replace Playwright browser automation. The two features have independent settings.
|
||||
{% /callout %}
|
||||
|
||||
{% /tab %}
|
||||
{% tab label="CLI" %}
|
||||
|
||||
|
||||
@@ -1091,7 +1091,7 @@
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"scope": "application",
|
||||
"description": "Enable the experimental Agent Manager browser panel and browser_open tool."
|
||||
"description": "Enable the experimental Integrated Browser panel and browser_open tool in Agent Manager."
|
||||
},
|
||||
"kilo-code.new.experimental.claudeMigration": {
|
||||
"type": "boolean",
|
||||
@@ -1147,10 +1147,26 @@
|
||||
"maximum": 24,
|
||||
"description": "Font size in pixels for the Kilo Code webview UI."
|
||||
},
|
||||
"kilo-code.new.browserAutomation.enabled": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Enable browser automation powered by Playwright. When enabled, the AI agent can interact with web pages in a visible Chrome window."
|
||||
},
|
||||
"kilo-code.new.browserAutomation.useSystemChrome": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Use system-installed Google Chrome. Disable only when a compatible Playwright Chromium browser is already installed."
|
||||
"description": "Use your system's installed Chrome browser instead of downloading a separate Chromium instance."
|
||||
},
|
||||
"kilo-code.new.browserAutomation.headless": {
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "Run browser automation in headless mode (no visible window). When disabled, you can watch the agent interact with the browser."
|
||||
},
|
||||
"kilo-code.new.agentManager.browser.useSystemChrome": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"scope": "application",
|
||||
"description": "Use system-installed Google Chrome for the Integrated Browser. Disable only when a compatible Playwright Chromium browser is already installed."
|
||||
},
|
||||
"kilo-code.new.attention.enabled": {
|
||||
"type": "boolean",
|
||||
|
||||
@@ -58,6 +58,7 @@ import { resolveProjectDirectory } from "./project-directory"
|
||||
import { seedSessionStatuses } from "./session-status"
|
||||
import { normalizeEnhancePromptErrorMessage } from "./enhance-prompt-error"
|
||||
import { retry } from "./services/cli-backend/retry"
|
||||
import { integratedBrowserUseSystemChrome } from "./services/browser-automation/chrome-setting"
|
||||
import { removeAgent } from "./services/agent-removal"
|
||||
import { normalize, type SSEPayload, type SyncPayload, type WirePayload } from "./services/cli-backend/sdk-sse-adapter"
|
||||
import { slimInfo, slimPart, slimParts } from "./kilo-provider/slim-metadata"
|
||||
@@ -4078,6 +4079,7 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
multiProject: this.multiProjectSetting(),
|
||||
claudeMigration: this.claudeMigrationSetting(),
|
||||
browserAutomation: this.browserAutomationSetting(),
|
||||
agentManagerBrowserUseSystemChrome: integratedBrowserUseSystemChrome(),
|
||||
"agentManager.autoBranchNaming": naming.get<boolean>("autoBranchNaming", true),
|
||||
"agentManager.branchPrefix": naming.get<string>("branchPrefix", ""),
|
||||
"agentManager.worktreePool": naming.get<boolean>("worktreePool", true),
|
||||
@@ -4349,6 +4351,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
}
|
||||
|
||||
await this.checkpoints.get(sid)
|
||||
// Wait for Playwright MCP before the prompt so its tools are advertised.
|
||||
// Kept outside withRetry so retryable prompt errors keep their backoff.
|
||||
// The Integrated Browser does not use Playwright and is not affected.
|
||||
await this.connectionService.prepareTools(dir)
|
||||
await runWithMessageConfirmation(this.confirmations, messageID, "KiloProvider: Message request", () =>
|
||||
this.withRetry(
|
||||
() =>
|
||||
@@ -4435,7 +4441,10 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
source: f.source,
|
||||
}))
|
||||
|
||||
if (!control) await this.checkpoints.get(sid)
|
||||
if (!control) {
|
||||
await this.checkpoints.get(sid)
|
||||
await this.connectionService.prepareTools(dir)
|
||||
}
|
||||
const send = () =>
|
||||
this.client!.session.command({
|
||||
sessionID: sid,
|
||||
@@ -4830,7 +4839,9 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper
|
||||
this.postMessage({
|
||||
type: "browserSettingsLoaded",
|
||||
settings: {
|
||||
enabled: config.get<boolean>("enabled", false),
|
||||
useSystemChrome: config.get<boolean>("useSystemChrome", true),
|
||||
headless: config.get<boolean>("headless", false),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,7 +21,11 @@ import { AttentionService, showOSNotification } from "./services/attention"
|
||||
import { CaffeinationService } from "./services/caffeination"
|
||||
import { confirmCaffeination } from "./services/caffeination/confirm"
|
||||
import { createCaffeinationDriver } from "./services/caffeination/inhibitor"
|
||||
import { BrowserBroker } from "./services/browser-automation"
|
||||
import { BrowserAutomationService, BrowserBroker } from "./services/browser-automation"
|
||||
import {
|
||||
integratedBrowserUseSystemChrome,
|
||||
migrateIntegratedBrowserUseSystemChrome,
|
||||
} from "./services/browser-automation/chrome-setting"
|
||||
import { TelemetryEventName, TelemetryProxy } from "./services/telemetry"
|
||||
import { registerCommitMessageService } from "./services/commit-message"
|
||||
import { registerCodeActions, registerTerminalActions, KiloCodeActionProvider } from "./services/code-actions"
|
||||
@@ -62,16 +66,28 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
const telemetry = TelemetryProxy.getInstance()
|
||||
|
||||
await migrateIntegratedBrowserUseSystemChrome().catch((error: unknown) =>
|
||||
console.warn("[Kilo New] Integrated Browser Chrome preference migration failed:", error),
|
||||
)
|
||||
|
||||
const browserBroker = new BrowserBroker({
|
||||
log: (...args) => console.warn("[Kilo New] BrowserBroker:", ...args),
|
||||
enabled: () => vscode.workspace.getConfiguration("kilo-code.new.experimental").get("browserAutomation", false),
|
||||
trusted: () => vscode.workspace.isTrusted,
|
||||
useSystemChrome: () =>
|
||||
vscode.workspace.getConfiguration("kilo-code.new.browserAutomation").get("useSystemChrome", true),
|
||||
useSystemChrome: () => integratedBrowserUseSystemChrome(),
|
||||
})
|
||||
|
||||
// Create shared connection service (one server for all webviews)
|
||||
const connectionService = new KiloConnectionService(context, () => browserBroker.env())
|
||||
const connectionService = new KiloConnectionService(
|
||||
context,
|
||||
() => browserBroker.env(),
|
||||
(dir): Promise<void> => browserAutomationService.ready(dir),
|
||||
)
|
||||
|
||||
// Manages the built-in Playwright MCP server for ordinary sessions. This is
|
||||
// independent from the Agent Manager browser broker above.
|
||||
const browserAutomationService = new BrowserAutomationService(connectionService)
|
||||
void browserAutomationService.syncWithSettings()
|
||||
const notebookBridge = createNotebookBridge(connectionService)
|
||||
let restore = context.workspaceState.get<RestoreState>(RESTORE_KEY) ?? {}
|
||||
const remember = (patch: RestoreState) => {
|
||||
@@ -88,6 +104,9 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
|
||||
const unsubscribeStateChange = connectionService.onStateChange((state) => {
|
||||
if (state === "connected") {
|
||||
void browserAutomationService
|
||||
.reregisterIfEnabled()
|
||||
.catch((error) => console.warn("[Kilo New] Playwright MCP re-registration failed:", error))
|
||||
const config = connectionService.getServerConfig()
|
||||
if (config) {
|
||||
telemetry.configure(config.baseUrl, config.password)
|
||||
@@ -747,6 +766,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
unsubscribeStateChange()
|
||||
attention.dispose()
|
||||
browserBroker.dispose()
|
||||
browserAutomationService.dispose()
|
||||
provider.dispose()
|
||||
notebookBridge.dispose()
|
||||
connectionService.dispose()
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
import * as vscode from "vscode"
|
||||
import type { KiloClient } from "@kilocode/sdk/v2/client"
|
||||
import type { KiloConnectionService } from "../cli-backend"
|
||||
import { playwrightCommand } from "./settings"
|
||||
import { canonicalizePath, samePath } from "../../agent-manager/project/paths"
|
||||
|
||||
type BrowserAutomationState = "disabled" | "registering" | "connected" | "failed" | "disconnected"
|
||||
|
||||
/**
|
||||
* Manages the built-in Playwright MCP browser server for ordinary Kilo sessions.
|
||||
*
|
||||
* This is independent from the Agent Manager browser broker. It must not read
|
||||
* Agent Manager settings, and Agent Manager must not read its settings.
|
||||
*/
|
||||
export class BrowserAutomationService implements vscode.Disposable {
|
||||
// MCP server name used when registering with the CLI backend
|
||||
private static readonly MCP_SERVER_NAME = "kilo-playwright"
|
||||
private readonly disposables: vscode.Disposable[] = []
|
||||
private readonly registered = new Set<string>()
|
||||
private queue: Promise<void> = Promise.resolve()
|
||||
private disposed = false
|
||||
private state: BrowserAutomationState = "disabled"
|
||||
|
||||
constructor(
|
||||
private readonly connectionService: KiloConnectionService,
|
||||
private readonly wait = 15_000,
|
||||
) {
|
||||
this.disposables.push(
|
||||
vscode.workspace.onDidChangeConfiguration((event) => {
|
||||
if (!event.affectsConfiguration("kilo-code.new.browserAutomation")) return
|
||||
void this.syncWithSettings()
|
||||
}),
|
||||
vscode.workspace.onDidChangeWorkspaceFolders(() => this.enqueue(() => this.apply(true))),
|
||||
{
|
||||
dispose: connectionService.onEvent((event) => {
|
||||
if (event.type !== "server.instance.disposed") return
|
||||
return this.enqueue(async () => {
|
||||
if (this.disposed) return
|
||||
const root = canonicalizePath(event.properties.directory)
|
||||
const dirs = [...new Set([...this.registered, ...this.directories()])].filter((dir) =>
|
||||
samePath(canonicalizePath(dir), root),
|
||||
)
|
||||
if (!dirs.length) return
|
||||
// Config saves and Reload discard MCP state without reconnecting SSE.
|
||||
for (const dir of dirs) this.registered.delete(dir)
|
||||
await this.apply(true)
|
||||
})
|
||||
}),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the Playwright settings and enable or disable the MCP server.
|
||||
* Called on construction and when Playwright settings change.
|
||||
*/
|
||||
syncWithSettings(): Promise<void> {
|
||||
return this.enqueue(() => this.apply())
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-register the MCP server after the CLI backend reconnects.
|
||||
*/
|
||||
reregisterIfEnabled(): Promise<void> {
|
||||
return this.enqueue(() => this.apply())
|
||||
}
|
||||
|
||||
ready(directory: string): Promise<void> {
|
||||
const task = this.enqueue(async () => {
|
||||
if (this.disposed || !this.enabled() || !vscode.workspace.isTrusted) return
|
||||
const dir = this.directories().find((dir) => samePath(canonicalizePath(dir), canonicalizePath(directory)))
|
||||
if (!dir) return
|
||||
const client = this.getClient()
|
||||
if (!client) throw new Error("Playwright browser automation is waiting for the CLI connection.")
|
||||
// A prompt can arrive before the disposal event or before MCP startup finishes.
|
||||
const { data: status } = await client.mcp.status({ directory: dir }, { throwOnError: true })
|
||||
const server = status[BrowserAutomationService.MCP_SERVER_NAME]
|
||||
if (server?.status === "connected") return
|
||||
// A failed server stays failed until settings change, reconnect, or
|
||||
// disposal. Do not spawn another npx attempt on every prompt.
|
||||
if (server?.status === "failed") throw BrowserAutomationService.failure((server as { error?: string }).error)
|
||||
this.registered.delete(dir)
|
||||
if (!this.enabled()) return
|
||||
await this.register([dir])
|
||||
if (this.enabled() && !this.registered.has(dir)) throw BrowserAutomationService.failure()
|
||||
})
|
||||
return BrowserAutomationService.bounded(task, this.wait)
|
||||
}
|
||||
|
||||
/**
|
||||
* Cap how long a prompt waits for Playwright MCP. A cold `npx` start can hold
|
||||
* the shared queue for up to the MCP timeout, and a prompt should not stall
|
||||
* that long; its tools arrive on a later turn instead.
|
||||
*/
|
||||
private static async bounded(task: Promise<void>, wait: number): Promise<void> {
|
||||
const limit = Promise.withResolvers<"timeout">()
|
||||
const timer = setTimeout(() => limit.resolve("timeout"), wait)
|
||||
const outcome = task.then(
|
||||
() => undefined,
|
||||
(error) => {
|
||||
console.warn("[Kilo New] BrowserAutomationService: readiness failed:", error)
|
||||
return { error }
|
||||
},
|
||||
)
|
||||
void outcome.then(() => clearTimeout(timer))
|
||||
const result = await Promise.race([outcome, limit.promise])
|
||||
if (result === "timeout") {
|
||||
console.warn(
|
||||
"[Kilo New] BrowserAutomationService: readiness timed out, submitting without waiting for Playwright MCP",
|
||||
)
|
||||
return
|
||||
}
|
||||
if (result) throw result.error
|
||||
}
|
||||
|
||||
private static failure(detail?: string): Error {
|
||||
return new Error(
|
||||
`Playwright browser automation could not connect${detail ? ` (${detail})` : ""}. Check the Extension Host output, or disable Browser Automation in Web Tools to continue without it.`,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Run one settings transition at a time. Each transition reads the current
|
||||
* settings when it runs, so a queued change cannot restore stale state.
|
||||
*/
|
||||
private enqueue(task: () => Promise<void>): Promise<void> {
|
||||
const next = this.queue.then(task, task)
|
||||
this.queue = next.then(
|
||||
() => undefined,
|
||||
() => undefined,
|
||||
)
|
||||
return next
|
||||
}
|
||||
|
||||
private async apply(reconcile = false): Promise<void> {
|
||||
if (this.disposed) return
|
||||
if (!this.enabled()) {
|
||||
await this.unregister()
|
||||
return
|
||||
}
|
||||
if (!vscode.workspace.isTrusted) {
|
||||
console.warn("[Kilo New] BrowserAutomationService: Workspace is not trusted, skipping Playwright MCP")
|
||||
this.setState("disabled")
|
||||
return
|
||||
}
|
||||
const dirs = this.directories()
|
||||
const removed = [...this.registered].filter((dir) => !dirs.includes(dir))
|
||||
if (removed.length) await this.unregister(removed)
|
||||
await this.register(reconcile ? dirs.filter((dir) => !this.registered.has(dir)) : dirs)
|
||||
}
|
||||
|
||||
private enabled(): boolean {
|
||||
return vscode.workspace.getConfiguration("kilo-code.new.browserAutomation").get<boolean>("enabled", false) === true
|
||||
}
|
||||
|
||||
private command(): string[] {
|
||||
const config = vscode.workspace.getConfiguration("kilo-code.new.browserAutomation")
|
||||
return playwrightCommand({
|
||||
headless: config.get<boolean>("headless", false),
|
||||
useSystemChrome: config.get<boolean>("useSystemChrome", true),
|
||||
})
|
||||
}
|
||||
|
||||
private directories(): string[] {
|
||||
const folders = vscode.workspace.workspaceFolders ?? []
|
||||
const dirs = folders.length > 0 ? folders.map((folder) => folder.uri.fsPath) : [process.cwd()]
|
||||
return [...new Set(dirs)]
|
||||
}
|
||||
|
||||
private async register(dirs: string[]): Promise<void> {
|
||||
const client = this.getClient()
|
||||
if (!client) {
|
||||
this.setState("failed")
|
||||
return
|
||||
}
|
||||
const command = this.command()
|
||||
this.setState("registering")
|
||||
let failure: unknown
|
||||
for (const directory of dirs) {
|
||||
try {
|
||||
const { data: status } = await client.mcp.add(
|
||||
{
|
||||
name: BrowserAutomationService.MCP_SERVER_NAME,
|
||||
config: {
|
||||
type: "local",
|
||||
command,
|
||||
enabled: true,
|
||||
timeout: 60000,
|
||||
},
|
||||
directory,
|
||||
},
|
||||
{ throwOnError: true },
|
||||
)
|
||||
const server = status[BrowserAutomationService.MCP_SERVER_NAME]
|
||||
if (server?.status === "connected") {
|
||||
this.registered.add(directory)
|
||||
continue
|
||||
}
|
||||
this.registered.delete(directory)
|
||||
if (server?.status === "failed") {
|
||||
const detail = (server as { error?: string }).error
|
||||
failure = new Error(`Playwright MCP failed to start${detail ? `: ${detail}` : ""}`)
|
||||
}
|
||||
} catch (error) {
|
||||
this.registered.delete(directory)
|
||||
failure = error
|
||||
}
|
||||
}
|
||||
if (this.registered.size > 0) {
|
||||
this.setState("connected")
|
||||
return
|
||||
}
|
||||
if (failure) {
|
||||
console.error("[Kilo New] BrowserAutomationService: Failed to register MCP server:", failure)
|
||||
this.setState("failed")
|
||||
return
|
||||
}
|
||||
this.setState("disconnected")
|
||||
}
|
||||
|
||||
private async unregister(dirs = [...this.registered]): Promise<void> {
|
||||
const client = this.getClient()
|
||||
if (client) {
|
||||
for (const directory of dirs) {
|
||||
try {
|
||||
await client.mcp.disconnect(
|
||||
{ name: BrowserAutomationService.MCP_SERVER_NAME, directory },
|
||||
{ throwOnError: true },
|
||||
)
|
||||
this.registered.delete(directory)
|
||||
} catch (error) {
|
||||
console.error("[Kilo New] BrowserAutomationService: Failed to disconnect MCP server:", error)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setState("disabled")
|
||||
}
|
||||
|
||||
private getClient(): KiloClient | null {
|
||||
try {
|
||||
return this.connectionService.getClient()
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
private setState(state: BrowserAutomationState): void {
|
||||
if (this.state === state) return
|
||||
console.log(`[Kilo New] BrowserAutomationService: State ${this.state} -> ${state}`)
|
||||
this.state = state
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposed = true
|
||||
for (const disposable of this.disposables) disposable.dispose()
|
||||
this.disposables.length = 0
|
||||
}
|
||||
}
|
||||
@@ -475,8 +475,8 @@ export class BrowserBroker {
|
||||
const detail = error instanceof Error ? error.message : String(error)
|
||||
const action =
|
||||
this.opts.useSystemChrome?.() === false
|
||||
? "Install a compatible Playwright Chromium browser or enable Use System Chrome in Kilo Settings > Web Tools."
|
||||
: "Install Google Chrome or select an existing Playwright Chromium browser in Kilo Settings > Web Tools."
|
||||
? "Install a compatible Playwright Chromium browser or enable Use System Chrome in Kilo Settings > Experimental for the Integrated Browser."
|
||||
: "Install Google Chrome or disable Use System Chrome in Kilo Settings > Experimental for the Integrated Browser to use an installed Playwright Chromium browser."
|
||||
throw new Error(`${action} ${detail}`.slice(0, 1000), { cause: error })
|
||||
} finally {
|
||||
this.browserStarting = undefined
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import * as vscode from "vscode"
|
||||
|
||||
const INTEGRATED_BROWSER = "kilo-code.new.agentManager.browser"
|
||||
const BROWSER_AUTOMATION = "kilo-code.new.browserAutomation"
|
||||
|
||||
/**
|
||||
* Read the Chrome preference for the Agent Manager Integrated Browser.
|
||||
*
|
||||
* The broker and the settings payload both use this so the toggle in Settings
|
||||
* and the effective value stay in sync. The Playwright setting under Web Tools
|
||||
* stays independent.
|
||||
*/
|
||||
export function integratedBrowserUseSystemChrome(): boolean {
|
||||
return vscode.workspace.getConfiguration(INTEGRATED_BROWSER).get("useSystemChrome", true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a user-level Chrome preference that was stored before this setting had
|
||||
* its own key.
|
||||
*
|
||||
* Runs once on activation and only when the current key has no explicit value,
|
||||
* so the old Playwright preference is preserved without aliasing the two
|
||||
* features afterwards. Workspace-scoped legacy values are left alone because
|
||||
* the current key is application-scoped and cannot store them.
|
||||
*/
|
||||
export async function migrateIntegratedBrowserUseSystemChrome(): Promise<void> {
|
||||
const browser = vscode.workspace.getConfiguration(INTEGRATED_BROWSER)
|
||||
if (browser.inspect?.<boolean>("useSystemChrome")?.globalValue !== undefined) return
|
||||
const value = vscode.workspace.getConfiguration(BROWSER_AUTOMATION).inspect?.<boolean>("useSystemChrome")?.globalValue
|
||||
if (value === undefined) return
|
||||
await browser.update("useSystemChrome", value, vscode.ConfigurationTarget.Global)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export { BrowserAutomationService } from "./browser-automation-service"
|
||||
export { BrowserBroker, diagnostic } from "./browser-broker"
|
||||
export type {
|
||||
BrowserContextFactory,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import * as os from "os"
|
||||
import * as path from "path"
|
||||
|
||||
export const PLAYWRIGHT_OUTPUT_DIR = path.join(os.tmpdir(), "kilo-playwright-mcp")
|
||||
|
||||
/**
|
||||
* Build the Playwright MCP launch command.
|
||||
*
|
||||
* Default artifacts go outside the workspace. Explicit screenshot paths can
|
||||
* bypass this directory, so this is not a guarantee against staging artifacts.
|
||||
*/
|
||||
export function playwrightCommand(input: { headless: boolean; useSystemChrome: boolean }): string[] {
|
||||
const command = ["npx", "@playwright/mcp@latest"]
|
||||
if (input.headless) command.push("--headless")
|
||||
if (input.useSystemChrome) command.push("--browser", "chrome")
|
||||
command.push("--output-dir", PLAYWRIGHT_OUTPUT_DIR)
|
||||
return command
|
||||
}
|
||||
@@ -149,7 +149,11 @@ export class KiloConnectionService {
|
||||
private viewedDirty = false
|
||||
private unsubRemote: (() => void) | null = null
|
||||
|
||||
constructor(context: vscode.ExtensionContext, env?: () => Promise<Record<string, string>>) {
|
||||
constructor(
|
||||
context: vscode.ExtensionContext,
|
||||
env?: () => Promise<Record<string, string>>,
|
||||
private readonly prepare?: (directory: string) => Promise<void>,
|
||||
) {
|
||||
const state =
|
||||
context.workspaceState ??
|
||||
({
|
||||
@@ -202,6 +206,10 @@ export class KiloConnectionService {
|
||||
return this.client
|
||||
}
|
||||
|
||||
async prepareTools(directory: string): Promise<void> {
|
||||
await this.prepare?.(directory)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the shared SDK client, auto-connecting if not yet started.
|
||||
* Accepts an optional directory to use as the workspace root; falls back
|
||||
|
||||
@@ -60,6 +60,7 @@ const mockVscode = {
|
||||
}),
|
||||
getConfiguration: () => ({
|
||||
get: <T>(_key: string, value?: T) => value,
|
||||
inspect: () => ({}),
|
||||
update: async () => {},
|
||||
}),
|
||||
asRelativePath: (pathOrUri: string | { fsPath?: string }) => {
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import * as vscode from "vscode"
|
||||
import {
|
||||
integratedBrowserUseSystemChrome,
|
||||
migrateIntegratedBrowserUseSystemChrome,
|
||||
} from "../../src/services/browser-automation/chrome-setting"
|
||||
|
||||
const INTEGRATED_BROWSER = "kilo-code.new.agentManager.browser"
|
||||
const BROWSER_AUTOMATION = "kilo-code.new.browserAutomation"
|
||||
|
||||
describe("Integrated Browser Chrome preference", () => {
|
||||
const descriptors = Object.getOwnPropertyDescriptors(vscode.workspace)
|
||||
let writes: Array<{ key: string; value: unknown; target: unknown }> = []
|
||||
|
||||
function config(input: { current?: boolean; previous?: boolean; previousWorkspace?: boolean }) {
|
||||
writes = []
|
||||
vscode.workspace.getConfiguration = ((section: string) =>
|
||||
({
|
||||
get: (_key: string, fallback?: unknown) =>
|
||||
section === INTEGRATED_BROWSER ? (input.current ?? fallback) : fallback,
|
||||
inspect: () =>
|
||||
section === INTEGRATED_BROWSER
|
||||
? { globalValue: input.current }
|
||||
: { globalValue: input.previous, workspaceValue: input.previousWorkspace },
|
||||
update: async (key: string, value: unknown, target: unknown) => {
|
||||
writes.push({ key, value, target })
|
||||
},
|
||||
}) as unknown as vscode.WorkspaceConfiguration) as typeof vscode.workspace.getConfiguration
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
Object.defineProperties(vscode.workspace, descriptors)
|
||||
})
|
||||
|
||||
test("reads the preference from the Integrated Browser key", () => {
|
||||
config({ current: false, previous: true })
|
||||
expect(integratedBrowserUseSystemChrome()).toBe(false)
|
||||
})
|
||||
|
||||
test("defaults to system Chrome when the key is unset", () => {
|
||||
config({})
|
||||
expect(integratedBrowserUseSystemChrome()).toBe(true)
|
||||
})
|
||||
|
||||
test("copies a legacy preference once when the key is unset", async () => {
|
||||
config({ previous: false })
|
||||
await migrateIntegratedBrowserUseSystemChrome()
|
||||
expect(writes).toEqual([{ key: "useSystemChrome", value: false, target: vscode.ConfigurationTarget.Global }])
|
||||
})
|
||||
|
||||
test("keeps an existing Integrated Browser preference", async () => {
|
||||
config({ current: true, previous: false })
|
||||
await migrateIntegratedBrowserUseSystemChrome()
|
||||
expect(writes).toEqual([])
|
||||
})
|
||||
|
||||
test("does not write when no legacy preference exists", async () => {
|
||||
config({})
|
||||
await migrateIntegratedBrowserUseSystemChrome()
|
||||
expect(writes).toEqual([])
|
||||
})
|
||||
|
||||
test("does not promote a workspace-scoped legacy preference", async () => {
|
||||
config({ previousWorkspace: false })
|
||||
await migrateIntegratedBrowserUseSystemChrome()
|
||||
expect(writes).toEqual([])
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,300 @@
|
||||
import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
||||
import * as vscode from "vscode"
|
||||
import { realpathSync } from "node:fs"
|
||||
import { tmpdir } from "node:os"
|
||||
import type { KiloClient } from "@kilocode/sdk/v2/client"
|
||||
import type { KiloConnectionService } from "../../src/services/cli-backend"
|
||||
import { BrowserAutomationService } from "../../src/services/browser-automation/browser-automation-service"
|
||||
|
||||
describe("Playwright MCP lifecycle", () => {
|
||||
const descriptors = Object.getOwnPropertyDescriptors(vscode.workspace)
|
||||
const listeners = new Set<() => Promise<void>>()
|
||||
const events = new Set<Parameters<KiloConnectionService["onEvent"]>[0]>()
|
||||
let service: BrowserAutomationService
|
||||
let connection: KiloConnectionService
|
||||
let enabled: boolean
|
||||
let connected: boolean
|
||||
let failed: boolean
|
||||
let pending: Promise<void> | undefined
|
||||
let additions: string[]
|
||||
let removals: string[]
|
||||
let active: Set<string>
|
||||
let down: Set<string>
|
||||
let started: ReturnType<typeof Promise.withResolvers<void>>
|
||||
|
||||
function folders(dirs: string[]) {
|
||||
Object.defineProperty(vscode.workspace, "workspaceFolders", {
|
||||
configurable: true,
|
||||
value: dirs.map((dir, index) => ({ uri: vscode.Uri.file(dir), name: dir, index })),
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
enabled = true
|
||||
connected = true
|
||||
failed = false
|
||||
pending = undefined
|
||||
additions = []
|
||||
removals = []
|
||||
active = new Set()
|
||||
down = new Set()
|
||||
started = Promise.withResolvers<void>()
|
||||
folders(["/repo"])
|
||||
Object.defineProperty(vscode.workspace, "isTrusted", { configurable: true, value: true })
|
||||
vscode.workspace.getConfiguration = (() => ({
|
||||
get: (key: string, fallback: unknown) => (key === "enabled" ? enabled : fallback),
|
||||
})) as typeof vscode.workspace.getConfiguration
|
||||
Object.defineProperty(vscode.workspace, "onDidChangeWorkspaceFolders", {
|
||||
configurable: true,
|
||||
value: (listener: () => Promise<void>) => {
|
||||
listeners.add(listener)
|
||||
return { dispose: () => listeners.delete(listener) }
|
||||
},
|
||||
})
|
||||
const client = {
|
||||
mcp: {
|
||||
status: async ({ directory }: { directory: string }) => ({
|
||||
data: active.has(directory)
|
||||
? { "kilo-playwright": { status: "connected" } }
|
||||
: down.has(directory)
|
||||
? { "kilo-playwright": { status: "failed", error: "MCP startup failed" } }
|
||||
: {},
|
||||
}),
|
||||
add: async ({ name, directory }: { name: string; directory: string }) => {
|
||||
additions.push(directory)
|
||||
started.resolve()
|
||||
await pending
|
||||
if (failed) {
|
||||
down.add(directory)
|
||||
return { data: { [name]: { status: "failed", error: "MCP startup failed" } } }
|
||||
}
|
||||
down.delete(directory)
|
||||
active.add(directory)
|
||||
return { data: { [name]: { status: "connected" } } }
|
||||
},
|
||||
disconnect: async ({ directory }: { directory: string }) => {
|
||||
removals.push(directory)
|
||||
active.delete(directory)
|
||||
down.delete(directory)
|
||||
},
|
||||
},
|
||||
} as unknown as KiloClient
|
||||
connection = {
|
||||
onEvent: (listener: Parameters<KiloConnectionService["onEvent"]>[0]) => {
|
||||
events.add(listener)
|
||||
return () => events.delete(listener)
|
||||
},
|
||||
getClient: () => {
|
||||
if (!connected) throw new Error("Disconnected")
|
||||
return client
|
||||
},
|
||||
} as KiloConnectionService
|
||||
service = new BrowserAutomationService(connection)
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
service.dispose()
|
||||
listeners.clear()
|
||||
events.clear()
|
||||
for (const key of Object.getOwnPropertyNames(vscode.workspace)) {
|
||||
if (!(key in descriptors)) Reflect.deleteProperty(vscode.workspace, key)
|
||||
}
|
||||
Object.defineProperties(vscode.workspace, descriptors)
|
||||
})
|
||||
|
||||
test("re-registers the same directory after a backend restart", async () => {
|
||||
await service.syncWithSettings()
|
||||
active.clear()
|
||||
await service.reregisterIfEnabled()
|
||||
expect(additions).toEqual(["/repo", "/repo"])
|
||||
expect([...active]).toEqual(["/repo"])
|
||||
})
|
||||
|
||||
test("prompt readiness waits for in-flight MCP startup without restarting it", async () => {
|
||||
const gate = Promise.withResolvers<void>()
|
||||
pending = gate.promise
|
||||
const registration = service.syncWithSettings()
|
||||
await started.promise
|
||||
let sent = false
|
||||
const prompt = service.ready("/repo").then(() => {
|
||||
sent = true
|
||||
})
|
||||
await Promise.resolve()
|
||||
expect(sent).toBe(false)
|
||||
gate.resolve()
|
||||
await Promise.all([registration, prompt])
|
||||
expect(sent).toBe(true)
|
||||
expect(additions).toEqual(["/repo"])
|
||||
})
|
||||
|
||||
test("prompt readiness gives up after the wait instead of stalling on startup", async () => {
|
||||
const gate = Promise.withResolvers<void>()
|
||||
pending = gate.promise
|
||||
service.dispose()
|
||||
service = new BrowserAutomationService(connection, 5)
|
||||
const registration = service.syncWithSettings()
|
||||
await started.promise
|
||||
await service.ready("/repo")
|
||||
expect(active.size).toBe(0)
|
||||
gate.resolve()
|
||||
await registration
|
||||
expect(active.has("/repo")).toBe(true)
|
||||
})
|
||||
|
||||
test("prompt readiness repairs lost registration before the disposal event arrives", async () => {
|
||||
await service.syncWithSettings()
|
||||
active.clear()
|
||||
await service.ready("/repo")
|
||||
expect(additions).toEqual(["/repo", "/repo"])
|
||||
expect(active.has("/repo")).toBe(true)
|
||||
})
|
||||
|
||||
test("prompt readiness surfaces startup failures rather than submitting without tools", async () => {
|
||||
failed = true
|
||||
await expect(service.ready("/repo")).rejects.toThrow("Playwright browser automation could not connect")
|
||||
expect(active.size).toBe(0)
|
||||
})
|
||||
|
||||
test("a failed server is not respawned on every prompt", async () => {
|
||||
failed = true
|
||||
await expect(service.ready("/repo")).rejects.toThrow("could not connect")
|
||||
await expect(service.ready("/repo")).rejects.toThrow("MCP startup failed")
|
||||
expect(additions).toEqual(["/repo"])
|
||||
failed = false
|
||||
await service.syncWithSettings()
|
||||
await service.ready("/repo")
|
||||
expect(additions).toEqual(["/repo", "/repo"])
|
||||
expect(active.has("/repo")).toBe(true)
|
||||
})
|
||||
|
||||
test("disabled Playwright and unrelated worktrees do not block prompts", async () => {
|
||||
await service.ready("/worktree")
|
||||
enabled = false
|
||||
await service.ready("/repo")
|
||||
expect(additions).toEqual([])
|
||||
})
|
||||
|
||||
async function invalidate(directory: string) {
|
||||
active.delete(directory)
|
||||
await Promise.all(
|
||||
[...events].map((listener) =>
|
||||
listener(
|
||||
{
|
||||
type: "server.instance.disposed",
|
||||
properties: { directory },
|
||||
},
|
||||
directory,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
test("restores registrations after config disposal without an SSE reconnect", async () => {
|
||||
folders(["/repo", "/second"])
|
||||
await service.syncWithSettings()
|
||||
await invalidate("/repo")
|
||||
expect(additions).toEqual(["/repo", "/second", "/repo"])
|
||||
expect(active.has("/repo")).toBe(true)
|
||||
expect(removals).toEqual([])
|
||||
await invalidate("/second")
|
||||
expect(active.size).toBe(2)
|
||||
expect(additions).toEqual(["/repo", "/second", "/repo", "/second"])
|
||||
})
|
||||
|
||||
test("ignores disposal for unrelated Agent Manager directories", async () => {
|
||||
await service.syncWithSettings()
|
||||
expect(events.size).toBe(1)
|
||||
await invalidate("/worktree")
|
||||
expect(additions).toEqual(["/repo"])
|
||||
expect(removals).toEqual([])
|
||||
})
|
||||
|
||||
test("matches canonical disposal paths to workspace aliases", async () => {
|
||||
const dir = tmpdir()
|
||||
folders([dir])
|
||||
await service.syncWithSettings()
|
||||
await invalidate(realpathSync(dir))
|
||||
expect(additions).toEqual([dir, dir])
|
||||
})
|
||||
|
||||
test("does not restore after disposal of the service", async () => {
|
||||
await service.syncWithSettings()
|
||||
service.dispose()
|
||||
await invalidate("/repo")
|
||||
expect(events.size).toBe(0)
|
||||
expect(additions).toEqual(["/repo"])
|
||||
})
|
||||
|
||||
test("does not restore a disposed registration when disabled", async () => {
|
||||
await service.syncWithSettings()
|
||||
enabled = false
|
||||
expect(events.size).toBe(1)
|
||||
await invalidate("/repo")
|
||||
expect(additions).toEqual(["/repo"])
|
||||
expect(removals).toEqual([])
|
||||
expect(active.size).toBe(0)
|
||||
// The handler ran: it dropped the directory, so a reconcile registers it again.
|
||||
enabled = true
|
||||
await Promise.all([...listeners].map((listener) => listener()))
|
||||
expect(additions).toEqual(["/repo", "/repo"])
|
||||
})
|
||||
|
||||
test("queues disposal behind an in-flight registration", async () => {
|
||||
const gate = Promise.withResolvers<void>()
|
||||
pending = gate.promise
|
||||
const registration = service.syncWithSettings()
|
||||
await started.promise
|
||||
const reset = invalidate("/repo")
|
||||
gate.resolve()
|
||||
await Promise.all([registration, reset])
|
||||
expect(additions).toEqual(["/repo", "/repo"])
|
||||
expect(active.has("/repo")).toBe(true)
|
||||
})
|
||||
|
||||
test("a queued disable wins over in-flight registration and reconnect", async () => {
|
||||
const gate = Promise.withResolvers<void>()
|
||||
pending = gate.promise
|
||||
const registration = service.syncWithSettings()
|
||||
await started.promise
|
||||
const reconnect = service.reregisterIfEnabled()
|
||||
enabled = false
|
||||
const disable = service.syncWithSettings()
|
||||
gate.resolve()
|
||||
await Promise.all([registration, reconnect, disable])
|
||||
expect(additions).toEqual(["/repo"])
|
||||
expect(removals).toEqual(["/repo"])
|
||||
expect(active.size).toBe(0)
|
||||
})
|
||||
|
||||
test("retries a disable on reconnect without losing its directory", async () => {
|
||||
await service.syncWithSettings()
|
||||
connected = false
|
||||
enabled = false
|
||||
await service.syncWithSettings()
|
||||
expect([...active]).toEqual(["/repo"])
|
||||
connected = true
|
||||
await service.reregisterIfEnabled()
|
||||
expect(removals).toEqual(["/repo"])
|
||||
expect(active.size).toBe(0)
|
||||
})
|
||||
|
||||
test("reconciles added and removed folders without restarting retained registrations", async () => {
|
||||
folders(["/repo", "/old"])
|
||||
await service.syncWithSettings()
|
||||
folders(["/repo", "/new"])
|
||||
await Promise.all([...listeners].map((listener) => listener()))
|
||||
expect(additions).toEqual(["/repo", "/old", "/new"])
|
||||
expect(removals).toEqual(["/old"])
|
||||
expect([...active]).toEqual(["/repo", "/new"])
|
||||
|
||||
enabled = false
|
||||
await service.syncWithSettings()
|
||||
folders(["/repo", "/disabled"])
|
||||
await Promise.all([...listeners].map((listener) => listener()))
|
||||
expect(additions).toEqual(["/repo", "/old", "/new"])
|
||||
expect(active.size).toBe(0)
|
||||
service.dispose()
|
||||
expect(listeners.size).toBe(0)
|
||||
expect(events.size).toBe(0)
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,31 @@
|
||||
import { describe, expect, it } from "bun:test"
|
||||
import { PLAYWRIGHT_OUTPUT_DIR, playwrightCommand } from "../../src/services/browser-automation/settings"
|
||||
|
||||
describe("Playwright MCP command", () => {
|
||||
it("uses system Chrome and a temp output directory by default", () => {
|
||||
expect(playwrightCommand({ headless: false, useSystemChrome: true })).toEqual([
|
||||
"npx",
|
||||
"@playwright/mcp@latest",
|
||||
"--browser",
|
||||
"chrome",
|
||||
"--output-dir",
|
||||
PLAYWRIGHT_OUTPUT_DIR,
|
||||
])
|
||||
})
|
||||
|
||||
it("adds headless and drops the Chrome channel", () => {
|
||||
expect(playwrightCommand({ headless: true, useSystemChrome: false })).toEqual([
|
||||
"npx",
|
||||
"@playwright/mcp@latest",
|
||||
"--headless",
|
||||
"--output-dir",
|
||||
PLAYWRIGHT_OUTPUT_DIR,
|
||||
])
|
||||
})
|
||||
|
||||
it("keeps artifacts outside the workspace", () => {
|
||||
const command = playwrightCommand({ headless: false, useSystemChrome: false })
|
||||
const index = command.indexOf("--output-dir")
|
||||
expect(command.at(index + 1)).not.toContain(process.cwd())
|
||||
})
|
||||
})
|
||||
@@ -495,20 +495,25 @@ describe("BrowserBroker", () => {
|
||||
expect(untrusted.sessions()).toEqual([])
|
||||
})
|
||||
|
||||
test("explains how to recover when the selected browser runtime is missing", async () => {
|
||||
const broker = new BrowserBroker({
|
||||
log: () => {},
|
||||
useSystemChrome: () => false,
|
||||
launch: async () => {
|
||||
throw new Error("Browser executable does not exist")
|
||||
},
|
||||
})
|
||||
brokers.push(broker)
|
||||
await expect(
|
||||
broker.open({ sessionId: "missing-runtime", directory: "/tmp/project" }, "http://localhost:3000/"),
|
||||
).rejects.toThrow("enable Use System Chrome")
|
||||
expect(broker.sessions()).toEqual([])
|
||||
})
|
||||
test.each([false, true])(
|
||||
"points at Agent Manager settings when the browser is missing (Chrome: %s)",
|
||||
async (chrome) => {
|
||||
const broker = new BrowserBroker({
|
||||
log: () => {},
|
||||
useSystemChrome: () => chrome,
|
||||
launch: async () => {
|
||||
throw new Error("Browser executable does not exist")
|
||||
},
|
||||
})
|
||||
brokers.push(broker)
|
||||
await expect(
|
||||
broker.open({ sessionId: "missing-runtime", directory: "/tmp/project" }, "http://localhost:3000/"),
|
||||
).rejects.toThrow(
|
||||
`${chrome ? "disable" : "enable"} Use System Chrome in Kilo Settings > Experimental for the Integrated Browser`,
|
||||
)
|
||||
expect(broker.sessions()).toEqual([])
|
||||
},
|
||||
)
|
||||
|
||||
test("rejects unregistered browser sessions before launching Chrome", async () => {
|
||||
const broker = new BrowserBroker({ log: () => {} })
|
||||
|
||||
@@ -226,6 +226,7 @@ function createConnection(client: ReturnType<typeof createClient> | null) {
|
||||
getConnectionError: () => null,
|
||||
resolveEventSessionId: () => undefined,
|
||||
recordMessageSessionId: () => undefined,
|
||||
prepareTools: async (_dir: string) => {},
|
||||
notifyNotificationDismissed: () => undefined,
|
||||
pruneSession: () => undefined,
|
||||
registerVisible: () => undefined,
|
||||
@@ -294,7 +295,7 @@ function makeProvider(
|
||||
sent.push(message)
|
||||
},
|
||||
}
|
||||
return { provider, internal, sent }
|
||||
return { provider, internal, sent, connection }
|
||||
}
|
||||
|
||||
function status(internal: ProviderInternals, type: "busy" | "idle", directory = "/repo", sessionID = "s1") {
|
||||
@@ -1595,6 +1596,74 @@ describe("KiloProvider.handleLoadMessages / slim payload", () => {
|
||||
expect(client.prompted).toHaveLength(1)
|
||||
})
|
||||
|
||||
it("waits for browser tool readiness before submitting the prompt", async () => {
|
||||
const client = createClient()
|
||||
const { internal, connection } = makeProvider(client)
|
||||
internal.currentSession = mkSession()
|
||||
internal.gatherEditorContext = async () => ({})
|
||||
const started = Promise.withResolvers<void>()
|
||||
const ready = Promise.withResolvers<void>()
|
||||
connection.prepareTools = async (dir) => {
|
||||
expect(dir).toBe("/repo")
|
||||
started.resolve()
|
||||
await ready.promise
|
||||
}
|
||||
const send = internal.handleSendMessage("browser test", "m1", "s1")
|
||||
await started.promise
|
||||
expect(client.prompted).toHaveLength(0)
|
||||
ready.resolve()
|
||||
await send
|
||||
expect(client.prompted).toHaveLength(1)
|
||||
})
|
||||
|
||||
it("waits for browser tool readiness for Agent Manager worktree prompts too", async () => {
|
||||
const client = createClient()
|
||||
const { internal, connection } = makeProvider(client)
|
||||
internal.gatherEditorContext = async () => ({})
|
||||
const order: string[] = []
|
||||
connection.prepareTools = async (dir) => {
|
||||
order.push(`prepare:${dir}`)
|
||||
}
|
||||
client.session.promptAsync = async (params: Record<string, unknown>) => {
|
||||
order.push(`prompt:${String(params.directory)}`)
|
||||
return { data: undefined }
|
||||
}
|
||||
await internal.handleSendMessage(
|
||||
"browser test",
|
||||
"m1",
|
||||
undefined,
|
||||
"draft-1",
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
"worktree-ctx",
|
||||
"/worktree",
|
||||
)
|
||||
expect(client.created).toEqual([expect.objectContaining({ directory: "/worktree" })])
|
||||
expect(order).toEqual(["prepare:/worktree", "prompt:/worktree"])
|
||||
})
|
||||
|
||||
it("reports a browser readiness failure instead of submitting without tools", async () => {
|
||||
const client = createClient()
|
||||
const { internal, connection, sent } = makeProvider(client)
|
||||
internal.currentSession = mkSession()
|
||||
internal.gatherEditorContext = async () => ({})
|
||||
connection.prepareTools = async () => {
|
||||
throw new Error("Playwright browser automation could not connect")
|
||||
}
|
||||
await internal.handleSendMessage("browser test", "m1", "s1")
|
||||
expect(client.prompted).toHaveLength(0)
|
||||
expect(sent).toContainEqual(
|
||||
expect.objectContaining({
|
||||
type: "sendMessageFailed",
|
||||
error: "Playwright browser automation could not connect",
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
it("aborts when the cost alert is stopped", async () => {
|
||||
const client = createClient()
|
||||
const { internal, sent } = makeProvider(client)
|
||||
|
||||
@@ -88,6 +88,7 @@ function mockConnection(getImpl?: (p: SessionGetParams) => Promise<unknown>, vcs
|
||||
getConnectionError: () => null,
|
||||
resolveEventSessionId: () => undefined,
|
||||
recordMessageSessionId: () => undefined,
|
||||
prepareTools: async () => {},
|
||||
notifyNotificationDismissed: () => undefined,
|
||||
} as unknown as ConstructorParameters<typeof KiloProvider>[1],
|
||||
}
|
||||
|
||||
@@ -6,6 +6,76 @@ import { createProjectStore } from "../../webview-ui/agent-manager/project/store
|
||||
import { setupVisible, updateSetup } from "../../webview-ui/agent-manager/project/progress"
|
||||
|
||||
describe("Agent Manager panel ownership", () => {
|
||||
it("opens and closes the Integrated Browser before a session exists", () => {
|
||||
createRoot((dispose) => {
|
||||
const panels = createSidePanel({ project: () => "project", selection: () => "local", current: () => undefined })
|
||||
panels.toggle(SidePanel.Browser)
|
||||
expect(panels.panel()).toBe(SidePanel.Browser)
|
||||
expect(panels.session()).toBeUndefined()
|
||||
panels.toggle(SidePanel.Browser)
|
||||
expect(panels.panel()).toBeNull()
|
||||
panels.open(SidePanel.Browser)
|
||||
panels.open(SidePanel.Documents)
|
||||
expect(panels.panel()).toBe(SidePanel.Documents)
|
||||
dispose()
|
||||
})
|
||||
})
|
||||
|
||||
it("keeps the empty browser separate from real sessions, projects, and worktrees", () => {
|
||||
createRoot((dispose) => {
|
||||
const [project, activate] = createSignal("project")
|
||||
const [selection, select] = createSignal("local")
|
||||
const [current, session] = createSignal<string>()
|
||||
const panels = createSidePanel({ project, selection, current })
|
||||
panels.open(SidePanel.Browser)
|
||||
select("worktree")
|
||||
expect(panels.panel()).toBeNull()
|
||||
select("local")
|
||||
activate("other")
|
||||
expect(panels.panel()).toBeNull()
|
||||
activate("project")
|
||||
expect(panels.panel()).toBe(SidePanel.Browser)
|
||||
session("real-session")
|
||||
expect(panels.panel()).toBeNull()
|
||||
panels.open(SidePanel.Browser)
|
||||
session("sibling")
|
||||
expect(panels.panel()).toBeNull()
|
||||
session("real-session")
|
||||
expect(panels.panel()).toBe(SidePanel.Browser)
|
||||
panels.close()
|
||||
session(undefined)
|
||||
expect(panels.panel()).toBe(SidePanel.Browser)
|
||||
dispose()
|
||||
})
|
||||
})
|
||||
|
||||
it("does not let a closed draft browser hide a worktree panel after the session ends", () => {
|
||||
createRoot((dispose) => {
|
||||
const [current, session] = createSignal<string>()
|
||||
const panels = createSidePanel({ project: () => "project", selection: () => "local", current })
|
||||
panels.open(SidePanel.Browser)
|
||||
panels.close()
|
||||
expect(panels.panel()).toBeNull()
|
||||
session("real-session")
|
||||
panels.open(SidePanel.Diff)
|
||||
expect(panels.panel()).toBe(SidePanel.Diff)
|
||||
session(undefined)
|
||||
expect(panels.panel()).toBe(SidePanel.Diff)
|
||||
dispose()
|
||||
})
|
||||
})
|
||||
|
||||
it("still requires a real session for other session-owned panels", () => {
|
||||
createRoot((dispose) => {
|
||||
const panels = createSidePanel({ project: () => "project", selection: () => "local", current: () => undefined })
|
||||
panels.open(SidePanel.Subagents)
|
||||
expect(panels.panel()).toBeNull()
|
||||
panels.open(SidePanel.EditPreview)
|
||||
expect(panels.panel()).toBeNull()
|
||||
dispose()
|
||||
})
|
||||
})
|
||||
|
||||
it("restores Local Diff and session panels independently, including explicit closes", () => {
|
||||
createRoot((dispose) => {
|
||||
const [project, activate] = createSignal("project")
|
||||
|
||||
+2
-2
@@ -422,7 +422,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "تم تفعيل وضع إبقاء الكمبيوتر مستيقظًا لوكلاء Kilo؛ انقر لتعطيله",
|
||||
"agentManager.caffeination.active": "يتم إبقاء الكمبيوتر مستيقظًا أثناء عمل وكلاء Kilo",
|
||||
"agentManager.caffeination.unavailable": "وضع إبقاء الكمبيوتر مستيقظًا غير متاح على هذا النظام الأساسي",
|
||||
"agentManager.browser.title": "المتصفح",
|
||||
"agentManager.browser.title": "المتصفح المدمج",
|
||||
"agentManager.browser.url": "URL التطبيق المحلي",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "فتح",
|
||||
@@ -431,7 +431,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "تحديد عنصر",
|
||||
"agentManager.browser.devtoolsTitle": "أدوات المطوّرين",
|
||||
"agentManager.browser.empty": "افتح تطبيقًا محليًا لمعاينته هنا.",
|
||||
"agentManager.browser.noSession": "اختر جلسة Agent Manager أولًا.",
|
||||
"agentManager.browser.noSession": "ابدأ جلسة أو اختر جلسة في Agent Manager لاستعراض تطبيق محلي.",
|
||||
"agentManager.browser.screenshotAlt": "صفحة المتصفح الحالية",
|
||||
"agentManager.browser.errors": "مشكلات المتصفح: {{count}}",
|
||||
"agentManager.browser.diagnostics": "تشخيص المتصفح",
|
||||
|
||||
+3
-2
@@ -431,7 +431,7 @@ export const dict = {
|
||||
"agentManager.caffeination.active": "Mantendo o computador acordado enquanto os agentes Kilo trabalham",
|
||||
"agentManager.caffeination.unavailable":
|
||||
"O modo de manter o computador acordado não está disponível nesta plataforma",
|
||||
"agentManager.browser.title": "Navegador",
|
||||
"agentManager.browser.title": "Navegador Integrado",
|
||||
"agentManager.browser.url": "URL da aplicação local",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Abrir",
|
||||
@@ -440,7 +440,8 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Atualizar navegador",
|
||||
"agentManager.browser.close": "Fechar navegador",
|
||||
"agentManager.browser.empty": "Abra uma aplicação local para visualizá-la aqui.",
|
||||
"agentManager.browser.noSession": "Selecione primeiro uma sessão do Agent Manager.",
|
||||
"agentManager.browser.noSession":
|
||||
"Inicie ou selecione uma sessão no Agent Manager para navegar em um aplicativo local.",
|
||||
"agentManager.browser.screenshotAlt": "Página atual do navegador",
|
||||
"agentManager.browser.errors": "Problemas do navegador: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Diagnóstico do navegador",
|
||||
|
||||
+3
-2
@@ -427,7 +427,7 @@ export const dict = {
|
||||
"Režim održavanja računara budnim je uključen za Kilo agente; kliknite da ga isključite",
|
||||
"agentManager.caffeination.active": "Računar se održava budnim dok Kilo agenti rade",
|
||||
"agentManager.caffeination.unavailable": "Režim održavanja računara budnim nije dostupan na ovoj platformi",
|
||||
"agentManager.browser.title": "Preglednik",
|
||||
"agentManager.browser.title": "Integrirani preglednik",
|
||||
"agentManager.browser.url": "URL lokalne aplikacije",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Otvori",
|
||||
@@ -436,7 +436,8 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Osvježi preglednik",
|
||||
"agentManager.browser.close": "Zatvori preglednik",
|
||||
"agentManager.browser.empty": "Otvorite lokalnu aplikaciju da biste je ovdje pregledali.",
|
||||
"agentManager.browser.noSession": "Najprije odaberite sesiju aplikacije Agent Manager.",
|
||||
"agentManager.browser.noSession":
|
||||
"Pokrenite ili odaberite sesiju u Agent Manageru da biste pregledali lokalnu aplikaciju.",
|
||||
"agentManager.browser.screenshotAlt": "Trenutna stranica preglednika",
|
||||
"agentManager.browser.errors": "Problemi preglednika: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Dijagnostika preglednika",
|
||||
|
||||
+2
-2
@@ -429,7 +429,7 @@ export const dict = {
|
||||
"agentManager.caffeination.active": "Holder computeren vågen, mens Kilo-agenterne arbejder",
|
||||
"agentManager.caffeination.unavailable":
|
||||
"Tilstanden til at holde computeren vågen er ikke tilgængelig på denne platform",
|
||||
"agentManager.browser.title": "Browser",
|
||||
"agentManager.browser.title": "Integreret browser",
|
||||
"agentManager.browser.url": "URL til lokal applikation",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Åbn",
|
||||
@@ -438,7 +438,7 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Opdater browser",
|
||||
"agentManager.browser.close": "Luk browser",
|
||||
"agentManager.browser.empty": "Åbn en lokal applikation for at få vist en forhåndsvisning her.",
|
||||
"agentManager.browser.noSession": "Vælg først en session i Agent Manager.",
|
||||
"agentManager.browser.noSession": "Start eller vælg en session i Agent Manager for at gennemse en lokal applikation.",
|
||||
"agentManager.browser.screenshotAlt": "Aktuel browserside",
|
||||
"agentManager.browser.errors": "Browserproblemer: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Browserdiagnostik",
|
||||
|
||||
@@ -434,7 +434,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "Wachhaltemodus für Kilo-Agenten aktiviert; zum Deaktivieren klicken",
|
||||
"agentManager.caffeination.active": "Computer wird wach gehalten, während Kilo-Agenten arbeiten",
|
||||
"agentManager.caffeination.unavailable": "Der Wachhaltemodus ist auf dieser Plattform nicht verfügbar",
|
||||
"agentManager.browser.title": "Browser",
|
||||
"agentManager.browser.title": "Integrierter Browser",
|
||||
"agentManager.browser.url": "URL der lokalen Anwendung",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Öffnen",
|
||||
@@ -443,7 +443,8 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Browser aktualisieren",
|
||||
"agentManager.browser.close": "Browser schließen",
|
||||
"agentManager.browser.empty": "Öffnen Sie eine lokale Anwendung, um sie hier in der Vorschau anzuzeigen.",
|
||||
"agentManager.browser.noSession": "Wählen Sie zuerst eine Sitzung im Agent Manager aus.",
|
||||
"agentManager.browser.noSession":
|
||||
"Starten oder wählen Sie eine Sitzung im Agent Manager, um eine lokale Anwendung zu öffnen.",
|
||||
"agentManager.browser.screenshotAlt": "Aktuelle Browserseite",
|
||||
"agentManager.browser.errors": "Browserprobleme: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Browserdiagnose",
|
||||
|
||||
@@ -435,7 +435,7 @@ export const dict = {
|
||||
"agentManager.documents.preview": "Preview document",
|
||||
"agentManager.documents.source": "Show source",
|
||||
"agentManager.documents.comments": "{{count}} comments",
|
||||
"agentManager.browser.title": "Browser",
|
||||
"agentManager.browser.title": "Integrated Browser",
|
||||
"agentManager.browser.url": "Local application URL",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Open",
|
||||
@@ -444,7 +444,7 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Refresh browser",
|
||||
"agentManager.browser.close": "Close browser",
|
||||
"agentManager.browser.empty": "Open a local application to preview it here.",
|
||||
"agentManager.browser.noSession": "Select an Agent Manager session first.",
|
||||
"agentManager.browser.noSession": "Start or select a session in Agent Manager to browse a local application.",
|
||||
"agentManager.browser.screenshotAlt": "Current browser page",
|
||||
"agentManager.browser.errors": "Browser issues: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Browser diagnostics",
|
||||
|
||||
+3
-2
@@ -434,7 +434,7 @@ export const dict = {
|
||||
"agentManager.caffeination.active": "Manteniendo el equipo activo mientras trabajan los agentes de Kilo",
|
||||
"agentManager.caffeination.unavailable":
|
||||
"El modo para mantener el equipo activo no está disponible en esta plataforma",
|
||||
"agentManager.browser.title": "Navegador",
|
||||
"agentManager.browser.title": "Navegador integrado",
|
||||
"agentManager.browser.url": "URL de la aplicación local",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Abrir",
|
||||
@@ -443,7 +443,8 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Actualizar navegador",
|
||||
"agentManager.browser.close": "Cerrar navegador",
|
||||
"agentManager.browser.empty": "Abre una aplicación local para previsualizarla aquí.",
|
||||
"agentManager.browser.noSession": "Selecciona primero una sesión de Agent Manager.",
|
||||
"agentManager.browser.noSession":
|
||||
"Inicia o selecciona una sesión en Agent Manager para navegar por una aplicación local.",
|
||||
"agentManager.browser.screenshotAlt": "Página actual del navegador",
|
||||
"agentManager.browser.errors": "Problemas del navegador: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Diagnóstico del navegador",
|
||||
|
||||
+2
-2
@@ -430,7 +430,7 @@ export const dict = {
|
||||
"حالت بیدار نگه داشتن رایانه برای عاملهای Kilo فعال است؛ برای غیرفعال کردن کلیک کنید",
|
||||
"agentManager.caffeination.active": "رایانه هنگام کار عاملهای Kilo بیدار نگه داشته میشود",
|
||||
"agentManager.caffeination.unavailable": "حالت بیدار نگه داشتن رایانه در این پلتفرم در دسترس نیست",
|
||||
"agentManager.browser.title": "مرورگر",
|
||||
"agentManager.browser.title": "مرورگر یکپارچه",
|
||||
"agentManager.browser.url": "URL برنامه محلی",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "باز کردن",
|
||||
@@ -439,7 +439,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "انتخاب عنصر",
|
||||
"agentManager.browser.devtoolsTitle": "ابزارهای توسعه",
|
||||
"agentManager.browser.empty": "برای پیشنمایش، یک برنامه محلی را باز کنید.",
|
||||
"agentManager.browser.noSession": "ابتدا یک جلسه Agent Manager را انتخاب کنید.",
|
||||
"agentManager.browser.noSession": "برای مرور یک برنامه محلی، یک جلسه در Agent Manager شروع یا انتخاب کنید.",
|
||||
"agentManager.browser.screenshotAlt": "صفحه فعلی مرورگر",
|
||||
"agentManager.browser.errors": "مشکلات مرورگر: {{count}}",
|
||||
"agentManager.browser.diagnostics": "عیبیابی مرورگر",
|
||||
|
||||
+3
-2
@@ -434,7 +434,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "Mode anti-veille activé pour les agents Kilo ; cliquez pour désactiver",
|
||||
"agentManager.caffeination.active": "Ordinateur maintenu éveillé pendant que les agents Kilo travaillent",
|
||||
"agentManager.caffeination.unavailable": "Le mode veille active n'est pas disponible sur cette plateforme",
|
||||
"agentManager.browser.title": "Navigateur",
|
||||
"agentManager.browser.title": "Navigateur intégré",
|
||||
"agentManager.browser.url": "URL de l'application locale",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Ouvrir",
|
||||
@@ -443,7 +443,8 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Actualiser le navigateur",
|
||||
"agentManager.browser.close": "Fermer le navigateur",
|
||||
"agentManager.browser.empty": "Ouvrez une application locale pour l'afficher ici en aperçu.",
|
||||
"agentManager.browser.noSession": "Sélectionnez d'abord une session dans Agent Manager.",
|
||||
"agentManager.browser.noSession":
|
||||
"Démarrez ou sélectionnez une session dans Agent Manager pour parcourir une application locale.",
|
||||
"agentManager.browser.screenshotAlt": "Page actuelle du navigateur",
|
||||
"agentManager.browser.errors": "Problèmes du navigateur : {{count}}",
|
||||
"agentManager.browser.diagnostics": "Diagnostics du navigateur",
|
||||
|
||||
+3
-2
@@ -440,7 +440,7 @@ export const dict = {
|
||||
"agentManager.caffeination.active": "Computer mantenuto attivo mentre gli agenti Kilo lavorano",
|
||||
"agentManager.caffeination.unavailable":
|
||||
"La modalità per mantenere il computer attivo non è disponibile su questa piattaforma",
|
||||
"agentManager.browser.title": "Browser",
|
||||
"agentManager.browser.title": "Browser integrato",
|
||||
"agentManager.browser.url": "URL dell'applicazione locale",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Apri",
|
||||
@@ -449,7 +449,8 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Aggiorna browser",
|
||||
"agentManager.browser.close": "Chiudi browser",
|
||||
"agentManager.browser.empty": "Apri un'applicazione locale per visualizzarla qui.",
|
||||
"agentManager.browser.noSession": "Seleziona prima una sessione di Agent Manager.",
|
||||
"agentManager.browser.noSession":
|
||||
"Avvia o seleziona una sessione in Agent Manager per navigare in un'applicazione locale.",
|
||||
"agentManager.browser.screenshotAlt": "Pagina corrente del browser",
|
||||
"agentManager.browser.errors": "Problemi del browser: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Diagnostica del browser",
|
||||
|
||||
+3
-2
@@ -427,7 +427,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "Kilo エージェント用のスリープ防止モードが有効です。クリックして無効にします",
|
||||
"agentManager.caffeination.active": "Kilo エージェントの作業中もコンピューターをスリープさせません",
|
||||
"agentManager.caffeination.unavailable": "このプラットフォームではスリープ防止モードを利用できません",
|
||||
"agentManager.browser.title": "ブラウザー",
|
||||
"agentManager.browser.title": "統合ブラウザー",
|
||||
"agentManager.browser.url": "ローカルアプリケーション URL",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "開く",
|
||||
@@ -436,7 +436,8 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "要素を選択",
|
||||
"agentManager.browser.devtoolsTitle": "開発者ツール",
|
||||
"agentManager.browser.empty": "ローカルアプリケーションを開くと、ここでプレビューできます。",
|
||||
"agentManager.browser.noSession": "先に Agent Manager セッションを選択してください。",
|
||||
"agentManager.browser.noSession":
|
||||
"ローカルアプリケーションを表示するには、Agent Manager でセッションを開始または選択してください。",
|
||||
"agentManager.browser.screenshotAlt": "現在のブラウザーページ",
|
||||
"agentManager.browser.errors": "ブラウザーの問題: {{count}} 件",
|
||||
"agentManager.browser.diagnostics": "ブラウザー診断",
|
||||
|
||||
+2
-2
@@ -425,7 +425,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "Kilo 에이전트용 절전 방지 모드가 활성화되었습니다. 클릭하여 비활성화",
|
||||
"agentManager.caffeination.active": "Kilo 에이전트가 작업하는 동안 컴퓨터를 절전 모드로 전환하지 않습니다",
|
||||
"agentManager.caffeination.unavailable": "이 플랫폼에서는 절전 방지 모드를 사용할 수 없습니다",
|
||||
"agentManager.browser.title": "브라우저",
|
||||
"agentManager.browser.title": "통합 브라우저",
|
||||
"agentManager.browser.url": "로컬 애플리케이션 URL",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "열기",
|
||||
@@ -434,7 +434,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "요소 선택",
|
||||
"agentManager.browser.devtoolsTitle": "개발자 도구",
|
||||
"agentManager.browser.empty": "로컬 애플리케이션을 열어 여기에서 미리 보세요.",
|
||||
"agentManager.browser.noSession": "먼저 Agent Manager 세션을 선택하세요.",
|
||||
"agentManager.browser.noSession": "로컬 애플리케이션을 탐색하려면 Agent Manager에서 세션을 시작하거나 선택하세요.",
|
||||
"agentManager.browser.screenshotAlt": "현재 브라우저 페이지",
|
||||
"agentManager.browser.errors": "브라우저 문제: {{count}}개",
|
||||
"agentManager.browser.diagnostics": "브라우저 진단",
|
||||
|
||||
+3
-2
@@ -436,7 +436,7 @@ export const dict = {
|
||||
"agentManager.caffeination.active": "Computer wordt wakker gehouden terwijl Kilo-agents werken",
|
||||
"agentManager.caffeination.unavailable":
|
||||
"De modus om de computer wakker te houden is niet beschikbaar op dit platform",
|
||||
"agentManager.browser.title": "Browser",
|
||||
"agentManager.browser.title": "Geïntegreerde browser",
|
||||
"agentManager.browser.url": "URL van lokale applicatie",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Openen",
|
||||
@@ -445,7 +445,8 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Browser vernieuwen",
|
||||
"agentManager.browser.close": "Browser sluiten",
|
||||
"agentManager.browser.empty": "Open een lokale applicatie om deze hier te bekijken.",
|
||||
"agentManager.browser.noSession": "Selecteer eerst een sessie in Agent Manager.",
|
||||
"agentManager.browser.noSession":
|
||||
"Start of selecteer een sessie in Agent Manager om een lokale applicatie te bekijken.",
|
||||
"agentManager.browser.screenshotAlt": "Huidige browserpagina",
|
||||
"agentManager.browser.errors": "Browserproblemen: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Browserdiagnostiek",
|
||||
|
||||
+2
-2
@@ -427,7 +427,7 @@ export const dict = {
|
||||
"agentManager.caffeination.active": "Holder datamaskinen våken mens Kilo-agentene arbeider",
|
||||
"agentManager.caffeination.unavailable":
|
||||
"Modus for å holde datamaskinen våken er ikke tilgjengelig på denne plattformen",
|
||||
"agentManager.browser.title": "Nettleser",
|
||||
"agentManager.browser.title": "Integrert nettleser",
|
||||
"agentManager.browser.url": "URL for lokal applikasjon",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Åpne",
|
||||
@@ -436,7 +436,7 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Oppdater nettleser",
|
||||
"agentManager.browser.close": "Lukk nettleser",
|
||||
"agentManager.browser.empty": "Åpne en lokal applikasjon for å forhåndsvise den her.",
|
||||
"agentManager.browser.noSession": "Velg en økt i Agent Manager først.",
|
||||
"agentManager.browser.noSession": "Start eller velg en økt i Agent Manager for å bla i en lokal applikasjon.",
|
||||
"agentManager.browser.screenshotAlt": "Gjeldende nettleserside",
|
||||
"agentManager.browser.errors": "Nettleserproblemer: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Nettleserdiagnostikk",
|
||||
|
||||
+2
-2
@@ -428,7 +428,7 @@ export const dict = {
|
||||
"Tryb zapobiegania uśpieniu komputera włączony dla agentów Kilo; kliknij, aby wyłączyć",
|
||||
"agentManager.caffeination.active": "Komputer pozostaje aktywny, gdy agenci Kilo pracują",
|
||||
"agentManager.caffeination.unavailable": "Tryb utrzymywania komputera aktywnego jest niedostępny na tej platformie",
|
||||
"agentManager.browser.title": "Przeglądarka",
|
||||
"agentManager.browser.title": "Zintegrowana przeglądarka",
|
||||
"agentManager.browser.url": "URL lokalnej aplikacji",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Otwórz",
|
||||
@@ -437,7 +437,7 @@ export const dict = {
|
||||
"agentManager.browser.refresh": "Odśwież przeglądarkę",
|
||||
"agentManager.browser.close": "Zamknij przeglądarkę",
|
||||
"agentManager.browser.empty": "Otwórz lokalną aplikację, aby wyświetlić ją tutaj.",
|
||||
"agentManager.browser.noSession": "Najpierw wybierz sesję aplikacji Agent Manager.",
|
||||
"agentManager.browser.noSession": "Uruchom lub wybierz sesję w Agent Manager, aby przeglądać lokalną aplikację.",
|
||||
"agentManager.browser.screenshotAlt": "Bieżąca strona przeglądarki",
|
||||
"agentManager.browser.errors": "Problemy przeglądarki: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Diagnostyka przeglądarki",
|
||||
|
||||
+2
-2
@@ -430,7 +430,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "Режим предотвращения сна включён для агентов Kilo; нажмите для отключения",
|
||||
"agentManager.caffeination.active": "Компьютер не переходит в спящий режим, пока работают агенты Kilo",
|
||||
"agentManager.caffeination.unavailable": "Режим предотвращения сна недоступен на этой платформе",
|
||||
"agentManager.browser.title": "Браузер",
|
||||
"agentManager.browser.title": "Встроенный браузер",
|
||||
"agentManager.browser.url": "URL локального приложения",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Открыть",
|
||||
@@ -439,7 +439,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "Выбрать элемент",
|
||||
"agentManager.browser.devtoolsTitle": "Инструменты разработчика",
|
||||
"agentManager.browser.empty": "Откройте локальное приложение, чтобы просмотреть его здесь.",
|
||||
"agentManager.browser.noSession": "Сначала выберите сеанс Agent Manager.",
|
||||
"agentManager.browser.noSession": "Запустите или выберите сеанс в Agent Manager, чтобы открыть локальное приложение.",
|
||||
"agentManager.browser.screenshotAlt": "Текущая страница браузера",
|
||||
"agentManager.browser.errors": "Проблемы браузера: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Диагностика браузера",
|
||||
|
||||
+2
-2
@@ -419,7 +419,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "เปิดโหมดป้องกันการพักเครื่องสำหรับเอเจนต์ Kilo แล้ว คลิกเพื่อปิดใช้งาน",
|
||||
"agentManager.caffeination.active": "กำลังป้องกันคอมพิวเตอร์เข้าสู่โหมดพักขณะเอเจนต์ Kilo ทำงาน",
|
||||
"agentManager.caffeination.unavailable": "โหมดป้องกันการพักเครื่องไม่พร้อมใช้งานบนแพลตฟอร์มนี้",
|
||||
"agentManager.browser.title": "เบราว์เซอร์",
|
||||
"agentManager.browser.title": "เบราว์เซอร์ในตัว",
|
||||
"agentManager.browser.url": "URL ของแอปพลิเคชันในเครื่อง",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "เปิด",
|
||||
@@ -428,7 +428,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "เลือกองค์ประกอบ",
|
||||
"agentManager.browser.devtoolsTitle": "เครื่องมือสำหรับนักพัฒนา",
|
||||
"agentManager.browser.empty": "เปิดแอปพลิเคชันในเครื่องเพื่อดูตัวอย่างที่นี่",
|
||||
"agentManager.browser.noSession": "เลือกเซสชัน Agent Manager ก่อน",
|
||||
"agentManager.browser.noSession": "เริ่มหรือเลือกเซสชันใน Agent Manager เพื่อเรียกดูแอปพลิเคชันในเครื่อง",
|
||||
"agentManager.browser.screenshotAlt": "หน้าปัจจุบันของเบราว์เซอร์",
|
||||
"agentManager.browser.errors": "ปัญหาเบราว์เซอร์: {{count}} รายการ",
|
||||
"agentManager.browser.diagnostics": "การวินิจฉัยเบราว์เซอร์",
|
||||
|
||||
+3
-2
@@ -436,7 +436,7 @@ export const dict = {
|
||||
"Kilo ajanları için bilgisayarı uyanık tutma modu etkin; devre dışı bırakmak için tıklayın",
|
||||
"agentManager.caffeination.active": "Kilo ajanları çalışırken bilgisayar uyanık tutuluyor",
|
||||
"agentManager.caffeination.unavailable": "Bilgisayarı uyanık tutma modu bu platformda kullanılamıyor",
|
||||
"agentManager.browser.title": "Tarayıcı",
|
||||
"agentManager.browser.title": "Entegre Tarayıcı",
|
||||
"agentManager.browser.url": "Yerel uygulama URL'si",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Aç",
|
||||
@@ -445,7 +445,8 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "Öğeyi seç",
|
||||
"agentManager.browser.devtoolsTitle": "Geliştirici araçları",
|
||||
"agentManager.browser.empty": "Burada önizlemek için yerel bir uygulama açın.",
|
||||
"agentManager.browser.noSession": "Önce bir Agent Manager oturumu seçin.",
|
||||
"agentManager.browser.noSession":
|
||||
"Yerel bir uygulamada gezinmek için Agent Manager'da bir oturum başlatın veya seçin.",
|
||||
"agentManager.browser.screenshotAlt": "Geçerli tarayıcı sayfası",
|
||||
"agentManager.browser.errors": "Tarayıcı sorunları: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Tarayıcı tanılaması",
|
||||
|
||||
+2
-2
@@ -438,7 +438,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "Режим запобігання сну ввімкнено для агентів Kilo; натисніть, щоб вимкнути",
|
||||
"agentManager.caffeination.active": "Комп'ютер не переходить у режим сну, доки працюють агенти Kilo",
|
||||
"agentManager.caffeination.unavailable": "Режим запобігання сну недоступний на цій платформі",
|
||||
"agentManager.browser.title": "Браузер",
|
||||
"agentManager.browser.title": "Вбудований браузер",
|
||||
"agentManager.browser.url": "URL локальної програми",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "Відкрити",
|
||||
@@ -447,7 +447,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "Вибрати елемент",
|
||||
"agentManager.browser.devtoolsTitle": "Інструменти розробника",
|
||||
"agentManager.browser.empty": "Відкрийте локальну програму, щоб переглянути її тут.",
|
||||
"agentManager.browser.noSession": "Спочатку виберіть сесію Agent Manager.",
|
||||
"agentManager.browser.noSession": "Запустіть або виберіть сесію в Agent Manager, щоб відкрити локальний застосунок.",
|
||||
"agentManager.browser.screenshotAlt": "Поточна сторінка браузера",
|
||||
"agentManager.browser.errors": "Проблеми браузера: {{count}}",
|
||||
"agentManager.browser.diagnostics": "Діагностика браузера",
|
||||
|
||||
+2
-2
@@ -415,7 +415,7 @@ export const dict = {
|
||||
"agentManager.caffeination.active": "Kilo 代理工作期间保持电脑唤醒",
|
||||
"agentManager.caffeination.unavailable": "此平台不支持保持唤醒模式",
|
||||
|
||||
"agentManager.browser.title": "浏览器",
|
||||
"agentManager.browser.title": "集成浏览器",
|
||||
"agentManager.browser.url": "本地应用 URL",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "打开",
|
||||
@@ -424,7 +424,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "选择元素",
|
||||
"agentManager.browser.devtoolsTitle": "开发者工具",
|
||||
"agentManager.browser.empty": "打开本地应用以在此处预览。",
|
||||
"agentManager.browser.noSession": "请先选择 Agent Manager 会话。",
|
||||
"agentManager.browser.noSession": "请在 Agent Manager 中启动或选择会话以浏览本地应用。",
|
||||
"agentManager.browser.screenshotAlt": "当前浏览器页面",
|
||||
"agentManager.browser.errors": "浏览器问题:{{count}}",
|
||||
"agentManager.browser.diagnostics": "浏览器诊断",
|
||||
|
||||
+2
-2
@@ -414,7 +414,7 @@ export const dict = {
|
||||
"agentManager.caffeination.armed": "已為 Kilo 代理啟用保持喚醒模式;點擊以停用",
|
||||
"agentManager.caffeination.active": "Kilo 代理工作期間保持電腦喚醒",
|
||||
"agentManager.caffeination.unavailable": "此平台無法使用保持喚醒模式",
|
||||
"agentManager.browser.title": "瀏覽器",
|
||||
"agentManager.browser.title": "整合瀏覽器",
|
||||
"agentManager.browser.url": "本機應用程式 URL",
|
||||
"agentManager.browser.urlPlaceholder": "http://localhost:3000",
|
||||
"agentManager.browser.open": "開啟",
|
||||
@@ -423,7 +423,7 @@ export const dict = {
|
||||
"agentManager.browser.inspect": "選取元素",
|
||||
"agentManager.browser.devtoolsTitle": "開發人員工具",
|
||||
"agentManager.browser.empty": "開啟本機應用程式,即可在此處預覽。",
|
||||
"agentManager.browser.noSession": "請先選取 Agent Manager 工作階段。",
|
||||
"agentManager.browser.noSession": "請在 Agent Manager 中啟動或選取工作階段以瀏覽本機應用程式。",
|
||||
"agentManager.browser.screenshotAlt": "目前的瀏覽器頁面",
|
||||
"agentManager.browser.errors": "瀏覽器問題:{{count}}",
|
||||
"agentManager.browser.diagnostics": "瀏覽器診斷",
|
||||
|
||||
@@ -24,9 +24,10 @@ export function createSidePanel(opts: {
|
||||
const id = opts.current()
|
||||
return id ? JSON.stringify([opts.project() ?? "single", id]) : undefined
|
||||
}
|
||||
// A draft can show the browser's no-session guidance without creating a backend session.
|
||||
const owner = () => session() ?? JSON.stringify([opts.project() ?? "single", opts.selection(), null])
|
||||
const selected = () => {
|
||||
const id = session()
|
||||
const override = id ? sessions()[id] : undefined
|
||||
const override = sessions()[owner()]
|
||||
return override !== undefined ? override : (worktrees()[worktree()] ?? null)
|
||||
}
|
||||
const panel = () => {
|
||||
@@ -36,21 +37,22 @@ export function createSidePanel(opts: {
|
||||
const open = (value: SidePanel) => {
|
||||
const id = session()
|
||||
if (ownership[value] === "session") {
|
||||
if (id) setSessions((prev) => ({ ...prev, [id]: value }))
|
||||
if (id || value === SidePanel.Browser) setSessions((prev) => ({ ...prev, [owner()]: value }))
|
||||
return
|
||||
}
|
||||
const key = worktree()
|
||||
batch(() => {
|
||||
setWorktrees((prev) => ({ ...prev, [key]: value }))
|
||||
if (id) setSessions((prev) => ({ ...prev, [id]: undefined }))
|
||||
setSessions((prev) => ({ ...prev, [owner()]: undefined }))
|
||||
})
|
||||
}
|
||||
const close = (expected?: SidePanel) => {
|
||||
const value = selected()
|
||||
if (!value || (expected && value !== expected)) return
|
||||
const id = session()
|
||||
if (ownership[value] === "session" && id) {
|
||||
setSessions((prev) => ({ ...prev, [id]: null }))
|
||||
if (ownership[value] === "session") {
|
||||
// A draft has no worktree panel to mask, so drop its entry instead of
|
||||
// storing an authoritative null that would hide later worktree panels.
|
||||
setSessions((prev) => ({ ...prev, [owner()]: session() ? null : undefined }))
|
||||
return
|
||||
}
|
||||
setWorktrees((prev) => ({ ...prev, [worktree()]: null }))
|
||||
|
||||
@@ -29,7 +29,9 @@ const BrowserTab: Component = () => {
|
||||
const { globalConfig, projectConfig, updateGlobalConfig } = useConfig()
|
||||
|
||||
const [settings, setSettings] = createSignal<BrowserSettings>({
|
||||
enabled: false,
|
||||
useSystemChrome: true,
|
||||
headless: false,
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
@@ -118,6 +120,16 @@ const BrowserTab: Component = () => {
|
||||
{t("settings.browser.description")}
|
||||
</p>
|
||||
<Card>
|
||||
{/* Enable toggle */}
|
||||
<SettingsRow
|
||||
title={t("settings.browser.enable.title")}
|
||||
description={t("settings.browser.enable.description")}
|
||||
>
|
||||
<Switch checked={settings().enabled} onChange={(checked: boolean) => update("enabled", checked)} hideLabel>
|
||||
{t("settings.browser.enable.title")}
|
||||
</Switch>
|
||||
</SettingsRow>
|
||||
|
||||
{/* Use System Chrome */}
|
||||
<SettingsRow
|
||||
title={t("settings.browser.systemChrome.title")}
|
||||
@@ -131,12 +143,18 @@ const BrowserTab: Component = () => {
|
||||
{t("settings.browser.systemChrome.title")}
|
||||
</Switch>
|
||||
</SettingsRow>
|
||||
|
||||
{/* Headless mode */}
|
||||
<SettingsRow
|
||||
title={t("settings.browser.headless.title")}
|
||||
description={t("settings.browser.headless.description")}
|
||||
last
|
||||
>
|
||||
<Switch checked disabled hideLabel>
|
||||
<Switch
|
||||
checked={settings().headless}
|
||||
onChange={(checked: boolean) => update("headless", checked)}
|
||||
hideLabel
|
||||
>
|
||||
{t("settings.browser.headless.title")}
|
||||
</Switch>
|
||||
</SettingsRow>
|
||||
|
||||
@@ -231,15 +231,30 @@ const ExperimentalTab: Component = () => {
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title={language.t("settings.browser.enable.title")}
|
||||
description={language.t("settings.browser.enable.description")}
|
||||
title={language.t("settings.experimental.browserAutomation.title")}
|
||||
description={language.t("settings.experimental.browserAutomation.description")}
|
||||
>
|
||||
<Switch
|
||||
checked={settings().browserAutomation === true}
|
||||
onChange={(checked) => applySetting("browserAutomation", checked, "experimental.browserAutomation")}
|
||||
hideLabel
|
||||
>
|
||||
{language.t("settings.browser.enable.title")}
|
||||
{language.t("settings.experimental.browserAutomation.title")}
|
||||
</Switch>
|
||||
</SettingsRow>
|
||||
|
||||
<SettingsRow
|
||||
title={language.t("settings.experimental.browserAutomation.systemChrome.title")}
|
||||
description={language.t("settings.experimental.browserAutomation.systemChrome.description")}
|
||||
>
|
||||
<Switch
|
||||
checked={settings().agentManagerBrowserUseSystemChrome !== false}
|
||||
onChange={(checked) =>
|
||||
applySetting("agentManagerBrowserUseSystemChrome", checked, "agentManager.browser.useSystemChrome")
|
||||
}
|
||||
hideLabel
|
||||
>
|
||||
{language.t("settings.experimental.browserAutomation.systemChrome.title")}
|
||||
</Switch>
|
||||
</SettingsRow>
|
||||
|
||||
|
||||
+7
-1
@@ -827,7 +827,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "المهارات",
|
||||
|
||||
"settings.browser.description":
|
||||
"عند التفعيل، يمكن لوكيل الذكاء الاصطناعي التفاعل مع صفحات الويب — التنقل والنقر والكتابة والتقاط لقطات الشاشة. سيتم فتح نافذة Chrome حتى تتمكن من مشاهدة الوكيل أثناء العمل.",
|
||||
"تكوين أتمتة المتصفح المدمجة المدعومة من Playwright. يمكن لـ Kilo التنقل والتفاعل مع صفحات الويب والتقاط لقطات شاشة لها في جلساتك.",
|
||||
"settings.browser.enable.title": "تفعيل أتمتة المتصفح",
|
||||
"settings.browser.enable.description": "تسجيل خادم Playwright MCP مع الواجهة الخلفية لـ CLI.",
|
||||
"settings.browser.systemChrome.title": "استخدام Chrome النظام",
|
||||
@@ -1325,5 +1325,11 @@ export const dict = {
|
||||
"chat.search.close": "إغلاق البحث",
|
||||
"chat.search.invalidRegex": "تعبير عادي غير صالح",
|
||||
"chat.search.noResults": "لا توجد نتائج",
|
||||
"settings.experimental.browserAutomation.title": "المتصفح المدمج",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"عرض معاينات التطبيقات المحلية في Agent Manager وإتاحة أداة browser_open لجلسات Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "استخدام Chrome النظام",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"استخدام Google Chrome المثبّت للمتصفح المدمج. عطّله فقط عند تثبيت متصفح Playwright Chromium متوافق.",
|
||||
"chat.search.searchingHistory": "جارٍ البحث في الرسائل السابقة…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -850,7 +850,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Habilidades",
|
||||
|
||||
"settings.browser.description":
|
||||
"Quando ativado, o agente de IA pode interagir com páginas da web — navegar, clicar, digitar e capturar telas. Uma janela do Chrome será aberta para que você possa acompanhar o trabalho do agente.",
|
||||
"Configure a automação de navegador integrada com tecnologia Playwright. O Kilo pode navegar, interagir e capturar telas de páginas da web nas suas sessões.",
|
||||
"settings.browser.enable.title": "Ativar Automação do Navegador",
|
||||
"settings.browser.enable.description": "Registrar o servidor Playwright MCP no backend CLI.",
|
||||
"settings.browser.systemChrome.title": "Usar Chrome do Sistema",
|
||||
@@ -1370,5 +1370,11 @@ export const dict = {
|
||||
"chat.search.close": "Fechar pesquisa",
|
||||
"chat.search.invalidRegex": "Expressão regular inválida",
|
||||
"chat.search.noResults": "Nenhum resultado",
|
||||
"settings.experimental.browserAutomation.title": "Navegador Integrado",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Mostre pré-visualizações de aplicativos locais no Agent Manager e exponha a ferramenta browser_open para sessões do Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Usar Chrome do Sistema",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Use o Google Chrome instalado para o Navegador Integrado. Desative apenas quando um navegador Playwright Chromium compatível já estiver instalado.",
|
||||
"chat.search.searchingHistory": "Pesquisando mensagens anteriores…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -847,7 +847,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Vještine",
|
||||
|
||||
"settings.browser.description":
|
||||
"Kada je omogućeno, AI agent može komunicirati s web stranicama — navigirati, klikati, tipkati i snimati ekran. Chrome prozor će se otvoriti kako biste mogli pratiti rad agenta.",
|
||||
"Konfigurirajte ugrađenu automatizaciju preglednika koju pokreće Playwright. Kilo može navigirati, komunicirati sa web stranicama i snimati ekran u vašim sesijama.",
|
||||
"settings.browser.enable.title": "Omogući automatizaciju preglednika",
|
||||
"settings.browser.enable.description": "Registriraj Playwright MCP server s CLI pozadinom.",
|
||||
"settings.browser.systemChrome.title": "Koristi sistemski Chrome",
|
||||
@@ -1361,5 +1361,11 @@ export const dict = {
|
||||
"chat.search.close": "Zatvori pretragu",
|
||||
"chat.search.invalidRegex": "Nevažeći regularni izraz",
|
||||
"chat.search.noResults": "Nema rezultata",
|
||||
"settings.experimental.browserAutomation.title": "Integrirani preglednik",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Prikažite preglede lokalnih aplikacija u Agent Manageru i omogućite alat browser_open sesijama Agent Managera.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Koristi sistemski Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Koristite instalirani Google Chrome za Integrirani preglednik. Onemogućite samo kada je kompatibilni Playwright Chromium preglednik već instaliran.",
|
||||
"chat.search.searchingHistory": "Pretraživanje ranijih poruka…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -846,7 +846,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Færdigheder",
|
||||
|
||||
"settings.browser.description":
|
||||
"Når aktiveret kan AI-agenten interagere med websider — navigere, klikke, skrive og tage skærmbilleder. Et Chrome-vindue åbnes, så du kan se agenten arbejde.",
|
||||
"Konfigurér indbygget browserautomatisering drevet af Playwright. Kilo kan navigere, interagere med og tage skærmbilleder af websider i dine sessioner.",
|
||||
"settings.browser.enable.title": "Aktivér browserautomatisering",
|
||||
"settings.browser.enable.description": "Registrér Playwright MCP-serveren hos CLI-backend'en.",
|
||||
"settings.browser.systemChrome.title": "Brug system-Chrome",
|
||||
@@ -1355,5 +1355,11 @@ export const dict = {
|
||||
"chat.search.close": "Luk søgning",
|
||||
"chat.search.invalidRegex": "Ugyldigt regulært udtryk",
|
||||
"chat.search.noResults": "Ingen resultater",
|
||||
"settings.experimental.browserAutomation.title": "Integreret browser",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Vis forhåndsvisninger af lokale applikationer i Agent Manager, og gør værktøjet browser_open tilgængeligt for Agent Manager-sessioner.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Brug system-Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Brug den installerede Google Chrome til den integrerede browser. Deaktivér kun, når en kompatibel Playwright Chromium-browser allerede er installeret.",
|
||||
"chat.search.searchingHistory": "Søger i tidligere beskeder…",
|
||||
}
|
||||
|
||||
@@ -861,7 +861,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Fähigkeiten",
|
||||
|
||||
"settings.browser.description":
|
||||
"Wenn aktiviert, kann der KI-Agent mit Webseiten interagieren — navigieren, klicken, tippen und Screenshots erstellen. Ein Chrome-Fenster wird geöffnet, damit Sie dem Agenten bei der Arbeit zusehen können.",
|
||||
"Integrierte Browser-Automatisierung auf Basis von Playwright konfigurieren. Kilo kann in Ihren Sitzungen Webseiten aufrufen, mit ihnen interagieren und Screenshots erstellen.",
|
||||
"settings.browser.enable.title": "Browser-Automatisierung aktivieren",
|
||||
"settings.browser.enable.description": "Den Playwright-MCP-Server beim CLI-Backend registrieren.",
|
||||
"settings.browser.systemChrome.title": "System-Chrome verwenden",
|
||||
@@ -1383,5 +1383,11 @@ export const dict = {
|
||||
"chat.search.close": "Suche schließen",
|
||||
"chat.search.invalidRegex": "Ungültiger regulärer Ausdruck",
|
||||
"chat.search.noResults": "Keine Ergebnisse",
|
||||
"settings.experimental.browserAutomation.title": "Integrierter Browser",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Lokale Anwendungsvorschauen im Agent Manager anzeigen und das Tool browser_open für Agent Manager-Sitzungen bereitstellen.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "System-Chrome verwenden",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Das installierte Google Chrome für den integrierten Browser verwenden. Nur deaktivieren, wenn bereits ein kompatibler Playwright-Chromium-Browser installiert ist.",
|
||||
"chat.search.searchingHistory": "Frühere Nachrichten werden durchsucht…",
|
||||
} satisfies Partial<Record<Keys, string>>
|
||||
|
||||
@@ -820,15 +820,14 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Skills",
|
||||
|
||||
"settings.browser.description":
|
||||
"Configure the browser runtime used by the experimental Agent Manager browser. The page preview stays in Agent Manager.",
|
||||
"Configure built-in browser automation powered by Playwright. Kilo can navigate, interact with, and screenshot web pages in your sessions.",
|
||||
"settings.browser.enable.title": "Enable Browser Automation",
|
||||
"settings.browser.enable.description": "Enable the session-scoped Agent Manager browser for local applications.",
|
||||
"settings.browser.enable.description": "Register the Playwright MCP server with the CLI backend.",
|
||||
"settings.browser.systemChrome.title": "Use System Chrome",
|
||||
"settings.browser.systemChrome.description":
|
||||
"Use installed Google Chrome. Disable only when a compatible Playwright Chromium browser is already installed.",
|
||||
"settings.browser.headless.title": "Headless Mode",
|
||||
"settings.browser.headless.description":
|
||||
"Agent Manager always runs the browser headlessly. The page preview appears in the Browser panel.",
|
||||
"settings.browser.headless.description": "Run in headless mode (no visible browser window).",
|
||||
|
||||
"settings.language.description":
|
||||
'Choose the language for the Kilo Code UI. "Auto" uses your VS Code display language.',
|
||||
@@ -924,6 +923,12 @@ export const dict = {
|
||||
"settings.experimental.multiProject.title": "Multi-Project Agent Manager",
|
||||
"settings.experimental.multiProject.description":
|
||||
"Enable managing sessions and worktrees across multiple repositories in Agent Manager. The current workspace repository is always the default project.",
|
||||
"settings.experimental.browserAutomation.title": "Integrated Browser",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Show local application previews in Agent Manager and expose the browser_open tool to Agent Manager sessions.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Use System Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Use installed Google Chrome for the Integrated Browser. Disable only when a compatible Playwright Chromium browser is already installed.",
|
||||
"settings.experimental.claudeMigration.title": "Claude Code Migration",
|
||||
"settings.experimental.claudeMigration.description":
|
||||
"On the next backend start, import supported global CLAUDE.md instructions, simple skills, and disabled MCP definitions. This runs once with no automatic retry; global Claude instructions and skills are then handed off to Kilo. Claude files stay unchanged; keep them if you still use Claude Code.",
|
||||
|
||||
+7
-1
@@ -853,7 +853,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Habilidades",
|
||||
|
||||
"settings.browser.description":
|
||||
"Cuando está activado, el agente de IA puede interactuar con páginas web: navegar, hacer clic, escribir y capturar pantallas. Se abrirá una ventana de Chrome para que puedas ver al agente trabajar.",
|
||||
"Configura la automatización de navegador integrada basada en Playwright. Kilo puede navegar, interactuar y capturar pantallas de páginas web en tus sesiones.",
|
||||
"settings.browser.enable.title": "Activar automatización del navegador",
|
||||
"settings.browser.enable.description": "Registrar el servidor Playwright MCP con el backend CLI.",
|
||||
"settings.browser.systemChrome.title": "Usar Chrome del sistema",
|
||||
@@ -1371,5 +1371,11 @@ export const dict = {
|
||||
"chat.search.close": "Cerrar búsqueda",
|
||||
"chat.search.invalidRegex": "Expresión regular no válida",
|
||||
"chat.search.noResults": "Sin resultados",
|
||||
"settings.experimental.browserAutomation.title": "Navegador integrado",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Muestra vistas previas de aplicaciones locales en Agent Manager y expone la herramienta browser_open a las sesiones de Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Usar Chrome del sistema",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Usa el Google Chrome instalado para el Navegador integrado. Desactívalo solo si ya hay instalado un navegador Playwright Chromium compatible.",
|
||||
"chat.search.searchingHistory": "Buscando en mensajes anteriores…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -827,7 +827,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "مهارتها",
|
||||
|
||||
"settings.browser.description":
|
||||
"وقتی فعال است، عامل هوش مصنوعی میتواند با صفحات وب تعامل داشته باشد — پیمایش، کلیک، تایپ و گرفتن اسکرینشات. یک پنجره Chrome باز میشود تا بتوانید عملکرد عامل را مشاهده کنید.",
|
||||
"پیکربندی اتوماسیون مرورگر داخلی با پشتیبانی Playwright. Kilo میتواند در جلسات شما در صفحات وب پیمایش کند، با آنها تعامل داشته باشد و اسکرینشات بگیرد.",
|
||||
"settings.browser.enable.title": "فعالسازی اتوماسیون مرورگر",
|
||||
"settings.browser.enable.description": "سرور Playwright MCP را با بکاند CLI ثبت کنید.",
|
||||
"settings.browser.systemChrome.title": "استفاده از Chrome سیستم",
|
||||
@@ -1355,5 +1355,11 @@ export const dict = {
|
||||
"chat.search.close": "بستن جستجو",
|
||||
"chat.search.invalidRegex": "عبارت منظم نامعتبر",
|
||||
"chat.search.noResults": "نتیجهای یافت نشد",
|
||||
"settings.experimental.browserAutomation.title": "مرورگر یکپارچه",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"پیشنمایش برنامههای محلی را در Agent Manager نشان دهید و ابزار browser_open را در اختیار جلسات Agent Manager قرار دهید.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "استفاده از Chrome سیستم",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"از Google Chrome نصبشده برای مرورگر یکپارچه استفاده کنید. فقط زمانی غیرفعال کنید که مرورگر Playwright Chromium سازگار از قبل نصب شده باشد.",
|
||||
"chat.search.searchingHistory": "در حال جستجو در پیامهای قبلی…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -863,7 +863,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Compétences",
|
||||
|
||||
"settings.browser.description":
|
||||
"Lorsqu'il est activé, l'agent IA peut interagir avec les pages web — naviguer, cliquer, saisir du texte et prendre des captures d'écran. Une fenêtre Chrome s'ouvrira pour que vous puissiez observer l'agent travailler.",
|
||||
"Configurez l'automatisation de navigateur intégrée propulsée par Playwright. Kilo peut naviguer, interagir et prendre des captures d'écran de pages web dans vos sessions.",
|
||||
"settings.browser.enable.title": "Activer l'automatisation du navigateur",
|
||||
"settings.browser.enable.description": "Enregistrer le serveur Playwright MCP auprès du backend CLI.",
|
||||
"settings.browser.systemChrome.title": "Utiliser le Chrome système",
|
||||
@@ -1392,5 +1392,11 @@ export const dict = {
|
||||
"chat.search.close": "Fermer la recherche",
|
||||
"chat.search.invalidRegex": "Expression régulière non valide",
|
||||
"chat.search.noResults": "Aucun résultat",
|
||||
"settings.experimental.browserAutomation.title": "Navigateur intégré",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Affichez des aperçus d'applications locales dans Agent Manager et exposez l'outil browser_open aux sessions Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Utiliser le Chrome système",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Utilisez le Google Chrome installé pour le Navigateur intégré. Désactivez uniquement lorsqu'un navigateur Playwright Chromium compatible est déjà installé.",
|
||||
"chat.search.searchingHistory": "Recherche dans les messages précédents…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -711,7 +711,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.workflows": "Workflow",
|
||||
"settings.agentBehaviour.subtab.skills": "Skill",
|
||||
"settings.browser.description":
|
||||
"Quando è abilitato, l'agente AI può interagire con pagine web: navigare, fare clic, scrivere e acquisire screenshot. Si aprirà una finestra Chrome così puoi osservare il lavoro dell'agente.",
|
||||
"Configura l'automazione del browser integrata basata su Playwright. Kilo può navigare, interagire e acquisire screenshot delle pagine web nelle tue sessioni.",
|
||||
"settings.browser.enable.title": "Abilita automazione browser",
|
||||
"settings.browser.enable.description": "Registra il server MCP Playwright con il backend CLI.",
|
||||
"settings.browser.systemChrome.title": "Usa Chrome di sistema",
|
||||
@@ -1337,5 +1337,11 @@ export const dict = {
|
||||
"chat.search.close": "Chiudi ricerca",
|
||||
"chat.search.invalidRegex": "Espressione regolare non valida",
|
||||
"chat.search.noResults": "Nessun risultato",
|
||||
"settings.experimental.browserAutomation.title": "Browser integrato",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Mostra le anteprime delle applicazioni locali in Agent Manager ed esponi lo strumento browser_open alle sessioni di Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Usa Chrome di sistema",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Usa il Google Chrome installato per il Browser integrato. Disattivalo solo se è già installato un browser Playwright Chromium compatibile.",
|
||||
"chat.search.searchingHistory": "Ricerca nei messaggi precedenti…",
|
||||
} as const
|
||||
|
||||
+7
-1
@@ -841,7 +841,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "スキル",
|
||||
|
||||
"settings.browser.description":
|
||||
"有効にすると、AIエージェントがWebページを操作できるようになります — ナビゲーション、クリック、入力、スクリーンショットの撮影。Chromeウィンドウが開き、エージェントの作業を確認できます。",
|
||||
"Playwrightを利用した組み込みブラウザ自動化を設定します。Kiloはセッション内でWebページのナビゲーション、操作、スクリーンショット撮影を行えます。",
|
||||
"settings.browser.enable.title": "ブラウザ自動化を有効にする",
|
||||
"settings.browser.enable.description": "Playwright MCPサーバーをCLIバックエンドに登録します。",
|
||||
"settings.browser.systemChrome.title": "システムChromeを使用",
|
||||
@@ -1347,5 +1347,11 @@ export const dict = {
|
||||
"chat.search.close": "検索を閉じる",
|
||||
"chat.search.invalidRegex": "正規表現が無効です",
|
||||
"chat.search.noResults": "見つかりませんでした",
|
||||
"settings.experimental.browserAutomation.title": "統合ブラウザー",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Agent Manager でローカルアプリケーションのプレビューを表示し、browser_open ツールを Agent Manager セッションに公開します。",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "システムChromeを使用",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"統合ブラウザーにインストール済みの Google Chrome を使用します。互換性のある Playwright Chromium ブラウザーが既にインストールされている場合にのみ無効にしてください。",
|
||||
"chat.search.searchingHistory": "以前のメッセージを検索しています…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -839,7 +839,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "스킬",
|
||||
|
||||
"settings.browser.description":
|
||||
"활성화하면 AI 에이전트가 웹 페이지와 상호작용할 수 있습니다 — 탐색, 클릭, 입력, 스크린샷 촬영. Chrome 창이 열려 에이전트의 작업을 확인할 수 있습니다.",
|
||||
"Playwright 기반의 내장 브라우저 자동화를 구성합니다. Kilo는 세션에서 웹 페이지를 탐색하고 상호 작용하며 스크린샷을 찍을 수 있습니다.",
|
||||
"settings.browser.enable.title": "브라우저 자동화 활성화",
|
||||
"settings.browser.enable.description": "Playwright MCP 서버를 CLI 백엔드에 등록합니다.",
|
||||
"settings.browser.systemChrome.title": "시스템 Chrome 사용",
|
||||
@@ -1334,5 +1334,11 @@ export const dict = {
|
||||
"chat.search.close": "검색 닫기",
|
||||
"chat.search.invalidRegex": "정규식이 잘못되었습니다",
|
||||
"chat.search.noResults": "검색 결과 없음",
|
||||
"settings.experimental.browserAutomation.title": "통합 브라우저",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Agent Manager에서 로컬 애플리케이션 미리보기를 표시하고 browser_open 도구를 Agent Manager 세션에 노출합니다.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "시스템 Chrome 사용",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"통합 브라우저에 설치된 Google Chrome을 사용합니다. 호환되는 Playwright Chromium 브라우저가 이미 설치된 경우에만 비활성화하세요.",
|
||||
"chat.search.searchingHistory": "이전 메시지를 검색하는 중…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -839,7 +839,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Skills",
|
||||
|
||||
"settings.browser.description":
|
||||
"Indien ingeschakeld kan de AI agent interactie hebben met webpagina's — navigeren, klikken, typen en screenshots maken. Er wordt een Chrome-venster geopend zodat je de agent aan het werk kunt zien.",
|
||||
"Configureer ingebouwde browserautomatisering mogelijk gemaakt door Playwright. Kilo kan in je sessies door webpagina's navigeren, ermee werken en schermafbeeldingen maken.",
|
||||
"settings.browser.enable.title": "Browserautomatisering inschakelen",
|
||||
"settings.browser.enable.description": "Registreer de Playwright MCP-server bij de CLI backend.",
|
||||
"settings.browser.systemChrome.title": "Gebruik Systeem Chrome",
|
||||
@@ -1383,5 +1383,11 @@ export const dict = {
|
||||
"chat.search.close": "Zoeken sluiten",
|
||||
"chat.search.invalidRegex": "Ongeldige reguliere expressie",
|
||||
"chat.search.noResults": "Geen resultaten",
|
||||
"settings.experimental.browserAutomation.title": "Geïntegreerde browser",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Toon voorbeelden van lokale applicaties in Agent Manager en stel de tool browser_open beschikbaar aan Agent Manager-sessies.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Gebruik Systeem Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Gebruik de geïnstalleerde Google Chrome voor de geïntegreerde browser. Schakel dit alleen uit als er al een compatibele Playwright Chromium-browser is geïnstalleerd.",
|
||||
"chat.search.searchingHistory": "Eerdere berichten doorzoeken…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -807,7 +807,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Ferdigheter",
|
||||
|
||||
"settings.browser.description":
|
||||
"Når aktivert kan AI-agenten samhandle med nettsider — navigere, klikke, skrive og ta skjermbilder. Et Chrome-vindu åpnes slik at du kan se agenten jobbe.",
|
||||
"Konfigurer innebygd nettleserautomatisering drevet av Playwright. Kilo kan navigere, samhandle med og ta skjermbilder av nettsider i øktene dine.",
|
||||
"settings.browser.enable.title": "Aktiver nettleserautomatisering",
|
||||
"settings.browser.enable.description": "Registrer Playwright MCP-serveren med CLI-backend.",
|
||||
"settings.browser.systemChrome.title": "Bruk system-Chrome",
|
||||
@@ -1352,5 +1352,11 @@ export const dict = {
|
||||
"chat.search.close": "Lukk søk",
|
||||
"chat.search.invalidRegex": "Ugyldig regulært uttrykk",
|
||||
"chat.search.noResults": "Ingen resultater",
|
||||
"settings.experimental.browserAutomation.title": "Integrert nettleser",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Vis forhåndsvisninger av lokale applikasjoner i Agent Manager, og gjør verktøyet browser_open tilgjengelig for Agent Manager-økter.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Bruk system-Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Bruk den installerte Google Chrome for den integrerte nettleseren. Deaktiver bare når en kompatibel Playwright Chromium-nettleser allerede er installert.",
|
||||
"chat.search.searchingHistory": "Søker i tidligere meldinger…",
|
||||
} satisfies Partial<Record<Keys, string>>
|
||||
|
||||
+7
-1
@@ -804,7 +804,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Umiejętności",
|
||||
|
||||
"settings.browser.description":
|
||||
"Po włączeniu agent AI może wchodzić w interakcję ze stronami internetowymi — nawigować, klikać, pisać i robić zrzuty ekranu. Otworzy się okno Chrome, abyś mógł obserwować pracę agenta.",
|
||||
"Skonfiguruj wbudowaną automatyzację przeglądarki opartą na Playwright. Kilo może nawigować po stronach internetowych, wchodzić z nimi w interakcję i robić zrzuty ekranu w Twoich sesjach.",
|
||||
"settings.browser.enable.title": "Włącz automatyzację przeglądarki",
|
||||
"settings.browser.enable.description": "Zarejestruj serwer Playwright MCP w backendzie CLI.",
|
||||
"settings.browser.systemChrome.title": "Użyj systemowego Chrome",
|
||||
@@ -1360,5 +1360,11 @@ export const dict = {
|
||||
"chat.search.close": "Zamknij wyszukiwanie",
|
||||
"chat.search.invalidRegex": "Nieprawidłowe wyrażenie regularne",
|
||||
"chat.search.noResults": "Brak wyników",
|
||||
"settings.experimental.browserAutomation.title": "Zintegrowana przeglądarka",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Wyświetlaj podglądy lokalnych aplikacji w Agent Manager i udostępniaj narzędzie browser_open sesjom Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Użyj systemowego Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Użyj zainstalowanej przeglądarki Google Chrome dla zintegrowanej przeglądarki. Wyłącz tylko wtedy, gdy zgodna przeglądarka Playwright Chromium jest już zainstalowana.",
|
||||
"chat.search.searchingHistory": "Wyszukiwanie we wcześniejszych wiadomościach…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -844,7 +844,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Навыки",
|
||||
|
||||
"settings.browser.description":
|
||||
"При включении ИИ-агент может взаимодействовать с веб-страницами — переходить по ссылкам, нажимать, вводить текст и делать скриншоты. Откроется окно Chrome, чтобы вы могли наблюдать за работой агента.",
|
||||
"Настройте встроенную автоматизацию браузера на основе Playwright. Kilo может переходить по веб-страницам, взаимодействовать с ними и делать скриншоты в ваших сессиях.",
|
||||
"settings.browser.enable.title": "Включить автоматизацию браузера",
|
||||
"settings.browser.enable.description": "Зарегистрировать сервер Playwright MCP в CLI-бэкенде.",
|
||||
"settings.browser.systemChrome.title": "Использовать системный Chrome",
|
||||
@@ -1354,5 +1354,11 @@ export const dict = {
|
||||
"chat.search.close": "Закрыть поиск",
|
||||
"chat.search.invalidRegex": "Недопустимое регулярное выражение",
|
||||
"chat.search.noResults": "Нет результатов",
|
||||
"settings.experimental.browserAutomation.title": "Встроенный браузер",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Показывайте предпросмотр локальных приложений в Agent Manager и предоставляйте инструмент browser_open сеансам Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Использовать системный Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Использовать установленный Google Chrome для встроенного браузера. Отключайте только если совместимый браузер Playwright Chromium уже установлен.",
|
||||
"chat.search.searchingHistory": "Поиск в более ранних сообщениях…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -834,7 +834,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "ทักษะ",
|
||||
|
||||
"settings.browser.description":
|
||||
"เมื่อเปิดใช้งาน ตัวแทน AI สามารถโต้ตอบกับหน้าเว็บได้ — นำทาง คลิก พิมพ์ และจับภาพหน้าจอ หน้าต่าง Chrome จะเปิดขึ้นเพื่อให้คุณดูการทำงานของตัวแทน",
|
||||
"กำหนดค่าการทำงานอัตโนมัติของเบราว์เซอร์ในตัวที่ขับเคลื่อนโดย Playwright Kilo สามารถนำทาง โต้ตอบ และจับภาพหน้าจอของหน้าเว็บในเซสชันของคุณได้",
|
||||
"settings.browser.enable.title": "เปิดใช้งานการทำงานอัตโนมัติของเบราว์เซอร์",
|
||||
"settings.browser.enable.description": "ลงทะเบียนเซิร์ฟเวอร์ Playwright MCP กับ CLI backend",
|
||||
"settings.browser.systemChrome.title": "ใช้ Chrome ของระบบ",
|
||||
@@ -1331,5 +1331,11 @@ export const dict = {
|
||||
"chat.search.close": "ปิดการค้นหา",
|
||||
"chat.search.invalidRegex": "นิพจน์ทั่วไปไม่ถูกต้อง",
|
||||
"chat.search.noResults": "ไม่มีผลลัพธ์",
|
||||
"settings.experimental.browserAutomation.title": "เบราว์เซอร์ในตัว",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"แสดงตัวอย่างแอปพลิเคชันในเครื่องใน Agent Manager และเปิดเผยเครื่องมือ browser_open ให้กับเซสชัน Agent Manager",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "ใช้ Chrome ของระบบ",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"ใช้ Google Chrome ที่ติดตั้งไว้สำหรับเบราว์เซอร์ในตัว ปิดใช้งานเฉพาะเมื่อติดตั้งเบราว์เซอร์ Playwright Chromium ที่เข้ากันได้ไว้แล้วเท่านั้น",
|
||||
"chat.search.searchingHistory": "กำลังค้นหาข้อความก่อนหน้า…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -834,7 +834,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Beceriler",
|
||||
|
||||
"settings.browser.description":
|
||||
"Etkinleştirildiğinde, yapay zeka ajanı web sayfalarıyla etkileşime girebilir — gezinme, tıklama, yazma ve ekran görüntüsü alma. Ajanın çalışmasını izleyebilmeniz için bir Chrome penceresi açılacak.",
|
||||
"Playwright ile çalışan yerleşik tarayıcı otomasyonunu yapılandırın. Kilo, oturumlarınızda web sayfalarında gezinebilir, bunlarla etkileşime girebilir ve ekran görüntüsü alabilir.",
|
||||
"settings.browser.enable.title": "Tarayıcı Otomasyonunu Etkinleştir",
|
||||
"settings.browser.enable.description": "Playwright MCP sunucusunu CLI arka ucuyla kaydet.",
|
||||
"settings.browser.systemChrome.title": "Sistem Chrome'unu Kullan",
|
||||
@@ -1370,5 +1370,11 @@ export const dict = {
|
||||
"chat.search.close": "Aramayı kapat",
|
||||
"chat.search.invalidRegex": "Geçersiz normal ifade",
|
||||
"chat.search.noResults": "Sonuç yok",
|
||||
"settings.experimental.browserAutomation.title": "Entegre Tarayıcı",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Agent Manager'da yerel uygulama önizlemelerini gösterin ve browser_open aracını Agent Manager oturumlarına sunun.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Sistem Chrome'unu Kullan",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Entegre Tarayıcı için yüklü Google Chrome'u kullanın. Yalnızca uyumlu bir Playwright Chromium tarayıcısı zaten yüklüyse devre dışı bırakın.",
|
||||
"chat.search.searchingHistory": "Önceki mesajlarda aranıyor…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -834,7 +834,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Навички",
|
||||
|
||||
"settings.browser.description":
|
||||
"Після увімкнення агент ШІ може взаємодіяти з веб-сторінками — навігація, натискання, введення тексту та знімки екрана. Відкриється вікно Chrome, щоб ви могли стежити за роботою агента.",
|
||||
"Налаштуйте вбудовану автоматизацію браузера на основі Playwright. Kilo може переходити веб-сторінками, взаємодіяти з ними та робити знімки екрана у ваших сесіях.",
|
||||
"settings.browser.enable.title": "Увімкнути автоматизацію браузера",
|
||||
"settings.browser.enable.description": "Зареєструвати MCP-сервер Playwright з CLI-бекендом.",
|
||||
"settings.browser.systemChrome.title": "Використовувати системний Chrome",
|
||||
@@ -1370,5 +1370,11 @@ export const dict = {
|
||||
"chat.search.close": "Закрити пошук",
|
||||
"chat.search.invalidRegex": "Недійсний регулярний вираз",
|
||||
"chat.search.noResults": "Немає результатів",
|
||||
"settings.experimental.browserAutomation.title": "Вбудований браузер",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"Показуйте попередній перегляд локальних застосунків в Agent Manager і надавайте інструмент browser_open сесіям Agent Manager.",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "Використовувати системний Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"Використовувати встановлений Google Chrome для вбудованого браузера. Вимкніть лише якщо сумісний браузер Playwright Chromium уже встановлено.",
|
||||
"chat.search.searchingHistory": "Пошук у попередніх повідомленнях…",
|
||||
}
|
||||
|
||||
+7
-1
@@ -814,7 +814,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "技能",
|
||||
|
||||
"settings.browser.description":
|
||||
"启用后,AI 代理可以与网页交互 — 导航、点击、输入和截取屏幕截图。Chrome 窗口将打开,以便您观察代理的工作。",
|
||||
"配置由 Playwright 提供支持的内置浏览器自动化。Kilo 可在你的会话中浏览网页、与网页交互并截取屏幕截图。",
|
||||
"settings.browser.enable.title": "启用浏览器自动化",
|
||||
"settings.browser.enable.description": "将 Playwright MCP 服务器注册到 CLI 后端。",
|
||||
"settings.browser.systemChrome.title": "使用系统 Chrome",
|
||||
@@ -1283,5 +1283,11 @@ export const dict = {
|
||||
"chat.search.close": "关闭搜索",
|
||||
"chat.search.invalidRegex": "正则表达式无效",
|
||||
"chat.search.noResults": "无结果",
|
||||
"settings.experimental.browserAutomation.title": "集成浏览器",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"在 Agent Manager 中显示本地应用预览,并向 Agent Manager 会话公开 browser_open 工具。",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "使用系统 Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"为集成浏览器使用已安装的 Google Chrome。仅在已安装兼容的 Playwright Chromium 浏览器时才禁用。",
|
||||
"chat.search.searchingHistory": "正在搜索更早的消息…",
|
||||
} satisfies Partial<Record<Keys, string>>
|
||||
|
||||
+7
-1
@@ -774,7 +774,7 @@ export const dict = {
|
||||
"settings.agentBehaviour.subtab.skills": "Skills",
|
||||
|
||||
"settings.browser.description":
|
||||
"啟用後,AI Agent 可以與網頁互動,可導覽、點選、輸入並擷取螢幕截圖。Chrome 視窗將開啟,方便觀察 Agent 的工作。",
|
||||
"設定由 Playwright 提供支援的內建瀏覽器自動化。Kilo 可以在你的工作階段中瀏覽網頁、與網頁互動,並擷取螢幕截圖。",
|
||||
"settings.browser.enable.title": "啟用瀏覽器自動化",
|
||||
"settings.browser.enable.description": "將 Playwright MCP 伺服器註冊到 CLI 後端。",
|
||||
"settings.browser.systemChrome.title": "使用系統 Chrome",
|
||||
@@ -1286,5 +1286,11 @@ export const dict = {
|
||||
"chat.search.close": "關閉搜尋",
|
||||
"chat.search.invalidRegex": "規則運算式無效",
|
||||
"chat.search.noResults": "無結果",
|
||||
"settings.experimental.browserAutomation.title": "整合瀏覽器",
|
||||
"settings.experimental.browserAutomation.description":
|
||||
"在 Agent Manager 中顯示本機應用程式預覽,並向 Agent Manager 工作階段公開 browser_open 工具。",
|
||||
"settings.experimental.browserAutomation.systemChrome.title": "使用系統 Chrome",
|
||||
"settings.experimental.browserAutomation.systemChrome.description":
|
||||
"為整合瀏覽器使用已安裝的 Google Chrome。僅在已安裝相容的 Playwright Chromium 瀏覽器時才停用。",
|
||||
"chat.search.searchingHistory": "正在搜尋較早的訊息…",
|
||||
} satisfies Partial<Record<Keys, string>>
|
||||
|
||||
@@ -128,7 +128,9 @@ export type KiloEmbeddingModelCatalog = {
|
||||
export type IndexingStatus = SdkIndexingStatus
|
||||
|
||||
export interface BrowserSettings {
|
||||
enabled: boolean
|
||||
useSystemChrome: boolean
|
||||
headless: boolean
|
||||
}
|
||||
|
||||
export type TerminalCommandDisplay = "expanded" | "collapsed"
|
||||
|
||||
@@ -67,7 +67,7 @@ export const BrowserOpenTool = Tool.define<
|
||||
) {
|
||||
return {
|
||||
title: "Browser unavailable",
|
||||
output: "The Agent Manager browser is not available in this session.",
|
||||
output: "The Integrated Browser is not available in this session.",
|
||||
metadata: { status: "error", errors: 0 } satisfies Meta,
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ export const BrowserOpenTool = Tool.define<
|
||||
state.logs?.length
|
||||
? `Console diagnostics:\n${state.logs.map((line) => `- ${line}`).join("\n")}`
|
||||
: undefined,
|
||||
"The user can inspect this page in the Agent Manager Browser panel.",
|
||||
"The user can inspect this page in the Integrated Browser panel in Agent Manager.",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n"),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Open the local application in the Browser panel for the current Agent Manager session.
|
||||
Open the local application in the Integrated Browser panel for the current Agent Manager session.
|
||||
|
||||
Use this tool when the user asks you to inspect or verify a local web application.
|
||||
The user can see the same browser page in Agent Manager. Reuse this browser instead
|
||||
|
||||
Reference in New Issue
Block a user