@omercnet/paseo-omp 0.4.0-next.119.1 → 0.4.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/package.json +1 -3
- package/server/package-version.ts +1 -1
- package/server/provider/connection.ts +1 -28
- package/server/provider/omp-rpc.ts +178 -792
- package/server/provider/session-descriptors.ts +18 -52
- package/server/provider/session.ts +1 -12
- package/server/provider/subsessions.ts +6 -28
- package/server/provider/timeline-projector.ts +24 -94
|
@@ -86,105 +86,7 @@ const MAX_RPC_ERROR_BYTES = 4_096;
|
|
|
86
86
|
const MAX_RPC_ERROR_CODE_BYTES = 256;
|
|
87
87
|
const PROMPT_SCHEDULING_FAILURE = "OMP prompt scheduling failed";
|
|
88
88
|
const PROTOCOL_VIOLATION_COALESCE_MS = 10_000;
|
|
89
|
-
|
|
90
|
-
const MAX_REPLAY_BYTES = 64 * 1024 * 1024;
|
|
91
|
-
const MAX_REPLAY_NODES = 400_000;
|
|
92
|
-
const OMP_MESSAGE_PAGE_LIMIT = 256;
|
|
93
|
-
const MAX_MESSAGE_PAGES = 512;
|
|
94
|
-
const MAX_MESSAGE_PAGE_BUSY_RETRIES = 4;
|
|
95
|
-
const MAX_MESSAGE_PAGE_STALE_RESTARTS = 2;
|
|
96
|
-
const MESSAGE_PAGE_RETRY_BASE_MS = 50;
|
|
97
|
-
|
|
98
|
-
export const OMP_MESSAGE_REPLAY_POLICIES = {
|
|
99
|
-
assistant: "render",
|
|
100
|
-
user: "render",
|
|
101
|
-
developer: "ignore",
|
|
102
|
-
toolResult: "render",
|
|
103
|
-
bashExecution: "normalize",
|
|
104
|
-
pythonExecution: "normalize",
|
|
105
|
-
custom: "normalize",
|
|
106
|
-
hookMessage: "normalize",
|
|
107
|
-
branchSummary: "ignore",
|
|
108
|
-
compactionSummary: "ignore",
|
|
109
|
-
fileMention: "ignore",
|
|
110
|
-
} as const;
|
|
111
|
-
|
|
112
|
-
export const OMP_SESSION_EVENT_POLICIES = {
|
|
113
|
-
agent_start: "lifecycle",
|
|
114
|
-
agent_end: "lifecycle",
|
|
115
|
-
turn_start: "lifecycle",
|
|
116
|
-
turn_end: "lifecycle",
|
|
117
|
-
message_start: "normalize",
|
|
118
|
-
message_update: "normalize",
|
|
119
|
-
message_end: "normalize",
|
|
120
|
-
tool_execution_start: "normalize",
|
|
121
|
-
tool_execution_update: "normalize",
|
|
122
|
-
tool_stream_update: "normalize",
|
|
123
|
-
tool_execution_end: "normalize",
|
|
124
|
-
auto_compaction_start: "normalize",
|
|
125
|
-
auto_compaction_end: "normalize",
|
|
126
|
-
auto_retry_start: "normalize",
|
|
127
|
-
auto_retry_end: "normalize",
|
|
128
|
-
retry_fallback_applied: "normalize",
|
|
129
|
-
retry_fallback_succeeded: "normalize",
|
|
130
|
-
model_changed: "normalize",
|
|
131
|
-
config_warnings_changed: "ignore",
|
|
132
|
-
advisor_cost_changed: "ignore",
|
|
133
|
-
advisor_yielded: "normalize",
|
|
134
|
-
ttsr_triggered: "ignore",
|
|
135
|
-
todo_reminder: "normalize",
|
|
136
|
-
todo_auto_clear: "normalize",
|
|
137
|
-
irc_message: "normalize",
|
|
138
|
-
notice: "normalize",
|
|
139
|
-
thinking_level_changed: "normalize",
|
|
140
|
-
goal_updated: "normalize",
|
|
141
|
-
} as const;
|
|
142
|
-
|
|
143
|
-
export const OMP_RPC_COMMAND_POLICIES = {
|
|
144
|
-
negotiate_protocol: "implemented",
|
|
145
|
-
prompt: "implemented",
|
|
146
|
-
steer: "implemented",
|
|
147
|
-
follow_up: "implemented",
|
|
148
|
-
abort: "implemented",
|
|
149
|
-
abort_and_prompt: "unsupported",
|
|
150
|
-
new_session: "unsupported",
|
|
151
|
-
get_state: "implemented",
|
|
152
|
-
set_fast_mode: "unsupported",
|
|
153
|
-
get_available_commands: "implemented",
|
|
154
|
-
set_todos: "unsupported",
|
|
155
|
-
set_host_tools: "implemented",
|
|
156
|
-
set_host_uri_schemes: "unsupported",
|
|
157
|
-
set_subagent_subscription: "implemented",
|
|
158
|
-
get_subagents: "implemented",
|
|
159
|
-
get_subagent_messages: "implemented",
|
|
160
|
-
set_model: "implemented",
|
|
161
|
-
cycle_model: "unsupported",
|
|
162
|
-
get_available_models: "implemented",
|
|
163
|
-
set_thinking_level: "implemented",
|
|
164
|
-
cycle_thinking_level: "unsupported",
|
|
165
|
-
set_steering_mode: "unsupported",
|
|
166
|
-
set_follow_up_mode: "unsupported",
|
|
167
|
-
set_interrupt_mode: "unsupported",
|
|
168
|
-
compact: "implemented",
|
|
169
|
-
set_auto_compaction: "implemented",
|
|
170
|
-
set_auto_retry: "unsupported",
|
|
171
|
-
abort_retry: "unsupported",
|
|
172
|
-
bash: "unsupported",
|
|
173
|
-
abort_bash: "unsupported",
|
|
174
|
-
get_session_stats: "implemented",
|
|
175
|
-
export_html: "unsupported",
|
|
176
|
-
switch_session: "unsupported",
|
|
177
|
-
branch: "implemented",
|
|
178
|
-
get_branch_messages: "implemented",
|
|
179
|
-
get_last_assistant_text: "unsupported",
|
|
180
|
-
set_session_name: "unsupported",
|
|
181
|
-
handoff: "implemented",
|
|
182
|
-
get_messages: "implemented",
|
|
183
|
-
get_messages_page: "implemented",
|
|
184
|
-
get_login_providers: "unsupported",
|
|
185
|
-
login: "unsupported",
|
|
186
|
-
} as const;
|
|
187
|
-
export const OMP_RPC_RESPONSE_POLICIES = OMP_RPC_COMMAND_POLICIES;
|
|
89
|
+
|
|
188
90
|
export const OMP_PROTOCOL_VIOLATION_CATEGORIES = [
|
|
189
91
|
"duplicate-ready",
|
|
190
92
|
"frame-limit",
|
|
@@ -254,7 +156,6 @@ export const OMP_PROTOCOL_EVENT_TYPES = [
|
|
|
254
156
|
"tool_execution_start",
|
|
255
157
|
"tool_execution_update",
|
|
256
158
|
"tool_execution_end",
|
|
257
|
-
"tool_stream_update",
|
|
258
159
|
"compaction_start",
|
|
259
160
|
"compaction_end",
|
|
260
161
|
"subagent_lifecycle",
|
|
@@ -262,10 +163,6 @@ export const OMP_PROTOCOL_EVENT_TYPES = [
|
|
|
262
163
|
"subagent_event",
|
|
263
164
|
"todo_reminder",
|
|
264
165
|
"model_changed",
|
|
265
|
-
"config_warnings_changed",
|
|
266
|
-
"advisor_cost_changed",
|
|
267
|
-
"ttsr_triggered",
|
|
268
|
-
"irc_message",
|
|
269
166
|
"thinking_level_changed",
|
|
270
167
|
"goal_updated",
|
|
271
168
|
"auto_retry_start",
|
|
@@ -395,11 +292,8 @@ function eventSchemaClassification(
|
|
|
395
292
|
case "message_update":
|
|
396
293
|
case "message_end":
|
|
397
294
|
return { reason: "message-event-schema", expected: "valid-message-event" };
|
|
398
|
-
case "irc_message":
|
|
399
|
-
return { reason: "message-event-schema", expected: "valid-message-event" };
|
|
400
295
|
case "tool_execution_start":
|
|
401
296
|
case "tool_execution_update":
|
|
402
|
-
case "tool_stream_update":
|
|
403
297
|
case "tool_execution_end":
|
|
404
298
|
case "host_tool_call":
|
|
405
299
|
case "host_tool_cancel":
|
|
@@ -418,9 +312,6 @@ function eventSchemaClassification(
|
|
|
418
312
|
case "available_commands_update":
|
|
419
313
|
case "retry_fallback_applied":
|
|
420
314
|
case "retry_fallback_succeeded":
|
|
421
|
-
case "config_warnings_changed":
|
|
422
|
-
case "advisor_cost_changed":
|
|
423
|
-
case "ttsr_triggered":
|
|
424
315
|
return { reason: "configuration-event-schema", expected: "valid-configuration-event" };
|
|
425
316
|
case "extension_ui_request":
|
|
426
317
|
return { reason: "extension-ui-schema", expected: "valid-extension-ui-event" };
|
|
@@ -517,13 +408,6 @@ function boundedString(maxBytes: number, minBytes = 0) {
|
|
|
517
408
|
return bytes >= minBytes && bytes <= maxBytes;
|
|
518
409
|
});
|
|
519
410
|
}
|
|
520
|
-
function isSafeOpaqueCursor(value: string): boolean {
|
|
521
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
522
|
-
const code = value.charCodeAt(index);
|
|
523
|
-
if (code <= 0x1f || code === 0x7f) return false;
|
|
524
|
-
}
|
|
525
|
-
return true;
|
|
526
|
-
}
|
|
527
411
|
function boundedOptionalStringArray(maxItems: number, maxBytes: number) {
|
|
528
412
|
return z.unknown().transform((value): string[] | undefined => {
|
|
529
413
|
if (!Array.isArray(value)) return undefined;
|
|
@@ -581,7 +465,7 @@ function sanitizeLiveMessageDisplay(value: unknown): unknown {
|
|
|
581
465
|
return content === message.content ? value : { ...message, content };
|
|
582
466
|
}
|
|
583
467
|
if (
|
|
584
|
-
|
|
468
|
+
message.role === "bashExecution" &&
|
|
585
469
|
typeof message.output === "string" &&
|
|
586
470
|
utf8Bytes(message.output) > MAX_IMAGE_DATA_LENGTH
|
|
587
471
|
) {
|
|
@@ -623,178 +507,6 @@ function isBoundedJson(
|
|
|
623
507
|
boundedJsonBytes(value, maxBytes, maxItems, maxBytes, maxNodes) !== Number.POSITIVE_INFINITY
|
|
624
508
|
);
|
|
625
509
|
}
|
|
626
|
-
const MAX_RESPONSE_DEPTH = 16;
|
|
627
|
-
export const OMP_RPC_BOUND_DIMENSIONS = [
|
|
628
|
-
"bytes",
|
|
629
|
-
"items",
|
|
630
|
-
"nodes",
|
|
631
|
-
"depth",
|
|
632
|
-
"string-bytes",
|
|
633
|
-
] as const;
|
|
634
|
-
export type OmpRpcBoundDimension = (typeof OMP_RPC_BOUND_DIMENSIONS)[number];
|
|
635
|
-
export const OMP_RPC_DIAGNOSTIC_COMMANDS = [
|
|
636
|
-
"negotiate_protocol",
|
|
637
|
-
"get_state",
|
|
638
|
-
"get_session_stats",
|
|
639
|
-
"get_available_models",
|
|
640
|
-
"get_available_commands",
|
|
641
|
-
"set_subagent_subscription",
|
|
642
|
-
"get_subagents",
|
|
643
|
-
"get_subagent_messages",
|
|
644
|
-
"prompt",
|
|
645
|
-
"compact",
|
|
646
|
-
"set_auto_compaction",
|
|
647
|
-
"set_model",
|
|
648
|
-
"set_thinking_level",
|
|
649
|
-
"handoff",
|
|
650
|
-
"get_branch_messages",
|
|
651
|
-
"branch",
|
|
652
|
-
"get_messages_page",
|
|
653
|
-
"get_messages",
|
|
654
|
-
"abort",
|
|
655
|
-
"set_host_tools",
|
|
656
|
-
] as const;
|
|
657
|
-
export type OmpRpcDiagnosticCommand = (typeof OMP_RPC_DIAGNOSTIC_COMMANDS)[number];
|
|
658
|
-
type JsonBoundViolation = {
|
|
659
|
-
dimension: OmpRpcBoundDimension;
|
|
660
|
-
actual: number;
|
|
661
|
-
limit: number;
|
|
662
|
-
};
|
|
663
|
-
type JsonBoundInspection = { bytes: number; nodes: number; violation?: JsonBoundViolation };
|
|
664
|
-
|
|
665
|
-
function rpcDiagnosticCommand(value: string): OmpRpcDiagnosticCommand | undefined {
|
|
666
|
-
return (OMP_RPC_DIAGNOSTIC_COMMANDS as readonly string[]).includes(value)
|
|
667
|
-
? (value as OmpRpcDiagnosticCommand)
|
|
668
|
-
: undefined;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
function encodedJsonStringBytes(value: string): number {
|
|
672
|
-
let bytes = 2;
|
|
673
|
-
for (let index = 0; index < value.length; index += 1) {
|
|
674
|
-
const code = value.charCodeAt(index);
|
|
675
|
-
if (code === 0x22 || code === 0x5c) {
|
|
676
|
-
bytes += 2;
|
|
677
|
-
} else if (code <= 0x1f) {
|
|
678
|
-
bytes +=
|
|
679
|
-
code === 0x08 || code === 0x09 || code === 0x0a || code === 0x0c || code === 0x0d ? 2 : 6;
|
|
680
|
-
} else if (code >= 0xd800 && code <= 0xdbff) {
|
|
681
|
-
const low = value.charCodeAt(index + 1);
|
|
682
|
-
if (low >= 0xdc00 && low <= 0xdfff) {
|
|
683
|
-
bytes += 4;
|
|
684
|
-
index += 1;
|
|
685
|
-
} else {
|
|
686
|
-
bytes += 6;
|
|
687
|
-
}
|
|
688
|
-
} else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
689
|
-
bytes += 6;
|
|
690
|
-
} else {
|
|
691
|
-
bytes += code <= 0x7f ? 1 : code <= 0x7ff ? 2 : 3;
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
|
-
return bytes;
|
|
695
|
-
}
|
|
696
|
-
|
|
697
|
-
function inspectJsonBounds(
|
|
698
|
-
value: unknown,
|
|
699
|
-
maxBytes: number,
|
|
700
|
-
maxItems: number,
|
|
701
|
-
maxStringBytes: number,
|
|
702
|
-
maxNodes: number,
|
|
703
|
-
): JsonBoundInspection {
|
|
704
|
-
const stack: Array<{ value: unknown; depth: number }> = [{ value, depth: 0 }];
|
|
705
|
-
let nodes = 0;
|
|
706
|
-
let bytes = 0;
|
|
707
|
-
const addBytes = (count: number): JsonBoundViolation | undefined => {
|
|
708
|
-
bytes += count;
|
|
709
|
-
return bytes > maxBytes ? { dimension: "bytes", actual: bytes, limit: maxBytes } : undefined;
|
|
710
|
-
};
|
|
711
|
-
while (stack.length > 0) {
|
|
712
|
-
const current = stack.pop();
|
|
713
|
-
if (!current) break;
|
|
714
|
-
nodes += 1;
|
|
715
|
-
if (nodes > maxNodes)
|
|
716
|
-
return { bytes, nodes, violation: { dimension: "nodes", actual: nodes, limit: maxNodes } };
|
|
717
|
-
if (current.depth > MAX_RESPONSE_DEPTH) {
|
|
718
|
-
return {
|
|
719
|
-
bytes,
|
|
720
|
-
nodes,
|
|
721
|
-
violation: { dimension: "depth", actual: current.depth, limit: MAX_RESPONSE_DEPTH },
|
|
722
|
-
};
|
|
723
|
-
}
|
|
724
|
-
const item = current.value;
|
|
725
|
-
if (item === null) {
|
|
726
|
-
const violation = addBytes(4);
|
|
727
|
-
if (violation) return { bytes, nodes, violation };
|
|
728
|
-
continue;
|
|
729
|
-
}
|
|
730
|
-
if (typeof item === "boolean") {
|
|
731
|
-
const violation = addBytes(item ? 4 : 5);
|
|
732
|
-
if (violation) return { bytes, nodes, violation };
|
|
733
|
-
continue;
|
|
734
|
-
}
|
|
735
|
-
if (typeof item === "number") {
|
|
736
|
-
const violation = addBytes((JSON.stringify(item) ?? "null").length);
|
|
737
|
-
if (violation) return { bytes, nodes, violation };
|
|
738
|
-
continue;
|
|
739
|
-
}
|
|
740
|
-
if (typeof item === "string") {
|
|
741
|
-
const itemBytes = utf8Bytes(item);
|
|
742
|
-
if (itemBytes > maxStringBytes) {
|
|
743
|
-
return {
|
|
744
|
-
bytes,
|
|
745
|
-
nodes,
|
|
746
|
-
violation: { dimension: "string-bytes", actual: itemBytes, limit: maxStringBytes },
|
|
747
|
-
};
|
|
748
|
-
}
|
|
749
|
-
const violation = addBytes(encodedJsonStringBytes(item));
|
|
750
|
-
if (violation) return { bytes, nodes, violation };
|
|
751
|
-
continue;
|
|
752
|
-
}
|
|
753
|
-
if (typeof item !== "object") continue;
|
|
754
|
-
if (Array.isArray(item)) {
|
|
755
|
-
if (item.length > maxItems) {
|
|
756
|
-
return {
|
|
757
|
-
bytes,
|
|
758
|
-
nodes,
|
|
759
|
-
violation: { dimension: "items", actual: item.length, limit: maxItems },
|
|
760
|
-
};
|
|
761
|
-
}
|
|
762
|
-
const violation = addBytes(2 + Math.max(0, item.length - 1));
|
|
763
|
-
if (violation) return { bytes, nodes, violation };
|
|
764
|
-
for (let index = item.length - 1; index >= 0; index -= 1) {
|
|
765
|
-
stack.push({ value: item[index], depth: current.depth + 1 });
|
|
766
|
-
}
|
|
767
|
-
continue;
|
|
768
|
-
}
|
|
769
|
-
const entries = Object.entries(item).filter(([, child]) => child !== undefined);
|
|
770
|
-
if (entries.length > maxItems) {
|
|
771
|
-
return {
|
|
772
|
-
bytes,
|
|
773
|
-
nodes,
|
|
774
|
-
violation: { dimension: "items", actual: entries.length, limit: maxItems },
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
let violation = addBytes(2 + Math.max(0, entries.length - 1) + entries.length);
|
|
778
|
-
if (violation) return { bytes, nodes, violation };
|
|
779
|
-
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
780
|
-
const [key, child] = entries[index] as [string, unknown];
|
|
781
|
-
violation = addBytes(encodedJsonStringBytes(key));
|
|
782
|
-
if (violation) return { bytes, nodes, violation };
|
|
783
|
-
stack.push({ value: child, depth: current.depth + 1 });
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
return { bytes, nodes };
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
function jsonBoundViolation(
|
|
790
|
-
value: unknown,
|
|
791
|
-
maxBytes: number,
|
|
792
|
-
maxItems: number,
|
|
793
|
-
maxStringBytes: number,
|
|
794
|
-
maxNodes: number,
|
|
795
|
-
): JsonBoundViolation | undefined {
|
|
796
|
-
return inspectJsonBounds(value, maxBytes, maxItems, maxStringBytes, maxNodes).violation;
|
|
797
|
-
}
|
|
798
510
|
function optionalMetadataMetrics(value: unknown) {
|
|
799
511
|
return boundedJsonMetrics(
|
|
800
512
|
value,
|
|
@@ -994,46 +706,52 @@ const OmpMessageIdentityShape = {
|
|
|
994
706
|
timestamp: z.number().finite().optional(),
|
|
995
707
|
details: OmpOptionalMetadataSchema,
|
|
996
708
|
};
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
meta: OmpOptionalMetadataSchema,
|
|
1014
|
-
};
|
|
1015
|
-
const OmpCustomMessageShape = {
|
|
1016
|
-
customType: NAME.optional(),
|
|
1017
|
-
content: OmpDisplayContentSchema.optional(),
|
|
1018
|
-
display: z.boolean().optional(),
|
|
1019
|
-
attribution: OmpOpaqueMessagePayloadSchema.optional(),
|
|
709
|
+
type OmpContentPart = z.infer<typeof OmpContentPartSchema>;
|
|
710
|
+
type OmpMessageIdentity = {
|
|
711
|
+
id?: string;
|
|
712
|
+
entryId?: string;
|
|
713
|
+
responseId?: string;
|
|
714
|
+
images?: OmpContentPart[];
|
|
715
|
+
timestamp?: number;
|
|
716
|
+
details?: unknown;
|
|
717
|
+
display?: boolean;
|
|
718
|
+
customType?: string;
|
|
719
|
+
content?: unknown;
|
|
720
|
+
command?: string;
|
|
721
|
+
output?: string;
|
|
722
|
+
exitCode?: number | null;
|
|
723
|
+
cancelled?: boolean;
|
|
724
|
+
truncated?: boolean;
|
|
1020
725
|
};
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
726
|
+
export type OmpMessage = OmpMessageIdentity &
|
|
727
|
+
(
|
|
728
|
+
| {
|
|
729
|
+
role: "assistant";
|
|
730
|
+
content?: string | OmpContentPart[];
|
|
731
|
+
errorMessage?: string | null;
|
|
732
|
+
stopReason?: string;
|
|
733
|
+
}
|
|
734
|
+
| { role: "user"; content: string | OmpContentPart[] }
|
|
735
|
+
| {
|
|
736
|
+
role: "toolResult";
|
|
737
|
+
toolCallId: string;
|
|
738
|
+
toolName: string;
|
|
739
|
+
content: unknown;
|
|
740
|
+
details?: unknown;
|
|
741
|
+
isError?: boolean;
|
|
742
|
+
}
|
|
743
|
+
| {
|
|
744
|
+
role: "bashExecution";
|
|
745
|
+
command: string;
|
|
746
|
+
output?: string;
|
|
747
|
+
exitCode?: number | null;
|
|
748
|
+
cancelled?: boolean;
|
|
749
|
+
truncated?: boolean;
|
|
750
|
+
}
|
|
751
|
+
| { role: "custom"; customType?: string; content?: unknown; display?: boolean }
|
|
752
|
+
);
|
|
1035
753
|
|
|
1036
|
-
const OmpMessageSchema = z.
|
|
754
|
+
const OmpMessageSchema: z.ZodType<OmpMessage> = z.union([
|
|
1037
755
|
z.object({
|
|
1038
756
|
role: z.literal("assistant"),
|
|
1039
757
|
content: OmpAssistantDisplayContentSchema.optional(),
|
|
@@ -1046,70 +764,42 @@ const OmpMessageSchema = z.discriminatedUnion("role", [
|
|
|
1046
764
|
content: OmpDisplayContentSchema,
|
|
1047
765
|
...OmpMessageIdentityShape,
|
|
1048
766
|
}),
|
|
1049
|
-
z.object({
|
|
1050
|
-
role: z.literal("developer"),
|
|
1051
|
-
content: OmpDisplayContentSchema,
|
|
1052
|
-
attribution: OmpOpaqueMessagePayloadSchema.optional(),
|
|
1053
|
-
synthetic: z.boolean().optional(),
|
|
1054
|
-
userInitiated: z.boolean().optional(),
|
|
1055
|
-
providerPayload: OmpOpaqueMessagePayloadSchema.optional(),
|
|
1056
|
-
...OmpMessageIdentityShape,
|
|
1057
|
-
}),
|
|
1058
767
|
z.object({
|
|
1059
768
|
role: z.literal("toolResult"),
|
|
1060
769
|
toolCallId: IDENTIFIER,
|
|
1061
770
|
toolName: NAME,
|
|
1062
|
-
content:
|
|
771
|
+
content: z
|
|
772
|
+
.unknown()
|
|
773
|
+
.refine((value) => isBoundedJson(value, MAX_SEMANTIC_FRAME_BYTES, 1_024, 8_192)),
|
|
1063
774
|
isError: z.boolean().optional(),
|
|
1064
|
-
attribution: OmpOpaqueMessagePayloadSchema.optional(),
|
|
1065
|
-
prunedAt: z.number().finite().nonnegative().optional(),
|
|
1066
|
-
providerMetadata: OmpOpaqueMessagePayloadSchema.optional(),
|
|
1067
|
-
useless: z.boolean().optional(),
|
|
1068
775
|
...OmpMessageIdentityShape,
|
|
1069
776
|
}),
|
|
1070
777
|
z.object({
|
|
1071
778
|
role: z.literal("bashExecution"),
|
|
1072
779
|
command: TEXT,
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
z.object({
|
|
1084
|
-
role: z.literal("hookMessage"),
|
|
1085
|
-
...OmpCustomMessageShape,
|
|
1086
|
-
...OmpMessageIdentityShape,
|
|
1087
|
-
}),
|
|
1088
|
-
z.object({
|
|
1089
|
-
role: z.literal("branchSummary"),
|
|
1090
|
-
summary: TEXT,
|
|
1091
|
-
fromId: IDENTIFIER,
|
|
1092
|
-
...OmpMessageIdentityShape,
|
|
1093
|
-
}),
|
|
1094
|
-
z.object({
|
|
1095
|
-
role: z.literal("compactionSummary"),
|
|
1096
|
-
summary: TEXT,
|
|
1097
|
-
shortSummary: TEXT.optional(),
|
|
1098
|
-
tokensBefore: z.number().finite().nonnegative(),
|
|
1099
|
-
tokensAfter: z.number().finite().nonnegative().optional(),
|
|
1100
|
-
method: NAME.optional(),
|
|
1101
|
-
providerPayload: OmpOpaqueMessagePayloadSchema.optional(),
|
|
1102
|
-
blocks: z.array(OmpContentPartSchema).max(OMP_MAX_CONTENT_PARTS).optional(),
|
|
1103
|
-
warning: boundedString(64 * 1024).optional(),
|
|
780
|
+
output: z.preprocess(
|
|
781
|
+
(value) =>
|
|
782
|
+
typeof value === "string" && utf8Bytes(value) > MAX_IMAGE_DATA_LENGTH
|
|
783
|
+
? DISPLAY_TRUNCATION_MARKER
|
|
784
|
+
: value,
|
|
785
|
+
RAW_DISPLAY_TEXT.optional(),
|
|
786
|
+
),
|
|
787
|
+
exitCode: z.number().int().nullable().optional(),
|
|
788
|
+
cancelled: z.boolean().optional(),
|
|
789
|
+
truncated: z.boolean().optional(),
|
|
1104
790
|
...OmpMessageIdentityShape,
|
|
1105
791
|
}),
|
|
1106
792
|
z.object({
|
|
1107
|
-
role: z.literal("
|
|
1108
|
-
|
|
793
|
+
role: z.literal("custom"),
|
|
794
|
+
customType: NAME.optional(),
|
|
795
|
+
content: z
|
|
796
|
+
.unknown()
|
|
797
|
+
.refine((value) => isBoundedJson(value, MAX_SEMANTIC_FRAME_BYTES, 1_024, 8_192))
|
|
798
|
+
.optional(),
|
|
799
|
+
display: z.boolean().optional(),
|
|
1109
800
|
...OmpMessageIdentityShape,
|
|
1110
801
|
}),
|
|
1111
802
|
]);
|
|
1112
|
-
export type OmpMessage = z.infer<typeof OmpMessageSchema>;
|
|
1113
803
|
|
|
1114
804
|
const OmpAssistantMessageEventSchema = z
|
|
1115
805
|
.object({
|
|
@@ -1258,7 +948,6 @@ const OmpReadyFrameSchema = z.object({
|
|
|
1258
948
|
const OmpResponseFrameSchema = z.object({
|
|
1259
949
|
type: z.literal("response"),
|
|
1260
950
|
id: IDENTIFIER,
|
|
1261
|
-
command: boundedString(64, 1).optional(),
|
|
1262
951
|
success: z.boolean(),
|
|
1263
952
|
data: z.unknown().optional(),
|
|
1264
953
|
error: boundedString(MAX_RPC_ERROR_BYTES).optional(),
|
|
@@ -1464,7 +1153,7 @@ const OmpCompactionEndSchema = z.object({
|
|
|
1464
1153
|
errorMessage: boundedString(4_096).optional(),
|
|
1465
1154
|
skipped: z.boolean().optional(),
|
|
1466
1155
|
});
|
|
1467
|
-
const
|
|
1156
|
+
const OmpAgentSessionEventSchema = z.discriminatedUnion("type", [
|
|
1468
1157
|
z.object({ type: z.literal("agent_start") }),
|
|
1469
1158
|
z.object({
|
|
1470
1159
|
type: z.literal("agent_end"),
|
|
@@ -1495,12 +1184,6 @@ const OmpCoreAgentEventSchema = z.discriminatedUnion("type", [
|
|
|
1495
1184
|
args: BoundedToolPayloadSchema.optional(),
|
|
1496
1185
|
partialResult: OmpToolResultPayloadSchema,
|
|
1497
1186
|
}),
|
|
1498
|
-
z.object({
|
|
1499
|
-
type: z.literal("tool_stream_update"),
|
|
1500
|
-
toolCallId: IDENTIFIER,
|
|
1501
|
-
toolName: NAME,
|
|
1502
|
-
update: BoundedToolPayloadSchema,
|
|
1503
|
-
}),
|
|
1504
1187
|
z.object({
|
|
1505
1188
|
type: z.literal("tool_execution_end"),
|
|
1506
1189
|
toolCallId: IDENTIFIER,
|
|
@@ -1527,99 +1210,6 @@ const OmpGoalModeStateSchema = z.object({
|
|
|
1527
1210
|
reason: boundedString(4_096).optional(),
|
|
1528
1211
|
goal: OmpGoalSchema.optional(),
|
|
1529
1212
|
});
|
|
1530
|
-
const OmpTodoReminderEventSchema = z.object({
|
|
1531
|
-
type: z.literal("todo_reminder"),
|
|
1532
|
-
todos: z
|
|
1533
|
-
.array(
|
|
1534
|
-
z.object({
|
|
1535
|
-
id: IDENTIFIER.optional(),
|
|
1536
|
-
content: boundedString(16_384),
|
|
1537
|
-
status: z.enum(["pending", "in_progress", "blocked", "completed", "abandoned"]),
|
|
1538
|
-
}),
|
|
1539
|
-
)
|
|
1540
|
-
.max(MAX_TODOS),
|
|
1541
|
-
attempt: z.number().int().nonnegative().safe().optional(),
|
|
1542
|
-
maxAttempts: z.number().int().nonnegative().safe().optional(),
|
|
1543
|
-
});
|
|
1544
|
-
const OmpThinkingLevelChangedEventSchema = z.object({
|
|
1545
|
-
type: z.literal("thinking_level_changed"),
|
|
1546
|
-
thinkingLevel: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES).optional(),
|
|
1547
|
-
configured: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES).optional(),
|
|
1548
|
-
resolved: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES).optional(),
|
|
1549
|
-
});
|
|
1550
|
-
const OmpAutoRetryStartEventSchema = z.object({
|
|
1551
|
-
type: z.literal("auto_retry_start"),
|
|
1552
|
-
attempt: z.number().int().nonnegative().safe(),
|
|
1553
|
-
maxAttempts: z.number().int().positive().safe(),
|
|
1554
|
-
delayMs: z.number().int().nonnegative().safe(),
|
|
1555
|
-
errorMessage: boundedString(64 * 1024),
|
|
1556
|
-
errorId: z.number().int().safe().optional(),
|
|
1557
|
-
});
|
|
1558
|
-
const OmpAutoRetryEndEventSchema = z.object({
|
|
1559
|
-
type: z.literal("auto_retry_end"),
|
|
1560
|
-
success: z.boolean(),
|
|
1561
|
-
attempt: z.number().int().nonnegative().safe(),
|
|
1562
|
-
finalError: boundedString(64 * 1024).optional(),
|
|
1563
|
-
retryErrors: BoundedToolPayloadSchema.optional(),
|
|
1564
|
-
recoveredErrors: BoundedToolPayloadSchema.optional(),
|
|
1565
|
-
});
|
|
1566
|
-
const OmpAgentSessionEventSchema = z.discriminatedUnion("type", [
|
|
1567
|
-
...OmpCoreAgentEventSchema.options,
|
|
1568
|
-
z.object({ type: z.literal("config_warnings_changed") }),
|
|
1569
|
-
z.object({ type: z.literal("advisor_cost_changed") }),
|
|
1570
|
-
z.object({ type: z.literal("advisor_yielded") }),
|
|
1571
|
-
z.object({
|
|
1572
|
-
type: z.literal("ttsr_triggered"),
|
|
1573
|
-
rules: z.array(BoundedToolPayloadSchema).max(MAX_ARRAY_ITEMS),
|
|
1574
|
-
}),
|
|
1575
|
-
OmpTodoReminderEventSchema,
|
|
1576
|
-
z.object({ type: z.literal("todo_auto_clear") }),
|
|
1577
|
-
z.object({
|
|
1578
|
-
type: z.literal("irc_message"),
|
|
1579
|
-
message: OmpMessageSchema.refine((message) => message.role === "custom"),
|
|
1580
|
-
}),
|
|
1581
|
-
z.object({ type: z.literal("model_changed") }),
|
|
1582
|
-
OmpThinkingLevelChangedEventSchema,
|
|
1583
|
-
z.object({
|
|
1584
|
-
type: z.literal("goal_updated"),
|
|
1585
|
-
goal: OmpGoalSchema.nullable().optional(),
|
|
1586
|
-
state: OmpGoalModeStateSchema.optional(),
|
|
1587
|
-
}),
|
|
1588
|
-
OmpAutoRetryStartEventSchema,
|
|
1589
|
-
OmpAutoRetryEndEventSchema,
|
|
1590
|
-
z.object({
|
|
1591
|
-
type: z.literal("retry_fallback_applied"),
|
|
1592
|
-
from: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1593
|
-
to: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1594
|
-
role: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1595
|
-
}),
|
|
1596
|
-
z.object({
|
|
1597
|
-
type: z.literal("retry_fallback_succeeded"),
|
|
1598
|
-
model: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1599
|
-
role: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1600
|
-
}),
|
|
1601
|
-
z.object({
|
|
1602
|
-
type: z.literal("auto_compaction_start"),
|
|
1603
|
-
reason: boundedString(4_096),
|
|
1604
|
-
action: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1605
|
-
}),
|
|
1606
|
-
z.object({
|
|
1607
|
-
type: z.literal("auto_compaction_end"),
|
|
1608
|
-
action: NAME.optional(),
|
|
1609
|
-
result: OmpCompactionResultSchema.nullable().optional(),
|
|
1610
|
-
aborted: z.boolean().optional(),
|
|
1611
|
-
willRetry: z.boolean().optional(),
|
|
1612
|
-
errorMessage: boundedString(64 * 1024).optional(),
|
|
1613
|
-
skipped: z.boolean().optional(),
|
|
1614
|
-
}),
|
|
1615
|
-
z.object({
|
|
1616
|
-
type: z.literal("notice"),
|
|
1617
|
-
id: IDENTIFIER.optional(),
|
|
1618
|
-
level: z.enum(["info", "warning", "error"]),
|
|
1619
|
-
message: boundedString(64 * 1024),
|
|
1620
|
-
source: boundedString(MAX_NAME_LENGTH).optional(),
|
|
1621
|
-
}),
|
|
1622
|
-
]);
|
|
1623
1213
|
const OmpSubagentStatusSchema = z.enum([
|
|
1624
1214
|
"pending",
|
|
1625
1215
|
"running",
|
|
@@ -1762,10 +1352,80 @@ const OmpRuntimeEventSchema = z.discriminatedUnion("type", [
|
|
|
1762
1352
|
type: z.literal("subagent_event"),
|
|
1763
1353
|
payload: z.object({ id: IDENTIFIER, event: OmpAgentSessionEventSchema }),
|
|
1764
1354
|
}),
|
|
1355
|
+
z.object({
|
|
1356
|
+
type: z.literal("todo_reminder"),
|
|
1357
|
+
todos: z
|
|
1358
|
+
.array(
|
|
1359
|
+
z.object({
|
|
1360
|
+
id: IDENTIFIER.optional(),
|
|
1361
|
+
content: boundedString(16_384),
|
|
1362
|
+
status: z.enum(["pending", "in_progress", "blocked", "completed", "abandoned"]),
|
|
1363
|
+
}),
|
|
1364
|
+
)
|
|
1365
|
+
.max(MAX_TODOS),
|
|
1366
|
+
}),
|
|
1367
|
+
z.object({ type: z.literal("model_changed") }),
|
|
1368
|
+
z.object({
|
|
1369
|
+
type: z.literal("thinking_level_changed"),
|
|
1370
|
+
thinkingLevel: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES).optional(),
|
|
1371
|
+
}),
|
|
1372
|
+
z.object({
|
|
1373
|
+
type: z.literal("goal_updated"),
|
|
1374
|
+
goal: OmpGoalSchema.nullable().optional(),
|
|
1375
|
+
state: OmpGoalModeStateSchema.optional(),
|
|
1376
|
+
}),
|
|
1377
|
+
z.object({
|
|
1378
|
+
type: z.literal("auto_retry_start"),
|
|
1379
|
+
attempt: z.number().int().nonnegative().safe(),
|
|
1380
|
+
maxAttempts: z.number().int().positive().safe(),
|
|
1381
|
+
delayMs: z.number().int().nonnegative().safe(),
|
|
1382
|
+
errorMessage: boundedString(64 * 1024),
|
|
1383
|
+
errorId: z.number().int().safe().optional(),
|
|
1384
|
+
}),
|
|
1385
|
+
z.object({
|
|
1386
|
+
type: z.literal("auto_retry_end"),
|
|
1387
|
+
success: z.boolean(),
|
|
1388
|
+
attempt: z.number().int().nonnegative().safe(),
|
|
1389
|
+
finalError: boundedString(64 * 1024).optional(),
|
|
1390
|
+
recoveredErrors: BoundedToolPayloadSchema.optional(),
|
|
1391
|
+
}),
|
|
1392
|
+
z.object({
|
|
1393
|
+
type: z.literal("retry_fallback_applied"),
|
|
1394
|
+
from: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1395
|
+
to: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1396
|
+
role: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1397
|
+
}),
|
|
1398
|
+
z.object({
|
|
1399
|
+
type: z.literal("retry_fallback_succeeded"),
|
|
1400
|
+
model: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1401
|
+
role: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1402
|
+
}),
|
|
1403
|
+
z.object({ type: z.literal("todo_auto_clear") }),
|
|
1404
|
+
z.object({
|
|
1405
|
+
type: z.literal("auto_compaction_start"),
|
|
1406
|
+
reason: boundedString(4_096),
|
|
1407
|
+
action: boundedString(MAX_CONFIG_EVENT_TEXT_BYTES),
|
|
1408
|
+
}),
|
|
1409
|
+
z.object({
|
|
1410
|
+
type: z.literal("auto_compaction_end"),
|
|
1411
|
+
action: NAME.optional(),
|
|
1412
|
+
result: OmpCompactionResultSchema.nullable().optional(),
|
|
1413
|
+
aborted: z.boolean().optional(),
|
|
1414
|
+
willRetry: z.boolean().optional(),
|
|
1415
|
+
errorMessage: boundedString(64 * 1024).optional(),
|
|
1416
|
+
skipped: z.boolean().optional(),
|
|
1417
|
+
}),
|
|
1765
1418
|
z.object({
|
|
1766
1419
|
type: z.literal("available_commands_update"),
|
|
1767
1420
|
commands: z.array(OmpAvailableCommandSchema).max(MAX_ARRAY_ITEMS),
|
|
1768
1421
|
}),
|
|
1422
|
+
z.object({
|
|
1423
|
+
type: z.literal("notice"),
|
|
1424
|
+
id: IDENTIFIER.optional(),
|
|
1425
|
+
level: z.enum(["info", "warning", "error"]),
|
|
1426
|
+
message: boundedString(64 * 1024),
|
|
1427
|
+
source: boundedString(MAX_NAME_LENGTH).optional(),
|
|
1428
|
+
}),
|
|
1769
1429
|
z.object({ type: z.literal("command_output"), text: TEXT.optional() }),
|
|
1770
1430
|
OmpExtensionUiRequestSchema,
|
|
1771
1431
|
z.object({
|
|
@@ -1777,6 +1437,7 @@ const OmpRuntimeEventSchema = z.discriminatedUnion("type", [
|
|
|
1777
1437
|
OmpHostToolCancelSchema,
|
|
1778
1438
|
OmpToolApprovalRequestSchema,
|
|
1779
1439
|
OmpToolApprovalCancelSchema,
|
|
1440
|
+
z.object({ type: z.literal("advisor_yielded") }),
|
|
1780
1441
|
]);
|
|
1781
1442
|
type OptionalDetailsMapper = (value: unknown, taskResult?: boolean) => unknown;
|
|
1782
1443
|
|
|
@@ -1831,8 +1492,6 @@ function mapAgentEventDetails(
|
|
|
1831
1492
|
return mapRecordField(frame, "result", map, frame.toolName === "task");
|
|
1832
1493
|
case "agent_end":
|
|
1833
1494
|
return mapRecordField(frame, "messages", (messages) => mapMessageList(messages, map));
|
|
1834
|
-
case "irc_message":
|
|
1835
|
-
return mapRecordField(frame, "message", map);
|
|
1836
1495
|
default:
|
|
1837
1496
|
return frame;
|
|
1838
1497
|
}
|
|
@@ -1863,25 +1522,6 @@ function sanitizeHistoryResponseData(value: unknown): unknown {
|
|
|
1863
1522
|
return mapRecordField(value as Record<string, unknown>, "messages", sanitizeMessageListMetadata);
|
|
1864
1523
|
}
|
|
1865
1524
|
|
|
1866
|
-
function projectSessionStateResponseData(value: unknown): unknown {
|
|
1867
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) return value;
|
|
1868
|
-
const source = value as Record<string, unknown>;
|
|
1869
|
-
const projected: Record<string, unknown> = {};
|
|
1870
|
-
for (const key of [
|
|
1871
|
-
"model",
|
|
1872
|
-
"thinkingLevel",
|
|
1873
|
-
"isStreaming",
|
|
1874
|
-
"isCompacting",
|
|
1875
|
-
"sessionId",
|
|
1876
|
-
"autoCompactionEnabled",
|
|
1877
|
-
"contextUsage",
|
|
1878
|
-
"sessionFile",
|
|
1879
|
-
] as const) {
|
|
1880
|
-
if (Object.hasOwn(source, key)) projected[key] = source[key];
|
|
1881
|
-
}
|
|
1882
|
-
return projected;
|
|
1883
|
-
}
|
|
1884
|
-
|
|
1885
1525
|
function runtimeFrameCollectionLimit(frame: Record<string, unknown>): number {
|
|
1886
1526
|
const type = frame.type;
|
|
1887
1527
|
if (
|
|
@@ -1907,12 +1547,7 @@ const OmpBranchMessagesResultSchema = z.object({
|
|
|
1907
1547
|
});
|
|
1908
1548
|
const OmpBranchResultSchema = z.object({ text: TEXT, cancelled: z.boolean() });
|
|
1909
1549
|
const OmpMessagesResultSchema = z.object({
|
|
1910
|
-
messages: z.array(OmpMessageSchema).max(
|
|
1911
|
-
});
|
|
1912
|
-
const OmpMessagesPageResultSchema = z.object({
|
|
1913
|
-
messages: z.array(OmpMessageSchema).max(OMP_MESSAGE_PAGE_LIMIT),
|
|
1914
|
-
nextCursor: boundedString(2_048, 1).refine(isSafeOpaqueCursor).optional(),
|
|
1915
|
-
totalMessages: z.number().int().nonnegative().max(MAX_REPLAY_MESSAGES),
|
|
1550
|
+
messages: z.array(OmpMessageSchema).max(100_000),
|
|
1916
1551
|
});
|
|
1917
1552
|
const OmpSubagentsResultSchema = z.object({
|
|
1918
1553
|
subagents: z
|
|
@@ -1938,7 +1573,7 @@ const OmpSubagentMessagesResultSchema = z.object({
|
|
|
1938
1573
|
fromByte: z.number().int().nonnegative(),
|
|
1939
1574
|
nextByte: z.number().int().nonnegative(),
|
|
1940
1575
|
reset: z.boolean(),
|
|
1941
|
-
messages: z.array(OmpMessageSchema).max(
|
|
1576
|
+
messages: z.array(OmpMessageSchema).max(100_000),
|
|
1942
1577
|
});
|
|
1943
1578
|
const ProtocolNegotiationResultSchema = z.object({
|
|
1944
1579
|
protocolVersion: z.literal(2),
|
|
@@ -2056,7 +1691,7 @@ export interface OmpRuntimeSession {
|
|
|
2056
1691
|
getBranchMessages(): Promise<Array<{ entryId: string; text: string }>>;
|
|
2057
1692
|
branch(entryId: string): Promise<OmpBranchResult>;
|
|
2058
1693
|
readonly canReplayHistory: boolean;
|
|
2059
|
-
getMessages(
|
|
1694
|
+
getMessages(): Promise<OmpMessage[]>;
|
|
2060
1695
|
abort(): Promise<void>;
|
|
2061
1696
|
setHostTools(tools: readonly OmpHostToolDefinition[]): Promise<string[]>;
|
|
2062
1697
|
sendHostToolResult(result: OmpHostToolResult): void;
|
|
@@ -2077,7 +1712,6 @@ export interface OmpRuntime {
|
|
|
2077
1712
|
readPersistedSubagentTranscript(options: {
|
|
2078
1713
|
parentSessionFile: string;
|
|
2079
1714
|
childTranscriptId: string;
|
|
2080
|
-
sessionFile?: string;
|
|
2081
1715
|
cwd: string;
|
|
2082
1716
|
signal?: AbortSignal;
|
|
2083
1717
|
}): Promise<OmpPersistedSubagentMessages>;
|
|
@@ -2103,30 +1737,13 @@ export interface OmpRpcRuntimeOptions {
|
|
|
2103
1737
|
) => OmpSessionDescriptor[] | Promise<OmpSessionDescriptor[]>;
|
|
2104
1738
|
}
|
|
2105
1739
|
|
|
2106
|
-
export type OmpRpcRequestRejectionCode = "session_busy" | "stale_cursor" | "unsupported_command";
|
|
2107
|
-
|
|
2108
1740
|
export class OmpRpcRequestRejectedError extends Error {
|
|
2109
|
-
constructor(
|
|
2110
|
-
readonly command?: OmpRpcDiagnosticCommand,
|
|
2111
|
-
readonly code?: OmpRpcRequestRejectionCode,
|
|
2112
|
-
) {
|
|
1741
|
+
constructor() {
|
|
2113
1742
|
super("OMP RPC request failed");
|
|
2114
1743
|
this.name = "OmpRpcRequestRejectedError";
|
|
2115
1744
|
}
|
|
2116
1745
|
}
|
|
2117
1746
|
|
|
2118
|
-
export class OmpRpcResponseLimitError extends Error {
|
|
2119
|
-
constructor(
|
|
2120
|
-
readonly command: OmpRpcDiagnosticCommand | undefined,
|
|
2121
|
-
readonly bound: OmpRpcBoundDimension,
|
|
2122
|
-
readonly actual: number,
|
|
2123
|
-
readonly limit: number,
|
|
2124
|
-
) {
|
|
2125
|
-
super("OMP RPC response exceeded command limits");
|
|
2126
|
-
this.name = "OmpRpcResponseLimitError";
|
|
2127
|
-
}
|
|
2128
|
-
}
|
|
2129
|
-
|
|
2130
1747
|
type PendingRequest = {
|
|
2131
1748
|
resolve(value: unknown): void;
|
|
2132
1749
|
reject(error: Error): void;
|
|
@@ -3001,13 +2618,8 @@ class OmpRpcProcess {
|
|
|
3001
2618
|
} else {
|
|
3002
2619
|
this.appendLinePart(part);
|
|
3003
2620
|
if (this.fatalError) return;
|
|
3004
|
-
if (this.discardingLine)
|
|
3005
|
-
|
|
3006
|
-
this.fail(new Error("OMP RPC frame exceeds the semantic byte limit"));
|
|
3007
|
-
return;
|
|
3008
|
-
}
|
|
3009
|
-
this.resetDiscardedLine();
|
|
3010
|
-
} else this.completeLine();
|
|
2621
|
+
if (this.discardingLine) this.resetDiscardedLine();
|
|
2622
|
+
else this.completeLine();
|
|
3011
2623
|
}
|
|
3012
2624
|
start = index + 1;
|
|
3013
2625
|
}
|
|
@@ -3062,6 +2674,10 @@ class OmpRpcProcess {
|
|
|
3062
2674
|
this.lineParts = [];
|
|
3063
2675
|
this.lineBytes = 0;
|
|
3064
2676
|
const payload = line.at(-1) === 13 ? line.subarray(0, -1) : line;
|
|
2677
|
+
if (payload.byteLength > MAX_SEMANTIC_FRAME_BYTES) {
|
|
2678
|
+
this.fail(new Error("OMP RPC frame exceeds the semantic byte limit"));
|
|
2679
|
+
return;
|
|
2680
|
+
}
|
|
3065
2681
|
let decoded: unknown;
|
|
3066
2682
|
try {
|
|
3067
2683
|
decoded = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(payload));
|
|
@@ -3083,10 +2699,7 @@ class OmpRpcProcess {
|
|
|
3083
2699
|
frame.byteLength > MAX_SEMANTIC_FRAME_BYTES &&
|
|
3084
2700
|
![...this.pending.values()].some(
|
|
3085
2701
|
(pending) =>
|
|
3086
|
-
pending.command === "get_messages" ||
|
|
3087
|
-
pending.command === "get_messages_page" ||
|
|
3088
|
-
pending.command === "get_subagent_messages" ||
|
|
3089
|
-
pending.command === "get_state",
|
|
2702
|
+
pending.command === "get_messages" || pending.command === "get_subagent_messages",
|
|
3090
2703
|
)
|
|
3091
2704
|
) {
|
|
3092
2705
|
this.fail(new Error("OMP RPC frame exceeds the semantic byte limit"));
|
|
@@ -3192,16 +2805,12 @@ class OmpRpcProcess {
|
|
|
3192
2805
|
const pending = typeof frame.id === "string" ? this.pending.get(frame.id) : undefined;
|
|
3193
2806
|
if (
|
|
3194
2807
|
frame.type === "response" &&
|
|
3195
|
-
(pending?.command === "get_messages" ||
|
|
3196
|
-
pending?.command === "get_messages_page" ||
|
|
3197
|
-
pending?.command === "get_subagent_messages" ||
|
|
3198
|
-
pending?.command === "get_state")
|
|
2808
|
+
(pending?.command === "get_messages" || pending?.command === "get_subagent_messages")
|
|
3199
2809
|
) {
|
|
3200
2810
|
this.receiveResponse(frame);
|
|
3201
2811
|
return;
|
|
3202
2812
|
}
|
|
3203
2813
|
}
|
|
3204
|
-
if (this.receiveUnsupportedCommandResponse(value)) return;
|
|
3205
2814
|
if (rawByteLength > MAX_SEMANTIC_FRAME_BYTES) {
|
|
3206
2815
|
this.fail(new Error("OMP RPC frame exceeds the semantic byte limit"));
|
|
3207
2816
|
return;
|
|
@@ -3236,30 +2845,6 @@ class OmpRpcProcess {
|
|
|
3236
2845
|
return true;
|
|
3237
2846
|
}
|
|
3238
2847
|
|
|
3239
|
-
private receiveUnsupportedCommandResponse(value: unknown): boolean {
|
|
3240
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
3241
|
-
const frame = value as Record<string, unknown>;
|
|
3242
|
-
if (
|
|
3243
|
-
frame.type !== "response" ||
|
|
3244
|
-
frame.id !== undefined ||
|
|
3245
|
-
frame.success !== false ||
|
|
3246
|
-
typeof frame.command !== "string" ||
|
|
3247
|
-
frame.error !== `Unknown command: ${frame.command}`
|
|
3248
|
-
) {
|
|
3249
|
-
return false;
|
|
3250
|
-
}
|
|
3251
|
-
const matches = [...this.pending.entries()].filter(
|
|
3252
|
-
([, pending]) => pending.command === frame.command,
|
|
3253
|
-
);
|
|
3254
|
-
if (matches.length === 0) return false;
|
|
3255
|
-
const [id, pending] = matches[0] ?? [];
|
|
3256
|
-
if (!id || !pending) return false;
|
|
3257
|
-
this.takePending(id)?.reject(
|
|
3258
|
-
new OmpRpcRequestRejectedError(rpcDiagnosticCommand(pending.command), "unsupported_command"),
|
|
3259
|
-
);
|
|
3260
|
-
return true;
|
|
3261
|
-
}
|
|
3262
|
-
|
|
3263
2848
|
private receiveResponse(frame: Record<string, unknown>): void {
|
|
3264
2849
|
const rawId = typeof frame.id === "string" ? frame.id : undefined;
|
|
3265
2850
|
const knownPending = rawId ? this.pending.get(rawId) : undefined;
|
|
@@ -3292,14 +2877,10 @@ class OmpRpcProcess {
|
|
|
3292
2877
|
}
|
|
3293
2878
|
const isBranchHistory = pending.command === "get_branch_messages";
|
|
3294
2879
|
const isHistory =
|
|
3295
|
-
pending.command === "get_messages" ||
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
pending.command === "get_state"
|
|
3300
|
-
? projectSessionStateResponseData(response.data.data)
|
|
3301
|
-
: response.data.data;
|
|
3302
|
-
const responseData = isHistory ? sanitizeHistoryResponseData(rawResponseData) : rawResponseData;
|
|
2880
|
+
pending.command === "get_messages" || pending.command === "get_subagent_messages";
|
|
2881
|
+
const responseData = isHistory
|
|
2882
|
+
? sanitizeHistoryResponseData(response.data.data)
|
|
2883
|
+
: response.data.data;
|
|
3303
2884
|
const boundedFrame =
|
|
3304
2885
|
responseData === response.data.data ? frame : { ...frame, data: responseData };
|
|
3305
2886
|
const responseItemLimit = isBranchHistory
|
|
@@ -3322,21 +2903,17 @@ class OmpRpcProcess {
|
|
|
3322
2903
|
: pending.command === "get_available_models"
|
|
3323
2904
|
? 16_384
|
|
3324
2905
|
: 2_048;
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
2906
|
+
if (
|
|
2907
|
+
boundedJsonBytes(
|
|
2908
|
+
boundedFrame,
|
|
2909
|
+
responseByteLimit,
|
|
2910
|
+
responseItemLimit,
|
|
2911
|
+
MAX_IMAGE_DATA_LENGTH,
|
|
2912
|
+
responseNodeLimit,
|
|
2913
|
+
) === Number.POSITIVE_INFINITY
|
|
2914
|
+
) {
|
|
3333
2915
|
this.takePending(response.data.id)?.reject(
|
|
3334
|
-
new
|
|
3335
|
-
rpcDiagnosticCommand(pending.command),
|
|
3336
|
-
violation.dimension,
|
|
3337
|
-
violation.actual,
|
|
3338
|
-
violation.limit,
|
|
3339
|
-
),
|
|
2916
|
+
new Error("OMP RPC response exceeded command limits"),
|
|
3340
2917
|
);
|
|
3341
2918
|
return;
|
|
3342
2919
|
}
|
|
@@ -3357,16 +2934,7 @@ class OmpRpcProcess {
|
|
|
3357
2934
|
settled.reject(new Error("OMP RPC response is invalid"));
|
|
3358
2935
|
}
|
|
3359
2936
|
} else {
|
|
3360
|
-
|
|
3361
|
-
const code: OmpRpcRequestRejectionCode | undefined =
|
|
3362
|
-
responseCode === "session_busy" ||
|
|
3363
|
-
responseCode === "stale_cursor" ||
|
|
3364
|
-
responseCode === "unsupported_command"
|
|
3365
|
-
? responseCode
|
|
3366
|
-
: response.data.error === `Unknown command: ${pending.command}`
|
|
3367
|
-
? "unsupported_command"
|
|
3368
|
-
: undefined;
|
|
3369
|
-
settled.reject(new OmpRpcRequestRejectedError(rpcDiagnosticCommand(pending.command), code));
|
|
2937
|
+
settled.reject(new OmpRpcRequestRejectedError());
|
|
3370
2938
|
}
|
|
3371
2939
|
}
|
|
3372
2940
|
|
|
@@ -3621,7 +3189,7 @@ class OmpRpcProcess {
|
|
|
3621
3189
|
this.activeToolCallIds.add(event.toolCallId);
|
|
3622
3190
|
return true;
|
|
3623
3191
|
}
|
|
3624
|
-
if (event.type === "tool_execution_update"
|
|
3192
|
+
if (event.type === "tool_execution_update") {
|
|
3625
3193
|
return this.activeToolCallIds.has(event.toolCallId);
|
|
3626
3194
|
}
|
|
3627
3195
|
if (event.type === "tool_execution_end") {
|
|
@@ -3832,7 +3400,6 @@ class OmpRpcSession implements OmpRuntimeSession {
|
|
|
3832
3400
|
readonly inheritedRedactionValues: readonly string[],
|
|
3833
3401
|
readonly supportsTypedToolApprovals: boolean,
|
|
3834
3402
|
) {}
|
|
3835
|
-
private messagePagingSupport: "unknown" | "supported" | "unsupported" = "unknown";
|
|
3836
3403
|
|
|
3837
3404
|
onEvent(listener: (event: OmpRpcEvent) => void): () => void {
|
|
3838
3405
|
return this.process.onEvent(listener);
|
|
@@ -3846,195 +3413,6 @@ class OmpRpcSession implements OmpRuntimeSession {
|
|
|
3846
3413
|
return OmpSessionStatsSchema.parse(await this.process.request({ type: "get_session_stats" }));
|
|
3847
3414
|
}
|
|
3848
3415
|
|
|
3849
|
-
async getMessages(signal?: AbortSignal): Promise<OmpMessage[]> {
|
|
3850
|
-
if (!this.canReplayHistory) {
|
|
3851
|
-
throw new Error("OMP history replay requires negotiated RPC protocol v2");
|
|
3852
|
-
}
|
|
3853
|
-
if (this.messagePagingSupport === "unsupported") {
|
|
3854
|
-
const legacy = OmpMessagesResultSchema.parse(
|
|
3855
|
-
await this.requestWithSignal({ type: "get_messages" }, signal),
|
|
3856
|
-
);
|
|
3857
|
-
return legacy.messages;
|
|
3858
|
-
}
|
|
3859
|
-
let staleRestarts = 0;
|
|
3860
|
-
let busyRetries = 0;
|
|
3861
|
-
while (true) {
|
|
3862
|
-
const messages: OmpMessage[] = [];
|
|
3863
|
-
const seenCursors = new Set<string>();
|
|
3864
|
-
const seenMessageIdentities = new Set<string>();
|
|
3865
|
-
let pageCount = 0;
|
|
3866
|
-
let cursor: string | undefined;
|
|
3867
|
-
let totalMessages: number | undefined;
|
|
3868
|
-
let aggregateBytes = 0;
|
|
3869
|
-
let aggregateNodes = 0;
|
|
3870
|
-
try {
|
|
3871
|
-
while (true) {
|
|
3872
|
-
signal?.throwIfAborted();
|
|
3873
|
-
let rawPage: unknown;
|
|
3874
|
-
try {
|
|
3875
|
-
rawPage = await this.requestWithSignal(
|
|
3876
|
-
{
|
|
3877
|
-
type: "get_messages_page",
|
|
3878
|
-
...(cursor ? { cursor } : {}),
|
|
3879
|
-
limit: OMP_MESSAGE_PAGE_LIMIT,
|
|
3880
|
-
},
|
|
3881
|
-
signal,
|
|
3882
|
-
);
|
|
3883
|
-
} catch (error) {
|
|
3884
|
-
if (
|
|
3885
|
-
error instanceof OmpRpcRequestRejectedError &&
|
|
3886
|
-
error.code === "unsupported_command"
|
|
3887
|
-
) {
|
|
3888
|
-
this.messagePagingSupport = "unsupported";
|
|
3889
|
-
const legacy = OmpMessagesResultSchema.parse(
|
|
3890
|
-
await this.requestWithSignal({ type: "get_messages" }, signal),
|
|
3891
|
-
);
|
|
3892
|
-
return legacy.messages;
|
|
3893
|
-
}
|
|
3894
|
-
if (
|
|
3895
|
-
error instanceof OmpRpcRequestRejectedError &&
|
|
3896
|
-
error.code === "session_busy" &&
|
|
3897
|
-
busyRetries < MAX_MESSAGE_PAGE_BUSY_RETRIES
|
|
3898
|
-
) {
|
|
3899
|
-
const delayMs = MESSAGE_PAGE_RETRY_BASE_MS * 2 ** busyRetries;
|
|
3900
|
-
busyRetries += 1;
|
|
3901
|
-
await this.waitForReplayRetry(delayMs, signal);
|
|
3902
|
-
continue;
|
|
3903
|
-
}
|
|
3904
|
-
throw error;
|
|
3905
|
-
}
|
|
3906
|
-
pageCount += 1;
|
|
3907
|
-
if (pageCount > MAX_MESSAGE_PAGES) {
|
|
3908
|
-
throw new OmpRpcResponseLimitError(
|
|
3909
|
-
"get_messages_page",
|
|
3910
|
-
"items",
|
|
3911
|
-
pageCount,
|
|
3912
|
-
MAX_MESSAGE_PAGES,
|
|
3913
|
-
);
|
|
3914
|
-
}
|
|
3915
|
-
const page = OmpMessagesPageResultSchema.parse(rawPage);
|
|
3916
|
-
this.messagePagingSupport = "supported";
|
|
3917
|
-
if (totalMessages !== undefined && page.totalMessages !== totalMessages) {
|
|
3918
|
-
throw new Error("OMP message pagination returned an inconsistent total");
|
|
3919
|
-
}
|
|
3920
|
-
totalMessages ??= page.totalMessages;
|
|
3921
|
-
const nextMessageCount = messages.length + page.messages.length;
|
|
3922
|
-
if (nextMessageCount > totalMessages || nextMessageCount > MAX_REPLAY_MESSAGES) {
|
|
3923
|
-
throw new OmpRpcResponseLimitError(
|
|
3924
|
-
"get_messages_page",
|
|
3925
|
-
"items",
|
|
3926
|
-
nextMessageCount,
|
|
3927
|
-
Math.min(totalMessages, MAX_REPLAY_MESSAGES),
|
|
3928
|
-
);
|
|
3929
|
-
}
|
|
3930
|
-
const pageIdentities = new Set<string>();
|
|
3931
|
-
for (const message of page.messages) {
|
|
3932
|
-
const identity = message.entryId ?? message.id ?? message.responseId;
|
|
3933
|
-
if (!identity) continue;
|
|
3934
|
-
if (seenMessageIdentities.has(identity)) {
|
|
3935
|
-
throw new Error("OMP message pagination repeated a message identity");
|
|
3936
|
-
}
|
|
3937
|
-
pageIdentities.add(identity);
|
|
3938
|
-
}
|
|
3939
|
-
const inspection = inspectJsonBounds(
|
|
3940
|
-
page.messages,
|
|
3941
|
-
MAX_REPLAY_BYTES,
|
|
3942
|
-
MAX_REPLAY_MESSAGES,
|
|
3943
|
-
MAX_IMAGE_DATA_LENGTH,
|
|
3944
|
-
MAX_REPLAY_NODES,
|
|
3945
|
-
);
|
|
3946
|
-
if (inspection.violation) {
|
|
3947
|
-
throw new OmpRpcResponseLimitError(
|
|
3948
|
-
"get_messages_page",
|
|
3949
|
-
inspection.violation.dimension,
|
|
3950
|
-
inspection.violation.actual,
|
|
3951
|
-
inspection.violation.limit,
|
|
3952
|
-
);
|
|
3953
|
-
}
|
|
3954
|
-
aggregateBytes += inspection.bytes;
|
|
3955
|
-
aggregateNodes += inspection.nodes;
|
|
3956
|
-
if (aggregateBytes > MAX_REPLAY_BYTES) {
|
|
3957
|
-
throw new OmpRpcResponseLimitError(
|
|
3958
|
-
"get_messages_page",
|
|
3959
|
-
"bytes",
|
|
3960
|
-
aggregateBytes,
|
|
3961
|
-
MAX_REPLAY_BYTES,
|
|
3962
|
-
);
|
|
3963
|
-
}
|
|
3964
|
-
if (aggregateNodes > MAX_REPLAY_NODES) {
|
|
3965
|
-
throw new OmpRpcResponseLimitError(
|
|
3966
|
-
"get_messages_page",
|
|
3967
|
-
"nodes",
|
|
3968
|
-
aggregateNodes,
|
|
3969
|
-
MAX_REPLAY_NODES,
|
|
3970
|
-
);
|
|
3971
|
-
}
|
|
3972
|
-
for (const identity of pageIdentities) seenMessageIdentities.add(identity);
|
|
3973
|
-
messages.push(...page.messages);
|
|
3974
|
-
const nextCursor = page.nextCursor;
|
|
3975
|
-
if (!nextCursor) {
|
|
3976
|
-
if (messages.length !== totalMessages) {
|
|
3977
|
-
throw new Error("OMP message pagination ended before the advertised total");
|
|
3978
|
-
}
|
|
3979
|
-
return messages;
|
|
3980
|
-
}
|
|
3981
|
-
if (page.messages.length === 0 || messages.length >= totalMessages) {
|
|
3982
|
-
throw new Error("OMP message pagination did not make progress");
|
|
3983
|
-
}
|
|
3984
|
-
if (seenCursors.has(nextCursor)) {
|
|
3985
|
-
throw new Error("OMP message pagination repeated a cursor");
|
|
3986
|
-
}
|
|
3987
|
-
seenCursors.add(nextCursor);
|
|
3988
|
-
cursor = nextCursor;
|
|
3989
|
-
}
|
|
3990
|
-
} catch (error) {
|
|
3991
|
-
if (
|
|
3992
|
-
error instanceof OmpRpcRequestRejectedError &&
|
|
3993
|
-
error.code === "stale_cursor" &&
|
|
3994
|
-
staleRestarts < MAX_MESSAGE_PAGE_STALE_RESTARTS
|
|
3995
|
-
) {
|
|
3996
|
-
staleRestarts += 1;
|
|
3997
|
-
continue;
|
|
3998
|
-
}
|
|
3999
|
-
throw error;
|
|
4000
|
-
}
|
|
4001
|
-
}
|
|
4002
|
-
}
|
|
4003
|
-
|
|
4004
|
-
private async requestWithSignal(
|
|
4005
|
-
command: Record<string, unknown>,
|
|
4006
|
-
signal?: AbortSignal,
|
|
4007
|
-
): Promise<unknown> {
|
|
4008
|
-
signal?.throwIfAborted();
|
|
4009
|
-
const request = this.process.request(command);
|
|
4010
|
-
if (!signal) return request;
|
|
4011
|
-
const aborted = Promise.withResolvers<never>();
|
|
4012
|
-
const onAbort = () => aborted.reject(signal.reason);
|
|
4013
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
4014
|
-
try {
|
|
4015
|
-
return await Promise.race([request, aborted.promise]);
|
|
4016
|
-
} finally {
|
|
4017
|
-
signal.removeEventListener("abort", onAbort);
|
|
4018
|
-
void request.catch(() => undefined);
|
|
4019
|
-
}
|
|
4020
|
-
}
|
|
4021
|
-
|
|
4022
|
-
private async waitForReplayRetry(delayMs: number, signal?: AbortSignal): Promise<void> {
|
|
4023
|
-
signal?.throwIfAborted();
|
|
4024
|
-
if (!signal) {
|
|
4025
|
-
await waitMs(delayMs);
|
|
4026
|
-
return;
|
|
4027
|
-
}
|
|
4028
|
-
const aborted = Promise.withResolvers<never>();
|
|
4029
|
-
const onAbort = () => aborted.reject(signal.reason);
|
|
4030
|
-
signal.addEventListener("abort", onAbort, { once: true });
|
|
4031
|
-
try {
|
|
4032
|
-
await Promise.race([waitMs(delayMs), aborted.promise]);
|
|
4033
|
-
} finally {
|
|
4034
|
-
signal.removeEventListener("abort", onAbort);
|
|
4035
|
-
}
|
|
4036
|
-
}
|
|
4037
|
-
|
|
4038
3416
|
async compact(customInstructions?: string): Promise<OmpCompactionResult> {
|
|
4039
3417
|
const instructions =
|
|
4040
3418
|
customInstructions === undefined
|
|
@@ -4130,6 +3508,16 @@ class OmpRpcSession implements OmpRuntimeSession {
|
|
|
4130
3508
|
return result.data;
|
|
4131
3509
|
}
|
|
4132
3510
|
|
|
3511
|
+
async getMessages(): Promise<OmpMessage[]> {
|
|
3512
|
+
if (!this.canReplayHistory) {
|
|
3513
|
+
throw new Error("OMP history replay requires negotiated RPC protocol v2");
|
|
3514
|
+
}
|
|
3515
|
+
const result = OmpMessagesResultSchema.parse(
|
|
3516
|
+
await this.process.request({ type: "get_messages" }),
|
|
3517
|
+
);
|
|
3518
|
+
return result.messages;
|
|
3519
|
+
}
|
|
3520
|
+
|
|
4133
3521
|
async setHostTools(tools: readonly OmpHostToolDefinition[]): Promise<string[]> {
|
|
4134
3522
|
const safeTools = z.array(OmpHostToolDefinitionSchema).max(MAX_HOST_TOOLS).parse(tools);
|
|
4135
3523
|
if (safeTools.length === 0) return [];
|
|
@@ -4239,14 +3627,13 @@ export class OmpRpcRuntime implements OmpRuntime {
|
|
|
4239
3627
|
...transcript,
|
|
4240
3628
|
messages: z
|
|
4241
3629
|
.array(OmpMessageSchema)
|
|
4242
|
-
.max(
|
|
3630
|
+
.max(100_000)
|
|
4243
3631
|
.parse(sanitizeMessageListMetadata(transcript.messages)),
|
|
4244
3632
|
};
|
|
4245
3633
|
}
|
|
4246
3634
|
async readPersistedSubagentTranscript(options: {
|
|
4247
3635
|
parentSessionFile: string;
|
|
4248
3636
|
childTranscriptId: string;
|
|
4249
|
-
sessionFile?: string;
|
|
4250
3637
|
cwd: string;
|
|
4251
3638
|
signal?: AbortSignal;
|
|
4252
3639
|
}): Promise<OmpPersistedSubagentMessages> {
|
|
@@ -4255,13 +3642,12 @@ export class OmpRpcRuntime implements OmpRuntime {
|
|
|
4255
3642
|
options.childTranscriptId,
|
|
4256
3643
|
options.cwd,
|
|
4257
3644
|
options.signal,
|
|
4258
|
-
options.sessionFile,
|
|
4259
3645
|
);
|
|
4260
3646
|
return {
|
|
4261
3647
|
...transcript,
|
|
4262
3648
|
messages: z
|
|
4263
3649
|
.array(OmpMessageSchema)
|
|
4264
|
-
.max(
|
|
3650
|
+
.max(100_000)
|
|
4265
3651
|
.parse(sanitizeMessageListMetadata(transcript.messages)),
|
|
4266
3652
|
};
|
|
4267
3653
|
}
|