agl 22.0.3 → 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 +20 -0
- package/dist_serve/bundle.js +2351 -2325
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.authstore.d.ts +1 -0
- package/dist_ts/classes.authstore.js +30 -1
- package/dist_ts/classes.controller.d.ts +2 -0
- package/dist_ts/classes.controller.js +520 -25
- 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 +4 -4
- package/readme.md +6 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.authstore.ts +44 -0
- package/ts/classes.controller.ts +617 -26
- 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 +1282 -170
package/ts/classes.controller.ts
CHANGED
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
controllerBuiltinCommands,
|
|
13
13
|
controllerMaxToolEventBytes,
|
|
14
14
|
controllerMaxLiveMessageEventBytes,
|
|
15
|
+
controllerLiveMessageDeltaTargetBytes,
|
|
15
16
|
controllerInitialMessageBundleLimit,
|
|
16
17
|
controllerMaximumTranscriptBytes,
|
|
17
18
|
controllerLiveToolPayloadNotice,
|
|
@@ -26,8 +27,11 @@ import {
|
|
|
26
27
|
type IControllerMessagePage,
|
|
27
28
|
type IControllerMessageStreamCursor,
|
|
28
29
|
type IControllerPendingPrompt,
|
|
30
|
+
type IControllerReasoningDelta,
|
|
29
31
|
type IControllerReasoningUpdate,
|
|
32
|
+
type IControllerTextDelta,
|
|
30
33
|
type IControllerTextUpdate,
|
|
34
|
+
type IControllerTodo,
|
|
31
35
|
type TControllerModelChoice,
|
|
32
36
|
type IControllerModelRefreshJob,
|
|
33
37
|
type IControllerPermission,
|
|
@@ -539,15 +543,24 @@ interface ILatestToolExecution {
|
|
|
539
543
|
interface ILatestReasoningUpdate {
|
|
540
544
|
projectId: string;
|
|
541
545
|
update: IControllerReasoningUpdate;
|
|
546
|
+
textUtf8Bytes: number;
|
|
542
547
|
bytes?: number;
|
|
543
548
|
}
|
|
544
549
|
|
|
545
550
|
interface ILatestTextUpdate {
|
|
546
551
|
projectId: string;
|
|
547
552
|
update: IControllerTextUpdate;
|
|
553
|
+
textUtf8Bytes: number;
|
|
548
554
|
bytes?: number;
|
|
549
555
|
}
|
|
550
556
|
|
|
557
|
+
type TControllerMessageDelta = IControllerReasoningDelta | IControllerTextDelta;
|
|
558
|
+
|
|
559
|
+
interface IControllerTextDeltaFragment {
|
|
560
|
+
delta: string;
|
|
561
|
+
utf8Bytes: number;
|
|
562
|
+
}
|
|
563
|
+
|
|
551
564
|
type TControllerToolExecutionSnapshot = Omit<
|
|
552
565
|
IControllerToolExecution,
|
|
553
566
|
'revision' | 'streamEpoch'
|
|
@@ -557,6 +570,103 @@ const historyLimitedNotice = '[earlier message content omitted: this transcript
|
|
|
557
570
|
const historyLimitedDigestPrefix = 'history-limited:';
|
|
558
571
|
const liveToolExecutionBytes = controllerMaxToolEventBytes - (8 * 1024);
|
|
559
572
|
|
|
573
|
+
const controllerEventMessageDelta = (
|
|
574
|
+
eventArg: IControllerEvent,
|
|
575
|
+
): TControllerMessageDelta | undefined => eventArg.reasoningDelta ?? eventArg.textDelta;
|
|
576
|
+
|
|
577
|
+
const controllerTextAfterAppendUtf8Bytes = (
|
|
578
|
+
textArg: string,
|
|
579
|
+
textUtf8BytesArg: number,
|
|
580
|
+
deltaArg: string,
|
|
581
|
+
): number | undefined => {
|
|
582
|
+
// Separately encoded surrogate halves cost six bytes; after append the pair costs four.
|
|
583
|
+
const boundaryCorrection = (
|
|
584
|
+
textArg.length > 0
|
|
585
|
+
&& deltaArg.length > 0
|
|
586
|
+
&& textArg.charCodeAt(textArg.length - 1) >= 0xD800
|
|
587
|
+
&& textArg.charCodeAt(textArg.length - 1) <= 0xDBFF
|
|
588
|
+
&& deltaArg.charCodeAt(0) >= 0xDC00
|
|
589
|
+
&& deltaArg.charCodeAt(0) <= 0xDFFF
|
|
590
|
+
) ? -2 : 0;
|
|
591
|
+
const result = textUtf8BytesArg + Buffer.byteLength(deltaArg, 'utf8') + boundaryCorrection;
|
|
592
|
+
return Number.isSafeInteger(result) && result >= 0 ? result : undefined;
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
const fragmentControllerTextDelta = (valueArg: string): IControllerTextDeltaFragment[] => {
|
|
596
|
+
const fragments: IControllerTextDeltaFragment[] = [];
|
|
597
|
+
let delta = '';
|
|
598
|
+
let utf8Bytes = 0;
|
|
599
|
+
for (const codePoint of valueArg) {
|
|
600
|
+
const codePointBytes = Buffer.byteLength(codePoint, 'utf8');
|
|
601
|
+
if (
|
|
602
|
+
delta !== ''
|
|
603
|
+
&& utf8Bytes + codePointBytes > controllerLiveMessageDeltaTargetBytes
|
|
604
|
+
) {
|
|
605
|
+
fragments.push({ delta, utf8Bytes });
|
|
606
|
+
delta = '';
|
|
607
|
+
utf8Bytes = 0;
|
|
608
|
+
}
|
|
609
|
+
delta += codePoint;
|
|
610
|
+
utf8Bytes += codePointBytes;
|
|
611
|
+
}
|
|
612
|
+
if (delta !== '') fragments.push({ delta, utf8Bytes });
|
|
613
|
+
return fragments;
|
|
614
|
+
};
|
|
615
|
+
|
|
616
|
+
const controllerMessageDeltaPendingKey = (eventArg: IControllerEvent): string | undefined => {
|
|
617
|
+
const delta = controllerEventMessageDelta(eventArg);
|
|
618
|
+
if (!delta) return undefined;
|
|
619
|
+
return JSON.stringify([
|
|
620
|
+
eventArg.type,
|
|
621
|
+
eventArg.harnessId ?? null,
|
|
622
|
+
eventArg.projectId ?? null,
|
|
623
|
+
controllerRuntimeIdKey(delta.sessionId),
|
|
624
|
+
controllerRuntimeIdKey(delta.partId),
|
|
625
|
+
]);
|
|
626
|
+
};
|
|
627
|
+
|
|
628
|
+
const controllerMessageDeltaEventsAreContiguous = (
|
|
629
|
+
previousEventArg: IControllerEvent,
|
|
630
|
+
eventArg: IControllerEvent,
|
|
631
|
+
): boolean => {
|
|
632
|
+
const previous = controllerEventMessageDelta(previousEventArg);
|
|
633
|
+
const delta = controllerEventMessageDelta(eventArg);
|
|
634
|
+
if (!previous || !delta) return false;
|
|
635
|
+
return previousEventArg.type === eventArg.type
|
|
636
|
+
&& previousEventArg.harnessId === eventArg.harnessId
|
|
637
|
+
&& previousEventArg.projectId === eventArg.projectId
|
|
638
|
+
&& (previousEventArg.sessionId
|
|
639
|
+
? eventArg.sessionId !== undefined
|
|
640
|
+
&& controllerRuntimeIdKey(previousEventArg.sessionId)
|
|
641
|
+
=== controllerRuntimeIdKey(eventArg.sessionId)
|
|
642
|
+
: eventArg.sessionId === undefined)
|
|
643
|
+
&& controllerRuntimeIdKey(previous.sessionId) === controllerRuntimeIdKey(delta.sessionId)
|
|
644
|
+
&& controllerRuntimeIdKey(previous.messageId) === controllerRuntimeIdKey(delta.messageId)
|
|
645
|
+
&& controllerRuntimeIdKey(previous.partId) === controllerRuntimeIdKey(delta.partId)
|
|
646
|
+
&& previous.streamEpoch === delta.streamEpoch
|
|
647
|
+
&& previous.order?.messageIndex === delta.order?.messageIndex
|
|
648
|
+
&& previous.order?.partIndex === delta.order?.partIndex
|
|
649
|
+
&& previous.textUtf8Bytes === delta.baseTextUtf8Bytes
|
|
650
|
+
&& delta.revision > previous.revision;
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
const mergeControllerMessageDeltaEvents = (
|
|
654
|
+
previousEventArg: IControllerEvent,
|
|
655
|
+
eventArg: IControllerEvent,
|
|
656
|
+
): IControllerEvent | undefined => {
|
|
657
|
+
if (!controllerMessageDeltaEventsAreContiguous(previousEventArg, eventArg)) return undefined;
|
|
658
|
+
const previous = controllerEventMessageDelta(previousEventArg)!;
|
|
659
|
+
const delta = controllerEventMessageDelta(eventArg)!;
|
|
660
|
+
const mergedDelta = {
|
|
661
|
+
...delta,
|
|
662
|
+
delta: `${previous.delta}${delta.delta}`,
|
|
663
|
+
baseTextUtf8Bytes: previous.baseTextUtf8Bytes,
|
|
664
|
+
};
|
|
665
|
+
return eventArg.reasoningDelta
|
|
666
|
+
? { ...eventArg, reasoningDelta: mergedDelta }
|
|
667
|
+
: { ...eventArg, textDelta: mergedDelta };
|
|
668
|
+
};
|
|
669
|
+
|
|
560
670
|
const markHistoryLimitedDigest = (digestArg: string): string => (
|
|
561
671
|
digestArg.startsWith(historyLimitedDigestPrefix)
|
|
562
672
|
? digestArg
|
|
@@ -8978,14 +9088,36 @@ export class OpenCodeController {
|
|
|
8978
9088
|
messagePage: IControllerMessagePage;
|
|
8979
9089
|
permissions: IControllerPermission[];
|
|
8980
9090
|
questions: IControllerQuestion[];
|
|
8981
|
-
todos: [];
|
|
9091
|
+
todos: IControllerTodo[];
|
|
8982
9092
|
model?: string;
|
|
8983
9093
|
effort?: string;
|
|
8984
9094
|
}> {
|
|
8985
9095
|
const reader = this.requireFlexProjectionReader();
|
|
8986
9096
|
const supervisor = this.flexSupervisor;
|
|
8987
|
-
const
|
|
8988
|
-
|
|
9097
|
+
const sessionPromise = reader.getSession(projectIdArg, sessionIdArg, signalArg);
|
|
9098
|
+
const todosPromise: Promise<IControllerTodo[]> = sessionPromise.then(async (session) => {
|
|
9099
|
+
if (
|
|
9100
|
+
session.sessionGenerationId === undefined
|
|
9101
|
+
|| session.sessionGenerationSequence === undefined
|
|
9102
|
+
) return [];
|
|
9103
|
+
signalArg?.throwIfAborted();
|
|
9104
|
+
const tasks = await this.requireAuthStore().readFlexProjectTasks(
|
|
9105
|
+
projectIdArg,
|
|
9106
|
+
sessionIdArg,
|
|
9107
|
+
{
|
|
9108
|
+
sessionGenerationId: session.sessionGenerationId,
|
|
9109
|
+
sessionGenerationSequence: session.sessionGenerationSequence,
|
|
9110
|
+
},
|
|
9111
|
+
);
|
|
9112
|
+
signalArg?.throwIfAborted();
|
|
9113
|
+
return tasks.map((task) => ({
|
|
9114
|
+
id: flexRuntimeId(task.id),
|
|
9115
|
+
content: task.content,
|
|
9116
|
+
status: task.status,
|
|
9117
|
+
}));
|
|
9118
|
+
});
|
|
9119
|
+
const [session, messagePage, permissionResult, todos] = await Promise.all([
|
|
9120
|
+
sessionPromise,
|
|
8989
9121
|
reader.listMessagePage(projectIdArg, sessionIdArg, {
|
|
8990
9122
|
limit: controllerInitialMessageBundleLimit,
|
|
8991
9123
|
}, signalArg),
|
|
@@ -8995,6 +9127,7 @@ export class OpenCodeController {
|
|
|
8995
9127
|
familyRootSessionId: sessionIdArg,
|
|
8996
9128
|
}, signalArg).catch(() => ({ permissions: [] as TFlexPermissionRequest[] }))
|
|
8997
9129
|
: Promise.resolve({ permissions: [] as TFlexPermissionRequest[] }),
|
|
9130
|
+
todosPromise,
|
|
8998
9131
|
]);
|
|
8999
9132
|
const bundles = messagePage.messages.map((message) => this.toFlexMessageBundle(message));
|
|
9000
9133
|
const messages = bundles.flatMap((bundle) => bundle.messages);
|
|
@@ -9016,7 +9149,7 @@ export class OpenCodeController {
|
|
|
9016
9149
|
}),
|
|
9017
9150
|
permissions: permissionResult.permissions.map((permission) => this.toFlexPermission(permission)),
|
|
9018
9151
|
questions: [],
|
|
9019
|
-
todos
|
|
9152
|
+
todos,
|
|
9020
9153
|
...(model === undefined ? {} : { model }),
|
|
9021
9154
|
...(effort === undefined ? {} : { effort }),
|
|
9022
9155
|
};
|
|
@@ -9968,6 +10101,10 @@ export class OpenCodeController {
|
|
|
9968
10101
|
this.handleFlexTextUpdate(eventArg);
|
|
9969
10102
|
return;
|
|
9970
10103
|
}
|
|
10104
|
+
if (eventArg.type === 'part.delta') {
|
|
10105
|
+
this.handleFlexPartDelta(eventArg);
|
|
10106
|
+
return;
|
|
10107
|
+
}
|
|
9971
10108
|
if (eventArg.type === 'permissions.changed') {
|
|
9972
10109
|
if (this.autoAcceptPermissions || this.hasFlexYoloSessions()) {
|
|
9973
10110
|
this.queueFlexAutoAcceptSweep(eventArg.scopeId, eventArg.sessionId);
|
|
@@ -10389,7 +10526,12 @@ export class OpenCodeController {
|
|
|
10389
10526
|
const bytes = Buffer.byteLength(JSON.stringify(eventArg), 'utf8');
|
|
10390
10527
|
return {
|
|
10391
10528
|
tool: eventArg.toolExecution ? bytes : 0,
|
|
10392
|
-
message: eventArg.reasoningUpdate
|
|
10529
|
+
message: eventArg.reasoningUpdate
|
|
10530
|
+
|| eventArg.reasoningDelta
|
|
10531
|
+
|| eventArg.textUpdate
|
|
10532
|
+
|| eventArg.textDelta
|
|
10533
|
+
? bytes
|
|
10534
|
+
: 0,
|
|
10393
10535
|
};
|
|
10394
10536
|
}
|
|
10395
10537
|
|
|
@@ -10549,7 +10691,12 @@ export class OpenCodeController {
|
|
|
10549
10691
|
this.latestFlexTextUpdates.clear();
|
|
10550
10692
|
this.latestFlexMessageUpdateBytes = 0;
|
|
10551
10693
|
for (const [key, event] of this.pendingFlexControllerEvents) {
|
|
10552
|
-
if (
|
|
10694
|
+
if (
|
|
10695
|
+
event.reasoningUpdate
|
|
10696
|
+
|| event.reasoningDelta
|
|
10697
|
+
|| event.textUpdate
|
|
10698
|
+
|| event.textDelta
|
|
10699
|
+
) this.deletePendingFlexControllerEvent(key);
|
|
10553
10700
|
}
|
|
10554
10701
|
const timestamp = Date.now();
|
|
10555
10702
|
const barrier: IControllerEvent = {
|
|
@@ -10635,11 +10782,19 @@ export class OpenCodeController {
|
|
|
10635
10782
|
for (const [key, event] of this.pendingFlexControllerEvents) {
|
|
10636
10783
|
if (
|
|
10637
10784
|
event.projectId === projectIdArg
|
|
10638
|
-
&& (
|
|
10785
|
+
&& (
|
|
10786
|
+
event.toolExecution
|
|
10787
|
+
|| event.reasoningUpdate
|
|
10788
|
+
|| event.reasoningDelta
|
|
10789
|
+
|| event.textUpdate
|
|
10790
|
+
|| event.textDelta
|
|
10791
|
+
)
|
|
10639
10792
|
&& controllerRuntimeIdKey(
|
|
10640
10793
|
event.toolExecution?.sessionId
|
|
10641
10794
|
?? event.reasoningUpdate?.sessionId
|
|
10642
|
-
?? event.
|
|
10795
|
+
?? event.reasoningDelta?.sessionId
|
|
10796
|
+
?? event.textUpdate?.sessionId
|
|
10797
|
+
?? event.textDelta!.sessionId,
|
|
10643
10798
|
) === sessionKey
|
|
10644
10799
|
) this.deletePendingFlexControllerEvent(key);
|
|
10645
10800
|
}
|
|
@@ -10705,7 +10860,13 @@ export class OpenCodeController {
|
|
|
10705
10860
|
for (const [key, event] of this.pendingFlexControllerEvents) {
|
|
10706
10861
|
if (
|
|
10707
10862
|
event.projectId === projectIdArg
|
|
10708
|
-
&& (
|
|
10863
|
+
&& (
|
|
10864
|
+
event.toolExecution
|
|
10865
|
+
|| event.reasoningUpdate
|
|
10866
|
+
|| event.reasoningDelta
|
|
10867
|
+
|| event.textUpdate
|
|
10868
|
+
|| event.textDelta
|
|
10869
|
+
)
|
|
10709
10870
|
) {
|
|
10710
10871
|
this.deletePendingFlexControllerEvent(key);
|
|
10711
10872
|
}
|
|
@@ -10862,7 +11023,11 @@ export class OpenCodeController {
|
|
|
10862
11023
|
}
|
|
10863
11024
|
this.setLatestFlexReasoningUpdate(
|
|
10864
11025
|
key,
|
|
10865
|
-
{
|
|
11026
|
+
{
|
|
11027
|
+
projectId: eventArg.scopeId,
|
|
11028
|
+
update,
|
|
11029
|
+
textUtf8Bytes: Buffer.byteLength(update.text, 'utf8'),
|
|
11030
|
+
},
|
|
10866
11031
|
eventBytes,
|
|
10867
11032
|
);
|
|
10868
11033
|
this.queueFlexControllerEvent(controllerEvent);
|
|
@@ -10922,12 +11087,169 @@ export class OpenCodeController {
|
|
|
10922
11087
|
}
|
|
10923
11088
|
this.setLatestFlexTextUpdate(
|
|
10924
11089
|
key,
|
|
10925
|
-
{
|
|
11090
|
+
{
|
|
11091
|
+
projectId: eventArg.scopeId,
|
|
11092
|
+
update,
|
|
11093
|
+
textUtf8Bytes: Buffer.byteLength(update.text, 'utf8'),
|
|
11094
|
+
},
|
|
10926
11095
|
eventBytes,
|
|
10927
11096
|
);
|
|
10928
11097
|
this.queueFlexControllerEvent(controllerEvent);
|
|
10929
11098
|
}
|
|
10930
11099
|
|
|
11100
|
+
private handleFlexPartDelta(
|
|
11101
|
+
eventArg: Extract<TFlexChildEvent, { type: 'part.delta' }>,
|
|
11102
|
+
): void {
|
|
11103
|
+
if (this.lifecycleState !== 'starting' && this.lifecycleState !== 'ready') return;
|
|
11104
|
+
const sourceUpdatedAt = Date.parse(eventArg.timestamp);
|
|
11105
|
+
if (!Number.isFinite(sourceUpdatedAt)) {
|
|
11106
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11107
|
+
return;
|
|
11108
|
+
}
|
|
11109
|
+
const sessionId = flexRuntimeId(eventArg.sessionId);
|
|
11110
|
+
const messageId = flexRuntimeId(eventArg.messageId);
|
|
11111
|
+
const partId = flexRuntimeId(eventArg.partId);
|
|
11112
|
+
const order = { messageIndex: eventArg.messageIndex, partIndex: eventArg.partIndex };
|
|
11113
|
+
const key = this.openCodeToolExecutionKey(eventArg.scopeId, { sessionId, partId });
|
|
11114
|
+
const cache = eventArg.partType === 'reasoning'
|
|
11115
|
+
? this.latestFlexReasoningUpdates
|
|
11116
|
+
: this.latestFlexTextUpdates;
|
|
11117
|
+
const entry = cache.get(key);
|
|
11118
|
+
const previous = entry?.update;
|
|
11119
|
+
if (
|
|
11120
|
+
!entry
|
|
11121
|
+
|| !previous
|
|
11122
|
+
|| this.flexMessageStreamEpoch === 0
|
|
11123
|
+
|| entry.projectId !== eventArg.scopeId
|
|
11124
|
+
|| previous.status !== 'running'
|
|
11125
|
+
|| previous.streamEpoch !== this.flexMessageStreamEpoch
|
|
11126
|
+
|| previous.revision > this.flexMessageStreamRevision
|
|
11127
|
+
|| controllerRuntimeIdKey(previous.sessionId) !== controllerRuntimeIdKey(sessionId)
|
|
11128
|
+
|| controllerRuntimeIdKey(previous.messageId) !== controllerRuntimeIdKey(messageId)
|
|
11129
|
+
|| controllerRuntimeIdKey(previous.partId) !== controllerRuntimeIdKey(partId)
|
|
11130
|
+
|| previous.order?.messageIndex !== order.messageIndex
|
|
11131
|
+
|| previous.order.partIndex !== order.partIndex
|
|
11132
|
+
|| sourceUpdatedAt < previous.sourceUpdatedAt
|
|
11133
|
+
|| entry.textUtf8Bytes !== eventArg.baseTextUtf8Bytes
|
|
11134
|
+
) {
|
|
11135
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11136
|
+
return;
|
|
11137
|
+
}
|
|
11138
|
+
const textUtf8Bytes = controllerTextAfterAppendUtf8Bytes(
|
|
11139
|
+
previous.text,
|
|
11140
|
+
entry.textUtf8Bytes,
|
|
11141
|
+
eventArg.delta,
|
|
11142
|
+
);
|
|
11143
|
+
if (
|
|
11144
|
+
textUtf8Bytes === undefined
|
|
11145
|
+
|| textUtf8Bytes <= entry.textUtf8Bytes
|
|
11146
|
+
|| textUtf8Bytes !== eventArg.textUtf8Bytes
|
|
11147
|
+
) {
|
|
11148
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11149
|
+
return;
|
|
11150
|
+
}
|
|
11151
|
+
|
|
11152
|
+
const revision = this.flexMessageStreamRevision + 1;
|
|
11153
|
+
const update = {
|
|
11154
|
+
...previous,
|
|
11155
|
+
text: `${previous.text}${eventArg.delta}`,
|
|
11156
|
+
sourceUpdatedAt,
|
|
11157
|
+
revision,
|
|
11158
|
+
streamEpoch: this.flexMessageStreamEpoch,
|
|
11159
|
+
} as IControllerReasoningUpdate | IControllerTextUpdate;
|
|
11160
|
+
const controllerEvent: IControllerEvent = eventArg.partType === 'reasoning'
|
|
11161
|
+
? {
|
|
11162
|
+
type: 'session.reasoning.delta',
|
|
11163
|
+
harnessId: 'flex',
|
|
11164
|
+
projectId: eventArg.scopeId,
|
|
11165
|
+
sessionId,
|
|
11166
|
+
reasoningDelta: {
|
|
11167
|
+
sessionId,
|
|
11168
|
+
messageId,
|
|
11169
|
+
partId,
|
|
11170
|
+
delta: eventArg.delta,
|
|
11171
|
+
baseTextUtf8Bytes: eventArg.baseTextUtf8Bytes,
|
|
11172
|
+
textUtf8Bytes,
|
|
11173
|
+
order,
|
|
11174
|
+
sourceUpdatedAt,
|
|
11175
|
+
revision,
|
|
11176
|
+
streamEpoch: this.flexMessageStreamEpoch,
|
|
11177
|
+
},
|
|
11178
|
+
timestamp: sourceUpdatedAt,
|
|
11179
|
+
}
|
|
11180
|
+
: {
|
|
11181
|
+
type: 'session.text.delta',
|
|
11182
|
+
harnessId: 'flex',
|
|
11183
|
+
projectId: eventArg.scopeId,
|
|
11184
|
+
sessionId,
|
|
11185
|
+
textDelta: {
|
|
11186
|
+
sessionId,
|
|
11187
|
+
messageId,
|
|
11188
|
+
partId,
|
|
11189
|
+
delta: eventArg.delta,
|
|
11190
|
+
baseTextUtf8Bytes: eventArg.baseTextUtf8Bytes,
|
|
11191
|
+
textUtf8Bytes,
|
|
11192
|
+
order,
|
|
11193
|
+
sourceUpdatedAt,
|
|
11194
|
+
revision,
|
|
11195
|
+
streamEpoch: this.flexMessageStreamEpoch,
|
|
11196
|
+
},
|
|
11197
|
+
timestamp: sourceUpdatedAt,
|
|
11198
|
+
};
|
|
11199
|
+
const snapshotEvent: IControllerEvent = eventArg.partType === 'reasoning'
|
|
11200
|
+
? {
|
|
11201
|
+
type: 'session.reasoning.updated',
|
|
11202
|
+
harnessId: 'flex',
|
|
11203
|
+
projectId: eventArg.scopeId,
|
|
11204
|
+
sessionId,
|
|
11205
|
+
reasoningUpdate: update as IControllerReasoningUpdate,
|
|
11206
|
+
timestamp: sourceUpdatedAt,
|
|
11207
|
+
}
|
|
11208
|
+
: {
|
|
11209
|
+
type: 'session.text.updated',
|
|
11210
|
+
harnessId: 'flex',
|
|
11211
|
+
projectId: eventArg.scopeId,
|
|
11212
|
+
sessionId,
|
|
11213
|
+
textUpdate: update as IControllerTextUpdate,
|
|
11214
|
+
timestamp: sourceUpdatedAt,
|
|
11215
|
+
};
|
|
11216
|
+
const eventBytes = Buffer.byteLength(JSON.stringify(controllerEvent), 'utf8');
|
|
11217
|
+
const snapshotBytes = Buffer.byteLength(JSON.stringify(snapshotEvent), 'utf8');
|
|
11218
|
+
if (
|
|
11219
|
+
eventBytes > controllerMaxLiveMessageEventBytes
|
|
11220
|
+
|| snapshotBytes > controllerMaxLiveMessageEventBytes
|
|
11221
|
+
|| this.latestFlexMessageUpdateBytes - (entry.bytes ?? 0) + snapshotBytes
|
|
11222
|
+
> maxLatestFlexMessageUpdateBytes
|
|
11223
|
+
) {
|
|
11224
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11225
|
+
return;
|
|
11226
|
+
}
|
|
11227
|
+
|
|
11228
|
+
this.flexMessageStreamRevision = revision;
|
|
11229
|
+
if (eventArg.partType === 'reasoning') {
|
|
11230
|
+
this.setLatestFlexReasoningUpdate(
|
|
11231
|
+
key,
|
|
11232
|
+
{
|
|
11233
|
+
projectId: eventArg.scopeId,
|
|
11234
|
+
update: update as IControllerReasoningUpdate,
|
|
11235
|
+
textUtf8Bytes,
|
|
11236
|
+
},
|
|
11237
|
+
snapshotBytes,
|
|
11238
|
+
);
|
|
11239
|
+
} else {
|
|
11240
|
+
this.setLatestFlexTextUpdate(
|
|
11241
|
+
key,
|
|
11242
|
+
{
|
|
11243
|
+
projectId: eventArg.scopeId,
|
|
11244
|
+
update: update as IControllerTextUpdate,
|
|
11245
|
+
textUtf8Bytes,
|
|
11246
|
+
},
|
|
11247
|
+
snapshotBytes,
|
|
11248
|
+
);
|
|
11249
|
+
}
|
|
11250
|
+
this.queueFlexControllerEvent(controllerEvent);
|
|
11251
|
+
}
|
|
11252
|
+
|
|
10931
11253
|
private getOpenCodeToolStreamCursor(): IControllerToolStreamCursor {
|
|
10932
11254
|
return {
|
|
10933
11255
|
streamEpoch: this.openCodeToolStreamEpoch,
|
|
@@ -11051,12 +11373,25 @@ export class OpenCodeController {
|
|
|
11051
11373
|
|
|
11052
11374
|
private advanceOpenCodeMessageStreamEpoch(includeSessionsChangedArg: boolean): void {
|
|
11053
11375
|
if (this.lifecycleState !== 'starting' && this.lifecycleState !== 'ready') return;
|
|
11376
|
+
const pendingEntries = includeSessionsChangedArg ? 2 : 1;
|
|
11377
|
+
if (
|
|
11378
|
+
this.pendingOpenCodeControllerEvents.size
|
|
11379
|
+
> maxPendingOpenCodeControllerEvents - pendingEntries
|
|
11380
|
+
) {
|
|
11381
|
+
this.advanceOpenCodeStreams(includeSessionsChangedArg);
|
|
11382
|
+
return;
|
|
11383
|
+
}
|
|
11054
11384
|
this.openCodeMessageStreamEpoch += 1;
|
|
11055
11385
|
this.openCodeMessageStreamRevision = 0;
|
|
11056
11386
|
this.latestOpenCodeReasoningUpdates.clear();
|
|
11057
11387
|
this.latestOpenCodeTextUpdates.clear();
|
|
11058
11388
|
for (const [key, event] of this.pendingOpenCodeControllerEvents) {
|
|
11059
|
-
if (
|
|
11389
|
+
if (
|
|
11390
|
+
event.reasoningUpdate
|
|
11391
|
+
|| event.reasoningDelta
|
|
11392
|
+
|| event.textUpdate
|
|
11393
|
+
|| event.textDelta
|
|
11394
|
+
) this.pendingOpenCodeControllerEvents.delete(key);
|
|
11060
11395
|
}
|
|
11061
11396
|
const timestamp = Date.now();
|
|
11062
11397
|
const barrier: IControllerEvent = {
|
|
@@ -11143,6 +11478,143 @@ export class OpenCodeController {
|
|
|
11143
11478
|
if (!cache.has(key) && cache.size >= maxLatestOpenCodeMessageUpdates) {
|
|
11144
11479
|
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11145
11480
|
}
|
|
11481
|
+
const previousEntry = cache.get(key);
|
|
11482
|
+
const previous = previousEntry?.update;
|
|
11483
|
+
if (
|
|
11484
|
+
previousEntry !== undefined
|
|
11485
|
+
&& previous !== undefined
|
|
11486
|
+
&& previousEntry.projectId === projectId
|
|
11487
|
+
&& previous.streamEpoch === this.openCodeMessageStreamEpoch
|
|
11488
|
+
&& previous.revision <= this.openCodeMessageStreamRevision
|
|
11489
|
+
&& controllerRuntimeIdKey(previous.sessionId) === controllerRuntimeIdKey(updateArg.sessionId)
|
|
11490
|
+
&& controllerRuntimeIdKey(previous.messageId) === controllerRuntimeIdKey(updateArg.messageId)
|
|
11491
|
+
&& controllerRuntimeIdKey(previous.partId) === controllerRuntimeIdKey(updateArg.partId)
|
|
11492
|
+
&& previous.status === 'running'
|
|
11493
|
+
&& updateArg.status === 'running'
|
|
11494
|
+
&& updateArg.text.length > previous.text.length
|
|
11495
|
+
&& updateArg.text.startsWith(previous.text)
|
|
11496
|
+
&& Number.isSafeInteger(previousEntry.textUtf8Bytes)
|
|
11497
|
+
) {
|
|
11498
|
+
const deltaText = updateArg.text.slice(previous.text.length);
|
|
11499
|
+
const fragments = fragmentControllerTextDelta(deltaText);
|
|
11500
|
+
const textUtf8Bytes = controllerTextAfterAppendUtf8Bytes(
|
|
11501
|
+
previous.text,
|
|
11502
|
+
previousEntry.textUtf8Bytes,
|
|
11503
|
+
deltaText,
|
|
11504
|
+
);
|
|
11505
|
+
const finalRevision = this.openCodeMessageStreamRevision + fragments.length;
|
|
11506
|
+
if (
|
|
11507
|
+
fragments.length === 0
|
|
11508
|
+
|| textUtf8Bytes === undefined
|
|
11509
|
+
|| textUtf8Bytes <= previousEntry.textUtf8Bytes
|
|
11510
|
+
|| !Number.isSafeInteger(finalRevision)
|
|
11511
|
+
) {
|
|
11512
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11513
|
+
return;
|
|
11514
|
+
}
|
|
11515
|
+
const update = {
|
|
11516
|
+
...updateArg,
|
|
11517
|
+
revision: finalRevision,
|
|
11518
|
+
streamEpoch: this.openCodeMessageStreamEpoch,
|
|
11519
|
+
} as IControllerReasoningUpdate | IControllerTextUpdate;
|
|
11520
|
+
const snapshotEvent: IControllerEvent = typeArg === 'reasoning'
|
|
11521
|
+
? {
|
|
11522
|
+
type: 'session.reasoning.updated',
|
|
11523
|
+
harnessId: 'opencode',
|
|
11524
|
+
projectId,
|
|
11525
|
+
sessionId: update.sessionId,
|
|
11526
|
+
reasoningUpdate: update as IControllerReasoningUpdate,
|
|
11527
|
+
timestamp: update.sourceUpdatedAt,
|
|
11528
|
+
}
|
|
11529
|
+
: {
|
|
11530
|
+
type: 'session.text.updated',
|
|
11531
|
+
harnessId: 'opencode',
|
|
11532
|
+
projectId,
|
|
11533
|
+
sessionId: update.sessionId,
|
|
11534
|
+
textUpdate: update as IControllerTextUpdate,
|
|
11535
|
+
timestamp: update.sourceUpdatedAt,
|
|
11536
|
+
};
|
|
11537
|
+
const snapshotBytes = Buffer.byteLength(JSON.stringify(snapshotEvent), 'utf8');
|
|
11538
|
+
if (snapshotBytes > controllerMaxLiveMessageEventBytes) {
|
|
11539
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11540
|
+
return;
|
|
11541
|
+
}
|
|
11542
|
+
|
|
11543
|
+
const events: IControllerEvent[] = [];
|
|
11544
|
+
let baseTextUtf8Bytes = previousEntry.textUtf8Bytes;
|
|
11545
|
+
for (const [index, fragment] of fragments.entries()) {
|
|
11546
|
+
const fragmentTextUtf8Bytes = index === 0
|
|
11547
|
+
? controllerTextAfterAppendUtf8Bytes(
|
|
11548
|
+
previous.text,
|
|
11549
|
+
baseTextUtf8Bytes,
|
|
11550
|
+
fragment.delta,
|
|
11551
|
+
)
|
|
11552
|
+
: baseTextUtf8Bytes + fragment.utf8Bytes;
|
|
11553
|
+
if (
|
|
11554
|
+
fragmentTextUtf8Bytes === undefined
|
|
11555
|
+
|| !Number.isSafeInteger(fragmentTextUtf8Bytes)
|
|
11556
|
+
|| fragmentTextUtf8Bytes <= baseTextUtf8Bytes
|
|
11557
|
+
) {
|
|
11558
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11559
|
+
return;
|
|
11560
|
+
}
|
|
11561
|
+
const revision = this.openCodeMessageStreamRevision + index + 1;
|
|
11562
|
+
const commonDelta = {
|
|
11563
|
+
sessionId: update.sessionId,
|
|
11564
|
+
messageId: update.messageId,
|
|
11565
|
+
partId: update.partId,
|
|
11566
|
+
delta: fragment.delta,
|
|
11567
|
+
baseTextUtf8Bytes,
|
|
11568
|
+
textUtf8Bytes: fragmentTextUtf8Bytes,
|
|
11569
|
+
sourceUpdatedAt: update.sourceUpdatedAt,
|
|
11570
|
+
revision,
|
|
11571
|
+
streamEpoch: this.openCodeMessageStreamEpoch,
|
|
11572
|
+
};
|
|
11573
|
+
const event: IControllerEvent = typeArg === 'reasoning'
|
|
11574
|
+
? {
|
|
11575
|
+
type: 'session.reasoning.delta',
|
|
11576
|
+
harnessId: 'opencode',
|
|
11577
|
+
projectId,
|
|
11578
|
+
sessionId: update.sessionId,
|
|
11579
|
+
reasoningDelta: commonDelta,
|
|
11580
|
+
timestamp: update.sourceUpdatedAt,
|
|
11581
|
+
}
|
|
11582
|
+
: {
|
|
11583
|
+
type: 'session.text.delta',
|
|
11584
|
+
harnessId: 'opencode',
|
|
11585
|
+
projectId,
|
|
11586
|
+
sessionId: update.sessionId,
|
|
11587
|
+
textDelta: commonDelta,
|
|
11588
|
+
timestamp: update.sourceUpdatedAt,
|
|
11589
|
+
};
|
|
11590
|
+
if (Buffer.byteLength(JSON.stringify(event), 'utf8') > controllerMaxLiveMessageEventBytes) {
|
|
11591
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11592
|
+
return;
|
|
11593
|
+
}
|
|
11594
|
+
events.push(event);
|
|
11595
|
+
baseTextUtf8Bytes = fragmentTextUtf8Bytes;
|
|
11596
|
+
}
|
|
11597
|
+
if (baseTextUtf8Bytes !== textUtf8Bytes) {
|
|
11598
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11599
|
+
return;
|
|
11600
|
+
}
|
|
11601
|
+
|
|
11602
|
+
this.openCodeMessageStreamRevision = finalRevision;
|
|
11603
|
+
cache.delete(key);
|
|
11604
|
+
cache.set(key, {
|
|
11605
|
+
projectId,
|
|
11606
|
+
update,
|
|
11607
|
+
textUtf8Bytes,
|
|
11608
|
+
bytes: snapshotBytes,
|
|
11609
|
+
} as ILatestReasoningUpdate & ILatestTextUpdate);
|
|
11610
|
+
const streamEpoch = this.openCodeMessageStreamEpoch;
|
|
11611
|
+
for (const event of events) {
|
|
11612
|
+
this.queueOpenCodeControllerEvent(event);
|
|
11613
|
+
if (this.openCodeMessageStreamEpoch !== streamEpoch) return;
|
|
11614
|
+
}
|
|
11615
|
+
return;
|
|
11616
|
+
}
|
|
11617
|
+
|
|
11146
11618
|
this.openCodeMessageStreamRevision += 1;
|
|
11147
11619
|
const update = {
|
|
11148
11620
|
...updateArg,
|
|
@@ -11166,12 +11638,18 @@ export class OpenCodeController {
|
|
|
11166
11638
|
textUpdate: update as IControllerTextUpdate,
|
|
11167
11639
|
timestamp: update.sourceUpdatedAt,
|
|
11168
11640
|
};
|
|
11169
|
-
|
|
11641
|
+
const eventBytes = Buffer.byteLength(JSON.stringify(event), 'utf8');
|
|
11642
|
+
if (eventBytes > controllerMaxLiveMessageEventBytes) {
|
|
11170
11643
|
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11171
11644
|
return;
|
|
11172
11645
|
}
|
|
11173
11646
|
cache.delete(key);
|
|
11174
|
-
cache.set(key, {
|
|
11647
|
+
cache.set(key, {
|
|
11648
|
+
projectId,
|
|
11649
|
+
update,
|
|
11650
|
+
textUtf8Bytes: Buffer.byteLength(update.text, 'utf8'),
|
|
11651
|
+
bytes: eventBytes,
|
|
11652
|
+
} as ILatestReasoningUpdate & ILatestTextUpdate);
|
|
11175
11653
|
this.queueOpenCodeControllerEvent(event);
|
|
11176
11654
|
}
|
|
11177
11655
|
|
|
@@ -11218,6 +11696,7 @@ export class OpenCodeController {
|
|
|
11218
11696
|
}
|
|
11219
11697
|
|
|
11220
11698
|
private controllerEventKey(eventArg: IControllerEvent): string {
|
|
11699
|
+
const delta = controllerEventMessageDelta(eventArg);
|
|
11221
11700
|
return JSON.stringify([
|
|
11222
11701
|
eventArg.type,
|
|
11223
11702
|
eventArg.harnessId ?? null,
|
|
@@ -11232,6 +11711,18 @@ export class OpenCodeController {
|
|
|
11232
11711
|
eventArg.textUpdate
|
|
11233
11712
|
? controllerRuntimeIdKey(eventArg.textUpdate.partId)
|
|
11234
11713
|
: null,
|
|
11714
|
+
delta
|
|
11715
|
+
? [
|
|
11716
|
+
controllerRuntimeIdKey(delta.messageId),
|
|
11717
|
+
controllerRuntimeIdKey(delta.partId),
|
|
11718
|
+
delta.streamEpoch,
|
|
11719
|
+
delta.order?.messageIndex ?? null,
|
|
11720
|
+
delta.order?.partIndex ?? null,
|
|
11721
|
+
delta.baseTextUtf8Bytes,
|
|
11722
|
+
delta.textUtf8Bytes,
|
|
11723
|
+
delta.revision,
|
|
11724
|
+
]
|
|
11725
|
+
: null,
|
|
11235
11726
|
eventArg.toolExecution
|
|
11236
11727
|
? eventArg.toolExecution.status === 'completed' || eventArg.toolExecution.status === 'error'
|
|
11237
11728
|
? 'terminal'
|
|
@@ -11248,15 +11739,59 @@ export class OpenCodeController {
|
|
|
11248
11739
|
]);
|
|
11249
11740
|
}
|
|
11250
11741
|
|
|
11251
|
-
private
|
|
11252
|
-
|
|
11742
|
+
private latestPendingControllerDelta(
|
|
11743
|
+
queueArg: Map<string, IControllerEvent>,
|
|
11744
|
+
eventArg: IControllerEvent,
|
|
11745
|
+
): { key: string; event: IControllerEvent } | undefined {
|
|
11746
|
+
const pendingKey = controllerMessageDeltaPendingKey(eventArg);
|
|
11747
|
+
if (!pendingKey) return undefined;
|
|
11748
|
+
let tail: [string, IControllerEvent] | undefined;
|
|
11749
|
+
for (const entry of queueArg) tail = entry;
|
|
11750
|
+
if (!tail || controllerMessageDeltaPendingKey(tail[1]) !== pendingKey) return undefined;
|
|
11751
|
+
return { key: tail[0], event: tail[1] };
|
|
11752
|
+
}
|
|
11753
|
+
|
|
11754
|
+
private queueOpenCodeControllerEvent(eventArg: IControllerEvent): boolean {
|
|
11755
|
+
if (this.lifecycleState !== 'starting' && this.lifecycleState !== 'ready') return false;
|
|
11756
|
+
const delta = controllerEventMessageDelta(eventArg);
|
|
11757
|
+
if (delta) {
|
|
11758
|
+
if (Buffer.byteLength(JSON.stringify(eventArg), 'utf8') > controllerMaxLiveMessageEventBytes) {
|
|
11759
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11760
|
+
return false;
|
|
11761
|
+
}
|
|
11762
|
+
const pending = this.latestPendingControllerDelta(
|
|
11763
|
+
this.pendingOpenCodeControllerEvents,
|
|
11764
|
+
eventArg,
|
|
11765
|
+
);
|
|
11766
|
+
if (pending) {
|
|
11767
|
+
const merged = mergeControllerMessageDeltaEvents(pending.event, eventArg);
|
|
11768
|
+
if (!merged) {
|
|
11769
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11770
|
+
return false;
|
|
11771
|
+
}
|
|
11772
|
+
if (
|
|
11773
|
+
Buffer.byteLength(JSON.stringify(merged), 'utf8')
|
|
11774
|
+
<= controllerMaxLiveMessageEventBytes
|
|
11775
|
+
) {
|
|
11776
|
+
this.pendingOpenCodeControllerEvents.set(pending.key, merged);
|
|
11777
|
+
this.startOpenCodeControllerEventDrain();
|
|
11778
|
+
return true;
|
|
11779
|
+
}
|
|
11780
|
+
}
|
|
11781
|
+
}
|
|
11253
11782
|
const key = this.controllerEventKey(eventArg);
|
|
11254
|
-
if (this.pendingOpenCodeControllerEvents.has(key)) {
|
|
11783
|
+
if (delta && this.pendingOpenCodeControllerEvents.has(key)) {
|
|
11784
|
+
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11785
|
+
return false;
|
|
11786
|
+
}
|
|
11787
|
+
if (!delta && this.pendingOpenCodeControllerEvents.has(key)) {
|
|
11255
11788
|
this.pendingOpenCodeControllerEvents.delete(key);
|
|
11256
11789
|
} else if (
|
|
11257
11790
|
this.pendingOpenCodeControllerEvents.size >= maxPendingOpenCodeControllerEvents
|
|
11258
11791
|
) {
|
|
11259
|
-
if (
|
|
11792
|
+
if (delta) {
|
|
11793
|
+
this.advanceOpenCodeStreams(true);
|
|
11794
|
+
} else if (eventArg.reasoningUpdate || eventArg.textUpdate) {
|
|
11260
11795
|
this.advanceOpenCodeMessageStreamEpoch(true);
|
|
11261
11796
|
} else if (eventArg.toolExecution) {
|
|
11262
11797
|
this.advanceOpenCodeToolStreamEpoch(true);
|
|
@@ -11288,10 +11823,11 @@ export class OpenCodeController {
|
|
|
11288
11823
|
rebasedEvent,
|
|
11289
11824
|
);
|
|
11290
11825
|
}
|
|
11291
|
-
return;
|
|
11826
|
+
return false;
|
|
11292
11827
|
}
|
|
11293
11828
|
this.pendingOpenCodeControllerEvents.set(key, eventArg);
|
|
11294
11829
|
this.startOpenCodeControllerEventDrain();
|
|
11830
|
+
return true;
|
|
11295
11831
|
}
|
|
11296
11832
|
|
|
11297
11833
|
private startOpenCodeControllerEventDrain(): void {
|
|
@@ -11358,7 +11894,11 @@ export class OpenCodeController {
|
|
|
11358
11894
|
};
|
|
11359
11895
|
this.setLatestFlexReasoningUpdate(
|
|
11360
11896
|
this.openCodeToolExecutionKey(eventArg.projectId, update),
|
|
11361
|
-
{
|
|
11897
|
+
{
|
|
11898
|
+
projectId: eventArg.projectId,
|
|
11899
|
+
update,
|
|
11900
|
+
textUtf8Bytes: Buffer.byteLength(update.text, 'utf8'),
|
|
11901
|
+
},
|
|
11362
11902
|
Buffer.byteLength(JSON.stringify(event), 'utf8'),
|
|
11363
11903
|
);
|
|
11364
11904
|
return event;
|
|
@@ -11377,7 +11917,11 @@ export class OpenCodeController {
|
|
|
11377
11917
|
};
|
|
11378
11918
|
this.setLatestFlexTextUpdate(
|
|
11379
11919
|
this.openCodeToolExecutionKey(eventArg.projectId, update),
|
|
11380
|
-
{
|
|
11920
|
+
{
|
|
11921
|
+
projectId: eventArg.projectId,
|
|
11922
|
+
update,
|
|
11923
|
+
textUtf8Bytes: Buffer.byteLength(update.text, 'utf8'),
|
|
11924
|
+
},
|
|
11381
11925
|
Buffer.byteLength(JSON.stringify(event), 'utf8'),
|
|
11382
11926
|
);
|
|
11383
11927
|
return event;
|
|
@@ -11385,10 +11929,51 @@ export class OpenCodeController {
|
|
|
11385
11929
|
return eventArg;
|
|
11386
11930
|
}
|
|
11387
11931
|
|
|
11388
|
-
private queueFlexControllerEvent(eventArg: IControllerEvent):
|
|
11389
|
-
if (this.lifecycleState !== 'starting' && this.lifecycleState !== 'ready') return;
|
|
11932
|
+
private queueFlexControllerEvent(eventArg: IControllerEvent): boolean {
|
|
11933
|
+
if (this.lifecycleState !== 'starting' && this.lifecycleState !== 'ready') return false;
|
|
11934
|
+
const delta = controllerEventMessageDelta(eventArg);
|
|
11935
|
+
if (delta) {
|
|
11936
|
+
if (Buffer.byteLength(JSON.stringify(eventArg), 'utf8') > controllerMaxLiveMessageEventBytes) {
|
|
11937
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11938
|
+
return false;
|
|
11939
|
+
}
|
|
11940
|
+
const pending = this.latestPendingControllerDelta(
|
|
11941
|
+
this.pendingFlexControllerEvents,
|
|
11942
|
+
eventArg,
|
|
11943
|
+
);
|
|
11944
|
+
if (pending) {
|
|
11945
|
+
const merged = mergeControllerMessageDeltaEvents(pending.event, eventArg);
|
|
11946
|
+
if (!merged) {
|
|
11947
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11948
|
+
return false;
|
|
11949
|
+
}
|
|
11950
|
+
const mergedBytes = this.flexControllerEventLiveBytes(merged);
|
|
11951
|
+
if (
|
|
11952
|
+
mergedBytes.message <= controllerMaxLiveMessageEventBytes
|
|
11953
|
+
) {
|
|
11954
|
+
const pendingBytes = this.flexControllerEventLiveBytes(pending.event);
|
|
11955
|
+
if (
|
|
11956
|
+
this.latestFlexMessageUpdateBytes
|
|
11957
|
+
+ this.pendingFlexMessageEventBytes
|
|
11958
|
+
- pendingBytes.message
|
|
11959
|
+
+ mergedBytes.message
|
|
11960
|
+
> maxLatestFlexMessageUpdateBytes
|
|
11961
|
+
) {
|
|
11962
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11963
|
+
return false;
|
|
11964
|
+
}
|
|
11965
|
+
this.setPendingFlexControllerEvent(pending.key, merged);
|
|
11966
|
+
this.startFlexControllerEventDrain();
|
|
11967
|
+
return true;
|
|
11968
|
+
}
|
|
11969
|
+
}
|
|
11970
|
+
}
|
|
11390
11971
|
const key = this.controllerEventKey(eventArg);
|
|
11391
|
-
this.
|
|
11972
|
+
if (delta && this.pendingFlexControllerEvents.has(key)) {
|
|
11973
|
+
this.advanceFlexMessageStreamEpoch(true);
|
|
11974
|
+
return false;
|
|
11975
|
+
}
|
|
11976
|
+
if (!delta) this.deletePendingFlexControllerEvent(key);
|
|
11392
11977
|
const liveBytes = this.flexControllerEventLiveBytes(eventArg);
|
|
11393
11978
|
const exceedsCountBound = this.pendingFlexControllerEvents.size >= maxPendingFlexControllerEvents;
|
|
11394
11979
|
const exceedsPendingBound = exceedsCountBound
|
|
@@ -11403,7 +11988,12 @@ export class OpenCodeController {
|
|
|
11403
11988
|
|| this.pendingFlexControllerEvents.size > maxPendingFlexControllerEvents - 3;
|
|
11404
11989
|
if (requiresCountCollapse) {
|
|
11405
11990
|
this.advanceFlexStreams(true);
|
|
11406
|
-
} else if (
|
|
11991
|
+
} else if (
|
|
11992
|
+
eventArg.reasoningUpdate
|
|
11993
|
+
|| eventArg.reasoningDelta
|
|
11994
|
+
|| eventArg.textUpdate
|
|
11995
|
+
|| eventArg.textDelta
|
|
11996
|
+
) {
|
|
11407
11997
|
this.advanceFlexMessageStreamEpoch(true);
|
|
11408
11998
|
} else if (eventArg.toolExecution) {
|
|
11409
11999
|
this.advanceFlexToolStreamEpoch(true);
|
|
@@ -11421,10 +12011,11 @@ export class OpenCodeController {
|
|
|
11421
12011
|
this.setPendingFlexControllerEvent(this.controllerEventKey(rebasedEvent), rebasedEvent);
|
|
11422
12012
|
}
|
|
11423
12013
|
this.startFlexControllerEventDrain();
|
|
11424
|
-
return;
|
|
12014
|
+
return false;
|
|
11425
12015
|
}
|
|
11426
12016
|
this.setPendingFlexControllerEvent(key, eventArg);
|
|
11427
12017
|
this.startFlexControllerEventDrain();
|
|
12018
|
+
return true;
|
|
11428
12019
|
}
|
|
11429
12020
|
|
|
11430
12021
|
private startFlexControllerEventDrain(): void {
|