@miphamai/cli 0.7.3 → 0.7.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@miphamai/cli",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Mipham Code — Multi-model open-core intelligent coding terminal by MiphamAI",
5
5
  "keywords": [
6
6
  "ai",
@@ -101,8 +101,26 @@ export class AnthropicProvider implements ProviderInstance {
101
101
  const decoder = new TextDecoder()
102
102
  let buffer = ''
103
103
 
104
+ // Streaming read timeout: if no data arrives for 90s, abort to prevent UI freeze.
105
+ const STREAM_READ_TIMEOUT_MS = 90_000
106
+
104
107
  while (true) {
105
- const { done, value } = await reader.read()
108
+ let readResult: Awaited<ReturnType<typeof reader.read>>
109
+ try {
110
+ readResult = await Promise.race([
111
+ reader.read(),
112
+ new Promise<never>((_, reject) =>
113
+ setTimeout(
114
+ () => reject(new Error('Stream read timeout — no data for 90s')),
115
+ STREAM_READ_TIMEOUT_MS,
116
+ ),
117
+ ),
118
+ ])
119
+ } catch (err) {
120
+ yield { type: 'error', error: `Stream stalled: ${String(err)}` }
121
+ return
122
+ }
123
+ const { done, value } = readResult
106
124
  if (done) break
107
125
 
108
126
  buffer += decoder.decode(value, { stream: true })
@@ -48,8 +48,27 @@ export class OpenAICompatProvider implements ProviderInstance {
48
48
  const pendingToolCalls = new Map<number, { id: string; name: string; arguments: string }>()
49
49
  let reasoningContent = ''
50
50
 
51
+ // Streaming read timeout: if no data arrives for 90s, abort to prevent UI freeze.
52
+ // DeepSeek V4 thinking mode can take 30-60s between chunks — 90s is a generous ceiling.
53
+ const STREAM_READ_TIMEOUT_MS = 90_000
54
+
51
55
  while (true) {
52
- const { done, value } = await reader.read()
56
+ let readResult: Awaited<ReturnType<typeof reader.read>>
57
+ try {
58
+ readResult = await Promise.race([
59
+ reader.read(),
60
+ new Promise<never>((_, reject) =>
61
+ setTimeout(
62
+ () => reject(new Error('Stream read timeout — no data for 90s')),
63
+ STREAM_READ_TIMEOUT_MS,
64
+ ),
65
+ ),
66
+ ])
67
+ } catch (err) {
68
+ yield { type: 'error', error: `Stream stalled: ${String(err)}` }
69
+ return
70
+ }
71
+ const { done, value } = readResult
53
72
  if (done) break
54
73
 
55
74
  buffer += decoder.decode(value, { stream: true })