opencode-kiro 0.4.0 → 0.5.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,22 +1,48 @@
1
1
  # opencode-kiro
2
2
 
3
- The ACP-compliant [Kiro](https://kiro.dev) auth plugin for [opencode](https://opencode.ai).
4
-
5
- opencode learns the `kiro` provider and its available models (US region) from the
6
- [models.dev](https://models.dev) catalog. This plugin supplies the following pieces:
7
-
8
- - **Auth** via the official `kiro-cli` login flow (`opencode auth login`, then "Kiro CLI Login")
9
- - **Provider options loader**: the `cwd`, `agent`, `trustAllTools`, `mcpTimeout` values
10
- opencode forwards into the SDK factory
11
- - **TUI credits display**: an opt-in Kiro credits box in the sidebar (appended below the
12
- native Context box) plus a matching footer credits chip
3
+ > ⚠️ **Experimental prerelease** — `0.5.0-beta.2` targets the **unreleased OpenCode v2**
4
+ > plugin contract at a pinned snapshot. It does **not** work with OpenCode v1.
5
+ > v1 users: stay on **`opencode-kiro@0.4.0`** (the `main` branch / npm `latest` line,
6
+ > which remains the supported stable release). See
7
+ > [RELEASE_NOTES_0.5.0-beta.2.md](./RELEASE_NOTES_0.5.0-beta.2.md) and
8
+ > [PINNED_VERSIONS.md](./PINNED_VERSIONS.md) for exact pins and the tested OpenCode SHA.
9
+ > No OpenCode v2 release date is known or claimed here.
10
+
11
+ The ACP-compliant [Kiro](https://kiro.dev) plugin for [opencode](https://opencode.ai).
12
+
13
+ The plugin supplies:
14
+
15
+ - **Auth** via the official `kiro-cli` login flow: it registers the `kiro` integration
16
+ with a **Kiro CLI Login** OAuth method (`opencode auth login`)
17
+ - **Model discovery**: after auth it captures Kiro's live model lineup and merges it
18
+ into OpenCode's catalog (exact ID intersection, reasoning-effort variants), with a
19
+ minimal self-registration fallback when the catalog lacks a `kiro` entry
20
+ - **Provider ownership**: an AISDK hook constructs the provider from
21
+ [`kiro-acp-ai-provider`](https://www.npmjs.com/package/kiro-acp-ai-provider) with the
22
+ right options (`cwd`, `agent`, `trustAllTools`, `mcpTimeout`, `contextWindows`)
23
+ - **TUI credits display**: a live Kiro credits box in the sidebar and a compact
24
+ credits chip in the prompt footer row beside the host cost/context display, both
25
+ styled with the host's active theme tokens — auto-loaded from the same single
26
+ config entry (`tui: true`)
27
+
28
+ `kiro-acp-ai-provider` talks to your locally installed `kiro-cli` over Kiro's
29
+ [Agent Client Protocol](https://agentclientprotocol.com) (ACP). This is the supported
30
+ integration path: requests go through kiro-cli exactly like Kiro's own IDE clients,
31
+ with no credential scraping and no reuse of Kiro credentials against other providers.
32
+
33
+ ## Compatibility
34
+
35
+ This prerelease is built and tested against **one pinned OpenCode v2 snapshot**:
36
+
37
+ | Item | Value |
38
+ |---|---|
39
+ | Tested OpenCode commit (`upstream/v2`) | `1cf61593b5ec204619b3f679fe418fec10ca5934` |
40
+ | `@opencode-ai/plugin` | `0.0.0-dev-17968` (exact) |
41
+ | Package version | `0.5.0-beta.2` |
13
42
 
14
- The `kiro` provider resolves to [`kiro-acp-ai-provider`](https://www.npmjs.com/package/kiro-acp-ai-provider),
15
- an AI-SDK provider that talks to your locally installed `kiro-cli` over Kiro's
16
- [Agent Client Protocol](https://agentclientprotocol.com) (ACP); opencode picks it up from
17
- the catalog's `npm` field. This is the supported integration path: requests go through
18
- kiro-cli exactly like Kiro's own IDE clients, with no credential scraping and no reuse of
19
- Kiro credentials against other providers.
43
+ Full pin table and verification evidence: [PINNED_VERSIONS.md](./PINNED_VERSIONS.md).
44
+ There is no `engines.opencode` constraint the v2 host has no stable semver yet; the
45
+ tested SHA above is the compatibility target. Other v2 snapshots may or may not work.
20
46
 
21
47
  ## Prerequisites
22
48
 
@@ -24,83 +50,85 @@ Kiro credentials against other providers.
24
50
  |---|---|
25
51
  | [kiro-cli](https://kiro.dev/docs/cli/) | Must be installed and on `PATH`; a Kiro subscription / AWS Builder ID account |
26
52
  | [Node.js](https://nodejs.org) `>= 20` | Enforced via `engines.node`. |
27
- | opencode `>= 1.16.0` | Enforced via `engines.opencode` on released builds. The shipped catalog must include the `kiro` provider (see [Troubleshooting](#troubleshooting)). |
28
-
29
- ## Install
30
-
31
- ```bash
32
- opencode plugin opencode-kiro
33
- ```
34
-
35
- (alias: `opencode plug opencode-kiro`; add `--global`/`-g` to install into your global config instead of the project)
36
-
37
- The installer reads this package's `exports` and detects both plugin entrypoints
38
- (`./server` and `./tui`), then patches **both** config files automatically:
39
-
40
- - `.opencode/opencode.json`: the server plugin (auth)
41
- - `.opencode/tui.json`: the TUI plugin (credits sidebar box + footer chip)
42
-
43
- (with `--global`: `~/.config/opencode/opencode.json` and `~/.config/opencode/tui.json`)
53
+ | OpenCode v2 at the tested snapshot | See [Compatibility](#compatibility). This prerelease does not support OpenCode v1. |
44
54
 
45
- You do **not** add a `provider.kiro` block; opencode loads the `kiro` provider and its
46
- models straight from the models.dev catalog. See
47
- [Credits in the sidebar](#credits-in-the-sidebar) for what the TUI plugin adds.
55
+ ## Install and configure
48
56
 
49
- ### Manual alternative
57
+ **One config entry — that's the whole setup.** Add the package to the **`plugins`**
58
+ array (plural) of your OpenCode config (`opencode.json`, project or global):
50
59
 
51
- Add the package name to the `plugin` array of **both** files yourself (in the
52
- project's `.opencode/` directory, at the project root, or in the global
53
- `~/.config/opencode/`, all are valid config locations):
60
+ ```json
61
+ {
62
+ "plugins": ["opencode-kiro@0.5.0-beta.2"]
63
+ }
64
+ ```
54
65
 
55
- `opencode.json`:
66
+ The object form pins the same version and leaves room for future options:
56
67
 
57
68
  ```json
58
69
  {
59
- "plugin": ["opencode-kiro"]
70
+ "plugins": [
71
+ {
72
+ "package": "opencode-kiro@0.5.0-beta.2",
73
+ "options": {}
74
+ }
75
+ ]
60
76
  }
61
77
  ```
62
78
 
63
- `tui.json`:
79
+ This loads the server entry (`./server` export): auth, model discovery, and provider
80
+ ownership. The server plugin declares **`tui: true`**, so the host TUI **auto-loads the
81
+ package's `./tui` entrypoint by itself** — the sidebar credits box and the composer
82
+ credits chip appear with no further configuration. **No `cli.json` TUI entry is
83
+ needed.** (The beta.1 two-file setup is obsolete: if you added `"opencode-kiro"` to
84
+ your global `cli.json` `plugins` array for beta.1, remove it.)
85
+
86
+ ### Disabling
87
+
88
+ One `"-kiro"` directive in the same `plugins` array disables **everything**: it removes
89
+ the server plugin, and with it the `tui: true` auto-load, so the TUI half never
90
+ activates either:
64
91
 
65
92
  ```json
66
93
  {
67
- "plugin": ["opencode-kiro"]
94
+ "plugins": ["opencode-kiro@0.5.0-beta.2", "-kiro"]
68
95
  }
69
96
  ```
70
97
 
71
- That single `plugin` entry is all the [credits sidebar](#credits-in-the-sidebar) box and
72
- footer chip need; there is no `plugin_enabled` step.
98
+ ### Legacy `tui.json` (v1)
99
+
100
+ `tui.json` is **legacy v1 configuration** and, under v2, is **migration input only**:
101
+ the host may read it when migrating old setups, and this plugin **never modifies it**.
102
+ Do not add new entries to `tui.json` (or to `cli.json` — neither is used by this
103
+ plugin anymore); the single `plugins` entry above is the only configuration.
73
104
 
74
105
  ### Local development (path source)
75
106
 
76
- Run a local checkout without npm: build first, then reference the repo directory by
77
- absolute path in both `plugin` arrays:
107
+ Run a local checkout without npm build and pack first, then reference the tarball
108
+ with the `name@file:` form in the `plugins` array:
78
109
 
79
110
  ```bash
80
111
  git clone https://github.com/NachoFLizaur/opencode-kiro && cd opencode-kiro
81
- npm install && npm run build
112
+ npm install && npm run build && npm pack
82
113
  ```
83
114
 
84
115
  ```json
85
- { "plugin": ["/absolute/path/to/opencode-kiro"] }
116
+ { "plugins": ["opencode-kiro@file:/absolute/path/to/opencode-kiro-0.5.0-beta.2.tgz"] }
86
117
  ```
87
118
 
88
- opencode resolves the right entrypoint per file from the package `exports`. Note that
89
- path-sourced TUI plugins **must export an `id`** (opencode rejects them otherwise);
90
- this package ships `{ id: "opencode-kiro", tui }`, so the id is identical across path
91
- and npm installs.
92
-
93
- Because the provider now comes from the catalog rather than the plugin, a local checkout
94
- also needs a catalog that includes `kiro`. opencode reads its catalog from
95
- `OPENCODE_MODELS_PATH` when set; point it at an `api.json` that contains the `kiro`
96
- provider (for example one generated from a [models.dev](https://models.dev) checkout):
97
-
98
- ```bash
99
- OPENCODE_MODELS_PATH=/path/to/api.json opencode models | grep '^kiro/'
100
- ```
119
+ A bare path or bare `file:` spec is rejected at the tested SHA — the `name@file:` form
120
+ is required. **Caveat (local `file:` installs only)**: the colon in the resulting
121
+ install dirname defeats the host's OpenTUI loader shim, so the TUI surfaces render a
122
+ contained per-slot error notice instead of the credits views (the rest of the TUI keeps
123
+ working). Registry installs (`opencode-kiro@0.5.0-beta.2`) use colon-free paths and are
124
+ fully green this affects local tarball validation only.
101
125
 
102
- Until the catalog opencode loads contains `kiro`, the provider will not appear regardless
103
- of this plugin being installed (the plugin only adds auth, not the provider definition).
126
+ The host resolves entrypoints from the package `exports` (`./server` for the server
127
+ half, `./tui` for the auto-loaded TUI half). Each entry module exports its own `id`:
128
+ the server plugin's id is `kiro` and the TUI plugin's id is `opencode-kiro`. Under
129
+ `tui: true` there is no separate TUI directive to manage — `-kiro` (the server id) is
130
+ the single kill-switch, and host logs use `kiro` for the server half and
131
+ `opencode-kiro` for the TUI half.
104
132
 
105
133
  ## Auth
106
134
 
@@ -108,24 +136,33 @@ of this plugin being installed (the plugin only adds auth, not the provider defi
108
136
  opencode auth login
109
137
  ```
110
138
 
111
- Select the **Kiro (plugin)** provider, then the **Kiro CLI Login** method:
139
+ Select the **Kiro** integration, then the **Kiro CLI Login** method:
112
140
 
113
141
  - **Already logged in to kiro-cli**: immediate success; the existing kiro-cli session is reused.
114
142
  - **Not logged in**: the plugin launches `kiro-cli login`, which opens a browser window.
115
- Complete the login there; the plugin polls for up to 120 seconds and stores the
116
- credential when kiro-cli reports success.
143
+ Complete the login there; the plugin polls for up to 120 seconds and stores a minimal
144
+ credential record when kiro-cli reports success.
145
+
146
+ There is no configuration prompt during login anymore: the beta.1
147
+ "Enable the Kiro credits sidebar?" consent select was removed (upstream deleted the
148
+ prompts API in favor of forms — and the sidebar no longer needs consent-driven config,
149
+ since `tui: true` auto-loads it).
117
150
 
118
151
  If the flow times out, authenticate directly with kiro-cli (`kiro-cli login`) and run
119
152
  `opencode auth login` again; the fast path then completes immediately.
120
153
 
121
- > **Note:** opencode will also surface `kiro` if the `KIRO_API_KEY` environment variable
122
- > is set, because the catalog entry declares `env: ["KIRO_API_KEY"]`. The intended auth
123
- > path for this plugin is still **Kiro CLI Login** above (it reuses your local kiro-cli
124
- > session); the env var is a secondary route opencode offers for any catalog provider.
154
+ kiro-cli owns credential storage and refresh OpenCode never stores real AWS tokens,
155
+ and the plugin implements no refresh callback.
125
156
 
126
157
  ## Models
127
158
 
128
- After authentication, the plugin exposes the exact, case-sensitive intersection of Kiro's runtime `modelId` values and the models.dev catalog's `model.api.id` values. The runtime `listModels()` result is authoritative: `runtimeEfforts` is always an array, an empty array leaves the matching catalog model unchanged, and nonempty arrays merge exact effort variants into the catalog. Existing variant metadata survives key collisions while the runtime effort sets `reasoningEffort`; an optional runtime `baselineEffort` sets the model's base effort. Successful discovery keeps every matching catalog key and all other metadata while omitting runtime-only and catalog-only IDs. A discovery exception or duplicate runtime ID preserves the exact original catalog unchanged.
159
+ After authentication, the plugin captures Kiro's runtime model list and transforms
160
+ OpenCode's catalog to the exact, case-sensitive intersection of runtime `modelId`
161
+ values and catalog model IDs. Runtime reasoning-effort levels are merged as model
162
+ variants (per model family, native levels only); an optional runtime baseline effort
163
+ sets the model's base effort. A discovery failure or duplicate runtime ID leaves the
164
+ catalog unchanged (fail-open). If the loaded catalog has no `kiro` provider at all, the
165
+ plugin self-registers a minimal fallback entry so discovered models remain usable.
129
166
 
130
167
  List the resulting models with:
131
168
 
@@ -134,95 +171,87 @@ opencode models
134
171
  opencode run -m kiro/<exact-model-id> "hello"
135
172
  ```
136
173
 
137
- Image input is capability-driven: paste an image path into the TUI prompt and
138
- image-capable models receive it as an attachment.
139
-
140
- ### Reasoning effort
141
-
142
- Effort-capable models expose a reasoning-effort toggle: cycle it in opencode with the
143
- **Cycle model variants** action (default keybind `ctrl+t`). It is **per model**, showing
144
- each family's native levels.
174
+ Effort-capable models expose their variants through OpenCode's model-variant selection.
175
+ The chosen level reaches the SDK through the provider-settings path: OpenCode overlays
176
+ the selected variant's `settings` onto the model's `settings`, hands them to the
177
+ plugin's `aisdk` hook as `event.options`, and the plugin passes them verbatim to
178
+ `createKiroAcp({ effort })`. That is why the plugin emits the SDK's own `effort` key
179
+ (not `reasoningEffort`) and why the SDK factory setting, not per-call provider
180
+ options, is the working carrier: OpenCode builds per-call `providerOptions` only for
181
+ the first-party `@ai-sdk/*` provider families, so `providerOptions.kiro.*` is never
182
+ populated for an `aisdk:` package provider like this one. Kiro cannot disable thinking,
183
+ so even the lowest level still produces a reasoning trail.
145
184
 
146
- Models without effort control show no effort option. opencode's **Default** (unset) returns the model to its native
147
- default effort. No config is required: the plugin's `provider.models` hook supplies the
148
- variants automatically and the chosen level flows to the SDK as
149
- `providerOptions.kiro.reasoningEffort`. Kiro cannot disable thinking, so even the lowest
150
- level still produces a reasoning trail.
151
-
152
- ## Credits in the sidebar
185
+ ## Credits in the TUI
153
186
 
154
187
  Kiro is subscription-metered: requests consume **credits**, and the dollar cost
155
- opencode normally displays for Kiro turns is always $0.00. To surface credits the
156
- plugin **appends** a small Kiro credits box in the sidebar, rendered right below the
157
- native **Context** box. It does **not** replace or disable any builtin section: the
158
- native Context box stays and keeps showing the usual tokens, context percentage, and
159
- cost.
160
-
161
- The credits box renders only for Kiro sessions; for a non-Kiro session it shows nothing,
162
- so that session's sidebar is unchanged. The credits value and its unit come from the
163
- metadata the SDK attaches to each message part (kiro-cli reports the unit); nothing is
164
- hardcoded client-side.
165
-
166
- All you need in `tui.json` is the plugin entry:
167
-
168
- ```json
169
- {
170
- "plugin": ["opencode-kiro"]
171
- }
172
- ```
173
-
174
- There is no `plugin_enabled` step anymore.
175
-
176
- ### Migrating from 0.2.1 and earlier
177
-
178
- Older versions replaced the native Context box with a clone and disabled the builtin via:
179
-
180
- ```json
181
- {
182
- "plugin_enabled": { "internal:sidebar-context": false }
183
- }
184
- ```
185
-
186
- If you upgraded from 0.2.1 or earlier and still have that line in your `tui.json`,
187
- remove it yourself: the plugin no longer manages `plugin_enabled`. Once the line is
188
- gone the native Context box returns and shows the usual tokens / context % / cost, and
189
- the Kiro credits box appears in a separate box right below it.
190
-
191
- ## Known limitation
192
-
193
- **Credits render in the TUI only.** Two TUI surfaces show them: the sidebar credits
194
- box (above) and the input/prompt meta row chip (`session_prompt_right`), which sits
195
- above the host's `$` cost chip. Every other cost surface (ACP clients, the web app,
196
- desktop, web share pages, and CLI cost output) shows $0.00 for Kiro sessions. The
197
- models.dev catalog declares Kiro's per-token `cost` as 0 (it is a subscription-metered
198
- provider with no per-token pricing), so opencode core computes $0.00 everywhere it
199
- renders dollar cost. That is expected, not a defect. A cross-surface credits display
200
- would require opencode core changes and is intentionally out of scope for this plugin.
188
+ OpenCode normally displays for Kiro turns is always $0.00. To surface credits the TUI
189
+ plugin renders two surfaces:
190
+
191
+ - a Kiro credits box in the sidebar (`sidebar.content` claim), showing the session's
192
+ live credits total and unit
193
+ - a compact credits chip in the prompt footer row beside the host cost/context
194
+ display (`prompt.footer.status` claim, v1 placement restored) with the same total
195
+
196
+ Both are additive `append` claims they compose with the host's built-in content and
197
+ never replace it — and both pick up the active theme's text tokens (feature-detected;
198
+ with no theme they fall back to default terminal styling). They render only for
199
+ sessions that carry Kiro credit data; other sessions are unchanged. The credits value
200
+ and unit come from the provider state the host persists on each message part
201
+ (`part.state.credits` / `part.state.creditsUnit`); nothing is hardcoded client-side.
202
+ The only configuration needed is the single `plugins` entry from
203
+ [Install](#install-and-configure) — the TUI half auto-loads via `tui: true`.
204
+
205
+ Durable credits are read straight from host message state (the host persists provider
206
+ state on text end — fixed upstream since beta.1). While a turn is still streaming,
207
+ credits for just-ended text are picked up live through a transient overlay that works
208
+ around a host reducer bug at the pinned snapshot (the live event path still drops
209
+ provider state); once durable state arrives it is authoritative and nothing is
210
+ double-counted. See the release notes for details.
211
+
212
+ ## Known limitations (prerelease)
213
+
214
+ - **Live text credits use a transient overlay.** The durable credits path is fixed
215
+ upstream, but the live `session.text.ended` reducer still drops provider state at
216
+ the tested SHA, so in-turn updates come from the plugin's transient overlay
217
+ (durable state always wins on reconcile). See
218
+ [Credits in the TUI](#credits-in-the-tui) and the release notes.
219
+ - **Credits render in the TUI only.** Every other cost surface (ACP clients, web,
220
+ desktop, share pages, CLI cost output) shows $0.00 for Kiro sessions because the
221
+ catalog declares Kiro's per-token `cost` as 0 (subscription-metered, no per-token
222
+ pricing). That is expected, not a defect.
223
+ - **Local `file:` installs show a per-slot TUI error.** The colon in a `name@file:`
224
+ install dirname defeats the host's OpenTUI loader shim; the failure is contained to
225
+ the plugin's slots (dismissible error notice, host TUI unaffected). Registry
226
+ installs are colon-free and fully working this affects local tarball validation
227
+ only.
228
+ - **Reduced toast feedback.** Auth-flow feedback is delivered as connect-flow text
229
+ rather than toasts; this plugin's core deliberately does not depend on the churning
230
+ TUI toast API.
231
+ - **One tested snapshot.** All pins are exact and the compatibility target is a single
232
+ OpenCode v2 SHA (see [Compatibility](#compatibility)); other snapshots may not work.
201
233
 
202
234
  ## How it works
203
235
 
204
- - **Provider metadata and runtime models**: opencode loads the `kiro` provider and model
205
- metadata from models.dev. After auth, this plugin keeps only exact catalog/runtime ID
206
- matches, preserves catalog metadata, and projects the runtime-authoritative effort
207
- options; a discovery exception or duplicate runtime ID keeps the input catalog unchanged.
208
- - **SDK resolution (resolveSDK)**: opencode reads the catalog's `npm` field
209
- (`kiro-acp-ai-provider`), installs that package into its package cache on first model
210
- use, and imports it. This plugin's `auth` loader supplies the provider options
211
- (`cwd`, `agent`, `trustAllTools`, `mcpTimeout`, `contextWindows`) that opencode forwards
212
- into `createKiroAcp(...)`. The loader relays each model's `limit.context` (from
213
- models.dev, via opencode's resolved catalog) into the SDK's `contextWindows` map keyed
214
- by `api.id`, so the SDK keeps no hardcoded per-model data and falls back to 1,000,000
215
- for any model absent from the relay.
216
- - **Auth (this plugin)**: registers the "Kiro CLI Login" OAuth method (kiro-cli login
217
- flow) plus the options loader above. The same plugin also imports `verifyAuth` from
218
- `kiro-acp-ai-provider` to check kiro-cli installation/login state.
219
- - **Session affinity & reset (in-SDK)**: the SDK keys kiro-cli sessions off opencode's
220
- `x-session-affinity` header, isolates tool-less utility calls (title generation) on
221
- an ephemeral session, detects prompt-history divergence (`fork/undo`), and starts a
222
- fresh kiro session when needed. No host-side session plumbing.
223
- - **Credits metadata**: the SDK attaches `{ kiro: { credits, creditsUnit } }` to the
224
- `metadata` of the final message part of each turn; opencode persists it, and the TUI
225
- plugin sums it per assistant message (deduped across text/reasoning parts) for the sidebar.
236
+ - **Auth (Integration + Credential)**: the plugin upserts the `kiro` integration with a
237
+ "Kiro CLI Login" OAuth method. `verifyAuth` from `kiro-acp-ai-provider` is the auth
238
+ authority (it delegates to kiro-cli); success is stored as a minimal
239
+ `Credential.OAuth` presence record.
240
+ - **Model discovery (catalog transform)**: after login (and on later login events) the
241
+ plugin runs `listModels()` outside the transform, then applies the validated capture
242
+ via a catalog transform and reload exact ID matching, catalog metadata preserved,
243
+ effort variants projected, fail-open on any discovery error.
244
+ - **Provider ownership (AISDK hook)**: the plugin's SDK hook always constructs the
245
+ provider from `kiro-acp-ai-provider` with the plugin-supplied options and sets it as
246
+ the event's SDK, so the Kiro provider is always plugin-owned. The options relay each
247
+ model's context window into the SDK's `contextWindows` map keyed by model ID.
248
+ - **Session affinity & reset (in-SDK)**: the SDK keys kiro-cli sessions off OpenCode's
249
+ session affinity, isolates tool-less utility calls on an ephemeral session, detects
250
+ prompt-history divergence, and starts a fresh kiro session when needed.
251
+ - **Credits state**: the SDK reports `credits` / `creditsUnit` in each turn's provider
252
+ metadata; OpenCode persists them key-unwrapped on message part state
253
+ (`part.state.credits`, `part.state.creditsUnit`), and the TUI plugin sums them per
254
+ assistant message (deduped across parts).
226
255
 
227
256
  ## Troubleshooting
228
257
 
@@ -230,11 +259,21 @@ would require opencode core changes and is intentionally out of scope for this p
230
259
  |---|---|
231
260
  | `kiro-cli is not installed` during auth | Install kiro-cli from <https://kiro.dev/docs/cli/> and ensure it is on `PATH` for the opencode process. |
232
261
  | Auth times out after ~120s | Complete the browser login faster, or run `kiro-cli login` yourself, then re-run `opencode auth login` (fast path). |
233
- | No credits line / credits stay 0 | Credits appear after the first **completed** kiro turn; cancelled turns and turns without usage metadata contribute nothing. Check the TUI plugin is `active` in the Plugins dialog (and listed in `tui.json`). |
234
- | Credits box never appears (even with `tui.json` configured correctly) | The TUI credits box renders only when `opencode-kiro` is resolvable in opencode's package cache. If the package is missing from the cache the box silently does not appear. Fix: ensure `opencode-kiro` is installed so it resolves in the cache. Do **not** manually clear the package cache: clearing can trigger a flaky on-demand refetch that fails with an "unknown git error". |
235
- | `kiro` provider not showing in `opencode models` | The provider comes from the models.dev catalog, not this plugin. Ensure your opencode version ships a catalog that includes `kiro` (run `opencode models --refresh` to update the cache). For local development, point opencode at a kiro-inclusive catalog via `OPENCODE_MODELS_PATH=/path/to/api.json` (see [Local development](#local-development-path-source)). |
236
- | Path install rejected (`must export id`) | Run `npm run build` in your checkout first and reference the repo root (both entry modules export ids). |
237
- | Provider visible but runs fail | The provider is selectable (from the catalog) before any credential exists. Run `opencode auth login` first. |
262
+ | No credits line / credits stay 0 | Credits appear after the first **completed** kiro turn; cancelled turns and turns without usage state contribute nothing. Check the plugin is active (no stray `"-kiro"` directive note that directive residue can persist on a reused data dir). |
263
+ | Credits surfaces never appear | The TUI half auto-loads from the server `plugins` entry via `tui: true` no separate TUI config exists. If the box/chip are missing, the server plugin itself is not loading (check your `plugins` entry and restart opencode). For local `name@file:` tarball installs, a contained per-slot error notice instead of the credits views is the known colon-path caveat; use a registry install. |
264
+ | `kiro` provider not showing in `opencode models` | Run `opencode auth login` first: models are discovered after auth. If the loaded catalog lacks a `kiro` entry, the plugin self-registers a minimal fallback during discovery. |
265
+ | Path install rejected (`must export id`) | Use the `name@file:<absolute tarball path>` form after `npm run build && npm pack` in your checkout (both entry modules export ids). |
266
+ | Provider visible but runs fail | The provider can be selectable before any credential exists. Run `opencode auth login` first. |
267
+ | Worked yesterday, broken today | This prerelease targets one pinned OpenCode snapshot (see [Compatibility](#compatibility)). If your OpenCode build moved past the tested SHA, the v2 plugin surface may have changed underneath it. |
268
+
269
+ ## Legacy: v1 / OpenCode v1 users (`0.4.0`)
270
+
271
+ `opencode-kiro@0.4.0` on the `main` branch is the supported stable line for OpenCode
272
+ v1 (`opencode >= 1.16.0`). It uses the v1 contract throughout: singular `plugin`
273
+ arrays in `opencode.json` and `tui.json`, the `opencode plugin opencode-kiro`
274
+ installer, and `part.metadata.kiro` credits. Its full documentation is the README at
275
+ the [`v0.4.0` tag](https://github.com/NachoFLizaur/opencode-kiro/tree/v0.4.0)
276
+ (equivalently, `main`). Do not install `0.5.0-beta.2` into an OpenCode v1 setup.
238
277
 
239
278
  ## Development
240
279
 
@@ -0,0 +1,40 @@
1
+ // src/tui/credits.ts
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null;
4
+ }
5
+ function readCreditState(state) {
6
+ if (!isRecord(state)) return void 0;
7
+ if (typeof state.credits !== "number" || !Number.isFinite(state.credits)) return void 0;
8
+ return {
9
+ credits: state.credits,
10
+ unit: typeof state.creditsUnit === "string" && state.creditsUnit.length > 0 ? state.creditsUnit : void 0
11
+ };
12
+ }
13
+ function readPartCredits(part) {
14
+ if (!isRecord(part)) return void 0;
15
+ if (part.type !== "text" && part.type !== "reasoning") return void 0;
16
+ return readCreditState(part.state);
17
+ }
18
+ function messageCredits(parts) {
19
+ const carriers = parts.map(readPartCredits).filter((value) => value !== void 0);
20
+ const last = carriers.at(-1);
21
+ if (!last) return void 0;
22
+ return {
23
+ credits: last.credits,
24
+ unit: last.unit ?? carriers.findLast((carrier) => carrier.unit !== void 0)?.unit
25
+ };
26
+ }
27
+ var creditsAmount = new Intl.NumberFormat("en-US", { maximumFractionDigits: 2 });
28
+ function formatCredits(value, unit) {
29
+ const amount = creditsAmount.format(Number.isFinite(value) ? value : 0);
30
+ if (!unit) return amount;
31
+ const label = value === 1 || unit.endsWith("s") ? unit : `${unit}s`;
32
+ return `${amount} ${label}`;
33
+ }
34
+ var money = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" });
35
+
36
+ export {
37
+ readCreditState,
38
+ messageCredits,
39
+ formatCredits
40
+ };
@@ -0,0 +1,37 @@
1
+ import {
2
+ formatCredits
3
+ } from "./chunk-M7OUVABX.js";
4
+
5
+ // src/tui/credits-box-view.ts
6
+ import { createElement, insert, insertNode, setProp } from "@opentui/solid";
7
+ import { createMemo } from "solid-js";
8
+ function createCreditsBoxView(credits, tokens) {
9
+ const current = createMemo(credits);
10
+ const root = createElement("box");
11
+ insertNode(
12
+ root,
13
+ headerLine(() => current().present ? "Kiro" : "", tokens?.default)
14
+ );
15
+ insertNode(
16
+ root,
17
+ plainLine(() => current().present ? formatCredits(current().total, current().unit) : "", tokens?.subdued)
18
+ );
19
+ return root;
20
+ }
21
+ function headerLine(content, fg) {
22
+ const line = createElement("text");
23
+ if (fg !== void 0) setProp(line, "fg", fg);
24
+ const bold = createElement("b");
25
+ insert(bold, content);
26
+ insertNode(line, bold);
27
+ return line;
28
+ }
29
+ function plainLine(content, fg) {
30
+ const line = createElement("text");
31
+ if (fg !== void 0) setProp(line, "fg", fg);
32
+ insert(line, content);
33
+ return line;
34
+ }
35
+ export {
36
+ createCreditsBoxView
37
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ formatCredits
3
+ } from "./chunk-M7OUVABX.js";
4
+
5
+ // src/tui/credits-chip-view.ts
6
+ import { createElement, insert, setProp } from "@opentui/solid";
7
+ import { createMemo } from "solid-js";
8
+ function createCreditsChipView(credits, tokens) {
9
+ const current = createMemo(credits);
10
+ const chip = createElement("text");
11
+ setProp(chip, "height", 1);
12
+ setProp(chip, "wrapMode", "none");
13
+ setProp(chip, "flexShrink", 0);
14
+ if (tokens?.subdued !== void 0) setProp(chip, "fg", tokens.subdued);
15
+ insert(chip, () => current().present ? formatCredits(current().total, current().unit) : "");
16
+ return chip;
17
+ }
18
+ export {
19
+ createCreditsChipView
20
+ };
package/dist/server.d.ts CHANGED
@@ -1,20 +1,7 @@
1
- import { Plugin, PluginInput, Hooks } from '@opencode-ai/plugin';
1
+ import { Plugin } from '@opencode-ai/plugin';
2
2
 
3
- declare function kiroTokenPath(): string;
4
- declare function readToken(tokenPath: string | undefined): Promise<{
5
- type: "success";
6
- refresh: string;
7
- access: string;
8
- expires: number;
9
- } | {
10
- type: "failed";
11
- }>;
12
- declare function notifyIfTokenExpired(client: PluginInput["client"] | undefined): Promise<void>;
13
- declare function enableSidebarConfig(path: string, input: PluginInput): Promise<void>;
14
- declare const KiroAuthPlugin: Plugin;
15
- declare const _default: {
16
- id: string;
17
- server: (input: PluginInput) => Promise<Hooks>;
18
- };
3
+ declare const plugin: Plugin.Plugin;
19
4
 
20
- export { KiroAuthPlugin, _default as default, enableSidebarConfig, kiroTokenPath, notifyIfTokenExpired, readToken };
5
+ declare const KiroAuthPlugin: Plugin.Plugin;
6
+
7
+ export { KiroAuthPlugin, plugin as default };