Skip to content

Migrate cua-cli to CuaAgentHarness runtime - #14

Closed
rgarcia wants to merge 5 commits into
mainfrom
hypeship/cua-cli-cuaagentharness-migration
Closed

Migrate cua-cli to CuaAgentHarness runtime#14
rgarcia wants to merge 5 commits into
mainfrom
hypeship/cua-cli-cuaagentharness-migration

Conversation

@rgarcia

@rgarcia rgarcia commented May 14, 2026

Copy link
Copy Markdown
Contributor

Summary

  • route cua-cli print, interactive, and action flows through @onkernel/cua-agent's CuaAgentHarness instead of wiring pi-agent-core Agent directly
  • replace SessionManager persistence plumbing with harness-native session primitives (JsonlSessionRepo/InMemorySessionRepo + NodeExecutionEnv) while preserving resume/session selection behavior
  • consolidate model/runtime dependencies onto @onkernel/cua-ai and remove direct provider package wiring from cua-cli

Test plan

  • npm run --workspace @onkernel/cua-cli build
  • npm run --workspace @onkernel/cua-cli test (fails in this environment: missing ptywright native dependency toolchain; zig not installed)

Made with Cursor


Note

Medium Risk
Refactors core cua-cli execution and session persistence paths onto @onkernel/cua-agent/@onkernel/cua-ai, which can change agent behavior and resume semantics across providers. Adds new live CI coverage, but failures would primarily affect CLI runtime and session files rather than data security.

Overview
Migrates cua-cli from direct pi-agent-core wiring to @onkernel/cua-agent’s CuaAgentHarness, including switching model discovery/loading to @onkernel/cua-ai runtime specs and consolidating computer tool wiring via createCuaComputerTools.

Replaces SessionManager persistence with harness-native sessions (JsonlSessionRepo/InMemorySessionRepo + NodeExecutionEnv), updating print/action/interactive flows to pass CuaSessionState and compute resume/initial-screenshot behavior from stored context.

Adds a new live CLI TUI e2e smoke test (and CI job that installs Zig + builds ptywright native) and tweaks agent live tests to terminate Yutori after the first completed tool batch for determinism; also adjusts ptywright ESM exports/imports for .js paths.

Reviewed by Cursor Bugbot for commit e17af3e. Bugbot is set up for automated code reviews on this repo. Configure here.

rgarcia and others added 5 commits May 13, 2026 04:20
Route print, interactive, and action flows through @onkernel/cua-agent/@onkernel/cua-ai with harness-native session repos so transcript persistence and resume behavior use the shared AgentHarness primitives.

Co-authored-by: Cursor <cursoragent@cursor.com>
Execute fixture-main via tsx with source conditions so ptywright-driven TUI e2e tests no longer fail on ESM extensionless imports in dist output.

Co-authored-by: Cursor <cursoragent@cursor.com>
Prepend the resolved Zig binary directory to PATH for build-ghostty subprocesses so combine_archives can invoke `zig ar` even when Zig is only installed under .dev/tools.

Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce an env-gated ptywright live test for OpenAI+Kernel flows and wire it into CI (non-draft PRs and main) with Zig installation and native ptywright build.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use explicit .js import specifiers in ptywright's ESM entrypoints so cli-e2e can resolve dist modules in Node. Add a Yutori harness test termination guard to avoid non-deterministic multi-round tool loops timing out in agent-e2e.

Co-authored-by: Cursor <cursoragent@cursor.com>
@rgarcia
rgarcia marked this pull request as ready for review May 14, 2026 12:16
@firetiger-agent

Copy link
Copy Markdown

Firetiger deploy monitoring skipped

This PR didn't match the auto-monitor filter configured on your GitHub connection:

Any PR that changes the kernel API. Monitor changes to API endpoints (packages/api/cmd/api/) and Temporal workflows (packages/api/lib/temporal) in the kernel repo

Reason: PR modifies cua-cli package and agent runtime, but does not change API endpoints (packages/api/cmd/api/) or Temporal workflows (packages/api/lib/temporal) that the filter specifies.

To monitor this PR anyway, reply with @firetiger monitor this.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Dead unsubscribePersist variable left from migration
    • Removed the unused unsubscribePersist declaration, redundant reassignment, and no-op cleanup call from runInteractive because persistence is already handled by the harness.

Create PR

Or push these changes by commenting:

@cursor push 0bee1c46f1
Preview (0bee1c46f1)
diff --git a/packages/cua-cli/src/tui/main.ts b/packages/cua-cli/src/tui/main.ts
--- a/packages/cua-cli/src/tui/main.ts
+++ b/packages/cua-cli/src/tui/main.ts
@@ -146,7 +146,6 @@
 		});
 	};
 
-	let unsubscribePersist = () => {};
 	const sm = opts.sessionState;
 	if (liveHandle && sm) await appendBrowserMetadata(sm, opts.browser);
 	if (liveHandle && sm && opts.resumed) {
@@ -154,7 +153,6 @@
 			`resumed from ${sm.getSessionFile() ?? "memory"} · ${sm.priorMessageCount} prior messages · fresh browser`,
 		);
 	}
