Skip to content

feat(world): add browser automation runtime - #12752

Open
IamCoder18 wants to merge 1 commit into
Kilo-Org:mainfrom
IamCoder18:feat/world-runtime
Open

feat(world): add browser automation runtime#12752
IamCoder18 wants to merge 1 commit into
Kilo-Org:mainfrom
IamCoder18:feat/world-runtime

Conversation

@IamCoder18

@IamCoder18 IamCoder18 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Context

Kilo’s existing browser automation relies on an extension-managed Playwright MCP server. That makes browser use client-specific, adds a separate registration and lifecycle path, and requires an external tool before the agent can verify its own UI work.

This PR introduces a native browser runtime shared by every Kilo client. Persistent, isolated sessions let the agent perform multi-step browser work without rebuilding context on every call, while direct screenshots and a compact action grammar make verification faster and more reliable than the previous MCP integration.

Most importantly, this makes the agent more proactive and improves the quality of visual work: the eventual World tool will instruct the agent to always verify visual changes instead of treating browser validation as an optional follow-up. The runtime’s action, session, and daemon boundaries also lay the foundation for future computer-use capabilities beyond the browser.

Closes #12751

Review and merge order: this PR → #12753#12754.

Implementation

I, a human, have manually reviewed every change in this PR.

Add a new @kilocode/world package with a quote-aware browser script parser and commands for navigation, snapshots, interaction, JavaScript evaluation, tabs, cookies, and screenshots. Browser state lives in a persistent per-session Node daemon, with private authenticated handshakes and isolated processes so sessions cannot read or reconfigure one another.

The runtime supports headless and headed execution, system Chrome detection with Chromium fallback, abortable actions, and platform-aware expansion of home and environment-variable paths before file access. The daemon is bundled as a companion artifact and has a Node smoke test so later clients can ship the same runtime beside the Kilo binary.

Screenshots / Video

N/A — this PR introduces the headless runtime and does not change a user interface.

before after
N/A N/A

How to Test

Manual/local verification

  • Ran the package typecheck, the browser-enabled package suite (46 passed), and the daemon build successfully.
  • Confirmed browser state persists within a session and remains isolated across daemon processes.
  • Confirmed generated screenshots resolve home and environment-variable paths and are written to disk.

Reviewer test steps

  1. From packages/kilo-world, run bun run typecheck.
  2. Run bun test --timeout 30000.
  3. Run bun run build:daemon and confirm dist/world-daemon.cjs is produced.

Checklist

  • Issue linked above, or exception explained
  • Tests/verification described
  • Screenshots/video included for visual changes, or marked N/A
  • Changeset considered for user-facing changes
  • I personally reviewed the diff and can explain the changes, including any AI-assisted work.

Get in Touch

Discord: @IamCoder18

Comment thread packages/kilo-world/src/core/browser/detect.ts Outdated
Comment thread packages/kilo-world/src/core/browser/launch.ts Outdated
Comment thread packages/kilo-world/src/core/browser/runner.ts
Comment thread packages/kilo-world/src/daemon/dispatch.ts Outdated
Comment thread packages/kilo-world/src/daemon/dispatch.ts
Comment thread package.json Outdated
Comment thread packages/kilo-world/test/daemon.test.ts Outdated
Comment thread packages/kilo-world/test/parse-script.test.ts Outdated
Comment thread packages/kilo-world/test/daemon.test.ts Outdated
Comment thread packages/kilo-world/test/browser.test.ts Outdated
@kilo-code-bot

kilo-code-bot Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Incremental review of fa916c00..3da9630c: the branch was re-pushed with an identical tree — no PR content changed since the previous review, so there is nothing new to report. All previous findings remain resolved.

Files Reviewed (0 files this round)
  • No files changed in the incremental range (re-push-only update; trees of fa916c00 and 3da9630c are identical).
Previous Review Summaries (9 snapshots, latest commit fa916c0)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit fa916c0)

Status: No Issues Found | Recommendation: Merge

Incremental review of 8ceefc9e..fa916c00: the branch was rebased onto current main (6ec20f23) with an identical tree — no PR content changed since the previous review, so there is nothing new to report. All previous findings remain resolved.

