Skip to content

sync: upstream v0.83.0 - #555

Closed
code-yeongyu wants to merge 118 commits into
mainfrom
automation/upstream-v0.83.0-30594691517
Closed

sync: upstream v0.83.0#555
code-yeongyu wants to merge 118 commits into
mainfrom
automation/upstream-v0.83.0-30594691517

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Jul 31, 2026

Copy link
Copy Markdown
Owner

Automated upstream sync for v0.83.0.

  • Upstream SHA: 74caa2649f10ed71b4378ce69f5d9fbfd2466ca5
  • Evidence artifact: upstream-agent-qa-v0.83.0
  • Release is evaluated only after this PR is merged with a merge commit.

QA completed before PR creation:

  • npm run build
  • npm run check
  • npm test
  • senpi-qa common, mock-loop, CLI smoke, and tmux TUI smoke when available

Summary by cubic

Upstream sync to v0.83.0. Adds an agent harness shutdown lifecycle, preserves raw stop reasons with a new "pending" streaming state, introduces alternate-screen TUI, per-request fetch, OpenRouter OAuth manual fallback, and the new @earendil-works/pi-protocol package.

  • New Features

    • Agent: graceful shutdown and task tracking; durable harness docs (harness.md, harness-v2.md).
    • AI: "pending" stopReason for partials; raw finish reasons preserved; per-request fetch; Copilot Claude Opus 5 via Anthropic; Qwen token-plan thinking controls; GPT-5.6 pricing refresh.
    • Coding Agent: alternate-screen TUI (--alt); chainable Markdown transformers; ctx.scopedModels in extensions; credential print commands; offline build script (npm run build:offline).
  • Migration

    • TypeBox upgraded to 1.3.7 in @earendil-works/pi-ai (breaking): removed deprecated APIs such as Type.Base, Type.Awaited, Type.Promise, Type.AsyncIterator, Type.Iterator, Type.Options, and Value.Mutate. Update extensions/custom providers to supported TypeBox APIs.
    • Provider adapters and custom providers should:
      • Initialize streamed outputs with stopReason: "pending".
      • Set a terminal stopReason from the final event and error if a stream ends without one.

Written for commit 0d9a845. Summary will update on new commits.

Review in cubic

christianklotz and others added 30 commits July 25, 2026 23:09
Route claude-opus-5 through the Anthropic Messages API with adaptive
thinking, the Copilot minimal thinking-level override, and pin the
extended 1M context window alongside the other Copilot Opus models.
* feat(ai): expose pending streaming stop reason

Closes #7142

* manual tidy up of human facing copy
…(#7114)

The OpenRouter PKCE flow only completed through the loopback callback
server, so remote/headless sessions (e.g. pi over SSH) could never
finish login: the browser runs on another machine and cannot reach
127.0.0.1 on the host running pi.

Race the callback server against a manual_code prompt, matching the
existing Anthropic and OpenAI Codex flows. Users can paste the final
redirect URL (or the bare authorization code) and the flow exchanges
it with the same PKCE verifier. A claimed callback keeps priority so
a pasted code cannot interrupt an in-flight exchange.

The callback server object follows the OAuthServerInfo shape from the
OpenAI Codex flow: waitForCredential() resolves null when cancelWait()
hands the login over to manual entry, and close() is pure cleanup that
never settles the wait.

Refs #7078
feat(coding-agent): add extension creation eval
Full design for the durable, resumable harness: session log with harness
entries, SessionTree query contract, public API with result unions, watch()
snapshots, events/hooks catalogs, recovery procedures as code, forks,
storage backends, and telemetry integration.
Extensions have no way to read the session's scoped model set (the models
resolved from --models / enabledModels against the available catalogue --
the same list /scoped-models shows). The only model surfaces on
ExtensionContext are ctx.model (active) and ctx.modelRegistry.getAvailable()
(the whole catalogue, unfiltered), so an extension that wants a scoped
model picker must either enumerate everything or re-implement pi's scope
resolution (minimatch on provider/modelId / bare modelId + enabledModels +
--models) from disk -- duplicating core logic.

Add ctx.scopedModels: readonly ScopedModel[] to ExtensionContext, mirroring
how ctx.model is exposed (field -> bindCore -> lazy getter in createContext()).
Empty when no scoping is configured (all available models usable). Each entry
is { model, thinkingLevel? }.

- types.ts: ExtensionContext.scopedModels + ExtensionContextActions.getScopedModels
- runner.ts: field, bindCore wiring, lazy scopedModels getter
- agent-session.ts: provide getScopedModels: () => this._scopedModels
- test: assert ctx.scopedModels reflects the action (default [] + live ref)
- docs/extensions.md: document the new field

Co-authored-by: ngSoftware <alessandro@pungitore.ch>
Bedrock profile configured via pi's auth flow was ignored when ambient
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY were set, because pi forced
config.credentials from those keys and the SDK treats explicit
credentials as overriding config.profile.

