@bogyie/opencode-kiro-plugin 0.1.0 → 0.2.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/CHANGELOG.md +1 -0
- package/README.md +13 -5
- package/dist/fetch-adapter.js +2 -0
- package/dist/index.d.ts +1 -1
- package/dist/kiro-transport.js +18 -0
- package/dist/response-adapter.d.ts +7 -1
- package/dist/response-adapter.js +6 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,7 @@ Initial OpenCode Kiro provider plugin implementation.
|
|
|
15
15
|
- OpenAI-compatible request adapter for system prompts, chat history, multimodal data URL images/documents, tool specs, and tool results.
|
|
16
16
|
- OpenAI-compatible generation options for temperature, token limit, and reasoning/thinking effort are preserved as best-effort model request fields in direct fetch mode.
|
|
17
17
|
- CodeWhisperer metadata token usage is mapped to OpenAI-compatible non-streaming usage fields on a best-effort basis.
|
|
18
|
+
- CodeWhisperer reasoning content is preserved separately from assistant text as OpenAI-compatible `reasoning_content`.
|
|
18
19
|
- CodeWhisperer/Kiro transport with streaming text, tool-call deltas, configurable retry attempts, and request timeout.
|
|
19
20
|
- CLI fallback using `kiro-cli chat --no-interactive`.
|
|
20
21
|
- CLI fallback responses are wrapped as OpenAI-compatible SSE for streaming OpenCode calls and sanitized to remove terminal prompt/credits output.
|
package/README.md
CHANGED
|
@@ -155,6 +155,9 @@ Direct fetch mode uses AWS SDK standard retry behavior. Tune `maxAttempts` and `
|
|
|
155
155
|
|
|
156
156
|
OpenAI-compatible `temperature`, `max_tokens`, `max_completion_tokens`, `reasoning_effort`, `reasoning.effort`, and `thinking.effort` are preserved for direct fetch mode through Kiro's `additionalModelRequestFields` path on a best-effort basis.
|
|
157
157
|
|
|
158
|
+
When Kiro emits token metadata in direct fetch mode, non-streaming responses map it to OpenAI-compatible `usage` fields.
|
|
159
|
+
When Kiro emits reasoning text, it is preserved separately from assistant text as `reasoning_content`.
|
|
160
|
+
|
|
158
161
|
For local checks:
|
|
159
162
|
|
|
160
163
|
```sh
|
|
@@ -167,13 +170,18 @@ For real Kiro/OpenCode validation, use [docs/e2e-validation.md](docs/e2e-validat
|
|
|
167
170
|
|
|
168
171
|
## Release
|
|
169
172
|
|
|
170
|
-
|
|
173
|
+
The npm package is published through npm Trusted Publishing with the GitHub Actions environment named `npm`. No `NPM_TOKEN` repository secret is required.
|
|
174
|
+
|
|
175
|
+
Configure the npm package trusted publisher to use:
|
|
176
|
+
|
|
177
|
+
- repository owner: `bogyie`
|
|
178
|
+
- repository name: `opencode-kiro-plugin`
|
|
179
|
+
- workflow filename: `npm-publish.yml`
|
|
180
|
+
- environment name: `npm`
|
|
171
181
|
|
|
172
|
-
|
|
173
|
-
2. Update `package.json` and `package-lock.json` to the release version.
|
|
174
|
-
3. Create and publish a GitHub Release whose tag matches the package version, for example `v0.1.0`.
|
|
182
|
+
To publish a new version, update `package.json` and `package-lock.json` to the release version and merge the change to `main`. `package.json.version` is the source of truth: when it changes on `main`, the `Publish npm package` workflow publishes that package version to npm and creates the matching GitHub Release tag, for example `v0.1.0`.
|
|
175
183
|
|
|
176
|
-
The
|
|
184
|
+
The workflow runs tests, typecheck, package smoke validation, `npm pack --dry-run`, and then `npm publish --access public`.
|
|
177
185
|
|
|
178
186
|
## License And References
|
|
179
187
|
|
package/dist/fetch-adapter.js
CHANGED
|
@@ -8,6 +8,8 @@ const unsupportedTransport = {
|
|
|
8
8
|
};
|
|
9
9
|
async function* streamGeneratedResponse(transport, request) {
|
|
10
10
|
const response = await transport.generate(request);
|
|
11
|
+
if (response.reasoning)
|
|
12
|
+
yield { type: "reasoning", text: response.reasoning, modelId: response.modelId ?? request.modelId };
|
|
11
13
|
if (response.text)
|
|
12
14
|
yield { type: "text", text: response.text, modelId: response.modelId ?? request.modelId };
|
|
13
15
|
for (const toolCall of response.toolCalls ?? [])
|
package/dist/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export { FALLBACK_MODELS } from "./models.js";
|
|
|
16
16
|
export { toKiroGenerateRequest } from "./request-adapter.js";
|
|
17
17
|
export type { KiroGenerateRequest, KiroModelOptions } from "./request-adapter.js";
|
|
18
18
|
export { toOpenAIChatResponse, toOpenAIChatStreamResponse } from "./response-adapter.js";
|
|
19
|
-
export type { KiroStreamEvent, KiroToolCallChunk } from "./response-adapter.js";
|
|
19
|
+
export type { KiroReasoningChunk, KiroStreamEvent, KiroToolCallChunk } from "./response-adapter.js";
|
|
20
20
|
declare const _default: {
|
|
21
21
|
id: string;
|
|
22
22
|
server: import("@opencode-ai/plugin").Plugin;
|
package/dist/kiro-transport.js
CHANGED
|
@@ -135,6 +135,7 @@ export async function collectAssistantText(stream) {
|
|
|
135
135
|
if (!stream)
|
|
136
136
|
return { text: "" };
|
|
137
137
|
let text = "";
|
|
138
|
+
let reasoning = "";
|
|
138
139
|
let modelId;
|
|
139
140
|
let usage;
|
|
140
141
|
for await (const event of stream) {
|
|
@@ -142,6 +143,9 @@ export async function collectAssistantText(stream) {
|
|
|
142
143
|
text += event.assistantResponseEvent.content ?? "";
|
|
143
144
|
modelId = event.assistantResponseEvent.modelId ?? modelId;
|
|
144
145
|
}
|
|
146
|
+
if (event.reasoningContentEvent?.text) {
|
|
147
|
+
reasoning += event.reasoningContentEvent.text;
|
|
148
|
+
}
|
|
145
149
|
usage = usageFromMetadataEvent(event) ?? usage;
|
|
146
150
|
if (event.error) {
|
|
147
151
|
throw new Error(event.error.message ?? "Kiro stream returned an error event");
|
|
@@ -149,6 +153,7 @@ export async function collectAssistantText(stream) {
|
|
|
149
153
|
}
|
|
150
154
|
return {
|
|
151
155
|
text,
|
|
156
|
+
...(reasoning ? { reasoning } : {}),
|
|
152
157
|
...(modelId ? { modelId } : {}),
|
|
153
158
|
...(usage ? { usage } : {}),
|
|
154
159
|
};
|
|
@@ -165,6 +170,12 @@ export async function* streamAssistantText(stream) {
|
|
|
165
170
|
...(event.assistantResponseEvent.modelId ? { modelId: event.assistantResponseEvent.modelId } : {}),
|
|
166
171
|
};
|
|
167
172
|
}
|
|
173
|
+
if (event.reasoningContentEvent?.text) {
|
|
174
|
+
yield {
|
|
175
|
+
type: "reasoning",
|
|
176
|
+
text: event.reasoningContentEvent.text,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
168
179
|
if (event.toolUseEvent?.toolUseId && event.toolUseEvent.name) {
|
|
169
180
|
const id = event.toolUseEvent.toolUseId;
|
|
170
181
|
const current = toolInputs.get(id) ?? { name: event.toolUseEvent.name, input: "" };
|
|
@@ -196,6 +207,7 @@ export async function* streamAssistantText(stream) {
|
|
|
196
207
|
}
|
|
197
208
|
async function collectChunks(chunks, fallbackModelId) {
|
|
198
209
|
let text = "";
|
|
210
|
+
let reasoning = "";
|
|
199
211
|
let modelId;
|
|
200
212
|
let usage;
|
|
201
213
|
const toolCalls = [];
|
|
@@ -205,6 +217,11 @@ async function collectChunks(chunks, fallbackModelId) {
|
|
|
205
217
|
modelId = chunk.modelId ?? modelId;
|
|
206
218
|
continue;
|
|
207
219
|
}
|
|
220
|
+
if (chunk.type === "reasoning") {
|
|
221
|
+
reasoning += chunk.text;
|
|
222
|
+
modelId = chunk.modelId ?? modelId;
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
208
225
|
text += chunk.text;
|
|
209
226
|
modelId = chunk.modelId ?? modelId;
|
|
210
227
|
if (chunk.usage)
|
|
@@ -212,6 +229,7 @@ async function collectChunks(chunks, fallbackModelId) {
|
|
|
212
229
|
}
|
|
213
230
|
return {
|
|
214
231
|
text,
|
|
232
|
+
...(reasoning ? { reasoning } : {}),
|
|
215
233
|
modelId: modelId ?? fallbackModelId,
|
|
216
234
|
...(toolCalls.length > 0 ? { toolCalls } : {}),
|
|
217
235
|
...(usage ? { usage } : {}),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export interface KiroGenerateResponse {
|
|
2
2
|
readonly text: string;
|
|
3
|
+
readonly reasoning?: string;
|
|
3
4
|
readonly modelId?: string;
|
|
4
5
|
readonly toolCalls?: ReadonlyArray<KiroToolCallChunk>;
|
|
5
6
|
readonly usage?: {
|
|
@@ -20,6 +21,11 @@ export interface KiroToolCallChunk {
|
|
|
20
21
|
readonly arguments: string;
|
|
21
22
|
readonly modelId?: string;
|
|
22
23
|
}
|
|
23
|
-
export
|
|
24
|
+
export interface KiroReasoningChunk {
|
|
25
|
+
readonly type: "reasoning";
|
|
26
|
+
readonly text: string;
|
|
27
|
+
readonly modelId?: string;
|
|
28
|
+
}
|
|
29
|
+
export type KiroStreamEvent = KiroStreamChunk | KiroToolCallChunk | KiroReasoningChunk;
|
|
24
30
|
export declare function toOpenAIChatResponse(response: KiroGenerateResponse, model: string): Response;
|
|
25
31
|
export declare function toOpenAIChatStreamResponse(chunks: AsyncIterable<KiroStreamEvent>, model: string): Response;
|
package/dist/response-adapter.js
CHANGED
|
@@ -11,6 +11,7 @@ export function toOpenAIChatResponse(response, model) {
|
|
|
11
11
|
message: {
|
|
12
12
|
role: "assistant",
|
|
13
13
|
content: toolCalls.length > 0 ? response.text || null : response.text,
|
|
14
|
+
...(response.reasoning ? { reasoning_content: response.reasoning } : {}),
|
|
14
15
|
...(toolCalls.length > 0
|
|
15
16
|
? {
|
|
16
17
|
tool_calls: toolCalls.map((toolCall, index) => ({
|
|
@@ -70,6 +71,11 @@ export function toOpenAIChatStreamResponse(chunks, model) {
|
|
|
70
71
|
],
|
|
71
72
|
};
|
|
72
73
|
}
|
|
74
|
+
else if (chunk.type === "reasoning") {
|
|
75
|
+
if (!chunk.text)
|
|
76
|
+
continue;
|
|
77
|
+
delta = { reasoning_content: chunk.text };
|
|
78
|
+
}
|
|
73
79
|
else {
|
|
74
80
|
if (!chunk.text)
|
|
75
81
|
continue;
|