@goodandready/dsh-subscriptions 0.5.5 → 0.5.6

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.
@@ -108,6 +108,33 @@ export async function discoverLocalCliSessions() {
108
108
  }
109
109
  }
110
110
 
111
+
112
+ // 7. AWS Kiro
113
+ const kiroPaths = [
114
+ homeFile('.kiro', 'credentials.json'),
115
+ homeFile('.aws', 'sso', 'cache', 'kiro-auth-token.json'),
116
+ ]
117
+ for (const p of kiroPaths) {
118
+ const k = await readJson(p)
119
+ if (k && (k.accessToken || k.access_token || k.token)) {
120
+ detected.kiro = {
121
+ provider: 'kiro',
122
+ path: p,
123
+ email: k.email || k.account || 'AWS Kiro User',
124
+ hasRefreshToken: !!(k.refreshToken || k.refresh_token),
125
+ }
126
+ break
127
+ }
128
+ }
129
+ if (!detected.kiro && process.env.KIRO_API_KEY) {
130
+ detected.kiro = {
131
+ provider: 'kiro',
132
+ path: 'KIRO_API_KEY env',
133
+ email: 'AWS Kiro API Key',
134
+ hasRefreshToken: false,
135
+ }
136
+ }
137
+
111
138
  return detected
112
139
  }
113
140
 
@@ -181,5 +208,16 @@ export async function loadLocalCliBlob(provider) {
181
208
  }
182
209
  }
183
210
 
211
+
212
+ if (provider === 'kiro') {
213
+ const token = process.env.KIRO_API_KEY || (raw && (raw.accessToken || raw.access_token || raw.token)) || ''
214
+ return {
215
+ accessToken: token,
216
+ refreshToken: (raw && (raw.refreshToken || raw.refresh_token)) || '',
217
+ expiresAt: (raw && raw.expiresAt) || (Date.now() + 30 * 86400 * 1000),
218
+ email: (raw && raw.email) || 'AWS Kiro User',
219
+ }
220
+ }
221
+
184
222
  throw new Error(`unsupported local CLI import for provider ${provider}`)
185
223
  }
package/lib/refs.js CHANGED
@@ -7,6 +7,7 @@ export const BUILTIN_PROVIDERS = Object.freeze([
7
7
  'kimi',
8
8
  'glm',
9
9
  'cursor',
10
+ 'kiro',
10
11
  ])
11
12
 
12
13
  const dynamicIds = new Set()
@@ -45,6 +46,7 @@ const DISPLAY = {
45
46
  kimi: 'Moonshot Kimi',
46
47
  glm: 'Zhipu GLM',
47
48
  cursor: 'Cursor',
49
+ kiro: 'AWS Kiro',
48
50
  }
49
51
 
