@sunerpy/opencode-kiro-auth 0.13.2 → 0.13.4

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.
@@ -74,14 +74,27 @@ export class RequestHandler {
74
74
  abortFromInbound();
75
75
  else
76
76
  inboundSignal?.addEventListener('abort', abortFromInbound, { once: true });
77
- const timeout = setDeadlineTimeout(() => requestController.abort(new DOMException('Kiro request timed out', 'TimeoutError')), this.config.request_timeout_ms);
77
+ let timeout;
78
+ const beginUpstreamWait = (phase) => {
79
+ if (requestController.signal.aborted)
80
+ return;
81
+ if (timeout)
82
+ clearDeadlineTimeout(timeout);
83
+ timeout = setDeadlineTimeout(() => requestController.abort(new DOMException(`Kiro request timed out waiting for ${phase}`, 'TimeoutError')), this.config.request_timeout_ms);
84
+ };
85
+ const endUpstreamWait = () => {
86
+ if (!timeout)
87
+ return;
88
+ clearDeadlineTimeout(timeout);
89
+ timeout = undefined;
90
+ };
78
91
  let requestCleanupDone = false;
79
92
  let responseOwnsLifecycle = false;
80
93
  const cleanupRequest = () => {
81
94
  if (requestCleanupDone)
82
95
  return;
83
96
  requestCleanupDone = true;
84
- clearDeadlineTimeout(timeout);
97
+ endUpstreamWait();
85
98
  inboundSignal?.removeEventListener('abort', abortFromInbound);
86
99
  };
87
100
  const signal = requestController.signal;
@@ -187,13 +200,22 @@ export class RequestHandler {
187
200
  this.handleSuccessfulRequest(acc);
188
201
  await this.usageTracker.syncUsage(acc, auth, isCurrentAttempt);
189
202
  };
190
- const sdkResponse = await client.send(command, { abortSignal: signal });
203
+ let sdkResponse;
204
+ beginUpstreamWait('SDK response');
205
+ try {
206
+ sdkResponse = await client.send(command, { abortSignal: signal });
207
+ }
208
+ finally {
209
+ endUpstreamWait();
210
+ }
191
211
  sendResolved = true;
192
212
  if (apiTimestamp) {
193
213
  this.logSdkResponse(sdkPrep, apiTimestamp);
194
214
  }
195
215
  const response = await this.responseHandler.handleSdkSuccess(sdkResponse, model, sdkPrep.conversationId, sdkPrep.streaming, {
196
216
  signal,
217
+ onUpstreamWaitStart: () => beginUpstreamWait('stream event'),
218
+ onUpstreamWaitEnd: endUpstreamWait,
197
219
  onComplete: completeRequest,
198
220
  onTerminal: cleanupRequest,
199
221
  onCancel: (reason) => requestController.abort(reason),
@@ -1,6 +1,8 @@
1
1
  import { SdkEventStreamIterationError } from './stream-error.js';
2
2
  export interface SdkResponseLifecycle {
3
3
  signal?: AbortSignal;
4
+ onUpstreamWaitStart?: () => void;
5
+ onUpstreamWaitEnd?: () => void;
4
6
  onComplete?: () => void | Promise<void>;
5
7
  onTerminal?: () => void;
6
8
  onCancel?: (reason: unknown) => void;
@@ -11,7 +11,7 @@ async function closeIterator(iterator) {
11
11
  }
12
12
  catch { }
13
13
  }
14
- function wrapSdkEventStream(sdkResponse, signal) {
14
+ function wrapSdkEventStream(sdkResponse, signal, onUpstreamWaitStart, onUpstreamWaitEnd) {
15
15
  const eventStream = sdkResponse.generateAssistantResponseResponse;
16
16
  if (!eventStream || typeof eventStream[Symbol.asyncIterator] !== 'function') {
17
17
  return { response: sdkResponse, closeRaw: async () => { } };
@@ -25,28 +25,34 @@ function wrapSdkEventStream(sdkResponse, signal) {
25
25
  await closeIterator(rawIterator);
26
26
  };
27
27
  const nextRaw = async () => {
28
- if (!signal)
29
- return rawIterator.next();
30
- if (signal.aborted) {
28
+ if (signal?.aborted) {
31
29
  await closeRaw();
32
30
  throw abortReason(signal);
33
31
  }
34
- return new Promise((resolve, reject) => {
35
- let settled = false;
36
- const settle = (callback) => {
37
- if (settled)
38
- return;
39
- settled = true;
40
- signal.removeEventListener('abort', onAbort);
41
- callback();
42
- };
43
- const onAbort = () => {
44
- void closeRaw();
45
- settle(() => reject(abortReason(signal)));
46
- };
47
- signal.addEventListener('abort', onAbort, { once: true });
48
- Promise.resolve(rawIterator.next()).then((result) => settle(() => resolve(result)), (error) => settle(() => reject(error)));
49
- });
32
+ onUpstreamWaitStart?.();
33
+ try {
34
+ if (!signal)
35
+ return await rawIterator.next();
36
+ return await new Promise((resolve, reject) => {
37
+ let settled = false;
38
+ const settle = (callback) => {
39
+ if (settled)
40
+ return;
41
+ settled = true;
42
+ signal.removeEventListener('abort', onAbort);
43
+ callback();
44
+ };
45
+ const onAbort = () => {
46
+ void closeRaw();
47
+ settle(() => reject(abortReason(signal)));
48
+ };
49
+ signal.addEventListener('abort', onAbort, { once: true });
50
+ Promise.resolve(rawIterator.next()).then((result) => settle(() => resolve(result)), (error) => settle(() => reject(error)));
51
+ });
52
+ }
53
+ finally {
54
+ onUpstreamWaitEnd?.();
55
+ }
50
56
  };
51
57
  const wrappedIterator = {
52
58
  async next() {
@@ -94,7 +100,7 @@ export class ResponseHandler {
94
100
  if (streaming) {
95
101
  return this.handleSdkStreaming(sdkResponse, model, conversationId, lifecycle);
96
102
  }
97
- return this.handleSdkNonStreaming(sdkResponse, model, conversationId, lifecycle.signal);
103
+ return this.handleSdkNonStreaming(sdkResponse, model, conversationId, lifecycle);
98
104
  }
99
105
  async handleStreaming(response, model, conversationId) {
100
106
  const s = transformKiroStream(response, model, conversationId);
@@ -113,7 +119,7 @@ export class ResponseHandler {
113
119
  }), { headers: { 'Content-Type': 'text/event-stream' } });
114
120
  }
115
121
  async handleSdkStreaming(sdkResponse, model, conversationId, lifecycle) {
116
- const wrapped = wrapSdkEventStream(sdkResponse, lifecycle.signal);
122
+ const wrapped = wrapSdkEventStream(sdkResponse, lifecycle.signal, lifecycle.onUpstreamWaitStart, lifecycle.onUpstreamWaitEnd);
117
123
  const transformed = transformSdkStream(wrapped.response, model, conversationId);
118
124
  const buffered = [];
119
125
  let firstSemantic;
@@ -215,14 +221,14 @@ export class ResponseHandler {
215
221
  }
216
222
  }, { highWaterMark: 0 }), { headers: { 'Content-Type': 'text/event-stream' } });
217
223
  }
218
- async handleSdkNonStreaming(sdkResponse, model, conversationId, signal) {
224
+ async handleSdkNonStreaming(sdkResponse, model, conversationId, lifecycle) {
219
225
  // For non-streaming SDK responses, collect all events
220
226
  let content = '';
221
227
  let reasoningContent = '';
222
228
  const toolCalls = [];
223
229
  let inputTokens = 0;
224
230
  let outputTokens = 0;
225
- const wrapped = wrapSdkEventStream(sdkResponse, signal);
231
+ const wrapped = wrapSdkEventStream(sdkResponse, lifecycle.signal, lifecycle.onUpstreamWaitStart, lifecycle.onUpstreamWaitEnd);
226
232
  const eventStream = wrapped.response.generateAssistantResponseResponse;
227
233
  if (eventStream) {
228
234
  try {
@@ -243,7 +249,7 @@ export class ResponseHandler {
243
249
  }
244
250
  }
245
251
  finally {
246
- if (signal?.aborted)
252
+ if (lifecycle.signal?.aborted)
247
253
  await wrapped.closeRaw();
248
254
  }
249
255
  }
@@ -1,10 +1,8 @@
1
1
  interface RetryConfig {
2
2
  max_request_iterations: number;
3
- request_timeout_ms: number;
4
3
  }
5
4
  interface RetryContext {
6
5
  iterations: number;
7
- startTime: number;
8
6
  }
9
7
  export declare class RetryStrategy {
10
8
  private config;
@@ -11,18 +11,11 @@ export class RetryStrategy {
11
11
  error: `Exceeded max iterations (${this.config.max_request_iterations})`
12
12
  };
13
13
  }
14
- if (Date.now() - context.startTime > this.config.request_timeout_ms) {
15
- return {
16
- canContinue: false,
17
- error: 'Request timeout'
18
- };
19
- }
20
14
  return { canContinue: true };
21
15
  }
22
16
  createContext() {
23
17
  return {
24
- iterations: 0,
25
- startTime: Date.now()
18
+ iterations: 0
26
19
  };
27
20
  }
28
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sunerpy/opencode-kiro-auth",
3
- "version": "0.13.2",
3
+ "version": "0.13.4",
4
4
  "description": "OpenCode plugin for AWS Kiro (CodeWhisperer) providing access to Claude models",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",