@bogyie/opencode-kiro-plugin 0.2.2 → 0.2.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/README.md CHANGED
@@ -67,7 +67,7 @@ Supported values:
67
67
 
68
68
  - `auto`: use CodeWhisperer fetch transport when an API key is available; otherwise use CLI chat fallback.
69
69
  - `fetch`: require the direct Kiro/CodeWhisperer fetch path. If no usable auth is available, requests fail with a structured backend/auth error.
70
- - `cli-chat`: call `kiro-cli chat --no-interactive`. This is official and stable, but Kiro CLI does not currently expose a guaranteed per-request model flag.
70
+ - `cli-chat`: call `kiro-cli chat --no-interactive --model <model>`. This is official and stable, and uses the model selected in OpenCode.
71
71
  - `acp`: launch `kiro-cli acp`, initialize a session, optionally set the requested model, send the prompt, and collect `AgentMessageChunk` notifications until `TurnEnd`.
72
72
 
73
73
  `trustAllTools` affects both `cli-chat` and ACP permission handling. In ACP mode, permission requests are rejected by default and allowed only when `trustAllTools: true`.
@@ -12,6 +12,8 @@ export function cliChatArgs(request, options = {}) {
12
12
  return [
13
13
  "chat",
14
14
  "--no-interactive",
15
+ "--model",
16
+ request.modelId,
15
17
  ...(options.trustAllTools ? ["--trust-all-tools"] : []),
16
18
  promptForCli(request),
17
19
  ];
@@ -44,8 +46,12 @@ export class KiroCliChatTransport {
44
46
  const authError = result.stderr.toLowerCase().includes("not logged in");
45
47
  throw new KiroPluginError(result.stderr.trim() || "kiro-cli chat failed", authError ? "KIRO_AUTH_ERROR" : "KIRO_CLI_FAILED", authError ? 401 : 502);
46
48
  }
49
+ const text = sanitizeCliChatOutput(result.stdout);
50
+ if (!text) {
51
+ throw new KiroPluginError(result.stderr.trim() || "kiro-cli chat completed without returning assistant text", "KIRO_EMPTY_RESPONSE", 502);
52
+ }
47
53
  return {
48
- text: sanitizeCliChatOutput(result.stdout),
54
+ text,
49
55
  modelId: request.modelId,
50
56
  };
51
57
  }
@@ -1,4 +1,4 @@
1
- import { errorResponse, UnsupportedBackendError } from "./errors.js";
1
+ import { errorResponse, KiroPluginError, UnsupportedBackendError } from "./errors.js";
2
2
  import { readOpenAIRequest, toKiroGenerateRequest } from "./request-adapter.js";
3
3
  import { toOpenAIChatResponse, toOpenAIChatStreamResponse } from "./response-adapter.js";
4
4
  const unsupportedTransport = {
@@ -6,12 +6,17 @@ const unsupportedTransport = {
6
6
  throw new UnsupportedBackendError();
7
7
  },
8
8
  };
9
- async function* streamGeneratedResponse(transport, request) {
10
- const response = await transport.generate(request);
9
+ function assertNonEmptyResponse(response) {
10
+ if (response.text || response.reasoning || (response.toolCalls?.length ?? 0) > 0)
11
+ return;
12
+ throw new KiroPluginError("Kiro backend returned an empty response.", "KIRO_EMPTY_RESPONSE", 502);
13
+ }
14
+ async function* responseToStream(response, fallbackModelId) {
15
+ assertNonEmptyResponse(response);
11
16
  if (response.reasoning)
12
- yield { type: "reasoning", text: response.reasoning, modelId: response.modelId ?? request.modelId };
17
+ yield { type: "reasoning", text: response.reasoning, modelId: response.modelId ?? fallbackModelId };
13
18
  if (response.text)
14
- yield { type: "text", text: response.text, modelId: response.modelId ?? request.modelId };
19
+ yield { type: "text", text: response.text, modelId: response.modelId ?? fallbackModelId };
15
20
  for (const toolCall of response.toolCalls ?? [])
16
21
  yield toolCall;
17
22
  }
@@ -25,9 +30,12 @@ export function createKiroFetch(options) {
25
30
  return toOpenAIChatStreamResponse(transport.stream(kiroRequest), kiroRequest.modelId);
26
31
  }
27
32
  if (request.stream === true) {
28
- return toOpenAIChatStreamResponse(streamGeneratedResponse(transport, kiroRequest), kiroRequest.modelId);
33
+ const response = await transport.generate(kiroRequest);
34
+ assertNonEmptyResponse(response);
35
+ return toOpenAIChatStreamResponse(responseToStream(response, kiroRequest.modelId), kiroRequest.modelId);
29
36
  }
30
37
  const response = await transport.generate(kiroRequest);
38
+ assertNonEmptyResponse(response);
31
39
  return toOpenAIChatResponse(response, kiroRequest.modelId);
32
40
  }
33
41
  catch (error) {
@@ -1,3 +1,4 @@
1
+ import { KiroPluginError } from "./errors.js";
1
2
  export function toOpenAIChatResponse(response, model) {
2
3
  const toolCalls = response.toolCalls ?? [];
3
4
  return Response.json({
@@ -47,6 +48,7 @@ export function toOpenAIChatStreamResponse(chunks, model) {
47
48
  const toolCallIndexes = new Map();
48
49
  let nextToolCallIndex = 0;
49
50
  let sawToolCall = false;
51
+ let sawDelta = false;
50
52
  for await (const chunk of chunks) {
51
53
  let delta;
52
54
  if (chunk.type === "tool_call") {
@@ -81,6 +83,7 @@ export function toOpenAIChatStreamResponse(chunks, model) {
81
83
  continue;
82
84
  delta = { content: chunk.text };
83
85
  }
86
+ sawDelta = true;
84
87
  controller.enqueue(encoder.encode(sse({
85
88
  id: `kiro-${crypto.randomUUID()}`,
86
89
  object: "chat.completion.chunk",
@@ -95,6 +98,9 @@ export function toOpenAIChatStreamResponse(chunks, model) {
95
98
  ],
96
99
  })));
97
100
  }
101
+ if (!sawDelta) {
102
+ throw new KiroPluginError("Kiro backend returned an empty response stream.", "KIRO_EMPTY_RESPONSE", 502);
103
+ }
98
104
  controller.enqueue(encoder.encode(sse({ choices: [{ index: 0, delta: {}, finish_reason: sawToolCall ? "tool_calls" : "stop" }] })));
99
105
  controller.enqueue(encoder.encode("data: [DONE]\n\n"));
100
106
  controller.close();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bogyie/opencode-kiro-plugin",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "OpenCode plugin for using Kiro as a provider adapter",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",