agl 22.0.4 → 23.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.
- package/changelog.md +10 -0
- package/dist_serve/bundle.js +2414 -2407
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.controller.d.ts +2 -0
- package/dist_ts/classes.controller.js +499 -22
- package/dist_ts/classes.flexservice.d.ts +5 -0
- package/dist_ts/classes.flexservice.js +131 -4
- package/dist_ts/classes.opencodeclient.d.ts +2 -0
- package/dist_ts/classes.opencodeclient.js +23 -1
- package/dist_ts/interfaces.flexipc.d.ts +18 -1
- package/dist_ts/interfaces.flexipc.js +42 -8
- package/dist_ts_interfaces/interfaces.d.ts +33 -2
- package/dist_ts_interfaces/interfaces.js +5 -2
- package/package.json +3 -3
- package/readme.md +6 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.controller.ts +589 -22
- package/ts/classes.flexservice.ts +132 -2
- package/ts/classes.opencodeclient.ts +19 -0
- package/ts/interfaces.flexipc.ts +65 -7
- package/ts_interfaces/interfaces.ts +36 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/classes.controllersocketclient.ts +113 -12
- package/ts_web/elements.harnesscontrollerapp.ts +1272 -167
|
@@ -3,6 +3,7 @@ import * as interfaces from '../ts_interfaces/index.js';
|
|
|
3
3
|
|
|
4
4
|
const controllerEventTypes: ReadonlySet<string> = new Set(interfaces.controllerEventTypes);
|
|
5
5
|
const controllerRequestTimeoutMs = 35_000;
|
|
6
|
+
const textEncoder = new TextEncoder();
|
|
6
7
|
|
|
7
8
|
const isQualifiedRuntimeId = (
|
|
8
9
|
valueArg: unknown,
|
|
@@ -16,7 +17,7 @@ const isQualifiedRuntimeId = (
|
|
|
16
17
|
&& allowedHarnessIdsArg.has(candidate.harnessId as interfaces.TControllerHarnessId)
|
|
17
18
|
&& typeof candidate.nativeId === 'string'
|
|
18
19
|
&& candidate.nativeId.length > 0
|
|
19
|
-
&&
|
|
20
|
+
&& textEncoder.encode(candidate.nativeId).byteLength <= 512
|
|
20
21
|
);
|
|
21
22
|
};
|
|
22
23
|
|
|
@@ -36,6 +37,14 @@ const textUpdateKeys = new Set([
|
|
|
36
37
|
'sessionId', 'messageId', 'partId', 'text', 'status', 'order',
|
|
37
38
|
'sourceUpdatedAt', 'revision', 'streamEpoch',
|
|
38
39
|
]);
|
|
40
|
+
const messageDeltaKeys = new Set([
|
|
41
|
+
'sessionId', 'messageId', 'partId', 'delta', 'baseTextUtf8Bytes', 'textUtf8Bytes',
|
|
42
|
+
'order', 'sourceUpdatedAt', 'revision', 'streamEpoch',
|
|
43
|
+
]);
|
|
44
|
+
const messageDeltaRequiredKeys = [
|
|
45
|
+
'sessionId', 'messageId', 'partId', 'delta', 'baseTextUtf8Bytes', 'textUtf8Bytes',
|
|
46
|
+
'sourceUpdatedAt', 'revision', 'streamEpoch',
|
|
47
|
+
] as const;
|
|
39
48
|
|
|
40
49
|
const isOptionalFiniteNumber = (valueArg: unknown): boolean => (
|
|
41
50
|
valueArg === undefined || (typeof valueArg === 'number' && Number.isFinite(valueArg))
|
|
@@ -53,12 +62,26 @@ const isTranscriptOrder = (valueArg: unknown): boolean => {
|
|
|
53
62
|
|
|
54
63
|
const serializedBytesWithin = (valueArg: unknown, byteLimitArg: number): boolean => {
|
|
55
64
|
try {
|
|
56
|
-
return
|
|
65
|
+
return textEncoder.encode(JSON.stringify(valueArg)).byteLength <= byteLimitArg;
|
|
57
66
|
} catch {
|
|
58
67
|
return false;
|
|
59
68
|
}
|
|
60
69
|
};
|
|
61
70
|
|
|
71
|
+
const hasExactDeltaUtf8Coordinates = (
|
|
72
|
+
deltaArg: string,
|
|
73
|
+
baseTextUtf8BytesArg: number,
|
|
74
|
+
textUtf8BytesArg: number,
|
|
75
|
+
): boolean => {
|
|
76
|
+
const encodedDeltaBytes = textEncoder.encode(deltaArg).byteLength;
|
|
77
|
+
const increment = textUtf8BytesArg - baseTextUtf8BytesArg;
|
|
78
|
+
if (increment === encodedDeltaBytes) return true;
|
|
79
|
+
const firstCodeUnit = deltaArg.charCodeAt(0);
|
|
80
|
+
return firstCodeUnit >= 0xDC00
|
|
81
|
+
&& firstCodeUnit <= 0xDFFF
|
|
82
|
+
&& increment === encodedDeltaBytes - 2;
|
|
83
|
+
};
|
|
84
|
+
|
|
62
85
|
const isDraftAttachment = (valueArg: unknown): valueArg is interfaces.IControllerDraftAttachment => {
|
|
63
86
|
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) return false;
|
|
64
87
|
const candidate = valueArg as Partial<interfaces.IControllerDraftAttachment>;
|
|
@@ -68,13 +91,13 @@ const isDraftAttachment = (valueArg: unknown): valueArg is interfaces.IControlle
|
|
|
68
91
|
))
|
|
69
92
|
|| typeof candidate.id !== 'string'
|
|
70
93
|
|| candidate.id.length === 0
|
|
71
|
-
||
|
|
94
|
+
|| textEncoder.encode(candidate.id).byteLength > 512
|
|
72
95
|
|| typeof candidate.name !== 'string'
|
|
73
96
|
|| candidate.name.length === 0
|
|
74
|
-
||
|
|
97
|
+
|| textEncoder.encode(candidate.name).byteLength > 255
|
|
75
98
|
|| typeof candidate.mediaType !== 'string'
|
|
76
99
|
|| candidate.mediaType.length === 0
|
|
77
|
-
||
|
|
100
|
+
|| textEncoder.encode(candidate.mediaType).byteLength > 129
|
|
78
101
|
|| !Number.isSafeInteger(candidate.size)
|
|
79
102
|
|| (candidate.size ?? -1) < 0
|
|
80
103
|
|| (candidate.size ?? 0) > interfaces.controllerMaxDraftAttachmentBytes
|
|
@@ -101,7 +124,7 @@ const isSessionDraftUpdate = (
|
|
|
101
124
|
|| (candidate.text === undefined && candidate.attachments === undefined)
|
|
102
125
|
|| (candidate.text !== undefined && (
|
|
103
126
|
typeof candidate.text !== 'string'
|
|
104
|
-
||
|
|
127
|
+
|| textEncoder.encode(candidate.text).byteLength > interfaces.controllerMaxDraftTextBytes
|
|
105
128
|
))
|
|
106
129
|
|| (candidate.attachments !== undefined && (
|
|
107
130
|
!Array.isArray(candidate.attachments)
|
|
@@ -130,7 +153,7 @@ const isControllerToolExecution = (
|
|
|
130
153
|
&& isQualifiedRuntimeId(candidate.callId, executionHarnessIds)
|
|
131
154
|
&& typeof candidate.toolName === 'string'
|
|
132
155
|
&& candidate.toolName.length > 0
|
|
133
|
-
&&
|
|
156
|
+
&& textEncoder.encode(candidate.toolName).byteLength <= 2048
|
|
134
157
|
&& ['pending', 'running', 'completed', 'error'].includes(candidate.status ?? '')
|
|
135
158
|
&& (candidate.exitCode === undefined
|
|
136
159
|
|| (Number.isSafeInteger(candidate.exitCode) && candidate.exitCode >= 0))
|
|
@@ -166,7 +189,7 @@ const isControllerReasoningUpdate = (
|
|
|
166
189
|
&& isQualifiedRuntimeId(candidate.messageId, harnessIds)
|
|
167
190
|
&& isQualifiedRuntimeId(candidate.partId, harnessIds)
|
|
168
191
|
&& typeof candidate.text === 'string'
|
|
169
|
-
&&
|
|
192
|
+
&& textEncoder.encode(candidate.text).byteLength
|
|
170
193
|
<= interfaces.controllerMaxLiveMessageEventBytes
|
|
171
194
|
&& ['running', 'completed', 'cancelled'].includes(candidate.status ?? '')
|
|
172
195
|
&& (candidate.order === undefined || isTranscriptOrder(candidate.order))
|
|
@@ -193,7 +216,7 @@ const isControllerTextUpdate = (
|
|
|
193
216
|
&& isQualifiedRuntimeId(candidate.messageId, harnessIds)
|
|
194
217
|
&& isQualifiedRuntimeId(candidate.partId, harnessIds)
|
|
195
218
|
&& typeof candidate.text === 'string'
|
|
196
|
-
&&
|
|
219
|
+
&& textEncoder.encode(candidate.text).byteLength
|
|
197
220
|
<= interfaces.controllerMaxLiveMessageEventBytes
|
|
198
221
|
&& ['running', 'completed'].includes(candidate.status ?? '')
|
|
199
222
|
&& (candidate.order === undefined || isTranscriptOrder(candidate.order))
|
|
@@ -207,6 +230,48 @@ const isControllerTextUpdate = (
|
|
|
207
230
|
&& (candidate.streamEpoch ?? -1) >= 0;
|
|
208
231
|
};
|
|
209
232
|
|
|
233
|
+
const isControllerMessageDelta = (
|
|
234
|
+
valueArg: unknown,
|
|
235
|
+
): valueArg is interfaces.IControllerReasoningDelta | interfaces.IControllerTextDelta => {
|
|
236
|
+
if (!valueArg || typeof valueArg !== 'object' || Array.isArray(valueArg)) return false;
|
|
237
|
+
const candidate = valueArg as Partial<interfaces.IControllerReasoningDelta>;
|
|
238
|
+
if (!isQualifiedRuntimeId(candidate.sessionId, sessionHarnessIds)) return false;
|
|
239
|
+
const harnessIds: ReadonlySet<interfaces.TControllerHarnessId> = new Set([
|
|
240
|
+
candidate.sessionId.harnessId,
|
|
241
|
+
]);
|
|
242
|
+
const keys = Object.keys(candidate);
|
|
243
|
+
const hasOrder = Object.prototype.hasOwnProperty.call(candidate, 'order');
|
|
244
|
+
return keys.length === messageDeltaRequiredKeys.length + (hasOrder ? 1 : 0)
|
|
245
|
+
&& keys.every((key) => messageDeltaKeys.has(key))
|
|
246
|
+
&& messageDeltaRequiredKeys.every((key) => (
|
|
247
|
+
Object.prototype.hasOwnProperty.call(candidate, key)
|
|
248
|
+
))
|
|
249
|
+
&& isQualifiedRuntimeId(candidate.messageId, harnessIds)
|
|
250
|
+
&& isQualifiedRuntimeId(candidate.partId, harnessIds)
|
|
251
|
+
&& typeof candidate.delta === 'string'
|
|
252
|
+
&& candidate.delta.length > 0
|
|
253
|
+
&& textEncoder.encode(candidate.delta).byteLength
|
|
254
|
+
<= interfaces.controllerMaxLiveMessageEventBytes
|
|
255
|
+
&& Number.isSafeInteger(candidate.baseTextUtf8Bytes)
|
|
256
|
+
&& (candidate.baseTextUtf8Bytes ?? -1) >= 0
|
|
257
|
+
&& Number.isSafeInteger(candidate.textUtf8Bytes)
|
|
258
|
+
&& (candidate.textUtf8Bytes ?? -1) > (candidate.baseTextUtf8Bytes ?? -1)
|
|
259
|
+
&& hasExactDeltaUtf8Coordinates(
|
|
260
|
+
candidate.delta,
|
|
261
|
+
candidate.baseTextUtf8Bytes!,
|
|
262
|
+
candidate.textUtf8Bytes!,
|
|
263
|
+
)
|
|
264
|
+
&& (!hasOrder || isTranscriptOrder(candidate.order))
|
|
265
|
+
&& (candidate.sessionId.harnessId !== 'flex' || hasOrder)
|
|
266
|
+
&& (candidate.sessionId.harnessId !== 'opencode' || !hasOrder)
|
|
267
|
+
&& typeof candidate.sourceUpdatedAt === 'number'
|
|
268
|
+
&& Number.isFinite(candidate.sourceUpdatedAt)
|
|
269
|
+
&& Number.isSafeInteger(candidate.revision)
|
|
270
|
+
&& (candidate.revision ?? -1) >= 0
|
|
271
|
+
&& Number.isSafeInteger(candidate.streamEpoch)
|
|
272
|
+
&& (candidate.streamEpoch ?? -1) >= 0;
|
|
273
|
+
};
|
|
274
|
+
|
|
210
275
|
export interface IControllerSocketClientOptions {
|
|
211
276
|
onStatus: (status: plugins.typedsocket.TConnectionStatus) => void;
|
|
212
277
|
onControllerEvent: (event: interfaces.IControllerEvent) => void | Promise<void>;
|
|
@@ -240,9 +305,18 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
240
305
|
const hasSessionMarker = candidate.sessionStatus !== undefined || candidate.sessionError !== undefined;
|
|
241
306
|
const hasToolExecution = candidate.toolExecution !== undefined;
|
|
242
307
|
const hasReasoningUpdate = candidate.reasoningUpdate !== undefined;
|
|
308
|
+
const hasReasoningDelta = candidate.reasoningDelta !== undefined;
|
|
243
309
|
const hasTextUpdate = candidate.textUpdate !== undefined;
|
|
310
|
+
const hasTextDelta = candidate.textDelta !== undefined;
|
|
244
311
|
const hasDraftUpdate = candidate.sessionDraftUpdate !== undefined;
|
|
245
312
|
const hasUpgrade = candidate.upgrade !== undefined;
|
|
313
|
+
const livePayloadCount = [
|
|
314
|
+
hasToolExecution,
|
|
315
|
+
hasReasoningUpdate,
|
|
316
|
+
hasReasoningDelta,
|
|
317
|
+
hasTextUpdate,
|
|
318
|
+
hasTextDelta,
|
|
319
|
+
].filter(Boolean).length;
|
|
246
320
|
return (
|
|
247
321
|
typeof candidate.type === 'string'
|
|
248
322
|
&& controllerEventTypes.has(candidate.type as interfaces.TControllerEventType)
|
|
@@ -269,14 +343,19 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
269
343
|
&& (candidate.toolExecution === undefined || isControllerToolExecution(candidate.toolExecution))
|
|
270
344
|
&& (candidate.reasoningUpdate === undefined
|
|
271
345
|
|| isControllerReasoningUpdate(candidate.reasoningUpdate))
|
|
346
|
+
&& (candidate.reasoningDelta === undefined
|
|
347
|
+
|| isControllerMessageDelta(candidate.reasoningDelta))
|
|
272
348
|
&& (candidate.textUpdate === undefined || isControllerTextUpdate(candidate.textUpdate))
|
|
349
|
+
&& (candidate.textDelta === undefined || isControllerMessageDelta(candidate.textDelta))
|
|
273
350
|
&& (candidate.sessionDraftUpdate === undefined
|
|
274
351
|
|| isSessionDraftUpdate(candidate.sessionDraftUpdate))
|
|
352
|
+
&& livePayloadCount <= 1
|
|
275
353
|
&& (!hasToolExecution || serializedBytesWithin(
|
|
276
354
|
candidate,
|
|
277
355
|
interfaces.controllerMaxToolEventBytes,
|
|
278
356
|
))
|
|
279
|
-
&& (!(hasReasoningUpdate || hasTextUpdate
|
|
357
|
+
&& (!(hasReasoningUpdate || hasReasoningDelta || hasTextUpdate || hasTextDelta)
|
|
358
|
+
|| serializedBytesWithin(
|
|
280
359
|
candidate,
|
|
281
360
|
interfaces.controllerMaxLiveMessageEventBytes,
|
|
282
361
|
))
|
|
@@ -312,6 +391,16 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
312
391
|
=== interfaces.controllerRuntimeIdKey(candidate.reasoningUpdate!.sessionId)
|
|
313
392
|
))
|
|
314
393
|
&& (hasReasoningUpdate || candidate.type !== 'session.reasoning.updated')
|
|
394
|
+
&& (!hasReasoningDelta || (
|
|
395
|
+
candidate.type === 'session.reasoning.delta'
|
|
396
|
+
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
397
|
+
&& typeof candidate.projectId === 'string'
|
|
398
|
+
&& isQualifiedRuntimeId(candidate.sessionId, sessionHarnessIds)
|
|
399
|
+
&& candidate.harnessId === candidate.reasoningDelta!.sessionId.harnessId
|
|
400
|
+
&& interfaces.controllerRuntimeIdKey(candidate.sessionId)
|
|
401
|
+
=== interfaces.controllerRuntimeIdKey(candidate.reasoningDelta!.sessionId)
|
|
402
|
+
))
|
|
403
|
+
&& (hasReasoningDelta || candidate.type !== 'session.reasoning.delta')
|
|
315
404
|
&& (!hasTextUpdate || (
|
|
316
405
|
candidate.type === 'session.text.updated'
|
|
317
406
|
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
@@ -322,6 +411,16 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
322
411
|
=== interfaces.controllerRuntimeIdKey(candidate.textUpdate!.sessionId)
|
|
323
412
|
))
|
|
324
413
|
&& (hasTextUpdate || candidate.type !== 'session.text.updated')
|
|
414
|
+
&& (!hasTextDelta || (
|
|
415
|
+
candidate.type === 'session.text.delta'
|
|
416
|
+
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
417
|
+
&& typeof candidate.projectId === 'string'
|
|
418
|
+
&& isQualifiedRuntimeId(candidate.sessionId, sessionHarnessIds)
|
|
419
|
+
&& candidate.harnessId === candidate.textDelta!.sessionId.harnessId
|
|
420
|
+
&& interfaces.controllerRuntimeIdKey(candidate.sessionId)
|
|
421
|
+
=== interfaces.controllerRuntimeIdKey(candidate.textDelta!.sessionId)
|
|
422
|
+
))
|
|
423
|
+
&& (hasTextDelta || candidate.type !== 'session.text.delta')
|
|
325
424
|
&& (!hasDraftUpdate || (
|
|
326
425
|
candidate.type === 'session.draft.changed'
|
|
327
426
|
&& typeof candidate.projectId === 'string'
|
|
@@ -337,7 +436,9 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
337
436
|
candidate.type === 'harness.changed'
|
|
338
437
|
&& (candidate.harnessId === 'opencode' || candidate.harnessId === 'flex')
|
|
339
438
|
&& !hasReasoningUpdate
|
|
439
|
+
&& !hasReasoningDelta
|
|
340
440
|
&& !hasTextUpdate
|
|
441
|
+
&& !hasTextDelta
|
|
341
442
|
))
|
|
342
443
|
&& (candidate.upgrade === undefined || (
|
|
343
444
|
typeof candidate.upgrade === 'object'
|
|
@@ -345,10 +446,10 @@ export const isControllerEvent = (valueArg: unknown): valueArg is interfaces.ICo
|
|
|
345
446
|
&& Object.keys(candidate.upgrade).length === 3
|
|
346
447
|
&& typeof candidate.upgrade.fromVersion === 'string'
|
|
347
448
|
&& candidate.upgrade.fromVersion.length > 0
|
|
348
|
-
&&
|
|
449
|
+
&& textEncoder.encode(candidate.upgrade.fromVersion).byteLength <= 128
|
|
349
450
|
&& typeof candidate.upgrade.toVersion === 'string'
|
|
350
451
|
&& candidate.upgrade.toVersion.length > 0
|
|
351
|
-
&&
|
|
452
|
+
&& textEncoder.encode(candidate.upgrade.toVersion).byteLength <= 128
|
|
352
453
|
&& ['preparing', 'pausing', 'installing', 'restarting', 'continuing', 'completed', 'failed']
|
|
353
454
|
.includes(candidate.upgrade.phase)
|
|
354
455
|
))
|