@zhafron/opencode-kiro-auth 1.0.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.
Files changed (110) hide show
  1. package/README.md +85 -0
  2. package/dist/constants.d.ts +26 -0
  3. package/dist/constants.js +60 -0
  4. package/dist/index.d.ts +3 -0
  5. package/dist/index.js +1 -0
  6. package/dist/kiro/auth.d.ts +5 -0
  7. package/dist/kiro/auth.js +24 -0
  8. package/dist/kiro/oauth-idc.d.ts +24 -0
  9. package/dist/kiro/oauth-idc.js +132 -0
  10. package/dist/kiro/oauth-social.d.ts +17 -0
  11. package/dist/kiro/oauth-social.js +51 -0
  12. package/dist/plugin/accounts.d.ts +28 -0
  13. package/dist/plugin/accounts.js +156 -0
  14. package/dist/plugin/auth-page.d.ts +3 -0
  15. package/dist/plugin/auth-page.js +568 -0
  16. package/dist/plugin/cli.d.ts +6 -0
  17. package/dist/plugin/cli.js +98 -0
  18. package/dist/plugin/config/index.d.ts +3 -0
  19. package/dist/plugin/config/index.js +2 -0
  20. package/dist/plugin/config/loader.d.ts +6 -0
  21. package/dist/plugin/config/loader.js +125 -0
  22. package/dist/plugin/config/schema.d.ts +44 -0
  23. package/dist/plugin/config/schema.js +28 -0
  24. package/dist/plugin/debug.d.ts +2 -0
  25. package/dist/plugin/debug.js +9 -0
  26. package/dist/plugin/errors.d.ts +17 -0
  27. package/dist/plugin/errors.js +34 -0
  28. package/dist/plugin/logger.d.ts +4 -0
  29. package/dist/plugin/logger.js +37 -0
  30. package/dist/plugin/models.d.ts +3 -0
  31. package/dist/plugin/models.js +14 -0
  32. package/dist/plugin/oauth-parser.d.ts +5 -0
  33. package/dist/plugin/oauth-parser.js +23 -0
  34. package/dist/plugin/quota.d.ts +15 -0
  35. package/dist/plugin/quota.js +68 -0
  36. package/dist/plugin/recovery.d.ts +19 -0
  37. package/dist/plugin/recovery.js +302 -0
  38. package/dist/plugin/refresh-queue.d.ts +14 -0
  39. package/dist/plugin/refresh-queue.js +69 -0
  40. package/dist/plugin/request.d.ts +4 -0
  41. package/dist/plugin/request.js +240 -0
  42. package/dist/plugin/response.d.ts +6 -0
  43. package/dist/plugin/response.js +246 -0
  44. package/dist/plugin/server.d.ts +24 -0
  45. package/dist/plugin/server.js +96 -0
  46. package/dist/plugin/storage.d.ts +7 -0
  47. package/dist/plugin/storage.js +75 -0
  48. package/dist/plugin/streaming.d.ts +3 -0
  49. package/dist/plugin/streaming.js +503 -0
  50. package/dist/plugin/token.d.ts +2 -0
  51. package/dist/plugin/token.js +56 -0
  52. package/dist/plugin/types.d.ts +148 -0
  53. package/dist/plugin/types.js +0 -0
  54. package/dist/plugin/usage.d.ts +3 -0
  55. package/dist/plugin/usage.js +36 -0
  56. package/dist/plugin.d.ts +32 -0
  57. package/dist/plugin.js +222 -0
  58. package/dist/src/constants.d.ts +22 -0
  59. package/dist/src/constants.js +35 -0
  60. package/dist/src/kiro/auth.d.ts +5 -0
  61. package/dist/src/kiro/auth.js +69 -0
  62. package/dist/src/kiro/oauth-idc.d.ts +22 -0
  63. package/dist/src/kiro/oauth-idc.js +99 -0
  64. package/dist/src/kiro/oauth-social.d.ts +17 -0
  65. package/dist/src/kiro/oauth-social.js +69 -0
  66. package/dist/src/plugin/accounts.d.ts +23 -0
  67. package/dist/src/plugin/accounts.js +265 -0
  68. package/dist/src/plugin/cli.d.ts +6 -0
  69. package/dist/src/plugin/cli.js +98 -0
  70. package/dist/src/plugin/config/index.d.ts +3 -0
  71. package/dist/src/plugin/config/index.js +2 -0
  72. package/dist/src/plugin/config/loader.d.ts +7 -0
  73. package/dist/src/plugin/config/loader.js +143 -0
  74. package/dist/src/plugin/config/schema.d.ts +68 -0
  75. package/dist/src/plugin/config/schema.js +44 -0
  76. package/dist/src/plugin/debug.d.ts +2 -0
  77. package/dist/src/plugin/debug.js +9 -0
  78. package/dist/src/plugin/errors.d.ts +17 -0
  79. package/dist/src/plugin/errors.js +34 -0
  80. package/dist/src/plugin/logger.d.ts +4 -0
  81. package/dist/src/plugin/logger.js +17 -0
  82. package/dist/src/plugin/models.d.ts +3 -0
  83. package/dist/src/plugin/models.js +14 -0
  84. package/dist/src/plugin/oauth-parser.d.ts +5 -0
  85. package/dist/src/plugin/oauth-parser.js +23 -0
  86. package/dist/src/plugin/quota.d.ts +25 -0
  87. package/dist/src/plugin/quota.js +175 -0
  88. package/dist/src/plugin/recovery.d.ts +19 -0
  89. package/dist/src/plugin/recovery.js +302 -0
  90. package/dist/src/plugin/refresh-queue.d.ts +14 -0
  91. package/dist/src/plugin/refresh-queue.js +69 -0
  92. package/dist/src/plugin/request.d.ts +35 -0
  93. package/dist/src/plugin/request.js +411 -0
  94. package/dist/src/plugin/response.d.ts +6 -0
  95. package/dist/src/plugin/response.js +246 -0
  96. package/dist/src/plugin/server.d.ts +10 -0
  97. package/dist/src/plugin/server.js +203 -0
  98. package/dist/src/plugin/storage.d.ts +5 -0
  99. package/dist/src/plugin/storage.js +106 -0
  100. package/dist/src/plugin/streaming.d.ts +12 -0
  101. package/dist/src/plugin/streaming.js +444 -0
  102. package/dist/src/plugin/token.d.ts +8 -0
  103. package/dist/src/plugin/token.js +130 -0
  104. package/dist/src/plugin/types.d.ts +144 -0
  105. package/dist/src/plugin/types.js +0 -0
  106. package/dist/src/plugin/usage.d.ts +28 -0
  107. package/dist/src/plugin/usage.js +159 -0
  108. package/dist/src/plugin.d.ts +2 -0
  109. package/dist/src/plugin.js +341 -0
  110. package/package.json +57 -0