Fixes #6957
…ome directory (#7167)

* fix(coding-agent): isolate autoload-disabled package test from real home directory

The test asserted result.skills is exactly empty, but resolve() also
scans ~/.agents/skills via getHomeDir(). On machines where that
directory is populated the test failed; CI runners have no
~/.agents/skills, so it always passed there. Stub HOME to the temp
dir with the same save/restore pattern used by neighbouring tests.

* fix(coding-agent): use vi.stubEnv for home directory isolation

Replaces the manual try/finally save/restore with vi.stubEnv plus
vi.unstubAllEnvs in afterEach, shrinking the fix to two added lines.

* fix(coding-agent): plant decoy user skill so the empty-skills assertion cannot pass vacuously

With an empty sandbox, result.skills equal to [] could not distinguish
the package skill being correctly excluded from skill resolution being
broken entirely. A decoy skill in the stubbed HOME's .agents/skills
proves scanning still works while the package skill stays excluded.

* fix(coding-agent): simplify home isolation test
* fix: rpc bash no longer bypass user_bash

* fix: rpc bash no longer bypass user_bash
actions-user and others added 26 commits July 30, 2026 19:32
…-v0.83.0-30571177813

# Conflicts:
#	.pi/extensions/prompt-url-widget.ts
#	package-lock.json
#	packages/agent/CHANGELOG.md
#	packages/agent/package.json
#	packages/ai/CHANGELOG.md
#	packages/ai/package.json
#	packages/ai/src/api/anthropic-messages.ts
#	packages/ai/src/api/openai-completions.ts
#	packages/ai/src/api/openai-responses.ts
#	packages/ai/src/types.ts
#	packages/coding-agent/CHANGELOG.md
#	packages/coding-agent/README.md
#	packages/coding-agent/docs/session-format.md
#	packages/coding-agent/examples/extensions/custom-provider-anthropic/package-lock.json
#	packages/coding-agent/examples/extensions/custom-provider-anthropic/package.json
#	packages/coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json
#	packages/coding-agent/examples/extensions/gondolin/package-lock.json
#	packages/coding-agent/examples/extensions/gondolin/package.json
#	packages/coding-agent/examples/extensions/sandbox/package-lock.json
#	packages/coding-agent/examples/extensions/sandbox/package.json
#	packages/coding-agent/examples/extensions/with-deps/package-lock.json
#	packages/coding-agent/examples/extensions/with-deps/package.json
#	packages/coding-agent/install-lock/package-lock.json
#	packages/coding-agent/install-lock/package.json
#	packages/coding-agent/npm-shrinkwrap.json
#	packages/coding-agent/package.json
#	packages/coding-agent/src/cli/args.ts
#	packages/coding-agent/src/cli/config-selector.ts
#	packages/coding-agent/src/cli/startup-ui.ts
#	packages/coding-agent/src/core/agent-session-runtime.ts
#	packages/coding-agent/src/core/agent-session.ts
#	packages/coding-agent/src/core/extensions/runner.ts
#	packages/coding-agent/src/core/extensions/types.ts
#	packages/coding-agent/src/core/resource-loader.ts
#	packages/coding-agent/src/main.ts
#	packages/coding-agent/src/modes/interactive/interactive-mode.ts
#	packages/coding-agent/src/modes/rpc/rpc-mode.ts
#	packages/coding-agent/test/extensions-runner.test.ts
#	packages/coding-agent/test/trigger-compact-extension.test.ts
#	packages/coding-agent/vitest.config.ts
#	packages/evals/package.json
#	packages/evals/src/pi-harness.ts
#	packages/server/CHANGELOG.md
#	packages/server/package.json
#	packages/storage/sqlite-node/CHANGELOG.md
#	packages/storage/sqlite-node/package.json
#	packages/tui/CHANGELOG.md
#	packages/tui/package.json
#	packages/tui/src/index.ts
#	packages/tui/src/terminal-image.ts
#	packages/tui/src/tui.ts
#	packages/tui/test/key-tester.ts
#	packages/tui/test/markdown.test.ts
#	packages/tui/test/terminal-image.test.ts
#	packages/tui/test/tui-render.test.ts
feat(protocol): add remote session wire protocol
Intl.Segmenter can group Indic conjuncts and spacing marks into one grapheme even when wcwidth-style terminals allocate multiple cells. Count visible consonants after marks and Unicode spacing marks separately while preserving zero-width exceptions.

This is a compatibility heuristic. Unicode Spacing_Mark indicates positive advance, not a full terminal cell; Kitty keeps many Indic continuations in the initial cell, while xterm-style terminals advance for them, so Pi overcounts some clusters in Kitty.

Overcounting causes horizontal drift, but undercounting can trigger terminal autowrap, so this change favors overcounting.

Clusters can contain repeated marks and mark-consonant continuations, so this implementation leaves their widths uncapped. Collapsing them would undercount terminals that advance for every visible continuation.

Mode 2027 does not report cluster widths, so Pi still needs local width calculations. This change does not implement OSC 66, which would be preferable where supported.

Fixes #6124

Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
…7286)

