opencode-kiro 0.3.1 → 0.3.3

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/dist/server.js CHANGED
@@ -1,12 +1,10 @@
1
1
  // src/server.ts
2
+ import { readFileSync } from "fs";
2
3
  import { homedir } from "os";
3
4
  import { dirname, join } from "path";
4
5
  var KIRO_PLUGIN_NAME = "opencode-kiro";
5
6
  var server = async (input) => {
6
- await notifyIfTokenExpired(input.client);
7
- const tuiPath = tuiConfigPath();
8
- const alreadyConfigured = isSidebarConfigured(await readTuiConfig(tuiPath));
9
- const prompts = alreadyConfigured ? [] : [
7
+ const prompts = [
10
8
  {
11
9
  type: "select",
12
10
  key: "sidebar",
@@ -20,18 +18,19 @@ var server = async (input) => {
20
18
  return {
21
19
  auth: {
22
20
  provider: "kiro",
23
- // Returned options are forwarded into createKiroAcp({...}). Relays each
24
- // catalog model's limit.context into contextWindows keyed by api.id;
25
- // zero/missing limits are skipped (SDK falls back to 1M).
26
- loader: async (_getAuth, provider) => ({
27
- cwd: input.directory ?? input.worktree,
28
- agent: "opencode",
29
- trustAllTools: true,
30
- mcpTimeout: 45,
31
- contextWindows: Object.fromEntries(
32
- Object.values(provider?.models ?? {}).filter((m) => m.api?.id && (m.limit?.context ?? 0) > 0).map((m) => [m.api.id, m.limit.context])
33
- )
34
- }),
21
+ // options forwarded into createKiroAcp(). maps each model's limit.context into contextWindows by api.id; zero/missing skipped (SDK falls back to 1M).
22
+ loader: async (_getAuth, provider) => {
23
+ void notifyIfTokenExpired(input.client);
24
+ return {
25
+ cwd: input.directory ?? input.worktree,
26
+ agent: "opencode",
27
+ trustAllTools: true,
28
+ mcpTimeout: 45,
29
+ contextWindows: Object.fromEntries(
30
+ Object.values(provider?.models ?? {}).filter((m) => m.api?.id && (m.limit?.context ?? 0) > 0).map((m) => [m.api.id, m.limit.context])
31
+ )
32
+ };
33
+ },
35
34
  methods: [
36
35
  {
37
36
  type: "oauth",
@@ -44,9 +43,8 @@ var server = async (input) => {
44
43
  throw new Error(
45
44
  "kiro-cli is not installed. Install it from https://kiro.dev/docs/cli/"
46
45
  );
47
- const enableSidebar = !alreadyConfigured && inputs?.sidebar === "yes";
48
46
  const onSuccess = async () => {
49
- if (enableSidebar) await enableSidebarConfig(tuiPath, input);
47
+ if (inputs?.sidebar === "yes") await enableSidebarConfig(tuiConfigPath(), input);
50
48
  };
51
49
  if (status.authenticated) {
52
50
  return {
@@ -91,18 +89,18 @@ var server = async (input) => {
91
89
  }
92
90
  ]
93
91
  },
94
- // Ensure a kiro provider entry exists so a stored login plus a kiro-less
95
- // catalog cannot crash opencode (core derefs an undefined provider during
96
- // auth init). Mutates in place; the ??= keeps it idempotent and never
97
- // clobbers a real models.dev kiro entry when one is present.
92
+ // crash guard: core derefs an undefined kiro provider during auth init when a cred exists but the catalog lacks kiro.
93
+ // only inject when authed; ??= is idempotent and won't clobber a real catalog entry.
98
94
  config: async (input2) => {
95
+ if (!hasStoredKiroCredential()) return;
99
96
  input2.provider ??= {};
100
97
  input2.provider.kiro ??= {};
101
98
  },
102
99
  provider: {
103
100
  id: "kiro",
104
- // Inject per-model reasoning-effort variants, consumed as providerOptions.kiro.reasoningEffort.
105
- async models(provider, _ctx) {
101
+ // inject per-model reasoning-effort variants (consumed as providerOptions.kiro.reasoningEffort)
102
+ async models(provider, ctx) {
103
+ if (!ctx.auth) return provider.models;
106
104
  const { reasoningEffortsFor } = await import("kiro-acp-ai-provider");
107
105
  for (const model of Object.values(provider.models)) {
108
106
  const apiId = model.api?.id;
@@ -142,8 +140,7 @@ async function readToken(tokenPath) {
142
140
  // real refresh when present, else ""
143
141
  access: access || "authenticated",
144
142
  // cosmetic; opencode-core only needs presence
145
- // FUTURE expiry, refreshed every startup (server() re-runs each session) so
146
- // opencode-core does not flag a logged-in user as expired. NOT the file value.
143
+ // future expiry, refreshed each startup (server() re-runs per session) so core doesn't flag a logged-in user as expired. not the file value.
147
144
  expires: Date.now() + 8 * 60 * 60 * 1e3
148
145
  };
149
146
  }
@@ -158,19 +155,19 @@ async function notifyIfTokenExpired(client) {
158
155
  } catch {
159
156
  }
160
157
  }
161
- function tuiConfigPath() {
162
- const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
163
- return join(base, "opencode", "tui.json");
164
- }
165
- async function readTuiConfig(path) {
158
+ function hasStoredKiroCredential() {
166
159
  try {
167
- const { readFile } = await import("fs/promises");
168
- const parsed = JSON.parse(await readFile(path, "utf8"));
169
- return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : void 0;
160
+ const path = process.env.XDG_DATA_HOME ? join(process.env.XDG_DATA_HOME, "opencode", "auth.json") : process.platform === "win32" ? join(homedir(), ".opencode", "auth.json") : join(homedir(), ".local", "share", "opencode", "auth.json");
161
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
162
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) && "kiro" in parsed;
170
163
  } catch {
171
- return void 0;
164
+ return false;
172
165
  }
173
166
  }
167
+ function tuiConfigPath() {
168
+ const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
169
+ return join(base, "opencode", "tui.json");
170
+ }
174
171
  function isSidebarConfigured(config) {
175
172
  if (!config) return false;
176
173
  const plugin = config.plugin;
package/dist/tui.d.ts CHANGED
@@ -17,10 +17,8 @@ interface SessionCredits {
17
17
  total: number;
18
18
  unit?: string;
19
19
  /**
20
- * True once any assistant message carried kiro credit metadata. Lets the
21
- * sidebar/footer pick the credits view over the builtin "$X spent" fallback,
22
- * since a credits total of 0 (a real kiro turn) is indistinguishable from
23
- * "no kiro metadata at all" by `total` alone.
20
+ * True once any assistant message carried kiro credit metadata. Lets the view pick credits over the
21
+ * "$X spent" fallback, since a 0-credit kiro turn is indistinguishable from no metadata by `total` alone.
24
22
  */
25
23
  present: boolean;
26
24
  }
@@ -35,14 +33,11 @@ declare function sumSessionCredits(messages: ReadonlyArray<CreditMessage>, parts
35
33
  /** Render credits with the unit, e.g. "12.5 credits", "1 credit". Unit is naively pluralized unless it ends in "s"; with no unit, only the number renders. */
36
34
  declare function formatCredits(value: number, unit?: string): string;
37
35
  /**
38
- * The sidebar's muted cost lines, returned as an ARRAY (one entry per rendered
39
- * muted row). Three display states:
40
- * - BOTH (credits present AND a non-zero dollar cost): TWO stacked lines
41
- * ["$X.XX spent", "N credits"]
42
- * - credits only (credits present, dollar cost 0): ["N credits"] (Kiro-only)
36
+ * Muted cost lines as an array (one per rendered row). Three states:
37
+ * - both (credits present + non-zero cost): ["$X.XX spent", "N credits"]
38
+ * - credits only (cost 0): ["N credits"]
43
39
  * - dollars only (no credits): ["$X.XX spent"] (also ["$0.00 spent"] when empty)
44
- * The matrix keys off `credits.present` (a real 0-credit Kiro turn is present)
45
- * and `cost > 0`, never off `credits.total` alone.
40
+ * Keys off `credits.present` and `cost > 0`, never `credits.total` alone (a 0-credit kiro turn is present).
46
41
  */
47
42
  declare function spendLines(input: {
48
43
  cost: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-kiro",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
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)",