Skip to content

fix(kiro): restore hardening and complete text turns#304

Closed
mushikingh wants to merge 14 commits into
lidge-jun:devfrom
mushikingh:fix/kiro-hardening-follow-up
Closed

fix(kiro): restore hardening and complete text turns#304
mushikingh wants to merge 14 commits into
lidge-jun:devfrom
mushikingh:fix/kiro-hardening-follow-up

Conversation

@mushikingh

@mushikingh mushikingh commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • restore the Kiro completion and transport hardening from feat(kiro): harden completion and transport integration #302, whose merge commit is no longer reachable from dev
  • preserve the reviewed provider-aware terminal-state, retry, OAuth, continuation, and cross-endpoint behavior
  • fix Codex turns hanging after Kiro already returned a complete plain-text answer by accepting clean text EOF without a second upstream generation
  • isolate the full test runner from user Codex/opencodex state

Runtime verification

Real codex exec -m kiro/gpt-5.6-sol prompts completed successfully through the local proxy, including the previously hanging Central Europe date prompt. The corrected path made one Kiro request instead of an unnecessary completion replay.

Validation

  • bun run typecheck
  • bun run privacy:scan
  • bun run test — 3,571 passed, 0 failed

Review note

This touches Kiro OAuth, credential refresh, and transport behavior, so it requires explicit security review under MAINTAINERS.md. @Ingwannu, please review the security-sensitive paths.

Summary by CodeRabbit

  • New Features

    • Improved Kiro model support with reliable completion handling, conversation continuation, tool-name protection, and reasoning-effort controls.
    • Added Kiro CLI credential import options for selecting credential databases and tokens.
    • Preserved response phases and provider continuation state across requests and restarts.
    • Commentary can now stream during web-search iterations without waiting for completion.
  • Bug Fixes

    • Improved handling of Kiro connection failures, authentication refreshes, incomplete responses, and structured error reporting.
    • Added safeguards against oversized event headers and invalid tool or credential data.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR substantially revises Kiro event parsing, completion fallback, retry and OAuth behavior, provider continuation persistence, response terminal semantics, web-search streaming, credential import, and isolated test execution. It also adds extensive adapter, bridge, OAuth, persistence, and end-to-end coverage.

Changes

Kiro adapter and protocol flow

