@markusylisiurunen/tau 0.3.41 → 0.3.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -6
- package/dist/core/agent/agent_runtime.js +32 -44
- package/dist/core/agent/agent_runtime.js.map +1 -1
- package/dist/core/auth/auth_manager.js +25 -9
- package/dist/core/auth/auth_manager.js.map +1 -1
- package/dist/core/auth/auth_storage.js +1 -0
- package/dist/core/auth/auth_storage.js.map +1 -1
- package/dist/core/auth/cli.js +49 -35
- package/dist/core/auth/cli.js.map +1 -1
- package/dist/core/auth/credential_store.js +54 -22
- package/dist/core/auth/credential_store.js.map +1 -1
- package/dist/core/auth/index.js +1 -1
- package/dist/core/auth/index.js.map +1 -1
- package/dist/core/auth/providers/openai_codex.js +71 -23
- package/dist/core/auth/providers/openai_codex.js.map +1 -1
- package/dist/core/cli.js +4 -2
- package/dist/core/cli.js.map +1 -1
- package/dist/core/config/builtin_themes.js +62 -155
- package/dist/core/config/builtin_themes.js.map +1 -1
- package/dist/core/index.js +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/models/tau_model_overrides.js +1 -66
- package/dist/core/models/tau_model_overrides.js.map +1 -1
- package/dist/core/session/direct_bash.js +1 -0
- package/dist/core/session/direct_bash.js.map +1 -1
- package/dist/core/session/runner.js +21 -14
- package/dist/core/session/runner.js.map +1 -1
- package/dist/core/static/code_mode/capabilities.mjs +25 -0
- package/dist/core/static/code_mode/history/documentation.md +2 -0
- package/dist/core/static/code_mode/history/sandbox_runner.mjs +4 -1
- package/dist/core/static/code_mode/nook/documentation.md +2 -0
- package/dist/core/static/code_mode/nook/sandbox_runner.mjs +4 -1
- package/dist/core/static/code_mode/web/documentation.md +2 -0
- package/dist/core/static/code_mode/web/sandbox_runner.mjs +4 -1
- package/dist/core/subagents/agent_supervisor.js +3 -3
- package/dist/core/subagents/agent_supervisor.js.map +1 -1
- package/dist/core/telegram/adapter.js +0 -23
- package/dist/core/telegram/adapter.js.map +1 -1
- package/dist/core/telegram/session_manager.js +34 -7
- package/dist/core/telegram/session_manager.js.map +1 -1
- package/dist/core/tools/bash.js +10 -2
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/code_mode.js +1 -0
- package/dist/core/tools/code_mode.js.map +1 -1
- package/dist/core/tools/presentation.js +1 -1
- package/dist/core/utils/auto_retry.js +1 -1
- package/dist/core/utils/auto_retry.js.map +1 -1
- package/dist/core/version.js +1 -1
- package/dist/host/local_session_host.js +319 -198
- package/dist/host/local_session_host.js.map +1 -1
- package/dist/host/session_protocol_handler.js +1 -1
- package/dist/host/session_protocol_handler.js.map +1 -1
- package/dist/main.js +16 -2
- package/dist/main.js.map +1 -1
- package/dist/protocol/index.d.ts +2 -2
- package/dist/protocol/index.js +1 -1
- package/dist/protocol/index.js.map +1 -1
- package/dist/protocol/session_protocol.d.ts +115 -40
- package/dist/protocol/session_protocol.js +377 -98
- package/dist/protocol/session_protocol.js.map +1 -1
- package/dist/sdk/index.d.ts +1 -2
- package/dist/sdk/index.js +0 -1
- package/dist/sdk/index.js.map +1 -1
- package/dist/store/session_snapshot_migrations.js +311 -4
- package/dist/store/session_snapshot_migrations.js.map +1 -1
- package/dist/tui/chat_controller/assistant_clipboard.js +12 -8
- package/dist/tui/chat_controller/assistant_clipboard.js.map +1 -1
- package/dist/tui/chat_controller/diff_review_service.js +13 -9
- package/dist/tui/chat_controller/diff_review_service.js.map +1 -1
- package/dist/tui/chat_controller/history_message_model.js +3 -3
- package/dist/tui/chat_controller/history_message_model.js.map +1 -1
- package/dist/tui/chat_controller/status_format.js +18 -0
- package/dist/tui/chat_controller/status_format.js.map +1 -1
- package/dist/tui/chat_view.js +39 -38
- package/dist/tui/chat_view.js.map +1 -1
- package/dist/tui/session_chat_app.js +1 -3
- package/dist/tui/session_chat_app.js.map +1 -1
- package/dist/tui/session_chat_controller.js +375 -241
- package/dist/tui/session_chat_controller.js.map +1 -1
- package/dist/tui/speech_playback.js +4 -4
- package/dist/tui/speech_playback.js.map +1 -1
- package/dist/tui/ui/assistant_message.js +1 -15
- package/dist/tui/ui/assistant_message.js.map +1 -1
- package/dist/tui/ui/chat_message_model.js +26 -7
- package/dist/tui/ui/chat_message_model.js.map +1 -1
- package/dist/tui/ui/custom_editor.js +1 -1
- package/dist/tui/ui/custom_editor.js.map +1 -1
- package/dist/tui/ui/footer.js +161 -47
- package/dist/tui/ui/footer.js.map +1 -1
- package/dist/tui/ui/theme/palette.js +10 -16
- package/dist/tui/ui/theme/palette.js.map +1 -1
- package/dist/tui/ui/theme/theme.js.map +1 -1
- package/dist/tui/ui/tool_card.js +12 -9
- package/dist/tui/ui/tool_card.js.map +1 -1
- package/dist/tui/ui/transcript_notice.js +44 -0
- package/dist/tui/ui/transcript_notice.js.map +1 -0
- package/dist/tui/ui/transcript_text.js +14 -0
- package/dist/tui/ui/transcript_text.js.map +1 -0
- package/package.json +10 -12
- package/dist/sdk/turn_outcome.d.ts +0 -2
- package/dist/sdk/turn_outcome.js +0 -4
- package/dist/sdk/turn_outcome.js.map +0 -1
- package/dist/tui/ui/system_message.js +0 -22
- package/dist/tui/ui/system_message.js.map +0 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
export const SESSION_PROTOCOL_VERSION =
|
|
2
|
+
export const SESSION_PROTOCOL_VERSION = 9;
|
|
3
3
|
export const SESSION_PROTOCOL_MAX_EXEC_CAPTURE_BYTES = 24 * 1024 * 1024;
|
|
4
4
|
export const SESSION_PROTOCOL_MAX_EXEC_STDIN_BYTES = 16 * 1024 * 1024;
|
|
5
|
+
const SESSION_PROTOCOL_NOTICE_TITLE_MAX_CHARS = 512;
|
|
6
|
+
const SESSION_PROTOCOL_NOTICE_CONTENT_MAX_ENTRIES = 16;
|
|
7
|
+
const SESSION_PROTOCOL_NOTICE_CONTENT_ENTRY_MAX_CHARS = 4_096;
|
|
5
8
|
export const SESSION_PROTOCOL_METHODS = [
|
|
6
9
|
"initialize",
|
|
7
10
|
"session.create",
|
|
@@ -65,6 +68,22 @@ const SESSION_PROTOCOL_ERROR_CODE_VALUES = [
|
|
|
65
68
|
SESSION_PROTOCOL_ERROR_CODES.cancelled,
|
|
66
69
|
SESSION_PROTOCOL_ERROR_CODES.internalError,
|
|
67
70
|
];
|
|
71
|
+
export function projectSessionProtocolNoticePresentation(title, content) {
|
|
72
|
+
const projectedContent = content
|
|
73
|
+
? content
|
|
74
|
+
.slice(0, SESSION_PROTOCOL_NOTICE_CONTENT_MAX_ENTRIES)
|
|
75
|
+
.map((entry) => truncateNoticeText(entry, SESSION_PROTOCOL_NOTICE_CONTENT_ENTRY_MAX_CHARS))
|
|
76
|
+
: [];
|
|
77
|
+
return {
|
|
78
|
+
title: truncateNoticeText(title, SESSION_PROTOCOL_NOTICE_TITLE_MAX_CHARS),
|
|
79
|
+
...(projectedContent.length > 0 ? { content: projectedContent } : {}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function truncateNoticeText(value, maxChars) {
|
|
83
|
+
if (value.length <= maxChars)
|
|
84
|
+
return value;
|
|
85
|
+
return `${value.slice(0, maxChars - 1)}…`;
|
|
86
|
+
}
|
|
68
87
|
const sessionProtocolMethodSchema = z.enum(SESSION_PROTOCOL_METHODS);
|
|
69
88
|
const sessionProtocolMethodListSchema = z
|
|
70
89
|
.array(sessionProtocolMethodSchema)
|
|
@@ -86,6 +105,9 @@ const nonEmptyStringSchema = z
|
|
|
86
105
|
.string()
|
|
87
106
|
.min(1)
|
|
88
107
|
.refine((value) => value.trim().length > 0);
|
|
108
|
+
const noticeTitleSchema = nonEmptyStringSchema
|
|
109
|
+
.max(SESSION_PROTOCOL_NOTICE_TITLE_MAX_CHARS)
|
|
110
|
+
.refine((value) => !value.includes("\n") && !value.includes("\r"), "notice title must be one line");
|
|
89
111
|
const sessionProtocolRequestIdSchema = nonEmptyStringSchema;
|
|
90
112
|
const nullableSessionProtocolRequestIdSchema = sessionProtocolRequestIdSchema.nullable();
|
|
91
113
|
const absolutePathSchema = nonEmptyStringSchema.refine((value) => value.startsWith("/"));
|
|
@@ -753,50 +775,136 @@ const sessionProtocolMessageSchema = z
|
|
|
753
775
|
state: z.enum(["draft", "committed", "interrupted", "discarded"]),
|
|
754
776
|
modelVisible: z.boolean(),
|
|
755
777
|
message: sessionProtocolMessagePayloadSchema,
|
|
756
|
-
turn: sessionProtocolTurnOutcomeSchema.optional(),
|
|
757
778
|
})
|
|
758
779
|
.strip();
|
|
780
|
+
const sessionProtocolSubjectSchema = z.discriminatedUnion("type", [
|
|
781
|
+
z.object({ type: z.literal("session") }).strip(),
|
|
782
|
+
z.object({ type: z.literal("message"), id: nonEmptyStringSchema }).strip(),
|
|
783
|
+
z.object({ type: z.literal("tool"), id: nonEmptyStringSchema }).strip(),
|
|
784
|
+
z.object({ type: z.literal("agent"), id: nonEmptyStringSchema }).strip(),
|
|
785
|
+
z.object({ type: z.literal("operation"), id: nonEmptyStringSchema }).strip(),
|
|
786
|
+
]);
|
|
787
|
+
const timelineNoticeKindSchema = nonEmptyStringSchema.regex(/^[a-z0-9-]+(?:\.[a-z0-9-]+)+$/, "timeline notice kind must be a lowercase dotted identifier");
|
|
759
788
|
const sessionProtocolNoticeSchema = z
|
|
760
789
|
.object({
|
|
790
|
+
kind: timelineNoticeKindSchema,
|
|
791
|
+
version: z.number().int().positive(),
|
|
761
792
|
severity: z.enum(["info", "warn", "error"]),
|
|
762
|
-
|
|
763
|
-
|
|
793
|
+
subject: sessionProtocolSubjectSchema,
|
|
794
|
+
presentation: z
|
|
795
|
+
.object({
|
|
796
|
+
title: noticeTitleSchema,
|
|
797
|
+
content: z
|
|
798
|
+
.array(z.string().max(SESSION_PROTOCOL_NOTICE_CONTENT_ENTRY_MAX_CHARS))
|
|
799
|
+
.min(1)
|
|
800
|
+
.max(SESSION_PROTOCOL_NOTICE_CONTENT_MAX_ENTRIES)
|
|
801
|
+
.optional(),
|
|
802
|
+
})
|
|
803
|
+
.strip(),
|
|
804
|
+
data: z.record(z.string(), z.unknown()),
|
|
764
805
|
})
|
|
765
806
|
.strip();
|
|
766
|
-
const
|
|
767
|
-
|
|
807
|
+
const sessionProtocolOperationBaseSchema = {
|
|
808
|
+
id: nonEmptyStringSchema,
|
|
768
809
|
kind: z.enum(["auto-compaction", "manual-compaction", "reload", "rewind"]),
|
|
769
|
-
status: z.enum(["running", "succeeded", "failed", "cancelled", "skipped"]),
|
|
770
810
|
startedAt: z.number().finite(),
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
811
|
+
};
|
|
812
|
+
const sessionProtocolOperationSchema = z.discriminatedUnion("status", [
|
|
813
|
+
z.object({ ...sessionProtocolOperationBaseSchema, status: z.literal("running") }).strip(),
|
|
814
|
+
z
|
|
815
|
+
.object({
|
|
816
|
+
...sessionProtocolOperationBaseSchema,
|
|
817
|
+
status: z.literal("succeeded"),
|
|
818
|
+
finishedAt: z.number().finite(),
|
|
819
|
+
})
|
|
820
|
+
.strip(),
|
|
821
|
+
z
|
|
822
|
+
.object({
|
|
823
|
+
...sessionProtocolOperationBaseSchema,
|
|
824
|
+
status: z.literal("failed"),
|
|
825
|
+
finishedAt: z.number().finite(),
|
|
826
|
+
error: nonEmptyStringSchema,
|
|
827
|
+
})
|
|
828
|
+
.strip(),
|
|
829
|
+
z
|
|
830
|
+
.object({
|
|
831
|
+
...sessionProtocolOperationBaseSchema,
|
|
832
|
+
status: z.literal("skipped"),
|
|
833
|
+
finishedAt: z.number().finite(),
|
|
834
|
+
reason: z.literal("no-eligible-history"),
|
|
835
|
+
})
|
|
836
|
+
.strip(),
|
|
837
|
+
z
|
|
838
|
+
.object({
|
|
839
|
+
...sessionProtocolOperationBaseSchema,
|
|
840
|
+
status: z.literal("cancelled"),
|
|
841
|
+
finishedAt: z.number().finite(),
|
|
842
|
+
reason: z.enum(["interrupted", "session-recovered"]),
|
|
843
|
+
})
|
|
844
|
+
.strip(),
|
|
845
|
+
]);
|
|
846
|
+
const sessionProtocolTimelineItemBaseSchema = {
|
|
847
|
+
id: nonEmptyStringSchema,
|
|
848
|
+
sequence: z.number().int().positive(),
|
|
849
|
+
createdAt: z.number().finite().nonnegative(),
|
|
850
|
+
};
|
|
777
851
|
const sessionProtocolTimelineItemSchema = z.discriminatedUnion("type", [
|
|
778
852
|
z
|
|
779
853
|
.object({
|
|
854
|
+
...sessionProtocolTimelineItemBaseSchema,
|
|
780
855
|
type: z.literal("message"),
|
|
781
|
-
id: nonEmptyStringSchema,
|
|
782
856
|
messageId: nonEmptyStringSchema,
|
|
783
857
|
})
|
|
784
858
|
.strip(),
|
|
785
859
|
z
|
|
786
860
|
.object({
|
|
861
|
+
...sessionProtocolTimelineItemBaseSchema,
|
|
862
|
+
type: z.literal("tool"),
|
|
863
|
+
toolId: nonEmptyStringSchema,
|
|
864
|
+
})
|
|
865
|
+
.strip(),
|
|
866
|
+
z
|
|
867
|
+
.object({
|
|
868
|
+
...sessionProtocolTimelineItemBaseSchema,
|
|
787
869
|
type: z.literal("notice"),
|
|
788
|
-
id: nonEmptyStringSchema,
|
|
789
870
|
notice: sessionProtocolNoticeSchema,
|
|
790
871
|
})
|
|
791
872
|
.strip(),
|
|
792
873
|
z
|
|
793
874
|
.object({
|
|
875
|
+
...sessionProtocolTimelineItemBaseSchema,
|
|
794
876
|
type: z.literal("operation"),
|
|
795
|
-
|
|
796
|
-
operation: sessionProtocolOperationSchema,
|
|
877
|
+
operationId: nonEmptyStringSchema,
|
|
797
878
|
})
|
|
798
879
|
.strip(),
|
|
799
880
|
]);
|
|
881
|
+
const sessionProtocolTimelineSchema = z
|
|
882
|
+
.object({
|
|
883
|
+
epoch: z.number().int().positive(),
|
|
884
|
+
sequence: z.number().int().nonnegative(),
|
|
885
|
+
items: z.array(sessionProtocolTimelineItemSchema),
|
|
886
|
+
})
|
|
887
|
+
.strip()
|
|
888
|
+
.superRefine((timeline, ctx) => {
|
|
889
|
+
let previousSequence = 0;
|
|
890
|
+
for (const [index, item] of timeline.items.entries()) {
|
|
891
|
+
if (item.sequence <= previousSequence) {
|
|
892
|
+
ctx.addIssue({
|
|
893
|
+
code: "custom",
|
|
894
|
+
path: ["items", index, "sequence"],
|
|
895
|
+
message: "timeline item sequences must be strictly increasing",
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
if (item.sequence > timeline.sequence) {
|
|
899
|
+
ctx.addIssue({
|
|
900
|
+
code: "custom",
|
|
901
|
+
path: ["items", index, "sequence"],
|
|
902
|
+
message: "timeline item sequence exceeds the timeline high-water sequence",
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
previousSequence = item.sequence;
|
|
906
|
+
}
|
|
907
|
+
});
|
|
800
908
|
const sessionProtocolToolRunBaseSchema = z.object({
|
|
801
909
|
id: nonEmptyStringSchema,
|
|
802
910
|
toolCallId: nonEmptyStringSchema,
|
|
@@ -918,17 +1026,10 @@ const sessionProtocolAgentRunSchema = z
|
|
|
918
1026
|
});
|
|
919
1027
|
}
|
|
920
1028
|
});
|
|
921
|
-
const sessionProtocolFacetSubjectSchema = z.discriminatedUnion("type", [
|
|
922
|
-
z.object({ type: z.literal("session") }).strip(),
|
|
923
|
-
z.object({ type: z.literal("message"), id: nonEmptyStringSchema }).strip(),
|
|
924
|
-
z.object({ type: z.literal("tool"), id: nonEmptyStringSchema }).strip(),
|
|
925
|
-
z.object({ type: z.literal("agent"), id: nonEmptyStringSchema }).strip(),
|
|
926
|
-
z.object({ type: z.literal("operation"), id: nonEmptyStringSchema }).strip(),
|
|
927
|
-
]);
|
|
928
1029
|
const sessionProtocolFacetSchema = z
|
|
929
1030
|
.object({
|
|
930
1031
|
id: nonEmptyStringSchema,
|
|
931
|
-
subject:
|
|
1032
|
+
subject: sessionProtocolSubjectSchema,
|
|
932
1033
|
kind: nonEmptyStringSchema,
|
|
933
1034
|
version: z.number().int().positive(),
|
|
934
1035
|
data: z.record(z.string(), z.unknown()),
|
|
@@ -943,11 +1044,11 @@ const sessionProtocolGoalSchema = z
|
|
|
943
1044
|
const sessionProtocolAgentStateSnapshotSchema = z
|
|
944
1045
|
.object({
|
|
945
1046
|
revision: z.number().int().nonnegative(),
|
|
946
|
-
|
|
1047
|
+
modelContextKey: nonEmptyStringSchema,
|
|
947
1048
|
usageCheckpoint: z
|
|
948
1049
|
.object({
|
|
949
1050
|
historyEntryId: nonEmptyStringSchema,
|
|
950
|
-
|
|
1051
|
+
modelContextKey: nonEmptyStringSchema,
|
|
951
1052
|
tokens: z.number().int().nonnegative(),
|
|
952
1053
|
})
|
|
953
1054
|
.strip()
|
|
@@ -969,8 +1070,9 @@ const sessionProtocolSnapshotSchema = z
|
|
|
969
1070
|
catalog: sessionProtocolContentCatalogSnapshotSchema,
|
|
970
1071
|
executionEnvironment: sessionProtocolExecutionEnvironmentSnapshotSchema,
|
|
971
1072
|
messages: z.array(sessionProtocolMessageSchema),
|
|
972
|
-
timeline:
|
|
1073
|
+
timeline: sessionProtocolTimelineSchema,
|
|
973
1074
|
tools: z.record(nonEmptyStringSchema, sessionProtocolToolRunSchema),
|
|
1075
|
+
operations: z.record(nonEmptyStringSchema, sessionProtocolOperationSchema),
|
|
974
1076
|
agents: z.record(nonEmptyStringSchema, sessionProtocolAgentRunSchema),
|
|
975
1077
|
facets: z.record(nonEmptyStringSchema, sessionProtocolFacetSchema),
|
|
976
1078
|
})
|
|
@@ -985,22 +1087,15 @@ const sessionProtocolSnapshotSchema = z
|
|
|
985
1087
|
message: `duplicate message id '${message.id}'`,
|
|
986
1088
|
});
|
|
987
1089
|
}
|
|
988
|
-
if (message.turn && message.message.role !== "user") {
|
|
989
|
-
ctx.addIssue({
|
|
990
|
-
code: "custom",
|
|
991
|
-
path: ["messages"],
|
|
992
|
-
message: `turn outcome belongs to non-user message '${message.id}'`,
|
|
993
|
-
});
|
|
994
|
-
}
|
|
995
1090
|
messagesById.set(message.id, message);
|
|
996
1091
|
}
|
|
997
1092
|
const checkpoint = snapshot.agentState.usageCheckpoint;
|
|
998
1093
|
if (checkpoint) {
|
|
999
|
-
if (checkpoint.
|
|
1094
|
+
if (checkpoint.modelContextKey !== snapshot.agentState.modelContextKey) {
|
|
1000
1095
|
ctx.addIssue({
|
|
1001
1096
|
code: "custom",
|
|
1002
|
-
path: ["agentState", "usageCheckpoint", "
|
|
1003
|
-
message: "usage checkpoint context
|
|
1097
|
+
path: ["agentState", "usageCheckpoint", "modelContextKey"],
|
|
1098
|
+
message: "usage checkpoint model context key must match agent state",
|
|
1004
1099
|
});
|
|
1005
1100
|
}
|
|
1006
1101
|
const checkpointMessage = messagesById.get(checkpoint.historyEntryId);
|
|
@@ -1019,29 +1114,109 @@ const sessionProtocolSnapshotSchema = z
|
|
|
1019
1114
|
});
|
|
1020
1115
|
}
|
|
1021
1116
|
}
|
|
1117
|
+
const subjectExists = (subject) => subject.type === "session" ||
|
|
1118
|
+
(subject.type === "message" && messagesById.has(subject.id)) ||
|
|
1119
|
+
(subject.type === "tool" && snapshot.tools[subject.id] !== undefined) ||
|
|
1120
|
+
(subject.type === "agent" && snapshot.agents[subject.id] !== undefined) ||
|
|
1121
|
+
(subject.type === "operation" && snapshot.operations[subject.id] !== undefined);
|
|
1022
1122
|
const timelineIds = new Set();
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1123
|
+
const timelineSequences = new Set();
|
|
1124
|
+
const timelineToolIds = new Set();
|
|
1125
|
+
const timelineOperationIds = new Set();
|
|
1126
|
+
let previousTimelineSequence = 0;
|
|
1127
|
+
for (const item of snapshot.timeline.items) {
|
|
1025
1128
|
if (timelineIds.has(item.id)) {
|
|
1026
1129
|
ctx.addIssue({
|
|
1027
1130
|
code: "custom",
|
|
1028
|
-
path: ["timeline"],
|
|
1131
|
+
path: ["timeline", "items"],
|
|
1029
1132
|
message: `duplicate timeline item id '${item.id}'`,
|
|
1030
1133
|
});
|
|
1031
1134
|
}
|
|
1032
1135
|
timelineIds.add(item.id);
|
|
1136
|
+
if (timelineSequences.has(item.sequence) ||
|
|
1137
|
+
item.sequence <= previousTimelineSequence ||
|
|
1138
|
+
item.sequence > snapshot.timeline.sequence) {
|
|
1139
|
+
ctx.addIssue({
|
|
1140
|
+
code: "custom",
|
|
1141
|
+
path: ["timeline", "items"],
|
|
1142
|
+
message: `timeline item '${item.id}' has invalid sequence '${item.sequence}'`,
|
|
1143
|
+
});
|
|
1144
|
+
}
|
|
1145
|
+
timelineSequences.add(item.sequence);
|
|
1146
|
+
previousTimelineSequence = item.sequence;
|
|
1033
1147
|
if (item.type === "message" && !messagesById.has(item.messageId)) {
|
|
1034
1148
|
ctx.addIssue({
|
|
1035
1149
|
code: "custom",
|
|
1036
|
-
path: ["timeline"],
|
|
1150
|
+
path: ["timeline", "items"],
|
|
1037
1151
|
message: `timeline message item '${item.id}' references unknown message '${item.messageId}'`,
|
|
1038
1152
|
});
|
|
1039
1153
|
}
|
|
1154
|
+
if (item.type === "tool") {
|
|
1155
|
+
if (timelineToolIds.has(item.toolId)) {
|
|
1156
|
+
ctx.addIssue({
|
|
1157
|
+
code: "custom",
|
|
1158
|
+
path: ["timeline", "items"],
|
|
1159
|
+
message: `tool '${item.toolId}' has multiple timeline items`,
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
timelineToolIds.add(item.toolId);
|
|
1163
|
+
if (snapshot.tools[item.toolId] === undefined) {
|
|
1164
|
+
ctx.addIssue({
|
|
1165
|
+
code: "custom",
|
|
1166
|
+
path: ["timeline", "items"],
|
|
1167
|
+
message: `timeline tool item '${item.id}' references unknown tool '${item.toolId}'`,
|
|
1168
|
+
});
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1040
1171
|
if (item.type === "operation") {
|
|
1041
|
-
|
|
1172
|
+
if (timelineOperationIds.has(item.operationId)) {
|
|
1173
|
+
ctx.addIssue({
|
|
1174
|
+
code: "custom",
|
|
1175
|
+
path: ["timeline", "items"],
|
|
1176
|
+
message: `operation '${item.operationId}' has multiple timeline items`,
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
timelineOperationIds.add(item.operationId);
|
|
1180
|
+
if (snapshot.operations[item.operationId] === undefined) {
|
|
1181
|
+
ctx.addIssue({
|
|
1182
|
+
code: "custom",
|
|
1183
|
+
path: ["timeline", "items"],
|
|
1184
|
+
message: `timeline operation item '${item.id}' references unknown operation '${item.operationId}'`,
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
if (item.type === "notice" && !subjectExists(item.notice.subject)) {
|
|
1189
|
+
ctx.addIssue({
|
|
1190
|
+
code: "custom",
|
|
1191
|
+
path: ["timeline", "items"],
|
|
1192
|
+
message: `timeline notice '${item.id}' references an unknown ${item.notice.subject.type} subject`,
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
for (const [id, operation] of Object.entries(snapshot.operations)) {
|
|
1197
|
+
if (!timelineOperationIds.has(id)) {
|
|
1198
|
+
ctx.addIssue({
|
|
1199
|
+
code: "custom",
|
|
1200
|
+
path: ["operations", id],
|
|
1201
|
+
message: `operation '${id}' has no timeline item`,
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
if (id !== operation.id) {
|
|
1205
|
+
ctx.addIssue({
|
|
1206
|
+
code: "custom",
|
|
1207
|
+
path: ["operations", id],
|
|
1208
|
+
message: `operation map key '${id}' does not match embedded id '${operation.id}'`,
|
|
1209
|
+
});
|
|
1042
1210
|
}
|
|
1043
1211
|
}
|
|
1044
1212
|
for (const [id, tool] of Object.entries(snapshot.tools)) {
|
|
1213
|
+
if (!timelineToolIds.has(id)) {
|
|
1214
|
+
ctx.addIssue({
|
|
1215
|
+
code: "custom",
|
|
1216
|
+
path: ["tools", id],
|
|
1217
|
+
message: `tool '${id}' has no timeline item`,
|
|
1218
|
+
});
|
|
1219
|
+
}
|
|
1045
1220
|
if (id !== tool.id || id !== tool.toolCallId) {
|
|
1046
1221
|
ctx.addIssue({
|
|
1047
1222
|
code: "custom",
|
|
@@ -1136,12 +1311,7 @@ const sessionProtocolSnapshotSchema = z
|
|
|
1136
1311
|
message: `facet map key '${id}' does not match embedded id '${facet.id}'`,
|
|
1137
1312
|
});
|
|
1138
1313
|
}
|
|
1139
|
-
|
|
1140
|
-
(facet.subject.type === "message" && messagesById.has(facet.subject.id)) ||
|
|
1141
|
-
(facet.subject.type === "tool" && snapshot.tools[facet.subject.id] !== undefined) ||
|
|
1142
|
-
(facet.subject.type === "agent" && snapshot.agents[facet.subject.id] !== undefined) ||
|
|
1143
|
-
(facet.subject.type === "operation" && operationIds.has(facet.subject.id));
|
|
1144
|
-
if (!subjectExists) {
|
|
1314
|
+
if (!subjectExists(facet.subject)) {
|
|
1145
1315
|
ctx.addIssue({
|
|
1146
1316
|
code: "custom",
|
|
1147
1317
|
path: ["facets", id, "subject"],
|
|
@@ -1150,18 +1320,41 @@ const sessionProtocolSnapshotSchema = z
|
|
|
1150
1320
|
}
|
|
1151
1321
|
}
|
|
1152
1322
|
});
|
|
1153
|
-
const
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1323
|
+
const sessionProtocolDeltaCauseSchema = z.union([
|
|
1324
|
+
z
|
|
1325
|
+
.object({
|
|
1326
|
+
type: z.enum([
|
|
1327
|
+
"user-message",
|
|
1328
|
+
"assistant-stream",
|
|
1329
|
+
"assistant-message",
|
|
1330
|
+
"tool-run",
|
|
1331
|
+
"tool-result",
|
|
1332
|
+
"notice",
|
|
1333
|
+
"agent-run",
|
|
1334
|
+
"maintenance",
|
|
1335
|
+
"configuration",
|
|
1336
|
+
"goal",
|
|
1337
|
+
]),
|
|
1338
|
+
})
|
|
1339
|
+
.strip(),
|
|
1340
|
+
z
|
|
1341
|
+
.object({
|
|
1342
|
+
type: z.literal("compaction"),
|
|
1343
|
+
previousEpoch: z.number().int().positive(),
|
|
1344
|
+
epoch: z.number().int().positive(),
|
|
1345
|
+
kind: z.enum(["auto", "manual"]),
|
|
1346
|
+
cutType: z.enum(["turn-boundary", "split-turn"]),
|
|
1347
|
+
retainedMessageCount: z.number().int().nonnegative(),
|
|
1348
|
+
})
|
|
1349
|
+
.strip(),
|
|
1350
|
+
z
|
|
1351
|
+
.object({
|
|
1352
|
+
type: z.literal("rewind"),
|
|
1353
|
+
epoch: z.number().int().positive(),
|
|
1354
|
+
cutoffSequence: z.number().int().nonnegative(),
|
|
1355
|
+
})
|
|
1356
|
+
.strip(),
|
|
1357
|
+
z.object({ type: z.literal("resync") }).strip(),
|
|
1165
1358
|
]);
|
|
1166
1359
|
const sessionProtocolChangeSchema = z.discriminatedUnion("type", [
|
|
1167
1360
|
z
|
|
@@ -1198,7 +1391,6 @@ const sessionProtocolChangeSchema = z.discriminatedUnion("type", [
|
|
|
1198
1391
|
.object({
|
|
1199
1392
|
type: z.literal("message.append"),
|
|
1200
1393
|
message: sessionProtocolMessageSchema,
|
|
1201
|
-
timelineItem: sessionProtocolTimelineItemSchema.optional(),
|
|
1202
1394
|
})
|
|
1203
1395
|
.strip(),
|
|
1204
1396
|
z
|
|
@@ -1224,14 +1416,15 @@ const sessionProtocolChangeSchema = z.discriminatedUnion("type", [
|
|
|
1224
1416
|
.strip(),
|
|
1225
1417
|
z
|
|
1226
1418
|
.object({
|
|
1227
|
-
type: z.literal("timeline.
|
|
1228
|
-
|
|
1419
|
+
type: z.literal("timeline.remove"),
|
|
1420
|
+
id: nonEmptyStringSchema,
|
|
1229
1421
|
})
|
|
1230
1422
|
.strip(),
|
|
1231
1423
|
z
|
|
1232
1424
|
.object({
|
|
1233
|
-
type: z.literal("timeline.
|
|
1234
|
-
|
|
1425
|
+
type: z.literal("timeline.advance"),
|
|
1426
|
+
epoch: z.number().int().positive(),
|
|
1427
|
+
sequence: z.number().int().positive(),
|
|
1235
1428
|
})
|
|
1236
1429
|
.strip(),
|
|
1237
1430
|
z
|
|
@@ -1246,6 +1439,18 @@ const sessionProtocolChangeSchema = z.discriminatedUnion("type", [
|
|
|
1246
1439
|
id: nonEmptyStringSchema,
|
|
1247
1440
|
})
|
|
1248
1441
|
.strip(),
|
|
1442
|
+
z
|
|
1443
|
+
.object({
|
|
1444
|
+
type: z.literal("operation.set"),
|
|
1445
|
+
operation: sessionProtocolOperationSchema,
|
|
1446
|
+
})
|
|
1447
|
+
.strip(),
|
|
1448
|
+
z
|
|
1449
|
+
.object({
|
|
1450
|
+
type: z.literal("operation.remove"),
|
|
1451
|
+
id: nonEmptyStringSchema,
|
|
1452
|
+
})
|
|
1453
|
+
.strip(),
|
|
1249
1454
|
z
|
|
1250
1455
|
.object({
|
|
1251
1456
|
type: z.literal("agent.set"),
|
|
@@ -1292,7 +1497,7 @@ const sessionProtocolDeltaMessageSchema = z
|
|
|
1292
1497
|
sessionId: nonEmptyStringSchema,
|
|
1293
1498
|
fromRevision: z.number().int().positive().nullable(),
|
|
1294
1499
|
toRevision: z.number().int().positive(),
|
|
1295
|
-
|
|
1500
|
+
cause: sessionProtocolDeltaCauseSchema,
|
|
1296
1501
|
delta: sessionProtocolDeltaSchema,
|
|
1297
1502
|
})
|
|
1298
1503
|
.strip()
|
|
@@ -1334,6 +1539,29 @@ const sessionProtocolDeltaMessageSchema = z
|
|
|
1334
1539
|
message: "snapshot.reset revision must equal toRevision",
|
|
1335
1540
|
});
|
|
1336
1541
|
}
|
|
1542
|
+
if (message.cause.type === "compaction") {
|
|
1543
|
+
if (message.delta.type !== "snapshot.reset" ||
|
|
1544
|
+
message.cause.epoch !== message.cause.previousEpoch + 1 ||
|
|
1545
|
+
message.delta.snapshot.timeline.epoch !== message.cause.epoch) {
|
|
1546
|
+
ctx.addIssue({
|
|
1547
|
+
code: "custom",
|
|
1548
|
+
path: ["cause"],
|
|
1549
|
+
message: "compaction cause must reset the snapshot to the next timeline epoch",
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
if (message.cause.type === "rewind") {
|
|
1554
|
+
const { cutoffSequence, epoch } = message.cause;
|
|
1555
|
+
if (message.delta.type !== "snapshot.reset" ||
|
|
1556
|
+
message.delta.snapshot.timeline.epoch !== epoch ||
|
|
1557
|
+
message.delta.snapshot.timeline.items.some((item) => item.sequence > cutoffSequence)) {
|
|
1558
|
+
ctx.addIssue({
|
|
1559
|
+
code: "custom",
|
|
1560
|
+
path: ["cause"],
|
|
1561
|
+
message: "rewind cause must reset and truncate the active timeline epoch",
|
|
1562
|
+
});
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
1337
1565
|
});
|
|
1338
1566
|
const sessionProtocolEphemeralAgentThreadUpdateEventSchema = z
|
|
1339
1567
|
.object({
|
|
@@ -1349,7 +1577,27 @@ const sessionProtocolEphemeralAgentThreadUpdateEventSchema = z
|
|
|
1349
1577
|
.strip(),
|
|
1350
1578
|
})
|
|
1351
1579
|
.strip();
|
|
1352
|
-
const
|
|
1580
|
+
const sessionProtocolFeedbackEventSchema = z
|
|
1581
|
+
.object({
|
|
1582
|
+
type: z.literal("feedback.notice"),
|
|
1583
|
+
title: noticeTitleSchema,
|
|
1584
|
+
tone: z.enum(["default", "error"]),
|
|
1585
|
+
presentation: z.literal("footer"),
|
|
1586
|
+
durationMs: z.number().int().positive().max(60_000),
|
|
1587
|
+
})
|
|
1588
|
+
.strip();
|
|
1589
|
+
const sessionProtocolEphemeralTimelineEventSchema = z
|
|
1590
|
+
.object({
|
|
1591
|
+
type: z.literal("timeline.item"),
|
|
1592
|
+
epoch: z.number().int().positive(),
|
|
1593
|
+
item: sessionProtocolTimelineItemSchema.refine((item) => item.type === "notice", "ephemeral timeline items must be notices"),
|
|
1594
|
+
})
|
|
1595
|
+
.strip();
|
|
1596
|
+
const sessionProtocolEphemeralEventSchema = z.union([
|
|
1597
|
+
sessionProtocolEphemeralAgentThreadUpdateEventSchema,
|
|
1598
|
+
sessionProtocolFeedbackEventSchema,
|
|
1599
|
+
sessionProtocolEphemeralTimelineEventSchema,
|
|
1600
|
+
]);
|
|
1353
1601
|
const sessionProtocolEphemeralMessageSchema = z
|
|
1354
1602
|
.object({
|
|
1355
1603
|
version: z.literal(SESSION_PROTOCOL_VERSION),
|
|
@@ -1594,7 +1842,7 @@ export function createSessionProtocolDeltaMessage(options) {
|
|
|
1594
1842
|
sessionId: options.sessionId,
|
|
1595
1843
|
fromRevision: options.fromRevision,
|
|
1596
1844
|
toRevision: options.toRevision,
|
|
1597
|
-
|
|
1845
|
+
cause: options.cause,
|
|
1598
1846
|
delta: options.delta,
|
|
1599
1847
|
};
|
|
1600
1848
|
const parsedMessage = sessionProtocolDeltaMessageSchema.safeParse(message);
|
|
@@ -1629,11 +1877,33 @@ export function createSessionProtocolPendingUserMessagesMessage(options) {
|
|
|
1629
1877
|
}
|
|
1630
1878
|
return parsedMessage.data;
|
|
1631
1879
|
}
|
|
1880
|
+
function validateSnapshotResetCause(snapshot, message) {
|
|
1881
|
+
if (message.delta.type !== "snapshot.reset") {
|
|
1882
|
+
return;
|
|
1883
|
+
}
|
|
1884
|
+
if (message.cause.type === "compaction" &&
|
|
1885
|
+
message.cause.previousEpoch !== snapshot.timeline.epoch) {
|
|
1886
|
+
throw new Error(`compaction delta previous epoch ${message.cause.previousEpoch} does not match current timeline epoch ${snapshot.timeline.epoch}`);
|
|
1887
|
+
}
|
|
1888
|
+
if (message.cause.type !== "rewind") {
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
if (message.cause.epoch !== snapshot.timeline.epoch) {
|
|
1892
|
+
throw new Error(`rewind delta epoch ${message.cause.epoch} does not match current timeline epoch ${snapshot.timeline.epoch}`);
|
|
1893
|
+
}
|
|
1894
|
+
if (message.cause.cutoffSequence > snapshot.timeline.sequence) {
|
|
1895
|
+
throw new Error(`rewind delta cutoff sequence ${message.cause.cutoffSequence} exceeds current timeline sequence ${snapshot.timeline.sequence}`);
|
|
1896
|
+
}
|
|
1897
|
+
if (message.delta.snapshot.timeline.sequence !== snapshot.timeline.sequence) {
|
|
1898
|
+
throw new Error(`rewind delta timeline sequence ${message.delta.snapshot.timeline.sequence} does not preserve current timeline sequence ${snapshot.timeline.sequence}`);
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1632
1901
|
export function applySessionProtocolDelta(snapshot, message) {
|
|
1633
1902
|
if (message.sessionId !== snapshot.sessionId) {
|
|
1634
1903
|
throw new Error(`session delta targets '${message.sessionId}' but current snapshot is '${snapshot.sessionId}'`);
|
|
1635
1904
|
}
|
|
1636
1905
|
if (message.delta.type === "snapshot.reset") {
|
|
1906
|
+
validateSnapshotResetCause(snapshot, message);
|
|
1637
1907
|
return structuredClone(message.delta.snapshot);
|
|
1638
1908
|
}
|
|
1639
1909
|
if (message.fromRevision !== snapshot.revision) {
|
|
@@ -1669,9 +1939,6 @@ export function applySessionProtocolDelta(snapshot, message) {
|
|
|
1669
1939
|
break;
|
|
1670
1940
|
case "message.append":
|
|
1671
1941
|
next.messages.push(structuredClone(change.message));
|
|
1672
|
-
if (change.timelineItem) {
|
|
1673
|
-
next.timeline.push(structuredClone(change.timelineItem));
|
|
1674
|
-
}
|
|
1675
1942
|
break;
|
|
1676
1943
|
case "message.replace": {
|
|
1677
1944
|
const index = next.messages.findIndex((entry) => entry.id === change.message.id);
|
|
@@ -1688,20 +1955,23 @@ export function applySessionProtocolDelta(snapshot, message) {
|
|
|
1688
1955
|
break;
|
|
1689
1956
|
}
|
|
1690
1957
|
case "timeline.append":
|
|
1691
|
-
next.timeline.
|
|
1692
|
-
|
|
1693
|
-
case "timeline.replace": {
|
|
1694
|
-
const index = next.timeline.findIndex((item) => item.id === change.item.id);
|
|
1695
|
-
if (index === -1) {
|
|
1696
|
-
next.timeline.push(structuredClone(change.item));
|
|
1697
|
-
}
|
|
1698
|
-
else {
|
|
1699
|
-
next.timeline[index] = structuredClone(change.item);
|
|
1958
|
+
if (change.item.sequence <= next.timeline.sequence) {
|
|
1959
|
+
throw new Error(`timeline append sequence ${change.item.sequence} must exceed current timeline sequence ${next.timeline.sequence}`);
|
|
1700
1960
|
}
|
|
1961
|
+
next.timeline.items.push(structuredClone(change.item));
|
|
1962
|
+
next.timeline.sequence = change.item.sequence;
|
|
1701
1963
|
break;
|
|
1702
|
-
}
|
|
1703
1964
|
case "timeline.remove":
|
|
1704
|
-
next.timeline = next.timeline.filter((item) => item.id !== change.id);
|
|
1965
|
+
next.timeline.items = next.timeline.items.filter((item) => item.id !== change.id);
|
|
1966
|
+
break;
|
|
1967
|
+
case "timeline.advance":
|
|
1968
|
+
if (next.timeline.epoch !== change.epoch) {
|
|
1969
|
+
throw new Error("timeline advance epoch does not match the active epoch");
|
|
1970
|
+
}
|
|
1971
|
+
if (change.sequence <= next.timeline.sequence) {
|
|
1972
|
+
throw new Error(`timeline advance sequence ${change.sequence} must exceed current timeline sequence ${next.timeline.sequence}`);
|
|
1973
|
+
}
|
|
1974
|
+
next.timeline.sequence = change.sequence;
|
|
1705
1975
|
break;
|
|
1706
1976
|
case "tool.set":
|
|
1707
1977
|
next.tools[change.tool.id] = structuredClone(change.tool);
|
|
@@ -1709,6 +1979,12 @@ export function applySessionProtocolDelta(snapshot, message) {
|
|
|
1709
1979
|
case "tool.remove":
|
|
1710
1980
|
delete next.tools[change.id];
|
|
1711
1981
|
break;
|
|
1982
|
+
case "operation.set":
|
|
1983
|
+
next.operations[change.operation.id] = structuredClone(change.operation);
|
|
1984
|
+
break;
|
|
1985
|
+
case "operation.remove":
|
|
1986
|
+
delete next.operations[change.id];
|
|
1987
|
+
break;
|
|
1712
1988
|
case "agent.set":
|
|
1713
1989
|
next.agents[change.agent.id] = structuredClone(change.agent);
|
|
1714
1990
|
break;
|
|
@@ -1751,17 +2027,16 @@ function changeCanInvalidateSnapshot(snapshot, change) {
|
|
|
1751
2027
|
const previous = snapshot.facets[change.facet.id];
|
|
1752
2028
|
return !previous || !hasSameFacetSubject(previous, change.facet);
|
|
1753
2029
|
}
|
|
1754
|
-
case "timeline.replace": {
|
|
1755
|
-
const previous = snapshot.timeline.find((item) => item.id === change.item.id);
|
|
1756
|
-
return !previous || !hasSameTimelineReferences(previous, change.item);
|
|
1757
|
-
}
|
|
1758
2030
|
case "agent-state.set":
|
|
1759
2031
|
case "message.append":
|
|
1760
2032
|
case "message.replace":
|
|
1761
2033
|
case "message.content.append":
|
|
1762
2034
|
case "timeline.append":
|
|
1763
2035
|
case "timeline.remove":
|
|
2036
|
+
case "timeline.advance":
|
|
1764
2037
|
case "tool.remove":
|
|
2038
|
+
case "operation.set":
|
|
2039
|
+
case "operation.remove":
|
|
1765
2040
|
case "agent.remove":
|
|
1766
2041
|
case "facet.remove":
|
|
1767
2042
|
return true;
|
|
@@ -1791,25 +2066,22 @@ function hasSameFacetSubject(previous, facet) {
|
|
|
1791
2066
|
(previous.subject.type === "session" ||
|
|
1792
2067
|
(facet.subject.type !== "session" && previous.subject.id === facet.subject.id)));
|
|
1793
2068
|
}
|
|
1794
|
-
function hasSameTimelineReferences(previous, item) {
|
|
1795
|
-
if (previous.type !== item.type)
|
|
1796
|
-
return false;
|
|
1797
|
-
if (previous.type === "message" && item.type === "message") {
|
|
1798
|
-
return previous.messageId === item.messageId;
|
|
1799
|
-
}
|
|
1800
|
-
return true;
|
|
1801
|
-
}
|
|
1802
2069
|
function applyKeyedRecordDelta(snapshot, message) {
|
|
1803
2070
|
if (message.delta.type !== "snapshot.patch") {
|
|
1804
2071
|
return undefined;
|
|
1805
2072
|
}
|
|
1806
2073
|
let nextTools;
|
|
2074
|
+
let nextOperations;
|
|
1807
2075
|
let nextAgents;
|
|
1808
2076
|
let nextFacets;
|
|
1809
2077
|
const cloneTools = () => {
|
|
1810
2078
|
nextTools ??= { ...snapshot.tools };
|
|
1811
2079
|
return nextTools;
|
|
1812
2080
|
};
|
|
2081
|
+
const cloneOperations = () => {
|
|
2082
|
+
nextOperations ??= { ...snapshot.operations };
|
|
2083
|
+
return nextOperations;
|
|
2084
|
+
};
|
|
1813
2085
|
const cloneAgents = () => {
|
|
1814
2086
|
nextAgents ??= { ...snapshot.agents };
|
|
1815
2087
|
return nextAgents;
|
|
@@ -1826,6 +2098,12 @@ function applyKeyedRecordDelta(snapshot, message) {
|
|
|
1826
2098
|
case "tool.remove":
|
|
1827
2099
|
delete cloneTools()[change.id];
|
|
1828
2100
|
break;
|
|
2101
|
+
case "operation.set":
|
|
2102
|
+
cloneOperations()[change.operation.id] = structuredClone(change.operation);
|
|
2103
|
+
break;
|
|
2104
|
+
case "operation.remove":
|
|
2105
|
+
delete cloneOperations()[change.id];
|
|
2106
|
+
break;
|
|
1829
2107
|
case "agent.set":
|
|
1830
2108
|
cloneAgents()[change.agent.id] = structuredClone(change.agent);
|
|
1831
2109
|
break;
|
|
@@ -1846,6 +2124,7 @@ function applyKeyedRecordDelta(snapshot, message) {
|
|
|
1846
2124
|
...snapshot,
|
|
1847
2125
|
revision: message.toRevision,
|
|
1848
2126
|
...(nextTools ? { tools: nextTools } : {}),
|
|
2127
|
+
...(nextOperations ? { operations: nextOperations } : {}),
|
|
1849
2128
|
...(nextAgents ? { agents: nextAgents } : {}),
|
|
1850
2129
|
...(nextFacets ? { facets: nextFacets } : {}),
|
|
1851
2130
|
};
|
|
@@ -2730,8 +3009,8 @@ function parseSessionProtocolDeltaMessage(payload) {
|
|
|
2730
3009
|
if (hasIssue(deltaMessage.error, ["toRevision"])) {
|
|
2731
3010
|
return fail("session.delta.toRevision must be a positive integer");
|
|
2732
3011
|
}
|
|
2733
|
-
if (hasIssue(deltaMessage.error, ["
|
|
2734
|
-
return fail("session.delta.
|
|
3012
|
+
if (hasIssue(deltaMessage.error, ["cause"])) {
|
|
3013
|
+
return fail("session.delta.cause is invalid");
|
|
2735
3014
|
}
|
|
2736
3015
|
if (hasIssue(deltaMessage.error, ["delta"])) {
|
|
2737
3016
|
return fail("session.delta.delta is invalid");
|
|
@@ -2746,7 +3025,7 @@ function parseSessionProtocolDeltaMessage(payload) {
|
|
|
2746
3025
|
sessionId: deltaMessage.data.sessionId,
|
|
2747
3026
|
fromRevision: deltaMessage.data.fromRevision,
|
|
2748
3027
|
toRevision: deltaMessage.data.toRevision,
|
|
2749
|
-
|
|
3028
|
+
cause: deltaMessage.data.cause,
|
|
2750
3029
|
delta: deltaMessage.data.delta,
|
|
2751
3030
|
},
|
|
2752
3031
|
};
|