@forgeax/engine-intelligence 0.1.7 → 0.1.20
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/README.md +14 -4
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.mjs +51 -12
- package/dist/index.mjs.map +1 -1
- package/dist/transport.d.ts +2 -0
- package/dist/transport.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/transport.test.ts +677 -0
- package/src/transport.ts +55 -12
package/src/transport.ts
CHANGED
|
@@ -71,7 +71,14 @@ export function bindIntelligencePort(
|
|
|
71
71
|
return;
|
|
72
72
|
}
|
|
73
73
|
if (message.kind === 'intelligence-poll') {
|
|
74
|
-
|
|
74
|
+
const events = runtime.poll(message.maxEvents);
|
|
75
|
+
try {
|
|
76
|
+
port.postMessage({ kind: 'intelligence-events', events });
|
|
77
|
+
} catch {
|
|
78
|
+
// Poll is destructive; a failed response must terminate the Host binding
|
|
79
|
+
// so the drained events cannot remain attached to a live runtime.
|
|
80
|
+
void close().catch(() => undefined);
|
|
81
|
+
}
|
|
75
82
|
return;
|
|
76
83
|
}
|
|
77
84
|
if (message.kind === 'intelligence-cancel') {
|
|
@@ -86,8 +93,13 @@ export function bindIntelligencePort(
|
|
|
86
93
|
port.removeEventListener('message', listener);
|
|
87
94
|
closeTask = (async () => {
|
|
88
95
|
await runtime.close();
|
|
89
|
-
|
|
90
|
-
|
|
96
|
+
try {
|
|
97
|
+
port.postMessage({ kind: 'intelligence-closed' });
|
|
98
|
+
} catch {
|
|
99
|
+
// A failed terminal notification must not strand the physical transport.
|
|
100
|
+
}
|
|
101
|
+
await new Promise<void>((resolve) => setTimeout(resolve, 0));
|
|
102
|
+
port.close();
|
|
91
103
|
})();
|
|
92
104
|
return closeTask;
|
|
93
105
|
};
|
|
@@ -146,6 +158,7 @@ export class IntelligencePortClient implements IntelligenceService {
|
|
|
146
158
|
private pollPending = false;
|
|
147
159
|
private closeTask: Promise<void> | undefined;
|
|
148
160
|
private closeResolve: (() => void) | undefined;
|
|
161
|
+
private transportReleased = false;
|
|
149
162
|
|
|
150
163
|
constructor(
|
|
151
164
|
readonly providerId: string,
|
|
@@ -170,8 +183,7 @@ export class IntelligencePortClient implements IntelligenceService {
|
|
|
170
183
|
this.rejected.set(message.activityId, message);
|
|
171
184
|
} else if (message.kind === 'intelligence-closed') {
|
|
172
185
|
this.markClosed();
|
|
173
|
-
this.
|
|
174
|
-
this.port.close();
|
|
186
|
+
this.releaseTransport();
|
|
175
187
|
this.closeResolve?.();
|
|
176
188
|
this.closeResolve = undefined;
|
|
177
189
|
this.closeTask ??= Promise.resolve();
|
|
@@ -189,6 +201,13 @@ export class IntelligencePortClient implements IntelligenceService {
|
|
|
189
201
|
this.pollPending = false;
|
|
190
202
|
}
|
|
191
203
|
|
|
204
|
+
private releaseTransport(): void {
|
|
205
|
+
if (this.transportReleased) return;
|
|
206
|
+
this.transportReleased = true;
|
|
207
|
+
this.port.removeEventListener('message', this.listener);
|
|
208
|
+
this.port.close();
|
|
209
|
+
}
|
|
210
|
+
|
|
192
211
|
submit(request: ActivityRequest): Result<ActivityRef, IntelligenceError> {
|
|
193
212
|
if (this.closed) return err(new IntelligenceError({ code: 'intelligence-closed', detail: {} }));
|
|
194
213
|
if (request.input.length === 0 || request.input.length > this.limits.maxInputChars) {
|
|
@@ -229,10 +248,16 @@ export class IntelligencePortClient implements IntelligenceService {
|
|
|
229
248
|
session: request.session ?? { providerId: this.providerId, id: this.createSessionId() },
|
|
230
249
|
};
|
|
231
250
|
this.active.add(ref.id);
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
251
|
+
try {
|
|
252
|
+
this.port.postMessage({
|
|
253
|
+
kind: 'intelligence-submit',
|
|
254
|
+
submission: { ...ref, input: request.input },
|
|
255
|
+
});
|
|
256
|
+
} catch {
|
|
257
|
+
this.markClosed();
|
|
258
|
+
this.releaseTransport();
|
|
259
|
+
return err(new IntelligenceError({ code: 'intelligence-closed', detail: {} }));
|
|
260
|
+
}
|
|
236
261
|
return ok(ref);
|
|
237
262
|
}
|
|
238
263
|
|
|
@@ -252,7 +277,13 @@ export class IntelligencePortClient implements IntelligenceService {
|
|
|
252
277
|
}
|
|
253
278
|
if (!this.pollPending) {
|
|
254
279
|
this.pollPending = true;
|
|
255
|
-
|
|
280
|
+
try {
|
|
281
|
+
this.port.postMessage({ kind: 'intelligence-poll', maxEvents: count });
|
|
282
|
+
} catch {
|
|
283
|
+
this.markClosed();
|
|
284
|
+
this.releaseTransport();
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
256
287
|
}
|
|
257
288
|
return events;
|
|
258
289
|
}
|
|
@@ -267,7 +298,13 @@ export class IntelligencePortClient implements IntelligenceService {
|
|
|
267
298
|
}),
|
|
268
299
|
);
|
|
269
300
|
}
|
|
270
|
-
|
|
301
|
+
try {
|
|
302
|
+
this.port.postMessage({ kind: 'intelligence-cancel', activityId: id });
|
|
303
|
+
} catch {
|
|
304
|
+
this.markClosed();
|
|
305
|
+
this.releaseTransport();
|
|
306
|
+
return err(new IntelligenceError({ code: 'intelligence-closed', detail: {} }));
|
|
307
|
+
}
|
|
271
308
|
return ok(undefined);
|
|
272
309
|
}
|
|
273
310
|
|
|
@@ -280,7 +317,13 @@ export class IntelligencePortClient implements IntelligenceService {
|
|
|
280
317
|
this.markClosed();
|
|
281
318
|
this.closeTask = new Promise((resolve) => {
|
|
282
319
|
this.closeResolve = resolve;
|
|
283
|
-
|
|
320
|
+
try {
|
|
321
|
+
this.port.postMessage({ kind: 'intelligence-close' });
|
|
322
|
+
} catch {
|
|
323
|
+
this.releaseTransport();
|
|
324
|
+
this.closeResolve = undefined;
|
|
325
|
+
resolve();
|
|
326
|
+
}
|
|
284
327
|
});
|
|
285
328
|
return this.closeTask;
|
|
286
329
|
}
|