Files Reviewed (0 files this round)
  • No files changed in the incremental range (rebase-only update; trees of 8ceefc9e and fa916c00 are identical).

Previous review (commit 8ceefc9)

Status: No Issues Found | Recommendation: Merge

Incremental review of 66348127..8ceefc9e (branch was rebased onto current main; the kilo-world delta is 3 files). Both findings from the previous round are resolved:

  • Stale-lock liveness (script/build-daemon.ts): alive() now returns false when the lock mtime is older than LOCK_TIMEOUT_MS, so a crashed holder with a recycled pid no longer blocks acquire() for the full deadline. The existing 1s pulse heartbeat keeps a live holder's lock fresh, so legitimate long builds are never mistaken for stale.
  • Fingerprint scope (src/daemon/build.ts): the fingerprint now hashes only the playwright spec, the resolved playwright/playwright-core lock entries, and playwright-scoped patches — unrelated monorepo dependency changes no longer force a daemon rebundle. The 4-space-indent and : [ prefix assumptions were verified against the current bun.lock (exactly one match per package; the catalog string entry and playwright/fsevents are correctly excluded).

The new fingerprint test exercises the real implementation against a synthetic monorepo fixture (no mocks) and asserts both directions: unrelated lock changes keep the fingerprint stable, playwright bumps invalidate it.

Files Reviewed (3 changed files this round)
  • packages/kilo-world/script/build-daemon.ts - no issues (previous WARNING resolved)
  • packages/kilo-world/src/daemon/build.ts - no issues (previous SUGGESTION resolved)
  • packages/kilo-world/test/build.test.ts - no issues

Assumptions: Reviewed statically in read-only mode — no install, build, or test run. The .github/docs-sync/* changes in the commit range are rebase noise from main and are outside this PR's changed-file list.

Previous review (commit 6634812)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1

Incremental review of b17830b6..66348127 (branch was rebased onto current main; the kilo-world delta is 4 files). The lock-release path now compares dev/ino before unlinking, alive() trusts a live pid unconditionally, dependency() fails loudly on every resolution miss, and parents() terminates via the dirname fixpoint with resolve(root) up front. All three findings from the previous round (stale-lock takeover deleting the winner's lock, silent fingerprint misses, non-terminating parent walk) are resolved by these commits.

Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-world/script/build-daemon.ts 86 With the mtime backstop removed, a crashed holder whose pid gets recycled reads as alive forever — every acquire() burns the 90s deadline and throws until the coincidental process exits or the hidden lock is manually deleted; bound the override (e.g. mtime older than LOCK_TIMEOUT_MS ⇒ dead)

SUGGESTION

File Line Issue
packages/kilo-world/src/daemon/build.ts 61 The fingerprint now hashes the entire ~740KB root bun.lock plus all patch files, so any unrelated monorepo dependency change forces a full daemon rebundle + smoke test; hash only the playwright spec/resolution (and playwright-relevant patches) instead
Files Reviewed (4 changed files this round)
  • packages/kilo-world/script/build-daemon.ts - 1 issue
  • packages/kilo-world/src/daemon/build.ts - 1 issue
  • packages/kilo-world/test/build.test.ts - no issues (cwd-dependent fingerprint(".") matches the documented package-local test flow)
  • bun.lock - no issues (lockfile-only; chart.js entries are rebase noise from main, the PR adds the kilo-world workspace + playwright resolution)

Assumptions: Reviewed statically in read-only mode — no install, build, test run, or browser launch. The bun.lock text-parsing assumptions in dependency() (4-space workspace indent, "playwright": "catalog:" in the workspace section, resolved playwright@… entry) were verified against the current lockfile.

Fix these issues in Kilo Cloud

Previous review (commit b17830b)

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 2

Incremental review of 87df327d..b17830b6, which reworks the daemon build lock (mtime heartbeat, freshness check moved inside the lock, stamp published last), replaces the require.resolve("playwright") fingerprint input with catalog-aware dependency resolution, and hoists the ENTRY/MANIFEST names into src/daemon/build.ts. The stamp-ordering and empty-pid problems from earlier rounds are resolved by these commits.

Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-world/script/build-daemon.ts 87 Liveness is now gated on a recent mtime even when process.kill(pid, 0) succeeds, so a >5s event-loop stall lets another process take the lock — and the original holder's unconditional fs.rm(lock) in finally then deletes the new holder's lock

SUGGESTION

File Line Issue
packages/kilo-world/src/daemon/build.ts 38 Any resolution miss (devDependencies, rename, unmatched catalog) silently contributes an empty string / literal catalog: to the fingerprint, so a playwright bump leaves a stale bundle instead of failing loudly
packages/kilo-world/src/daemon/build.ts 58 parents() never terminates for a non-absolute root because dirname has a fixpoint at .; stop when dirname stops changing instead of comparing against parse().root
Files Reviewed (4 changed files this round)
  • packages/kilo-world/script/build-daemon.ts - 1 issue
  • packages/kilo-world/src/daemon/build.ts - 2 issues
  • packages/kilo-world/script/daemon.ts - no issues
  • packages/kilo-world/src/daemon/client.ts - no issues (constant extraction plus a longer build-failure cooldown; both look intentional)

Assumptions: Reviewed statically in read-only mode — no install, build, test run, or browser launch. The catalog resolution path was verified against the root package.json (workspaces.catalog.playwright is pinned to 1.57.0), so the declared-vs-installed fingerprint gap is latent rather than active today.

Fix these issues in Kilo Cloud

Previous review (commit 87df327)

Status: No Issues Found | Recommendation: Merge

Overview

Incremental review of c746b6e..87df327d. The head commit moved, but it is a rebase onto newer main — not a content update. Diffing the previous reviewed commit against current HEAD scoped to every file this PR owns (packages/kilo-world/**, root package.json, bun.lock, .gitignore) returns an empty diff. The commits that appear in the range (fix(cli): preserve configured subagent routing, the JetBrains 7.0.12 release, and its changeset) all come from main and are outside this PR's scope.

Since no PR-authored line changed in this round, there is nothing new to review and no previously reported finding sits on a changed line. Existing inline comments from earlier rounds are unchanged and still apply where GitHub still anchors them.

Files Reviewed (0 changed files this round)

No PR-owned file changed between c746b6e and 87df327d.

Assumptions: Reviewed statically in read-only mode — no install, build, test run, or browser launch. Equivalence of the two commits was established by a path-scoped git diff over the PR's file set rather than by re-reading each file.

Previous review (commit c746b6e)

Status: No Issues Found | Recommendation: Merge

Overview

Incremental review of 1197d81..c746b6e — 1 changed file, 4 added / 2 removed lines. The only change hardens the Node runner test's staging directory: packages/kilo-world/node_modules is now created with mkdirSync(dir, { recursive: true }) before mkdtempSync, so the test no longer depends on bun having materialized a per-package node_modules. Module resolution for the playwright / chromium-bidi / electron externals still works from the nested temp dir because Node walks up past an empty packages/kilo-world/node_modules to the hoisted root, and the temp dir is still removed in the finally.

Previously reported finding that is now resolved:

  • test/daemon.test.ts:165mkdtempSync assuming packages/kilo-world/node_modules exists. Fixed by the recursive mkdirSync.

No new issues in the changed lines. Inline comments previously posted on files that were not touched in this round are unchanged and still apply.

Files Reviewed (1 changed file this round)
  • packages/kilo-world/test/daemon.test.ts - no new issues (previous staging-dir finding resolved)

Assumptions: Reviewed statically in read-only mode — no install, build, test run, or browser launch. node_modules is not present in this environment, so bun's hoisting layout and Node's resolution from the nested staging directory were reasoned from the manifests rather than observed.

Previous review (commit 1197d81)

Status: 6 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 2
SUGGESTION 4

Overview

Incremental review of 0246c18..1197d81 (7 changed files, ~123 added / ~65 removed lines). This round finishes hardening the lazy daemon build: fingerprint()/fresh() moved into src/daemon/build.ts and now hash playwright/package.json, the lock and build budgets are split (LOCK_TIMEOUT_MS 90s vs BUILD_TIMEOUT_MS 150s), the promote order became chunks → binary → stamp → manifest, an unwritten lock no longer reads as a live pid, build-daemon.ts sweeps stale staging dirs, the client group-kills the build on timeout and only latches failures for 2s, and the smoke daemon now gets --idle=15000 plus KILO_WORLD_PARENT_PID so it can't outlive its build.

What's left is mostly the edges of those new mechanisms: the timeout still only requests termination (no SIGKILL escalation, and close waits on stdio the smoke daemon inherits), the 2s failure cooldown makes a permanently broken checkout re-run a full build per action, and staging moved into the package source root, which is what forces the new prefix-matched recursive delete there.

Previously reported findings that are now resolved:

  • build-daemon.ts promoting STAMP before the binary it describes — fixed; the stamp is now renamed after world-daemon.cjs and before the manifest, and every intermediate state either fails fresh() or already has the new binary in place.
  • build-daemon.ts treating an unwritten lock as pid 0 — fixed via Number.isSafeInteger(pid) && pid > 0 plus the mtime fallback.
  • client.ts latching transient build failures for the process lifetime — fixed by the timestamped cooldown (see the new note on its length).
  • client.ts build timeout orphaning the smoke daemon — fixed; the build is spawned detached and killed by process group, and the daemon now has a parent-pid watchdog and a finite idle timeout.
  • build.ts one constant serving as both the lock wait and the kill deadline — fixed by splitting LOCK_TIMEOUT_MS / BUILD_TIMEOUT_MS.
  • build.ts fingerprint ignoring dependencies — addressed for the one that matters (playwright/package.json is now hashed).
  • server.ts unused shutdownTimeoutMs export — removed.
  • daemon.test.ts not cleaning up the child and staging dir not ignored — fixed.

Still open from the previous round on a changed file:

  • client.ts:61 — an already-aborted opts.signal makes wait() throw at signal.throwIfAborted() before it subscribes to building.task, so a later build failure becomes an unhandled rejection. Code unchanged; the existing inline comment is still current.

Other open inline comments on files not touched this round are unchanged.

Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-world/src/daemon/client.ts 89 Timeout sends SIGTERM with no SIGKILL escalation, and close waits on stdio the smoke daemon inherits, so entry() can hang with no deadline
packages/kilo-world/src/daemon/client.ts 61 (carried) Pre-aborted signal leaves the build task's rejection unhandled

SUGGESTION

File Line Issue
packages/kilo-world/src/daemon/client.ts 14 2s failure cooldown makes a permanently broken checkout re-run a full 150s build per action
packages/kilo-world/src/daemon/client.ts 45 "world-daemon.assets.json" duplicates WorldDaemon.manifest; drift silently disables the freshness check
packages/kilo-world/script/build-daemon.ts 23 Staging in the package source root forces a prefix-matched recursive delete there; dist/ works and is already ignored
packages/kilo-world/test/daemon.test.ts 165 mkdtempSync assumes packages/kilo-world/node_modules exists, which bun's hoisting does not guarantee
Files Reviewed (7 changed files this round)
  • packages/kilo-world/src/daemon/client.ts - 3 new issues + 1 carried
  • packages/kilo-world/script/build-daemon.ts - 1 issue
  • packages/kilo-world/test/daemon.test.ts - 1 issue
  • packages/kilo-world/src/daemon/build.ts - no new issues
  • packages/kilo-world/script/daemon.ts - no issues (smoke test now bounded by idle timeout + parent watchdog)
  • packages/kilo-world/src/daemon/server.ts - no issues (dead export removed)
  • .gitignore - no issues

Assumptions: Reviewed statically in read-only mode — no install, build, test run, or browser launch. node_modules is not present in this environment, so the playwright/package.json resolution in fingerprint() and bun's per-package node_modules layout were reasoned from the manifests rather than observed. The build/lock/promote sequences are likewise reasoned from script/build-daemon.ts, script/daemon.ts, src/daemon/build.ts, and src/daemon/server.ts.

Fix these issues in Kilo Cloud

Previous review (commit 0246c18)

Status: 9 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 5
SUGGESTION 4

Overview

Incremental review of 1349e4d..0246c18 (6 changed files, ~245 added / ~30 removed lines). This round hardens the lazy daemon build: a new src/daemon/build.ts fingerprints the package sources, build-daemon.ts now takes a pid lock, builds into a staging dir, stamps a fingerprint and promotes files by rename, and client.ts pipes/caps build output, adds a 90s kill timeout, honours opts.signal, and caches failures. A new test/runner-node.ts re-adds the Runner guarantees under Node, driven from daemon.test.ts.

The remaining findings cluster around the promote-and-stamp sequence (the stamp lands before the binary it describes, so a mid-rename kill can mark a stale daemon current), the lock's stale detection (an unwritten lock reads as pid 0, which process.kill reports as alive), and the client's new lifecycle edges (a pre-aborted signal leaves the build's rejection unhandled; the timeout kill orphans the smoke-test daemon; transient failures are latched forever). The 90s constant serving as both the inner lock wait and the outer kill deadline ties several of these together.

Previous findings on changed lines:

  • client.ts stdio: "inherit" polluting host streams and hiding the real failure — resolved; output is now piped, capped, and included in the thrown error.
  • client.ts in-process-only build dedupe racing a delete-then-rewrite — resolved; the build now stages + renames under a cross-process lock.
  • client.ts build ignoring opts.signal / no timeout / full retry after permanent failure — resolved (see the new findings on the resulting edges).
  • daemon.test.ts dropped Runner guarantees — resolved; test/runner-node.ts restores the close() home-containment, relaunch-on-config-change, and ensureBrowser dedupe checks, and the anti-detect test now restores config in finally.
  • build-daemon.ts stale-artifact cleanup targeting names that are never produced — resolved; cleanup is now driven by the previous manifest's basenames.

Other open inline comments on files not touched this round are unchanged.

Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-world/script/build-daemon.ts 28 STAMP is renamed in before world-daemon.cjs, so a kill mid-promote can leave the new fingerprint next to the old binary and current() returns true
packages/kilo-world/script/build-daemon.ts 61 An unwritten lock reads as pid 0; process.kill(0, 0) targets the caller's own group and always succeeds, so alive() never falls back to the mtime check
packages/kilo-world/src/daemon/client.ts 44 failed latches lock timeouts, SIGKILLs, and kill-timeouts permanently, keyed only on the source fingerprint
packages/kilo-world/src/daemon/client.ts 58 An already-aborted opts.signal makes wait() throw before it observes building.task, so a later build failure becomes an unhandled rejection
packages/kilo-world/src/daemon/client.ts 82 The 90s child.kill() signals only the bundler, orphaning the --idle=0 smoke-test daemon with no parent watchdog

SUGGESTION

File Line Issue
packages/kilo-world/src/daemon/build.ts 7 BUILD_TIMEOUT_MS is both the inner lock wait and the outer kill deadline, so a contended build is killed just as it starts working
packages/kilo-world/src/daemon/build.ts 10 The fingerprint ignores dependencies, so a playwright bump leaves the bundled client stale while the stamp still matches
packages/kilo-world/src/daemon/server.ts 49 shutdownTimeoutMs is never read, and it exceeds the 5s timeout DaemonClient.stop() actually uses
packages/kilo-world/test/daemon.test.ts 190 The child isn't killed on failure/timeout, and test/.runner-* isn't gitignored
Files Reviewed (6 changed files this round)
  • packages/kilo-world/script/build-daemon.ts - 2 issues
  • packages/kilo-world/src/daemon/build.ts - 2 issues (new file)
  • packages/kilo-world/src/daemon/client.ts - 3 issues
  • packages/kilo-world/src/daemon/server.ts - 1 issue
  • packages/kilo-world/test/daemon.test.ts - 1 issue
  • packages/kilo-world/test/runner-node.ts - no issues (new file; folder() base64url-encodes the session name, so the ../../victim containment assertion is meaningful)

Assumptions: Reviewed statically in read-only mode — no install, build, test run, or browser launch, so the lock/stamp races, the orphaned smoke daemon, and the unhandled-rejection path are reasoned from client.ts, script/build-daemon.ts, script/daemon.ts, and src/daemon/server.ts rather than observed. packages/opencode/ still has no reference to @kilocode/world, so the lazy-build path is not yet exercised by the shipped CLI.

Fix these issues in Kilo Cloud

Previous review (commit 1349e4d)

Status: 4 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 1

Overview

Incremental review of 7787e8a..1349e4d (5 changed files, ~127 added / ~161 removed lines). Two changes this round: the root dev script no longer pre-builds the daemon and DaemonClient.entry() instead builds world-daemon.cjs lazily on first use, and browser.test.ts was deleted with most of its cases re-expressed against the daemon in daemon.test.ts.

The new lazy-build path is where the new findings sit: it inherits the host process's stdout/stderr, has no cross-process locking against build-daemon.ts's delete-then-rewrite sequence, and is neither cancellable nor cached across failures. The test migration also silently drops three Runner-level guarantees that no longer exist anywhere in test/.

Previous findings on changed lines:

  • package.json bun dev depending on build:daemon — resolved; the step was removed and replaced by the on-demand build.
  • packages/kilo-world/src/daemon/server.ts shutdown() not guaranteeing process.exit(0) — resolved; the body is now wrapped in try/finally with the clear() failure logged.

Other open inline comments on files not touched this round are unchanged.

Issue Details (click to expand)

WARNING

File Line Issue
packages/kilo-world/src/daemon/client.ts 55 stdio: "inherit" writes bundler and smoke-test output into the TUI / kilo serve streams, and hides the real failure behind exit 1
packages/kilo-world/src/daemon/client.ts 44 building only dedupes in-process; concurrent lazy builds can spawn a truncated world-daemon.cjs because the build deletes then rewrites in place
packages/kilo-world/test/daemon.test.ts 164 Deleting browser.test.ts drops the Runner.close() home-containment guard, browser relaunch-on-config-change, and ensureBrowser dedupe coverage; anti-detect config is also never restored

SUGGESTION

File Line Issue
packages/kilo-world/src/daemon/client.ts 42 The build ignores opts.signal, has no timeout, and is re-attempted in full on every later call after a permanent failure
Files Reviewed (5 changed files this round)
  • packages/kilo-world/src/daemon/client.ts - 3 issues
  • packages/kilo-world/test/daemon.test.ts - 1 issue
  • package.json - previous finding resolved
  • packages/kilo-world/src/daemon/server.ts - previous finding resolved
  • `pack

[Snapshot truncated.]

Additional previous summary content was truncated to keep this comment within platform limits.


Reviewed by kimi-k3 · Input: 33.5K · Output: 3.9K · Cached: 235.4K

Review guidance: REVIEW.md from base branch main

Comment thread packages/kilo-world/src/daemon/server.ts Outdated
Comment thread packages/kilo-world/src/daemon/server.ts Outdated
Comment thread packages/kilo-world/src/daemon/client.ts
Comment thread packages/kilo-world/src/daemon/dispatch.ts
Comment thread packages/kilo-world/src/core/browser/runner.ts Outdated
Comment thread packages/kilo-world/src/core/browser/runner.ts
Comment thread bun.lock Outdated
Comment thread package.json
Comment thread packages/kilo-world/package.json Outdated
Comment thread packages/kilo-world/package.json Outdated
Comment thread packages/kilo-world/src/core/browser/runner.ts Outdated
Comment thread packages/kilo-world/test/browser.test.ts Outdated
Comment thread package.json Outdated
Comment thread packages/kilo-world/src/daemon/server.ts Outdated
Comment thread packages/kilo-world/src/daemon/client.ts Outdated
Comment thread packages/kilo-world/src/daemon/client.ts
Comment thread packages/kilo-world/src/daemon/client.ts Outdated
Comment thread packages/kilo-world/test/daemon.test.ts
Comment thread packages/kilo-world/script/build-daemon.ts Outdated
Comment thread packages/kilo-world/script/build-daemon.ts Outdated
Comment thread packages/kilo-world/src/daemon/client.ts Outdated
Comment thread packages/kilo-world/src/daemon/client.ts
Comment thread packages/kilo-world/src/daemon/client.ts Outdated
Comment thread packages/kilo-world/src/daemon/build.ts Outdated
Comment thread packages/kilo-world/src/daemon/build.ts Outdated
Comment thread packages/kilo-world/src/daemon/server.ts Outdated
Comment thread packages/kilo-world/test/daemon.test.ts
Comment thread packages/kilo-world/src/daemon/client.ts
Comment thread packages/kilo-world/src/daemon/client.ts Outdated
Comment thread packages/kilo-world/src/daemon/client.ts Outdated
Comment thread packages/kilo-world/script/build-daemon.ts
Comment thread packages/kilo-world/test/daemon.test.ts Outdated
@IamCoder18
IamCoder18 force-pushed the feat/world-runtime branch 2 times, most recently from c746b6e to 87df327 Compare August 3, 2026 04:03
@IamCoder18

Copy link
Copy Markdown
Contributor Author

Hey! This PR is finally done. I know it is quite large, and hard to test by itself, so if you have any questions, feel free to ask me. I am fully open to any changes.

Note that this PR only adds the World implementation, adding it to the CLI is covered in #12753 and adding it to VS Code is covered in #12754.

I hope to add JetBrains support soon, and I'll work on Computer Use as well (Windows and Linux only at first).

I might also be able to share benchmarks and comparisons of with and without World.

Comment thread packages/kilo-world/script/build-daemon.ts Outdated
Comment thread packages/kilo-world/src/daemon/build.ts Outdated
Comment thread packages/kilo-world/src/daemon/build.ts Outdated
Comment thread packages/kilo-world/script/build-daemon.ts
Comment thread packages/kilo-world/src/daemon/build.ts Outdated
@IamCoder18
IamCoder18 force-pushed the feat/world-runtime branch 2 times, most recently from 8ceefc9 to fa916c0 Compare August 3, 2026 22:35
@IamCoder18

Copy link
Copy Markdown
Contributor Author

No issues found, check are all green!

@IamCoder18

Copy link
Copy Markdown
Contributor Author

Benchmarks

Transparency first: the code I used to benchmark is available at https://gist.github.com/IamCoder18/ad7c646cd43326325bd0316b3e052954.
It allows me to run bun bench.ts --name foo --tool all --prompt "..." and compare the three options. --tool supports playwright, plain, and world, and support multiple --tools (like --tool plain --tool world), as well as --tool all.

Prompt: Create a dashboard with lots of charts and graphs populated with sample data. Add a button on the page that toggles all the graphs into a 3D space where the user can rotate the view with the mouse, zoom in/out with the scroll wheel, and pan/move around the scene with click-and-drag. Constraint: do not use any chart/graph library — write the visualization code yourself (e.g. SVG, Canvas, or raw DOM). You may use a 3D library such as three.js to render the 3D view.

Results

image

No Playwright, No World (MiniMax M3, $0.0368, ~3m13s)

image image

With Playwright (MiniMax M3, $0.0357 (<- highest cost out of the runs), ~4m12s)

image image

Note: Some 3D controls were inverted, rotating caused text selection on cards, and there were a few visibility and contrast issues.

With World (MiniMax M3, $0.0305, ~3m36s)

image image image

Notes: Cards always face the camera is a great touch.

Winner: World

Prompt: Turn llama.cpp into a fully interactive 3D world. It should explain how data passes and how the 'magic' of llama.cpp works. Have both interactive walkthroughs as well as explore at your own pace options. The repo containing llama cpp source code is stored at /tmp/llamacpp for reference.

Results

image

No Playwright, No World (MiniMax M3, $0.0245, 2m32s)

image

With Playwright (MiniMax M3, $0.0669, 3m11s)

image image

With World (MiniMax M3, $0.0331, 2m16s) (half the cost of Playwright, fastest run)

image image

Winner: World

Though this run was close, World wins because it has better visuals to show data flow (an explicit part of the prompt) and has nicer 3D control.


Results

Both Playwright and World drastically improve agent performance, however, World improves the quality of agents' work faster and cheaper than Playwright. Through earlier (undocumented) testing, World has a larger improvement on free models than smarter models, and is a valuable asset to users running free models for webdev.

t7tran pushed a commit to t7tran/kilocode that referenced this pull request Aug 14, 2026
@IamCoder18

Copy link
Copy Markdown
Contributor Author

Comment to prevent this PR from automatically closing due to 30 days of inactivity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(world): add a native browser automation runtime

1 participant