@pikku/core 0.12.0 → 0.12.2
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 +40 -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/middleware-runner.js +1 -0
- package/dist/permissions.d.ts +2 -2
- package/dist/permissions.js +1 -0
- package/dist/pikku-state.d.ts +9 -8
- package/dist/pikku-state.js +34 -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/gateway-service.d.ts +19 -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 +5 -2
- package/dist/services/index.js +2 -0
- package/dist/services/local-content.d.ts +2 -1
- package/dist/services/local-content.js +6 -1
- package/dist/services/local-gateway-service.d.ts +22 -0
- package/dist/services/local-gateway-service.js +51 -0
- 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 +27 -19
- package/dist/types/state.types.d.ts +22 -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 +168 -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-memory.js +13 -2
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +4 -5
- package/dist/wirings/ai-agent/ai-agent-prepare.js +80 -31
- 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 +263 -89
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +96 -4
- 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 +7 -4
- package/dist/wirings/channel/channel-handler.js +15 -5
- package/dist/wirings/channel/channel-middleware-runner.js +1 -0
- 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 +10 -6
- package/dist/wirings/channel/index.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-handler.d.ts +7 -0
- package/dist/wirings/channel/local/local-channel-handler.js +17 -0
- package/dist/wirings/channel/local/local-channel-runner.d.ts +7 -2
- package/dist/wirings/channel/local/local-channel-runner.js +18 -4
- 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 +2 -1
- package/dist/wirings/channel/pikku-abstract-channel-handler.js +1 -0
- package/dist/wirings/channel/serverless/serverless-channel-runner.d.ts +4 -4
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +26 -20
- 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-runner.js +3 -0
- package/dist/wirings/cli/cli.types.d.ts +3 -3
- package/dist/wirings/cli/command-parser.d.ts +1 -1
- package/dist/wirings/gateway/gateway-runner.d.ts +24 -0
- package/dist/wirings/gateway/gateway-runner.js +325 -0
- package/dist/wirings/gateway/gateway.types.d.ts +127 -0
- package/dist/wirings/gateway/index.d.ts +2 -0
- package/dist/wirings/gateway/index.js +1 -0
- package/dist/wirings/http/http-runner.d.ts +9 -9
- package/dist/wirings/http/http-runner.js +36 -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 +4 -2
- 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 +2 -1
- package/src/permissions.test.ts +2 -2
- package/src/permissions.ts +3 -2
- package/src/pikku-state.test.ts +224 -0
- package/src/pikku-state.ts +45 -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/gateway-service.ts +20 -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 +4 -1
- package/src/services/local-content.ts +9 -3
- package/src/services/local-gateway-service.ts +62 -0
- 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 +28 -19
- package/src/types/state.types.ts +32 -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 +238 -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-memory.ts +10 -1
- package/src/wirings/ai-agent/ai-agent-model-config.test.ts +115 -0
- package/src/wirings/ai-agent/ai-agent-prepare.ts +98 -46
- 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 +390 -104
- package/src/wirings/ai-agent/ai-agent.types.ts +91 -4
- package/src/wirings/ai-agent/index.ts +13 -0
- package/src/wirings/channel/channel-common.ts +2 -2
- package/src/wirings/channel/channel-handler.ts +43 -11
- package/src/wirings/channel/channel-middleware-runner.ts +1 -0
- 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 +15 -8
- package/src/wirings/channel/index.ts +1 -0
- package/src/wirings/channel/local/local-channel-handler.ts +26 -0
- package/src/wirings/channel/local/local-channel-runner.test.ts +19 -12
- package/src/wirings/channel/local/local-channel-runner.ts +33 -14
- 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.test.ts +2 -0
- package/src/wirings/channel/pikku-abstract-channel-handler.ts +8 -1
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +38 -33
- 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 +14 -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/gateway/gateway-runner.test.ts +474 -0
- package/src/wirings/gateway/gateway-runner.ts +411 -0
- package/src/wirings/gateway/gateway.types.ts +149 -0
- package/src/wirings/gateway/index.ts +13 -0
- 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 +46 -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/src/wirings/workflow/workflow-utils.ts +0 -0
- /package/dist/{wirings/workflow/workflow-utils.d.ts → services/gateway-service.js} +0 -0
- /package/dist/wirings/{workflow/workflow-utils.js → gateway/gateway.types.js} +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,8 +109,12 @@ 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(),
|
|
117
|
+
sendBinary: (data) => parent.sendBinary(data),
|
|
97
118
|
send: (event: AIStreamEvent) => {
|
|
98
119
|
if (storage) {
|
|
99
120
|
switch (event.type) {
|
|
@@ -119,6 +140,9 @@ function createPersistingChannel(
|
|
|
119
140
|
})
|
|
120
141
|
break
|
|
121
142
|
case 'usage':
|
|
143
|
+
totalUsage.inputTokens += event.tokens.input
|
|
144
|
+
totalUsage.outputTokens += event.tokens.output
|
|
145
|
+
if (event.model) totalUsage.model = event.model
|
|
122
146
|
flushStep()
|
|
123
147
|
break
|
|
124
148
|
case 'done':
|
|
@@ -144,6 +168,7 @@ async function postStreamCleanup(
|
|
|
144
168
|
aiRunState: AIRunStateService,
|
|
145
169
|
runId: string
|
|
146
170
|
): Promise<void> {
|
|
171
|
+
const usage = persistingChannel.totalUsage
|
|
147
172
|
let outputText = persistingChannel.fullText
|
|
148
173
|
let outputMessages = messages
|
|
149
174
|
for (let i = aiMiddlewares.length - 1; i >= 0; i--) {
|
|
@@ -152,7 +177,10 @@ async function postStreamCleanup(
|
|
|
152
177
|
const result = await mw.modifyOutput(singletonServices, {
|
|
153
178
|
text: outputText,
|
|
154
179
|
messages: outputMessages,
|
|
155
|
-
usage: {
|
|
180
|
+
usage: {
|
|
181
|
+
inputTokens: usage.inputTokens,
|
|
182
|
+
outputTokens: usage.outputTokens,
|
|
183
|
+
},
|
|
156
184
|
})
|
|
157
185
|
outputText = result.text
|
|
158
186
|
outputMessages = result.messages
|
|
@@ -183,18 +211,254 @@ async function postStreamCleanup(
|
|
|
183
211
|
}
|
|
184
212
|
}
|
|
185
213
|
|
|
186
|
-
await aiRunState.updateRun(runId, {
|
|
214
|
+
await aiRunState.updateRun(runId, {
|
|
215
|
+
status: 'completed',
|
|
216
|
+
...(usage.model
|
|
217
|
+
? {
|
|
218
|
+
usage: {
|
|
219
|
+
inputTokens: usage.inputTokens,
|
|
220
|
+
outputTokens: usage.outputTokens,
|
|
221
|
+
model: usage.model,
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
: {}),
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
type StepLoopParams = {
|
|
229
|
+
agent: CoreAIAgent
|
|
230
|
+
runnerParams: AIAgentRunnerParams
|
|
231
|
+
maxSteps: number
|
|
232
|
+
agentRunner: AIAgentRunnerService
|
|
233
|
+
persistingChannel: PersistingChannel
|
|
234
|
+
channel: AIStreamChannel
|
|
235
|
+
runId: string
|
|
236
|
+
aiMiddlewares: PikkuAIMiddlewareHooks[]
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
type StepLoopResult =
|
|
240
|
+
| { outcome: 'done' }
|
|
241
|
+
| { outcome: 'approval'; approval: ToolApprovalRequired }
|
|
242
|
+
|
|
243
|
+
async function runStreamStepLoop(
|
|
244
|
+
params: StepLoopParams
|
|
245
|
+
): Promise<StepLoopResult> {
|
|
246
|
+
const {
|
|
247
|
+
agent,
|
|
248
|
+
runnerParams,
|
|
249
|
+
maxSteps,
|
|
250
|
+
agentRunner,
|
|
251
|
+
persistingChannel,
|
|
252
|
+
channel,
|
|
253
|
+
runId,
|
|
254
|
+
aiMiddlewares,
|
|
255
|
+
} = params
|
|
256
|
+
|
|
257
|
+
const singletonServices = getSingletonServices()
|
|
258
|
+
|
|
259
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
260
|
+
if (agent.prepareStep) {
|
|
261
|
+
let stopped = false
|
|
262
|
+
await agent.prepareStep({
|
|
263
|
+
stepNumber: step,
|
|
264
|
+
messages: runnerParams.messages,
|
|
265
|
+
tools: runnerParams.tools,
|
|
266
|
+
toolChoice: runnerParams.toolChoice,
|
|
267
|
+
model: runnerParams.model,
|
|
268
|
+
stop: () => {
|
|
269
|
+
stopped = true
|
|
270
|
+
},
|
|
271
|
+
})
|
|
272
|
+
if (stopped) break
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
channel.send({ type: 'step-start', stepNumber: step })
|
|
276
|
+
|
|
277
|
+
const stepResult = await agentRunner.stream(runnerParams, persistingChannel)
|
|
278
|
+
|
|
279
|
+
for (const mw of aiMiddlewares) {
|
|
280
|
+
if (mw.afterStep) {
|
|
281
|
+
await mw.afterStep(singletonServices, {
|
|
282
|
+
stepNumber: step,
|
|
283
|
+
text: stepResult.text,
|
|
284
|
+
toolCalls: stepResult.toolCalls,
|
|
285
|
+
toolResults: stepResult.toolResults,
|
|
286
|
+
usage: stepResult.usage,
|
|
287
|
+
finishReason: stepResult.finishReason,
|
|
288
|
+
})
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (stepResult.toolCalls.length === 0) break
|
|
293
|
+
|
|
294
|
+
const approvalNeeded = checkForApproval(
|
|
295
|
+
stepResult,
|
|
296
|
+
runnerParams.tools,
|
|
297
|
+
runId
|
|
298
|
+
)
|
|
299
|
+
if (approvalNeeded) {
|
|
300
|
+
return { outcome: 'approval', approval: approvalNeeded }
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
appendStepMessages(runnerParams, stepResult)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return { outcome: 'done' }
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
function checkForApproval(
|
|
310
|
+
stepResult: AIAgentStepResult,
|
|
311
|
+
tools: AIAgentRunnerParams['tools'],
|
|
312
|
+
runId: string
|
|
313
|
+
): ToolApprovalRequired | null {
|
|
314
|
+
for (const tc of stepResult.toolCalls) {
|
|
315
|
+
const toolDef = tools.find((t) => t.name === tc.toolName)
|
|
316
|
+
|
|
317
|
+
if (toolDef?.needsApproval) {
|
|
318
|
+
return new ToolApprovalRequired(tc.toolCallId, tc.toolName, tc.args)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
const tr = stepResult.toolResults.find(
|
|
322
|
+
(r) => r.toolCallId === tc.toolCallId
|
|
323
|
+
)
|
|
324
|
+
if (
|
|
325
|
+
tr?.result &&
|
|
326
|
+
typeof tr.result === 'object' &&
|
|
327
|
+
'__approvalRequired' in (tr.result as object)
|
|
328
|
+
) {
|
|
329
|
+
const r = tr.result as {
|
|
330
|
+
toolName: string
|
|
331
|
+
args: unknown
|
|
332
|
+
reason?: string
|
|
333
|
+
displayToolName?: string
|
|
334
|
+
displayArgs?: unknown
|
|
335
|
+
agentRunId?: string
|
|
336
|
+
}
|
|
337
|
+
return new ToolApprovalRequired(
|
|
338
|
+
tc.toolCallId,
|
|
339
|
+
r.toolName,
|
|
340
|
+
r.args,
|
|
341
|
+
r.reason,
|
|
342
|
+
r.displayToolName,
|
|
343
|
+
r.displayArgs,
|
|
344
|
+
r.agentRunId
|
|
345
|
+
)
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return null
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function appendStepMessages(
|
|
352
|
+
runnerParams: AIAgentRunnerParams,
|
|
353
|
+
stepResult: AIAgentStepResult
|
|
354
|
+
): void {
|
|
355
|
+
const assistantMsg: AIMessage = {
|
|
356
|
+
id: randomUUID(),
|
|
357
|
+
role: 'assistant',
|
|
358
|
+
content: stepResult.text || undefined,
|
|
359
|
+
toolCalls:
|
|
360
|
+
stepResult.toolCalls.length > 0
|
|
361
|
+
? stepResult.toolCalls.map((tc) => ({
|
|
362
|
+
id: tc.toolCallId,
|
|
363
|
+
name: tc.toolName,
|
|
364
|
+
args: tc.args as Record<string, unknown>,
|
|
365
|
+
}))
|
|
366
|
+
: undefined,
|
|
367
|
+
createdAt: new Date(),
|
|
368
|
+
}
|
|
369
|
+
runnerParams.messages.push(assistantMsg)
|
|
370
|
+
|
|
371
|
+
if (stepResult.toolResults.length > 0) {
|
|
372
|
+
const toolMsg: AIMessage = {
|
|
373
|
+
id: randomUUID(),
|
|
374
|
+
role: 'tool',
|
|
375
|
+
toolResults: stepResult.toolResults.map((tr) => ({
|
|
376
|
+
id: tr.toolCallId,
|
|
377
|
+
name: tr.toolName,
|
|
378
|
+
result:
|
|
379
|
+
typeof tr.result === 'string' ? tr.result : JSON.stringify(tr.result),
|
|
380
|
+
})),
|
|
381
|
+
createdAt: new Date(),
|
|
382
|
+
}
|
|
383
|
+
runnerParams.messages.push(toolMsg)
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
function handleApproval(
|
|
388
|
+
err: ToolApprovalRequired,
|
|
389
|
+
runId: string,
|
|
390
|
+
channel: AIStreamChannel,
|
|
391
|
+
aiRunState: AIRunStateService,
|
|
392
|
+
persistingChannel: PersistingChannel
|
|
393
|
+
): Promise<void> {
|
|
394
|
+
return (async () => {
|
|
395
|
+
await persistingChannel.flush()
|
|
396
|
+
|
|
397
|
+
const pendingApproval = err.agentRunId
|
|
398
|
+
? {
|
|
399
|
+
type: 'agent-call' as const,
|
|
400
|
+
toolCallId: err.toolCallId,
|
|
401
|
+
agentName: err.toolName,
|
|
402
|
+
agentRunId: err.agentRunId,
|
|
403
|
+
displayToolName: err.displayToolName ?? err.toolName,
|
|
404
|
+
displayArgs: err.displayArgs ?? err.args,
|
|
405
|
+
}
|
|
406
|
+
: {
|
|
407
|
+
type: 'tool-call' as const,
|
|
408
|
+
toolCallId: err.toolCallId,
|
|
409
|
+
toolName: err.toolName,
|
|
410
|
+
args: err.args,
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
await aiRunState.updateRun(runId, {
|
|
414
|
+
status: 'suspended',
|
|
415
|
+
suspendReason: 'approval',
|
|
416
|
+
pendingApprovals: [pendingApproval],
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
const approvalEvent = {
|
|
420
|
+
type: 'approval-request' as const,
|
|
421
|
+
toolCallId: err.toolCallId,
|
|
422
|
+
toolName: err.displayToolName ?? err.toolName,
|
|
423
|
+
args: err.displayArgs ?? err.args,
|
|
424
|
+
reason: err.reason,
|
|
425
|
+
runId,
|
|
426
|
+
}
|
|
427
|
+
channel.send(approvalEvent as any)
|
|
428
|
+
channel.send({ type: 'done' })
|
|
429
|
+
channel.close()
|
|
430
|
+
})()
|
|
187
431
|
}
|
|
188
432
|
|
|
189
433
|
export async function streamAIAgent(
|
|
190
434
|
agentName: string,
|
|
191
|
-
input:
|
|
435
|
+
input:
|
|
436
|
+
| { message: string; threadId: string; resourceId: string }
|
|
437
|
+
| Record<string, unknown>,
|
|
192
438
|
channel: AIStreamChannel,
|
|
193
439
|
params: RunAIAgentParams,
|
|
194
440
|
agentSessionMap?: Map<string, string>,
|
|
195
441
|
options?: StreamAIAgentOptions
|
|
196
442
|
): Promise<void> {
|
|
197
443
|
const sessionMap = agentSessionMap ?? new Map<string, string>()
|
|
444
|
+
|
|
445
|
+
const { agent: resolvedAgentForProtocol } = resolveAgent(agentName)
|
|
446
|
+
const inputRecord = input as Record<string, unknown>
|
|
447
|
+
const useUIMessageStream =
|
|
448
|
+
resolvedAgentForProtocol.protocol === 'ui-message-stream' ||
|
|
449
|
+
Array.isArray(inputRecord.messages)
|
|
450
|
+
let normalizedInput: { message: string; threadId: string; resourceId: string }
|
|
451
|
+
if (useUIMessageStream) {
|
|
452
|
+
normalizedInput = parseAssistantUIInput(inputRecord)
|
|
453
|
+
channel = createAssistantUIChannel(channel)
|
|
454
|
+
} else {
|
|
455
|
+
normalizedInput = input as {
|
|
456
|
+
message: string
|
|
457
|
+
threadId: string
|
|
458
|
+
resourceId: string
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
|
|
198
462
|
const streamContext: StreamContext = { channel, options }
|
|
199
463
|
|
|
200
464
|
const {
|
|
@@ -207,11 +471,18 @@ export async function streamAIAgent(
|
|
|
207
471
|
threadId,
|
|
208
472
|
userMessage,
|
|
209
473
|
runnerParams,
|
|
474
|
+
maxSteps,
|
|
210
475
|
missingRpcs,
|
|
211
476
|
workingMemorySchemaName,
|
|
212
|
-
} = await prepareAgentRun(
|
|
477
|
+
} = await prepareAgentRun(
|
|
478
|
+
agentName,
|
|
479
|
+
normalizedInput,
|
|
480
|
+
params,
|
|
481
|
+
sessionMap,
|
|
482
|
+
streamContext
|
|
483
|
+
)
|
|
213
484
|
|
|
214
|
-
const
|
|
485
|
+
const singletonServices = getSingletonServices()
|
|
215
486
|
const { aiRunState } = singletonServices
|
|
216
487
|
if (!aiRunState) {
|
|
217
488
|
throw new Error('AIRunStateService not available in singletonServices')
|
|
@@ -221,7 +492,7 @@ export async function streamAIAgent(
|
|
|
221
492
|
await aiRunState.createRun({
|
|
222
493
|
agentName,
|
|
223
494
|
threadId,
|
|
224
|
-
resourceId:
|
|
495
|
+
resourceId: normalizedInput.resourceId,
|
|
225
496
|
status: 'suspended',
|
|
226
497
|
suspendReason: 'rpc-missing',
|
|
227
498
|
missingRpcs,
|
|
@@ -254,7 +525,7 @@ export async function streamAIAgent(
|
|
|
254
525
|
const runId = await aiRunState.createRun({
|
|
255
526
|
agentName,
|
|
256
527
|
threadId,
|
|
257
|
-
resourceId:
|
|
528
|
+
resourceId: normalizedInput.resourceId,
|
|
258
529
|
status: 'running',
|
|
259
530
|
usage: { inputTokens: 0, outputTokens: 0, model: agent.model },
|
|
260
531
|
createdAt: new Date(),
|
|
@@ -277,7 +548,12 @@ export async function streamAIAgent(
|
|
|
277
548
|
allEvents,
|
|
278
549
|
state,
|
|
279
550
|
})
|
|
280
|
-
if (result
|
|
551
|
+
if (result == null) return
|
|
552
|
+
if (Array.isArray(result)) {
|
|
553
|
+
for (const r of result) await next(r)
|
|
554
|
+
} else {
|
|
555
|
+
await next(result)
|
|
556
|
+
}
|
|
281
557
|
}
|
|
282
558
|
})
|
|
283
559
|
|
|
@@ -311,7 +587,27 @@ export async function streamAIAgent(
|
|
|
311
587
|
)
|
|
312
588
|
|
|
313
589
|
try {
|
|
314
|
-
await
|
|
590
|
+
const loopResult = await runStreamStepLoop({
|
|
591
|
+
agent,
|
|
592
|
+
runnerParams,
|
|
593
|
+
maxSteps,
|
|
594
|
+
agentRunner,
|
|
595
|
+
persistingChannel,
|
|
596
|
+
channel,
|
|
597
|
+
runId,
|
|
598
|
+
aiMiddlewares,
|
|
599
|
+
})
|
|
600
|
+
|
|
601
|
+
if (loopResult.outcome === 'approval') {
|
|
602
|
+
await handleApproval(
|
|
603
|
+
loopResult.approval,
|
|
604
|
+
runId,
|
|
605
|
+
channel,
|
|
606
|
+
aiRunState,
|
|
607
|
+
persistingChannel
|
|
608
|
+
)
|
|
609
|
+
return
|
|
610
|
+
}
|
|
315
611
|
|
|
316
612
|
await postStreamCleanup(
|
|
317
613
|
persistingChannel,
|
|
@@ -325,46 +621,23 @@ export async function streamAIAgent(
|
|
|
325
621
|
aiRunState,
|
|
326
622
|
runId
|
|
327
623
|
)
|
|
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
624
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
625
|
+
channel.send({ type: 'done' })
|
|
626
|
+
channel.close()
|
|
627
|
+
} catch (err) {
|
|
628
|
+
for (const mw of aiMiddlewares) {
|
|
629
|
+
if (mw.onError) {
|
|
630
|
+
try {
|
|
631
|
+
await mw.onError(singletonServices, {
|
|
632
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
633
|
+
stepNumber: -1,
|
|
634
|
+
messages: runnerParams.messages,
|
|
635
|
+
})
|
|
636
|
+
} catch {
|
|
637
|
+
// onError hooks must not affect error flow
|
|
638
|
+
}
|
|
361
639
|
}
|
|
362
|
-
channel.send(approvalEvent as any)
|
|
363
|
-
channel.send({ type: 'done' })
|
|
364
|
-
channel.close()
|
|
365
|
-
return
|
|
366
640
|
}
|
|
367
|
-
|
|
368
641
|
await aiRunState.updateRun(runId, { status: 'failed' })
|
|
369
642
|
channel.send({
|
|
370
643
|
type: 'error',
|
|
@@ -377,6 +650,7 @@ export async function streamAIAgent(
|
|
|
377
650
|
|
|
378
651
|
export async function resumeAIAgent(
|
|
379
652
|
input: {
|
|
653
|
+
runId: string
|
|
380
654
|
toolCallId: string
|
|
381
655
|
approved: boolean
|
|
382
656
|
},
|
|
@@ -384,18 +658,25 @@ export async function resumeAIAgent(
|
|
|
384
658
|
params: RunAIAgentParams,
|
|
385
659
|
options?: StreamAIAgentOptions
|
|
386
660
|
): Promise<void> {
|
|
387
|
-
const
|
|
661
|
+
const singletonServices = getSingletonServices()
|
|
388
662
|
const { aiRunState } = singletonServices
|
|
389
663
|
if (!aiRunState) {
|
|
390
664
|
throw new Error('AIRunStateService not available in singletonServices')
|
|
391
665
|
}
|
|
392
666
|
|
|
393
|
-
const
|
|
394
|
-
if (!
|
|
395
|
-
throw new Error(`No
|
|
667
|
+
const run = await aiRunState.getRun(input.runId)
|
|
668
|
+
if (!run) {
|
|
669
|
+
throw new Error(`No run found for runId ${input.runId}`)
|
|
396
670
|
}
|
|
397
671
|
|
|
398
|
-
const
|
|
672
|
+
const pending = run.pendingApprovals?.find(
|
|
673
|
+
(p) => p.toolCallId === input.toolCallId
|
|
674
|
+
)
|
|
675
|
+
if (!pending) {
|
|
676
|
+
throw new Error(
|
|
677
|
+
`No pending approval for toolCallId ${input.toolCallId} on run ${input.runId}`
|
|
678
|
+
)
|
|
679
|
+
}
|
|
399
680
|
|
|
400
681
|
await aiRunState.resolveApproval(
|
|
401
682
|
input.toolCallId,
|
|
@@ -476,7 +757,11 @@ export async function resumeAIAgent(
|
|
|
476
757
|
})
|
|
477
758
|
|
|
478
759
|
await resumeAIAgent(
|
|
479
|
-
{
|
|
760
|
+
{
|
|
761
|
+
runId: pending.agentRunId,
|
|
762
|
+
toolCallId: subPending.toolCallId,
|
|
763
|
+
approved: true,
|
|
764
|
+
},
|
|
480
765
|
subChannel,
|
|
481
766
|
params,
|
|
482
767
|
options
|
|
@@ -510,14 +795,16 @@ export async function resumeAIAgent(
|
|
|
510
795
|
channel,
|
|
511
796
|
options: { ...options, requiresToolApproval: false },
|
|
512
797
|
}
|
|
798
|
+
const aiMiddlewaresForResume: PikkuAIMiddlewareHooks[] =
|
|
799
|
+
agent.aiMiddleware ?? []
|
|
513
800
|
const { tools } = buildToolDefs(
|
|
514
|
-
singletonServices,
|
|
515
801
|
params,
|
|
516
802
|
new Map<string, string>(),
|
|
517
803
|
run.resourceId,
|
|
518
804
|
resolvedName,
|
|
519
805
|
packageName,
|
|
520
|
-
streamContext
|
|
806
|
+
streamContext,
|
|
807
|
+
aiMiddlewaresForResume
|
|
521
808
|
)
|
|
522
809
|
|
|
523
810
|
const matchingTool = tools.find((t) => t.name === pending.toolName)
|
|
@@ -529,14 +816,10 @@ export async function resumeAIAgent(
|
|
|
529
816
|
|
|
530
817
|
const toolArgs =
|
|
531
818
|
typeof pending.args === 'string' ? JSON.parse(pending.args) : pending.args
|
|
532
|
-
const { toolApprovalReason: _ignored, ...cleanArgs } = toolArgs as Record<
|
|
533
|
-
string,
|
|
534
|
-
unknown
|
|
535
|
-
>
|
|
536
819
|
|
|
537
820
|
let toolResult: unknown
|
|
538
821
|
try {
|
|
539
|
-
toolResult = await matchingTool.execute(
|
|
822
|
+
toolResult = await matchingTool.execute(toolArgs)
|
|
540
823
|
} catch (execErr) {
|
|
541
824
|
toolResult = `Error: ${execErr instanceof Error ? execErr.message : String(execErr)}`
|
|
542
825
|
}
|
|
@@ -598,7 +881,7 @@ async function continueAfterToolResult(
|
|
|
598
881
|
aiRunState: AIRunStateService,
|
|
599
882
|
options?: StreamAIAgentOptions
|
|
600
883
|
): Promise<void> {
|
|
601
|
-
const
|
|
884
|
+
const singletonServices = getSingletonServices()
|
|
602
885
|
const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta')
|
|
603
886
|
const meta = agentsMeta[resolvedName]
|
|
604
887
|
const workingMemorySchemaName = meta?.workingMemorySchema ?? null
|
|
@@ -651,7 +934,12 @@ async function continueAfterToolResult(
|
|
|
651
934
|
allEvents,
|
|
652
935
|
state,
|
|
653
936
|
})
|
|
654
|
-
if (result
|
|
937
|
+
if (result == null) return
|
|
938
|
+
if (Array.isArray(result)) {
|
|
939
|
+
for (const r of result) await next(r)
|
|
940
|
+
} else {
|
|
941
|
+
await next(result)
|
|
942
|
+
}
|
|
655
943
|
}
|
|
656
944
|
})
|
|
657
945
|
|
|
@@ -684,24 +972,25 @@ async function continueAfterToolResult(
|
|
|
684
972
|
|
|
685
973
|
const streamContext: StreamContext = { channel, options }
|
|
686
974
|
const resumeTools = buildToolDefs(
|
|
687
|
-
singletonServices,
|
|
688
975
|
params,
|
|
689
976
|
new Map<string, string>(),
|
|
690
977
|
run.resourceId,
|
|
691
978
|
resolvedName,
|
|
692
979
|
packageName,
|
|
693
|
-
streamContext
|
|
980
|
+
streamContext,
|
|
981
|
+
aiMiddlewares
|
|
694
982
|
).tools
|
|
695
983
|
|
|
696
984
|
const resolved = resolveModelConfig(resolvedName, agent)
|
|
985
|
+
const maxSteps = resolved.maxSteps ?? 10
|
|
697
986
|
|
|
698
|
-
const runnerParams = {
|
|
987
|
+
const runnerParams: AIAgentRunnerParams = {
|
|
699
988
|
model: resolved.model,
|
|
700
989
|
temperature: resolved.temperature,
|
|
701
990
|
instructions: modifiedInstructions,
|
|
702
991
|
messages: modifiedMessages,
|
|
703
992
|
tools: resumeTools,
|
|
704
|
-
maxSteps:
|
|
993
|
+
maxSteps: 1,
|
|
705
994
|
toolChoice: (agent.toolChoice ?? 'auto') as 'auto' | 'required' | 'none',
|
|
706
995
|
outputSchema: meta?.outputSchema
|
|
707
996
|
? pikkuState(packageName, 'misc', 'schemas').get(meta.outputSchema)
|
|
@@ -709,7 +998,27 @@ async function continueAfterToolResult(
|
|
|
709
998
|
}
|
|
710
999
|
|
|
711
1000
|
try {
|
|
712
|
-
await
|
|
1001
|
+
const loopResult = await runStreamStepLoop({
|
|
1002
|
+
agent,
|
|
1003
|
+
runnerParams,
|
|
1004
|
+
maxSteps,
|
|
1005
|
+
agentRunner,
|
|
1006
|
+
persistingChannel,
|
|
1007
|
+
channel,
|
|
1008
|
+
runId: run.runId,
|
|
1009
|
+
aiMiddlewares,
|
|
1010
|
+
})
|
|
1011
|
+
|
|
1012
|
+
if (loopResult.outcome === 'approval') {
|
|
1013
|
+
await handleApproval(
|
|
1014
|
+
loopResult.approval,
|
|
1015
|
+
run.runId,
|
|
1016
|
+
channel,
|
|
1017
|
+
aiRunState,
|
|
1018
|
+
persistingChannel
|
|
1019
|
+
)
|
|
1020
|
+
return
|
|
1021
|
+
}
|
|
713
1022
|
|
|
714
1023
|
await postStreamCleanup(
|
|
715
1024
|
persistingChannel,
|
|
@@ -723,46 +1032,23 @@ async function continueAfterToolResult(
|
|
|
723
1032
|
aiRunState,
|
|
724
1033
|
run.runId
|
|
725
1034
|
)
|
|
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
1035
|
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
1036
|
+
channel.send({ type: 'done' })
|
|
1037
|
+
channel.close()
|
|
1038
|
+
} catch (err) {
|
|
1039
|
+
for (const mw of aiMiddlewares) {
|
|
1040
|
+
if (mw.onError) {
|
|
1041
|
+
try {
|
|
1042
|
+
await mw.onError(singletonServices, {
|
|
1043
|
+
error: err instanceof Error ? err : new Error(String(err)),
|
|
1044
|
+
stepNumber: -1,
|
|
1045
|
+
messages: runnerParams.messages,
|
|
1046
|
+
})
|
|
1047
|
+
} catch {
|
|
1048
|
+
// onError hooks must not affect error flow
|
|
1049
|
+
}
|
|
759
1050
|
}
|
|
760
|
-
channel.send(approvalEvent as any)
|
|
761
|
-
channel.send({ type: 'done' })
|
|
762
|
-
channel.close()
|
|
763
|
-
return
|
|
764
1051
|
}
|
|
765
|
-
|
|
766
1052
|
await aiRunState.updateRun(run.runId, { status: 'failed' })
|
|
767
1053
|
channel.send({
|
|
768
1054
|
type: 'error',
|