@pikku/core 0.12.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/dist/errors/errors.d.ts +6 -0
- package/dist/errors/errors.js +10 -0
- package/dist/errors/index.d.ts +1 -0
- package/dist/errors/index.js +1 -0
- package/dist/function/function-runner.d.ts +3 -3
- package/dist/function/function-runner.js +66 -44
- package/dist/function/functions.types.d.ts +1 -0
- package/dist/handle-error.d.ts +2 -2
- package/dist/handle-error.js +2 -2
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -1
- package/dist/internal.d.ts +3 -0
- package/dist/internal.js +2 -0
- package/dist/middleware/auth-bearer.d.ts +1 -1
- package/dist/middleware/auth-bearer.js +1 -1
- package/dist/middleware/auth-cookie.d.ts +2 -2
- package/dist/middleware/auth-cookie.js +1 -1
- package/dist/middleware/cors.d.ts +2 -2
- package/dist/middleware/cors.js +45 -37
- package/dist/middleware-runner.d.ts +1 -1
- package/dist/permissions.d.ts +2 -2
- package/dist/pikku-state.d.ts +9 -8
- package/dist/pikku-state.js +30 -17
- package/dist/schema.d.ts +4 -4
- package/dist/schema.js +9 -5
- package/dist/services/ai-agent-runner-service.d.ts +22 -3
- package/dist/services/ai-run-state-service.d.ts +1 -1
- package/dist/services/ai-storage-service.d.ts +1 -1
- package/dist/services/content-service.d.ts +6 -0
- package/dist/services/gopass-secrets.d.ts +1 -1
- package/dist/services/gopass-secrets.js +3 -0
- package/dist/services/in-memory-ai-run-state-service.d.ts +15 -0
- package/dist/services/in-memory-ai-run-state-service.js +44 -0
- package/dist/services/in-memory-trigger-service.d.ts +0 -1
- package/dist/services/in-memory-trigger-service.js +6 -8
- package/dist/services/index.d.ts +3 -2
- package/dist/services/index.js +1 -0
- package/dist/services/local-content.d.ts +2 -1
- package/dist/services/local-content.js +6 -1
- package/dist/services/local-secrets.d.ts +2 -2
- package/dist/services/local-variables.d.ts +1 -1
- package/dist/services/logger-console.d.ts +2 -1
- package/dist/services/scheduler-service.d.ts +0 -12
- package/dist/services/scheduler-service.js +0 -6
- package/dist/services/scoped-secret-service.d.ts +1 -1
- package/dist/services/trigger-service.d.ts +0 -7
- package/dist/services/user-session-service.d.ts +3 -3
- package/dist/services/workflow-service.d.ts +2 -3
- package/dist/types/core.types.d.ts +24 -18
- package/dist/types/state.types.d.ts +17 -15
- package/dist/utils.d.ts +5 -5
- package/dist/utils.js +12 -9
- package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +5 -0
- package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +146 -0
- package/dist/wirings/ai-agent/ai-agent-helpers.d.ts +28 -0
- package/dist/wirings/ai-agent/ai-agent-helpers.js +40 -0
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +4 -5
- package/dist/wirings/ai-agent/ai-agent-prepare.js +66 -30
- package/dist/wirings/ai-agent/ai-agent-registry.d.ts +1 -1
- package/dist/wirings/ai-agent/ai-agent-runner.js +107 -8
- package/dist/wirings/ai-agent/ai-agent-stream.d.ts +2 -1
- package/dist/wirings/ai-agent/ai-agent-stream.js +246 -87
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +61 -2
- package/dist/wirings/ai-agent/index.d.ts +3 -1
- package/dist/wirings/ai-agent/index.js +2 -0
- package/dist/wirings/channel/channel-common.d.ts +2 -2
- package/dist/wirings/channel/channel-handler.d.ts +3 -3
- package/dist/wirings/channel/channel-handler.js +4 -4
- package/dist/wirings/channel/channel-runner.d.ts +5 -5
- package/dist/wirings/channel/channel-runner.js +3 -2
- package/dist/wirings/channel/channel-store.d.ts +1 -1
- package/dist/wirings/channel/channel.types.d.ts +4 -6
- package/dist/wirings/channel/local/local-channel-runner.d.ts +7 -2
- package/dist/wirings/channel/local/local-channel-runner.js +4 -3
- package/dist/wirings/channel/local/local-eventhub-service.d.ts +2 -2
- package/dist/wirings/channel/log-channels.d.ts +1 -1
- package/dist/wirings/channel/pikku-abstract-channel-handler.d.ts +1 -1
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +4 -4
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +25 -19
- package/dist/wirings/cli/channel/cli-channel-runner.d.ts +1 -1
- package/dist/wirings/cli/cli-runner.d.ts +2 -2
- package/dist/wirings/cli/cli.types.d.ts +3 -3
- package/dist/wirings/cli/command-parser.d.ts +1 -1
- package/dist/wirings/http/http-runner.d.ts +9 -9
- package/dist/wirings/http/http-runner.js +33 -14
- package/dist/wirings/http/http.types.d.ts +2 -6
- package/dist/wirings/http/log-http-routes.d.ts +1 -1
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -1
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +2 -2
- package/dist/wirings/http/pikku-fetch-http-response.js +6 -1
- package/dist/wirings/http/routers/http-router.d.ts +1 -1
- package/dist/wirings/http/routers/path-to-regex.d.ts +2 -2
- package/dist/wirings/mcp/mcp-endpoint-registry.d.ts +1 -1
- package/dist/wirings/mcp/mcp-runner.d.ts +0 -3
- package/dist/wirings/mcp/mcp-runner.js +4 -2
- package/dist/wirings/mcp/mcp.types.d.ts +2 -2
- package/dist/wirings/oauth2/oauth2-client.d.ts +3 -3
- package/dist/wirings/oauth2/wire-oauth2-credential.d.ts +1 -1
- package/dist/wirings/queue/index.d.ts +1 -1
- package/dist/wirings/queue/index.js +1 -1
- package/dist/wirings/queue/queue-runner.d.ts +1 -12
- package/dist/wirings/queue/queue-runner.js +4 -12
- package/dist/wirings/queue/queue.types.d.ts +3 -9
- package/dist/wirings/queue/register-queue-helper.d.ts +2 -2
- package/dist/wirings/queue/register-queue-helper.js +1 -1
- package/dist/wirings/queue/validate-worker-config.d.ts +1 -1
- package/dist/wirings/rpc/index.d.ts +2 -0
- package/dist/wirings/rpc/index.js +1 -0
- package/dist/wirings/rpc/rpc-runner.d.ts +36 -14
- package/dist/wirings/rpc/rpc-runner.js +56 -28
- package/dist/wirings/rpc/rpc-types.d.ts +14 -2
- package/dist/wirings/rpc/wire-addon.d.ts +10 -0
- package/dist/wirings/rpc/wire-addon.js +9 -0
- package/dist/wirings/scheduler/index.d.ts +1 -1
- package/dist/wirings/scheduler/index.js +1 -1
- package/dist/wirings/scheduler/log-schedulers.d.ts +1 -1
- package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -10
- package/dist/wirings/scheduler/scheduler-runner.js +4 -25
- package/dist/wirings/scheduler/scheduler.types.d.ts +2 -2
- package/dist/wirings/trigger/pikku-trigger-service.d.ts +2 -6
- package/dist/wirings/trigger/pikku-trigger-service.js +11 -16
- package/dist/wirings/trigger/trigger-runner.d.ts +1 -5
- package/dist/wirings/trigger/trigger-runner.js +4 -3
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +2 -6
- package/dist/wirings/workflow/pikku-workflow-service.js +20 -29
- package/dist/wirings/workflow/workflow.types.d.ts +2 -2
- package/package.json +2 -1
- package/src/crypto-utils.test.ts +116 -0
- package/src/errors/error.test.ts +143 -2
- package/src/errors/errors.ts +10 -0
- package/src/errors/index.ts +1 -0
- package/src/function/function-runner.test.ts +2 -2
- package/src/function/function-runner.ts +72 -49
- package/src/function/functions.types.ts +1 -0
- package/src/handle-error.test.ts +361 -0
- package/src/handle-error.ts +4 -4
- package/src/index.ts +3 -10
- package/src/internal.ts +6 -0
- package/src/middleware/auth-apikey.test.ts +1 -1
- package/src/middleware/auth-bearer.test.ts +1 -1
- package/src/middleware/auth-bearer.ts +2 -5
- package/src/middleware/auth-cookie.test.ts +1 -1
- package/src/middleware/auth-cookie.ts +3 -5
- package/src/middleware/cors.test.ts +424 -0
- package/src/middleware/cors.ts +14 -6
- package/src/middleware/remote-auth.test.ts +488 -0
- package/src/middleware-runner.test.ts +1 -1
- package/src/middleware-runner.ts +1 -1
- package/src/permissions.test.ts +2 -2
- package/src/permissions.ts +2 -2
- package/src/pikku-state.test.ts +224 -0
- package/src/pikku-state.ts +40 -28
- package/src/schema.test.ts +198 -6
- package/src/schema.ts +11 -7
- package/src/services/ai-agent-runner-service.ts +15 -3
- package/src/services/ai-run-state-service.ts +1 -1
- package/src/services/ai-storage-service.ts +1 -1
- package/src/services/content-service.ts +7 -0
- package/src/services/gopass-secrets.ts +4 -1
- package/src/services/in-memory-ai-run-state-service.ts +73 -0
- package/src/services/in-memory-trigger-service.ts +6 -10
- package/src/services/in-memory-workflow-service.test.ts +351 -0
- package/src/services/index.ts +2 -1
- package/src/services/local-content.ts +9 -3
- package/src/services/local-secrets.test.ts +80 -0
- package/src/services/local-secrets.ts +2 -2
- package/src/services/local-variables.test.ts +61 -0
- package/src/services/local-variables.ts +1 -1
- package/src/services/logger-console.test.ts +118 -0
- package/src/services/logger-console.ts +2 -1
- package/src/services/scheduler-service.ts +0 -18
- package/src/services/scoped-secret-service.test.ts +74 -0
- package/src/services/scoped-secret-service.ts +1 -1
- package/src/services/trigger-service.ts +0 -21
- package/src/services/typed-secret-service.test.ts +93 -0
- package/src/services/typed-variables-service.test.ts +73 -0
- package/src/services/user-session-service.test.ts +113 -0
- package/src/services/user-session-service.ts +3 -3
- package/src/services/workflow-service.ts +2 -12
- package/src/time-utils.test.ts +1 -1
- package/src/types/core.types.ts +25 -19
- package/src/types/state.types.ts +24 -15
- package/src/utils.test.ts +350 -0
- package/src/utils.ts +14 -13
- package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +363 -0
- package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +214 -0
- package/src/wirings/ai-agent/ai-agent-helpers.test.ts +152 -0
- package/src/wirings/ai-agent/ai-agent-helpers.ts +76 -0
- package/src/wirings/ai-agent/ai-agent-model-config.test.ts +115 -0
- package/src/wirings/ai-agent/ai-agent-prepare.ts +79 -45
- package/src/wirings/ai-agent/ai-agent-registry.ts +1 -1
- package/src/wirings/ai-agent/ai-agent-runner.test.ts +245 -3
- package/src/wirings/ai-agent/ai-agent-runner.ts +121 -7
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +430 -24
- package/src/wirings/ai-agent/ai-agent-stream.ts +377 -102
- package/src/wirings/ai-agent/ai-agent.types.ts +57 -2
- package/src/wirings/ai-agent/index.ts +11 -0
- package/src/wirings/channel/channel-common.ts +2 -2
- package/src/wirings/channel/channel-handler.ts +13 -9
- package/src/wirings/channel/channel-runner.ts +6 -6
- package/src/wirings/channel/channel-store.ts +1 -1
- package/src/wirings/channel/channel.types.ts +4 -8
- package/src/wirings/channel/local/local-channel-runner.test.ts +19 -12
- package/src/wirings/channel/local/local-channel-runner.ts +18 -13
- package/src/wirings/channel/local/local-eventhub-service.test.ts +2 -2
- package/src/wirings/channel/local/local-eventhub-service.ts +2 -2
- package/src/wirings/channel/log-channels.ts +1 -1
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +1 -1
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +37 -32
- package/src/wirings/cli/channel/cli-channel-runner.ts +1 -1
- package/src/wirings/cli/cli-runner.test.ts +1 -1
- package/src/wirings/cli/cli-runner.ts +11 -4
- package/src/wirings/cli/cli.types.ts +3 -3
- package/src/wirings/cli/command-parser.test.ts +1 -1
- package/src/wirings/cli/command-parser.ts +1 -1
- package/src/wirings/http/http-routes.test.ts +1 -1
- package/src/wirings/http/http-runner.test.ts +9 -17
- package/src/wirings/http/http-runner.ts +43 -27
- package/src/wirings/http/http.types.ts +1 -14
- package/src/wirings/http/log-http-routes.ts +1 -1
- package/src/wirings/http/pikku-fetch-http-request.ts +1 -1
- package/src/wirings/http/pikku-fetch-http-response.ts +12 -5
- package/src/wirings/http/routers/http-router.ts +1 -1
- package/src/wirings/http/routers/path-to-regex.test.ts +1 -1
- package/src/wirings/http/routers/path-to-regex.ts +4 -3
- package/src/wirings/mcp/mcp-endpoint-registry.ts +5 -1
- package/src/wirings/mcp/mcp-runner.ts +9 -15
- package/src/wirings/mcp/mcp.types.ts +2 -2
- package/src/wirings/oauth2/oauth2-client.ts +3 -3
- package/src/wirings/oauth2/wire-oauth2-credential.ts +1 -1
- package/src/wirings/queue/index.ts +0 -1
- package/src/wirings/queue/queue-runner.test.ts +52 -25
- package/src/wirings/queue/queue-runner.ts +8 -30
- package/src/wirings/queue/queue.types.ts +3 -13
- package/src/wirings/queue/register-queue-helper.ts +3 -5
- package/src/wirings/queue/validate-worker-config.test.ts +108 -0
- package/src/wirings/queue/validate-worker-config.ts +4 -1
- package/src/wirings/rpc/index.ts +2 -0
- package/src/wirings/rpc/rpc-runner.ts +92 -49
- package/src/wirings/rpc/rpc-types.ts +17 -2
- package/src/wirings/rpc/wire-addon.ts +20 -0
- package/src/wirings/scheduler/index.ts +0 -1
- package/src/wirings/scheduler/log-schedulers.ts +1 -1
- package/src/wirings/scheduler/scheduler-runner.test.ts +49 -60
- package/src/wirings/scheduler/scheduler-runner.ts +9 -56
- package/src/wirings/scheduler/scheduler.types.ts +2 -2
- package/src/wirings/secret/validate-secret-definitions.test.ts +140 -0
- package/src/wirings/trigger/pikku-trigger-service.ts +17 -39
- package/src/wirings/trigger/trigger-runner.test.ts +79 -0
- package/src/wirings/trigger/trigger-runner.ts +8 -11
- package/src/wirings/variable/validate-variable-definitions.test.ts +91 -0
- package/src/wirings/workflow/graph/graph-runner.test.ts +14 -22
- package/src/wirings/workflow/graph/template.test.ts +49 -0
- package/src/wirings/workflow/pikku-workflow-service.test.ts +15 -27
- package/src/wirings/workflow/pikku-workflow-service.ts +29 -45
- package/src/wirings/workflow/workflow-helpers.test.ts +129 -0
- package/src/wirings/workflow/workflow.types.ts +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/wirings/workflow/workflow-utils.d.ts +0 -1
- package/dist/wirings/workflow/workflow-utils.js +0 -1
- package/src/wirings/workflow/workflow-utils.ts +0 -0
|
@@ -9,13 +9,17 @@ import type {
|
|
|
9
9
|
CoreAIAgent,
|
|
10
10
|
AIAgentMemoryConfig,
|
|
11
11
|
} from './ai-agent.types.js'
|
|
12
|
-
import { pikkuState } from '../../pikku-state.js'
|
|
12
|
+
import { pikkuState, getSingletonServices } from '../../pikku-state.js'
|
|
13
13
|
import {
|
|
14
14
|
combineChannelMiddleware,
|
|
15
15
|
wrapChannelWithMiddleware,
|
|
16
16
|
} from '../channel/channel-middleware-runner.js'
|
|
17
17
|
import { randomUUID } from 'crypto'
|
|
18
18
|
import type { AIStorageService } from '../../services/ai-storage-service.js'
|
|
19
|
+
import type {
|
|
20
|
+
AIAgentRunnerParams,
|
|
21
|
+
AIAgentStepResult,
|
|
22
|
+
} from '../../services/ai-agent-runner-service.js'
|
|
19
23
|
|
|
20
24
|
import {
|
|
21
25
|
parseWorkingMemory,
|
|
@@ -35,6 +39,10 @@ import {
|
|
|
35
39
|
type StreamAIAgentOptions,
|
|
36
40
|
type StreamContext,
|
|
37
41
|
} from './ai-agent-prepare.js'
|
|
42
|
+
import {
|
|
43
|
+
createAssistantUIChannel,
|
|
44
|
+
parseAssistantUIInput,
|
|
45
|
+
} from './ai-agent-assistant-ui.js'
|
|
38
46
|
import { resolveModelConfig } from './ai-agent-model-config.js'
|
|
39
47
|
import type { AIRunStateService } from '../../services/ai-run-state-service.js'
|
|
40
48
|
import type { AIAgentRunnerService } from '../../services/ai-agent-runner-service.js'
|
|
@@ -42,6 +50,7 @@ import type { AIAgentRunnerService } from '../../services/ai-agent-runner-servic
|
|
|
42
50
|
type PersistingChannel = AIStreamChannel & {
|
|
43
51
|
fullText: string
|
|
44
52
|
flush: () => Promise<void>
|
|
53
|
+
totalUsage: { inputTokens: number; outputTokens: number; model?: string }
|
|
45
54
|
}
|
|
46
55
|
|
|
47
56
|
function createPersistingChannel(
|
|
@@ -53,6 +62,14 @@ function createPersistingChannel(
|
|
|
53
62
|
let stepText = ''
|
|
54
63
|
let stepToolCalls: AIToolCall[] = []
|
|
55
64
|
let stepToolResults: AIToolResult[] = []
|
|
65
|
+
const totalUsage: {
|
|
66
|
+
inputTokens: number
|
|
67
|
+
outputTokens: number
|
|
68
|
+
model?: string
|
|
69
|
+
} = {
|
|
70
|
+
inputTokens: 0,
|
|
71
|
+
outputTokens: 0,
|
|
72
|
+
}
|
|
56
73
|
|
|
57
74
|
const flushStep = async () => {
|
|
58
75
|
if (!storage) return
|
|
@@ -92,6 +109,9 @@ function createPersistingChannel(
|
|
|
92
109
|
get fullText() {
|
|
93
110
|
return fullText
|
|
94
111
|
},
|
|
112
|
+
get totalUsage() {
|
|
113
|
+
return totalUsage
|
|
114
|
+
},
|
|
95
115
|
flush: flushStep,
|
|
96
116
|
close: () => parent.close(),
|
|
97
117
|
send: (event: AIStreamEvent) => {
|
|
@@ -119,6 +139,9 @@ function createPersistingChannel(
|
|
|
119
139
|
})
|
|
120
140
|
break
|
|
121
141
|
case 'usage':
|
|
142
|
+
totalUsage.inputTokens += event.tokens.input
|
|
143
|
+
totalUsage.outputTokens += event.tokens.output
|
|
144
|
+
if (event.model) totalUsage.model = event.model
|
|
122
145
|
flushStep()
|
|
123
146
|
break
|
|
124
147
|
case 'done':
|
|
@@ -144,6 +167,7 @@ async function postStreamCleanup(
|
|
|
144
167
|
aiRunState: AIRunStateService,
|
|
145
168
|
runId: string
|
|
146
169
|
): Promise<void> {
|
|
170
|
+
const usage = persistingChannel.totalUsage
|
|
147
171
|
let outputText = persistingChannel.fullText
|
|
148
172
|
let outputMessages = messages
|
|
149
173
|
for (let i = aiMiddlewares.length - 1; i >= 0; i--) {
|
|
@@ -152,7 +176,10 @@ async function postStreamCleanup(
|
|
|
152
176
|
const result = await mw.modifyOutput(singletonServices, {
|
|
153
177
|
text: outputText,
|
|
154
178
|
messages: outputMessages,
|
|
155
|
-
usage: {
|
|
179
|
+
usage: {
|
|
180
|
+
inputTokens: usage.inputTokens,
|
|
181
|
+
outputTokens: usage.outputTokens,
|
|
182
|
+
},
|
|
156
183
|
})
|
|
157
184
|
outputText = result.text
|
|
158
185
|
outputMessages = result.messages
|
|
@@ -183,18 +210,254 @@ async function postStreamCleanup(
|
|
|
183
210
|
}
|
|
184
211
|
}
|
|
185
212
|
|
|
186
|
-
await aiRunState.updateRun(runId, {
|
|
213
|
+
await aiRunState.updateRun(runId, {
|
|
214
|
+
status: 'completed',
|
|
215
|
+
...(usage.model
|
|
216
|
+
? {
|
|
217
|
+
usage: {
|
|
218
|
+
inputTokens: usage.inputTokens,
|
|
219
|
+
outputTokens: usage.outputTokens,
|
|
220
|
+
model: usage.model,
|
|
221
|
+
},
|
|
222
|
+
}
|
|
223
|
+
: {}),
|
|
224
|
+
})
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
type StepLoopParams = {
|
|
228
|
+
agent: CoreAIAgent
|
|
229
|
+
runnerParams: AIAgentRunnerParams
|
|
230
|
+
maxSteps: number
|
|
231
|
+
agentRunner: AIAgentRunnerService
|
|
232
|
+
persistingChannel: PersistingChannel
|
|
233
|
+
channel: AIStreamChannel
|
|
234
|
+
runId: string
|
|
235
|
+
aiMiddlewares: PikkuAIMiddlewareHooks[]
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
type StepLoopResult =
|
|
239
|
+
| { outcome: 'done' }
|
|
240
|
+
| { outcome: 'approval'; approval: ToolApprovalRequired }
|
|
241
|
+
|
|
242
|
+
async function runStreamStepLoop(
|
|
243
|
+
params: StepLoopParams
|
|
244
|
+
): Promise<StepLoopResult> {
|
|
245
|
+
const {
|
|
246
|
+
agent,
|
|
247
|
+
runnerParams,
|
|
248
|
+
maxSteps,
|
|
249
|
+
agentRunner,
|
|
250
|
+
persistingChannel,
|
|
251
|
+
channel,
|
|
252
|
+
runId,
|
|
253
|
+
aiMiddlewares,
|
|
254
|
+
} = params
|
|
255
|
+
|
|
256
|
+
const singletonServices = getSingletonServices()
|
|
257
|
+
|
|
258
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
259
|
+
if (agent.prepareStep) {
|
|
260
|
+
let stopped = false
|
|
261
|
+
await agent.prepareStep({
|
|
262
|
+
stepNumber: step,
|
|
263
|
+
messages: runnerParams.messages,
|
|
264
|
+
tools: runnerParams.tools,
|
|
265
|
+
toolChoice: runnerParams.toolChoice,
|
|
266
|
+
model: runnerParams.model,
|
|
267
|
+
stop: () => {
|
|
268
|
+
stopped = true
|
|
269
|
+
},
|
|
270
|
+
})
|
|
271
|
+
if (stopped) break
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
channel.send({ type: 'step-start', stepNumber: step })
|
|
275
|
+
|
|
276
|
+
const stepResult = await agentRunner.stream(runnerParams, persistingChannel)
|
|
277
|
+
|
|
278
|
+
for (const mw of aiMiddlewares) {
|
|
279
|
+
if (mw.afterStep) {
|
|
280
|
+
await mw.afterStep(singletonServices, {
|
|
281
|
+
stepNumber: step,
|
|
282
|
+
text: stepResult.text,
|
|
283
|
+
toolCalls: stepResult.toolCalls,
|
|
284
|
+
toolResults: stepResult.toolResults,
|
|
285
|
+
usage: stepResult.usage,
|
|
286
|
+
finishReason: stepResult.finishReason,
|
|
287
|
+
})
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (stepResult.toolCalls.length === 0) break
|
|
292
|
+
|
|
293
|
+
const approvalNeeded = checkForApproval(
|
|
294
|
+
stepResult,
|
|
295
|
+
runnerParams.tools,
|
|
296
|
+
runId
|
|
297
|
+
)
|
|
298
|
+
if (approvalNeeded) {
|
|
299
|
+
return { outcome: 'approval', approval: approvalNeeded }
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
appendStepMessages(runnerParams, stepResult)
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return { outcome: 'done' }
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function checkForApproval(
|
|
309
|
+
stepResult: AIAgentStepResult,
|
|
310
|
+
tools: AIAgentRunnerParams['tools'],
|
|
311
|
+
runId: string
|
|
312
|
+
): ToolApprovalRequired | null {
|
|
313
|
+
for (const tc of stepResult.toolCalls) {
|
|
314
|
+
const toolDef = tools.find((t) => t.name === tc.toolName)
|
|
315
|
+
|
|
316
|
+
if (toolDef?.needsApproval) {
|
|
317
|
+
return new ToolApprovalRequired(tc.toolCallId, tc.toolName, tc.args)
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const tr = stepResult.toolResults.find(
|
|
321
|
+
(r) => r.toolCallId === tc.toolCallId
|
|
322
|
+
)
|
|
323
|
+
if (
|
|
324
|
+
tr?.result &&
|
|
325
|
+
typeof tr.result === 'object' &&
|
|
326
|
+
'__approvalRequired' in (tr.result as object)
|
|
327
|
+
) {
|
|
328
|
+
const r = tr.result as {
|
|
329
|
+
toolName: string
|
|
330
|
+
args: unknown
|
|
331
|
+
reason?: string
|
|
332
|
+
displayToolName?: string
|
|
333
|
+
displayArgs?: unknown
|
|
334
|
+
agentRunId?: string
|
|
335
|
+
}
|
|
336
|
+
return new ToolApprovalRequired(
|
|
337
|
+
tc.toolCallId,
|
|
338
|
+
r.toolName,
|
|
339
|
+
r.args,
|
|
340
|
+
r.reason,
|
|
341
|
+
r.displayToolName,
|
|
342
|
+
r.displayArgs,
|
|
343
|
+
r.agentRunId
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return null
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function appendStepMessages(
|
|
351
|
+
runnerParams: AIAgentRunnerParams,
|
|
352
|
+
stepResult: AIAgentStepResult
|
|
353
|
+
): void {
|
|
354
|
+
const assistantMsg: AIMessage = {
|
|
355
|
+
id: randomUUID(),
|
|
356
|
+
role: 'assistant',
|
|
357
|
+
content: stepResult.text || undefined,
|
|
358
|
+
toolCalls:
|
|
359
|
+
stepResult.toolCalls.length > 0
|
|
360
|
+
? stepResult.toolCalls.map((tc) => ({
|
|
361
|
+
id: tc.toolCallId,
|
|
362
|
+
name: tc.toolName,
|
|
363
|
+
args: tc.args as Record<string, unknown>,
|
|
364
|
+
}))
|
|
365
|
+
: undefined,
|
|
366
|
+
createdAt: new Date(),
|
|
367
|
+
}
|
|
368
|
+
runnerParams.messages.push(assistantMsg)
|
|
369
|
+
|
|
370
|
+
if (stepResult.toolResults.length > 0) {
|
|
371
|
+
const toolMsg: AIMessage = {
|
|
372
|
+
id: randomUUID(),
|
|
373
|
+
role: 'tool',
|
|
374
|
+
toolResults: stepResult.toolResults.map((tr) => ({
|
|
375
|
+
id: tr.toolCallId,
|
|
376
|
+
name: tr.toolName,
|
|
377
|
+
result:
|
|
378
|
+
typeof tr.result === 'string' ? tr.result : JSON.stringify(tr.result),
|
|
379
|
+
})),
|
|
380
|
+
createdAt: new Date(),
|
|
381
|
+
}
|
|
382
|
+
runnerParams.messages.push(toolMsg)
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function handleApproval(
|
|
387
|
+
err: ToolApprovalRequired,
|
|
388
|
+
runId: string,
|
|
389
|
+
channel: AIStreamChannel,
|
|
390
|
+
aiRunState: AIRunStateService,
|
|
391
|
+
persistingChannel: PersistingChannel
|
|
392
|
+
): Promise<void> {
|
|
393
|
+
return (async () => {
|
|
394
|
+
await persistingChannel.flush()
|
|
395
|
+
|
|
396
|
+
const pendingApproval = err.agentRunId
|
|
397
|
+
? {
|
|
398
|
+
type: 'agent-call' as const,
|
|
399
|
+
toolCallId: err.toolCallId,
|
|
400
|
+
agentName: err.toolName,
|
|
401
|
+
agentRunId: err.agentRunId,
|
|
402
|
+
displayToolName: err.displayToolName ?? err.toolName,
|
|
403
|
+
displayArgs: err.displayArgs ?? err.args,
|
|
404
|
+
}
|
|
405
|
+
: {
|
|
406
|
+
type: 'tool-call' as const,
|
|
407
|
+
toolCallId: err.toolCallId,
|
|
408
|
+
toolName: err.toolName,
|
|
409
|
+
args: err.args,
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
await aiRunState.updateRun(runId, {
|
|
413
|
+
status: 'suspended',
|
|
414
|
+
suspendReason: 'approval',
|
|
415
|
+
pendingApprovals: [pendingApproval],
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
const approvalEvent = {
|
|
419
|
+
type: 'approval-request' as const,
|
|
420
|
+
toolCallId: err.toolCallId,
|
|
421
|
+
toolName: err.displayToolName ?? err.toolName,
|
|
422
|
+
args: err.displayArgs ?? err.args,
|
|
423
|
+
reason: err.reason,
|
|
424
|
+
runId,
|
|
425
|
+
}
|
|
426
|
+
channel.send(approvalEvent as any)
|
|
427
|
+
channel.send({ type: 'done' })
|
|
428
|
+
channel.close()
|
|
429
|
+
})()
|
|
187
430
|
}
|
|
188
431
|
|
|
189
432
|
export async function streamAIAgent(
|
|
190
433
|
agentName: string,
|
|
191
|
-
input:
|
|
434
|
+
input:
|
|
435
|
+
| { message: string; threadId: string; resourceId: string }
|
|
436
|
+
| Record<string, unknown>,
|
|
192
437
|
channel: AIStreamChannel,
|
|
193
438
|
params: RunAIAgentParams,
|
|
194
439
|
agentSessionMap?: Map<string, string>,
|
|
195
440
|
options?: StreamAIAgentOptions
|
|
196
441
|
): Promise<void> {
|
|
197
442
|
const sessionMap = agentSessionMap ?? new Map<string, string>()
|
|
443
|
+
|
|
444
|
+
const { agent: resolvedAgentForProtocol } = resolveAgent(agentName)
|
|
445
|
+
const inputRecord = input as Record<string, unknown>
|
|
446
|
+
const useUIMessageStream =
|
|
447
|
+
resolvedAgentForProtocol.protocol === 'ui-message-stream' ||
|
|
448
|
+
Array.isArray(inputRecord.messages)
|
|
449
|
+
let normalizedInput: { message: string; threadId: string; resourceId: string }
|
|
450
|
+
if (useUIMessageStream) {
|
|
451
|
+
normalizedInput = parseAssistantUIInput(inputRecord)
|
|
452
|
+
channel = createAssistantUIChannel(channel)
|
|
453
|
+
} else {
|
|
454
|
+
normalizedInput = input as {
|
|
455
|
+
message: string
|
|
456
|
+
threadId: string
|
|
457
|
+
resourceId: string
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
198
461
|
const streamContext: StreamContext = { channel, options }
|
|
199
462
|
|
|
200
463
|
const {
|
|
@@ -207,11 +470,18 @@ export async function streamAIAgent(
|
|
|
207
470
|
threadId,
|
|
208
471
|
userMessage,
|
|
209
472
|
runnerParams,
|
|
473
|
+
maxSteps,
|
|
210
474
|
missingRpcs,
|
|
211
475
|
workingMemorySchemaName,
|
|
212
|
-
} = await prepareAgentRun(
|
|
476
|
+
} = await prepareAgentRun(
|
|
477
|
+
agentName,
|
|
478
|
+
normalizedInput,
|
|
479
|
+
params,
|
|
480
|
+
sessionMap,
|
|
481
|
+
streamContext
|
|
482
|
+
)
|
|
213
483
|
|
|
214
|
-
const
|
|
484
|
+
const singletonServices = getSingletonServices()
|
|
215
485
|
const { aiRunState } = singletonServices
|
|
216
486
|
if (!aiRunState) {
|
|
217
487
|
throw new Error('AIRunStateService not available in singletonServices')
|
|
@@ -221,7 +491,7 @@ export async function streamAIAgent(
|
|
|
221
491
|
await aiRunState.createRun({
|
|
222
492
|
agentName,
|
|
223
493
|
threadId,
|
|
224
|
-
resourceId:
|
|
494
|
+
resourceId: normalizedInput.resourceId,
|
|
225
495
|
status: 'suspended',
|
|
226
496
|
suspendReason: 'rpc-missing',
|
|
227
497
|
missingRpcs,
|
|
@@ -254,7 +524,7 @@ export async function streamAIAgent(
|
|
|
254
524
|
const runId = await aiRunState.createRun({
|
|
255
525
|
agentName,
|
|
256
526
|
threadId,
|
|
257
|
-
resourceId:
|
|
527
|
+
resourceId: normalizedInput.resourceId,
|
|
258
528
|
status: 'running',
|
|
259
529
|
usage: { inputTokens: 0, outputTokens: 0, model: agent.model },
|
|
260
530
|
createdAt: new Date(),
|
|
@@ -311,7 +581,27 @@ export async function streamAIAgent(
|
|
|
311
581
|
)
|
|
312
582
|
|
|
313
583
|
try {
|
|
314
|
-
await
|
|
584
|
+
const loopResult = await runStreamStepLoop({
|
|
585
|
+
agent,
|
|
586
|
+
runnerParams,
|
|
587
|
+
maxSteps,
|
|
588
|
+
agentRunner,
|
|
589
|
+
persistingChannel,
|
|
590
|
+
channel,
|
|
591
|
+
runId,
|
|
592
|
+
aiMiddlewares,
|
|
593
|
+
})
|
|
594
|
+
|
|
595
|
+
if (loopResult.outcome === 'approval') {
|
|
596
|
+
await handleApproval(
|
|
597
|
+
loopResult.approval,
|
|
598
|
+
runId,
|
|
599
|
+
channel,
|
|
600
|
+
aiRunState,
|
|
601
|
+
persistingChannel
|
|
602
|
+
)
|
|
603
|
+
return
|
|
604
|
+
}
|
|
315
605
|
|
|
316
606
|
await postStreamCleanup(
|
|
317
607
|
persistingChannel,
|
|
@@ -325,46 +615,23 @@ export async function streamAIAgent(
|
|
|
325
615
|
aiRunState,
|
|
326
616
|
runId
|
|
327
617
|
)
|
|
328
|
-
} catch (err) {
|
|
329
|
-
if (err instanceof ToolApprovalRequired) {
|
|
330
|
-
await persistingChannel.flush()
|
|
331
|
-
|
|
332
|
-
const pendingApproval = err.agentRunId
|
|
333
|
-
? {
|
|
334
|
-
type: 'agent-call' as const,
|
|
335
|
-
toolCallId: err.toolCallId,
|
|
336
|
-
agentName: err.toolName,
|
|
337
|
-
agentRunId: err.agentRunId,
|
|
338
|
-
displayToolName: err.displayToolName ?? err.toolName,
|
|
339
|
-
displayArgs: err.displayArgs ?? err.args,
|
|
340
|
-
}
|
|
341
|
-
: {
|
|
342
|
-
type: 'tool-call' as const,
|
|
343
|
-
toolCallId: err.toolCallId,
|
|
344
|
-
toolName: err.toolName,
|
|
345
|
-
args: err.args,
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
await aiRunState.updateRun(runId, {
|
|
349
|
-
status: 'suspended',
|
|
350
|
-
suspendReason: 'approval',
|
|
351
|
-
pendingApprovals: [pendingApproval],
|
|
352
|
-
})
|
|
353
618
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
619
|
+
channel.send({ type: 'done' })
|
|
620
|
+
channel.close()
|
|
621
|
+
} catch (err) {
|
|
622
|
+
for (const mw of aiMiddlewares) {
|
|
623
|
+
if (mw.onError) {
|
|
624
|
+
try {
|
|
625
|
+
await mw.onError(singletonServices, {
|
|
626
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
627
|
+
stepNumber: -1,
|
|
628
|
+
messages: runnerParams.messages,
|
|
629
|
+
})
|
|
630
|
+
} catch {
|
|
631
|
+
// onError hooks must not affect error flow
|
|
632
|
+
}
|
|
361
633
|
}
|
|
362
|
-
channel.send(approvalEvent as any)
|
|
363
|
-
channel.send({ type: 'done' })
|
|
364
|
-
channel.close()
|
|
365
|
-
return
|
|
366
634
|
}
|
|
367
|
-
|
|
368
635
|
await aiRunState.updateRun(runId, { status: 'failed' })
|
|
369
636
|
channel.send({
|
|
370
637
|
type: 'error',
|
|
@@ -377,6 +644,7 @@ export async function streamAIAgent(
|
|
|
377
644
|
|
|
378
645
|
export async function resumeAIAgent(
|
|
379
646
|
input: {
|
|
647
|
+
runId: string
|
|
380
648
|
toolCallId: string
|
|
381
649
|
approved: boolean
|
|
382
650
|
},
|
|
@@ -384,18 +652,25 @@ export async function resumeAIAgent(
|
|
|
384
652
|
params: RunAIAgentParams,
|
|
385
653
|
options?: StreamAIAgentOptions
|
|
386
654
|
): Promise<void> {
|
|
387
|
-
const
|
|
655
|
+
const singletonServices = getSingletonServices()
|
|
388
656
|
const { aiRunState } = singletonServices
|
|
389
657
|
if (!aiRunState) {
|
|
390
658
|
throw new Error('AIRunStateService not available in singletonServices')
|
|
391
659
|
}
|
|
392
660
|
|
|
393
|
-
const
|
|
394
|
-
if (!
|
|
395
|
-
throw new Error(`No
|
|
661
|
+
const run = await aiRunState.getRun(input.runId)
|
|
662
|
+
if (!run) {
|
|
663
|
+
throw new Error(`No run found for runId ${input.runId}`)
|
|
396
664
|
}
|
|
397
665
|
|
|
398
|
-
const
|
|
666
|
+
const pending = run.pendingApprovals?.find(
|
|
667
|
+
(p) => p.toolCallId === input.toolCallId
|
|
668
|
+
)
|
|
669
|
+
if (!pending) {
|
|
670
|
+
throw new Error(
|
|
671
|
+
`No pending approval for toolCallId ${input.toolCallId} on run ${input.runId}`
|
|
672
|
+
)
|
|
673
|
+
}
|
|
399
674
|
|
|
400
675
|
await aiRunState.resolveApproval(
|
|
401
676
|
input.toolCallId,
|
|
@@ -476,7 +751,11 @@ export async function resumeAIAgent(
|
|
|
476
751
|
})
|
|
477
752
|
|
|
478
753
|
await resumeAIAgent(
|
|
479
|
-
{
|
|
754
|
+
{
|
|
755
|
+
runId: pending.agentRunId,
|
|
756
|
+
toolCallId: subPending.toolCallId,
|
|
757
|
+
approved: true,
|
|
758
|
+
},
|
|
480
759
|
subChannel,
|
|
481
760
|
params,
|
|
482
761
|
options
|
|
@@ -510,14 +789,16 @@ export async function resumeAIAgent(
|
|
|
510
789
|
channel,
|
|
511
790
|
options: { ...options, requiresToolApproval: false },
|
|
512
791
|
}
|
|
792
|
+
const aiMiddlewaresForResume: PikkuAIMiddlewareHooks[] =
|
|
793
|
+
agent.aiMiddleware ?? []
|
|
513
794
|
const { tools } = buildToolDefs(
|
|
514
|
-
singletonServices,
|
|
515
795
|
params,
|
|
516
796
|
new Map<string, string>(),
|
|
517
797
|
run.resourceId,
|
|
518
798
|
resolvedName,
|
|
519
799
|
packageName,
|
|
520
|
-
streamContext
|
|
800
|
+
streamContext,
|
|
801
|
+
aiMiddlewaresForResume
|
|
521
802
|
)
|
|
522
803
|
|
|
523
804
|
const matchingTool = tools.find((t) => t.name === pending.toolName)
|
|
@@ -529,14 +810,10 @@ export async function resumeAIAgent(
|
|
|
529
810
|
|
|
530
811
|
const toolArgs =
|
|
531
812
|
typeof pending.args === 'string' ? JSON.parse(pending.args) : pending.args
|
|
532
|
-
const { toolApprovalReason: _ignored, ...cleanArgs } = toolArgs as Record<
|
|
533
|
-
string,
|
|
534
|
-
unknown
|
|
535
|
-
>
|
|
536
813
|
|
|
537
814
|
let toolResult: unknown
|
|
538
815
|
try {
|
|
539
|
-
toolResult = await matchingTool.execute(
|
|
816
|
+
toolResult = await matchingTool.execute(toolArgs)
|
|
540
817
|
} catch (execErr) {
|
|
541
818
|
toolResult = `Error: ${execErr instanceof Error ? execErr.message : String(execErr)}`
|
|
542
819
|
}
|
|
@@ -598,7 +875,7 @@ async function continueAfterToolResult(
|
|
|
598
875
|
aiRunState: AIRunStateService,
|
|
599
876
|
options?: StreamAIAgentOptions
|
|
600
877
|
): Promise<void> {
|
|
601
|
-
const
|
|
878
|
+
const singletonServices = getSingletonServices()
|
|
602
879
|
const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta')
|
|
603
880
|
const meta = agentsMeta[resolvedName]
|
|
604
881
|
const workingMemorySchemaName = meta?.workingMemorySchema ?? null
|
|
@@ -684,24 +961,25 @@ async function continueAfterToolResult(
|
|
|
684
961
|
|
|
685
962
|
const streamContext: StreamContext = { channel, options }
|
|
686
963
|
const resumeTools = buildToolDefs(
|
|
687
|
-
singletonServices,
|
|
688
964
|
params,
|
|
689
965
|
new Map<string, string>(),
|
|
690
966
|
run.resourceId,
|
|
691
967
|
resolvedName,
|
|
692
968
|
packageName,
|
|
693
|
-
streamContext
|
|
969
|
+
streamContext,
|
|
970
|
+
aiMiddlewares
|
|
694
971
|
).tools
|
|
695
972
|
|
|
696
973
|
const resolved = resolveModelConfig(resolvedName, agent)
|
|
974
|
+
const maxSteps = resolved.maxSteps ?? 10
|
|
697
975
|
|
|
698
|
-
const runnerParams = {
|
|
976
|
+
const runnerParams: AIAgentRunnerParams = {
|
|
699
977
|
model: resolved.model,
|
|
700
978
|
temperature: resolved.temperature,
|
|
701
979
|
instructions: modifiedInstructions,
|
|
702
980
|
messages: modifiedMessages,
|
|
703
981
|
tools: resumeTools,
|
|
704
|
-
maxSteps:
|
|
982
|
+
maxSteps: 1,
|
|
705
983
|
toolChoice: (agent.toolChoice ?? 'auto') as 'auto' | 'required' | 'none',
|
|
706
984
|
outputSchema: meta?.outputSchema
|
|
707
985
|
? pikkuState(packageName, 'misc', 'schemas').get(meta.outputSchema)
|
|
@@ -709,7 +987,27 @@ async function continueAfterToolResult(
|
|
|
709
987
|
}
|
|
710
988
|
|
|
711
989
|
try {
|
|
712
|
-
await
|
|
990
|
+
const loopResult = await runStreamStepLoop({
|
|
991
|
+
agent,
|
|
992
|
+
runnerParams,
|
|
993
|
+
maxSteps,
|
|
994
|
+
agentRunner,
|
|
995
|
+
persistingChannel,
|
|
996
|
+
channel,
|
|
997
|
+
runId: run.runId,
|
|
998
|
+
aiMiddlewares,
|
|
999
|
+
})
|
|
1000
|
+
|
|
1001
|
+
if (loopResult.outcome === 'approval') {
|
|
1002
|
+
await handleApproval(
|
|
1003
|
+
loopResult.approval,
|
|
1004
|
+
run.runId,
|
|
1005
|
+
channel,
|
|
1006
|
+
aiRunState,
|
|
1007
|
+
persistingChannel
|
|
1008
|
+
)
|
|
1009
|
+
return
|
|
1010
|
+
}
|
|
713
1011
|
|
|
714
1012
|
await postStreamCleanup(
|
|
715
1013
|
persistingChannel,
|
|
@@ -723,46 +1021,23 @@ async function continueAfterToolResult(
|
|
|
723
1021
|
aiRunState,
|
|
724
1022
|
run.runId
|
|
725
1023
|
)
|
|
726
|
-
} catch (err) {
|
|
727
|
-
if (err instanceof ToolApprovalRequired) {
|
|
728
|
-
await persistingChannel.flush()
|
|
729
|
-
|
|
730
|
-
const pendingApproval = err.agentRunId
|
|
731
|
-
? {
|
|
732
|
-
type: 'agent-call' as const,
|
|
733
|
-
toolCallId: err.toolCallId,
|
|
734
|
-
agentName: err.toolName,
|
|
735
|
-
agentRunId: err.agentRunId,
|
|
736
|
-
displayToolName: err.displayToolName ?? err.toolName,
|
|
737
|
-
displayArgs: err.displayArgs ?? err.args,
|
|
738
|
-
}
|
|
739
|
-
: {
|
|
740
|
-
type: 'tool-call' as const,
|
|
741
|
-
toolCallId: err.toolCallId,
|
|
742
|
-
toolName: err.toolName,
|
|
743
|
-
args: err.args,
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
await aiRunState.updateRun(run.runId, {
|
|
747
|
-
status: 'suspended',
|
|
748
|
-
suspendReason: 'approval',
|
|
749
|
-
pendingApprovals: [pendingApproval],
|
|
750
|
-
})
|
|
751
1024
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
1025
|
+
channel.send({ type: 'done' })
|
|
1026
|
+
channel.close()
|
|
1027
|
+
} catch (err) {
|
|
1028
|
+
for (const mw of aiMiddlewares) {
|
|
1029
|
+
if (mw.onError) {
|
|
1030
|
+
try {
|
|
1031
|
+
await mw.onError(singletonServices, {
|
|
1032
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
1033
|
+
stepNumber: -1,
|
|
1034
|
+
messages: runnerParams.messages,
|
|
1035
|
+
})
|
|
1036
|
+
} catch {
|
|
1037
|
+
// onError hooks must not affect error flow
|
|
1038
|
+
}
|
|
759
1039
|
}
|
|
760
|
-
channel.send(approvalEvent as any)
|
|
761
|
-
channel.send({ type: 'done' })
|
|
762
|
-
channel.close()
|
|
763
|
-
return
|
|
764
1040
|
}
|
|
765
|
-
|
|
766
1041
|
await aiRunState.updateRun(run.runId, { status: 'failed' })
|
|
767
1042
|
channel.send({
|
|
768
1043
|
type: 'error',
|