Skip to content

refactor(oauth): make the login platform layer provider-neutral - #34

Merged
elkaix merged 8 commits into
mainfrom
chore/kimi-oauth-removal
Aug 7, 2026
Merged

refactor(oauth): make the login platform layer provider-neutral#34
elkaix merged 8 commits into
mainfrom
chore/kimi-oauth-removal

Conversation

@elkaix

@elkaix elkaix commented Aug 7, 2026

Copy link
Copy Markdown
Member

Related Issue

No issue — this is a cleanup of an internal abstraction that had grown a
provider-specific home. The problem is described below.

Problem

Model listing, capability derivation and the on-disk config shape lived in a
provider-specific module, and every other login path imported them from there:
the API-key open platforms, the OpenAI Codex OAuth flow, and the custom
api.json registry all reached into managed-kimi-code.ts for
ManagedKimiCodeModelInfo and ManagedKimiConfigShape. Two copies of
capabilitiesForModel existed side by side, byte-identical, and two variants of
the /models parser differed only in how they handled a missing
context_length.

Sitting on top of that was a managed-subscription provider that nothing else
used. Its device-code OAuth flow, token storage, usage and feedback endpoints,
agent-core OAuth service, REST routes, SDK auth facade and model provider were
all reachable only through that one provider.

What changed

The platform layer is provider-neutral. PlatformModelInfo,
PlatformConfigShape, PlatformProviderConfig, PlatformModelAlias and
SupportsThinkingType now live in open-platform.ts — moved rather than
copied, so the file count goes down. The duplicate capabilitiesForModel and
toModelInfo collapse into one each; the survivor parses
supported_reasoning_efforts, so no field is lost.

