opencode-kiro 0.2.1 → 0.3.1
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 +38 -33
- package/dist/credits-box-view-BYKGQHSS.js +40 -0
- package/dist/server.d.ts +2 -1
- package/dist/server.js +2 -8
- package/dist/tui.js +3 -3
- package/package.json +1 -1
- package/dist/context-view-E6Q2FXL3.js +0 -64
package/README.md
CHANGED
|
@@ -8,8 +8,8 @@ opencode learns the `kiro` provider and its available models (US region) from th
|
|
|
8
8
|
- **Auth** via the official `kiro-cli` login flow (`opencode auth login`, then "Kiro CLI Login")
|
|
9
9
|
- **Provider options loader**: the `cwd`, `agent`, `trustAllTools`, `mcpTimeout` values
|
|
10
10
|
opencode forwards into the SDK factory
|
|
11
|
-
- **TUI credits display**: an opt-in
|
|
12
|
-
|
|
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
|
|
13
13
|
|
|
14
14
|
The `kiro` provider resolves to [`kiro-acp-ai-provider`](https://www.npmjs.com/package/kiro-acp-ai-provider),
|
|
15
15
|
an AI-SDK provider that talks to your locally installed `kiro-cli` over Kiro's
|
|
@@ -38,13 +38,13 @@ The installer reads this package's `exports` and detects both plugin entrypoints
|
|
|
38
38
|
(`./server` and `./tui`), then patches **both** config files automatically:
|
|
39
39
|
|
|
40
40
|
- `.opencode/opencode.json`: the server plugin (auth)
|
|
41
|
-
- `.opencode/tui.json`: the TUI plugin (credits sidebar box)
|
|
41
|
+
- `.opencode/tui.json`: the TUI plugin (credits sidebar box + footer chip)
|
|
42
42
|
|
|
43
43
|
(with `--global`: `~/.config/opencode/opencode.json` and `~/.config/opencode/tui.json`)
|
|
44
44
|
|
|
45
45
|
You do **not** add a `provider.kiro` block; opencode loads the `kiro` provider and its
|
|
46
|
-
models straight from the models.dev catalog.
|
|
47
|
-
[Credits in the sidebar](#credits-in-the-sidebar).
|
|
46
|
+
models straight from the models.dev catalog. See
|
|
47
|
+
[Credits in the sidebar](#credits-in-the-sidebar) for what the TUI plugin adds.
|
|
48
48
|
|
|
49
49
|
### Manual alternative
|
|
50
50
|
|
|
@@ -64,12 +64,12 @@ project's `.opencode/` directory, at the project root, or in the global
|
|
|
64
64
|
|
|
65
65
|
```json
|
|
66
66
|
{
|
|
67
|
-
"plugin": ["opencode-kiro"]
|
|
68
|
-
"plugin_enabled": { "internal:sidebar-context": false }
|
|
67
|
+
"plugin": ["opencode-kiro"]
|
|
69
68
|
}
|
|
70
69
|
```
|
|
71
70
|
|
|
72
|
-
|
|
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.
|
|
73
73
|
|
|
74
74
|
### Local development (path source)
|
|
75
75
|
|
|
@@ -87,8 +87,8 @@ npm install && npm run build
|
|
|
87
87
|
|
|
88
88
|
opencode resolves the right entrypoint per file from the package `exports`. Note that
|
|
89
89
|
path-sourced TUI plugins **must export an `id`** (opencode rejects them otherwise);
|
|
90
|
-
this package ships `{ id: "opencode-kiro", tui }`, so the id
|
|
91
|
-
|
|
90
|
+
this package ships `{ id: "opencode-kiro", tui }`, so the id is identical across path
|
|
91
|
+
and npm installs.
|
|
92
92
|
|
|
93
93
|
Because the provider now comes from the catalog rather than the plugin, a local checkout
|
|
94
94
|
also needs a catalog that includes `kiro`. opencode reads its catalog from
|
|
@@ -154,19 +154,30 @@ level still produces a reasoning trail.
|
|
|
154
154
|
## Credits in the sidebar
|
|
155
155
|
|
|
156
156
|
Kiro is subscription-metered: requests consume **credits**, and the dollar cost
|
|
157
|
-
opencode normally displays for Kiro turns is always $0.00.
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
opencode normally displays for Kiro turns is always $0.00. To surface credits the
|
|
158
|
+
plugin **appends** a small Kiro credits box in the sidebar, rendered right below the
|
|
159
|
+
native **Context** box. It does **not** replace or disable any builtin section: the
|
|
160
|
+
native Context box stays and keeps showing the usual tokens, context percentage, and
|
|
161
|
+
cost.
|
|
160
162
|
|
|
161
|
-
The
|
|
163
|
+
The credits box renders only for Kiro sessions; for a non-Kiro session it shows nothing,
|
|
164
|
+
so that session's sidebar is unchanged. The credits value and its unit come from the
|
|
165
|
+
metadata the SDK attaches to each message part (kiro-cli reports the unit); nothing is
|
|
166
|
+
hardcoded client-side.
|
|
162
167
|
|
|
163
|
-
|
|
164
|
-
non-Kiro sessions look identical to the built-in box.
|
|
165
|
-
- **Credits only** (Kiro turns, no dollar cost): a single `N credits` line.
|
|
166
|
-
- **Both** (the session used a dollar-based model AND Kiro in one session): two
|
|
167
|
-
stacked lines, `$X.XX spent` then `N credits`, so neither figure is hidden.
|
|
168
|
+
All you need in `tui.json` is the plugin entry:
|
|
168
169
|
|
|
169
|
-
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"plugin": ["opencode-kiro"]
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
There is no `plugin_enabled` step anymore.
|
|
177
|
+
|
|
178
|
+
### Migrating from 0.2.1 and earlier
|
|
179
|
+
|
|
180
|
+
Older versions replaced the native Context box with a clone and disabled the builtin via:
|
|
170
181
|
|
|
171
182
|
```json
|
|
172
183
|
{
|
|
@@ -174,19 +185,14 @@ Disable the builtin box in `tui.json` so only the replacement renders:
|
|
|
174
185
|
}
|
|
175
186
|
```
|
|
176
187
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
Trade-off: the replacement box applies to **every** session and disabling the builtin
|
|
182
|
-
is global. The replacement reproduces the builtin `$X.XX spent` line for non-Kiro
|
|
183
|
-
sessions (and stacks it above credits when a session used both), so mixed-provider
|
|
184
|
-
users keep dollar cost in the sidebar; if you prefer the original built-in box, leave
|
|
185
|
-
it enabled at the cost of the duplicate box.
|
|
188
|
+
If you upgraded from 0.2.1 or earlier and still have that line in your `tui.json`,
|
|
189
|
+
remove it yourself: the plugin no longer manages `plugin_enabled`. Once the line is
|
|
190
|
+
gone the native Context box returns and shows the usual tokens / context % / cost, and
|
|
191
|
+
the Kiro credits box appears in a separate box right below it.
|
|
186
192
|
|
|
187
193
|
## Known limitation
|
|
188
194
|
|
|
189
|
-
**Credits render in the TUI only.** Two TUI surfaces show them: the sidebar
|
|
195
|
+
**Credits render in the TUI only.** Two TUI surfaces show them: the sidebar credits
|
|
190
196
|
box (above) and the input/prompt meta row chip (`session_prompt_right`), which sits
|
|
191
197
|
above the host's `$` cost chip. Every other cost surface (ACP clients, the web app,
|
|
192
198
|
desktop, web share pages, and CLI cost output) shows $0.00 for Kiro sessions. The
|
|
@@ -225,11 +231,10 @@ would require opencode core changes and is intentionally out of scope for this p
|
|
|
225
231
|
|---|---|
|
|
226
232
|
| `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. |
|
|
227
233
|
| Auth times out after ~120s | Complete the browser login faster, or run `kiro-cli login` yourself, then re-run `opencode auth login` (fast path). |
|
|
228
|
-
| Two "Context" boxes in the sidebar | Add `"plugin_enabled": { "internal:sidebar-context": false }` to `tui.json` (see [Credits in the sidebar](#credits-in-the-sidebar)). |
|
|
229
234
|
| 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`). |
|
|
230
|
-
| Credits
|
|
235
|
+
| 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". |
|
|
231
236
|
| `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)). |
|
|
232
|
-
| `sdk.languageModel is not a function` | A stale `kiro-acp-ai-provider` from before the 2.0.x line resolved from opencode's package cache. Remove the cached copy (`$XDG_CACHE_HOME/opencode/packages/kiro-acp-ai-provider`, default `~/.cache/opencode/packages/...`) and retry; the factory auto-discovery clash was fixed in the 2.0.x line, and this plugin currently pins 2.0.
|
|
237
|
+
| `sdk.languageModel is not a function` | A stale `kiro-acp-ai-provider` from before the 2.0.x line resolved from opencode's package cache. Remove the cached copy (`$XDG_CACHE_HOME/opencode/packages/kiro-acp-ai-provider`, default `~/.cache/opencode/packages/...`) and retry; the factory auto-discovery clash was fixed in the 2.0.x line, and this plugin currently pins 2.1.0. |
|
|
233
238
|
| Path install rejected (`must export id`) | Run `npm run build` in your checkout first and reference the repo root (both entry modules export ids). |
|
|
234
239
|
| Provider visible but runs fail | The provider is selectable (from the catalog) before any credential exists. Run `opencode auth login` first. |
|
|
235
240
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {
|
|
2
|
+
formatCredits,
|
|
3
|
+
sumSessionCredits
|
|
4
|
+
} from "./chunk-MQVMKLNA.js";
|
|
5
|
+
|
|
6
|
+
// src/tui/credits-box-view.ts
|
|
7
|
+
import { createElement, effect, insert, insertNode, setProp } from "@opentui/solid";
|
|
8
|
+
import { createMemo } from "solid-js";
|
|
9
|
+
function createCreditsBoxView(api, sessionID) {
|
|
10
|
+
const theme = () => api.theme.current;
|
|
11
|
+
const messages = createMemo(() => api.state.session.messages(sessionID));
|
|
12
|
+
const credits = createMemo(() => sumSessionCredits(messages(), (messageID) => api.state.part(messageID)));
|
|
13
|
+
const root = createElement("box");
|
|
14
|
+
insertNode(
|
|
15
|
+
root,
|
|
16
|
+
headerLine(theme, () => credits().present ? "Kiro" : "")
|
|
17
|
+
);
|
|
18
|
+
insertNode(
|
|
19
|
+
root,
|
|
20
|
+
mutedLine(theme, () => credits().present ? formatCredits(credits().total, credits().unit) : "")
|
|
21
|
+
);
|
|
22
|
+
return root;
|
|
23
|
+
}
|
|
24
|
+
function headerLine(theme, content) {
|
|
25
|
+
const line = createElement("text");
|
|
26
|
+
effect(() => setProp(line, "fg", theme().text));
|
|
27
|
+
const bold = createElement("b");
|
|
28
|
+
insert(bold, content);
|
|
29
|
+
insertNode(line, bold);
|
|
30
|
+
return line;
|
|
31
|
+
}
|
|
32
|
+
function mutedLine(theme, content) {
|
|
33
|
+
const line = createElement("text");
|
|
34
|
+
effect(() => setProp(line, "fg", theme().textMuted));
|
|
35
|
+
insert(line, content);
|
|
36
|
+
return line;
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
createCreditsBoxView
|
|
40
|
+
};
|
package/dist/server.d.ts
CHANGED
|
@@ -10,10 +10,11 @@ declare function readToken(tokenPath: string | undefined): Promise<{
|
|
|
10
10
|
type: "failed";
|
|
11
11
|
}>;
|
|
12
12
|
declare function notifyIfTokenExpired(client: PluginInput["client"] | undefined): Promise<void>;
|
|
13
|
+
declare function enableSidebarConfig(path: string, input: PluginInput): Promise<void>;
|
|
13
14
|
declare const KiroAuthPlugin: Plugin;
|
|
14
15
|
declare const _default: {
|
|
15
16
|
id: string;
|
|
16
17
|
server: (input: PluginInput) => Promise<Hooks>;
|
|
17
18
|
};
|
|
18
19
|
|
|
19
|
-
export { KiroAuthPlugin, _default as default, kiroTokenPath, notifyIfTokenExpired, readToken };
|
|
20
|
+
export { KiroAuthPlugin, _default as default, enableSidebarConfig, kiroTokenPath, notifyIfTokenExpired, readToken };
|
package/dist/server.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { dirname, join } from "path";
|
|
4
4
|
var KIRO_PLUGIN_NAME = "opencode-kiro";
|
|
5
|
-
var SIDEBAR_PLUGIN_ID = "internal:sidebar-context";
|
|
6
5
|
var server = async (input) => {
|
|
7
6
|
await notifyIfTokenExpired(input.client);
|
|
8
7
|
const tuiPath = tuiConfigPath();
|
|
@@ -175,10 +174,7 @@ async function readTuiConfig(path) {
|
|
|
175
174
|
function isSidebarConfigured(config) {
|
|
176
175
|
if (!config) return false;
|
|
177
176
|
const plugin = config.plugin;
|
|
178
|
-
|
|
179
|
-
const hasPlugin = Array.isArray(plugin) && plugin.includes(KIRO_PLUGIN_NAME);
|
|
180
|
-
const sidebarOff = typeof enabled === "object" && enabled !== null && enabled[SIDEBAR_PLUGIN_ID] === false;
|
|
181
|
-
return hasPlugin && sidebarOff;
|
|
177
|
+
return Array.isArray(plugin) && plugin.includes(KIRO_PLUGIN_NAME);
|
|
182
178
|
}
|
|
183
179
|
async function enableSidebarConfig(path, input) {
|
|
184
180
|
try {
|
|
@@ -205,9 +201,6 @@ async function enableSidebarConfig(path, input) {
|
|
|
205
201
|
const plugin = Array.isArray(config.plugin) ? [...config.plugin] : [];
|
|
206
202
|
if (!plugin.includes(KIRO_PLUGIN_NAME)) plugin.push(KIRO_PLUGIN_NAME);
|
|
207
203
|
config.plugin = plugin;
|
|
208
|
-
const enabled = typeof config.plugin_enabled === "object" && config.plugin_enabled !== null && !Array.isArray(config.plugin_enabled) ? config.plugin_enabled : {};
|
|
209
|
-
enabled[SIDEBAR_PLUGIN_ID] = false;
|
|
210
|
-
config.plugin_enabled = enabled;
|
|
211
204
|
await mkdir(dirname(path), { recursive: true });
|
|
212
205
|
await writeFile(path, JSON.stringify(config, null, 2) + "\n", "utf8");
|
|
213
206
|
try {
|
|
@@ -227,6 +220,7 @@ var server_default = { id: "kiro", server };
|
|
|
227
220
|
export {
|
|
228
221
|
KiroAuthPlugin,
|
|
229
222
|
server_default as default,
|
|
223
|
+
enableSidebarConfig,
|
|
230
224
|
kiroTokenPath,
|
|
231
225
|
notifyIfTokenExpired,
|
|
232
226
|
readToken
|
package/dist/tui.js
CHANGED
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
|
|
10
10
|
// src/tui.ts
|
|
11
11
|
var tui = async (api) => {
|
|
12
|
-
const {
|
|
12
|
+
const { createCreditsBoxView } = await import("./credits-box-view-BYKGQHSS.js");
|
|
13
13
|
const { createCreditsChipView } = await import("./credits-chip-view-RL5JAEZ5.js");
|
|
14
14
|
api.slots.register({
|
|
15
|
-
order:
|
|
15
|
+
order: 150,
|
|
16
16
|
slots: {
|
|
17
17
|
sidebar_content(_ctx, props) {
|
|
18
|
-
return
|
|
18
|
+
return createCreditsBoxView(api, props.session_id);
|
|
19
19
|
},
|
|
20
20
|
session_prompt_right(_ctx, props) {
|
|
21
21
|
return createCreditsChipView(api, props.session_id);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-kiro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "The ACP-compliant Kiro plugin for opencode: auth via the official kiro-cli login, the live Kiro model lineup through the Agent Client Protocol, and TUI credits display",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Nacho F. Lizaur (https://github.com/NachoFLizaur)",
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
spendLines,
|
|
3
|
-
sumSessionCredits
|
|
4
|
-
} from "./chunk-MQVMKLNA.js";
|
|
5
|
-
|
|
6
|
-
// src/tui/context-view.ts
|
|
7
|
-
import { createElement, effect, insert, insertNode, setProp } from "@opentui/solid";
|
|
8
|
-
import { createMemo } from "solid-js";
|
|
9
|
-
function createContextView(api, sessionID) {
|
|
10
|
-
const theme = () => api.theme.current;
|
|
11
|
-
const messages = createMemo(() => api.state.session.messages(sessionID));
|
|
12
|
-
const usage = createMemo(() => {
|
|
13
|
-
const last = messages().findLast(
|
|
14
|
-
(item) => item.role === "assistant" && item.tokens.output > 0
|
|
15
|
-
);
|
|
16
|
-
if (!last) {
|
|
17
|
-
return {
|
|
18
|
-
tokens: 0,
|
|
19
|
-
percent: null
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
const tokens = last.tokens.input + last.tokens.output + last.tokens.reasoning + last.tokens.cache.read + last.tokens.cache.write;
|
|
23
|
-
const model = api.state.provider.find((item) => item.id === last.providerID)?.models[last.modelID];
|
|
24
|
-
return {
|
|
25
|
-
tokens,
|
|
26
|
-
percent: model?.limit.context ? Math.round(tokens / model.limit.context * 100) : null
|
|
27
|
-
};
|
|
28
|
-
});
|
|
29
|
-
const credits = createMemo(() => sumSessionCredits(messages(), (messageID) => api.state.part(messageID)));
|
|
30
|
-
const cost = createMemo(() => api.state.session.get(sessionID)?.cost ?? 0);
|
|
31
|
-
const root = createElement("box");
|
|
32
|
-
insertNode(root, headerLine(theme));
|
|
33
|
-
insertNode(
|
|
34
|
-
root,
|
|
35
|
-
mutedLine(theme, () => `${usage().tokens.toLocaleString()} tokens`)
|
|
36
|
-
);
|
|
37
|
-
insertNode(
|
|
38
|
-
root,
|
|
39
|
-
mutedLine(theme, () => `${usage().percent ?? 0}% used`)
|
|
40
|
-
);
|
|
41
|
-
const costLines = createMemo(() => spendLines({ cost: cost(), credits: credits() }));
|
|
42
|
-
insertNode(
|
|
43
|
-
root,
|
|
44
|
-
mutedLine(theme, () => costLines().join("\n"))
|
|
45
|
-
);
|
|
46
|
-
return root;
|
|
47
|
-
}
|
|
48
|
-
function headerLine(theme) {
|
|
49
|
-
const line = createElement("text");
|
|
50
|
-
effect(() => setProp(line, "fg", theme().text));
|
|
51
|
-
const bold = createElement("b");
|
|
52
|
-
insert(bold, "Context");
|
|
53
|
-
insertNode(line, bold);
|
|
54
|
-
return line;
|
|
55
|
-
}
|
|
56
|
-
function mutedLine(theme, content) {
|
|
57
|
-
const line = createElement("text");
|
|
58
|
-
effect(() => setProp(line, "fg", theme().textMuted));
|
|
59
|
-
insert(line, content);
|
|
60
|
-
return line;
|
|
61
|
-
}
|
|
62
|
-
export {
|
|
63
|
-
createContextView
|
|
64
|
-
};
|