@swarmclawai/swarmclaw 1.2.1 → 1.2.3
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 +16 -85
- package/bin/server-cmd.js +64 -1
- package/package.json +2 -2
- package/skills/coding-agent/SKILL.md +111 -0
- package/skills/github/SKILL.md +140 -0
- package/skills/nano-banana-pro/SKILL.md +62 -0
- package/skills/nano-banana-pro/scripts/generate_image.py +235 -0
- package/skills/nano-pdf/SKILL.md +53 -0
- package/skills/openai-image-gen/SKILL.md +78 -0
- package/skills/openai-image-gen/scripts/gen.py +328 -0
- package/skills/resourceful-problem-solving/SKILL.md +49 -0
- package/skills/skill-creator/SKILL.md +147 -0
- package/skills/skill-creator/scripts/init_skill.py +378 -0
- package/skills/skill-creator/scripts/quick_validate.py +159 -0
- package/skills/summarize/SKILL.md +77 -0
- package/src/app/api/auth/route.ts +20 -5
- package/src/app/api/chats/[id]/devserver/route.ts +13 -19
- package/src/app/api/chats/[id]/messages/route.ts +13 -15
- package/src/app/api/chats/[id]/route.ts +9 -10
- package/src/app/api/chats/[id]/stop/route.ts +5 -7
- package/src/app/api/chats/messages-route.test.ts +8 -6
- package/src/app/api/chats/route.ts +9 -10
- package/src/app/api/ip/route.ts +2 -2
- package/src/app/api/preview-server/route.ts +1 -1
- package/src/app/api/projects/[id]/route.ts +7 -46
- package/src/cli/server-cmd.test.js +74 -0
- package/src/components/chat/chat-area.tsx +45 -23
- package/src/components/chat/message-bubble.test.ts +35 -0
- package/src/components/chat/message-bubble.tsx +19 -9
- package/src/components/chat/message-list.tsx +37 -3
- package/src/components/input/chat-input.tsx +34 -14
- package/src/components/openclaw/openclaw-deploy-panel.tsx +4 -0
- package/src/instrumentation.ts +1 -1
- package/src/lib/chat/assistant-render-id.ts +3 -0
- package/src/lib/chat/chat-streaming-state.test.ts +42 -3
- package/src/lib/chat/chat-streaming-state.ts +20 -8
- package/src/lib/chat/queued-message-queue.test.ts +23 -1
- package/src/lib/chat/queued-message-queue.ts +11 -2
- package/src/lib/providers/cli-utils.test.ts +124 -0
- package/src/lib/server/activity/activity-log.ts +21 -0
- package/src/lib/server/agents/agent-availability.test.ts +10 -5
- package/src/lib/server/agents/agent-cascade.ts +79 -59
- package/src/lib/server/agents/agent-registry.ts +3 -1
- package/src/lib/server/agents/agent-repository.ts +90 -0
- package/src/lib/server/agents/delegation-job-repository.ts +53 -0
- package/src/lib/server/agents/delegation-jobs.ts +11 -4
- package/src/lib/server/agents/guardian-checkpoint-repository.ts +35 -0
- package/src/lib/server/agents/guardian.ts +2 -2
- package/src/lib/server/agents/main-agent-loop.ts +10 -3
- package/src/lib/server/agents/main-loop-state-repository.ts +38 -0
- package/src/lib/server/agents/subagent-runtime.ts +9 -6
- package/src/lib/server/agents/subagent-swarm.ts +3 -2
- package/src/lib/server/agents/task-session.ts +3 -4
- package/src/lib/server/approvals/approval-repository.ts +30 -0
- package/src/lib/server/autonomy/supervisor-incident-repository.ts +42 -0
- package/src/lib/server/chat-execution/chat-execution-types.ts +38 -0
- package/src/lib/server/chat-execution/chat-execution-utils.ts +1 -1
- package/src/lib/server/chat-execution/chat-execution.ts +84 -1926
- package/src/lib/server/chat-execution/chat-turn-finalization.ts +620 -0
- package/src/lib/server/chat-execution/chat-turn-partial-persistence.ts +221 -0
- package/src/lib/server/chat-execution/chat-turn-preflight.ts +133 -0
- package/src/lib/server/chat-execution/chat-turn-preparation.ts +817 -0
- package/src/lib/server/chat-execution/chat-turn-stream-execution.ts +296 -0
- package/src/lib/server/chat-execution/chat-turn-tool-routing.ts +5 -5
- package/src/lib/server/chat-execution/message-classifier.test.ts +329 -0
- package/src/lib/server/chat-execution/post-stream-finalization.ts +1 -1
- package/src/lib/server/chat-execution/prompt-builder.ts +11 -0
- package/src/lib/server/chat-execution/prompt-sections.ts +5 -6
- package/src/lib/server/chat-execution/situational-awareness.ts +12 -7
- package/src/lib/server/chat-execution/stream-agent-chat.ts +16 -13
- package/src/lib/server/chatrooms/chatroom-repository.ts +32 -0
- package/src/lib/server/connectors/connector-repository.ts +58 -0
- package/src/lib/server/connectors/runtime-state.test.ts +117 -0
- package/src/lib/server/credentials/credential-repository.ts +7 -0
- package/src/lib/server/gateways/gateway-profile-repository.ts +4 -0
- package/src/lib/server/memory/memory-abstract.test.ts +59 -0
- package/src/lib/server/missions/mission-repository.ts +74 -0
- package/src/lib/server/missions/mission-service/actions.ts +6 -0
- package/src/lib/server/missions/mission-service/bindings.ts +9 -0
- package/src/lib/server/missions/mission-service/context.ts +4 -0
- package/src/lib/server/missions/mission-service/core.ts +2269 -0
- package/src/lib/server/missions/mission-service/queries.ts +12 -0
- package/src/lib/server/missions/mission-service/recovery.ts +5 -0
- package/src/lib/server/missions/mission-service/ticks.ts +9 -0
- package/src/lib/server/missions/mission-service.test.ts +9 -2
- package/src/lib/server/missions/mission-service.ts +6 -2266
- package/src/lib/server/openclaw/deploy.test.ts +42 -3
- package/src/lib/server/openclaw/deploy.ts +26 -12
- package/src/lib/server/persistence/repository-utils.ts +154 -0
- package/src/lib/server/persistence/storage-context.ts +51 -0
- package/src/lib/server/persistence/transaction.ts +1 -0
- package/src/lib/server/projects/project-repository.ts +36 -0
- package/src/lib/server/projects/project-service.ts +79 -0
- package/src/lib/server/protocols/protocol-normalization.test.ts +6 -4
- package/src/lib/server/runtime/alert-dispatch.ts +1 -1
- package/src/lib/server/runtime/daemon-policy.ts +1 -1
- package/src/lib/server/runtime/daemon-state/core.ts +1570 -0
- package/src/lib/server/runtime/daemon-state/health.ts +6 -0
- package/src/lib/server/runtime/daemon-state/policy.ts +7 -0
- package/src/lib/server/runtime/daemon-state/supervisor.ts +6 -0
- package/src/lib/server/runtime/daemon-state.test.ts +48 -0
- package/src/lib/server/runtime/daemon-state.ts +3 -1470
- package/src/lib/server/runtime/estop-repository.ts +4 -0
- package/src/lib/server/runtime/estop.ts +3 -1
- package/src/lib/server/runtime/heartbeat-service.test.ts +2 -2
- package/src/lib/server/runtime/heartbeat-service.ts +55 -34
- package/src/lib/server/runtime/heartbeat-wake.ts +6 -4
- package/src/lib/server/runtime/idle-window.ts +2 -2
- package/src/lib/server/runtime/network.ts +11 -0
- package/src/lib/server/runtime/orchestrator-events.ts +2 -2
- package/src/lib/server/runtime/queue/claims.ts +4 -0
- package/src/lib/server/runtime/queue/core.ts +2079 -0
- package/src/lib/server/runtime/queue/execution.ts +7 -0
- package/src/lib/server/runtime/queue/followups.ts +4 -0
- package/src/lib/server/runtime/queue/queries.ts +12 -0
- package/src/lib/server/runtime/queue/recovery.ts +7 -0
- package/src/lib/server/runtime/queue-recovery.test.ts +48 -13
- package/src/lib/server/runtime/queue-repository.ts +17 -0
- package/src/lib/server/runtime/queue.ts +5 -2061
- package/src/lib/server/runtime/run-ledger.ts +6 -5
- package/src/lib/server/runtime/run-repository.ts +73 -0
- package/src/lib/server/runtime/runtime-lock-repository.ts +8 -0
- package/src/lib/server/runtime/runtime-settings.ts +1 -1
- package/src/lib/server/runtime/runtime-state.ts +99 -0
- package/src/lib/server/runtime/scheduler.ts +4 -2
- package/src/lib/server/runtime/session-run-manager/cancellation.ts +157 -0
- package/src/lib/server/runtime/session-run-manager/drain.ts +246 -0
- package/src/lib/server/runtime/session-run-manager/enqueue.ts +287 -0
- package/src/lib/server/runtime/session-run-manager/queries.ts +117 -0
- package/src/lib/server/runtime/session-run-manager/recovery.ts +238 -0
- package/src/lib/server/runtime/session-run-manager/state.ts +441 -0
- package/src/lib/server/runtime/session-run-manager/types.ts +74 -0
- package/src/lib/server/runtime/session-run-manager.ts +72 -1377
- package/src/lib/server/runtime/watch-job-repository.ts +35 -0
- package/src/lib/server/runtime/watch-jobs.ts +3 -1
- package/src/lib/server/schedules/schedule-repository.ts +42 -0
- package/src/lib/server/sessions/session-repository.ts +85 -0
- package/src/lib/server/settings/settings-repository.ts +25 -0
- package/src/lib/server/skills/skill-discovery.test.ts +2 -2
- package/src/lib/server/skills/skill-discovery.ts +2 -2
- package/src/lib/server/skills/skill-repository.ts +14 -0
- package/src/lib/server/storage.ts +13 -24
- package/src/lib/server/tasks/task-repository.ts +54 -0
- package/src/lib/server/usage/usage-repository.ts +30 -0
- package/src/lib/server/webhooks/webhook-repository.ts +10 -0
- package/src/lib/strip-internal-metadata.test.ts +42 -41
- package/src/stores/use-chat-store.test.ts +54 -0
- package/src/stores/use-chat-store.ts +21 -5
- /package/{bundled-skills → skills}/google-workspace/SKILL.md +0 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getSession,
|
|
3
|
+
saveSession,
|
|
4
|
+
} from '@/lib/server/sessions/session-repository'
|
|
5
|
+
import { notify } from '@/lib/server/ws-hub'
|
|
6
|
+
import type { MessageToolEvent, SSEEvent } from '@/types'
|
|
7
|
+
import { upsertStreamingAssistantArtifact } from '@/lib/chat/chat-streaming-state'
|
|
8
|
+
import { pruneIncompleteToolEvents } from '@/lib/server/chat-execution/chat-streaming-utils'
|
|
9
|
+
import {
|
|
10
|
+
collectToolEvent,
|
|
11
|
+
dedupeConsecutiveToolEvents,
|
|
12
|
+
extractEventJson,
|
|
13
|
+
} from '@/lib/server/chat-execution/chat-execution-tool-events'
|
|
14
|
+
import {
|
|
15
|
+
getToolEventsSnapshotKey,
|
|
16
|
+
hasPersistableAssistantPayload,
|
|
17
|
+
} from '@/lib/server/chat-execution/chat-execution-utils'
|
|
18
|
+
import {
|
|
19
|
+
applyMessageLifecycleHooks,
|
|
20
|
+
type PreparedExecutableChatTurn,
|
|
21
|
+
} from '@/lib/server/chat-execution/chat-turn-preparation'
|
|
22
|
+
|
|
23
|
+
export interface PartialAssistantSnapshot {
|
|
24
|
+
thinkingText: string
|
|
25
|
+
toolEvents: MessageToolEvent[]
|
|
26
|
+
streamErrors: string[]
|
|
27
|
+
accumulatedUsage: {
|
|
28
|
+
inputTokens: number
|
|
29
|
+
outputTokens: number
|
|
30
|
+
estimatedCost: number
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface PartialAssistantPersistence {
|
|
35
|
+
emit: (event: SSEEvent) => void
|
|
36
|
+
parseAndEmit: (raw: string) => void
|
|
37
|
+
stop: () => void
|
|
38
|
+
awaitIdle: () => Promise<void>
|
|
39
|
+
getToolEvents: () => MessageToolEvent[]
|
|
40
|
+
getSnapshot: () => PartialAssistantSnapshot
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const PARTIAL_SAVE_INTERVAL_MS = 3500
|
|
44
|
+
const PARTIAL_SAVE_MIN_INTERVAL_MS = 400
|
|
45
|
+
|
|
46
|
+
export function createPartialAssistantPersistence(input: {
|
|
47
|
+
prepared: PreparedExecutableChatTurn
|
|
48
|
+
onEvent?: (event: SSEEvent) => void
|
|
49
|
+
}): PartialAssistantPersistence {
|
|
50
|
+
const { prepared, onEvent } = input
|
|
51
|
+
const toolEvents: MessageToolEvent[] = []
|
|
52
|
+
const streamErrors: string[] = []
|
|
53
|
+
const accumulatedUsage = { inputTokens: 0, outputTokens: 0, estimatedCost: 0 }
|
|
54
|
+
|
|
55
|
+
let thinkingText = ''
|
|
56
|
+
let streamingPartialText = ''
|
|
57
|
+
let lastPartialSaveAt = 0
|
|
58
|
+
let lastPartialSnapshotKey = ''
|
|
59
|
+
let partialSaveTimeout: ReturnType<typeof setTimeout> | null = null
|
|
60
|
+
let partialPersistenceClosed = false
|
|
61
|
+
let partialPersistChain: Promise<void> = Promise.resolve()
|
|
62
|
+
|
|
63
|
+
const persistStreamingAssistantArtifact = async () => {
|
|
64
|
+
if (prepared.hideAssistantTranscript) return
|
|
65
|
+
partialSaveTimeout = null
|
|
66
|
+
if (partialPersistenceClosed) return
|
|
67
|
+
const persistedToolEvents = toolEvents.length
|
|
68
|
+
? dedupeConsecutiveToolEvents(pruneIncompleteToolEvents([...toolEvents]))
|
|
69
|
+
: []
|
|
70
|
+
if (!hasPersistableAssistantPayload(streamingPartialText, thinkingText, persistedToolEvents)) return
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const current = getSession(prepared.sessionId)
|
|
74
|
+
if (!current) return
|
|
75
|
+
current.messages = Array.isArray(current.messages) ? current.messages : []
|
|
76
|
+
const partialMsg = await applyMessageLifecycleHooks({
|
|
77
|
+
session: current,
|
|
78
|
+
message: {
|
|
79
|
+
role: 'assistant',
|
|
80
|
+
text: streamingPartialText,
|
|
81
|
+
time: Date.now(),
|
|
82
|
+
streaming: true,
|
|
83
|
+
runId: prepared.lifecycleRunId,
|
|
84
|
+
thinking: thinkingText || undefined,
|
|
85
|
+
toolEvents: persistedToolEvents.length ? persistedToolEvents : undefined,
|
|
86
|
+
},
|
|
87
|
+
enabledIds: prepared.extensionsForRun,
|
|
88
|
+
phase: 'assistant_partial',
|
|
89
|
+
runId: prepared.lifecycleRunId,
|
|
90
|
+
isSynthetic: true,
|
|
91
|
+
})
|
|
92
|
+
if (!partialMsg) return
|
|
93
|
+
const snapshotKey = JSON.stringify([
|
|
94
|
+
partialMsg.text,
|
|
95
|
+
partialMsg.thinking || '',
|
|
96
|
+
getToolEventsSnapshotKey(partialMsg.toolEvents || []),
|
|
97
|
+
])
|
|
98
|
+
if (snapshotKey === lastPartialSnapshotKey) return
|
|
99
|
+
lastPartialSnapshotKey = snapshotKey
|
|
100
|
+
lastPartialSaveAt = Date.now()
|
|
101
|
+
upsertStreamingAssistantArtifact(current.messages, partialMsg, {
|
|
102
|
+
minIndex: prepared.runMessageStartIndex,
|
|
103
|
+
minTime: prepared.runStartedAt,
|
|
104
|
+
})
|
|
105
|
+
saveSession(prepared.sessionId, current)
|
|
106
|
+
notify(`messages:${prepared.sessionId}`)
|
|
107
|
+
} catch {
|
|
108
|
+
// Partial persistence is best-effort.
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const triggerPartialAssistantPersist = () => {
|
|
113
|
+
partialPersistChain = partialPersistChain
|
|
114
|
+
.catch(() => {})
|
|
115
|
+
.then(async () => {
|
|
116
|
+
await persistStreamingAssistantArtifact()
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const queuePartialAssistantPersist = (immediate = false) => {
|
|
121
|
+
if (partialPersistenceClosed) return
|
|
122
|
+
const now = Date.now()
|
|
123
|
+
if (immediate || now - lastPartialSaveAt >= PARTIAL_SAVE_MIN_INTERVAL_MS) {
|
|
124
|
+
if (partialSaveTimeout) {
|
|
125
|
+
clearTimeout(partialSaveTimeout)
|
|
126
|
+
partialSaveTimeout = null
|
|
127
|
+
}
|
|
128
|
+
triggerPartialAssistantPersist()
|
|
129
|
+
return
|
|
130
|
+
}
|
|
131
|
+
if (partialSaveTimeout) return
|
|
132
|
+
partialSaveTimeout = setTimeout(() => {
|
|
133
|
+
triggerPartialAssistantPersist()
|
|
134
|
+
}, PARTIAL_SAVE_MIN_INTERVAL_MS - (now - lastPartialSaveAt))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const emit = (event: SSEEvent) => {
|
|
138
|
+
let shouldPersistPartial = false
|
|
139
|
+
let immediatePartialPersist = false
|
|
140
|
+
if (event.t === 'reset') {
|
|
141
|
+
streamingPartialText = event.text || ''
|
|
142
|
+
thinkingText = ''
|
|
143
|
+
toolEvents.length = 0
|
|
144
|
+
shouldPersistPartial = true
|
|
145
|
+
immediatePartialPersist = true
|
|
146
|
+
}
|
|
147
|
+
if (event.t === 'd' && typeof event.text === 'string') {
|
|
148
|
+
streamingPartialText += event.text
|
|
149
|
+
shouldPersistPartial = true
|
|
150
|
+
immediatePartialPersist = streamingPartialText.length === event.text.length
|
|
151
|
+
}
|
|
152
|
+
if (event.t === 'err' && typeof event.text === 'string') {
|
|
153
|
+
const trimmed = event.text.trim()
|
|
154
|
+
if (trimmed) {
|
|
155
|
+
streamErrors.push(trimmed)
|
|
156
|
+
if (streamErrors.length > 8) streamErrors.shift()
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (event.t === 'thinking' && event.text) {
|
|
160
|
+
thinkingText += event.text
|
|
161
|
+
shouldPersistPartial = true
|
|
162
|
+
}
|
|
163
|
+
if (event.t === 'md' && event.text) {
|
|
164
|
+
try {
|
|
165
|
+
const mdPayload = JSON.parse(event.text) as Record<string, unknown>
|
|
166
|
+
const usage = mdPayload.usage as { inputTokens?: number; outputTokens?: number; estimatedCost?: number } | undefined
|
|
167
|
+
if (usage) {
|
|
168
|
+
if (typeof usage.inputTokens === 'number') accumulatedUsage.inputTokens += usage.inputTokens
|
|
169
|
+
if (typeof usage.outputTokens === 'number') accumulatedUsage.outputTokens += usage.outputTokens
|
|
170
|
+
if (typeof usage.estimatedCost === 'number') accumulatedUsage.estimatedCost += usage.estimatedCost
|
|
171
|
+
}
|
|
172
|
+
} catch {
|
|
173
|
+
// Ignore non-JSON md events.
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
collectToolEvent(event, toolEvents)
|
|
177
|
+
if (event.t === 'tool_call' || event.t === 'tool_result') {
|
|
178
|
+
shouldPersistPartial = true
|
|
179
|
+
immediatePartialPersist = true
|
|
180
|
+
}
|
|
181
|
+
if (shouldPersistPartial) queuePartialAssistantPersist(immediatePartialPersist)
|
|
182
|
+
onEvent?.(event)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const periodicTimer = setInterval(() => {
|
|
186
|
+
persistStreamingAssistantArtifact()
|
|
187
|
+
}, PARTIAL_SAVE_INTERVAL_MS)
|
|
188
|
+
|
|
189
|
+
return {
|
|
190
|
+
emit,
|
|
191
|
+
parseAndEmit(raw: string) {
|
|
192
|
+
const lines = raw.split('\n').filter(Boolean)
|
|
193
|
+
for (const line of lines) {
|
|
194
|
+
const event = extractEventJson(line)
|
|
195
|
+
if (event) emit(event)
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
stop() {
|
|
199
|
+
partialPersistenceClosed = true
|
|
200
|
+
if (partialSaveTimeout) {
|
|
201
|
+
clearTimeout(partialSaveTimeout)
|
|
202
|
+
partialSaveTimeout = null
|
|
203
|
+
}
|
|
204
|
+
clearInterval(periodicTimer)
|
|
205
|
+
},
|
|
206
|
+
awaitIdle() {
|
|
207
|
+
return partialPersistChain.catch(() => {})
|
|
208
|
+
},
|
|
209
|
+
getToolEvents() {
|
|
210
|
+
return toolEvents
|
|
211
|
+
},
|
|
212
|
+
getSnapshot() {
|
|
213
|
+
return {
|
|
214
|
+
thinkingText,
|
|
215
|
+
toolEvents: [...toolEvents],
|
|
216
|
+
streamErrors: [...streamErrors],
|
|
217
|
+
accumulatedUsage: { ...accumulatedUsage },
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
}
|
|
221
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { notify } from '@/lib/server/ws-hub'
|
|
2
|
+
import { getSession, saveSession } from '@/lib/server/sessions/session-repository'
|
|
3
|
+
import type { MessageToolEvent, SSEEvent } from '@/types'
|
|
4
|
+
import type { ExecuteChatTurnResult } from './chat-execution-types'
|
|
5
|
+
import {
|
|
6
|
+
resolveRequestedToolPreflightResponse,
|
|
7
|
+
runExclusiveDirectMemoryPreflight,
|
|
8
|
+
} from '@/lib/server/chat-execution/chat-turn-tool-routing'
|
|
9
|
+
import {
|
|
10
|
+
applyMessageLifecycleHooks,
|
|
11
|
+
type PreparedBlockedChatTurn,
|
|
12
|
+
type PreparedExecutableChatTurn,
|
|
13
|
+
} from '@/lib/server/chat-execution/chat-turn-preparation'
|
|
14
|
+
|
|
15
|
+
type DirectMemoryPreflightResult = Awaited<ReturnType<typeof runExclusiveDirectMemoryPreflight>>
|
|
16
|
+
|
|
17
|
+
export interface ChatTurnPreflightResult {
|
|
18
|
+
terminalResult?: ExecuteChatTurnResult
|
|
19
|
+
directMemoryResult?: DirectMemoryPreflightResult
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function completeSyntheticAssistantTurn(params: {
|
|
23
|
+
runId?: string
|
|
24
|
+
sessionId: string
|
|
25
|
+
text: string
|
|
26
|
+
lifecycleRunId: string
|
|
27
|
+
enabledIds: string[]
|
|
28
|
+
shouldPersist: boolean
|
|
29
|
+
phase: 'assistant_final' | 'heartbeat'
|
|
30
|
+
error?: string
|
|
31
|
+
notifyMessages?: boolean
|
|
32
|
+
notifySessions?: boolean
|
|
33
|
+
}): Promise<ExecuteChatTurnResult> {
|
|
34
|
+
const session = getSession(params.sessionId)
|
|
35
|
+
let persisted = false
|
|
36
|
+
if (session && params.shouldPersist) {
|
|
37
|
+
const nextAssistantMessage = await applyMessageLifecycleHooks({
|
|
38
|
+
session,
|
|
39
|
+
message: {
|
|
40
|
+
role: 'assistant',
|
|
41
|
+
text: params.text,
|
|
42
|
+
time: Date.now(),
|
|
43
|
+
},
|
|
44
|
+
enabledIds: params.enabledIds,
|
|
45
|
+
phase: params.phase,
|
|
46
|
+
runId: params.lifecycleRunId,
|
|
47
|
+
isSynthetic: true,
|
|
48
|
+
})
|
|
49
|
+
if (nextAssistantMessage) {
|
|
50
|
+
session.messages = Array.isArray(session.messages) ? session.messages : []
|
|
51
|
+
session.messages.push(nextAssistantMessage)
|
|
52
|
+
session.lastActiveAt = Date.now()
|
|
53
|
+
saveSession(params.sessionId, session)
|
|
54
|
+
if (params.notifyMessages) notify(`messages:${params.sessionId}`)
|
|
55
|
+
if (params.notifySessions) notify('sessions')
|
|
56
|
+
persisted = true
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
runId: params.runId,
|
|
62
|
+
sessionId: params.sessionId,
|
|
63
|
+
text: params.text,
|
|
64
|
+
persisted,
|
|
65
|
+
toolEvents: [],
|
|
66
|
+
error: params.error,
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export async function completeBlockedChatTurn(prepared: PreparedBlockedChatTurn): Promise<ExecuteChatTurnResult> {
|
|
71
|
+
return completeSyntheticAssistantTurn({
|
|
72
|
+
runId: prepared.runId,
|
|
73
|
+
sessionId: prepared.sessionId,
|
|
74
|
+
text: prepared.blockedMessage,
|
|
75
|
+
lifecycleRunId: prepared.lifecycleRunId,
|
|
76
|
+
enabledIds: prepared.syntheticEnabledIds,
|
|
77
|
+
shouldPersist: !prepared.internal,
|
|
78
|
+
phase: 'assistant_final',
|
|
79
|
+
error: prepared.blockedMessage,
|
|
80
|
+
})
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function runChatTurnPreflight(params: {
|
|
84
|
+
prepared: PreparedExecutableChatTurn
|
|
85
|
+
emit: (event: SSEEvent) => void
|
|
86
|
+
toolEvents: MessageToolEvent[]
|
|
87
|
+
}): Promise<ChatTurnPreflightResult | null> {
|
|
88
|
+
const { prepared, emit, toolEvents } = params
|
|
89
|
+
|
|
90
|
+
const requestedToolPreflightResponse = resolveRequestedToolPreflightResponse({
|
|
91
|
+
message: prepared.message,
|
|
92
|
+
enabledExtensions: prepared.extensionsForRun,
|
|
93
|
+
toolPolicy: prepared.toolPolicy,
|
|
94
|
+
appSettings: prepared.appSettings,
|
|
95
|
+
internal: prepared.internal,
|
|
96
|
+
source: prepared.source,
|
|
97
|
+
session: prepared.sessionForRun,
|
|
98
|
+
})
|
|
99
|
+
if (requestedToolPreflightResponse) {
|
|
100
|
+
return {
|
|
101
|
+
terminalResult: await completeSyntheticAssistantTurn({
|
|
102
|
+
runId: prepared.runId,
|
|
103
|
+
sessionId: prepared.sessionId,
|
|
104
|
+
text: requestedToolPreflightResponse,
|
|
105
|
+
lifecycleRunId: prepared.lifecycleRunId,
|
|
106
|
+
enabledIds: prepared.extensionsForRun,
|
|
107
|
+
shouldPersist: !prepared.hideAssistantTranscript,
|
|
108
|
+
phase: 'assistant_final',
|
|
109
|
+
notifyMessages: true,
|
|
110
|
+
notifySessions: true,
|
|
111
|
+
}),
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const directMemoryResult = await runExclusiveDirectMemoryPreflight({
|
|
116
|
+
session: prepared.sessionForRun,
|
|
117
|
+
sessionId: prepared.sessionId,
|
|
118
|
+
message: prepared.message,
|
|
119
|
+
effectiveMessage: prepared.effectiveMessage,
|
|
120
|
+
enabledExtensions: prepared.extensionsForRun,
|
|
121
|
+
toolPolicy: prepared.toolPolicy,
|
|
122
|
+
appSettings: prepared.appSettings,
|
|
123
|
+
internal: prepared.internal,
|
|
124
|
+
source: prepared.source,
|
|
125
|
+
toolEvents,
|
|
126
|
+
emit,
|
|
127
|
+
})
|
|
128
|
+
if (directMemoryResult) {
|
|
129
|
+
return { directMemoryResult }
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return null
|
|
133
|
+
}
|