The managed-subscription provider is gone, and with it the device-code OAuth
stack, managed-usage.ts, managed-feedback.ts, services/oauth/*,
services/auth/managedAuth.ts, the /oauth REST routes, PythinkerAuthFacade
and PythinkerForCodingProvider. Nothing configured any of it once model
listing stopped depending on it.

providerConfig.oauth is removed — its schema, TOML round-trip, the
ProviderManager auth resolver it fed, and the mutual-exclusion rule that only
existed to keep it apart from static keys. Nothing writes an oauth ref now:
OpenAI Codex stores its access token as the provider apiKey with the refresh
token under source, and every other path is a plain key.

Logging in is an API key, a models.dev catalog provider, or OpenAI Codex
OAuth. "Is the user logged in" is one predicate —
PythinkerHarness.isAuthenticated(), over configured providers with a usable
credential — shared by the CLI, the VS Code extension and the ACP adapter.
/feedback opens the issue tracker.

Surfaces that had options with no flow behind them are cleaned up: the
platform picker no longer offers an entry whose handler was deleted, the VS Code
welcome screen no longer renders a device-code URL panel that can never fill,
and the web client drops the device-code dialog and its /oauth calls —
logging in there opens the provider manager, which is where API-key and catalog
providers are added.

VS Code sign-out is now non-destructive. It removes only providers a login
created (those carrying a source) and writes once through replaceConfig, so
hand-written config.toml entries survive and a failure cannot leave a
half-signed-out config behind.

Verification

Gate Result
pnpm run typecheck 0
pnpm run lint 0
pnpm --filter ./apps/vscode run typecheck 0
pnpm vitest run (all projects) 9739 passed, 0 failed

Two regressions added, both mutation-verified (they fail when the code under
test is broken):

  • the OpenAI Codex scope: 'oauth' refresh path, which the deleted
    managed-scope tests used to cover;
  • Codex-only readiness — the readiness probe now has a single api-key branch,
    and Codex satisfies it only because it stores its access token as apiKey.
    Nothing said so, so a future change to that storage would have sent every
    Codex user to AuthTokenMissingError on their first turn.

Note for reviewers

packages/migration-legacy deliberately keeps its managed:kimi-code fixtures:
it reads legacy configs that really did carry that provider.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

elkaix added 7 commits August 7, 2026 01:24
Model listing, capability derivation and the on-disk config shape lived in a
provider-specific module while every other login path imported them from there.
Move them into open-platform.ts as PlatformModelInfo / PlatformConfigShape and
collapse the two duplicate copies of capabilitiesForModel and toModelInfo into
one; the survivor parses supported_reasoning_efforts so no field is lost.

Drop the managed-subscription provider along with it: the device-code OAuth
flow, its token storage and manager, the managed usage and feedback endpoints,
the agent-core OAuth service and REST routes, the SDK auth facade, and the
managed model provider. Nothing configured them any more once model listing
became provider-neutral.

Logging in is now: API key, models.dev catalog provider, or OpenAI Codex OAuth.
'Is the user logged in' becomes PythinkerHarness.isAuthenticated(), one
predicate over configured providers with a usable credential, shared by the VS
Code extension and the ACP adapter. /feedback opens the issue tracker.
…onfig

Nothing writes an oauth ref now that logins end in an api key: OpenAI Codex
stores its access token as the provider apiKey with the refresh token under
`source`, and every other path is a plain key. Remove the field, the schema,
its TOML round-trip, the ProviderManager auth resolver it fed, and the
mutual-exclusion rule that only existed to keep it apart from static keys.

The web client loses the device-code login dialog and the /oauth REST calls
behind it; logging in there opens the provider manager, which adds API-key and
catalog providers.
The platform picker still offered 'Kimi (OAuth)' and the VS Code welcome screen
still said 'Sign in with Kimi' with a device-code URL panel, but the handlers
behind both were gone — picking that option did nothing and the URL panel could
never fill in. Drop the option, the loginUrl event nothing emits any more, and
the managed-provider login gate that could no longer fire; the VS Code welcome
screen now describes what login actually does.
… cleanup

Review found the VS Code sign-out looping removeProvider over every configured
provider — that deletes hand-written config.toml entries and can stop halfway.
Only providers a login created carry a `source`, so scope the removal to those
and write it once through replaceConfig.

Also: the web settings dialog still printed a hardcoded managed provider id and
offered a sign-out whose handler was gone; the web /login command opened the
provider panel without loading it; and the SDK config smoke fixture paired a
Moonshot provider with a model it does not serve. Add the OpenAI Codex refresh
regression the deleted managed-scope tests used to cover.
…r OAuth-backed

The readiness probe used to have two branches: an api key, or a managed OAuth
token. Only the api-key branch is left, and OpenAI Codex satisfies it only
because it stores its access token as the provider apiKey. Nothing said so, so
a future change to that storage would silently send every Codex user to
AuthTokenMissingError on their first turn.
The Codex refresh case only asserted the stale default was gone, not what
replaced it; it re-points at the model it just fetched, so assert that. The VS
Code refresh-failure case never checked the refresh was attempted. The mobile
sheet's account button now names the panel it opens, matching the desktop
dialog.
…d them

The ACP adapter tests stubbed harness.auth.status; the adapter now asks
harness.isAuthenticated, so every stub returned undefined and the auth gate
surfaced as -32603 Internal error instead of -32000 auth_required. Replace the
two status payloads in the shared helper with the predicate itself. Drop the
managed_provider expectation and the managed OAuth refresh route case from the
server e2e suites, both of which cover endpoints that no longer exist.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 167 files, which is 17 over the limit of 150.

To get a review, reduce the PR to 150 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to Pro+ to raise the limit.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a4de5ca2-4371-4795-875c-bd68b34c3efa

📥 Commits

Reviewing files that changed from the base of the PR and between a0fc153 and 07cfc8b.

📒 Files selected for processing (167)
  • .changeset/provider-neutral-login-platform.md
  • apps/pythinker-code/src/auth/terminal-login-ui.ts
  • apps/pythinker-code/src/cli/run-prompt.ts
  • apps/pythinker-code/src/cli/run-shell.ts
  • apps/pythinker-code/src/cli/sub/provider.ts
  • apps/pythinker-code/src/cli/telemetry.ts
  • apps/pythinker-code/src/constant/app.ts
  • apps/pythinker-code/src/tui/commands/auth.ts
  • apps/pythinker-code/src/tui/commands/dispatch.ts
  • apps/pythinker-code/src/tui/commands/info.ts
  • apps/pythinker-code/src/tui/commands/prompts.ts
  • apps/pythinker-code/src/tui/commands/provider.ts
  • apps/pythinker-code/src/tui/components/dialogs/model-selector.ts
  • apps/pythinker-code/src/tui/components/dialogs/provider-manager.ts
  • apps/pythinker-code/src/tui/constant/pythinker-tui.ts
  • apps/pythinker-code/src/tui/controllers/auth-flow.ts
  • apps/pythinker-code/src/tui/pythinker-tui.ts
  • apps/pythinker-code/src/tui/utils/refresh-providers.ts
  • apps/pythinker-code/test/cli/acp.test.ts
  • apps/pythinker-code/test/cli/export.test.ts
  • apps/pythinker-code/test/cli/login.test.ts
  • apps/pythinker-code/test/cli/provider.test.ts
  • apps/pythinker-code/test/cli/run-prompt.test.ts
  • apps/pythinker-code/test/cli/run-shell.test.ts
  • apps/pythinker-code/test/tui/components/dialogs/model-selector.test.ts
  • apps/pythinker-code/test/tui/components/dialogs/platform-selector.test.ts
  • apps/pythinker-code/test/tui/components/dialogs/tabbed-model-selector.test.ts
  • apps/pythinker-code/test/tui/pythinker-tui-message-flow.test.ts
  • apps/pythinker-code/test/tui/pythinker-tui-startup.test.ts
  • apps/pythinker-code/test/tui/utils/refresh-providers.test.ts
  • apps/pythinker-web/src/App.vue
  • apps/pythinker-web/src/api/daemon/client.ts
  • apps/pythinker-web/src/api/daemon/wire.ts
  • apps/pythinker-web/src/api/types.ts
  • apps/pythinker-web/src/components/LoginDialog.vue
  • apps/pythinker-web/src/components/MobileSettingsSheet.vue
  • apps/pythinker-web/src/components/ProviderManager.vue
  • apps/pythinker-web/src/components/SettingsDialog.vue
  • apps/pythinker-web/src/composables/usePythinkerWebClient.ts
  • apps/pythinker-web/src/i18n/locales/en/sidebar.ts
  • apps/vscode/shared/bridge.ts
  • apps/vscode/src/auth/vscode-login-ui.ts
  • apps/vscode/src/handlers/auth.handler.ts
  • apps/vscode/src/utils/context.ts
  • apps/vscode/test/bridge-handler.test.ts
  • apps/vscode/test/settings-store.test.ts
  • apps/vscode/webview-ui/src/components/LoginScreen.tsx
  • apps/vscode/webview-ui/src/hooks/useAppInit.ts
  • apps/vscode/webview-ui/src/stores/index.ts
  • apps/vscode/webview-ui/src/stores/settings.store.ts
  • docs/configuration/config-files.md
  • docs/configuration/env-vars.md
  • docs/configuration/overrides.md
  • docs/configuration/providers.md
  • packages/acp-adapter/src/server.ts
  • packages/acp-adapter/test/_helpers/harness-stubs.ts
  • packages/acp-adapter/test/approval-cancel.test.ts
  • packages/acp-adapter/test/approval-display.test.ts
  • packages/acp-adapter/test/approval.test.ts
  • packages/acp-adapter/test/auth-gate.test.ts
  • packages/acp-adapter/test/cancel.test.ts
  • packages/acp-adapter/test/e2e-fs.test.ts
  • packages/acp-adapter/test/e2e-happy-path.test.ts
  • packages/acp-adapter/test/error-mapping.test.ts
  • packages/acp-adapter/test/kaos-activation.test.ts
  • packages/acp-adapter/test/mcp-forward.test.ts
  • packages/acp-adapter/test/plan-and-commands.test.ts
  • packages/acp-adapter/test/session-config-option-funnel.test.ts
  • packages/acp-adapter/test/session-control.test.ts
  • packages/acp-adapter/test/session-list.test.ts
  • packages/acp-adapter/test/session-load.test.ts
  • packages/acp-adapter/test/session-new.test.ts
  • packages/acp-adapter/test/session-prompt.test.ts
  • packages/acp-adapter/test/session-resume.test.ts
  • packages/acp-adapter/test/session-slash.test.ts
  • packages/acp-adapter/test/set-session-config-option.test.ts
  • packages/acp-adapter/test/tool-call-stream.test.ts
  • packages/acp-adapter/test/tool-result.test.ts
  • packages/agent-core/src/config/schema.ts
  • packages/agent-core/src/config/toml.ts
  • packages/agent-core/src/index.ts
  • packages/agent-core/src/rpc/core-impl.ts
  • packages/agent-core/src/services/auth/managedAuth.ts
  • packages/agent-core/src/services/authSummary/authSummaryService.ts
  • packages/agent-core/src/services/config/configService.ts
  • packages/agent-core/src/services/coreProcess/coreProcessService.ts
  • packages/agent-core/src/services/index.ts
  • packages/agent-core/src/services/modelCatalog/modelCatalog.ts
  • packages/agent-core/src/services/modelCatalog/modelCatalogService.ts
  • packages/agent-core/src/services/oauth/oauth.ts
  • packages/agent-core/src/services/oauth/oauthService.ts
  • packages/agent-core/src/session/provider-manager.ts
  • packages/agent-core/test/agent/compaction/full.test.ts
  • packages/agent-core/test/agent/turn.test.ts
  • packages/agent-core/test/config/configs.test.ts
  • packages/agent-core/test/harness/runtime-provider.test.ts
  • packages/agent-core/test/harness/runtime.test.ts
  • packages/agent-core/test/loop/retry.test.ts
  • packages/agent-core/test/rpc/plugins-rpc.test.ts
  • packages/agent-core/test/services/auth-summary-service.test.ts
  • packages/agent-core/test/services/coreProcessService.test.ts
  • packages/agent-core/test/services/model-catalog-service.test.ts
  • packages/agent-core/test/services/oauth-service.test.ts
  • packages/node-sdk/examples/pythinker-harness-auth-smoke.ts
  • packages/node-sdk/examples/pythinker-harness-config-smoke.ts
  • packages/node-sdk/src/auth.ts
  • packages/node-sdk/src/index.ts
  • packages/node-sdk/src/login/flows.ts
  • packages/node-sdk/src/login/model-alias.ts
  • packages/node-sdk/src/login/platform-options.ts
  • packages/node-sdk/src/login/types.ts
  • packages/node-sdk/src/mcp-server.ts
  • packages/node-sdk/src/oauth-error.ts
  • packages/node-sdk/src/pythinker-code-model-provider.ts
  • packages/node-sdk/src/pythinker-harness.ts
  • packages/node-sdk/src/sdk-rpc-client.ts
  • packages/node-sdk/src/types.ts
  • packages/node-sdk/test/auth-facade.test.ts
  • packages/node-sdk/test/create-session-transport.test.ts
  • packages/node-sdk/test/pythinker-code-model-provider.test.ts
  • packages/node-sdk/test/runtime-provider-oauth.test.ts
  • packages/node-sdk/test/session-set-model.test.ts
  • packages/oauth/examples/kimi-oauth-smoke.ts
  • packages/oauth/package.json
  • packages/oauth/src/constants.ts
  • packages/oauth/src/custom-registry.ts
  • packages/oauth/src/errors.ts
  • packages/oauth/src/identity.ts
  • packages/oauth/src/index.ts
  • packages/oauth/src/managed-feedback.ts
  • packages/oauth/src/managed-kimi-code.ts
  • packages/oauth/src/managed-usage.ts
  • packages/oauth/src/oauth-manager.ts
  • packages/oauth/src/oauth.ts
  • packages/oauth/src/open-platform.ts
  • packages/oauth/src/openai-codex-oauth.ts
  • packages/oauth/src/storage.ts
  • packages/oauth/src/token-state.ts
  • packages/oauth/src/toolkit.ts
  • packages/oauth/src/types.ts
  • packages/oauth/test/custom-registry.test.ts
  • packages/oauth/test/managed-feedback.test.ts
  • packages/oauth/test/managed-kimi-code.test.ts
  • packages/oauth/test/managed-usage.test.ts
  • packages/oauth/test/oauth-manager-lock-failure.test.ts
  • packages/oauth/test/oauth-manager-multi-process.test.ts
  • packages/oauth/test/oauth-manager.test.ts
  • packages/oauth/test/oauth.test.ts
  • packages/oauth/test/open-platform.test.ts
  • packages/oauth/test/openai-codex-oauth.test.ts
  • packages/oauth/test/refresh-threshold.test.ts
  • packages/oauth/test/storage.test.ts
  • packages/oauth/test/toolkit.test.ts
  • packages/protocol/src/__tests__/rest-auth.test.ts
  • packages/protocol/src/index.ts
  • packages/protocol/src/rest/auth.ts
  • packages/protocol/src/rest/modelCatalog.ts
  • packages/protocol/src/rest/oauth.ts
  • packages/server-e2e/test/client.test.ts
  • packages/server-e2e/test/refresh-replay.test.ts
  • packages/server/src/routes/modelCatalog.ts
  • packages/server/src/routes/oauth.ts
  • packages/server/src/routes/registerApiV1Routes.ts
  • packages/server/src/start.ts
  • packages/server/test/auth.e2e.test.ts
  • packages/server/test/model-catalog.e2e.test.ts
  • packages/server/test/oauth.e2e.test.ts

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Aug 7, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@pythoughts/pythinker-code@07cfc8b
npx https://pkg.pr.new/@pythoughts/pythinker-code@07cfc8b

commit: 07cfc8b

Comment thread packages/acp-adapter/test/auth-gate.test.ts Fixed
Comment thread packages/acp-adapter/test/session-load.test.ts Fixed
Comment thread packages/acp-adapter/test/session-resume.test.ts Fixed
…ed them

auth-gate, session-load and session-resume imported AUTHED/UNAUTHED but
still hand-rolled `isAuthenticated`, leaving the imports dead. auth-gate
was already half-converted (the inline harness uses UNAUTHED), so this
finishes what 1456fb2 started and matches the 18 sibling test files.
@elkaix

elkaix commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

CodeRabbit skipped this PR on size (167 files > 150), so the review ran through the local CodeRabbit CLI instead:

coderabbit review --committed --base main --agent

Basis chore/kimi-oauth-removal vs main, all 167 files reviewed, 0 findings.

The three github-code-quality findings (dead AUTHED/UNAUTHED imports in auth-gate, session-load and session-resume) are fixed in 07cfc8b and their threads are resolved.

@elkaix
elkaix merged commit 42da384 into main Aug 7, 2026
11 checks passed
@elkaix
elkaix deleted the chore/kimi-oauth-removal branch August 7, 2026 09:44
elkaix added a commit that referenced this pull request Aug 7, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and the packages will
be published to npm automatically. If you're not ready to do a release
yet, that's fine, whenever you add more changesets to main, this PR will
be updated.


# Releases
## @pythoughts/pythinker-code@0.11.0

### Minor Changes

- [#32](#32)
[`a504a82`](a504a82)
- Rename the ACP authentication method to reflect that login is
multi-provider: it now reads "Log in with a provider" and explains that
the provider is chosen in a terminal. Clients matching the previous
wording will need updating.

- [#32](#32)
[`a504a82`](a504a82)
- Let a Dynamic Workflow require structured output from its subagents.
Passing `output_schema` makes each subagent return a validated object
instead of free text, and a subagent that cannot satisfy the schema is
reported separately from one that failed outright.

- [#32](#32)
[`a504a82`](a504a82)
- `pythinker login` now opens a provider picker instead of going
straight to one provider, and accepts `--provider <id|name>` to skip it.
The VS Code extension's sign-in offers the same providers, and both
surfaces present the same thinking-effort levels for a given model.

- [#34](#34)
[`42da384`](42da384)
- Make the login platform layer provider-neutral. Model listing,
capability derivation and the on-disk config shape are now one set of
types shared by every login path, instead of living in a
provider-specific module that other providers imported from; the
duplicate copies of the capability derivation and the model-info parser
are collapsed into one.

Logging in is an API key, a models.dev catalog provider, or OpenAI Codex
OAuth. "Is the user logged in" is now a single predicate over configured
providers with a usable credential, shared by the CLI, the VS Code
extension and the ACP adapter. `/feedback` opens the issue tracker.

- [#32](#32)
[`a504a82`](a504a82)
- Give every Dynamic Workflow run an id and stamp it on the subagent
events it produces, so a client can tell which run a given subagent
belongs to when several are in flight.

- [#32](#32)
[`a504a82`](a504a82)
- Add two ways to rein in Dynamic Workflow fan-out: `disableWorkflows`
turns the tool off entirely, and `workflowSizeGuideline` sets an
advisory ceiling that is mentioned to the model and warned about, on
every surface, when a run exceeds it. Both are settable in config or by
environment variable.

- [#32](#32)
[`a504a82`](a504a82)
- Bound subagent fan-out with hard caps: 128 subagents per call, 200 per
session, and a nesting depth of 3. Nesting was previously unbounded, so
a workflow that spawned workflows could grow without limit; past depth 3
the call now fails instead.

- [#32](#32)
[`a504a82`](a504a82)
- Replace the Dynamic Workflow progress bar with the two things it can
actually know: how many tool calls each agent has made, and how long it
has been silent. The old bar pinned every tool-using agent at 75% until
it finished, so an agent working hard and one wedged for ten minutes
looked identical. A row that goes quiet now turns amber, then red.

### Patch Changes

- [#32](#32)
[`a504a82`](a504a82)
- Survive two malformed inputs that used to end a run. A catalog entry
that is not an object is now dropped when the catalog is read, instead
of reaching the provider picker and throwing past the bundled-catalog
fallback that was meant to save the login. A non-finite subagent
concurrency limit now falls back to the default: `NaN` passed every
clamp, and each free-slot test against it was false, so the batch
launched nothing and never finished.

- [#32](#32)
[`a504a82`](a504a82)
- Offer a model's declared thinking-effort levels when signing in to
OpenAI Codex. The picker previously fell back to low / medium / high
regardless of what the model supports, disagreeing with the effort list
recorded in the config it then wrote.

- [#32](#32)
[`a504a82`](a504a82)
- Accept a provider's plain id for `--provider` at login, so a catalog
provider no longer has to be named by its full display name, and stop a
cancelled OpenAI Codex sign-in from holding the process open for the
rest of its two-minute callback timeout. In the editor extension,
signing in now shows one cancellable progress notification, a repeated
sign-in joins the one already running instead of opening a second set of
prompts, and a completed sign-in is no longer reported as failed when
the status refresh behind it fails.

- [#32](#32)
[`a504a82`](a504a82)
- Save the thinking-effort level picked during login. Only an on/off
flag was stored, so choosing low, medium, or xhigh reopened the session
at high, and an OpenAI Codex login reopened at the model's maximum
effort regardless of the choice.

- [#32](#32)
[`a504a82`](a504a82)
- Write the thinking effort picked at login to disk. The apply step
recorded the level, but the patch that saved the result listed
everything except it, so an API-key login still reopened at the default
effort. Choosing `off` now also clears a level a previous login left
behind, which a patch that only merges could not do by omitting the key.

- [#32](#32)
[`a504a82`](a504a82)
- Keep the configured provider signed in when a login is abandoned.
Backing out at the model picker, or a failure while fetching the model
list, no longer clears the existing credentials, and dismissing the
provider picker returns to the sign-in screen instead of reporting a
failed login.

- [#32](#32)
[`a504a82`](a504a82)
- Refuse a device authorization whose verification URL is not HTTPS.
Every surface hands that URL to the host's "open externally" API, so a
provider answering with `file:`, `javascript:`, or an installed
application's own scheme had the agent launch it. The check runs where
the response is parsed, so the terminal, the TUI, and the editor
extension are all covered.

- [#32](#32)
[`a504a82`](a504a82)
- Finish handling blank Dynamic Workflow items. A run that dropped one
reported its results after a note explaining the drop, which made the
whole result parse as unsupported and rendered a successful run as
failed; the note now follows the results. A blank entry also no longer
leaves a row queued forever with the header stuck below its total, and
no longer pushes a full item list over the subagent cap and back into
whole-call rejection.

- [#32](#32)
[`a504a82`](a504a82)
- Ignore empty entries in a Dynamic Workflow's item list instead of
rejecting the call. A trailing empty item used to fail argument
validation, which discarded the whole workflow before any subagent
started and forced the agent to send every prompt again. The dropped
count is now reported with the results, and the launch panel counts only
the subagents that will actually run.

- [#32](#32)
[`a504a82`](a504a82)
- Stop a Dynamic Workflow row that has not started from reading as
stalled. A queued row measured its silence from the launch of the whole
run, so a long queue turned every waiting row amber and then red while
nothing was wrong. A queued row now shows the same placeholder a
finished one does, and a suspended row keeps its count without the alarm
colours, because only a running row can stall.

- [#32](#32)
[`a504a82`](a504a82)
- Keep a Dynamic Workflow subagent's output schema when a provider rate
limit forces its turn to be retried. The retried turn lost the schema,
so the subagent answered in prose and the workflow reported it as
completed rather than as a schema failure.

- [#32](#32)
[`a504a82`](a504a82)
- Show a Dynamic Workflow's running rows with a spinning grey dot, so a
working agent reads as motion rather than as a static dot the eye cannot
tell from a finished one, and shimmer the Orchestrating label in
periwinkle instead of grey.

- [#32](#32)
[`a504a82`](a504a82)
- Show the whole large-workflow warning in the editor extension. The
line was truncated to the panel width, so in a narrow side panel the
reader saw the opening words and no reason.
## @pythoughts/pythinker-code-sdk@0.12.0

### Minor Changes

- [#34](#34)
[`42da384`](42da384)
- Make the login platform layer provider-neutral. Model listing,
capability derivation and the on-disk config shape are now one set of
types shared by every login path, instead of living in a
provider-specific module that other providers imported from; the
duplicate copies of the capability derivation and the model-info parser
are collapsed into one.

Logging in is an API key, a models.dev catalog provider, or OpenAI Codex
OAuth. "Is the user logged in" is now a single predicate over configured
providers with a usable credential, shared by the CLI, the VS Code
extension and the ACP adapter. `/feedback` opens the issue tracker.
## pythinker-code@0.8.5

### Patch Changes

- Updated dependencies
[[`42da384`](42da384)]:
  - @pythoughts/pythinker-code-sdk@0.12.0

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: M Elkholy <melkholy@techmatrix.com>
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