* feat(ai): preserve structured metadata for Bedrock provider errors

A failed Bedrock turn only exposed `errorMessage`, so downstream runtimes
could not classify a provider failure or correlate it with AWS support
without parsing that string. The AWS SDK carries the HTTP status, the
modeled error code, and the request id on the thrown exception; the
provider dropped all three.

Attach them as a `bedrock_response_failure` diagnostic on the existing
`AssistantMessage.diagnostics` array. No new core type surface, and no
existing line changed: the diff is purely additive.

`errorMessage` stays byte-identical because `isRetryableAssistantError`
classifies retries by string-matching it, and `BEDROCK_ERROR_PREFIXES` is
documented as load-bearing for that.

Scope note: the serialized-stream noise in the original report
(`Validation error: 400: {"_events":...}`) was already fixed in v0.82.1 by
 #7081, which added the unread-stream guard in `normalizeProviderError`.
Verified against main: `errorMessage` is clean today. This change covers
only the remaining half of the issue, the missing structured metadata.

Details:
- Carries `details` only, no `error` block, as `pi_messages_rewrite` does.
  A modeled mid-stream exception is not an `Error` at all, so routing it
  through `extractDiagnosticError` would record `"[object Object]"` plus a
  stack trace pointing into the SDK. The readable text is in `errorMessage`.
- `errorCode` reads `error.name`, which is where the SDK puts the modeled
  code for both paths that expose one: service exceptions from
  `client.send()` (via `x-amzn-errortype`) and the plain `Error` the
  event-stream unmarshaller throws for an unmodeled stream error (via
  `:error-code`). All 13 modeled Bedrock errors end in `Exception`, so that
  suffix is the gate; it excludes transport failures such as `TimeoutError`
  and `CredentialsProviderError`, and the SDK's `Unknown` placeholder,
  without enumerating them.
- A modeled mid-stream exception reports only a request id, on purpose.
  `@smithy/core` `getMessageUnmarshaller` throws `deserializedException[code]`
  after reading the code into a local, and the JSON shape deserializer built
  that value as a bare object literal, so the code no longer exists by the
  time it reaches us. The request id from the initial response is used as a
  fallback so these failures stay correlatable.
- `details.status` matches the key `pi_messages_response_failure` uses.
- Header-derived values are dropped when over-long rather than truncated: a
  truncated request id is not a request id.
- Aborted turns emit no diagnostic.

closes #7224

* docs(ai): trim comment density in the Bedrock failure diagnostic

The added block sat at 52 percent comment against 14 percent for the rest
of bedrock-converse-stream.ts and 2-9 percent across the other providers.
Cut to the facts a future maintainer cannot infer from the code: why the
error code is not gated on `BedrockRuntimeServiceException`, why a modeled
mid-stream exception yields only a request id, and the `errorMessage`
byte-identity invariant. Now 29 percent of a 27-line block.

Test comments trimmed the same way, 15 percent to 4 percent, matching
bedrock-custom-headers.test.ts. No behavior change; all tests unchanged
and passing.

---------

Co-authored-by: Brian Stanley <brian.stanley@kavak.com>
* feat(tui): export bundled Marked parser

* feat(coding-agent): add width-aware Markdown transformers

---------

Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
…1177813' into automation/upstream-v0.83.0-30594691517
…-v0.83.0-30594691517

# Conflicts:
#	package-lock.json
#	package.json
#	packages/ai/src/api/openai-completions.ts
#	packages/coding-agent/CHANGELOG.md
#	packages/coding-agent/src/core/package-manager.ts
#	packages/coding-agent/src/index.ts
#	packages/coding-agent/src/modes/interactive/components/assistant-message.ts
#	packages/coding-agent/src/modes/interactive/interactive-mode.ts
#	packages/tui/CHANGELOG.md
#	packages/tui/src/components/markdown.ts
#	scripts/local-release.mjs
#	scripts/publish.mjs
#	tsconfig.json
@code-yeongyu

Copy link
Copy Markdown
Owner Author

QA evidence

Evidence files captured before this PR was opened:

  • git-status-after-check.txt
  • git-status-before-qa.txt
  • last-merge-report.md
  • npm-build.txt
  • npm-check.txt
  • npm-test.txt
  • secret-files.txt
  • senpi-qa-cli-smoke.txt
  • senpi-qa-common.txt
  • senpi-qa-mock-loop.txt
  • senpi-qa-tui.txt
  • tool-versions.txt

@code-yeongyu

Copy link
Copy Markdown
Owner Author

Closing duplicate automated upstream sync PR.

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.