Upgrade pi to 0.83.0 and adopt context-first harness tools - #72
Merged
Conversation
- Upgrade @earendil-works/pi-ai, pi-agent-core, pi-coding-agent, and
pi-tui to exact 0.83.0 with one deduplicated instance of each.
- Redesign CuaAgentHarness on pi's TContext-first AgentHarness generics:
CuaAgentHarness<TContext, TSkill, TPromptTemplate> accepts and forwards
toolContext directly, and executable harness tools are pi
AgentHarnessTool<TContext> via the new CuaHarnessTool<TContext> union.
CuaAgent stays on the ordinary AgentTool (CuaAgentTool).
- Remove CuaAgentHarnessOptions.env, CuaAgentHarness.env, and
CuaSystemPromptCallback with no aliases; execution environments now
travel through the tool context.
- Move CLI coding tools from pi-coding-agent createCodingTools(cwd) to
pi-agent-core createReadTool/createBashTool/createEditTool/
createWriteTool (order preserved), supplying
toolContext: { env: new NodeExecutionEnv({ cwd }) }.
- Adopt pi's Kimi K3 low/high/max reasoning-effort metadata and request
behavior with no override; pin the metadata and add payload regression
coverage for the CLI default low level on Moonshot and OpenRouter.
- Drop the local claude-opus-5 and gemini-3.6-flash/3.5-flash-lite
overrides now carried by pi's registry; keep the CUA-only Meta, Tzafon,
and Yutori models.
- Add a downstream published-declaration compile test (skipLibCheck:
false) and context-delivery tests proving custom harness tools receive
the exact supplied context, exercising pi's native read/bash/edit/
write tools through CUA.
- Release as @onkernel/cua-ai 0.10.0, @onkernel/cua-agent 0.10.0, and
@onkernel/cua-cli 0.8.0.
Tzafon's Responses API rejects a computer_call_output whose output carries no image (400: empty image slot). After a non-screenshot action the tool result was text-only, so the follow-up request after any click or keypress failed and the turn ended in an API error. The Tzafon native computer spec now declares a postActionScreenshot execution policy, and CuaExecutionResources attaches a best-effort post-execution screenshot when an action batch produced no image read, on success and failure alike. A failed capture never masks the action outcome. Canonical and other provider-native tools are unchanged.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Missing TSDoc on exported helper
- Added a TSDoc block to the exported mapThinkingLevel helper documenting purpose, defaulting behavior, and invalid-input error contract.
Or push these changes by commenting:
@cursor push 21209a2a93
Preview (21209a2a93)
diff --git a/packages/cli/src/cli-harness.ts b/packages/cli/src/cli-harness.ts
--- a/packages/cli/src/cli-harness.ts
+++ b/packages/cli/src/cli-harness.ts
@@ -487,6 +487,12 @@
return value && value.length > 0 ? value : undefined;
}
+/**
+ * Normalize CLI `--thinking` values to canonical harness thinking levels.
+ *
+ * Defaults to `"low"` when the flag is unset or empty, and throws when the
+ * input does not match a supported level.
+ */
export function mapThinkingLevel(raw: string | undefined): "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max" {
const v = (raw ?? "low").trim().toLowerCase();
switch (v) {You can send follow-ups to the cloud agent here.
Add the missing TSDoc on the newly exported mapThinkingLevel and record the postActionScreenshot execution policy in both 0.10.0 changelogs.
cua-cli 0.8.0 shipped from main with queued-turn steering, so the pi 0.83 CLI changes here move to a new 0.9.0 entry; the changelog conflict resolves to both entries and packages/cli bumps to 0.9.0.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Tzafon image guard blocks continuations
- Native Tzafon tool-result replay now emits a text-backed
computer_screenshot.errorpayload when no image is present instead of throwing, so valid text-only continuations no longer hard-fail.
- Native Tzafon tool-result replay now emits a text-backed
Or push these changes by commenting:
@cursor push 62940dda82
Preview (62940dda82)
diff --git a/packages/ai/src/providers/tzafon/provider.ts b/packages/ai/src/providers/tzafon/provider.ts
--- a/packages/ai/src/providers/tzafon/provider.ts
+++ b/packages/ai/src/providers/tzafon/provider.ts
@@ -344,15 +344,12 @@
.trim();
const image = [...message.content].reverse().find((part): part is ImageContent => part.type === "image");
if (nativeComputerName && message.toolName === nativeComputerName) {
- if (!image) {
- throw new Error(
- "Tzafon native computer action loops require image tool results; text-only results are unsupported because CUA does not capture post-action screenshots automatically.",
- );
- }
items.push({
type: "computer_call_output",
call_id: message.toolCallId,
- output: { type: "computer_screenshot", image_url: `data:${image.mimeType};base64,${image.data}` },
+ output: image
+ ? { type: "computer_screenshot", image_url: `data:${image.mimeType};base64,${image.data}` }
+ : { type: "computer_screenshot", error: message.isError ? text || "tool execution failed" : text || "no screenshot" },
});
continue;
}
diff --git a/packages/ai/test/tzafon-provider.test.ts b/packages/ai/test/tzafon-provider.test.ts
--- a/packages/ai/test/tzafon-provider.test.ts
+++ b/packages/ai/test/tzafon-provider.test.ts
@@ -99,8 +99,8 @@
expect(toolCalls(message.content)).toEqual([]);
});
- it("rejects text-only native computer results before sending a request", () => {
- expect(() => tzafon.buildTzafonRequestInput(model, {
+ it("serializes text-only native computer results as computer_screenshot errors", () => {
+ const payload = tzafon.buildTzafonRequestInput(model, {
messages: [
{
role: "assistant",
@@ -125,7 +125,19 @@
}, {
disableResponseThreading: true,
cuaIncomingToolPlan: { tzafonComputerName: "computer", yutoriNames: {}, googleNames: {}, googleExcludedNames: [], nativeToolNames: ["computer"] },
- })).toThrow("text-only results are unsupported");
+ });
+
+ expect(payload.input).toEqual(expect.arrayContaining([
+ expect.objectContaining({ type: "computer_call", call_id: "call_click" }),
+ expect.objectContaining({
+ type: "computer_call_output",
+ call_id: "call_click",
+ output: {
+ type: "computer_screenshot",
+ error: "Actions executed successfully.",
+ },
+ }),
+ ]));
});
it("degrades malformed function-call arguments to empty args instead of failing the turn", async () => {You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit f588ba4. Configure here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
Upgrades the whole pi stack to exact 0.83.0 (
@earendil-works/pi-ai,pi-agent-core,pi-coding-agent,pi-tui) with one deduplicated instance of each, and adopts pi 0.83's context-first harness API as a breaking release:@onkernel/cua-ai0.10.0,@onkernel/cua-agent0.10.0,@onkernel/cua-cli0.9.0 (0.8.0 shipped from main with queued-turn steering while this PR was open).Harness redesign (
@onkernel/cua-agent)CuaAgentHarnessandCuaAgentHarnessOptionsare now TContext-first —CuaAgentHarness<TContext, TSkill, TPromptTemplate>— mirroring pi'sAgentHarnessgeneric order and semantics. The suppliedtoolContextis forwarded to pi untouched.AgentHarnessTool<TContext>via the newCuaHarnessTool<TContext>union (a CUA spec or anAgentHarnessTool).CuaAgentstays on the ordinary piAgentTool(CuaAgentTool); the two tool APIs are no longer conflated.CuaToolManagernow materializes both views from one compiled catalog.CuaAgentHarnessOptions.env,CuaAgentHarness.env, andCuaSystemPromptCallback— no aliases. Execution environments travel through the tool context;systemPromptis pi'sAgentHarnessSystemPrompt.CuaAgentHarnessOptions.retryomits pi's new harnessretry?: RetryPolicy(compaction/branch-summary) so it keeps meaning CUA's provider retry policy, unchanged.streamFnstays optional onCuaAgentOptions(CUA supplies its default stream) even though pi 0.83 makesAgentOptions.streamFnrequired.CLI (
@onkernel/cua-cli)createCodingTools(cwd)to pi-agent-corecreateReadTool/createBashTool/createEditTool/createWriteTool(read/bash/edit/write order preserved), withtoolContext: { env: new NodeExecutionEnv({ cwd }) }.low/high/maxmap throughthinkingLevelMap, and the CLI default (--thinkingunset →low) sendsreasoning_effort: "low"to Moonshot andreasoning: { effort: "low" }through OpenRouter. New payload regression tests pin both.Models (
@onkernel/cua-ai)claude-opus-5,gemini-3.6-flash, andgemini-3.5-flash-liteoverrides — pi 0.83's registry carries all three with the same metadata. Overrides remain only for the CUA-only providers pi does not ship (Meta, Tzafon, Yutori).Tzafon native action-loop guard (
@onkernel/cua-ai)computer_call_outputto carry an image. CUA does not synthesize post-action screenshots, so native non-screenshot actions now fail before browser execution instead of entering an unsupported text-only loop. Explicit screenshot and terminal answer actions remain supported.toolResultImageReplayLimit, since pruning them would make valid history impossible to replay through that protocol. Other tool-result images remain bounded.Tests
npm run typecheck(clean build): pass.@onkernel/cua-ai: 114 passed.@onkernel/cua-agent: 291 passed, 19 skipped (live tests self-skip withoutKERNEL_API_KEY).@onkernel/cua-cli: 141 passed, 14 skipped (ptywright native binding not built locally).harness-context.test.tsproves a custom harness tool receives the exact supplied context object and drives pi's native read/write/edit/bash tools through CUA against a real temp directory;published-declarations.test.tscompiles a downstream consumer against the packageddist/declarations withskipLibCheck: false;kimi-reasoning-payload.test.tspins the default-low payloads; Tzafon provider tests pin the native non-screenshot rejection before browser execution.cua models,cua --help) without secrets.npm ls: single 0.83.0 of each pi package, single typebox 1.3.7.npm audit: 3 remaining advisories (brace-expansion, undici via pi-coding-agent, and a moderate) are pre-existing onmainand pinned by upstream dependency ranges; not changed by this PR.packages/ptywright's own test suite fails on main with extensionless ESM imports (ERR_MODULE_NOT_FOUNDfordist/index); this PR does not touch ptywright. Latent type errors inbrowser-wait.test.ts/cli-executor.test.tsalso predate this change (test files are outside every tsconfig project).Note
High Risk
Breaking public harness and CLI APIs plus a major pi/TypeBox bump affect all consumers; Tzafon and image-replay behavior changes are easy to miss in integration testing.
Overview
Bumps the monorepo to pi 0.83.0 (
pi-ai,pi-agent-core,pi-coding-agent,pi-tui) and ships breaking 0.10.0 agent/ai and 0.9.0 CLI releases.CuaAgentHarnessis now context-first: generics areCuaAgentHarness<TContext, …>, harness tools areCuaHarnessTool/ piAgentHarnessToolwithtoolContextforwarded on each call, andenvon the harness is removed (execution env goes throughtoolContext, e.g.NodeExecutionEnvfor read/bash/edit/write).CuaAgentkeeps context-freeCuaAgentTool;CuaToolManagerexposes both agent and harness tool views from one catalog.CLI swaps
createCodingToolsfor pi-agent-core read/bash/edit/write tools and wirestoolContext: { env }. Kimi K3 default thinking maps toreasoning_effort: lowper pi catalog metadata.@onkernel/cua-aidrops local overrides for Opus 5 and Gemini models now in pi’s registry. Tzafon rejects native non-screenshot computer actions and text-only native tool results because continuation requires images CUA does not auto-capture. Agent exempts Tzafon native screenshot tool results fromtoolResultImageReplayLimittrimming.New tests cover harness tool context, published declarations with
skipLibCheck: false, Kimi payloads, and Tzafon guards; docs note pi 0.83.0 for dynamicsetTools()behavior.Reviewed by Cursor Bugbot for commit e922447. Bugbot is set up for automated code reviews on this repo. Configure here.