@@ -0,0 +1,503 @@
1
+ import { parseBracketToolCalls, parseEventLine } from './response';
2
+ const THINKING_START_TAG = '<thinking>';
3
+ const THINKING_END_TAG = '</thinking>';
4
+ export async function* transformKiroStream(response, model, conversationId) {
5
+ const thinkingRequested = true;
6
+ const streamState = {
7
+ thinkingRequested,
8
+ buffer: '',
9
+ inThinking: false,
10
+ thinkingExtracted: false,
11
+ thinkingBlockIndex: null,
12
+ textBlockIndex: null,
13
+ nextBlockIndex: 0,
14
+ stoppedBlocks: new Set()
15
+ };
16
+ if (!response.body) {
17
+ throw new Error('Response body is null');
18
+ }
19
+ const reader = response.body.getReader();
20
+ const decoder = new TextDecoder();
21
+ let rawBuffer = '';
22
+ let totalContent = '';
23
+ let outputTokens = 0;
24
+ let inputTokens = 0;
25
+ let contextUsagePercentage = null;
26
+ const toolCalls = [];
27
+ let currentToolCall = null;
28
+ try {
29
+ while (true) {
30
+ const { done, value } = await reader.read();
31
+ if (done)
32
+ break;
33
+ const chunk = decoder.decode(value, { stream: true });
34
+ rawBuffer += chunk;
35
+ const events = parseStreamBuffer(rawBuffer);
36
+ rawBuffer = events.remaining;
37
+ for (const event of events.events) {
38
+ if (event.type === 'contextUsage' && event.data.contextUsagePercentage) {
39
+ contextUsagePercentage = event.data.contextUsagePercentage;
40
+ }
41
+ else if (event.type === 'content' && event.data) {
42
+ totalContent += event.data;
43
+ if (!thinkingRequested) {
44
+ for (const ev of createTextDeltaEvents(event.data, streamState)) {
45
+ yield convertToOpenAI(ev, conversationId, model);
46
+ }
47
+ continue;
48
+ }
49
+ streamState.buffer += event.data;
50
+ const deltaEvents = [];
51
+ while (streamState.buffer.length > 0) {
52
+ if (!streamState.inThinking && !streamState.thinkingExtracted) {
53
+ const startPos = findRealTag(streamState.buffer, THINKING_START_TAG);
54
+ if (startPos !== -1) {
55
+ const before = streamState.buffer.slice(0, startPos);
56
+ if (before) {
57
+ deltaEvents.push(...createTextDeltaEvents(before, streamState));
58
+ }
59
+ streamState.buffer = streamState.buffer.slice(startPos + THINKING_START_TAG.length);
60
+ streamState.inThinking = true;
61
+ continue;
62
+ }
63
+ const safeLen = Math.max(0, streamState.buffer.length - THINKING_START_TAG.length);
64
+ if (safeLen > 0) {
65
+ const safeText = streamState.buffer.slice(0, safeLen);
66
+ if (safeText) {
67
+ deltaEvents.push(...createTextDeltaEvents(safeText, streamState));
68
+ }
69
+ streamState.buffer = streamState.buffer.slice(safeLen);
70
+ }
71
+ break;
72
+ }
73
+ if (streamState.inThinking) {
74
+ const endPos = findRealTag(streamState.buffer, THINKING_END_TAG);
75
+ if (endPos !== -1) {
76
+ const thinkingPart = streamState.buffer.slice(0, endPos);
77
+ if (thinkingPart) {
78
+ deltaEvents.push(...createThinkingDeltaEvents(thinkingPart, streamState));
79
+ }
80
+ streamState.buffer = streamState.buffer.slice(endPos + THINKING_END_TAG.length);
81
+ streamState.inThinking = false;
82
+ streamState.thinkingExtracted = true;
83
+ deltaEvents.push(...createThinkingDeltaEvents('', streamState));
84
+ deltaEvents.push(...stopBlock(streamState.thinkingBlockIndex, streamState));
85
+ if (streamState.buffer.startsWith('\n\n')) {
86
+ streamState.buffer = streamState.buffer.slice(2);
87
+ }
88
+ continue;
89
+ }
90
+ const safeLen = Math.max(0, streamState.buffer.length - THINKING_END_TAG.length);
91
+ if (safeLen > 0) {
92
+ const safeThinking = streamState.buffer.slice(0, safeLen);
93
+ if (safeThinking) {
94
+ deltaEvents.push(...createThinkingDeltaEvents(safeThinking, streamState));
95
+ }
96
+ streamState.buffer = streamState.buffer.slice(safeLen);
97
+ }
98
+ break;
99
+ }
100
+ if (streamState.thinkingExtracted) {
101
+ const rest = streamState.buffer;
102
+ streamState.buffer = '';
103
+ if (rest) {
104
+ deltaEvents.push(...createTextDeltaEvents(rest, streamState));
105
+ }
106
+ break;
107
+ }
108
+ }
109
+ for (const ev of deltaEvents) {
110
+ yield convertToOpenAI(ev, conversationId, model);
111
+ }
112
+ }
113
+ else if (event.type === 'toolUse') {
114
+ const tc = event.data;
115
+ if (tc.name) {
116
+ totalContent += tc.name;
117
+ }
118
+ if (tc.input) {
119
+ totalContent += tc.input;
120
+ }
121
+ if (tc.name && tc.toolUseId) {
122
+ if (currentToolCall && currentToolCall.toolUseId === tc.toolUseId) {
123
+ currentToolCall.input += tc.input || '';
124
+ }
125
+ else {
126
+ if (currentToolCall) {
127
+ toolCalls.push(currentToolCall);
128
+ }
129
+ currentToolCall = {
130
+ toolUseId: tc.toolUseId,
131
+ name: tc.name,
132
+ input: tc.input || ''
133
+ };
134
+ }
135
+ if (tc.stop && currentToolCall) {
136
+ toolCalls.push(currentToolCall);
137
+ currentToolCall = null;
138
+ }
139
+ }
140
+ }
141
+ else if (event.type === 'toolUseInput') {
142
+ if (event.data.input) {
143
+ totalContent += event.data.input;
144
+ }
145
+ if (currentToolCall) {
146
+ currentToolCall.input += event.data.input || '';
147
+ }
148
+ }
149
+ else if (event.type === 'toolUseStop') {
150
+ if (currentToolCall && event.data.stop) {
151
+ toolCalls.push(currentToolCall);
152
+ currentToolCall = null;
153
+ }
154
+ }
155
+ }
156
+ }
157
+ if (currentToolCall) {
158
+ toolCalls.push(currentToolCall);
159
+ currentToolCall = null;
160
+ }
161
+ if (thinkingRequested && streamState.buffer) {
162
+ if (streamState.inThinking) {
163
+ for (const ev of createThinkingDeltaEvents(streamState.buffer, streamState))
164
+ yield convertToOpenAI(ev, conversationId, model);
165
+ streamState.buffer = '';
166
+ for (const ev of createThinkingDeltaEvents('', streamState))
167
+ yield convertToOpenAI(ev, conversationId, model);
168
+ for (const ev of stopBlock(streamState.thinkingBlockIndex, streamState))
169
+ yield convertToOpenAI(ev, conversationId, model);
170
+ }
171
+ else {
172
+ for (const ev of createTextDeltaEvents(streamState.buffer, streamState))
173
+ yield convertToOpenAI(ev, conversationId, model);
174
+ streamState.buffer = '';
175
+ }
176
+ }
177
+ for (const ev of stopBlock(streamState.textBlockIndex, streamState))
178
+ yield convertToOpenAI(ev, conversationId, model);
179
+ const bracketToolCalls = parseBracketToolCalls(totalContent);
180
+ if (bracketToolCalls.length > 0) {
181
+ for (const btc of bracketToolCalls) {
182
+ toolCalls.push({
183
+ toolUseId: btc.toolUseId,
184
+ name: btc.name,
185
+ input: typeof btc.input === 'string' ? btc.input : JSON.stringify(btc.input)
186
+ });
187
+ }
188
+ }
189
+ if (toolCalls.length > 0) {
190
+ const baseIndex = streamState.nextBlockIndex;
191
+ for (let i = 0; i < toolCalls.length; i++) {
192
+ const tc = toolCalls[i];
193
+ if (!tc)
194
+ continue;
195
+ const blockIndex = baseIndex + i;
196
+ yield convertToOpenAI({
197
+ type: 'content_block_start',
198
+ index: blockIndex,
199
+ content_block: {
200
+ type: 'tool_use',
201
+ id: tc.toolUseId,
202
+ name: tc.name,
203
+ input: {}
204
+ }
205
+ }, conversationId, model);
206
+ let inputJson;
207
+ try {
208
+ const parsed = JSON.parse(tc.input);
209
+ inputJson = JSON.stringify(parsed);
210
+ }
211
+ catch (e) {
212
+ inputJson = tc.input;
213
+ }
214
+ yield convertToOpenAI({
215
+ type: 'content_block_delta',
216
+ index: blockIndex,
217
+ delta: {
218
+ type: 'input_json_delta',
219
+ partial_json: inputJson
220
+ }
221
+ }, conversationId, model);
222
+ yield convertToOpenAI({ type: 'content_block_stop', index: blockIndex }, conversationId, model);
223
+ }
224
+ }
225
+ outputTokens = estimateTokens(totalContent);
226
+ if (contextUsagePercentage !== null && contextUsagePercentage > 0) {
227
+ const totalTokens = Math.round((200000 * contextUsagePercentage) / 100);
228
+ inputTokens = Math.max(0, totalTokens - outputTokens);
229
+ }
230
+ yield convertToOpenAI({
231
+ type: 'message_delta',
232
+ delta: { stop_reason: toolCalls.length > 0 ? 'tool_use' : 'end_turn' },
233
+ usage: {
234
+ input_tokens: inputTokens,
235
+ output_tokens: outputTokens,
236
+ cache_creation_input_tokens: 0,
237
+ cache_read_input_tokens: 0
238
+ }
239
+ }, conversationId, model);
240
+ yield convertToOpenAI({ type: 'message_stop' }, conversationId, model);
241
+ }
242
+ finally {
243
+ reader.releaseLock();
244
+ }
245
+ }
246
+ function convertToOpenAI(event, id, model) {
247
+ const base = {
248
+ id,
249
+ object: 'chat.completion.chunk',
250
+ created: Math.floor(Date.now() / 1000),
251
+ model,
252
+ choices: []
253
+ };
254
+ if (event.type === 'content_block_delta') {
255
+ if (event.delta.type === 'text_delta') {
256
+ base.choices.push({
257
+ index: 0,
258
+ delta: { content: event.delta.text },
259
+ finish_reason: null
260
+ });
261
+ }
262
+ else if (event.delta.type === 'thinking_delta') {
263
+ base.choices.push({
264
+ index: 0,
265
+ delta: { reasoning_content: event.delta.thinking },
266
+ finish_reason: null
267
+ });
268
+ }
269
+ else if (event.delta.type === 'input_json_delta') {
270
+ base.choices.push({
271
+ index: 0,
272
+ delta: {
273
+ tool_calls: [
274
+ {
275
+ index: event.index,
276
+ function: { arguments: event.delta.partial_json }
277
+ }
278
+ ]
279
+ },
280
+ finish_reason: null
281
+ });
282
+ }
283
+ }
284
+ else if (event.type === 'content_block_start' && event.content_block?.type === 'tool_use') {
285
+ base.choices.push({
286
+ index: 0,
287
+ delta: {
288
+ tool_calls: [
289
+ {
290
+ index: event.index,
291
+ id: event.content_block.id,
292
+ type: 'function',
293
+ function: { name: event.content_block.name, arguments: '' }
294
+ }
295
+ ]
296
+ },
297
+ finish_reason: null
298
+ });
299
+ }
300
+ else if (event.type === 'message_delta') {
301
+ base.choices.push({
302
+ index: 0,
303
+ delta: {},
304
+ finish_reason: event.delta.stop_reason === 'tool_use' ? 'tool_calls' : 'stop'
305
+ });
306
+ base.usage = {
307
+ prompt_tokens: event.usage?.input_tokens || 0,
308
+ completion_tokens: event.usage?.output_tokens || 0,
309
+ total_tokens: (event.usage?.input_tokens || 0) + (event.usage?.output_tokens || 0)
310
+ };
311
+ }
312
+ return base;
313
+ }
314
+ function parseStreamBuffer(buffer) {
315
+ const events = [];
316
+ let remaining = buffer;
317
+ let searchStart = 0;
318
+ while (true) {
319
+ const contentStart = remaining.indexOf('{"content":', searchStart);
320
+ const nameStart = remaining.indexOf('{"name":', searchStart);
321
+ const followupStart = remaining.indexOf('{"followupPrompt":', searchStart);
322
+ const inputStart = remaining.indexOf('{"input":', searchStart);
323
+ const stopStart = remaining.indexOf('{"stop":', searchStart);
324
+ const contextUsageStart = remaining.indexOf('{"contextUsagePercentage":', searchStart);
325
+ const candidates = [contentStart, nameStart, followupStart, inputStart, stopStart, contextUsageStart].filter((pos) => pos >= 0);
326
+ if (candidates.length === 0)
327
+ break;
328
+ const jsonStart = Math.min(...candidates);
329
+ if (jsonStart < 0)
330
+ break;
331
+ let braceCount = 0;
332
+ let jsonEnd = -1;
333
+ let inString = false;
334
+ let escapeNext = false;
335
+ for (let i = jsonStart; i < remaining.length; i++) {
336
+ const char = remaining[i];
337
+ if (escapeNext) {
338
+ escapeNext = false;
339
+ continue;
340
+ }
341
+ if (char === '\\') {
342
+ escapeNext = true;
343
+ continue;
344
+ }
345
+ if (char === '"') {
346
+ inString = !inString;
347
+ continue;
348
+ }
349
+ if (!inString) {
350
+ if (char === '{') {
351
+ braceCount++;
352
+ }
353
+ else if (char === '}') {
354
+ braceCount--;
355
+ if (braceCount === 0) {
356
+ jsonEnd = i;
357
+ break;
358
+ }
359
+ }
360
+ }
361
+ }
362
+ if (jsonEnd < 0) {
363
+ remaining = remaining.substring(jsonStart);
364
+ break;
365
+ }
366
+ const jsonStr = remaining.substring(jsonStart, jsonEnd + 1);
367
+ const parsed = parseEventLine(jsonStr);
368
+ if (parsed) {
369
+ if (parsed.content !== undefined && !parsed.followupPrompt) {
370
+ events.push({ type: 'content', data: parsed.content });
371
+ }
372
+ else if (parsed.name && parsed.toolUseId) {
373
+ events.push({
374
+ type: 'toolUse',
375
+ data: {
376
+ name: parsed.name,
377
+ toolUseId: parsed.toolUseId,
378
+ input: parsed.input || '',
379
+ stop: parsed.stop || false
380
+ }
381
+ });
382
+ }
383
+ else if (parsed.input !== undefined && !parsed.name) {
384
+ events.push({
385
+ type: 'toolUseInput',
386
+ data: {
387
+ input: parsed.input
388
+ }
389
+ });
390
+ }
391
+ else if (parsed.stop !== undefined && parsed.contextUsagePercentage === undefined) {
392
+ events.push({
393
+ type: 'toolUseStop',
394
+ data: {
395
+ stop: parsed.stop
396
+ }
397
+ });
398
+ }
399
+ else if (parsed.contextUsagePercentage !== undefined) {
400
+ events.push({
401
+ type: 'contextUsage',
402
+ data: {
403
+ contextUsagePercentage: parsed.contextUsagePercentage
404
+ }
405
+ });
406
+ }
407
+ }
408
+ searchStart = jsonEnd + 1;
409
+ if (searchStart >= remaining.length) {
410
+ remaining = '';
411
+ break;
412
+ }
413
+ }
414
+ if (searchStart > 0 && remaining.length > 0) {
415
+ remaining = remaining.substring(searchStart);
416
+ }
417
+ return { events, remaining };
418
+ }
419
+ function ensureBlockStart(blockType, streamState) {
420
+ if (blockType === 'thinking') {
421
+ if (streamState.thinkingBlockIndex != null)
422
+ return [];
423
+ const idx = streamState.nextBlockIndex++;
424
+ streamState.thinkingBlockIndex = idx;
425
+ return [
426
+ {
427
+ type: 'content_block_start',
428
+ index: idx,
429
+ content_block: { type: 'thinking', thinking: '' }
430
+ }
431
+ ];
432
+ }
433
+ if (blockType === 'text') {
434
+ if (streamState.textBlockIndex != null)
435
+ return [];
436
+ const idx = streamState.nextBlockIndex++;
437
+ streamState.textBlockIndex = idx;
438
+ return [
439
+ {
440
+ type: 'content_block_start',
441
+ index: idx,
442
+ content_block: { type: 'text', text: '' }
443
+ }
444
+ ];
445
+ }
446
+ return [];
447
+ }
448
+ function stopBlock(index, streamState) {
449
+ if (index == null)
450
+ return [];
451
+ if (streamState.stoppedBlocks.has(index))
452
+ return [];
453
+ streamState.stoppedBlocks.add(index);
454
+ return [{ type: 'content_block_stop', index }];
455
+ }
456
+ function createTextDeltaEvents(text, streamState) {
457
+ if (!text)
458
+ return [];
459
+ const events = [];
460
+ events.push(...ensureBlockStart('text', streamState));
461
+ events.push({
462
+ type: 'content_block_delta',
463
+ index: streamState.textBlockIndex,
464
+ delta: { type: 'text_delta', text }
465
+ });
466
+ return events;
467
+ }
468
+ function createThinkingDeltaEvents(thinking, streamState) {
469
+ const events = [];
470
+ events.push(...ensureBlockStart('thinking', streamState));
471
+ events.push({
472
+ type: 'content_block_delta',
473
+ index: streamState.thinkingBlockIndex,
474
+ delta: { type: 'thinking_delta', thinking }
475
+ });
476
+ return events;
477
+ }
478
+ export function findRealTag(buffer, tag) {
479
+ const codeBlockPattern = /```[\s\S]*?```/g;
480
+ const codeBlocks = [];
481
+ let match;
482
+ while ((match = codeBlockPattern.exec(buffer)) !== null) {
483
+ codeBlocks.push([match.index, match.index + match[0].length]);
484
+ }
485
+ let pos = 0;
486
+ while ((pos = buffer.indexOf(tag, pos)) !== -1) {
487
+ let inCodeBlock = false;
488
+ for (const [start, end] of codeBlocks) {
489
+ if (pos >= start && pos < end) {
490
+ inCodeBlock = true;
491
+ break;
492
+ }
493
+ }
494
+ if (!inCodeBlock) {
495
+ return pos;
496
+ }
497
+ pos += tag.length;
498
+ }
499
+ return -1;
500
+ }
501
+ export function estimateTokens(text) {
502
+ return Math.ceil(text.length / 4);
503
+ }
@@ -0,0 +1,2 @@
1
+ import type { KiroAuthDetails } from './types';
2
+ export declare function refreshAccessToken(auth: KiroAuthDetails): Promise<KiroAuthDetails>;
@@ -0,0 +1,56 @@
1
+ import { KiroTokenRefreshError } from './errors';
2
+ import { decodeRefreshToken, encodeRefreshToken } from '../kiro/auth';
3
+ export async function refreshAccessToken(auth) {
4
+ const url = `https://oidc.${auth.region}.amazonaws.com/token`;
5
+ const p = decodeRefreshToken(auth.refresh);
6
+ if (!p.clientId || !p.clientSecret)
7
+ throw new KiroTokenRefreshError('Missing creds', 'MISSING_CREDENTIALS');
8
+ const requestBody = {
9
+ refreshToken: p.refreshToken,
10
+ clientId: p.clientId,
11
+ clientSecret: p.clientSecret,
12
+ grantType: 'refresh_token'
13
+ };
14
+ const res = await fetch(url, {
15
+ method: 'POST',
16
+ headers: {
17
+ 'Content-Type': 'application/json',
18
+ Accept: 'application/json',
19
+ 'amz-sdk-request': 'attempt=1; max=1',
20
+ 'x-amzn-kiro-agent-mode': 'vibe',
21
+ Connection: 'close'
22
+ },
23
+ body: JSON.stringify(requestBody)
24
+ });
25
+ if (!res.ok) {
26
+ const txt = await res.text();
27
+ let data = {};
28
+ try {
29
+ data = JSON.parse(txt);
30
+ }
31
+ catch {
32
+ data = { message: txt };
33
+ }
34
+ throw new KiroTokenRefreshError(`Refresh failed: ${data.message || data.error_description || txt}`, data.error || `HTTP_${res.status}`);
35
+ }
36
+ const d = await res.json();
37
+ const acc = d.access_token || d.accessToken;
38
+ if (!acc)
39
+ throw new KiroTokenRefreshError('No access token', 'INVALID_RESPONSE');
40
+ const upP = {
41
+ refreshToken: d.refresh_token || d.refreshToken || p.refreshToken,
42
+ clientId: p.clientId,
43
+ clientSecret: p.clientSecret,
44
+ authMethod: 'idc'
45
+ };
46
+ return {
47
+ refresh: encodeRefreshToken(upP),
48
+ access: acc,
49
+ expires: Date.now() + (d.expires_in || 3600) * 1000,
50
+ authMethod: 'idc',
51
+ region: auth.region,
52
+ clientId: auth.clientId,
53
+ clientSecret: auth.clientSecret,
54
+ email: auth.email
55
+ };
56
+ }