@javargasm/opencode-kiro-auth 0.1.0
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 +190 -0
- package/dist/dashboard-stats.d.ts +22 -0
- package/dist/dashboard-stats.d.ts.map +1 -0
- package/dist/dashboard-ui.d.ts +2 -0
- package/dist/dashboard-ui.d.ts.map +1 -0
- package/dist/debug.d.ts +12 -0
- package/dist/debug.d.ts.map +1 -0
- package/dist/event-parser.d.ts +61 -0
- package/dist/event-parser.d.ts.map +1 -0
- package/dist/health.d.ts +6 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3647 -0
- package/dist/kiro-cli-sync.d.ts +16 -0
- package/dist/kiro-cli-sync.d.ts.map +1 -0
- package/dist/kiro-defaults.d.ts +25 -0
- package/dist/kiro-defaults.d.ts.map +1 -0
- package/dist/models.d.ts +104 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/oauth.d.ts +46 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/stream.d.ts +29 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/thinking-parser.d.ts +24 -0
- package/dist/thinking-parser.d.ts.map +1 -0
- package/dist/tokenizer.d.ts +2 -0
- package/dist/tokenizer.d.ts.map +1 -0
- package/dist/transform.d.ts +119 -0
- package/dist/transform.d.ts.map +1 -0
- package/dist/types.d.ts +180 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# opencode-kiro
|
|
2
|
+
|
|
3
|
+
Kiro provider plugin for [OpenCode](https://opencode.ai). Authenticates via AWS Builder ID or IAM Identity Center and exposes all Kiro models through an Anthropic-compatible local gateway.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **AWS Builder ID / IAM Identity Center** — OAuth device-code login with automatic token refresh
|
|
8
|
+
- **Dynamic model discovery** — fetches available models from the Kiro API at runtime; falls back to a curated static catalog
|
|
9
|
+
- **Local Anthropic gateway** — translates Anthropic Messages API requests to Kiro's CodeWhisperer streaming protocol
|
|
10
|
+
- **Adaptive thinking** — maps reasoning effort levels (`low` → `max`) through the `output_config.effort` parameter
|
|
11
|
+
- **Multi-region** — supports `us-east-1` and `eu-central-1` Kiro API regions with automatic SSO region mapping
|
|
12
|
+
- **Zero external dependencies** — self-contained plugin; no runtime deps beyond the OpenCode SDK
|
|
13
|
+
|
|
14
|
+
## Supported Models
|
|
15
|
+
|
|
16
|
+
| Model | Reasoning | Context | Effort Levels |
|
|
17
|
+
|:---|:---:|:---:|:---|
|
|
18
|
+
| Claude Fable 5 | ✅ | 1M | low, medium, high, xhigh, max |
|
|
19
|
+
| Claude Opus 4.8 | ✅ | 1M | low, medium, high, xhigh, max |
|
|
20
|
+
| Claude Opus 4.7 | ✅ | 1M | low, medium, high, xhigh, max |
|
|
21
|
+
| Claude Opus 4.6 | ✅ | 1M | low, medium, high, max |
|
|
22
|
+
| Claude Sonnet 4.6 | ✅ | 1M | low, medium, high, max |
|
|
23
|
+
| Claude Opus 4.5 | ✅ | 200K | — |
|
|
24
|
+
| Claude Sonnet 4.5 | ✅ | 200K | — |
|
|
25
|
+
| Claude Sonnet 4 | ✅ | 200K | — |
|
|
26
|
+
| Claude Haiku 4.5 | ❌ | 200K | — |
|
|
27
|
+
| DeepSeek 3.2 | ✅ | 128K | — |
|
|
28
|
+
| Kimi K2.5 | ✅ | 200K | — |
|
|
29
|
+
| MiniMax M2.1 / M2.5 | ❌ | 196K | — |
|
|
30
|
+
| GLM 4.7 / 4.7 Flash | ✅/❌ | 128K | — |
|
|
31
|
+
| Qwen3 Coder Next | ✅ | 256K | — |
|
|
32
|
+
| Qwen3 Coder 480B | ✅ | 128K | — |
|
|
33
|
+
| AGI Nova Beta | ✅ | 1M | — |
|
|
34
|
+
|
|
35
|
+
> Models without effort levels listed use Kiro's default reasoning behavior. Additional models may appear dynamically via the `ListAvailableModels` API.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
### From npm (recommended)
|
|
40
|
+
|
|
41
|
+
Add the plugin to your `opencode.json`:
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{
|
|
45
|
+
"$schema": "https://opencode.ai/config.json",
|
|
46
|
+
"plugin": [
|
|
47
|
+
"opencode-kiro"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
OpenCode will auto-install the package on startup.
|
|
53
|
+
|
|
54
|
+
### From local source
|
|
55
|
+
|
|
56
|
+
1. Clone the repository:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/your-org/opencode-kiro.git
|
|
60
|
+
cd opencode-kiro
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
2. Install dependencies and build:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
bun install
|
|
67
|
+
bun run build
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
3. Register the plugin in your `opencode.json` using the absolute path to the built entry point:
|
|
71
|
+
|
|
72
|
+
```json
|
|
73
|
+
{
|
|
74
|
+
"$schema": "https://opencode.ai/config.json",
|
|
75
|
+
"plugin": [
|
|
76
|
+
"/absolute/path/to/opencode-kiro/dist/index.js"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Authentication
|
|
82
|
+
|
|
83
|
+
Once the plugin is loaded, authenticate through the OpenCode TUI:
|
|
84
|
+
|
|
85
|
+
1. Run `/connect` inside OpenCode
|
|
86
|
+
2. Select **Kiro (Builder ID / IAM Identity Center)**
|
|
87
|
+
3. Choose your login method:
|
|
88
|
+
- **Builder ID** — press Enter at the SSO URL prompt (default)
|
|
89
|
+
- **IAM Identity Center** — enter your organization's SSO Start URL (e.g. `https://mycompany.awsapps.com/start`) and optionally the SSO region
|
|
90
|
+
4. Complete the browser-based authorization using the provided verification code
|
|
91
|
+
5. Tokens are stored securely and refreshed automatically
|
|
92
|
+
|
|
93
|
+
## Usage
|
|
94
|
+
|
|
95
|
+
After authentication, select any Kiro model in the OpenCode model picker. The plugin:
|
|
96
|
+
|
|
97
|
+
1. Starts a local Anthropic-compatible gateway on a random port
|
|
98
|
+
2. Registers all available models as OpenCode provider entries
|
|
99
|
+
3. Routes requests through `@ai-sdk/anthropic` → local gateway → Kiro CodeWhisperer API
|
|
100
|
+
|
|
101
|
+
### Selecting a model
|
|
102
|
+
|
|
103
|
+
Use the model picker in the OpenCode TUI or set a default in your `opencode.json`:
|
|
104
|
+
|
|
105
|
+
```json
|
|
106
|
+
{
|
|
107
|
+
"model": "kiro/claude-opus-4-7"
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Reasoning effort
|
|
112
|
+
|
|
113
|
+
Models that support adaptive thinking accept effort levels through OpenCode's reasoning configuration. The plugin passes them 1:1 to Kiro's `output_config.effort` parameter:
|
|
114
|
+
|
|
115
|
+
- `low` — speed/cost optimized
|
|
116
|
+
- `medium` — balanced general-purpose
|
|
117
|
+
- `high` — default, best balance
|
|
118
|
+
- `xhigh` — complex multi-step tasks (Fable 5, Opus 4.7, 4.8)
|
|
119
|
+
- `max` — maximum reasoning depth (Fable 5, Opus 4.7, 4.8)
|
|
120
|
+
|
|
121
|
+
Not all models support every level — see the model table above for supported efforts per model.
|
|
122
|
+
|
|
123
|
+
## Development
|
|
124
|
+
|
|
125
|
+
### Prerequisites
|
|
126
|
+
|
|
127
|
+
- [Bun](https://bun.sh) ≥ 1.0
|
|
128
|
+
- TypeScript ≥ 5.0
|
|
129
|
+
|
|
130
|
+
### Commands
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
# Type-check + run tests
|
|
134
|
+
bun run check
|
|
135
|
+
|
|
136
|
+
# Type-check only
|
|
137
|
+
bun run typecheck
|
|
138
|
+
|
|
139
|
+
# Run tests
|
|
140
|
+
bun test
|
|
141
|
+
|
|
142
|
+
# Run tests in watch mode
|
|
143
|
+
bun test --watch
|
|
144
|
+
|
|
145
|
+
# Build for distribution
|
|
146
|
+
bun run build
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Project Structure
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
src/
|
|
153
|
+
├── index.ts # Plugin entry: auth hooks, model registration, gateway lifecycle
|
|
154
|
+
├── types.ts # Local type definitions and runtime utilities
|
|
155
|
+
├── server.ts # Bun.serve Anthropic gateway (Messages API → Kiro SSE)
|
|
156
|
+
├── stream.ts # Kiro streaming orchestrator (request build, retry, event parsing)
|
|
157
|
+
├── models.ts # Model catalog, region mapping, dynamic model discovery
|
|
158
|
+
├── oauth.ts # OIDC device-code auth (Builder ID + Identity Center)
|
|
159
|
+
├── transform.ts # Message format conversion (OpenCode ↔ Kiro wire format)
|
|
160
|
+
├── thinking-parser.ts # Streaming <thinking> tag parser for inline reasoning
|
|
161
|
+
├── event-parser.ts # Kiro JSON event stream parser
|
|
162
|
+
├── kiro-defaults.ts # Static protocol constants (system seed, tool schemas)
|
|
163
|
+
├── health.ts # Permanent error classification
|
|
164
|
+
├── tokenizer.ts # Lightweight token estimation
|
|
165
|
+
└── debug.ts # Structured logging
|
|
166
|
+
test/
|
|
167
|
+
└── gateway.test.ts # Gateway integration tests (health, auth, streaming, non-streaming)
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Architecture
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
┌──────────────┐ ┌─────────────────────┐ ┌──────────────────┐
|
|
174
|
+
│ OpenCode │────▶│ Local Gateway │────▶│ Kiro API │
|
|
175
|
+
│ (@ai-sdk/ │ │ (Bun.serve) │ │ (CodeWhisperer │
|
|
176
|
+
│ anthropic) │◀────│ │◀────│ Streaming) │
|
|
177
|
+
│ │ SSE │ POST /v1/messages │ │ │
|
|
178
|
+
└──────────────┘ └─────────────────────┘ └──────────────────┘
|
|
179
|
+
▲
|
|
180
|
+
│ Translates:
|
|
181
|
+
│ • Anthropic Messages → Kiro request body
|
|
182
|
+
│ • Kiro JSON events → Anthropic SSE events
|
|
183
|
+
│ • Handles retry, capacity, context truncation
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
The gateway runs on `127.0.0.1` on a random port. It accepts standard Anthropic Messages API requests and translates them bidirectionally to Kiro's proprietary CodeWhisperer streaming protocol.
|
|
187
|
+
|
|
188
|
+
## License
|
|
189
|
+
|
|
190
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface RequestMetrics {
|
|
2
|
+
id: string;
|
|
3
|
+
timestamp: number;
|
|
4
|
+
model: string;
|
|
5
|
+
inputTokens: number;
|
|
6
|
+
outputTokens: number;
|
|
7
|
+
credits: number;
|
|
8
|
+
stream: boolean;
|
|
9
|
+
}
|
|
10
|
+
declare class DashboardStats {
|
|
11
|
+
private requests;
|
|
12
|
+
recordRequest(metrics: Omit<RequestMetrics, "timestamp">): void;
|
|
13
|
+
getStats(): {
|
|
14
|
+
totalRequests: number;
|
|
15
|
+
totalTokens: number;
|
|
16
|
+
totalCredits: number;
|
|
17
|
+
requests: RequestMetrics[];
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export declare const stats: DashboardStats;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=dashboard-stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-stats.d.ts","sourceRoot":"","sources":["../src/dashboard-stats.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;CACjB;AAID,cAAM,cAAc;IAClB,OAAO,CAAC,QAAQ,CAAwB;IAExC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC;IAOxD,QAAQ;;;;;;CAYT;AAED,eAAO,MAAM,KAAK,gBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-ui.d.ts","sourceRoot":"","sources":["../src/dashboard-ui.ts"],"names":[],"mappings":"AAAA,wBAAgB,gBAAgB,IAAI,MAAM,CA8TzC"}
|
package/dist/debug.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type LogLevel = "error" | "warn" | "info" | "debug";
|
|
2
|
+
export declare const log: {
|
|
3
|
+
error: (msg: string, data?: unknown) => void;
|
|
4
|
+
warn: (msg: string, data?: unknown) => void;
|
|
5
|
+
info: (msg: string, data?: unknown) => void;
|
|
6
|
+
debug: (msg: string, data?: unknown) => void;
|
|
7
|
+
/** True when the current threshold includes `debug`. Use to avoid
|
|
8
|
+
* expensive serialization of payloads we won't log. */
|
|
9
|
+
isDebug: () => boolean;
|
|
10
|
+
};
|
|
11
|
+
export declare function previewChunk(s: string): string;
|
|
12
|
+
//# sourceMappingURL=debug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.d.ts","sourceRoot":"","sources":["../src/debug.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAgF3D,eAAO,MAAM,GAAG;iBACD,MAAM,SAAS,OAAO;gBACvB,MAAM,SAAS,OAAO;gBACtB,MAAM,SAAS,OAAO;iBACrB,MAAM,SAAS,OAAO;IACnC;4DACwD;;CAEzD,CAAC;AAWF,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAa9C"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type KiroStreamEvent = {
|
|
2
|
+
type: "content";
|
|
3
|
+
data: string;
|
|
4
|
+
} | {
|
|
5
|
+
type: "toolUse";
|
|
6
|
+
data: {
|
|
7
|
+
name: string;
|
|
8
|
+
toolUseId: string;
|
|
9
|
+
input: string;
|
|
10
|
+
stop?: boolean;
|
|
11
|
+
};
|
|
12
|
+
} | {
|
|
13
|
+
type: "toolUseInput";
|
|
14
|
+
data: {
|
|
15
|
+
input: string;
|
|
16
|
+
};
|
|
17
|
+
} | {
|
|
18
|
+
type: "toolUseStop";
|
|
19
|
+
data: {
|
|
20
|
+
stop: boolean;
|
|
21
|
+
};
|
|
22
|
+
} | {
|
|
23
|
+
type: "contextUsage";
|
|
24
|
+
data: {
|
|
25
|
+
contextUsagePercentage: number;
|
|
26
|
+
};
|
|
27
|
+
} | {
|
|
28
|
+
type: "reasoning";
|
|
29
|
+
data: {
|
|
30
|
+
text: string;
|
|
31
|
+
signature?: string;
|
|
32
|
+
};
|
|
33
|
+
} | {
|
|
34
|
+
type: "followupPrompt";
|
|
35
|
+
data: string;
|
|
36
|
+
} | {
|
|
37
|
+
type: "usage";
|
|
38
|
+
data: {
|
|
39
|
+
inputTokens?: number;
|
|
40
|
+
outputTokens?: number;
|
|
41
|
+
};
|
|
42
|
+
} | {
|
|
43
|
+
type: "error";
|
|
44
|
+
data: {
|
|
45
|
+
error: string;
|
|
46
|
+
message?: string;
|
|
47
|
+
};
|
|
48
|
+
} | {
|
|
49
|
+
type: "metering";
|
|
50
|
+
data: {
|
|
51
|
+
usage: number;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
/** Find the matching `}` for the `{` at `start`. Returns -1 if incomplete. */
|
|
55
|
+
export declare function findJsonEnd(text: string, start: number): number;
|
|
56
|
+
export declare function parseKiroEventMulti(parsed: Record<string, unknown>): KiroStreamEvent[];
|
|
57
|
+
export declare function parseKiroEvents(buffer: string): {
|
|
58
|
+
events: KiroStreamEvent[];
|
|
59
|
+
remaining: string;
|
|
60
|
+
};
|
|
61
|
+
//# sourceMappingURL=event-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-parser.d.ts","sourceRoot":"","sources":["../src/event-parser.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GAC7F;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE;QAAE,sBAAsB,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACjE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAElD,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA2B/D;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,EAAE,CAqItF;AAoCD,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,GACb;IAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAqElD"}
|
package/dist/health.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../src/health.ts"],"names":[],"mappings":"AAiBA;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAGzD"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,qBAAqB,CAAC;AAoBvE,eAAO,MAAM,UAAU,EAAE,MAiUxB,CAAC;;;;;AAEF,wBAGyB"}
|