-	unsubscribePersist = () => {};
 	let driver: InteractiveDriver =
 		opts.driver ?? new LiveInteractiveDriver(liveHandle!, { skipInitialScreenshot: opts.resumed === true });
 
@@ -339,7 +337,6 @@
 	} finally {
 		removeListener();
 		unsubscribe();
-		unsubscribePersist();
 		tui.stop();
 		try {
 			await driver.dispose();

You can send follow-ups to the cloud agent here.

Comment thread packages/cua-cli/src/tui/main.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Autofix Details

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: Redundant resumed prop duplicates sessionState.resumed
    • I removed the separate InteractiveOptions.resumed field and now derive resume behavior directly from sessionState.resumed at use sites to eliminate duplicate state.

Create PR

Or push these changes by commenting:

@cursor push afca7c44df
Preview (afca7c44df)
diff --git a/packages/cua-cli/src/cli.ts b/packages/cua-cli/src/cli.ts
--- a/packages/cua-cli/src/cli.ts
+++ b/packages/cua-cli/src/cli.ts
@@ -884,7 +884,6 @@
 		debugTui: flags.debugTui,
 		imageProtocol: flags.imageProtocol,
 		sessionState: sm,
-		resumed: sm.resumed,
 		skills: startupResources.skills,
 		startupResources,
 	});

diff --git a/packages/cua-cli/src/tui/main.ts b/packages/cua-cli/src/tui/main.ts
--- a/packages/cua-cli/src/tui/main.ts
+++ b/packages/cua-cli/src/tui/main.ts
@@ -41,8 +41,6 @@
 	imageProtocol?: string;
 	/** Optional harness-native session state for transcript persistence. */
 	sessionState?: CuaSessionState;
-	/** True when seeding the agent from a previously persisted session. */
-	resumed?: boolean;
 	/** Skills available for /skill:name expansion and system-prompt injection. */
 	skills?: Skill[];
 	/** Optional startup sections mirroring pi's Context/Skills inventory. */
@@ -148,15 +146,16 @@
 
 	let unsubscribePersist = () => {};
 	const sm = opts.sessionState;
+	const resumed = sm?.resumed === true;
 	if (liveHandle && sm) await appendBrowserMetadata(sm, opts.browser);
-	if (liveHandle && sm && opts.resumed) {
+	if (liveHandle && sm && resumed) {
 		messages.addNotice(
 			`resumed from ${sm.getSessionFile() ?? "memory"} · ${sm.priorMessageCount} prior messages · fresh browser`,
 		);
 	}
 	unsubscribePersist = () => {};
 	let driver: InteractiveDriver =
-		opts.driver ?? new LiveInteractiveDriver(liveHandle!, { skipInitialScreenshot: opts.resumed === true });
+		opts.driver ?? new LiveInteractiveDriver(liveHandle!, { skipInitialScreenshot: resumed });
 
 	let assistantBuffer: AssistantBuffer | undefined;
 	let inflight = 0;

You can send follow-ups to the cloud agent here.

Comment thread packages/cua-cli/src/tui/main.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix prepared a fix for the issue found in the latest run.

  • ✅ Fixed: New exported interfaces lack required TSDoc comments
    • Added TSDoc comments to both exported interfaces SessionInfo and CuaSessionState in packages/cua-cli/src/sessions.ts to document their purpose and usage semantics.

Create PR

Or push these changes by commenting:

@cursor push 75a8d44ff4
Preview (75a8d44ff4)
diff --git a/packages/cua-cli/src/sessions.ts b/packages/cua-cli/src/sessions.ts
--- a/packages/cua-cli/src/sessions.ts
+++ b/packages/cua-cli/src/sessions.ts
@@ -29,6 +29,7 @@
 	parentSession?: string;
 }
 
+/** Display-oriented metadata for a persisted session in session list and resume selection flows. */
 export interface SessionInfo {
 	path: string;
 	id: string;
@@ -41,6 +42,12 @@
 	firstMessage: string;
 }
 
+/**
+ * Runtime session bundle shared by CLI flows after opening or resuming a session.
+ *
+ * `resumed` and `priorMessageCount` describe whether existing transcript history was loaded,
+ * and `getSessionFile()` returns the persisted JSONL path (or `undefined` for ephemeral sessions).
+ */
 export interface CuaSessionState {
 	env: NodeExecutionEnv;
 	session: Session;

You can send follow-ups to the cloud agent here.

Reviewed by Cursor Bugbot for commit e17af3e. Configure here.

resumed: boolean;
priorMessageCount: number;
getSessionFile(): string | undefined;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New exported interfaces lack required TSDoc comments

Low Severity

The newly introduced exported interfaces CuaSessionState and SessionInfo lack TSDoc-style comments explaining their purpose. These are key types used across the CLI for session management and are exported for use by other modules, so newcomers would benefit from documentation explaining what they represent.

Additional Locations (1)
Fix in Cursor Fix in Web

Triggered by learned rule: Exported types, interfaces, and classes require TSDoc

Reviewed by Cursor Bugbot for commit e17af3e. Configure here.

@rgarcia rgarcia closed this Jun 12, 2026
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.

1 participant