@yolk-sdk/agent 0.1.0-canary.20 → 0.1.0-canary.21
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 +21 -1
- package/dist/client/state.d.mts +4 -2
- package/dist/client/state.d.mts.map +1 -1
- package/dist/client/state.mjs +42 -22
- package/dist/client/state.mjs.map +1 -1
- package/dist/loop/error.d.mts +3 -2
- package/dist/loop/error.d.mts.map +1 -1
- package/dist/loop/error.mjs +6 -3
- package/dist/loop/error.mjs.map +1 -1
- package/dist/loop/run.d.mts.map +1 -1
- package/dist/loop/run.mjs +17 -3
- package/dist/loop/run.mjs.map +1 -1
- package/dist/loop/services/loop-config.mjs +1 -1
- package/dist/loop/services/loop-config.mjs.map +1 -1
- package/dist/protocol/event.d.mts +17 -5
- package/dist/protocol/event.d.mts.map +1 -1
- package/dist/protocol/event.mjs +24 -3
- package/dist/protocol/event.mjs.map +1 -1
- package/dist/protocol/index.d.mts +2 -2
- package/dist/protocol/index.d.mts.map +1 -1
- package/dist/protocol/index.mjs +2 -2
- package/dist/providers/anthropic/claude-provider.d.mts.map +1 -1
- package/dist/providers/anthropic/claude-provider.mjs +36 -15
- package/dist/providers/anthropic/claude-provider.mjs.map +1 -1
- package/dist/providers/openai/codex-provider.d.mts.map +1 -1
- package/dist/providers/openai/codex-provider.mjs +59 -17
- package/dist/providers/openai/codex-provider.mjs.map +1 -1
- package/dist/providers/openai/provider.d.mts.map +1 -1
- package/dist/providers/openai/provider.mjs +16 -10
- package/dist/providers/openai/provider.mjs.map +1 -1
- package/dist/providers/provider-error.d.mts +32 -0
- package/dist/providers/provider-error.d.mts.map +1 -0
- package/dist/providers/provider-error.mjs +91 -0
- package/dist/providers/provider-error.mjs.map +1 -0
- package/dist/react/chat-core.d.mts +3 -1
- package/dist/react/chat-core.d.mts.map +1 -1
- package/dist/react/chat-core.mjs +42 -6
- package/dist/react/chat-core.mjs.map +1 -1
- package/dist/react/chat-items.d.mts +8 -2
- package/dist/react/chat-items.d.mts.map +1 -1
- package/dist/react/chat-items.mjs +16 -9
- package/dist/react/chat-items.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client/state.ts +43 -18
- package/src/loop/error.ts +6 -3
- package/src/loop/run.ts +27 -4
- package/src/loop/services/loop-config.ts +1 -1
- package/src/protocol/event.ts +26 -2
- package/src/protocol/index.ts +2 -0
- package/src/providers/anthropic/claude-provider.ts +51 -22
- package/src/providers/openai/codex-provider.ts +81 -19
- package/src/providers/openai/provider.ts +22 -18
- package/src/providers/provider-error.ts +213 -0
- package/src/react/chat-core.ts +46 -5
- package/src/react/chat-items.ts +10 -3
package/dist/react/chat-core.mjs
CHANGED
|
@@ -5,6 +5,8 @@ import { hitlResponseEvent } from "@yolk-sdk/agent/protocol";
|
|
|
5
5
|
const initialAgentChatState = {
|
|
6
6
|
status: "idle",
|
|
7
7
|
error: null,
|
|
8
|
+
errorInfo: null,
|
|
9
|
+
retryInfo: null,
|
|
8
10
|
chatMessages: [],
|
|
9
11
|
sessionEvents: [],
|
|
10
12
|
seenEventIds: []
|
|
@@ -14,17 +16,25 @@ const rememberEvent = (state, event) => event.eventId === void 0 ? state : {
|
|
|
14
16
|
...state,
|
|
15
17
|
seenEventIds: [...state.seenEventIds, event.eventId]
|
|
16
18
|
};
|
|
19
|
+
const clearRetryInfo = (state) => state.retryInfo === null ? state : {
|
|
20
|
+
...state,
|
|
21
|
+
retryInfo: null
|
|
22
|
+
};
|
|
17
23
|
const reduceAgentChatState = (state, action) => {
|
|
18
24
|
switch (action._tag) {
|
|
19
25
|
case "HydrateMessage": return {
|
|
20
26
|
...state,
|
|
21
27
|
chatMessages: appendProtocolMessage(state.chatMessages, action.message),
|
|
22
|
-
error: null
|
|
28
|
+
error: null,
|
|
29
|
+
errorInfo: null,
|
|
30
|
+
retryInfo: null
|
|
23
31
|
};
|
|
24
32
|
case "Submit": return {
|
|
25
33
|
...state,
|
|
26
34
|
status: "running",
|
|
27
35
|
error: null,
|
|
36
|
+
errorInfo: null,
|
|
37
|
+
retryInfo: null,
|
|
28
38
|
seenEventIds: [],
|
|
29
39
|
chatMessages: appendProtocolMessage(state.chatMessages, action.message),
|
|
30
40
|
sessionEvents: [...state.sessionEvents, UserMessageSubmitted.make({ message: action.message })]
|
|
@@ -33,12 +43,16 @@ const reduceAgentChatState = (state, action) => {
|
|
|
33
43
|
...state,
|
|
34
44
|
chatMessages: appendProtocolMessage(state.chatMessages, action.message),
|
|
35
45
|
error: null,
|
|
46
|
+
errorInfo: null,
|
|
47
|
+
retryInfo: null,
|
|
36
48
|
sessionEvents: [...state.sessionEvents, ProtocolMessageAppended.make({ message: action.message })]
|
|
37
49
|
};
|
|
38
50
|
case "SubmitHitlResponse": return {
|
|
39
51
|
...state,
|
|
40
52
|
status: "running",
|
|
41
53
|
error: null,
|
|
54
|
+
errorInfo: null,
|
|
55
|
+
retryInfo: null,
|
|
42
56
|
seenEventIds: [],
|
|
43
57
|
chatMessages: applyAgentEventToChatMessages(state.chatMessages, hitlResponseEvent(action.response))
|
|
44
58
|
};
|
|
@@ -48,6 +62,8 @@ const reduceAgentChatState = (state, action) => {
|
|
|
48
62
|
return {
|
|
49
63
|
...state,
|
|
50
64
|
error: null,
|
|
65
|
+
errorInfo: null,
|
|
66
|
+
retryInfo: null,
|
|
51
67
|
chatMessages: next.messages,
|
|
52
68
|
sessionEvents: [...state.sessionEvents, TurnDeleted.make({
|
|
53
69
|
turnStartMessageId: next.turnStartMessageId,
|
|
@@ -62,6 +78,8 @@ const reduceAgentChatState = (state, action) => {
|
|
|
62
78
|
...state,
|
|
63
79
|
status: "running",
|
|
64
80
|
error: null,
|
|
81
|
+
errorInfo: null,
|
|
82
|
+
retryInfo: null,
|
|
65
83
|
seenEventIds: [],
|
|
66
84
|
chatMessages: next.messages,
|
|
67
85
|
sessionEvents: [...state.sessionEvents, MessagesRegenerated.make({
|
|
@@ -77,6 +95,8 @@ const reduceAgentChatState = (state, action) => {
|
|
|
77
95
|
...state,
|
|
78
96
|
status: "running",
|
|
79
97
|
error: null,
|
|
98
|
+
errorInfo: null,
|
|
99
|
+
retryInfo: null,
|
|
80
100
|
seenEventIds: [],
|
|
81
101
|
chatMessages: next.messages,
|
|
82
102
|
sessionEvents: [...state.sessionEvents, UserMessageEdited.make({
|
|
@@ -93,29 +113,41 @@ const reduceAgentChatState = (state, action) => {
|
|
|
93
113
|
...state,
|
|
94
114
|
status: "running",
|
|
95
115
|
error: null,
|
|
116
|
+
errorInfo: null,
|
|
117
|
+
retryInfo: null,
|
|
96
118
|
chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)
|
|
97
119
|
}, action.event);
|
|
98
120
|
case "AgentError": return rememberEvent({
|
|
99
121
|
...state,
|
|
100
122
|
status: "error",
|
|
101
123
|
error: action.event.message,
|
|
124
|
+
errorInfo: action.event,
|
|
125
|
+
retryInfo: null,
|
|
102
126
|
chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)
|
|
103
127
|
}, action.event);
|
|
104
128
|
case "AgentEnd": return rememberEvent({
|
|
105
129
|
...state,
|
|
106
130
|
status: "done",
|
|
107
131
|
error: null,
|
|
132
|
+
errorInfo: null,
|
|
133
|
+
retryInfo: null,
|
|
108
134
|
chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)
|
|
109
135
|
}, action.event);
|
|
110
136
|
case "AgentAwaitingInput": return rememberEvent({
|
|
111
137
|
...state,
|
|
112
138
|
status: "waiting",
|
|
113
139
|
error: null,
|
|
140
|
+
errorInfo: null,
|
|
141
|
+
retryInfo: null,
|
|
142
|
+
chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)
|
|
143
|
+
}, action.event);
|
|
144
|
+
case "AgentRetry": return rememberEvent({
|
|
145
|
+
...state,
|
|
146
|
+
retryInfo: action.event,
|
|
114
147
|
chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)
|
|
115
148
|
}, action.event);
|
|
116
|
-
case "AssistantMessage":
|
|
117
|
-
case "AgentRetry":
|
|
118
149
|
case "CompactionEnd":
|
|
150
|
+
case "AssistantMessage":
|
|
119
151
|
case "CompactionStart":
|
|
120
152
|
case "LLMReasoningDelta":
|
|
121
153
|
case "LLMStreamEnd":
|
|
@@ -138,21 +170,25 @@ const reduceAgentChatState = (state, action) => {
|
|
|
138
170
|
case "ToolInputStart":
|
|
139
171
|
case "TurnEnd":
|
|
140
172
|
case "TurnStart":
|
|
141
|
-
case "UsageUpdate": return rememberEvent({
|
|
173
|
+
case "UsageUpdate": return rememberEvent(clearRetryInfo({
|
|
142
174
|
...state,
|
|
143
175
|
chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)
|
|
144
|
-
}, action.event);
|
|
176
|
+
}), action.event);
|
|
145
177
|
}
|
|
146
178
|
case "Error": return {
|
|
147
179
|
...state,
|
|
148
180
|
status: "error",
|
|
149
181
|
error: action.message,
|
|
182
|
+
errorInfo: null,
|
|
183
|
+
retryInfo: null,
|
|
150
184
|
chatMessages: markChatError(state.chatMessages, action.message)
|
|
151
185
|
};
|
|
152
186
|
case "Abort": return {
|
|
153
187
|
...state,
|
|
154
188
|
status: "aborted",
|
|
155
|
-
error: null
|
|
189
|
+
error: null,
|
|
190
|
+
errorInfo: null,
|
|
191
|
+
retryInfo: null
|
|
156
192
|
};
|
|
157
193
|
}
|
|
158
194
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-core.mjs","names":[],"sources":["../../src/react/chat-core.ts"],"sourcesContent":["import {\n hitlResponseEvent,\n type AgentEvent,\n type AgentMessage,\n type Content,\n type HitlResponse,\n type UserMessage\n} from '@yolk-sdk/agent/protocol'\nimport {\n appendProtocolMessage,\n applyAgentEventToChatMessages,\n deleteChatTurn,\n editChatUserMessage,\n markChatError,\n regenerateChatMessagesFrom,\n type AgentChatMessage,\n type AgentChatPart,\n type ApplyAgentEventToChatMessagesOptions\n} from './chat-messages.ts'\nimport {\n MessagesRegenerated,\n ProtocolMessageAppended,\n TurnDeleted,\n UserMessageEdited,\n UserMessageSubmitted,\n type AgentChatSessionEvent\n} from './chat-session-events.ts'\n\nexport type AgentRunStatus = 'idle' | 'running' | 'waiting' | 'done' | 'error' | 'aborted'\n\nexport type AgentChatState = {\n readonly status: AgentRunStatus\n readonly error: string | null\n readonly chatMessages: ReadonlyArray<AgentChatMessage>\n readonly sessionEvents: ReadonlyArray<AgentChatSessionEvent>\n readonly seenEventIds: ReadonlyArray<string>\n}\n\nexport const initialAgentChatState: AgentChatState = {\n status: 'idle',\n error: null,\n chatMessages: [],\n sessionEvents: [],\n seenEventIds: []\n}\n\nconst hasSeenEvent = (state: AgentChatState, event: AgentEvent) =>\n event.eventId !== undefined && state.seenEventIds.includes(event.eventId)\n\nconst rememberEvent = (state: AgentChatState, event: AgentEvent): AgentChatState =>\n event.eventId === undefined\n ? state\n : { ...state, seenEventIds: [...state.seenEventIds, event.eventId] }\n\nexport type AgentChatAction =\n | { readonly _tag: 'HydrateMessage'; readonly message: AgentMessage }\n | { readonly _tag: 'Submit'; readonly message: UserMessage }\n | { readonly _tag: 'AppendMessage'; readonly message: AgentMessage }\n | { readonly _tag: 'SubmitHitlResponse'; readonly response: HitlResponse }\n | { readonly _tag: 'DeleteTurn'; readonly messageId: string }\n | { readonly _tag: 'RegenerateFrom'; readonly messageId: string }\n | { readonly _tag: 'EditUserMessage'; readonly messageId: string; readonly content: Content }\n | ({ readonly _tag: 'Event'; readonly event: AgentEvent } & ApplyAgentEventToChatMessagesOptions)\n | { readonly _tag: 'Error'; readonly message: string }\n | { readonly _tag: 'Abort' }\n\nexport const reduceAgentChatState = (\n state: AgentChatState,\n action: AgentChatAction\n): AgentChatState => {\n switch (action._tag) {\n case 'HydrateMessage':\n return {\n ...state,\n chatMessages: appendProtocolMessage(state.chatMessages, action.message),\n error: null\n }\n case 'Submit':\n return {\n ...state,\n status: 'running',\n error: null,\n seenEventIds: [],\n chatMessages: appendProtocolMessage(state.chatMessages, action.message),\n sessionEvents: [\n ...state.sessionEvents,\n UserMessageSubmitted.make({ message: action.message })\n ]\n }\n case 'AppendMessage':\n return {\n ...state,\n chatMessages: appendProtocolMessage(state.chatMessages, action.message),\n error: null,\n sessionEvents: [\n ...state.sessionEvents,\n ProtocolMessageAppended.make({ message: action.message })\n ]\n }\n case 'SubmitHitlResponse':\n return {\n ...state,\n status: 'running',\n error: null,\n seenEventIds: [],\n chatMessages: applyAgentEventToChatMessages(\n state.chatMessages,\n hitlResponseEvent(action.response)\n )\n }\n case 'DeleteTurn': {\n const next = deleteChatTurn(state.chatMessages, action.messageId)\n\n if (next._tag === 'NotFound') {\n return state\n }\n\n return {\n ...state,\n error: null,\n chatMessages: next.messages,\n sessionEvents: [\n ...state.sessionEvents,\n TurnDeleted.make({\n turnStartMessageId: next.turnStartMessageId,\n deletedMessageIds: next.deletedMessageIds\n })\n ]\n }\n }\n case 'RegenerateFrom': {\n const next = regenerateChatMessagesFrom(state.chatMessages, action.messageId)\n\n if (next._tag === 'NotFound') {\n return state\n }\n\n return {\n ...state,\n status: 'running',\n error: null,\n seenEventIds: [],\n chatMessages: next.messages,\n sessionEvents: [\n ...state.sessionEvents,\n MessagesRegenerated.make({\n fromMessageId: action.messageId,\n keptMessageIds: next.messages.map(message => message.id)\n })\n ]\n }\n }\n case 'EditUserMessage': {\n const next = editChatUserMessage(state.chatMessages, action.messageId, action.content)\n\n if (next._tag !== 'Edited') {\n return state\n }\n\n return {\n ...state,\n status: 'running',\n error: null,\n seenEventIds: [],\n chatMessages: next.messages,\n sessionEvents: [\n ...state.sessionEvents,\n UserMessageEdited.make({\n messageId: next.messageId,\n content: action.content,\n keptMessageIds: next.messages.map(message => message.id)\n })\n ]\n }\n }\n case 'Event': {\n if (hasSeenEvent(state, action.event)) {\n return state\n }\n\n switch (action.event._tag) {\n case 'AgentStart':\n return rememberEvent(\n {\n ...state,\n status: 'running',\n error: null,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AgentError':\n return rememberEvent(\n {\n ...state,\n status: 'error',\n error: action.event.message,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AgentEnd':\n return rememberEvent(\n {\n ...state,\n status: 'done',\n error: null,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AgentAwaitingInput':\n return rememberEvent(\n {\n ...state,\n status: 'waiting',\n error: null,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AssistantMessage':\n case 'AgentRetry':\n case 'CompactionEnd':\n case 'CompactionStart':\n case 'LLMReasoningDelta':\n case 'LLMStreamEnd':\n case 'LLMStreamStart':\n case 'LLMTextDelta':\n case 'ProviderToolResult':\n case 'QuestionAnswered':\n case 'QuestionCancelled':\n case 'QuestionRequested':\n case 'SubagentCompleted':\n case 'SubagentStarted':\n case 'ToolApprovalDenied':\n case 'ToolApprovalGranted':\n case 'ToolApprovalRequested':\n case 'ToolExecutionCompleted':\n case 'ToolExecutionError':\n case 'ToolExecutionStarted':\n case 'ToolInputDelta':\n case 'ToolInputEnd':\n case 'ToolInputStart':\n case 'TurnEnd':\n case 'TurnStart':\n case 'UsageUpdate':\n return rememberEvent(\n {\n ...state,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n }\n }\n case 'Error': {\n return {\n ...state,\n status: 'error',\n error: action.message,\n chatMessages: markChatError(state.chatMessages, action.message)\n }\n }\n case 'Abort':\n return { ...state, status: 'aborted', error: null }\n }\n}\n\nexport const hasAgentMessageReasoning = (message: AgentMessage) =>\n message._tag === 'Assistant' &&\n message.parts.some(part => part._tag === 'Reasoning' && part.text.length > 0)\n\nexport const hasAgentChatReasoningSummary = (state: AgentChatState) =>\n state.chatMessages.some(message =>\n message.parts.some(part => part._tag === 'Reasoning' && part.text.length > 0)\n )\n\nexport const isActiveChatToolPart = (part: AgentChatPart) =>\n part._tag === 'ToolCall' &&\n part.state._tag !== 'Completed' &&\n part.state._tag !== 'ProviderCompleted' &&\n part.state._tag !== 'QuestionAnswered' &&\n part.state._tag !== 'QuestionCancelled' &&\n part.state._tag !== 'Errored' &&\n part.state._tag !== 'Denied'\nexport type ActiveChatToolPart = Extract<AgentChatPart, { readonly _tag: 'ToolCall' }>\n\nexport const isCompletedChatToolPart = (part: AgentChatPart) =>\n part._tag === 'ToolCall' && part.state._tag === 'Completed'\nexport type CompletedChatToolPart = Extract<AgentChatPart, { readonly _tag: 'ToolCall' }>\n\nexport const getActiveChatToolParts = (messages: ReadonlyArray<AgentChatMessage>) =>\n messages.flatMap(message =>\n message.parts.filter((part): part is ActiveChatToolPart => isActiveChatToolPart(part))\n )\n\nexport const getCompletedChatToolParts = (messages: ReadonlyArray<AgentChatMessage>) =>\n messages.flatMap(message =>\n message.parts.filter((part): part is CompletedChatToolPart => isCompletedChatToolPart(part))\n )\n\ntype AgentChatLiveActivityInput = {\n readonly isTextRunning: boolean\n readonly activeToolCallCount: number\n readonly isVoiceActive: boolean\n}\n\nexport const getAgentChatLiveActivityCount = ({\n isTextRunning,\n activeToolCallCount,\n isVoiceActive\n}: AgentChatLiveActivityInput) =>\n (isTextRunning ? 1 : 0) + activeToolCallCount + (isVoiceActive ? 1 : 0)\n"],"mappings":";;;;AAsCA,MAAa,wBAAwC;CACnD,QAAQ;CACR,OAAO;CACP,cAAc,CAAC;CACf,eAAe,CAAC;CAChB,cAAc,CAAC;AACjB;AAEA,MAAM,gBAAgB,OAAuB,UAC3C,MAAM,YAAY,KAAA,KAAa,MAAM,aAAa,SAAS,MAAM,OAAO;AAE1E,MAAM,iBAAiB,OAAuB,UAC5C,MAAM,YAAY,KAAA,IACd,QACA;CAAE,GAAG;CAAO,cAAc,CAAC,GAAG,MAAM,cAAc,MAAM,OAAO;AAAE;AAcvE,MAAa,wBACX,OACA,WACmB;CACnB,QAAQ,OAAO,MAAf;EACE,KAAK,kBACH,OAAO;GACL,GAAG;GACH,cAAc,sBAAsB,MAAM,cAAc,OAAO,OAAO;GACtE,OAAO;EACT;EACF,KAAK,UACH,OAAO;GACL,GAAG;GACH,QAAQ;GACR,OAAO;GACP,cAAc,CAAC;GACf,cAAc,sBAAsB,MAAM,cAAc,OAAO,OAAO;GACtE,eAAe,CACb,GAAG,MAAM,eACT,qBAAqB,KAAK,EAAE,SAAS,OAAO,QAAQ,CAAC,CACvD;EACF;EACF,KAAK,iBACH,OAAO;GACL,GAAG;GACH,cAAc,sBAAsB,MAAM,cAAc,OAAO,OAAO;GACtE,OAAO;GACP,eAAe,CACb,GAAG,MAAM,eACT,wBAAwB,KAAK,EAAE,SAAS,OAAO,QAAQ,CAAC,CAC1D;EACF;EACF,KAAK,sBACH,OAAO;GACL,GAAG;GACH,QAAQ;GACR,OAAO;GACP,cAAc,CAAC;GACf,cAAc,8BACZ,MAAM,cACN,kBAAkB,OAAO,QAAQ,CACnC;EACF;EACF,KAAK,cAAc;GACjB,MAAM,OAAO,eAAe,MAAM,cAAc,OAAO,SAAS;GAEhE,IAAI,KAAK,SAAS,YAChB,OAAO;GAGT,OAAO;IACL,GAAG;IACH,OAAO;IACP,cAAc,KAAK;IACnB,eAAe,CACb,GAAG,MAAM,eACT,YAAY,KAAK;KACf,oBAAoB,KAAK;KACzB,mBAAmB,KAAK;IAC1B,CAAC,CACH;GACF;EACF;EACA,KAAK,kBAAkB;GACrB,MAAM,OAAO,2BAA2B,MAAM,cAAc,OAAO,SAAS;GAE5E,IAAI,KAAK,SAAS,YAChB,OAAO;GAGT,OAAO;IACL,GAAG;IACH,QAAQ;IACR,OAAO;IACP,cAAc,CAAC;IACf,cAAc,KAAK;IACnB,eAAe,CACb,GAAG,MAAM,eACT,oBAAoB,KAAK;KACvB,eAAe,OAAO;KACtB,gBAAgB,KAAK,SAAS,KAAI,YAAW,QAAQ,EAAE;IACzD,CAAC,CACH;GACF;EACF;EACA,KAAK,mBAAmB;GACtB,MAAM,OAAO,oBAAoB,MAAM,cAAc,OAAO,WAAW,OAAO,OAAO;GAErF,IAAI,KAAK,SAAS,UAChB,OAAO;GAGT,OAAO;IACL,GAAG;IACH,QAAQ;IACR,OAAO;IACP,cAAc,CAAC;IACf,cAAc,KAAK;IACnB,eAAe,CACb,GAAG,MAAM,eACT,kBAAkB,KAAK;KACrB,WAAW,KAAK;KAChB,SAAS,OAAO;KAChB,gBAAgB,KAAK,SAAS,KAAI,YAAW,QAAQ,EAAE;IACzD,CAAC,CACH;GACF;EACF;EACA,KAAK;GACH,IAAI,aAAa,OAAO,OAAO,KAAK,GAClC,OAAO;GAGT,QAAQ,OAAO,MAAM,MAArB;IACE,KAAK,cACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO;KACP,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK,cACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO,OAAO,MAAM;KACpB,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK,YACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO;KACP,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK,sBACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO;KACP,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK,eACH,OAAO,cACL;KACE,GAAG;KACH,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;GACJ;EAEF,KAAK,SACH,OAAO;GACL,GAAG;GACH,QAAQ;GACR,OAAO,OAAO;GACd,cAAc,cAAc,MAAM,cAAc,OAAO,OAAO;EAChE;EAEF,KAAK,SACH,OAAO;GAAE,GAAG;GAAO,QAAQ;GAAW,OAAO;EAAK;CACtD;AACF;AAEA,MAAa,4BAA4B,YACvC,QAAQ,SAAS,eACjB,QAAQ,MAAM,MAAK,SAAQ,KAAK,SAAS,eAAe,KAAK,KAAK,SAAS,CAAC;AAE9E,MAAa,gCAAgC,UAC3C,MAAM,aAAa,MAAK,YACtB,QAAQ,MAAM,MAAK,SAAQ,KAAK,SAAS,eAAe,KAAK,KAAK,SAAS,CAAC,CAC9E;AAEF,MAAa,wBAAwB,SACnC,KAAK,SAAS,cACd,KAAK,MAAM,SAAS,eACpB,KAAK,MAAM,SAAS,uBACpB,KAAK,MAAM,SAAS,sBACpB,KAAK,MAAM,SAAS,uBACpB,KAAK,MAAM,SAAS,aACpB,KAAK,MAAM,SAAS;AAGtB,MAAa,2BAA2B,SACtC,KAAK,SAAS,cAAc,KAAK,MAAM,SAAS;AAGlD,MAAa,0BAA0B,aACrC,SAAS,SAAQ,YACf,QAAQ,MAAM,QAAQ,SAAqC,qBAAqB,IAAI,CAAC,CACvF;AAEF,MAAa,6BAA6B,aACxC,SAAS,SAAQ,YACf,QAAQ,MAAM,QAAQ,SAAwC,wBAAwB,IAAI,CAAC,CAC7F;AAQF,MAAa,iCAAiC,EAC5C,eACA,qBACA,qBAEC,gBAAgB,IAAI,KAAK,uBAAuB,gBAAgB,IAAI"}
|
|
1
|
+
{"version":3,"file":"chat-core.mjs","names":[],"sources":["../../src/react/chat-core.ts"],"sourcesContent":["import {\n hitlResponseEvent,\n type AgentError,\n type AgentEvent,\n type AgentMessage,\n type AgentRetry,\n type Content,\n type HitlResponse,\n type UserMessage\n} from '@yolk-sdk/agent/protocol'\nimport {\n appendProtocolMessage,\n applyAgentEventToChatMessages,\n deleteChatTurn,\n editChatUserMessage,\n markChatError,\n regenerateChatMessagesFrom,\n type AgentChatMessage,\n type AgentChatPart,\n type ApplyAgentEventToChatMessagesOptions\n} from './chat-messages.ts'\nimport {\n MessagesRegenerated,\n ProtocolMessageAppended,\n TurnDeleted,\n UserMessageEdited,\n UserMessageSubmitted,\n type AgentChatSessionEvent\n} from './chat-session-events.ts'\n\nexport type AgentRunStatus = 'idle' | 'running' | 'waiting' | 'done' | 'error' | 'aborted'\n\nexport type AgentChatState = {\n readonly status: AgentRunStatus\n readonly error: string | null\n readonly errorInfo: AgentError | null\n readonly retryInfo: AgentRetry | null\n readonly chatMessages: ReadonlyArray<AgentChatMessage>\n readonly sessionEvents: ReadonlyArray<AgentChatSessionEvent>\n readonly seenEventIds: ReadonlyArray<string>\n}\n\nexport const initialAgentChatState: AgentChatState = {\n status: 'idle',\n error: null,\n errorInfo: null,\n retryInfo: null,\n chatMessages: [],\n sessionEvents: [],\n seenEventIds: []\n}\n\nconst hasSeenEvent = (state: AgentChatState, event: AgentEvent) =>\n event.eventId !== undefined && state.seenEventIds.includes(event.eventId)\n\nconst rememberEvent = (state: AgentChatState, event: AgentEvent): AgentChatState =>\n event.eventId === undefined\n ? state\n : { ...state, seenEventIds: [...state.seenEventIds, event.eventId] }\n\nconst clearRetryInfo = (state: AgentChatState): AgentChatState =>\n state.retryInfo === null ? state : { ...state, retryInfo: null }\n\nexport type AgentChatAction =\n | { readonly _tag: 'HydrateMessage'; readonly message: AgentMessage }\n | { readonly _tag: 'Submit'; readonly message: UserMessage }\n | { readonly _tag: 'AppendMessage'; readonly message: AgentMessage }\n | { readonly _tag: 'SubmitHitlResponse'; readonly response: HitlResponse }\n | { readonly _tag: 'DeleteTurn'; readonly messageId: string }\n | { readonly _tag: 'RegenerateFrom'; readonly messageId: string }\n | { readonly _tag: 'EditUserMessage'; readonly messageId: string; readonly content: Content }\n | ({ readonly _tag: 'Event'; readonly event: AgentEvent } & ApplyAgentEventToChatMessagesOptions)\n | { readonly _tag: 'Error'; readonly message: string }\n | { readonly _tag: 'Abort' }\n\nexport const reduceAgentChatState = (\n state: AgentChatState,\n action: AgentChatAction\n): AgentChatState => {\n switch (action._tag) {\n case 'HydrateMessage':\n return {\n ...state,\n chatMessages: appendProtocolMessage(state.chatMessages, action.message),\n error: null,\n errorInfo: null,\n retryInfo: null\n }\n case 'Submit':\n return {\n ...state,\n status: 'running',\n error: null,\n errorInfo: null,\n retryInfo: null,\n seenEventIds: [],\n chatMessages: appendProtocolMessage(state.chatMessages, action.message),\n sessionEvents: [\n ...state.sessionEvents,\n UserMessageSubmitted.make({ message: action.message })\n ]\n }\n case 'AppendMessage':\n return {\n ...state,\n chatMessages: appendProtocolMessage(state.chatMessages, action.message),\n error: null,\n errorInfo: null,\n retryInfo: null,\n sessionEvents: [\n ...state.sessionEvents,\n ProtocolMessageAppended.make({ message: action.message })\n ]\n }\n case 'SubmitHitlResponse':\n return {\n ...state,\n status: 'running',\n error: null,\n errorInfo: null,\n retryInfo: null,\n seenEventIds: [],\n chatMessages: applyAgentEventToChatMessages(\n state.chatMessages,\n hitlResponseEvent(action.response)\n )\n }\n case 'DeleteTurn': {\n const next = deleteChatTurn(state.chatMessages, action.messageId)\n\n if (next._tag === 'NotFound') {\n return state\n }\n\n return {\n ...state,\n error: null,\n errorInfo: null,\n retryInfo: null,\n chatMessages: next.messages,\n sessionEvents: [\n ...state.sessionEvents,\n TurnDeleted.make({\n turnStartMessageId: next.turnStartMessageId,\n deletedMessageIds: next.deletedMessageIds\n })\n ]\n }\n }\n case 'RegenerateFrom': {\n const next = regenerateChatMessagesFrom(state.chatMessages, action.messageId)\n\n if (next._tag === 'NotFound') {\n return state\n }\n\n return {\n ...state,\n status: 'running',\n error: null,\n errorInfo: null,\n retryInfo: null,\n seenEventIds: [],\n chatMessages: next.messages,\n sessionEvents: [\n ...state.sessionEvents,\n MessagesRegenerated.make({\n fromMessageId: action.messageId,\n keptMessageIds: next.messages.map(message => message.id)\n })\n ]\n }\n }\n case 'EditUserMessage': {\n const next = editChatUserMessage(state.chatMessages, action.messageId, action.content)\n\n if (next._tag !== 'Edited') {\n return state\n }\n\n return {\n ...state,\n status: 'running',\n error: null,\n errorInfo: null,\n retryInfo: null,\n seenEventIds: [],\n chatMessages: next.messages,\n sessionEvents: [\n ...state.sessionEvents,\n UserMessageEdited.make({\n messageId: next.messageId,\n content: action.content,\n keptMessageIds: next.messages.map(message => message.id)\n })\n ]\n }\n }\n case 'Event': {\n if (hasSeenEvent(state, action.event)) {\n return state\n }\n\n switch (action.event._tag) {\n case 'AgentStart':\n return rememberEvent(\n {\n ...state,\n status: 'running',\n error: null,\n errorInfo: null,\n retryInfo: null,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AgentError':\n return rememberEvent(\n {\n ...state,\n status: 'error',\n error: action.event.message,\n errorInfo: action.event,\n retryInfo: null,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AgentEnd':\n return rememberEvent(\n {\n ...state,\n status: 'done',\n error: null,\n errorInfo: null,\n retryInfo: null,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AgentAwaitingInput':\n return rememberEvent(\n {\n ...state,\n status: 'waiting',\n error: null,\n errorInfo: null,\n retryInfo: null,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'AgentRetry':\n return rememberEvent(\n {\n ...state,\n retryInfo: action.event,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n },\n action.event\n )\n case 'CompactionEnd':\n case 'AssistantMessage':\n case 'CompactionStart':\n case 'LLMReasoningDelta':\n case 'LLMStreamEnd':\n case 'LLMStreamStart':\n case 'LLMTextDelta':\n case 'ProviderToolResult':\n case 'QuestionAnswered':\n case 'QuestionCancelled':\n case 'QuestionRequested':\n case 'SubagentCompleted':\n case 'SubagentStarted':\n case 'ToolApprovalDenied':\n case 'ToolApprovalGranted':\n case 'ToolApprovalRequested':\n case 'ToolExecutionCompleted':\n case 'ToolExecutionError':\n case 'ToolExecutionStarted':\n case 'ToolInputDelta':\n case 'ToolInputEnd':\n case 'ToolInputStart':\n case 'TurnEnd':\n case 'TurnStart':\n case 'UsageUpdate':\n return rememberEvent(\n clearRetryInfo({\n ...state,\n chatMessages: applyAgentEventToChatMessages(state.chatMessages, action.event, action)\n }),\n action.event\n )\n }\n }\n case 'Error': {\n return {\n ...state,\n status: 'error',\n error: action.message,\n errorInfo: null,\n retryInfo: null,\n chatMessages: markChatError(state.chatMessages, action.message)\n }\n }\n case 'Abort':\n return { ...state, status: 'aborted', error: null, errorInfo: null, retryInfo: null }\n }\n}\n\nexport const hasAgentMessageReasoning = (message: AgentMessage) =>\n message._tag === 'Assistant' &&\n message.parts.some(part => part._tag === 'Reasoning' && part.text.length > 0)\n\nexport const hasAgentChatReasoningSummary = (state: AgentChatState) =>\n state.chatMessages.some(message =>\n message.parts.some(part => part._tag === 'Reasoning' && part.text.length > 0)\n )\n\nexport const isActiveChatToolPart = (part: AgentChatPart) =>\n part._tag === 'ToolCall' &&\n part.state._tag !== 'Completed' &&\n part.state._tag !== 'ProviderCompleted' &&\n part.state._tag !== 'QuestionAnswered' &&\n part.state._tag !== 'QuestionCancelled' &&\n part.state._tag !== 'Errored' &&\n part.state._tag !== 'Denied'\nexport type ActiveChatToolPart = Extract<AgentChatPart, { readonly _tag: 'ToolCall' }>\n\nexport const isCompletedChatToolPart = (part: AgentChatPart) =>\n part._tag === 'ToolCall' && part.state._tag === 'Completed'\nexport type CompletedChatToolPart = Extract<AgentChatPart, { readonly _tag: 'ToolCall' }>\n\nexport const getActiveChatToolParts = (messages: ReadonlyArray<AgentChatMessage>) =>\n messages.flatMap(message =>\n message.parts.filter((part): part is ActiveChatToolPart => isActiveChatToolPart(part))\n )\n\nexport const getCompletedChatToolParts = (messages: ReadonlyArray<AgentChatMessage>) =>\n messages.flatMap(message =>\n message.parts.filter((part): part is CompletedChatToolPart => isCompletedChatToolPart(part))\n )\n\ntype AgentChatLiveActivityInput = {\n readonly isTextRunning: boolean\n readonly activeToolCallCount: number\n readonly isVoiceActive: boolean\n}\n\nexport const getAgentChatLiveActivityCount = ({\n isTextRunning,\n activeToolCallCount,\n isVoiceActive\n}: AgentChatLiveActivityInput) =>\n (isTextRunning ? 1 : 0) + activeToolCallCount + (isVoiceActive ? 1 : 0)\n"],"mappings":";;;;AA0CA,MAAa,wBAAwC;CACnD,QAAQ;CACR,OAAO;CACP,WAAW;CACX,WAAW;CACX,cAAc,CAAC;CACf,eAAe,CAAC;CAChB,cAAc,CAAC;AACjB;AAEA,MAAM,gBAAgB,OAAuB,UAC3C,MAAM,YAAY,KAAA,KAAa,MAAM,aAAa,SAAS,MAAM,OAAO;AAE1E,MAAM,iBAAiB,OAAuB,UAC5C,MAAM,YAAY,KAAA,IACd,QACA;CAAE,GAAG;CAAO,cAAc,CAAC,GAAG,MAAM,cAAc,MAAM,OAAO;AAAE;AAEvE,MAAM,kBAAkB,UACtB,MAAM,cAAc,OAAO,QAAQ;CAAE,GAAG;CAAO,WAAW;AAAK;AAcjE,MAAa,wBACX,OACA,WACmB;CACnB,QAAQ,OAAO,MAAf;EACE,KAAK,kBACH,OAAO;GACL,GAAG;GACH,cAAc,sBAAsB,MAAM,cAAc,OAAO,OAAO;GACtE,OAAO;GACP,WAAW;GACX,WAAW;EACb;EACF,KAAK,UACH,OAAO;GACL,GAAG;GACH,QAAQ;GACR,OAAO;GACP,WAAW;GACX,WAAW;GACX,cAAc,CAAC;GACf,cAAc,sBAAsB,MAAM,cAAc,OAAO,OAAO;GACtE,eAAe,CACb,GAAG,MAAM,eACT,qBAAqB,KAAK,EAAE,SAAS,OAAO,QAAQ,CAAC,CACvD;EACF;EACF,KAAK,iBACH,OAAO;GACL,GAAG;GACH,cAAc,sBAAsB,MAAM,cAAc,OAAO,OAAO;GACtE,OAAO;GACP,WAAW;GACX,WAAW;GACX,eAAe,CACb,GAAG,MAAM,eACT,wBAAwB,KAAK,EAAE,SAAS,OAAO,QAAQ,CAAC,CAC1D;EACF;EACF,KAAK,sBACH,OAAO;GACL,GAAG;GACH,QAAQ;GACR,OAAO;GACP,WAAW;GACX,WAAW;GACX,cAAc,CAAC;GACf,cAAc,8BACZ,MAAM,cACN,kBAAkB,OAAO,QAAQ,CACnC;EACF;EACF,KAAK,cAAc;GACjB,MAAM,OAAO,eAAe,MAAM,cAAc,OAAO,SAAS;GAEhE,IAAI,KAAK,SAAS,YAChB,OAAO;GAGT,OAAO;IACL,GAAG;IACH,OAAO;IACP,WAAW;IACX,WAAW;IACX,cAAc,KAAK;IACnB,eAAe,CACb,GAAG,MAAM,eACT,YAAY,KAAK;KACf,oBAAoB,KAAK;KACzB,mBAAmB,KAAK;IAC1B,CAAC,CACH;GACF;EACF;EACA,KAAK,kBAAkB;GACrB,MAAM,OAAO,2BAA2B,MAAM,cAAc,OAAO,SAAS;GAE5E,IAAI,KAAK,SAAS,YAChB,OAAO;GAGT,OAAO;IACL,GAAG;IACH,QAAQ;IACR,OAAO;IACP,WAAW;IACX,WAAW;IACX,cAAc,CAAC;IACf,cAAc,KAAK;IACnB,eAAe,CACb,GAAG,MAAM,eACT,oBAAoB,KAAK;KACvB,eAAe,OAAO;KACtB,gBAAgB,KAAK,SAAS,KAAI,YAAW,QAAQ,EAAE;IACzD,CAAC,CACH;GACF;EACF;EACA,KAAK,mBAAmB;GACtB,MAAM,OAAO,oBAAoB,MAAM,cAAc,OAAO,WAAW,OAAO,OAAO;GAErF,IAAI,KAAK,SAAS,UAChB,OAAO;GAGT,OAAO;IACL,GAAG;IACH,QAAQ;IACR,OAAO;IACP,WAAW;IACX,WAAW;IACX,cAAc,CAAC;IACf,cAAc,KAAK;IACnB,eAAe,CACb,GAAG,MAAM,eACT,kBAAkB,KAAK;KACrB,WAAW,KAAK;KAChB,SAAS,OAAO;KAChB,gBAAgB,KAAK,SAAS,KAAI,YAAW,QAAQ,EAAE;IACzD,CAAC,CACH;GACF;EACF;EACA,KAAK;GACH,IAAI,aAAa,OAAO,OAAO,KAAK,GAClC,OAAO;GAGT,QAAQ,OAAO,MAAM,MAArB;IACE,KAAK,cACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO;KACP,WAAW;KACX,WAAW;KACX,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK,cACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO,OAAO,MAAM;KACpB,WAAW,OAAO;KAClB,WAAW;KACX,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK,YACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO;KACP,WAAW;KACX,WAAW;KACX,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK,sBACH,OAAO,cACL;KACE,GAAG;KACH,QAAQ;KACR,OAAO;KACP,WAAW;KACX,WAAW;KACX,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK,cACH,OAAO,cACL;KACE,GAAG;KACH,WAAW,OAAO;KAClB,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,GACA,OAAO,KACT;IACF,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK,eACH,OAAO,cACL,eAAe;KACb,GAAG;KACH,cAAc,8BAA8B,MAAM,cAAc,OAAO,OAAO,MAAM;IACtF,CAAC,GACD,OAAO,KACT;GACJ;EAEF,KAAK,SACH,OAAO;GACL,GAAG;GACH,QAAQ;GACR,OAAO,OAAO;GACd,WAAW;GACX,WAAW;GACX,cAAc,cAAc,MAAM,cAAc,OAAO,OAAO;EAChE;EAEF,KAAK,SACH,OAAO;GAAE,GAAG;GAAO,QAAQ;GAAW,OAAO;GAAM,WAAW;GAAM,WAAW;EAAK;CACxF;AACF;AAEA,MAAa,4BAA4B,YACvC,QAAQ,SAAS,eACjB,QAAQ,MAAM,MAAK,SAAQ,KAAK,SAAS,eAAe,KAAK,KAAK,SAAS,CAAC;AAE9E,MAAa,gCAAgC,UAC3C,MAAM,aAAa,MAAK,YACtB,QAAQ,MAAM,MAAK,SAAQ,KAAK,SAAS,eAAe,KAAK,KAAK,SAAS,CAAC,CAC9E;AAEF,MAAa,wBAAwB,SACnC,KAAK,SAAS,cACd,KAAK,MAAM,SAAS,eACpB,KAAK,MAAM,SAAS,uBACpB,KAAK,MAAM,SAAS,sBACpB,KAAK,MAAM,SAAS,uBACpB,KAAK,MAAM,SAAS,aACpB,KAAK,MAAM,SAAS;AAGtB,MAAa,2BAA2B,SACtC,KAAK,SAAS,cAAc,KAAK,MAAM,SAAS;AAGlD,MAAa,0BAA0B,aACrC,SAAS,SAAQ,YACf,QAAQ,MAAM,QAAQ,SAAqC,qBAAqB,IAAI,CAAC,CACvF;AAEF,MAAa,6BAA6B,aACxC,SAAS,SAAQ,YACf,QAAQ,MAAM,QAAQ,SAAwC,wBAAwB,IAAI,CAAC,CAC7F;AAQF,MAAa,iCAAiC,EAC5C,eACA,qBACA,qBAEC,gBAAgB,IAAI,KAAK,uBAAuB,gBAAgB,IAAI"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AgentChatMessage } from "./chat-messages.mjs";
|
|
2
|
-
import { Content, QuestionRequest, QuestionResponse, ToolApprovalRequest, ToolCall, ToolResult } from "@yolk-sdk/agent/protocol";
|
|
2
|
+
import { AgentRetry, Content, QuestionRequest, QuestionResponse, ToolApprovalRequest, ToolCall, ToolResult } from "@yolk-sdk/agent/protocol";
|
|
3
3
|
import { Option } from "effect";
|
|
4
4
|
|
|
5
5
|
//#region src/react/chat-items.d.ts
|
|
@@ -104,6 +104,10 @@ type AgentChatItem = {
|
|
|
104
104
|
readonly _tag: 'AssistantDraft';
|
|
105
105
|
readonly id: string;
|
|
106
106
|
readonly text: string;
|
|
107
|
+
} | {
|
|
108
|
+
readonly _tag: 'Retry';
|
|
109
|
+
readonly id: string;
|
|
110
|
+
readonly retry: AgentRetry;
|
|
107
111
|
} | {
|
|
108
112
|
readonly _tag: 'AssistantStatus';
|
|
109
113
|
readonly id: string;
|
|
@@ -117,12 +121,14 @@ type BuildAgentChatItemsInput = {
|
|
|
117
121
|
readonly messages: ReadonlyArray<AgentChatMessage>;
|
|
118
122
|
readonly isRunning: boolean;
|
|
119
123
|
readonly activeToolLabel: Option.Option<string>;
|
|
124
|
+
readonly retryInfo?: AgentRetry | null;
|
|
120
125
|
};
|
|
121
126
|
declare const dedupeAgentChatToolRunItems: (items: ReadonlyArray<AgentChatItem>) => ReadonlyArray<AgentChatItem>;
|
|
122
127
|
declare const buildAgentChatItems: ({
|
|
123
128
|
messages,
|
|
124
129
|
isRunning,
|
|
125
|
-
activeToolLabel
|
|
130
|
+
activeToolLabel,
|
|
131
|
+
retryInfo
|
|
126
132
|
}: BuildAgentChatItemsInput) => ReadonlyArray<AgentChatItem>;
|
|
127
133
|
//#endregion
|
|
128
134
|
export { AgentChatItem, BuildAgentChatItemsInput, ToolDuration, ToolRunState, ToolRunTiming, buildAgentChatItems, dedupeAgentChatToolRunItems };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-items.d.mts","names":[],"sources":["../../src/react/chat-items.ts"],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"chat-items.d.mts","names":[],"sources":["../../src/react/chat-items.ts"],"mappings":"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"}
|
|
@@ -153,16 +153,23 @@ const itemFromPart = (message, part) => {
|
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
155
|
};
|
|
156
|
-
const buildAgentChatItems = ({ messages, isRunning, activeToolLabel }) => {
|
|
156
|
+
const buildAgentChatItems = ({ messages, isRunning, activeToolLabel, retryInfo }) => {
|
|
157
157
|
const items = dedupeAgentChatToolRunItems(Array.getSomes(Array.flatMap(messages, (message) => Array.map(message.parts, (part) => itemFromPart(message, part)))));
|
|
158
|
-
if (isRunning)
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
158
|
+
if (isRunning) {
|
|
159
|
+
if (retryInfo !== void 0 && retryInfo !== null) return [...items, {
|
|
160
|
+
_tag: "Retry",
|
|
161
|
+
id: "agent-retry",
|
|
162
|
+
retry: retryInfo
|
|
163
|
+
}];
|
|
164
|
+
return [...items, {
|
|
165
|
+
_tag: "AssistantStatus",
|
|
166
|
+
id: "assistant-status",
|
|
167
|
+
label: activeStatusLabel({
|
|
168
|
+
messages,
|
|
169
|
+
activeToolLabel
|
|
170
|
+
})
|
|
171
|
+
}];
|
|
172
|
+
}
|
|
166
173
|
return items;
|
|
167
174
|
};
|
|
168
175
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-items.mjs","names":["Arr"],"sources":["../../src/react/chat-items.ts"],"sourcesContent":["import { Array as Arr, Option } from 'effect'\nimport {\n contentText,\n type QuestionRequest,\n type QuestionResponse,\n type ToolApprovalRequest,\n type ToolResult,\n type Content,\n type ToolCall\n} from '@yolk-sdk/agent/protocol'\nimport type { AgentChatMessage, ChatToolState } from './chat-messages.ts'\n\nexport type ToolDuration =\n | { readonly _tag: 'Known'; readonly milliseconds: number }\n | { readonly _tag: 'Unknown' }\n\ntype ToolRunNoTiming = {\n readonly duration: { readonly _tag: 'Unknown' }\n readonly startedAtMs?: undefined\n readonly endedAtMs?: undefined\n}\n\ntype ToolRunStartedTiming = {\n readonly duration: { readonly _tag: 'Unknown' }\n readonly startedAtMs: number\n readonly endedAtMs?: undefined\n}\n\ntype ToolRunKnownTiming = {\n readonly duration: { readonly _tag: 'Known'; readonly milliseconds: number }\n readonly startedAtMs: number\n readonly endedAtMs: number\n}\n\nexport type ToolRunTiming = ToolRunNoTiming | ToolRunStartedTiming | ToolRunKnownTiming\n\ntype ToolRunTerminalTiming = ToolRunTiming\n\nexport type ToolRunState =\n | ({ readonly _tag: 'Running' } & ToolRunStartedTiming)\n | ({ readonly _tag: 'Called' } & ToolRunNoTiming)\n | ({ readonly _tag: 'InputStreaming'; readonly input: string } & ToolRunNoTiming)\n | ({\n readonly _tag: 'ApprovalRequested'\n readonly request?: ToolApprovalRequest\n } & ToolRunNoTiming)\n | ({ readonly _tag: 'Denied'; readonly reason: string } & ToolRunNoTiming)\n | ({ readonly _tag: 'QuestionRequested'; readonly request: QuestionRequest } & ToolRunNoTiming)\n | ({\n readonly _tag: 'QuestionAnswered'\n readonly response: QuestionResponse\n readonly request?: QuestionRequest\n } & ToolRunNoTiming)\n | ({\n readonly _tag: 'QuestionCancelled'\n readonly response: QuestionResponse\n readonly request?: QuestionRequest\n } & ToolRunNoTiming)\n | ({ readonly _tag: 'Completed'; readonly result: ToolResult } & ToolRunTerminalTiming)\n | ({ readonly _tag: 'Errored'; readonly message: string } & ToolRunTerminalTiming)\n | ({\n readonly _tag: 'ProviderCompleted'\n readonly result: ToolResult\n } & ToolRunNoTiming)\n\nexport type AgentChatItem =\n | {\n readonly _tag: 'UserMessage'\n readonly id: string\n readonly messageId: string\n readonly content: Content\n }\n | {\n readonly _tag: 'AssistantMessage'\n readonly id: string\n readonly messageId: string\n readonly content: Content\n }\n | {\n readonly _tag: 'Reasoning'\n readonly id: string\n readonly messageId: string\n readonly text: string\n }\n | {\n readonly _tag: 'ToolRun'\n readonly id: string\n readonly messageId: string\n readonly call: ToolCall\n readonly state: ToolRunState\n }\n | {\n readonly _tag: 'ToolResult'\n readonly id: string\n readonly messageId: string\n readonly toolCallId: string\n readonly name: string\n readonly content: Content\n readonly isError?: boolean\n }\n | { readonly _tag: 'UserDraft'; readonly id: string; readonly text: string }\n | { readonly _tag: 'AssistantDraft'; readonly id: string; readonly text: string }\n | { readonly _tag: 'AssistantStatus'; readonly id: string; readonly label: string }\n | { readonly _tag: 'Error'; readonly id: string; readonly message: string }\n\nexport type BuildAgentChatItemsInput = {\n readonly messages: ReadonlyArray<AgentChatMessage>\n readonly isRunning: boolean\n readonly activeToolLabel: Option.Option<string>\n}\n\nexport const dedupeAgentChatToolRunItems = (\n items: ReadonlyArray<AgentChatItem>\n): ReadonlyArray<AgentChatItem> => {\n // Tool call ids are transcript-global; latest wins when live and persisted projections overlap.\n const latestIndexByToolCallId = new Map<string, number>()\n\n for (const [index, item] of items.entries()) {\n if (item._tag === 'ToolRun') {\n latestIndexByToolCallId.set(item.call.id, index)\n }\n }\n\n return items.filter(\n (item, index) =>\n item._tag !== 'ToolRun' || latestIndexByToolCallId.get(item.call.id) === index\n )\n}\n\nconst activeStatusLabel = ({\n messages,\n activeToolLabel\n}: Pick<BuildAgentChatItemsInput, 'messages' | 'activeToolLabel'>) => {\n if (Option.isSome(activeToolLabel)) {\n return activeToolLabel.value\n }\n\n const parts = messages.flatMap(message =>\n message.parts.map(part => ({ messageRole: message.role, part }))\n )\n\n if (\n parts.some(\n ({ messageRole, part }) =>\n part._tag === 'Text' && part.state === 'streaming' && messageRole === 'assistant'\n )\n ) {\n return 'Responding'\n }\n\n if (parts.some(({ part }) => part._tag === 'Reasoning' && part.state === 'streaming')) {\n return 'Thinking'\n }\n\n return 'Thinking'\n}\n\nconst noTiming = (): ToolRunNoTiming => ({ duration: { _tag: 'Unknown' } })\n\nconst startedTiming = (startedAtMs: number): ToolRunStartedTiming => ({\n duration: { _tag: 'Unknown' },\n startedAtMs\n})\n\nconst unknownTerminalTiming = (startedAtMs?: number): ToolRunNoTiming | ToolRunStartedTiming =>\n startedAtMs === undefined ? noTiming() : startedTiming(startedAtMs)\n\nconst knownTiming = (startedAtMs: number, endedAtMs: number): ToolRunTiming => ({\n duration: { _tag: 'Known', milliseconds: Math.max(0, endedAtMs - startedAtMs) },\n startedAtMs,\n endedAtMs\n})\n\nconst terminalTimingFromState = (\n state: Extract<ChatToolState, { readonly _tag: 'Completed' | 'Errored' }>\n): ToolRunTerminalTiming => {\n if (state.startedAtMs !== undefined && state.endedAtMs !== undefined) {\n return knownTiming(state.startedAtMs, state.endedAtMs)\n }\n\n return unknownTerminalTiming(state.startedAtMs)\n}\n\nconst toolRunStateFor = (state: ChatToolState): ToolRunState => {\n if (state._tag === 'Running') {\n return { _tag: 'Running', ...startedTiming(state.startedAtMs) }\n }\n\n if (state._tag === 'Completed') {\n return { _tag: 'Completed', ...terminalTimingFromState(state), result: state.result }\n }\n\n if (state._tag === 'InputStreaming') {\n return { _tag: 'InputStreaming', ...noTiming(), input: state.input }\n }\n\n if (state._tag === 'ApprovalRequested') {\n return { _tag: 'ApprovalRequested', ...noTiming(), request: state.request }\n }\n\n if (state._tag === 'Denied') {\n return { _tag: 'Denied', ...noTiming(), reason: state.reason }\n }\n\n if (state._tag === 'QuestionRequested') {\n return { _tag: 'QuestionRequested', ...noTiming(), request: state.request }\n }\n\n if (state._tag === 'QuestionAnswered') {\n return {\n _tag: 'QuestionAnswered',\n ...noTiming(),\n response: state.response,\n request: state.request\n }\n }\n\n if (state._tag === 'QuestionCancelled') {\n return {\n _tag: 'QuestionCancelled',\n ...noTiming(),\n response: state.response,\n request: state.request\n }\n }\n\n if (state._tag === 'Errored') {\n return { _tag: 'Errored', ...terminalTimingFromState(state), message: state.message }\n }\n\n if (state._tag === 'ProviderCompleted') {\n return { _tag: 'ProviderCompleted', ...noTiming(), result: state.result }\n }\n\n return { _tag: 'Called', ...noTiming() }\n}\n\nconst textItemFromPart = (\n message: AgentChatMessage,\n part: Extract<AgentChatMessage['parts'][number], { readonly _tag: 'Text' }>\n): Option.Option<AgentChatItem> => {\n if (part.state === 'streaming') {\n switch (message.role) {\n case 'user':\n return Option.some({\n _tag: 'UserDraft',\n id: part.id,\n text: contentText(part.content)\n })\n case 'assistant':\n return Option.some({\n _tag: 'AssistantDraft',\n id: part.id,\n text: contentText(part.content)\n })\n case 'system':\n return Option.none()\n }\n }\n\n switch (message.role) {\n case 'user':\n return Option.some({\n _tag: 'UserMessage',\n id: part.id,\n messageId: message.id,\n content: part.content\n })\n case 'assistant':\n return Option.some({\n _tag: 'AssistantMessage',\n id: part.id,\n messageId: message.id,\n content: part.content\n })\n case 'system':\n return Option.none()\n }\n}\n\nconst itemFromPart = (\n message: AgentChatMessage,\n part: AgentChatMessage['parts'][number]\n): Option.Option<AgentChatItem> => {\n switch (part._tag) {\n case 'Text':\n return textItemFromPart(message, part)\n case 'Reasoning':\n return Option.some({ _tag: 'Reasoning', id: part.id, messageId: message.id, text: part.text })\n case 'ToolCall':\n return Option.some({\n _tag: 'ToolRun',\n id: part.id,\n messageId: message.id,\n call: part.call,\n state: toolRunStateFor(part.state)\n })\n case 'ToolResult':\n return Option.some({\n _tag: 'ToolResult',\n id: part.id,\n messageId: message.id,\n toolCallId: part.toolCallId,\n name: part.name,\n content: part.content,\n isError: part.isError\n })\n case 'Error':\n return Option.some({ _tag: 'Error', id: part.id, message: part.message })\n }\n}\n\nexport const buildAgentChatItems = ({\n messages,\n isRunning,\n activeToolLabel\n}: BuildAgentChatItemsInput): ReadonlyArray<AgentChatItem> => {\n const items = dedupeAgentChatToolRunItems(\n Arr.getSomes(\n Arr.flatMap(messages, message => Arr.map(message.parts, part => itemFromPart(message, part)))\n )\n )\n\n if (isRunning) {\n return [\n ...items,\n {\n _tag: 'AssistantStatus',\n id: 'assistant-status',\n label: activeStatusLabel({ messages, activeToolLabel })\n }\n ]\n }\n\n return items\n}\n"],"mappings":";;;AA+GA,MAAa,+BACX,UACiC;CAEjC,MAAM,0CAA0B,IAAI,IAAoB;CAExD,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,QAAQ,GACxC,IAAI,KAAK,SAAS,WAChB,wBAAwB,IAAI,KAAK,KAAK,IAAI,KAAK;CAInD,OAAO,MAAM,QACV,MAAM,UACL,KAAK,SAAS,aAAa,wBAAwB,IAAI,KAAK,KAAK,EAAE,MAAM,KAC7E;AACF;AAEA,MAAM,qBAAqB,EACzB,UACA,sBACoE;CACpE,IAAI,OAAO,OAAO,eAAe,GAC/B,OAAO,gBAAgB;CAGzB,MAAM,QAAQ,SAAS,SAAQ,YAC7B,QAAQ,MAAM,KAAI,UAAS;EAAE,aAAa,QAAQ;EAAM;CAAK,EAAE,CACjE;CAEA,IACE,MAAM,MACH,EAAE,aAAa,WACd,KAAK,SAAS,UAAU,KAAK,UAAU,eAAe,gBAAgB,WAC1E,GAEA,OAAO;CAGT,IAAI,MAAM,MAAM,EAAE,WAAW,KAAK,SAAS,eAAe,KAAK,UAAU,WAAW,GAClF,OAAO;CAGT,OAAO;AACT;AAEA,MAAM,kBAAmC,EAAE,UAAU,EAAE,MAAM,UAAU,EAAE;AAEzE,MAAM,iBAAiB,iBAA+C;CACpE,UAAU,EAAE,MAAM,UAAU;CAC5B;AACF;AAEA,MAAM,yBAAyB,gBAC7B,gBAAgB,KAAA,IAAY,SAAS,IAAI,cAAc,WAAW;AAEpE,MAAM,eAAe,aAAqB,eAAsC;CAC9E,UAAU;EAAE,MAAM;EAAS,cAAc,KAAK,IAAI,GAAG,YAAY,WAAW;CAAE;CAC9E;CACA;AACF;AAEA,MAAM,2BACJ,UAC0B;CAC1B,IAAI,MAAM,gBAAgB,KAAA,KAAa,MAAM,cAAc,KAAA,GACzD,OAAO,YAAY,MAAM,aAAa,MAAM,SAAS;CAGvD,OAAO,sBAAsB,MAAM,WAAW;AAChD;AAEA,MAAM,mBAAmB,UAAuC;CAC9D,IAAI,MAAM,SAAS,WACjB,OAAO;EAAE,MAAM;EAAW,GAAG,cAAc,MAAM,WAAW;CAAE;CAGhE,IAAI,MAAM,SAAS,aACjB,OAAO;EAAE,MAAM;EAAa,GAAG,wBAAwB,KAAK;EAAG,QAAQ,MAAM;CAAO;CAGtF,IAAI,MAAM,SAAS,kBACjB,OAAO;EAAE,MAAM;EAAkB,GAAG,SAAS;EAAG,OAAO,MAAM;CAAM;CAGrE,IAAI,MAAM,SAAS,qBACjB,OAAO;EAAE,MAAM;EAAqB,GAAG,SAAS;EAAG,SAAS,MAAM;CAAQ;CAG5E,IAAI,MAAM,SAAS,UACjB,OAAO;EAAE,MAAM;EAAU,GAAG,SAAS;EAAG,QAAQ,MAAM;CAAO;CAG/D,IAAI,MAAM,SAAS,qBACjB,OAAO;EAAE,MAAM;EAAqB,GAAG,SAAS;EAAG,SAAS,MAAM;CAAQ;CAG5E,IAAI,MAAM,SAAS,oBACjB,OAAO;EACL,MAAM;EACN,GAAG,SAAS;EACZ,UAAU,MAAM;EAChB,SAAS,MAAM;CACjB;CAGF,IAAI,MAAM,SAAS,qBACjB,OAAO;EACL,MAAM;EACN,GAAG,SAAS;EACZ,UAAU,MAAM;EAChB,SAAS,MAAM;CACjB;CAGF,IAAI,MAAM,SAAS,WACjB,OAAO;EAAE,MAAM;EAAW,GAAG,wBAAwB,KAAK;EAAG,SAAS,MAAM;CAAQ;CAGtF,IAAI,MAAM,SAAS,qBACjB,OAAO;EAAE,MAAM;EAAqB,GAAG,SAAS;EAAG,QAAQ,MAAM;CAAO;CAG1E,OAAO;EAAE,MAAM;EAAU,GAAG,SAAS;CAAE;AACzC;AAEA,MAAM,oBACJ,SACA,SACiC;CACjC,IAAI,KAAK,UAAU,aACjB,QAAQ,QAAQ,MAAhB;EACE,KAAK,QACH,OAAO,OAAO,KAAK;GACjB,MAAM;GACN,IAAI,KAAK;GACT,MAAM,YAAY,KAAK,OAAO;EAChC,CAAC;EACH,KAAK,aACH,OAAO,OAAO,KAAK;GACjB,MAAM;GACN,IAAI,KAAK;GACT,MAAM,YAAY,KAAK,OAAO;EAChC,CAAC;EACH,KAAK,UACH,OAAO,OAAO,KAAK;CACvB;CAGF,QAAQ,QAAQ,MAAhB;EACE,KAAK,QACH,OAAO,OAAO,KAAK;GACjB,MAAM;GACN,IAAI,KAAK;GACT,WAAW,QAAQ;GACnB,SAAS,KAAK;EAChB,CAAC;EACH,KAAK,aACH,OAAO,OAAO,KAAK;GACjB,MAAM;GACN,IAAI,KAAK;GACT,WAAW,QAAQ;GACnB,SAAS,KAAK;EAChB,CAAC;EACH,KAAK,UACH,OAAO,OAAO,KAAK;CACvB;AACF;AAEA,MAAM,gBACJ,SACA,SACiC;CACjC,QAAQ,KAAK,MAAb;EACE,KAAK,QACH,OAAO,iBAAiB,SAAS,IAAI;EACvC,KAAK,aACH,OAAO,OAAO,KAAK;GAAE,MAAM;GAAa,IAAI,KAAK;GAAI,WAAW,QAAQ;GAAI,MAAM,KAAK;EAAK,CAAC;EAC/F,KAAK,YACH,OAAO,OAAO,KAAK;GACjB,MAAM;GACN,IAAI,KAAK;GACT,WAAW,QAAQ;GACnB,MAAM,KAAK;GACX,OAAO,gBAAgB,KAAK,KAAK;EACnC,CAAC;EACH,KAAK,cACH,OAAO,OAAO,KAAK;GACjB,MAAM;GACN,IAAI,KAAK;GACT,WAAW,QAAQ;GACnB,YAAY,KAAK;GACjB,MAAM,KAAK;GACX,SAAS,KAAK;GACd,SAAS,KAAK;EAChB,CAAC;EACH,KAAK,SACH,OAAO,OAAO,KAAK;GAAE,MAAM;GAAS,IAAI,KAAK;GAAI,SAAS,KAAK;EAAQ,CAAC;CAC5E;AACF;AAEA,MAAa,uBAAuB,EAClC,UACA,WACA,sBAC4D;CAC5D,MAAM,QAAQ,4BACZA,MAAI,SACFA,MAAI,QAAQ,WAAU,YAAWA,MAAI,IAAI,QAAQ,QAAO,SAAQ,aAAa,SAAS,IAAI,CAAC,CAAC,CAC9F,CACF;CAEA,IAAI,WACF,OAAO,CACL,GAAG,OACH;EACE,MAAM;EACN,IAAI;EACJ,OAAO,kBAAkB;GAAE;GAAU;EAAgB,CAAC;CACxD,CACF;CAGF,OAAO;AACT"}
|
|
1
|
+
{"version":3,"file":"chat-items.mjs","names":["Arr"],"sources":["../../src/react/chat-items.ts"],"sourcesContent":["import { Array as Arr, Option } from 'effect'\nimport {\n contentText,\n type AgentRetry,\n type QuestionRequest,\n type QuestionResponse,\n type ToolApprovalRequest,\n type ToolResult,\n type Content,\n type ToolCall\n} from '@yolk-sdk/agent/protocol'\nimport type { AgentChatMessage, ChatToolState } from './chat-messages.ts'\n\nexport type ToolDuration =\n | { readonly _tag: 'Known'; readonly milliseconds: number }\n | { readonly _tag: 'Unknown' }\n\ntype ToolRunNoTiming = {\n readonly duration: { readonly _tag: 'Unknown' }\n readonly startedAtMs?: undefined\n readonly endedAtMs?: undefined\n}\n\ntype ToolRunStartedTiming = {\n readonly duration: { readonly _tag: 'Unknown' }\n readonly startedAtMs: number\n readonly endedAtMs?: undefined\n}\n\ntype ToolRunKnownTiming = {\n readonly duration: { readonly _tag: 'Known'; readonly milliseconds: number }\n readonly startedAtMs: number\n readonly endedAtMs: number\n}\n\nexport type ToolRunTiming = ToolRunNoTiming | ToolRunStartedTiming | ToolRunKnownTiming\n\ntype ToolRunTerminalTiming = ToolRunTiming\n\nexport type ToolRunState =\n | ({ readonly _tag: 'Running' } & ToolRunStartedTiming)\n | ({ readonly _tag: 'Called' } & ToolRunNoTiming)\n | ({ readonly _tag: 'InputStreaming'; readonly input: string } & ToolRunNoTiming)\n | ({\n readonly _tag: 'ApprovalRequested'\n readonly request?: ToolApprovalRequest\n } & ToolRunNoTiming)\n | ({ readonly _tag: 'Denied'; readonly reason: string } & ToolRunNoTiming)\n | ({ readonly _tag: 'QuestionRequested'; readonly request: QuestionRequest } & ToolRunNoTiming)\n | ({\n readonly _tag: 'QuestionAnswered'\n readonly response: QuestionResponse\n readonly request?: QuestionRequest\n } & ToolRunNoTiming)\n | ({\n readonly _tag: 'QuestionCancelled'\n readonly response: QuestionResponse\n readonly request?: QuestionRequest\n } & ToolRunNoTiming)\n | ({ readonly _tag: 'Completed'; readonly result: ToolResult } & ToolRunTerminalTiming)\n | ({ readonly _tag: 'Errored'; readonly message: string } & ToolRunTerminalTiming)\n | ({\n readonly _tag: 'ProviderCompleted'\n readonly result: ToolResult\n } & ToolRunNoTiming)\n\nexport type AgentChatItem =\n | {\n readonly _tag: 'UserMessage'\n readonly id: string\n readonly messageId: string\n readonly content: Content\n }\n | {\n readonly _tag: 'AssistantMessage'\n readonly id: string\n readonly messageId: string\n readonly content: Content\n }\n | {\n readonly _tag: 'Reasoning'\n readonly id: string\n readonly messageId: string\n readonly text: string\n }\n | {\n readonly _tag: 'ToolRun'\n readonly id: string\n readonly messageId: string\n readonly call: ToolCall\n readonly state: ToolRunState\n }\n | {\n readonly _tag: 'ToolResult'\n readonly id: string\n readonly messageId: string\n readonly toolCallId: string\n readonly name: string\n readonly content: Content\n readonly isError?: boolean\n }\n | { readonly _tag: 'UserDraft'; readonly id: string; readonly text: string }\n | { readonly _tag: 'AssistantDraft'; readonly id: string; readonly text: string }\n | { readonly _tag: 'Retry'; readonly id: string; readonly retry: AgentRetry }\n | { readonly _tag: 'AssistantStatus'; readonly id: string; readonly label: string }\n | { readonly _tag: 'Error'; readonly id: string; readonly message: string }\n\nexport type BuildAgentChatItemsInput = {\n readonly messages: ReadonlyArray<AgentChatMessage>\n readonly isRunning: boolean\n readonly activeToolLabel: Option.Option<string>\n readonly retryInfo?: AgentRetry | null\n}\n\nexport const dedupeAgentChatToolRunItems = (\n items: ReadonlyArray<AgentChatItem>\n): ReadonlyArray<AgentChatItem> => {\n // Tool call ids are transcript-global; latest wins when live and persisted projections overlap.\n const latestIndexByToolCallId = new Map<string, number>()\n\n for (const [index, item] of items.entries()) {\n if (item._tag === 'ToolRun') {\n latestIndexByToolCallId.set(item.call.id, index)\n }\n }\n\n return items.filter(\n (item, index) => item._tag !== 'ToolRun' || latestIndexByToolCallId.get(item.call.id) === index\n )\n}\n\nconst activeStatusLabel = ({\n messages,\n activeToolLabel\n}: Pick<BuildAgentChatItemsInput, 'messages' | 'activeToolLabel'>) => {\n if (Option.isSome(activeToolLabel)) {\n return activeToolLabel.value\n }\n\n const parts = messages.flatMap(message =>\n message.parts.map(part => ({ messageRole: message.role, part }))\n )\n\n if (\n parts.some(\n ({ messageRole, part }) =>\n part._tag === 'Text' && part.state === 'streaming' && messageRole === 'assistant'\n )\n ) {\n return 'Responding'\n }\n\n if (parts.some(({ part }) => part._tag === 'Reasoning' && part.state === 'streaming')) {\n return 'Thinking'\n }\n\n return 'Thinking'\n}\n\nconst noTiming = (): ToolRunNoTiming => ({ duration: { _tag: 'Unknown' } })\n\nconst startedTiming = (startedAtMs: number): ToolRunStartedTiming => ({\n duration: { _tag: 'Unknown' },\n startedAtMs\n})\n\nconst unknownTerminalTiming = (startedAtMs?: number): ToolRunNoTiming | ToolRunStartedTiming =>\n startedAtMs === undefined ? noTiming() : startedTiming(startedAtMs)\n\nconst knownTiming = (startedAtMs: number, endedAtMs: number): ToolRunTiming => ({\n duration: { _tag: 'Known', milliseconds: Math.max(0, endedAtMs - startedAtMs) },\n startedAtMs,\n endedAtMs\n})\n\nconst terminalTimingFromState = (\n state: Extract<ChatToolState, { readonly _tag: 'Completed' | 'Errored' }>\n): ToolRunTerminalTiming => {\n if (state.startedAtMs !== undefined && state.endedAtMs !== undefined) {\n return knownTiming(state.startedAtMs, state.endedAtMs)\n }\n\n return unknownTerminalTiming(state.startedAtMs)\n}\n\nconst toolRunStateFor = (state: ChatToolState): ToolRunState => {\n if (state._tag === 'Running') {\n return { _tag: 'Running', ...startedTiming(state.startedAtMs) }\n }\n\n if (state._tag === 'Completed') {\n return { _tag: 'Completed', ...terminalTimingFromState(state), result: state.result }\n }\n\n if (state._tag === 'InputStreaming') {\n return { _tag: 'InputStreaming', ...noTiming(), input: state.input }\n }\n\n if (state._tag === 'ApprovalRequested') {\n return { _tag: 'ApprovalRequested', ...noTiming(), request: state.request }\n }\n\n if (state._tag === 'Denied') {\n return { _tag: 'Denied', ...noTiming(), reason: state.reason }\n }\n\n if (state._tag === 'QuestionRequested') {\n return { _tag: 'QuestionRequested', ...noTiming(), request: state.request }\n }\n\n if (state._tag === 'QuestionAnswered') {\n return {\n _tag: 'QuestionAnswered',\n ...noTiming(),\n response: state.response,\n request: state.request\n }\n }\n\n if (state._tag === 'QuestionCancelled') {\n return {\n _tag: 'QuestionCancelled',\n ...noTiming(),\n response: state.response,\n request: state.request\n }\n }\n\n if (state._tag === 'Errored') {\n return { _tag: 'Errored', ...terminalTimingFromState(state), message: state.message }\n }\n\n if (state._tag === 'ProviderCompleted') {\n return { _tag: 'ProviderCompleted', ...noTiming(), result: state.result }\n }\n\n return { _tag: 'Called', ...noTiming() }\n}\n\nconst textItemFromPart = (\n message: AgentChatMessage,\n part: Extract<AgentChatMessage['parts'][number], { readonly _tag: 'Text' }>\n): Option.Option<AgentChatItem> => {\n if (part.state === 'streaming') {\n switch (message.role) {\n case 'user':\n return Option.some({\n _tag: 'UserDraft',\n id: part.id,\n text: contentText(part.content)\n })\n case 'assistant':\n return Option.some({\n _tag: 'AssistantDraft',\n id: part.id,\n text: contentText(part.content)\n })\n case 'system':\n return Option.none()\n }\n }\n\n switch (message.role) {\n case 'user':\n return Option.some({\n _tag: 'UserMessage',\n id: part.id,\n messageId: message.id,\n content: part.content\n })\n case 'assistant':\n return Option.some({\n _tag: 'AssistantMessage',\n id: part.id,\n messageId: message.id,\n content: part.content\n })\n case 'system':\n return Option.none()\n }\n}\n\nconst itemFromPart = (\n message: AgentChatMessage,\n part: AgentChatMessage['parts'][number]\n): Option.Option<AgentChatItem> => {\n switch (part._tag) {\n case 'Text':\n return textItemFromPart(message, part)\n case 'Reasoning':\n return Option.some({ _tag: 'Reasoning', id: part.id, messageId: message.id, text: part.text })\n case 'ToolCall':\n return Option.some({\n _tag: 'ToolRun',\n id: part.id,\n messageId: message.id,\n call: part.call,\n state: toolRunStateFor(part.state)\n })\n case 'ToolResult':\n return Option.some({\n _tag: 'ToolResult',\n id: part.id,\n messageId: message.id,\n toolCallId: part.toolCallId,\n name: part.name,\n content: part.content,\n isError: part.isError\n })\n case 'Error':\n return Option.some({ _tag: 'Error', id: part.id, message: part.message })\n }\n}\n\nexport const buildAgentChatItems = ({\n messages,\n isRunning,\n activeToolLabel,\n retryInfo\n}: BuildAgentChatItemsInput): ReadonlyArray<AgentChatItem> => {\n const items = dedupeAgentChatToolRunItems(\n Arr.getSomes(\n Arr.flatMap(messages, message => Arr.map(message.parts, part => itemFromPart(message, part)))\n )\n )\n\n if (isRunning) {\n if (retryInfo !== undefined && retryInfo !== null) {\n return [...items, { _tag: 'Retry', id: 'agent-retry', retry: retryInfo }]\n }\n\n return [\n ...items,\n {\n _tag: 'AssistantStatus',\n id: 'assistant-status',\n label: activeStatusLabel({ messages, activeToolLabel })\n }\n ]\n }\n\n return items\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yolk-sdk/agent",
|
|
3
|
-
"version": "0.1.0-canary.
|
|
3
|
+
"version": "0.1.0-canary.21",
|
|
4
4
|
"description": "Protocol, loop, runtime, client, compaction, tools, React, providers, OAuth, skillset, and voice primitives for building Yolk agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/client/state.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type AgentError,
|
|
2
3
|
type AgentEvent,
|
|
3
4
|
type AgentMessage,
|
|
5
|
+
type AgentRetry,
|
|
4
6
|
type HitlRequest,
|
|
5
7
|
type QuestionRequest,
|
|
6
8
|
type QuestionResponse,
|
|
@@ -63,6 +65,8 @@ export type AgentClientState = {
|
|
|
63
65
|
readonly reasoning: string
|
|
64
66
|
readonly toolRuns: ReadonlyArray<AgentToolRun>
|
|
65
67
|
readonly error: string | null
|
|
68
|
+
readonly errorInfo: AgentError | null
|
|
69
|
+
readonly retryInfo: AgentRetry | null
|
|
66
70
|
readonly seenEventIds: ReadonlyArray<string>
|
|
67
71
|
}
|
|
68
72
|
|
|
@@ -80,9 +84,14 @@ export const initialAgentClientState: AgentClientState = {
|
|
|
80
84
|
reasoning: '',
|
|
81
85
|
toolRuns: [],
|
|
82
86
|
error: null,
|
|
87
|
+
errorInfo: null,
|
|
88
|
+
retryInfo: null,
|
|
83
89
|
seenEventIds: []
|
|
84
90
|
}
|
|
85
91
|
|
|
92
|
+
const clearRetryInfo = (state: AgentClientState): AgentClientState =>
|
|
93
|
+
state.retryInfo === null ? state : { ...state, retryInfo: null }
|
|
94
|
+
|
|
86
95
|
const hasSeenEvent = (state: AgentClientState, event: AgentEvent) =>
|
|
87
96
|
event.eventId !== undefined && state.seenEventIds.includes(event.eventId)
|
|
88
97
|
|
|
@@ -260,16 +269,18 @@ const applyAgentEventUnchecked = (
|
|
|
260
269
|
reasoning: '',
|
|
261
270
|
liveMessages: [],
|
|
262
271
|
toolRuns: completedToolRuns(state.toolRuns),
|
|
263
|
-
error: null
|
|
272
|
+
error: null,
|
|
273
|
+
errorInfo: null,
|
|
274
|
+
retryInfo: null
|
|
264
275
|
}
|
|
265
276
|
case 'AgentError':
|
|
266
|
-
return markAgentError(state, event.message)
|
|
277
|
+
return markAgentError(state, event.message, event)
|
|
267
278
|
case 'LLMTextDelta':
|
|
268
|
-
return { ...state, text: `${state.text}${event.text}` }
|
|
279
|
+
return clearRetryInfo({ ...state, text: `${state.text}${event.text}` })
|
|
269
280
|
case 'LLMReasoningDelta':
|
|
270
|
-
return { ...state, reasoning: `${state.reasoning}${event.text}` }
|
|
281
|
+
return clearRetryInfo({ ...state, reasoning: `${state.reasoning}${event.text}` })
|
|
271
282
|
case 'ToolInputStart':
|
|
272
|
-
return {
|
|
283
|
+
return clearRetryInfo({
|
|
273
284
|
...state,
|
|
274
285
|
toolRuns: replaceToolRun(state.toolRuns, {
|
|
275
286
|
_tag: 'InputStreaming',
|
|
@@ -277,14 +288,17 @@ const applyAgentEventUnchecked = (
|
|
|
277
288
|
name: event.name,
|
|
278
289
|
input: ''
|
|
279
290
|
})
|
|
280
|
-
}
|
|
291
|
+
})
|
|
281
292
|
case 'ToolInputDelta':
|
|
282
|
-
return {
|
|
293
|
+
return clearRetryInfo({
|
|
294
|
+
...state,
|
|
295
|
+
toolRuns: appendToolInputDelta(state.toolRuns, event.id, event.delta)
|
|
296
|
+
})
|
|
283
297
|
case 'ToolInputEnd':
|
|
284
|
-
return {
|
|
298
|
+
return clearRetryInfo({
|
|
285
299
|
...state,
|
|
286
300
|
toolRuns: replaceToolRun(state.toolRuns, { _tag: 'InputReady', call: event.call })
|
|
287
|
-
}
|
|
301
|
+
})
|
|
288
302
|
case 'ToolApprovalRequested':
|
|
289
303
|
return {
|
|
290
304
|
...state,
|
|
@@ -370,21 +384,21 @@ const applyAgentEventUnchecked = (
|
|
|
370
384
|
})
|
|
371
385
|
}
|
|
372
386
|
case 'ProviderToolResult':
|
|
373
|
-
return {
|
|
387
|
+
return clearRetryInfo({
|
|
374
388
|
...state,
|
|
375
389
|
toolRuns: replaceToolRun(state.toolRuns, {
|
|
376
390
|
_tag: 'ProviderCompleted',
|
|
377
391
|
call: event.call,
|
|
378
392
|
result: event.result
|
|
379
393
|
})
|
|
380
|
-
}
|
|
394
|
+
})
|
|
381
395
|
case 'AssistantMessage':
|
|
382
|
-
return {
|
|
396
|
+
return clearRetryInfo({
|
|
383
397
|
...state,
|
|
384
398
|
liveMessages: [...state.liveMessages, event.message],
|
|
385
399
|
text: '',
|
|
386
400
|
reasoning: ''
|
|
387
|
-
}
|
|
401
|
+
})
|
|
388
402
|
case 'AgentEnd':
|
|
389
403
|
return {
|
|
390
404
|
...state,
|
|
@@ -393,7 +407,8 @@ const applyAgentEventUnchecked = (
|
|
|
393
407
|
liveMessages: [],
|
|
394
408
|
text: '',
|
|
395
409
|
reasoning: '',
|
|
396
|
-
toolRuns: completedToolRuns(state.toolRuns)
|
|
410
|
+
toolRuns: completedToolRuns(state.toolRuns),
|
|
411
|
+
retryInfo: null
|
|
397
412
|
}
|
|
398
413
|
case 'AgentAwaitingInput':
|
|
399
414
|
return {
|
|
@@ -403,9 +418,12 @@ const applyAgentEventUnchecked = (
|
|
|
403
418
|
liveMessages: [],
|
|
404
419
|
text: '',
|
|
405
420
|
reasoning: '',
|
|
406
|
-
error: null
|
|
421
|
+
error: null,
|
|
422
|
+
errorInfo: null,
|
|
423
|
+
retryInfo: null
|
|
407
424
|
}
|
|
408
425
|
case 'AgentRetry':
|
|
426
|
+
return { ...state, retryInfo: event }
|
|
409
427
|
case 'CompactionEnd':
|
|
410
428
|
case 'CompactionStart':
|
|
411
429
|
case 'LLMStreamEnd':
|
|
@@ -431,24 +449,31 @@ export const submitAgentUserMessage = (
|
|
|
431
449
|
reasoning: '',
|
|
432
450
|
toolRuns: completedToolRuns(state.toolRuns),
|
|
433
451
|
error: null,
|
|
452
|
+
errorInfo: null,
|
|
453
|
+
retryInfo: null,
|
|
434
454
|
seenEventIds: []
|
|
435
455
|
})
|
|
436
456
|
|
|
437
457
|
export const markAgentError = (
|
|
438
458
|
state: AgentClientState,
|
|
439
|
-
message = 'Agent request failed'
|
|
459
|
+
message = 'Agent request failed',
|
|
460
|
+
errorInfo: AgentError | null = null
|
|
440
461
|
): AgentClientState => ({
|
|
441
462
|
...state,
|
|
442
463
|
status: 'error',
|
|
443
464
|
toolRuns: completedToolRuns(state.toolRuns),
|
|
444
|
-
error: message
|
|
465
|
+
error: message,
|
|
466
|
+
errorInfo,
|
|
467
|
+
retryInfo: null
|
|
445
468
|
})
|
|
446
469
|
|
|
447
470
|
export const markAgentAborted = (state: AgentClientState): AgentClientState => ({
|
|
448
471
|
...state,
|
|
449
472
|
status: 'aborted',
|
|
450
473
|
toolRuns: completedToolRuns(state.toolRuns),
|
|
451
|
-
error: null
|
|
474
|
+
error: null,
|
|
475
|
+
errorInfo: null,
|
|
476
|
+
retryInfo: null
|
|
452
477
|
})
|
|
453
478
|
|
|
454
479
|
export const reduceAgentEvents = (
|
package/src/loop/error.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import * as Schema from 'effect/Schema'
|
|
2
|
-
import { AgentError, type AgentErrorCode } from '@yolk-sdk/agent/protocol'
|
|
2
|
+
import { AgentError, ProviderErrorInfo, type AgentErrorCode } from '@yolk-sdk/agent/protocol'
|
|
3
3
|
|
|
4
4
|
export class LLMError extends Schema.TaggedErrorClass<LLMError>()('LLMError', {
|
|
5
5
|
cause: Schema.Literals([
|
|
6
6
|
'validation_error',
|
|
7
7
|
'provider_error',
|
|
8
8
|
'rate_limit',
|
|
9
|
+
'overloaded',
|
|
9
10
|
'context_overflow',
|
|
10
11
|
'invalid_response'
|
|
11
12
|
]),
|
|
12
13
|
message: Schema.String,
|
|
13
|
-
retryable: Schema.Boolean
|
|
14
|
+
retryable: Schema.Boolean,
|
|
15
|
+
provider: Schema.optional(ProviderErrorInfo)
|
|
14
16
|
}) {}
|
|
15
17
|
|
|
16
18
|
export class FauxExhaustedError extends Schema.TaggedErrorClass<FauxExhaustedError>()(
|
|
@@ -75,7 +77,8 @@ export const agentLoopErrorToAgentError = (error: AgentLoopError): AgentError =>
|
|
|
75
77
|
return AgentError.make({
|
|
76
78
|
code: error.cause,
|
|
77
79
|
message: error.message,
|
|
78
|
-
retryable: error.retryable
|
|
80
|
+
retryable: error.retryable,
|
|
81
|
+
...(error.provider === undefined ? {} : { provider: error.provider })
|
|
79
82
|
})
|
|
80
83
|
case 'ToolError':
|
|
81
84
|
return AgentError.make({
|
package/src/loop/run.ts
CHANGED
|
@@ -292,8 +292,30 @@ type TurnStreamInput = {
|
|
|
292
292
|
readonly turn: number
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
const
|
|
296
|
-
|
|
295
|
+
const maxUnhintedRetryDelayMs = 30_000
|
|
296
|
+
const maxHintedRetryDelayMs = 2_147_483_647
|
|
297
|
+
|
|
298
|
+
const validDelayMs = (delayMs: number) =>
|
|
299
|
+
Number.isFinite(delayMs) && delayMs >= 0 ? Math.floor(delayMs) : undefined
|
|
300
|
+
|
|
301
|
+
const hintedRetryDelayMs = (error: LLMError) => {
|
|
302
|
+
const delayMs = error.provider?.retryAfterMs
|
|
303
|
+
const validDelay = delayMs === undefined ? undefined : validDelayMs(delayMs)
|
|
304
|
+
|
|
305
|
+
return validDelay === undefined ? undefined : Math.min(validDelay, maxHintedRetryDelayMs)
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const retryDelayMs = (baseDelayMs: number, attempt: number, error: LLMError) => {
|
|
309
|
+
const hintedDelay = hintedRetryDelayMs(error)
|
|
310
|
+
|
|
311
|
+
if (hintedDelay !== undefined) {
|
|
312
|
+
return hintedDelay
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const delayMs = validDelayMs(baseDelayMs * 2 ** Math.max(0, attempt - 1)) ?? 0
|
|
316
|
+
|
|
317
|
+
return Math.min(delayMs, maxUnhintedRetryDelayMs)
|
|
318
|
+
}
|
|
297
319
|
|
|
298
320
|
const retryReason = (error: LLMError): AgentErrorCode => error.cause
|
|
299
321
|
|
|
@@ -332,13 +354,14 @@ const withProviderRetries = (
|
|
|
332
354
|
return failAgentLoopError(error)
|
|
333
355
|
}
|
|
334
356
|
|
|
335
|
-
const delayMs = retryDelayMs(loopConfig.retryBaseDelayMs, attempt)
|
|
357
|
+
const delayMs = retryDelayMs(loopConfig.retryBaseDelayMs, attempt, error)
|
|
336
358
|
return Stream.make(
|
|
337
359
|
AgentRetry.make({
|
|
338
360
|
attempt,
|
|
339
361
|
reason: retryReason(error),
|
|
340
362
|
delayMs,
|
|
341
|
-
message: error.message
|
|
363
|
+
message: error.message,
|
|
364
|
+
...(error.provider === undefined ? {} : { provider: error.provider })
|
|
342
365
|
})
|
|
343
366
|
).pipe(
|
|
344
367
|
Stream.concat(sleepStream(delayMs)),
|