Layer / File(s) Summary
Event, error, and continuation contracts
src/types.ts, src/adapters/kiro-events.ts, src/adapters/kiro-errors.ts, src/responses/state.ts
Adds structured Kiro events/errors, provider continuation state, phase preservation, v2 snapshot migration, and bounded eventstream header validation.
Completion, tools, reasoning, and transport
src/adapters/kiro.ts, src/adapters/kiro-tools.ts, src/adapters/kiro-wire.ts, src/adapters/kiro-retry.ts, src/adapters/kiro-constants.ts
Adds reserved completion handling, bounded fallback continuation, tool-name collision protection, model-specific reasoning/tool behavior, and narrowed reset/fallback retry policies.
Response and sidecar integration
src/bridge.ts, src/server/responses.ts, src/web-search/*, src/claude/outbound.ts
Propagates phases, end-turn state, usage, provider state, structured failures, incomplete events, and live commentary through streaming and batch paths.
OAuth import and replay
src/oauth/kiro-credentials.ts, src/oauth/index.ts, tests/kiro-oauth.test.ts, tests/server-kiro-oauth-401-replay.test.ts
Supports explicit Kiro SQLite database/token selection and bounded OAuth refresh/replay behavior.
Test execution and supporting fixes
scripts/test.ts, package.json, src/cli/index.ts, src/server/ports.ts, src/codex/catalog.ts, src/codex/home.ts, tests/*
Introduces isolated test execution and updates supporting port, catalog, WSL, connectivity, and configuration coverage.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ServerResponses
  participant KiroAdapter
  participant KiroUpstream
  participant ResponseBridge
  Client->>ServerResponses: POST /v1/responses
  ServerResponses->>KiroAdapter: build and send request
  KiroAdapter->>KiroUpstream: stream Kiro event frames
  KiroUpstream-->>KiroAdapter: content, reasoning, tool, metadata, terminal events
  KiroAdapter->>KiroUpstream: bounded completion fallback when required
  KiroAdapter->>ResponseBridge: adapter events and provider state
  ResponseBridge-->>Client: SSE or JSON response
Loading

Possibly related PRs

  • lidge-jun/opencodex#302: Covers closely related Kiro completion, transport, credential import, bridge, and response semantics.

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.40% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the PR’s main scope: Kiro hardening plus completing plain-text turns without extra replay.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Checkov (3.3.8)
package.json

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install timed out. The project may have too many dependencies for the sandbox.


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

@coderabbitai coderabbitai 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.

Actionable comments posted: 9

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/guides/providers.md`:
- Around line 98-110: Synchronize the new “Kiro credential import” section from
the English providers guide into the Japanese, Korean, Russian, and Simplified
Chinese locale guides. Translate the heading and content while preserving the
environment variable names, privacy guidance, and read-only/database behavior;
alternatively mark each locale page as intentionally pending translation to
prevent drift.

In `@docs-site/src/content/docs/reference/adapters.md`:
- Around line 87-118: Synchronize the Kiro sections in the Japanese, Korean,
Russian, and Simplified Chinese adapter documentation with the current English
semantics: custom baseUrl handling and bounded canonical-endpoint fallback,
replay/refresh ownership, private completion-tool and continuation behavior,
web-search buffering, and model-specific reasoning-effort support. Preserve each
locale’s existing formatting and terminology while replacing the outdated
descriptions.

In `@scripts/test.ts`:
- Line 12: Sanitize the environment used by the test runner instead of
inheriting credential and provider-state variables through baseEnv. Update the
baseEnv setup and child-process environment construction in scripts/test.ts to
allow only safe variables or explicitly remove OPENCODEX_API_AUTH_TOKEN, OAuth
credentials, and Kiro provider database-selection variables such as
KIROCLI_DB_PATH, while preserving required test configuration. Add coverage in
tests/test-runner.test.ts verifying these variables cannot escape the temporary
test environment.

In `@src/adapters/kiro-errors.ts`:
- Around line 112-118: Update the quota classification branch in the
authoritative classifier to exclude rate-limit evidence, matching the rate-quota
disambiguation used by classifyKiroText. Ensure messages such as “requests per
minute quota exceeded” continue to the 429/rate-limit branch, while genuine
exhausted quota errors still return non-retryable insufficient_quota.

In `@src/adapters/kiro-events.ts`:
- Around line 136-150: Compute the result of parseTokenUsage once in the
metadataEvent case, store it in a local variable, and reuse that value for both
the undefined check and usage property. Apply the same compute-once pattern to
optionalString and optionalBoolean in the assistantResponseEvent,
reasoningContentEvent, and toolUseEvent cases, preserving the existing
conditional spread behavior.

In `@src/oauth/kiro-credentials.ts`:
- Around line 265-266: Replace the message-substring check in the catch block
with a dedicated error type or stable error identifier used by the fatal
selection errors thrown at the earlier validation points. Update those throw
sites and the catch guard together so fatal selection errors are always rethrown
even if their messages change, while other errors retain the existing
schema-mismatch handling.
- Around line 228-247: Update the sqliteEntries() scan around selectTokenRow(db)
so the "ambiguous" and "selected_missing" cases record their diagnostics and
failure details, then continue to the next candidate instead of throwing
immediately. Preserve the existing successful-token flow and, after all
candidates are exhausted without a usable credential, propagate an appropriate
final error consistent with the surrounding scan behavior.

In `@tests/claude-messages-endpoint.test.ts`:
- Around line 266-268: In the temporary server setup for the refusal-path test,
await the promise returned by closed.stop(true) before issuing the downstream
request. Keep closedOrigin captured before shutdown and preserve the existing
request assertions.

In `@tests/kiro-oauth.test.ts`:
- Around line 116-157: Add a focused regression test alongside the existing
KIROCLI SQLite tests for a configured KIROCLI_TOKEN_KEY that is absent from
auth_kv. Seed one valid token row, set KIROCLI_DB_PATH and a nonexistent
KIROCLI_TOKEN_KEY, then assert readKiroCliSqlite explicitly throws the
missing-selection error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c3f39104-f119-4f8a-aefe-d55afda14ace

📥 Commits

Reviewing files that changed from the base of the PR and between 54e0bbf and 9ca7ea3.

📒 Files selected for processing (53)
  • docs-site/src/content/docs/guides/providers.md
  • docs-site/src/content/docs/reference/adapters.md
  • package.json
  • scripts/test.ts
  • src/adapters/kiro-constants.ts
  • src/adapters/kiro-errors.ts
  • src/adapters/kiro-events.ts
  • src/adapters/kiro-retry.ts
  • src/adapters/kiro-tools.ts
  • src/adapters/kiro-wire.ts
  • src/adapters/kiro.ts
  • src/bridge.ts
  • src/claude/outbound.ts
  • src/cli/index.ts
  • src/codex/catalog.ts
  • src/codex/home.ts
  • src/lib/eventstream-decoder.ts
  • src/oauth/index.ts
  • src/oauth/kiro-credentials.ts
  • src/providers/kiro-models.ts
  • src/responses/parser.ts
  • src/responses/schema.ts
  • src/responses/state.ts
  • src/server/claude-messages.ts
  • src/server/ports.ts
  • src/server/responses.ts
  • src/types.ts
  • src/web-search/loop.ts
  • src/web-search/progress-stream.ts
  • structure/04_transports-and-sidecars.md
  • tests/bridge.test.ts
  • tests/claude-management-api.test.ts
  • tests/claude-messages-endpoint.test.ts
  • tests/claude-models-discovery.test.ts
  • tests/claude-native-passthrough.test.ts
  • tests/claude-outbound.test.ts
  • tests/cli-account.test.ts
  • tests/eventstream-decoder.test.ts
  • tests/kiro-adapter.test.ts
  • tests/kiro-oauth.test.ts
  • tests/kiro-retry.test.ts
  • tests/kiro-stream.test.ts
  • tests/ports.test.ts
  • tests/provider-connection-test.test.ts
  • tests/responses-parser.test.ts
  • tests/responses-state.test.ts
  • tests/server-auth.test.ts
  • tests/server-combo-failover-e2e.test.ts
  • tests/server-kiro-completion-e2e.test.ts
  • tests/server-kiro-oauth-401-replay.test.ts
  • tests/test-runner.test.ts
  • tests/web-search-progress-stream.test.ts
  • tests/web-search.test.ts

Comment on lines +98 to +110
### Kiro credential import

`ocx login kiro` searches the platform Kiro CLI stores and opens SQLite databases read-only. Two
environment variables make selection explicit without copying credentials into opencodex:

- `KIROCLI_DB_PATH` selects a nonstandard Kiro CLI SQLite database. The path must already exist;
opencodex does not create it or modify the database, WAL, or SHM files.
- `KIROCLI_TOKEN_KEY` selects the exact `auth_kv` token key when a database contains multiple
otherwise ambiguous token rows. A missing selection fails login instead of guessing.

Keep these variables and the selected database private. Do not attach database files or raw login
diagnostics to bug reports.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd -a 'providers.md' docs-site/src/content/docs -t f

Repository: lidge-jun/opencodex

Length of output: 502


🏁 Script executed:

#!/bin/bash
set -euo pipefail

files=(
  docs-site/src/content/docs/guides/providers.md
  docs-site/src/content/docs/ja/guides/providers.md
  docs-site/src/content/docs/ko/guides/providers.md
  docs-site/src/content/docs/ru/guides/providers.md
  docs-site/src/content/docs/zh-cn/guides/providers.md
)

for f in "${files[@]}"; do
  echo "===== $f ====="
  rg -n -C 3 'Kiro credential import|KIROCLI_DB_PATH|KIROCLI_TOKEN_KEY|Kiro' "$f" || true
  echo
done

Repository: lidge-jun/opencodex

Length of output: 5876


Sync the new Kiro import section into the locale docs docs-site/src/content/docs/ja/guides/providers.md, docs-site/src/content/docs/ko/guides/providers.md, docs-site/src/content/docs/ru/guides/providers.md, and docs-site/src/content/docs/zh-cn/guides/providers.md still stop at the “multiple OAuth accounts” section and don’t include the new ### Kiro credential import block from docs-site/src/content/docs/guides/providers.md:98-110. Add the translated section, or mark these pages as intentionally pending translation so they don’t drift from the English source.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs-site/src/content/docs/guides/providers.md` around lines 98 - 110,
Synchronize the new “Kiro credential import” section from the English providers
guide into the Japanese, Korean, Russian, and Simplified Chinese locale guides.
Translate the heading and content while preserving the environment variable
names, privacy guidance, and read-only/database behavior; alternatively mark
each locale page as intentionally pending translation to prevent drift.

Source: Path instructions

Comment on lines +87 to +118
- Uses the configured `baseUrl` verbatim when it is custom. A canonical
`runtime.{region}.kiro.dev` URL follows the imported credential's API region; only that canonical
shape is eligible for one bounded fallback to `q.{region}.amazonaws.com` after an endpoint,
signature, DNS, or connection failure.
- Owns replay-safe connection-reset recovery, that single eligible endpoint fallback, and one OAuth
refresh/replay after HTTP 401. The client owns throttling, timeout, and ordinary service retries;
opencodex does not multiply those policies inside the adapter.
- Its non-streaming parser drains the same event stream for the web-search loop.

### Completion semantics

Kiro text events do not carry a dependable end-turn phase. When an ordinary client tool is present,
opencodex therefore adds a private `codex_kiro_final_answer` tool to the upstream request. Progress
text streams as commentary and cannot terminate the turn. The adapter consumes the private call,
emits its answer as final text, and never exposes the private tool to Codex or Claude Code.
When the web-search sidecar is active, this commentary still streams immediately; only the events
needed to decide whether the model requested a synthetic search remain buffered.

If Kiro emits progress without calling the completion tool, the adapter makes one continuation. That
single retry may finish with a validated private completion or plain final text. It cannot recurse:
an empty or reasoning-only retry is returned as retryable incomplete, while a real client tool call
keeps the turn open. If the retry only repeats the preceding commentary after whitespace
normalization, the duplicate output is suppressed while the turn still completes. Tool-free
requests retain normal text completion behavior.

### Reasoning effort

`gpt-5.6-sol` has verified native effort support. Its selected `low`, `medium`, `high`, `xhigh`, or
`max` value is sent as `additionalModelRequestFields.reasoning.effort`. Other Kiro models currently
use emulated reasoning: opencodex converts the selected level into bounded thinking instructions in
the user content because their native effort field has not been verified. Do not interpret an
advertised effort control on those models as proof of upstream-native reasoning support.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Locate localized copies of the kiro adapters page and check whether they still
# reference the pre-change endpoint/completion wording.
fd -t f 'adapters.md' docs-site/src/content/docs | sort
echo "---- locale files mentioning kiro ----"
fd -t f 'adapters.md' docs-site/src/content/docs \
  | rg -l --iglob '*/{ja,ko,ru,zh-cn}/*' 'kiro' || echo "no localized kiro adapter pages found"

Repository: lidge-jun/opencodex

Length of output: 494


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  docs-site/src/content/docs/ja/reference/adapters.md \
  docs-site/src/content/docs/ko/reference/adapters.md \
  docs-site/src/content/docs/ru/reference/adapters.md \
  docs-site/src/content/docs/zh-cn/reference/adapters.md
do
  echo "===== $f ====="
  wc -l "$f"
  # Show the Kiro-related section if present, otherwise the first 220 lines.
  if rg -n "Kiro|kiro|completion semantics|reasoning effort|baseUrl|fallback|401|codex_kiro_final_answer" "$f" >/tmp/rg.$$; then
    sed -n '1,240p' "$f" | nl -ba | sed -n '1,240p'
  else
    sed -n '1,220p' "$f" | nl -ba | sed -n '1,220p'
  fi
  echo
done
rm -f /tmp/rg.$$

Repository: lidge-jun/opencodex

Length of output: 317


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in \
  docs-site/src/content/docs/ja/reference/adapters.md \
  docs-site/src/content/docs/ko/reference/adapters.md \
  docs-site/src/content/docs/ru/reference/adapters.md \
  docs-site/src/content/docs/zh-cn/reference/adapters.md
do
  echo "===== $f ====="
  echo "-- headings / Kiro-related matches --"
  grep -nEi '^(#|##|###|####|Kiro|kiro|baseUrl|fallback|401|reasoning|completion|tool|progress)' "$f" || true
  echo "-- first 160 lines --"
  sed -n '1,160p' "$f" | cat -n
  echo
done

Repository: lidge-jun/opencodex

Length of output: 27106


Sync the Kiro section in the localized adapters docs
docs-site/src/content/docs/ja/reference/adapters.md:65-74, docs-site/src/content/docs/ko/reference/adapters.md:78-89, docs-site/src/content/docs/ru/reference/adapters.md:83-97, and docs-site/src/content/docs/zh-cn/reference/adapters.md:74-85 still describe the older Kiro behavior. Update them to match the English page’s current baseUrl/fallback, completion, and reasoning-effort semantics so the locales don’t contradict the source.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs-site/src/content/docs/reference/adapters.md` around lines 87 - 118,
Synchronize the Kiro sections in the Japanese, Korean, Russian, and Simplified
Chinese adapter documentation with the current English semantics: custom baseUrl
handling and bounded canonical-endpoint fallback, replay/refresh ownership,
private completion-tool and continuation behavior, web-search buffering, and
model-specific reasoning-effort support. Preserve each locale’s existing
formatting and terminology while replacing the outdated descriptions.

Source: Path instructions

Comment thread scripts/test.ts
}

export function createIsolatedTestEnvironment(
baseEnv: Record<string, string | undefined> = process.env,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Sanitize inherited credential and provider-state variables.

baseEnv preserves the caller’s OPENCODEX_API_AUTH_TOKEN and variables such as KIROCLI_DB_PATH. Tests can therefore use the developer’s real proxy token or open a real Kiro CLI database outside the temporary root, bypassing the intended isolation. Build the child environment from an allowlist or explicitly remove authentication, OAuth, and provider database-selection variables; add coverage for this behavior in tests/test-runner.test.ts.

Also applies to: 22-28

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/test.ts` at line 12, Sanitize the environment used by the test runner
instead of inheriting credential and provider-state variables through baseEnv.
Update the baseEnv setup and child-process environment construction in
scripts/test.ts to allow only safe variables or explicitly remove
OPENCODEX_API_AUTH_TOKEN, OAuth credentials, and Kiro provider
database-selection variables such as KIROCLI_DB_PATH, while preserving required
test configuration. Add coverage in tests/test-runner.test.ts verifying these
variables cannot escape the temporary test environment.

Comment on lines +112 to +118
if (
evidence.includes("insufficient_quota")
|| evidence.includes("quota exhausted")
|| evidence.includes("quota exceeded")
) {
return { message, status: 429, errorType: "insufficient_quota", code: "insufficient_quota", retryable: false };
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Rate-limit messages containing "quota exceeded" get misclassified as non-retryable insufficient_quota.

The quota branch here runs before the 429/rate-limit branch and matches a bare "quota exceeded" substring with no rate-limit disambiguation. Because evidence folds in the raw payload details, an upstream throttle worded like "requests per minute quota exceeded" lands in this branch and returns retryable: false, so a transient rate limit is never replayed. Note the sibling classifyKiroText deliberately avoids this with its quotaExhausted && !rateQuota guard — that guard was lost in the authoritative classifier.

🐛 Proposed fix: restore rate-quota disambiguation
+  const rateQuota = /requests?\s+per\s+(?:min|minute|second)|rpm|tpm/.test(evidence);
   if (
-    evidence.includes("insufficient_quota")
-    || evidence.includes("quota exhausted")
-    || evidence.includes("quota exceeded")
+    (evidence.includes("insufficient_quota")
+      || evidence.includes("quota exhausted")
+      || evidence.includes("quota exceeded"))
+    && !rateQuota
   ) {
     return { message, status: 429, errorType: "insufficient_quota", code: "insufficient_quota", retryable: false };
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (
evidence.includes("insufficient_quota")
|| evidence.includes("quota exhausted")
|| evidence.includes("quota exceeded")
) {
return { message, status: 429, errorType: "insufficient_quota", code: "insufficient_quota", retryable: false };
}
const rateQuota = /requests?\s+per\s+(?:min|minute|second)|rpm|tpm/.test(evidence);
if (
(evidence.includes("insufficient_quota")
|| evidence.includes("quota exhausted")
|| evidence.includes("quota exceeded"))
&& !rateQuota
) {
return { message, status: 429, errorType: "insufficient_quota", code: "insufficient_quota", retryable: false };
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adapters/kiro-errors.ts` around lines 112 - 118, Update the quota
classification branch in the authoritative classifier to exclude rate-limit
evidence, matching the rate-quota disambiguation used by classifyKiroText.
Ensure messages such as “requests per minute quota exceeded” continue to the
429/rate-limit branch, while genuine exhausted quota errors still return
non-retryable insufficient_quota.

Comment on lines +136 to +150
case "metadataEvent": {
const contextUsagePercentage = parsed.contextUsagePercentage;
if (
contextUsagePercentage !== undefined
&& (typeof contextUsagePercentage !== "number" || !Number.isFinite(contextUsagePercentage))
) {
return malformed(eventType, "contextUsagePercentage must be a finite number");
}
return {
type: "metadata",
...(parseTokenUsage(eventType, parsed.tokenUsage) !== undefined
? { usage: parseTokenUsage(eventType, parsed.tokenUsage) }
: {}),
...(typeof contextUsagePercentage === "number" ? { contextUsagePercentage } : {}),
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Redundant double-evaluation of parseTokenUsage (and the optionalString pattern) — compute once.

In the metadataEvent case (Lines 146‑147) parseTokenUsage(eventType, parsed.tokenUsage) runs twice: once in the !== undefined guard and once to produce the value. Each invocation fully re-validates five token fields and allocates a fresh OcxUsage object, so every metadata frame pays double the work. The same call-it-twice shape recurs for optionalString/optionalBoolean in the assistantResponseEvent, reasoningContentEvent, and toolUseEvent cases (Lines 99‑127). It is functionally correct (the extractors are deterministic and throw on the first call), just wasteful and harder to read.

♻️ Compute once, then spread
-    case "metadataEvent": {
-      const contextUsagePercentage = parsed.contextUsagePercentage;
+    case "metadataEvent": {
+      const contextUsagePercentage = parsed.contextUsagePercentage;
+      const usage = parseTokenUsage(eventType, parsed.tokenUsage);
       if (
         contextUsagePercentage !== undefined
         && (typeof contextUsagePercentage !== "number" || !Number.isFinite(contextUsagePercentage))
       ) {
         return malformed(eventType, "contextUsagePercentage must be a finite number");
       }
       return {
         type: "metadata",
-        ...(parseTokenUsage(eventType, parsed.tokenUsage) !== undefined
-          ? { usage: parseTokenUsage(eventType, parsed.tokenUsage) }
-          : {}),
+        ...(usage !== undefined ? { usage } : {}),
         ...(typeof contextUsagePercentage === "number" ? { contextUsagePercentage } : {}),
       };
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case "metadataEvent": {
const contextUsagePercentage = parsed.contextUsagePercentage;
if (
contextUsagePercentage !== undefined
&& (typeof contextUsagePercentage !== "number" || !Number.isFinite(contextUsagePercentage))
) {
return malformed(eventType, "contextUsagePercentage must be a finite number");
}
return {
type: "metadata",
...(parseTokenUsage(eventType, parsed.tokenUsage) !== undefined
? { usage: parseTokenUsage(eventType, parsed.tokenUsage) }
: {}),
...(typeof contextUsagePercentage === "number" ? { contextUsagePercentage } : {}),
};
case "metadataEvent": {
const contextUsagePercentage = parsed.contextUsagePercentage;
const usage = parseTokenUsage(eventType, parsed.tokenUsage);
if (
contextUsagePercentage !== undefined
&& (typeof contextUsagePercentage !== "number" || !Number.isFinite(contextUsagePercentage))
) {
return malformed(eventType, "contextUsagePercentage must be a finite number");
}
return {
type: "metadata",
...(usage !== undefined ? { usage } : {}),
...(typeof contextUsagePercentage === "number" ? { contextUsagePercentage } : {}),
};
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/adapters/kiro-events.ts` around lines 136 - 150, Compute the result of
parseTokenUsage once in the metadataEvent case, store it in a local variable,
and reuse that value for both the undefined check and usage property. Apply the
same compute-once pattern to optionalString and optionalBoolean in the
assistantResponseEvent, reasoningContentEvent, and toolUseEvent cases,
preserving the existing conditional spread behavior.

Comment on lines +228 to +247
const row = selectTokenRow(db);
if (row === "ambiguous") {
diagnostics.push({ location, status: "token_ambiguous" });
throw new Error("Kiro CLI credential database contains multiple tokens; set KIROCLI_TOKEN_KEY to select one");
}
if (row === "selected_missing") {
diagnostics.push({ location, status: "token_key_missing" });
throw new Error("The KIROCLI_TOKEN_KEY selection was not found in the Kiro CLI credential database");
}
if (!tokenData) {
if (!row) {
diagnostics.push({ location, status: "token_missing" });
continue;
}
let tokenData: JsonObject;
try {
tokenData = JSON.parse(row.value) as JsonObject;
} catch {
diagnostics.push({ location, status: "invalid_json" });
continue;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Ambiguous/missing-selection errors abort the entire multi-location scan instead of trying remaining candidates.

Unlike "missing", "unreadable", "token_missing", and "invalid_json" (all of which continue to the next candidate in sqliteEntries()), the "ambiguous" (Line 229-232) and "selected_missing" (Line 233-236) branches immediately throw. When KIROCLI_DB_PATH is unset, sqliteEntries() can return up to 4 default candidate paths (mac/linux kiro-cli, amazon-q, kiro-sso-cache); if the first readable candidate happens to have ambiguous tokens (or lacks the KIROCLI_TOKEN_KEY-selected row) while a later candidate holds a perfectly usable, unambiguous credential, login now fails hard instead of falling through — a real functional regression versus the surrounding fallback design.

Consider recording the failure and continuing the loop, only throwing after all candidates are exhausted with no successful credential:

🔧 Proposed fix
 function readSqliteCredentials(diagnostics: KiroImportDiagnostic[]): ImportedKiroCredential | undefined {
+  let selectionError: Error | undefined;
   for (const { location, path } of sqliteEntries()) {
     ...
     try {
       const row = selectTokenRow(db);
       if (row === "ambiguous") {
         diagnostics.push({ location, status: "token_ambiguous" });
-        throw new Error("Kiro CLI credential database contains multiple tokens; set KIROCLI_TOKEN_KEY to select one");
+        selectionError ??= new Error("Kiro CLI credential database contains multiple tokens; set KIROCLI_TOKEN_KEY to select one");
+        continue;
       }
       if (row === "selected_missing") {
         diagnostics.push({ location, status: "token_key_missing" });
-        throw new Error("The KIROCLI_TOKEN_KEY selection was not found in the Kiro CLI credential database");
+        selectionError ??= new Error("The KIROCLI_TOKEN_KEY selection was not found in the Kiro CLI credential database");
+        continue;
       }
       ...
     } catch (error) {
-      if (error instanceof Error && error.message.includes("KIROCLI_TOKEN_KEY")) throw error;
       diagnostics.push({ location, status: "schema_mismatch" });
     } finally {
       db.close();
     }
   }
+  if (selectionError) throw selectionError;
   return undefined;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const row = selectTokenRow(db);
if (row === "ambiguous") {
diagnostics.push({ location, status: "token_ambiguous" });
throw new Error("Kiro CLI credential database contains multiple tokens; set KIROCLI_TOKEN_KEY to select one");
}
if (row === "selected_missing") {
diagnostics.push({ location, status: "token_key_missing" });
throw new Error("The KIROCLI_TOKEN_KEY selection was not found in the Kiro CLI credential database");
}
if (!tokenData) {
if (!row) {
diagnostics.push({ location, status: "token_missing" });
continue;
}
let tokenData: JsonObject;
try {
tokenData = JSON.parse(row.value) as JsonObject;
} catch {
diagnostics.push({ location, status: "invalid_json" });
continue;
}
function readSqliteCredentials(diagnostics: KiroImportDiagnostic[]): ImportedKiroCredential | undefined {
let selectionError: Error | undefined;
for (const { location, path } of sqliteEntries()) {
const row = selectTokenRow(db);
if (row === "ambiguous") {
diagnostics.push({ location, status: "token_ambiguous" });
selectionError ??= new Error("Kiro CLI credential database contains multiple tokens; set KIROCLI_TOKEN_KEY to select one");
continue;
}
if (row === "selected_missing") {
diagnostics.push({ location, status: "token_key_missing" });
selectionError ??= new Error("The KIROCLI_TOKEN_KEY selection was not found in the Kiro CLI credential database");
continue;
}
if (!row) {
diagnostics.push({ location, status: "token_missing" });
continue;
}
let tokenData: JsonObject;
try {
tokenData = JSON.parse(row.value) as JsonObject;
} catch {
diagnostics.push({ location, status: "invalid_json" });
continue;
}
}
if (selectionError) throw selectionError;
return undefined;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oauth/kiro-credentials.ts` around lines 228 - 247, Update the
sqliteEntries() scan around selectTokenRow(db) so the "ambiguous" and
"selected_missing" cases record their diagnostics and failure details, then
continue to the next candidate instead of throwing immediately. Preserve the
existing successful-token flow and, after all candidates are exhausted without a
usable credential, propagate an appropriate final error consistent with the
surrounding scan behavior.

Comment on lines +265 to +266
} catch (error) {
if (error instanceof Error && error.message.includes("KIROCLI_TOKEN_KEY")) throw error;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Brittle substring-based error discrimination in the rethrow guard.

error.message.includes("KIROCLI_TOKEN_KEY") couples control flow to the exact wording of the errors thrown at Lines 231 and 235. Any future edit to either message (e.g. localization, wording tweak) that drops that literal substring would silently misclassify a fatal selection error as "schema_mismatch" and swallow it instead of propagating. A dedicated error type is more robust:

🔧 Proposed fix
+class KiroTokenSelectionError extends Error {}
+
 function readSqliteCredentials(diagnostics: KiroImportDiagnostic[]): ImportedKiroCredential | undefined {
   ...
       if (row === "ambiguous") {
         diagnostics.push({ location, status: "token_ambiguous" });
-        throw new Error("Kiro CLI credential database contains multiple tokens; set KIROCLI_TOKEN_KEY to select one");
+        throw new KiroTokenSelectionError("Kiro CLI credential database contains multiple tokens; set KIROCLI_TOKEN_KEY to select one");
       }
       if (row === "selected_missing") {
         diagnostics.push({ location, status: "token_key_missing" });
-        throw new Error("The KIROCLI_TOKEN_KEY selection was not found in the Kiro CLI credential database");
+        throw new KiroTokenSelectionError("The KIROCLI_TOKEN_KEY selection was not found in the Kiro CLI credential database");
       }
       ...
     } catch (error) {
-      if (error instanceof Error && error.message.includes("KIROCLI_TOKEN_KEY")) throw error;
+      if (error instanceof KiroTokenSelectionError) throw error;
       diagnostics.push({ location, status: "schema_mismatch" });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (error) {
if (error instanceof Error && error.message.includes("KIROCLI_TOKEN_KEY")) throw error;
} catch (error) {
if (error instanceof KiroTokenSelectionError) throw error;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/oauth/kiro-credentials.ts` around lines 265 - 266, Replace the
message-substring check in the catch block with a dedicated error type or stable
error identifier used by the fatal selection errors thrown at the earlier
validation points. Update those throw sites and the catch guard together so
fatal selection errors are always rethrown even if their messages change, while
other errors retain the existing schema-mismatch handling.

Comment on lines +266 to +268
const closed = Bun.serve({ port: 0, fetch: () => new Response() });
const closedOrigin = closed.url.toString().replace(/\/$/, "");
closed.stop(true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== File context =="
sed -n '230,310p' tests/claude-messages-endpoint.test.ts | cat -n

echo
echo "== Search for stop(true) usage =="
rg -n "stop\\(true\\)" tests src . -g '!**/node_modules/**' || true

echo
echo "== Bun type/docs hints in repo =="
rg -n "Promise<void>|stop\\(true\\)|Server.stop" . -g '!**/node_modules/**' || true

Repository: lidge-jun/opencodex

Length of output: 50375


🌐 Web query:

Bun.serve server stop(true) Promise<void> official docs

💡 Result:

In Bun, the server.stop method is used to stop the server from accepting new connections [1][2]. When you call server.stop(true), you are performing a force stop [1]. This immediately terminates all active connections, including in-flight HTTP requests and WebSocket connections, and stops the server from accepting new ones [1][3][2]. By default, calling server.stop without any arguments (or with false) performs a graceful stop, allowing existing in-flight requests and WebSocket connections to complete before the server shuts down [1][2]. The method returns a Promise, which resolves once the server has fully stopped [1][3]. Example usage: const server = Bun.serve({ fetch(req) { return new Response("Hello!"); }, }); // Force stop and close all active connections await server.stop(true);

Citations:


🌐 Web query:

Bun server stop(true) await Promise<void> docs

💡 Result:

In Bun, the server.stop method is used to stop a server from accepting new connections [1][2]. The method accepts an optional boolean argument, closeActiveConnections [2][3]. The syntax is: await server.stop(closeActiveConnections?: boolean); When called as await server.stop(true), the server immediately terminates all in-flight requests and WebSocket connections, in addition to stopping the acceptance of new connections [2][3]. By default, if you call await server.stop without arguments (or with false), the server stops accepting new connections but allows existing in-flight requests and WebSocket connections to complete, which may take some time [2][3]. The method returns a Promise that resolves once the server has stopped [2][3].

Citations:


🌐 Web query:

site:bun.sh/docs server.stop(true) Promise<void>

💡 Result:

In the context of the Bun runtime, server.stop(true) is a method used to terminate a server instance [1]. The method server.stop(closeActiveConnections?: boolean): Promise stops the server from accepting new connections [1]. When you pass true as the argument (server.stop(true)), it instructs the server to immediately terminate all active connections [1]. If the argument is omitted or false (the default behavior), the server performs a graceful shutdown, allowing existing in-flight requests and WebSocket connections to complete before stopping [1]. The method returns a Promise that resolves when the server has fully stopped [1].

Citations:


Await closed.stop(true) before sending the refusal-path request.
tests/claude-messages-endpoint.test.ts:266-268 calls closed.stop(true) and immediately issues the downstream request. Bun’s stop(true) is asynchronous and resolves only after the server has fully stopped, so this can race shutdown and intermittently hit the temporary server instead of the connection-refused path.

Proposed fix
-  closed.stop(true);
+  await closed.stop(true);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const closed = Bun.serve({ port: 0, fetch: () => new Response() });
const closedOrigin = closed.url.toString().replace(/\/$/, "");
closed.stop(true);
const closed = Bun.serve({ port: 0, fetch: () => new Response() });
const closedOrigin = closed.url.toString().replace(/\/$/, "");
await closed.stop(true);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/claude-messages-endpoint.test.ts` around lines 266 - 268, In the
temporary server setup for the refusal-path test, await the promise returned by
closed.stop(true) before issuing the downstream request. Keep closedOrigin
captured before shutdown and preserve the existing request assertions.

Comment thread tests/kiro-oauth.test.ts
Comment on lines +116 to +157
test("KIROCLI_DB_PATH selects a nonstandard read-only database without creating missing paths", () => {
const path = join(tmp, "custom", "credentials.sqlite3");
seedCustomTokenDb(path, [["kirocli:social:token", { access_token: "aoa-custom", refresh_token: "rt-custom" }]]);
process.env.KIROCLI_DB_PATH = path;
expect(readKiroCliSqlite()?.access).toBe("aoa-custom");

const missing = join(tmp, "missing", "credentials.sqlite3");
seedKiroCliDb({ access_token: "aoa-default-must-not-win", refresh_token: "rt-default" });
process.env.KIROCLI_DB_PATH = missing;
expect(readKiroCliSqlite()).toBeNull();
expect(existsSync(missing)).toBe(false);
});

test("known token rows are preferred deterministically and KIROCLI_TOKEN_KEY overrides them", () => {
const path = join(tmp, "selection", "credentials.sqlite3");
seedCustomTokenDb(path, [
["kirocli:social:token", { access_token: "aoa-social", refresh_token: "rt-social" }],
["kirocli:odic:token", { access_token: "aoa-oidc", refresh_token: "rt-oidc" }],
]);
process.env.KIROCLI_DB_PATH = path;
expect(readKiroCliSqlite()?.access).toBe("aoa-oidc");
process.env.KIROCLI_TOKEN_KEY = "kirocli:social:token";
expect(readKiroCliSqlite()?.access).toBe("aoa-social");
});

test("otherwise ambiguous token rows require explicit selection without leaking paths or secrets", () => {
const path = join(tmp, "ambiguous", "credentials.sqlite3");
seedCustomTokenDb(path, [
["custom:a:token", { access_token: "aoa-secret-a", refresh_token: "rt-a" }],
["custom:b:token", { access_token: "aoa-secret-b", refresh_token: "rt-b" }],
]);
process.env.KIROCLI_DB_PATH = path;
expect(() => readKiroCliSqlite()).toThrow("set KIROCLI_TOKEN_KEY to select one");
try {
readKiroCliSqlite();
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
expect(message).not.toContain(tmp);
expect(message).not.toContain("aoa-secret");
}
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing regression test for KIROCLI_TOKEN_KEY pointing at a nonexistent key.

The three new tests cover default DB-path resolution, deterministic preference + a matching KIROCLI_TOKEN_KEY override, and ambiguous-row rejection — but none set KIROCLI_TOKEN_KEY to a key absent from the seeded auth_kv rows. That leaves the "selected_missing" branch (kiro-credentials.ts lines 233-236, token_key_missing diagnostic) completely untested.

🧪 Suggested additional test
test("KIROCLI_TOKEN_KEY selecting a nonexistent key fails login explicitly", () => {
  const path = join(tmp, "missing-key", "credentials.sqlite3");
  seedCustomTokenDb(path, [["kirocli:social:token", { access_token: "aoa-social", refresh_token: "rt-social" }]]);
  process.env.KIROCLI_DB_PATH = path;
  process.env.KIROCLI_TOKEN_KEY = "kirocli:does-not-exist:token";
  expect(() => readKiroCliSqlite()).toThrow("KIROCLI_TOKEN_KEY selection was not found");
});

As per path instructions for tests/**: "A behavior change in src/ should come with a focused regression test near the existing tests for that subsystem."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/kiro-oauth.test.ts` around lines 116 - 157, Add a focused regression
test alongside the existing KIROCLI SQLite tests for a configured
KIROCLI_TOKEN_KEY that is absent from auth_kv. Seed one valid token row, set
KIROCLI_DB_PATH and a nonexistent KIROCLI_TOKEN_KEY, then assert
readKiroCliSqlite explicitly throws the missing-selection error.

Source: Path instructions

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ca7ea3264

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/bridge.ts
if (currentToolCall) closeCurrentToolCall();
if (currentWebSearch) closeCurrentWebSearch("failed", []);
const failure = adapterFailureFromMessage(event.message);
const failure = adapterFailureFromEvent(event);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve adapter error statuses in failed responses

When a streaming adapter now provides a structured event.status (Kiro 401/429/400), adapterFailureFromEvent computes failure.httpStatus but the emitted response.failed only serializes failure.error, which has no status field. The Claude translator explicitly reads response.error.status and defaults absent values to 500, so Kiro auth or rate-limit stream failures are returned to Claude Code as retryable overloaded_error instead of authentication/rate-limit errors; include the status in error/last_error when emitting the failed response.

Useful? React with 👍 / 👎.

Comment thread src/oauth/index.ts

/** Providers whose upstream-401 replay path may force a snapshot refresh. */
const FORCE_REFRESH_PROVIDERS = new Set(["xai", "github-copilot"]);
const FORCE_REFRESH_PROVIDERS = new Set(["xai", "github-copilot", "kiro"]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid replaying the same Kiro token after 401

Adding Kiro to the forced-401 replay set sends rejected local-cli credentials through the generic refresh path. For the normal Kiro login source (source: "local-cli"), refreshAndPersistAccessToken first re-imports any unexpired Kiro CLI row and returns it before calling refreshKiroToken; if that row is the same access token that just received 401 (for example a stale/revoked token with future or missing expiry), the replay uses the identical Bearer and cannot recover. Skip the local-cli shortcut on forced refresh unless the imported generation differs.

AGENTS.md reference: AGENTS.md:L65-L69

Useful? React with 👍 / 👎.

Comment thread src/adapters/kiro.ts
return;
}
if (!fallback.response.ok) {
const payload = await fallback.response.text().catch(() => "");

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bound fallback error body reads

When the bounded Kiro completion retry returns a non-2xx response, this reads the raw upstream body with Response.text(). Unlike the normal Kiro HTTP error path, that has no byte or inactivity bound and buffers the whole body, so a large or stalled 401/429/5xx retry body can hang the turn or consume memory after the first attempt; use the same bounded error-body helper used elsewhere before classifying the retry failure.

Useful? React with 👍 / 👎.

Comment thread src/adapters/kiro-wire.ts
Comment on lines +113 to +114
const remembered = parsed._providerContinuation?.kiro?.conversationId;
if (isValidKiroConversationId(remembered)) return remembered;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reset Kiro conversations at compaction boundaries

For a previous_response_id request that appends a new context_compaction marker, the parser sets _contextCompactionBoundary, but this code still reuses the remembered Kiro conversation id unconditionally. That lets Kiro continue its server-side conversation with the pre-compaction context even though the local history has started a compacted epoch, defeating compaction and risking old context influencing later turns; mint a fresh Kiro conversation id when the boundary flag is set.

Useful? React with 👍 / 👎.

@Ingwannu

Copy link
Copy Markdown
Owner

Closing this restoration PR. Its stated purpose is to restore the old #302 change set after that merge became unreachable, and it now spans 53 files across Kiro OAuth, bridge, Responses state, web search, test runner, and shared types. Against current dev it is conflicting (12 conflict sections / 69 conflict markers) and still carries unresolved correctness and credential/test-environment review items. Replaying the old stack wholesale would reintroduce stale assumptions and overwrite newer work. Please open a fresh, minimal PR for any Kiro bug that still reproduces on current dev, with the reproduction and only the directly required files.

@Ingwannu Ingwannu closed this Jul 23, 2026
lidge-jun added a commit that referenced this pull request Jul 23, 2026
eachann1024 pushed a commit to eachann1024/opencodex that referenced this pull request Jul 23, 2026
…tack, review doc 050) — conflicts resolved to PR-side which already contains upstream dev
eachann1024 pushed a commit to eachann1024/opencodex that referenced this pull request Jul 23, 2026
eachann1024 pushed a commit to eachann1024/opencodex that referenced this pull request Jul 23, 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.

2 participants