From 74e70a3367af2510adb8c4153573de214883ee1e Mon Sep 17 00:00:00 2001 From: Daniel Prevoznik Date: Thu, 19 Feb 2026 10:42:52 -0500 Subject: [PATCH 1/5] Add invocation_id to Yutori template browser creation Pass ctx.invocation_id when creating browsers in both TypeScript and Python yutori-computer-use templates so the dashboard can link browser sessions to invocations. - TS: SessionOptions.invocationId, passed to kernel.browsers.create() - TS: index.ts passes ctx.invocation_id to KernelBrowserSession - Python: KernelBrowserSession.invocation_id, passed to browsers.create() - Python: main.py passes ctx.invocation_id to KernelBrowserSession Co-authored-by: Cursor --- .../python/yutori-computer-use/main.py | 1 + .../python/yutori-computer-use/session.py | 4 ++++ .../typescript/yutori-computer-use/index.ts | 1 + .../typescript/yutori-computer-use/session.ts | 17 +++++++++++------ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/pkg/templates/python/yutori-computer-use/main.py b/pkg/templates/python/yutori-computer-use/main.py index 8952af5..4679df8 100644 --- a/pkg/templates/python/yutori-computer-use/main.py +++ b/pkg/templates/python/yutori-computer-use/main.py @@ -50,6 +50,7 @@ async def cua_task( kiosk_mode = payload.get("kiosk", False) async with KernelBrowserSession( + invocation_id=ctx.invocation_id, stealth=True, record_replay=record_replay, kiosk_mode=kiosk_mode, diff --git a/pkg/templates/python/yutori-computer-use/session.py b/pkg/templates/python/yutori-computer-use/session.py index 74c27de..9bf020f 100644 --- a/pkg/templates/python/yutori-computer-use/session.py +++ b/pkg/templates/python/yutori-computer-use/session.py @@ -42,6 +42,9 @@ class KernelBrowserSession: # Kiosk mode (hides address bar and tabs in live view) kiosk_mode: bool = False + # Invocation ID to link browser session to the action invocation + invocation_id: Optional[str] = None + # Set after browser creation session_id: Optional[str] = field(default=None, init=False) live_view_url: Optional[str] = field(default=None, init=False) @@ -54,6 +57,7 @@ async def __aenter__(self) -> "KernelBrowserSession": self._kernel = Kernel() browser = self._kernel.browsers.create( + invocation_id=self.invocation_id, stealth=self.stealth, timeout_seconds=self.timeout_seconds, viewport={ diff --git a/pkg/templates/typescript/yutori-computer-use/index.ts b/pkg/templates/typescript/yutori-computer-use/index.ts index b3786f4..364e723 100644 --- a/pkg/templates/typescript/yutori-computer-use/index.ts +++ b/pkg/templates/typescript/yutori-computer-use/index.ts @@ -35,6 +35,7 @@ app.action( // Create browser session with optional replay recording and kiosk mode const kioskMode = payload.kiosk ?? false; const session = new KernelBrowserSession(kernel, { + invocationId: ctx.invocation_id, stealth: true, recordReplay: payload.record_replay ?? false, kioskMode, diff --git a/pkg/templates/typescript/yutori-computer-use/session.ts b/pkg/templates/typescript/yutori-computer-use/session.ts index 4a0699b..b0edcc3 100644 --- a/pkg/templates/typescript/yutori-computer-use/session.ts +++ b/pkg/templates/typescript/yutori-computer-use/session.ts @@ -8,6 +8,8 @@ import type { Kernel } from '@onkernel/sdk'; export interface SessionOptions { + /** Invocation ID to link browser session to the action invocation */ + invocationId?: string; /** Enable stealth mode to avoid bot detection */ stealth?: boolean; /** Browser session timeout in seconds */ @@ -34,7 +36,9 @@ export interface SessionInfo { viewportHeight: number; } -const DEFAULT_OPTIONS: Required = { +type SessionOptionsWithDefaults = Required> & Pick; + +const DEFAULT_OPTIONS: Required> = { stealth: true, timeoutSeconds: 300, recordReplay: false, @@ -60,7 +64,7 @@ const DEFAULT_OPTIONS: Required = { */ export class KernelBrowserSession { private kernel: Kernel; - private options: Required; + private options: SessionOptionsWithDefaults; // Session state private _sessionId: string | null = null; @@ -119,6 +123,7 @@ export class KernelBrowserSession { async start(): Promise { const browser = await this.kernel.browsers.create({ + invocation_id: this.options.invocationId, stealth: this.options.stealth, timeout_seconds: this.options.timeoutSeconds, viewport: { @@ -128,9 +133,9 @@ export class KernelBrowserSession { kiosk_mode: this.options.kioskMode, }); - this._sessionId = browser.session_id; - this._liveViewUrl = browser.browser_live_view_url; - this._cdpWsUrl = browser.cdp_ws_url; + this._sessionId = browser.session_id ?? null; + this._liveViewUrl = browser.browser_live_view_url ?? null; + this._cdpWsUrl = browser.cdp_ws_url ?? null; console.log(`Kernel browser created: ${this._sessionId}`); console.log(`Live view URL: ${this._liveViewUrl}`); @@ -183,7 +188,7 @@ export class KernelBrowserSession { const replays = await this.kernel.browsers.replays.list(this._sessionId); for (const replay of replays) { if (replay.replay_id === this._replayId) { - this._replayViewUrl = replay.replay_view_url; + this._replayViewUrl = replay.replay_view_url ?? null; replayReady = true; break; } From dfd426d7352f6bf17eefa3919aa72d672e845aff Mon Sep 17 00:00:00 2001 From: Daniel Prevoznik Date: Thu, 19 Feb 2026 11:13:57 -0500 Subject: [PATCH 2/5] Add invocation_id to Gemini computer-use template browser creation Co-authored-by: Cursor --- pkg/templates/python/gemini-computer-use/main.py | 1 + pkg/templates/python/gemini-computer-use/session.py | 4 ++++ pkg/templates/typescript/gemini-computer-use/index.ts | 1 + pkg/templates/typescript/gemini-computer-use/session.ts | 9 +++++++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/templates/python/gemini-computer-use/main.py b/pkg/templates/python/gemini-computer-use/main.py index 0c7d461..870ff77 100644 --- a/pkg/templates/python/gemini-computer-use/main.py +++ b/pkg/templates/python/gemini-computer-use/main.py @@ -52,6 +52,7 @@ async def cua_task( record_replay = payload.get("record_replay", False) async with KernelBrowserSession( + invocation_id=ctx.invocation_id, stealth=True, record_replay=record_replay, ) as session: diff --git a/pkg/templates/python/gemini-computer-use/session.py b/pkg/templates/python/gemini-computer-use/session.py index 82e856d..16c998b 100644 --- a/pkg/templates/python/gemini-computer-use/session.py +++ b/pkg/templates/python/gemini-computer-use/session.py @@ -23,6 +23,9 @@ class KernelBrowserSession: record_replay: bool = False replay_grace_period: float = 5.0 # Seconds to wait before stopping replay + # Invocation ID to link browser session to the action invocation + invocation_id: Optional[str] = None + # Set after browser creation session_id: Optional[str] = field(default=None, init=False) live_view_url: Optional[str] = field(default=None, init=False) @@ -35,6 +38,7 @@ async def __aenter__(self) -> "KernelBrowserSession": # Create browser with specified settings browser = self._kernel.browsers.create( + invocation_id=self.invocation_id, stealth=self.stealth, timeout_seconds=self.timeout_seconds, viewport={ diff --git a/pkg/templates/typescript/gemini-computer-use/index.ts b/pkg/templates/typescript/gemini-computer-use/index.ts index 1b27b42..91f47e4 100644 --- a/pkg/templates/typescript/gemini-computer-use/index.ts +++ b/pkg/templates/typescript/gemini-computer-use/index.ts @@ -39,6 +39,7 @@ app.action( // Create browser session with optional replay recording const session = new KernelBrowserSession(kernel, { + invocationId: ctx.invocation_id, stealth: true, recordReplay: payload.record_replay ?? false, }); diff --git a/pkg/templates/typescript/gemini-computer-use/session.ts b/pkg/templates/typescript/gemini-computer-use/session.ts index fd68442..627b442 100644 --- a/pkg/templates/typescript/gemini-computer-use/session.ts +++ b/pkg/templates/typescript/gemini-computer-use/session.ts @@ -9,6 +9,8 @@ import type { Kernel } from '@onkernel/sdk'; import { DEFAULT_SCREEN_SIZE } from './tools/types/gemini'; export interface SessionOptions { + /** Invocation ID to link browser session to the action invocation */ + invocationId?: string; stealth?: boolean; timeoutSeconds?: number; recordReplay?: boolean; @@ -22,7 +24,9 @@ export interface SessionInfo { replayViewUrl?: string; } -const DEFAULT_OPTIONS: Required = { +type SessionOptionsWithDefaults = Required> & Pick; + +const DEFAULT_OPTIONS: Required> = { stealth: true, timeoutSeconds: 300, recordReplay: false, @@ -31,7 +35,7 @@ const DEFAULT_OPTIONS: Required = { export class KernelBrowserSession { private kernel: Kernel; - private options: Required; + private options: SessionOptionsWithDefaults; // Session state private _sessionId: string | null = null; @@ -71,6 +75,7 @@ export class KernelBrowserSession { async start(): Promise { // Create browser with specified settings const browser = await this.kernel.browsers.create({ + invocation_id: this.options.invocationId, stealth: this.options.stealth, timeout_seconds: this.options.timeoutSeconds, viewport: { From 5c69fcdd3285aaa6ab3b07ab5b0c0f823be6a66d Mon Sep 17 00:00:00 2001 From: Daniel Prevoznik Date: Thu, 19 Feb 2026 11:14:27 -0500 Subject: [PATCH 3/5] Add invocation_id to OpenAGI computer-use template browser creation Co-authored-by: Cursor --- .../python/openagi-computer-use/kernel_session.py | 4 ++++ pkg/templates/python/openagi-computer-use/main.py | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/pkg/templates/python/openagi-computer-use/kernel_session.py b/pkg/templates/python/openagi-computer-use/kernel_session.py index 61758e7..1e8984f 100644 --- a/pkg/templates/python/openagi-computer-use/kernel_session.py +++ b/pkg/templates/python/openagi-computer-use/kernel_session.py @@ -35,6 +35,9 @@ class KernelBrowserSession: replay_framerate: int = 30 replay_grace_period: float = 5.0 # Seconds to wait before stopping replay + # Invocation ID to link browser session to the action invocation + invocation_id: str | None = None + # Set after browser creation session_id: str | None = None live_view_url: str | None = None @@ -48,6 +51,7 @@ async def __aenter__(self) -> "KernelBrowserSession": # Create browser with specified settings browser = self._kernel.browsers.create( + invocation_id=self.invocation_id, stealth=self.stealth, timeout_seconds=self.timeout_seconds, ) diff --git a/pkg/templates/python/openagi-computer-use/main.py b/pkg/templates/python/openagi-computer-use/main.py index 83b172c..1ac427d 100644 --- a/pkg/templates/python/openagi-computer-use/main.py +++ b/pkg/templates/python/openagi-computer-use/main.py @@ -103,7 +103,10 @@ async def oagi_default_task( model = payload.get("model", "lux-actor-1") record_replay = payload.get("record_replay", False) - async with KernelBrowserSession(record_replay=record_replay) as session: + async with KernelBrowserSession( + record_replay=record_replay, + invocation_id=ctx.invocation_id, + ) as session: print("Kernel browser live view url:", session.live_view_url) provider = KernelScreenshotProvider(session) @@ -155,7 +158,10 @@ async def oagi_tasker_task( todos = payload["todos"] record_replay = payload.get("record_replay", False) - async with KernelBrowserSession(record_replay=record_replay) as session: + async with KernelBrowserSession( + record_replay=record_replay, + invocation_id=ctx.invocation_id, + ) as session: print("Kernel browser live view url:", session.live_view_url) provider = KernelScreenshotProvider(session) From 480ddb5ead368f35394fe08a63227f88193aef32 Mon Sep 17 00:00:00 2001 From: Daniel Prevoznik Date: Thu, 19 Feb 2026 11:15:17 -0500 Subject: [PATCH 4/5] Add invocation_id to Anthropic computer-use template browser creation Co-authored-by: Cursor --- pkg/templates/python/anthropic-computer-use/main.py | 1 + .../python/anthropic-computer-use/session.py | 4 ++++ .../typescript/anthropic-computer-use/index.ts | 1 + .../typescript/anthropic-computer-use/session.ts | 11 ++++++++--- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/pkg/templates/python/anthropic-computer-use/main.py b/pkg/templates/python/anthropic-computer-use/main.py index 51b571d..9f3e58b 100644 --- a/pkg/templates/python/anthropic-computer-use/main.py +++ b/pkg/templates/python/anthropic-computer-use/main.py @@ -48,6 +48,7 @@ async def cua_task( record_replay = payload.get("record_replay", False) async with KernelBrowserSession( + invocation_id=ctx.invocation_id, stealth=True, record_replay=record_replay, ) as session: diff --git a/pkg/templates/python/anthropic-computer-use/session.py b/pkg/templates/python/anthropic-computer-use/session.py index 4718dbd..eb4c16b 100644 --- a/pkg/templates/python/anthropic-computer-use/session.py +++ b/pkg/templates/python/anthropic-computer-use/session.py @@ -39,6 +39,9 @@ class KernelBrowserSession: record_replay: bool = False replay_grace_period: float = 5.0 # Seconds to wait before stopping replay + # Invocation ID to link browser session to the action invocation + invocation_id: Optional[str] = None + # Set after browser creation session_id: Optional[str] = field(default=None, init=False) live_view_url: Optional[str] = field(default=None, init=False) @@ -52,6 +55,7 @@ async def __aenter__(self) -> "KernelBrowserSession": # Create browser with specified settings browser = self._kernel.browsers.create( + invocation_id=self.invocation_id, stealth=self.stealth, timeout_seconds=self.timeout_seconds, viewport={ diff --git a/pkg/templates/typescript/anthropic-computer-use/index.ts b/pkg/templates/typescript/anthropic-computer-use/index.ts index b126626..ec16d40 100644 --- a/pkg/templates/typescript/anthropic-computer-use/index.ts +++ b/pkg/templates/typescript/anthropic-computer-use/index.ts @@ -33,6 +33,7 @@ app.action( // Create browser session with optional replay recording const session = new KernelBrowserSession(kernel, { + invocationId: ctx.invocation_id, stealth: true, recordReplay: payload.record_replay ?? false, }); diff --git a/pkg/templates/typescript/anthropic-computer-use/session.ts b/pkg/templates/typescript/anthropic-computer-use/session.ts index fed3dd4..6c2c77d 100644 --- a/pkg/templates/typescript/anthropic-computer-use/session.ts +++ b/pkg/templates/typescript/anthropic-computer-use/session.ts @@ -8,6 +8,8 @@ import type { Kernel } from '@onkernel/sdk'; export interface SessionOptions { + /** Invocation ID to link browser session to the action invocation */ + invocationId?: string; /** Enable stealth mode to avoid bot detection */ stealth?: boolean; /** Browser session timeout in seconds */ @@ -31,7 +33,9 @@ export interface SessionInfo { viewportHeight: number; } -const DEFAULT_OPTIONS: Required = { +type SessionOptionsWithDefaults = Required> & Pick; + +const DEFAULT_OPTIONS: Required> = { stealth: true, timeoutSeconds: 300, recordReplay: false, @@ -56,8 +60,8 @@ const DEFAULT_OPTIONS: Required = { */ export class KernelBrowserSession { private kernel: Kernel; - private options: Required; - + private options: SessionOptionsWithDefaults; + // Session state private _sessionId: string | null = null; private _liveViewUrl: string | null = null; @@ -109,6 +113,7 @@ export class KernelBrowserSession { async start(): Promise { // Create browser with specified settings const browser = await this.kernel.browsers.create({ + invocation_id: this.options.invocationId, stealth: this.options.stealth, timeout_seconds: this.options.timeoutSeconds, viewport: { From 732e43dde410de7cd638e2012d08a0d7d344cae7 Mon Sep 17 00:00:00 2001 From: Daniel Prevoznik Date: Thu, 19 Feb 2026 16:23:00 -0500 Subject: [PATCH 5/5] Upgrade Yutori, Gemini, OpenAGI, Anthropic templates to Kernel SDK 0.35.0 Co-authored-by: Cursor --- pkg/templates/python/anthropic-computer-use/pyproject.toml | 2 +- pkg/templates/python/gemini-computer-use/pyproject.toml | 2 +- pkg/templates/python/openagi-computer-use/pyproject.toml | 2 +- pkg/templates/python/yutori-computer-use/pyproject.toml | 2 +- pkg/templates/typescript/anthropic-computer-use/package.json | 2 +- pkg/templates/typescript/gemini-computer-use/package.json | 2 +- pkg/templates/typescript/yutori-computer-use/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/templates/python/anthropic-computer-use/pyproject.toml b/pkg/templates/python/anthropic-computer-use/pyproject.toml index f5b75de..4356b1a 100644 --- a/pkg/templates/python/anthropic-computer-use/pyproject.toml +++ b/pkg/templates/python/anthropic-computer-use/pyproject.toml @@ -8,6 +8,6 @@ dependencies = [ "python-dateutil>=2.9.0", "pydantic>=2.12.5", "typing-extensions>=4.15.0", - "kernel>=0.24.0", + "kernel>=0.35.0", "python-dotenv>=1.2.1", ] diff --git a/pkg/templates/python/gemini-computer-use/pyproject.toml b/pkg/templates/python/gemini-computer-use/pyproject.toml index c689f30..b8d1a97 100644 --- a/pkg/templates/python/gemini-computer-use/pyproject.toml +++ b/pkg/templates/python/gemini-computer-use/pyproject.toml @@ -6,7 +6,7 @@ readme = "README.md" requires-python = ">=3.11" dependencies = [ "google-genai>=1.0.0", - "kernel>=0.5.0", + "kernel>=0.35.0", ] [tool.uv] diff --git a/pkg/templates/python/openagi-computer-use/pyproject.toml b/pkg/templates/python/openagi-computer-use/pyproject.toml index a4ea55d..8c2345c 100644 --- a/pkg/templates/python/openagi-computer-use/pyproject.toml +++ b/pkg/templates/python/openagi-computer-use/pyproject.toml @@ -5,7 +5,7 @@ description = "Kernel sample app for OpenAGI Lux computer-use models" readme = "README.md" requires-python = ">=3.11" dependencies = [ - "kernel>=0.22.0", + "kernel>=0.35.0", "oagi>=0.1.0", "python-dotenv>=1.0.0", "Pillow>=10.0.0", diff --git a/pkg/templates/python/yutori-computer-use/pyproject.toml b/pkg/templates/python/yutori-computer-use/pyproject.toml index 2547174..aafe423 100644 --- a/pkg/templates/python/yutori-computer-use/pyproject.toml +++ b/pkg/templates/python/yutori-computer-use/pyproject.toml @@ -5,7 +5,7 @@ description = "Kernel reference app for Yutori n1 Computer Use" requires-python = ">=3.9" dependencies = [ "openai>=1.58.0", - "kernel>=0.24.0", + "kernel>=0.35.0", "python-dotenv>=1.2.1", "Pillow>=10.0.0", ] diff --git a/pkg/templates/typescript/anthropic-computer-use/package.json b/pkg/templates/typescript/anthropic-computer-use/package.json index 8012da1..ad09a3d 100644 --- a/pkg/templates/typescript/anthropic-computer-use/package.json +++ b/pkg/templates/typescript/anthropic-computer-use/package.json @@ -5,7 +5,7 @@ "private": true, "dependencies": { "@anthropic-ai/sdk": "^0.71.2", - "@onkernel/sdk": "^0.24.0", + "@onkernel/sdk": "^0.35.0", "luxon": "^3.7.2" }, "devDependencies": { diff --git a/pkg/templates/typescript/gemini-computer-use/package.json b/pkg/templates/typescript/gemini-computer-use/package.json index 8ef6ebf..eee9937 100644 --- a/pkg/templates/typescript/gemini-computer-use/package.json +++ b/pkg/templates/typescript/gemini-computer-use/package.json @@ -5,7 +5,7 @@ "private": true, "dependencies": { "@google/genai": "^1.0.0", - "@onkernel/sdk": "^0.23.0" + "@onkernel/sdk": "^0.35.0" }, "devDependencies": { "@types/node": "^22.15.17", diff --git a/pkg/templates/typescript/yutori-computer-use/package.json b/pkg/templates/typescript/yutori-computer-use/package.json index e3683db..f1fc38c 100644 --- a/pkg/templates/typescript/yutori-computer-use/package.json +++ b/pkg/templates/typescript/yutori-computer-use/package.json @@ -4,7 +4,7 @@ "type": "module", "private": true, "dependencies": { - "@onkernel/sdk": "^0.24.0", + "@onkernel/sdk": "^0.35.0", "openai": "^4.77.0", "sharp": "^0.33.0" },