50
52
  export function displayName(provider) {
@@ -1,3 +1,4 @@
1
+ import * as kiro from './kiro.js'
1
2
  import * as cursor from './cursor.js'
2
3
  import * as codex from './codex.js'
3
4
  import * as claude from './claude.js'
@@ -7,7 +8,7 @@ import * as kimi from './kimi.js'
7
8
  import * as glm from './glm.js'
8
9
  import { createVendorFromProfile } from '../vendor-factory.js'
9
10
 
10
- const builtins = { codex, claude, grok, antigravity, kimi, glm, cursor }
11
+ const builtins = { codex, claude, grok, antigravity, kimi, glm, cursor, kiro }
11
12
 
12
13
  const customVendors = new Map()
13
14
 
@@ -0,0 +1,116 @@
1
+ import { LlmError } from '@deepseek-ai/dsh-llm'
2
+ import { openaiMessages, openaiTools } from '../messages.js'
3
+ import { openaiChatStream, readJson, httpError } from '../wire.js'
4
+ import { asUsageSnapshot } from '../usage.js'
5
+
6
+ export const id = 'kiro'
7
+
8
+ export const KIRO_PORTAL_URL = 'https://app.kiro.dev'
9
+ export const KIRO_API_BASE = 'https://prod.us-east-1.auth.desktop.kiro.dev'
10
+ export const KIRO_MODELS = [
11
+ {
12
+ id: 'claude-sonnet-5',
13
+ name: 'Claude Sonnet 5 (Kiro)',
14
+ contextWindow: 1000000,
15
+ maxTokens: 64000,
16
+ inputModalities: ['text', 'image'],
17
+ reasoning: { efforts: [{ id: 'off', name: 'Off' }, { id: 'low', name: 'Low' }, { id: 'medium', name: 'Medium' }, { id: 'high', name: 'High' }, { id: 'max', name: 'Max' }] },
18
+ },
19
+ {
20
+ id: 'claude-opus-5',
21
+ name: 'Claude Opus 5 (Kiro)',
22
+ contextWindow: 1000000,
23
+ maxTokens: 64000,
24
+ inputModalities: ['text', 'image'],
25
+ },
26
+ {
27
+ id: 'gpt-5.6-luna',
28
+ name: 'GPT-5.6 Luna (Kiro)',
29
+ contextWindow: 272000,
30
+ maxTokens: 64000,
31
+ inputModalities: ['text', 'image'],
32
+ },
33
+ {
34
+ id: 'claude-sonnet-4.6',
35
+ name: 'Claude Sonnet 4.6 (Kiro)',
36
+ contextWindow: 200000,
37
+ maxTokens: 64000,
38
+ inputModalities: ['text'],
39
+ },
40
+ ]
41
+
42
+ export function providerInfo() {
43
+ return { id, name: 'AWS Kiro' }
44
+ }
45
+
46
+ export function defaults() {
47
+ return {
48
+ apiBase: KIRO_API_BASE,
49
+ models: KIRO_MODELS.map((m) => m.id),
50
+ }
51
+ }
52
+
53
+ export function authorizeUrl() {
54
+ return `${KIRO_PORTAL_URL}/oauth/authorize`
55
+ }
56
+
57
+ export async function listModels() {
58
+ return KIRO_MODELS
59
+ }
60
+
61
+ export async function usage(blob, config, fetchImpl) {
62
+ try {
63
+ const impl = fetchImpl || fetch
64
+ const token = blob && (blob.accessToken || blob.access_token)
65
+ if (!token) return null
66
+ const res = await impl(`${(config && config.apiBase) || KIRO_API_BASE}/api/usage`, {
67
+ headers: {
68
+ Authorization: `Bearer ${token}`,
69
+ Accept: 'application/json',
70
+ },
71
+ })
72
+ if (!res.ok) return null
73
+ const json = await readJson(res)
74
+ if (json && json.usedPercent != null) {
75
+ const snap = asUsageSnapshot(Math.round(json.usedPercent))
76
+ if (snap) snap.plan = json.plan || 'Pro'
77
+ return snap
78
+ }
79
+ return null
80
+ } catch {
81
+ return null
82
+ }
83
+ }
84
+
85
+ export async function* streamOnce({ blob, options, fetchImpl, headers, config, signal }) {
86
+ const impl = fetchImpl || fetch
87
+ const token = blob && (blob.accessToken || blob.access_token)
88
+ if (!token) throw new LlmError('AWS Kiro not authenticated', 'AUTH')
89
+
90
+ const body = {
91
+ model: options.model || 'claude-sonnet-5',
92
+ messages: openaiMessages(options),
93
+ stream: true,
94
+ ...(options.maxTokens != null ? { max_tokens: options.maxTokens } : {}),
95
+ ...(options.temperature != null ? { temperature: options.temperature } : {}),
96
+ }
97
+
98
+ const tools = openaiTools(options)
99
+ if (tools && tools.length) body.tools = tools
100
+
101
+ const url = (config && config.chatUrl) || `${(config && config.apiBase) || KIRO_API_BASE}/v1/chat/completions`
102
+ const res = await impl(url, {
103
+ method: 'POST',
104
+ headers: {
105
+ ...headers,
106
+ Authorization: `Bearer ${token}`,
107
+ 'Content-Type': 'application/json',
108
+ 'User-Agent': 'dsh-plugin-oauth-subs',
109
+ },
110
+ body: JSON.stringify(body),
111
+ signal,
112
+ })
113
+
114
+ if (!res.ok) throw httpError(res.status, await res.text())
115
+ yield* openaiChatStream(res.body)
116
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-subscriptions",
3
- "version": "0.5.5",
3
+ "version": "0.5.6",
4
4
  "description": "Use ChatGPT Codex, Claude, Grok, and Antigravity subscriptions as DeepSeek Harness LLM providers via OAuth.",
5
5
  "license": "MIT",
6
6
  "type": "module",