Improve Kiro provider catalog, credits, streaming, endpoints, and TUI integration#96
Improve Kiro provider catalog, credits, streaming, endpoints, and TUI integration#96garysassano wants to merge 7 commits into
Conversation
|
Looks like this PR is still actively changing — I noticed another commit landed after review started. To avoid reviewing/merging a moving target, can you mark this PR as Draft while you’re still iterating? Once the implementation is stable, please switch it back to Ready for review or comment here, and I’ll do the final merge-readiness review then. |
dcd8249 to
0bfd515
Compare
0bfd515 to
6cf82d3
Compare
853acbd to
725f3bb
Compare
tickernelz
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Changes requested
PR scope is good, but I found one blocking streaming regression that can leak the closing </thinking> tag and answer text into reasoning output.
Critical
-
src/plugin/streaming/stream-parser.ts/src/plugin/streaming/thinking-parser.ts—findRealThinkingEndTag()only accepts</thinking>when followed by a blank line or stream end. Valid streams like<thinking>reason</thinking>Answerare not closed, so</thinking>Answeris emitted asreasoning_contentinstead of normal answercontent.I reproduced locally with:
createContentDeltaEvents('<thinking>reason</thinking>Answer', createStreamState(true))
Actual output includes:
{ "type": "thinking_delta", "thinking": "</thinking>Answer" }This is a response-shape correctness regression. The parser should close on a real, unquoted/non-code-fenced
</thinking>regardless of whether the model inserts a double newline after it; then separately strip optional leading newlines from the answer, as the PR already tries to do.
Warnings / follow-ups
src/plugin/sync/kiro-cli.ts— stale CLI sync can still overwrite a healthier/newer stored account when usage fetch succeeds. The skip guard no longer protects token fields in that case, while the laterupsertAccount()writesaccessToken,refreshToken, andexpiresAtfrom the CLI snapshot. Consider preserving newer credentials and only merging quota fields when the CLI token snapshot is older.src/tui-usage.ts— TUI sidebar picks the first healthy account globally bylast_used, not necessarily the active account for the current session. This can show the wrong quota in multi-account setups. If OpenCode exposes active provider auth/session account metadata, wire it through; otherwise document this limitation.
Verified locally
bun install --frozen-lockfilebun run checkgit diff --check origin/master...HEADnpm pack --dry-run
All declared checks pass after dependencies are installed.
|
|
The TUI right panel now supports optional display fields via Defaults stay compact/private:
Users who want to distinguish multiple stored Kiro credentials can opt in to showing the account email: {
"$schema": "https://opencode.ai/tui.json",
"plugin": [
[
"@zhafron/opencode-kiro-auth",
{
"show_account_email": true,
"show_plan": true,
"show_credits": true
}
]
]
} |
|
is it done? |
|
@tickernelz Yes, I've been using it for a few days without issues. |
tickernelz
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: Changes requested
Thanks for the follow-up. The previous immediate </thinking>Answer regression is fixed and the declared checks pass, but I found a few remaining correctness/data-loss issues that should be fixed before merge.
Blocking
-
src/plugin/streaming/stream-parser.ts:142-156/src/plugin/streaming/thinking-parser.ts:63-119— quoted/code-fenced tag handling is still not robust.findRealTag()only checks whether the tag is immediately adjacent to a quote/backtick and recomputes code-fence state from the current buffer. That means tags inside a quoted span like"... </thinking> ..."still close reasoning, and split code fences can make the whole thinking block flush as answer text.Reproduced locally:
// Expected: reasoning includes the quoted literal tag, content is "Done" ['<thinking>quote "keep </thinking> inside" still thinking</thinking>Done'] // Actual: reasoning = 'quote "keep ', content = ' inside" still thinking</thinking>Done' // Expected: reasoning includes the fenced literal tag, content is "Done" ['<thinking>```text\ninside code ', '</thinking>\n```\nstill thinking</thinking>Done'] // Actual: content = '<thinking>```text\ninside code </thinking>\n```\nstill thinking</thinking>Done'
The parser needs persistent lexical state (inside quote / inside fenced block), or another approach that does not discard that context when
streamState.bufferis drained. -
src/plugin/sync/kiro-cli.ts:76-109,182-201+src/plugin/storage/locked-operations.ts:68-87— a failed CLI usage fetch can still overwrite good quota data with0/0.syncFromKiroCli()initializesusedCount/limitCountto zero and still upserts withlastSync: Date.now()whenfetchUsageLimits()fails.mergeAccounts()treats that newerlastSyncas a newer quota snapshot, so previously precise remote usage gets replaced by zeros.Minimal repro against
mergeAccounts():existing: { "usedCount": 120.5, "limitCount": 2000, "lastSync": 1000 } incoming after failed usage fetch: { "usedCount": 0, "limitCount": 0, "lastSync": 2000 } result: { "usedCount": 0, "limitCount": 0 }
Token freshness and quota freshness need to be tracked separately, or failed usage fetches should preserve existing quota fields / not advance the quota sync timestamp.
-
src/plugin/sync/kiro-cli.ts:47,218-225— read-side now accepts bothodicandoidc, but write-back only targetskirocli:odic:token. If a user's CLI DB useskirocli:oidc:token, refreshed tokens are never written back, then later sync can re-import the stale token snapshot. I reproduced with a temp SQLiteauth_kvrow namedkirocli:oidc:token;writeToKiroCli()left the old access/refresh tokens unchanged. -
src/plugin/opencode-auth.ts:18-30,48-57— malformed OpenCodeauth.jsonis silently overwritten with only the Kiro placeholder.readAuthFile()logs that it is skipping placeholder setup on parse failure, but returns{};ensureOpenCodeAuthPlaceholder()then writes that empty object plus the placeholder. This can drop other provider credentials ifauth.jsonis temporarily truncated/corrupt. On parse failure, this should be a hard no-write path. -
src/index.ts:3-6/tsconfig.build.json:4-6/index.ts:1-10— the package root public API regresses after build. The repo-rootindex.tsstill exportsauthorizeKiroIDC,createKiroPlugin, andKiroAuthDetails, but the build now only compilessrc/**/*, so the publisheddist/index.jscomes fromsrc/index.tsand exports only:["KIRO_LEGACY_PROVIDER_ID","KIRO_PROVIDER_ID","KiroOAuthPlugin","default"]
Existing consumers importing
authorizeKiroIDC/createKiroPluginfrom the package root will break. Either keep the old root exports insrc/index.tsor intentionally remove/update the stale repo-root entrypoint and docs/tests.
Warning / follow-up
src/constants.ts:244-249/README.md:55-58— olderclaude-sonnet-4-5-1mandclaude-sonnet-4-5-1m-thinkingaliases were previously accepted but now throwUnsupported model, while the README still claims older*-1maliases are converted where possible. Either preserve those aliases (probably toclaude-sonnet-4.5) or narrow the compatibility claim.
Verified locally
bun run check— 45 tests pass, typecheck pass, build passbunx prettier --check 'src/**/*.{ts,tsx}' 'scripts/**/*.ts' 'README.md' 'package.json'— passgit diff --check origin/master...HEAD— passnpm pack --dry-run— pass- Additional custom repros for streaming parser, quota merge,
oidcwrite-back, malformedauth.json, and built package exports as noted above
Preview
Highlights
Fixed thinking stream ordering
This PR fixes the thinking stream transform so Kiro reasoning is emitted before the final answer text. The previous parser could leak pre-thinking fragments or emit content in the wrong order when
<thinking>tags arrived split across streaming chunks.The new shared parser handles:
<thinking>/</thinking>tags across chunksUpdated Kiro model catalog
The default Kiro model catalog has been refreshed against the official Kiro CLI model list: https://kiro.dev/docs/cli/models/
This includes newer Claude and open-weight models such as Opus 4.7, Opus 4.6, Sonnet 4.6, DeepSeek 3.2, MiniMax M2.5, GLM-5, MiniMax M2.1, and Qwen3 Coder Next.
The provider injects the model catalog automatically, so users no longer need to copy model definitions into their OpenCode config. Legacy/dotted/hyphenated/
*-thinking/older*-1maliases are still converted where possible for compatibility with existing configs, but they are not advertised as default models.Added an OpenCode TUI plugin sidebar panel
OpenCode documents plugins here: https://opencode.ai/docs/plugins/ and its terminal UI as the TUI here: https://opencode.ai/docs/tui/.
This package now exposes a separate TUI plugin entrypoint at
./tui. When installed/configured intui.jsonc, it adds a compact Kiro section to the session sidebar showing only:KiroPlan: <plan>Credits: <used> / <limit>The panel mirrors the useful account/credits information from the official Kiro IDE/CLI flow while keeping the OpenCode UI quiet. It is hidden for non-Kiro sessions and reads
kiro.dbin readonly mode without loading access tokens, refresh tokens, client secrets, or OIDC credentials.Matched Kiro CLI credit precision
Usage tracking now matches the official
kiro-cli /usagebehavior more closely:currentUsageWithPrecision/usageLimitWithPrecisionREALso fractional credits are preservedKIRO PRO+Uses Kiro's new runtime and management endpoints
Kiro's firewall docs list the new service endpoints under
runtime.<region>.kiro.devandmanagement.<region>.kiro.dev, while documentingq.<region>.amazonaws.comas legacy but still required until deprecation completes: https://kiro.dev/docs/cli/privacy-and-security/firewalls/Other Changes
Auth and provider integration
kiroas the primary provider ID while retaining a bridge for olderkiro-authconfig.Runtime and reasoning support
low,medium, andhigheffort values without advertising fake model variants.Packaging and README
dist/tui.js.Verification
bun run format --checkbun run checkgit diff --checkruntime.us-east-1.kiro.devgeneration returnedendpoint-okmanagement.us-east-1.kiro.dev/getUsageLimitsreturned quota/plan dataq.us-east-1.amazonaws.comgeneration and usage still workTest coverage added/updated for: