@ynhcj/xiaoyi-channel 0.0.62-next → 0.0.63-next

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.
@@ -114,7 +114,7 @@ function createRetryingStream(createStream, cronJob) {
114
114
  if (!hasContent && !isContent) {
115
115
  // ── Buffer phase (no content yet) ──
116
116
  if (event.type === "done") {
117
- // Success without content flush buffer and finish
117
+ console.log(`[xiaoyiprovider] stream completed (no content), usage: input=${event.message?.usage?.input} output=${event.message?.usage?.output}`);
118
118
  for (const b of buffer)
119
119
  yield b;
120
120
  resultResolve(event.message);
@@ -129,20 +129,27 @@ function createRetryingStream(createStream, cronJob) {
129
129
  else {
130
130
  // ── Streaming phase ──
131
131
  if (!hasContent) {
132
- // First content event flush buffer then yield
132
+ console.log("[xiaoyiprovider] first content event received, switching to streaming mode");
133
133
  hasContent = true;
134
134
  for (const b of buffer)
135
135
  yield b;
136
136
  }
137
- yield event;
137
+ // IMPORTANT: resolve result() BEFORE yielding terminal events to avoid deadlock.
138
+ // The SDK calls result() when it sees done/error — if we yield first, the generator
139
+ // suspends and can never reach resolve, causing a permanent deadlock.
138
140
  if (event.type === "done") {
141
+ console.log(`[xiaoyiprovider] stream completed, usage: input=${event.message?.usage?.input} output=${event.message?.usage?.output}`);
139
142
  resultResolve(event.message);
143
+ yield event;
140
144
  return;
141
145
  }
142
146
  if (event.type === "error") {
147
+ console.log(`[xiaoyiprovider] stream error after content: ${event.error?.errorMessage}`);
143
148
  resultResolve(event.error);
149
+ yield event;
144
150
  return;
145
151
  }
152
+ yield event;
146
153
  }
147
154
  }
148
155
  // Stream ended during buffer phase — decide whether to retry
@@ -159,24 +166,37 @@ function createRetryingStream(createStream, cronJob) {
159
166
  else if (errorResult) {
160
167
  console.log(`[xiaoyiprovider] non-retryable error: ${errorResult.errorMessage}`);
161
168
  }
162
- // Non-retryable or retries exhausted — yield buffered events
163
- for (const b of buffer)
169
+ // Non-retryable or retries exhausted — yield buffered events.
170
+ // Resolve before yielding the terminal event to avoid the same deadlock.
171
+ for (const b of buffer) {
172
+ if (b.type === "done") {
173
+ resultResolve(b.message);
174
+ }
175
+ else if (b.type === "error") {
176
+ resultResolve(b.error);
177
+ }
164
178
  yield b;
165
- resultResolve(errorResult);
179
+ }
180
+ if (errorResult && buffer.every(b => b.type !== "done" && b.type !== "error")) {
181
+ resultResolve(errorResult);
182
+ }
166
183
  return;
167
184
  }
168
185
  // Safety: final fallback attempt
186
+ console.log("[xiaoyiprovider] entering final fallback attempt");
169
187
  const lastStream = await createStream();
170
188
  for await (const event of lastStream) {
171
- yield event;
172
189
  if (event.type === "done") {
173
190
  resultResolve(event.message);
191
+ yield event;
174
192
  return;
175
193
  }
176
194
  if (event.type === "error") {
177
195
  resultResolve(event.error);
196
+ yield event;
178
197
  return;
179
198
  }
199
+ yield event;
180
200
  }
181
201
  }
182
202
  const gen = retryGenerator();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynhcj/xiaoyi-channel",
3
- "version": "0.0.62-next",
3
+ "version": "0.0.63-next",
4
4
  "description": "OpenClaw Xiaoyi Channel plugin - Xiaoyi A2A protocol integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",