@pikku/core 0.12.2 → 0.12.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/CHANGELOG.md +18 -0
- package/dist/crypto-utils.d.ts +10 -0
- package/dist/crypto-utils.js +62 -0
- package/dist/function/function-runner.js +4 -4
- package/dist/function/functions.types.d.ts +26 -1
- package/dist/function/functions.types.js +16 -0
- package/dist/handle-error.d.ts +1 -1
- package/dist/handle-error.js +7 -3
- package/dist/index.d.ts +14 -2
- package/dist/index.js +1 -1
- package/dist/pikku-state.js +3 -1
- package/dist/schema.js +1 -1
- package/dist/services/in-memory-workflow-service.d.ts +8 -2
- package/dist/services/in-memory-workflow-service.js +28 -1
- package/dist/services/workflow-service.d.ts +8 -2
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +1 -0
- package/dist/testing/service-tests.d.ts +31 -0
- package/dist/testing/service-tests.js +598 -0
- package/dist/types/core.types.d.ts +9 -1
- package/dist/types/state.types.d.ts +4 -2
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.js +23 -0
- package/dist/wirings/ai-agent/agent-dynamic-workflow.d.ts +6 -0
- package/dist/wirings/ai-agent/agent-dynamic-workflow.js +348 -0
- package/dist/wirings/ai-agent/ai-agent-memory.d.ts +1 -1
- package/dist/wirings/ai-agent/ai-agent-memory.js +6 -5
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -7
- package/dist/wirings/ai-agent/ai-agent-prepare.js +127 -47
- package/dist/wirings/ai-agent/ai-agent-runner.d.ts +4 -0
- package/dist/wirings/ai-agent/ai-agent-runner.js +381 -27
- package/dist/wirings/ai-agent/ai-agent-stream.d.ts +7 -2
- package/dist/wirings/ai-agent/ai-agent-stream.js +109 -46
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +22 -1
- package/dist/wirings/ai-agent/index.d.ts +1 -2
- package/dist/wirings/ai-agent/index.js +1 -2
- package/dist/wirings/channel/channel-handler.js +5 -1
- package/dist/wirings/channel/channel.types.d.ts +1 -7
- package/dist/wirings/channel/local/local-channel-handler.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-handler.js +5 -3
- package/dist/wirings/channel/local/local-channel-runner.js +14 -4
- package/dist/wirings/channel/serverless/serverless-channel-runner.js +4 -1
- package/dist/wirings/cli/cli-runner.js +10 -2
- package/dist/wirings/cli/cli.types.d.ts +1 -0
- package/dist/wirings/http/http-routes.js +0 -1
- package/dist/wirings/http/http-runner.d.ts +1 -1
- package/dist/wirings/http/http-runner.js +25 -3
- package/dist/wirings/http/http.types.d.ts +3 -11
- package/dist/wirings/http/index.d.ts +2 -1
- package/dist/wirings/http/index.js +1 -0
- package/dist/wirings/http/pikku-fetch-http-request.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-request.js +3 -0
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-response.js +4 -4
- package/dist/wirings/http/web-request.d.ts +12 -0
- package/dist/wirings/http/web-request.js +85 -0
- package/dist/wirings/mcp/mcp-endpoint-registry.js +1 -1
- package/dist/wirings/mcp/mcp-runner.js +13 -1
- package/dist/wirings/rpc/rpc-runner.d.ts +30 -6
- package/dist/wirings/rpc/rpc-runner.js +36 -14
- package/dist/wirings/rpc/rpc-types.d.ts +6 -1
- package/dist/wirings/rpc/wire-addon.d.ts +1 -0
- package/dist/wirings/rpc/wire-addon.js +1 -1
- package/dist/wirings/scheduler/scheduler-runner.js +1 -0
- package/dist/wirings/workflow/graph/graph-validation.d.ts +3 -0
- package/dist/wirings/workflow/graph/graph-validation.js +175 -0
- package/dist/wirings/workflow/graph/index.d.ts +1 -0
- package/dist/wirings/workflow/graph/index.js +1 -0
- package/dist/wirings/workflow/index.d.ts +1 -1
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +8 -2
- package/dist/wirings/workflow/pikku-workflow-service.js +1 -2
- package/dist/wirings/workflow/workflow.types.d.ts +10 -1
- package/package.json +4 -2
- package/src/crypto-utils.test.ts +99 -1
- package/src/crypto-utils.ts +114 -0
- package/src/function/function-runner.ts +5 -5
- package/src/function/functions.types.ts +38 -1
- package/src/handle-error.test.ts +65 -2
- package/src/handle-error.ts +8 -4
- package/src/index.ts +14 -0
- package/src/pikku-state.ts +3 -1
- package/src/schema.ts +1 -1
- package/src/services/in-memory-workflow-service.ts +45 -2
- package/src/services/workflow-service.ts +12 -1
- package/src/testing/index.ts +2 -0
- package/src/testing/service-tests.ts +873 -0
- package/src/types/core.types.ts +9 -1
- package/src/types/state.types.ts +4 -2
- package/src/utils/hash.test.ts +68 -0
- package/src/utils/hash.ts +26 -0
- package/src/wirings/ai-agent/agent-dynamic-workflow.ts +469 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +7 -6
- package/src/wirings/ai-agent/ai-agent-prepare.ts +175 -61
- package/src/wirings/ai-agent/ai-agent-runner.test.ts +3 -1
- package/src/wirings/ai-agent/ai-agent-runner.ts +553 -31
- package/src/wirings/ai-agent/ai-agent-stream.test.ts +209 -2
- package/src/wirings/ai-agent/ai-agent-stream.ts +182 -89
- package/src/wirings/ai-agent/ai-agent.types.ts +23 -1
- package/src/wirings/ai-agent/index.ts +1 -5
- package/src/wirings/channel/channel-handler.ts +11 -2
- package/src/wirings/channel/channel.types.ts +1 -7
- package/src/wirings/channel/local/local-channel-handler.ts +5 -3
- package/src/wirings/channel/local/local-channel-runner.ts +17 -7
- package/src/wirings/channel/serverless/serverless-channel-runner.ts +4 -1
- package/src/wirings/cli/cli-runner.ts +12 -2
- package/src/wirings/cli/cli.types.ts +1 -0
- package/src/wirings/http/http-routes.ts +0 -1
- package/src/wirings/http/http-runner.ts +35 -10
- package/src/wirings/http/http.types.ts +3 -12
- package/src/wirings/http/index.ts +3 -0
- package/src/wirings/http/pikku-fetch-http-request.ts +4 -0
- package/src/wirings/http/pikku-fetch-http-response.ts +4 -4
- package/src/wirings/http/web-request.test.ts +236 -0
- package/src/wirings/http/web-request.ts +104 -0
- package/src/wirings/mcp/mcp-endpoint-registry.ts +1 -1
- package/src/wirings/mcp/mcp-runner.ts +30 -12
- package/src/wirings/rpc/rpc-runner.ts +45 -24
- package/src/wirings/rpc/rpc-types.ts +6 -1
- package/src/wirings/rpc/wire-addon.ts +2 -1
- package/src/wirings/scheduler/scheduler-runner.ts +1 -0
- package/src/wirings/workflow/graph/graph-validation.test.ts +170 -0
- package/src/wirings/workflow/graph/graph-validation.ts +237 -0
- package/src/wirings/workflow/graph/index.ts +5 -0
- package/src/wirings/workflow/index.ts +1 -0
- package/src/wirings/workflow/pikku-workflow-service.ts +14 -3
- package/src/wirings/workflow/workflow.types.ts +9 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/wirings/ai-agent/ai-agent-assistant-ui.d.ts +0 -5
- package/dist/wirings/ai-agent/ai-agent-assistant-ui.js +0 -168
- package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +0 -363
- package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +0 -238
|
@@ -69,6 +69,8 @@ export interface AIAgentInput {
|
|
|
69
69
|
threadId: string
|
|
70
70
|
resourceId: string
|
|
71
71
|
attachments?: AIAgentInputAttachment[]
|
|
72
|
+
model?: string
|
|
73
|
+
temperature?: number
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
export interface AIAgentOutput {
|
|
@@ -78,6 +80,14 @@ export interface AIAgentOutput {
|
|
|
78
80
|
threadId: string
|
|
79
81
|
steps: AIAgentStep[]
|
|
80
82
|
usage: { inputTokens: number; outputTokens: number }
|
|
83
|
+
status?: 'completed' | 'suspended'
|
|
84
|
+
pendingApprovals?: Array<{
|
|
85
|
+
toolCallId: string
|
|
86
|
+
toolName: string
|
|
87
|
+
args: unknown
|
|
88
|
+
reason?: string
|
|
89
|
+
runId: string
|
|
90
|
+
}>
|
|
81
91
|
}
|
|
82
92
|
|
|
83
93
|
export interface AIAgentToolDef {
|
|
@@ -86,6 +96,7 @@ export interface AIAgentToolDef {
|
|
|
86
96
|
inputSchema: Record<string, unknown>
|
|
87
97
|
execute: (input: unknown) => Promise<unknown>
|
|
88
98
|
needsApproval?: boolean
|
|
99
|
+
approvalDescriptionFn?: (input: unknown) => Promise<string>
|
|
89
100
|
}
|
|
90
101
|
|
|
91
102
|
export interface PikkuAIMiddlewareHooks<
|
|
@@ -189,13 +200,14 @@ export type CoreAIAgent<
|
|
|
189
200
|
temperature?: number
|
|
190
201
|
tools?: unknown[]
|
|
191
202
|
agents?: unknown[]
|
|
203
|
+
agentMode?: 'delegate' | 'supervise'
|
|
192
204
|
memory?: AIAgentMemoryConfig
|
|
193
205
|
maxSteps?: number
|
|
194
206
|
toolChoice?: 'auto' | 'required' | 'none'
|
|
207
|
+
dynamicWorkflows?: 'read' | 'always' | 'ask'
|
|
195
208
|
input?: unknown
|
|
196
209
|
output?: unknown
|
|
197
210
|
tags?: string[]
|
|
198
|
-
protocol?: 'ui-message-stream'
|
|
199
211
|
prepareStep?: (ctx: {
|
|
200
212
|
stepNumber: number
|
|
201
213
|
messages: AIMessage[]
|
|
@@ -267,6 +279,13 @@ export type AIStreamEvent =
|
|
|
267
279
|
session?: string
|
|
268
280
|
}
|
|
269
281
|
| { type: 'audio-done'; agent?: string; session?: string }
|
|
282
|
+
| {
|
|
283
|
+
type: 'workflow-created'
|
|
284
|
+
workflowName: string
|
|
285
|
+
graph: any
|
|
286
|
+
agent?: string
|
|
287
|
+
session?: string
|
|
288
|
+
}
|
|
270
289
|
| {
|
|
271
290
|
type: 'suspended'
|
|
272
291
|
reason: 'rpc-missing'
|
|
@@ -298,6 +317,7 @@ export interface AgentRunState {
|
|
|
298
317
|
threadId: string
|
|
299
318
|
resourceId: string
|
|
300
319
|
status: 'running' | 'suspended' | 'completed' | 'failed'
|
|
320
|
+
errorMessage?: string
|
|
301
321
|
suspendReason?: 'approval' | 'rpc-missing'
|
|
302
322
|
missingRpcs?: string[]
|
|
303
323
|
pendingApprovals?: PendingApproval[]
|
|
@@ -312,6 +332,7 @@ export interface AgentRunRow {
|
|
|
312
332
|
threadId: string
|
|
313
333
|
resourceId: string
|
|
314
334
|
status: string
|
|
335
|
+
errorMessage?: string
|
|
315
336
|
suspendReason?: string
|
|
316
337
|
missingRpcs?: string[]
|
|
317
338
|
usageInputTokens: number
|
|
@@ -356,5 +377,6 @@ export type AIAgentMeta = Record<
|
|
|
356
377
|
channelMiddleware?: MiddlewareMetadata[]
|
|
357
378
|
aiMiddleware?: MiddlewareMetadata[]
|
|
358
379
|
permissions?: PermissionMetadata[]
|
|
380
|
+
dynamicWorkflows?: 'read' | 'always' | 'ask'
|
|
359
381
|
}
|
|
360
382
|
>
|
|
@@ -4,12 +4,8 @@ export {
|
|
|
4
4
|
agentResume,
|
|
5
5
|
agentApprove,
|
|
6
6
|
} from './ai-agent-helpers.js'
|
|
7
|
-
export { runAIAgent } from './ai-agent-runner.js'
|
|
7
|
+
export { runAIAgent, resumeAIAgentSync } from './ai-agent-runner.js'
|
|
8
8
|
export { streamAIAgent, resumeAIAgent } from './ai-agent-stream.js'
|
|
9
|
-
export {
|
|
10
|
-
createAssistantUIChannel,
|
|
11
|
-
parseAssistantUIInput,
|
|
12
|
-
} from './ai-agent-assistant-ui.js'
|
|
13
9
|
export {
|
|
14
10
|
type RunAIAgentParams,
|
|
15
11
|
type StreamAIAgentOptions,
|
|
@@ -98,11 +98,18 @@ export const processMessageHandlers = (
|
|
|
98
98
|
return
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
const routeMeta = getRouteMeta(
|
|
102
|
+
channelConfig.name,
|
|
103
|
+
routingProperty,
|
|
104
|
+
routerValue
|
|
105
|
+
)
|
|
101
106
|
const {
|
|
102
|
-
|
|
107
|
+
packageName,
|
|
103
108
|
middleware: routeInheritedMiddleware,
|
|
104
109
|
permissions: inheritedPermissions,
|
|
105
|
-
} =
|
|
110
|
+
} = routeMeta
|
|
111
|
+
|
|
112
|
+
const pikkuFuncId = routeMeta.pikkuFuncId
|
|
106
113
|
|
|
107
114
|
// Get wire middleware: channel-level middleware + message-specific middleware
|
|
108
115
|
const channelWireMiddleware = channelConfig.middleware || []
|
|
@@ -146,12 +153,14 @@ export const processMessageHandlers = (
|
|
|
146
153
|
wireChannelMiddleware: wireChannelMiddleware as any,
|
|
147
154
|
inheritedPermissions,
|
|
148
155
|
wirePermissions,
|
|
156
|
+
coerceDataFromSchema: true,
|
|
149
157
|
tags: channelConfig.tags,
|
|
150
158
|
sessionService: userSession,
|
|
151
159
|
wire: {
|
|
152
160
|
channel: channelHandler.getChannel(),
|
|
153
161
|
...(userSession && createMiddlewareSessionWireProps(userSession)),
|
|
154
162
|
},
|
|
163
|
+
packageName,
|
|
155
164
|
})
|
|
156
165
|
}
|
|
157
166
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { PikkuError } from '../../errors/error-handler.js'
|
|
2
1
|
import type {
|
|
3
2
|
HTTPFunctionMetaInputTypes,
|
|
4
3
|
PikkuHTTPRequest,
|
|
@@ -47,6 +46,7 @@ export type RunChannelParams<ChannelData> = {
|
|
|
47
46
|
|
|
48
47
|
export interface ChannelMessageMeta {
|
|
49
48
|
pikkuFuncId: string
|
|
49
|
+
packageName?: string
|
|
50
50
|
summary?: string
|
|
51
51
|
description?: string
|
|
52
52
|
errors?: string[]
|
|
@@ -141,12 +141,6 @@ export type CoreChannel<
|
|
|
141
141
|
data: BinaryData,
|
|
142
142
|
channel: PikkuChannel<ChannelData, any>
|
|
143
143
|
) => Promise<BinaryData | void> | BinaryData | void
|
|
144
|
-
docs?: Partial<{
|
|
145
|
-
description: string
|
|
146
|
-
response: string
|
|
147
|
-
errors: Array<typeof PikkuError>
|
|
148
|
-
tags: string[]
|
|
149
|
-
}>
|
|
150
144
|
tags?: string[]
|
|
151
145
|
}
|
|
152
146
|
|
|
@@ -8,7 +8,7 @@ export class PikkuLocalChannelHandler<
|
|
|
8
8
|
private onMessageCallback?: (message: unknown) => void
|
|
9
9
|
private onBinaryMessageCallback?: (data: BinaryData) => void
|
|
10
10
|
private openCallBack?: () => void
|
|
11
|
-
private
|
|
11
|
+
private closeCallbacks: (() => void)[] = []
|
|
12
12
|
private sendCallback?: (message: Out, isBinary?: boolean) => void
|
|
13
13
|
private sendBinaryCallback?: (data: BinaryData) => void
|
|
14
14
|
|
|
@@ -44,7 +44,7 @@ export class PikkuLocalChannelHandler<
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
public registerOnClose(callback: () => void): void {
|
|
47
|
-
this.
|
|
47
|
+
this.closeCallbacks.push(callback)
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
public close() {
|
|
@@ -52,7 +52,9 @@ export class PikkuLocalChannelHandler<
|
|
|
52
52
|
return
|
|
53
53
|
}
|
|
54
54
|
super.close()
|
|
55
|
-
this.
|
|
55
|
+
for (const cb of this.closeCallbacks) {
|
|
56
|
+
cb()
|
|
57
|
+
}
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
public registerOnSend(send: (message: Out) => void) {
|
|
@@ -119,9 +119,12 @@ export const runLocalChannel = async ({
|
|
|
119
119
|
if (result !== undefined) {
|
|
120
120
|
await channel.send(result)
|
|
121
121
|
}
|
|
122
|
-
} catch (e) {
|
|
122
|
+
} catch (e: any) {
|
|
123
123
|
singletonServices.logger.error(`Error handling onConnect: ${e}`)
|
|
124
|
-
channel.send({
|
|
124
|
+
channel.send({
|
|
125
|
+
error: e.message || 'Unknown error',
|
|
126
|
+
errorName: e.constructor?.name,
|
|
127
|
+
})
|
|
125
128
|
}
|
|
126
129
|
}
|
|
127
130
|
})
|
|
@@ -138,9 +141,12 @@ export const runLocalChannel = async ({
|
|
|
138
141
|
channel,
|
|
139
142
|
channelMiddlewareMeta: meta.channelMiddleware,
|
|
140
143
|
})
|
|
141
|
-
} catch (e) {
|
|
144
|
+
} catch (e: any) {
|
|
142
145
|
singletonServices.logger.error(`Error handling onDisconnect: ${e}`)
|
|
143
|
-
channel.send({
|
|
146
|
+
channel.send({
|
|
147
|
+
error: e.message || 'Unknown error',
|
|
148
|
+
errorName: e.constructor?.name,
|
|
149
|
+
})
|
|
144
150
|
}
|
|
145
151
|
}
|
|
146
152
|
|
|
@@ -157,9 +163,13 @@ export const runLocalChannel = async ({
|
|
|
157
163
|
try {
|
|
158
164
|
const result = await onMessage(data)
|
|
159
165
|
await channel.send(result)
|
|
160
|
-
} catch (e) {
|
|
161
|
-
singletonServices.logger.error(
|
|
162
|
-
channel.send({
|
|
166
|
+
} catch (e: any) {
|
|
167
|
+
singletonServices.logger.error(e)
|
|
168
|
+
channel.send({
|
|
169
|
+
error: e.message || 'Unknown error',
|
|
170
|
+
errorName: e.constructor?.name,
|
|
171
|
+
})
|
|
172
|
+
setTimeout(() => channel.close(), 200)
|
|
163
173
|
}
|
|
164
174
|
})
|
|
165
175
|
if (onBinaryMessage) {
|
|
@@ -276,7 +276,10 @@ export const runChannelMessage = async (
|
|
|
276
276
|
singletonServices.logger.error(
|
|
277
277
|
`Error processing message: ${e.message || e}`
|
|
278
278
|
)
|
|
279
|
-
return {
|
|
279
|
+
return {
|
|
280
|
+
error: e.message || 'Unknown error',
|
|
281
|
+
errorName: e.constructor?.name,
|
|
282
|
+
}
|
|
280
283
|
} finally {
|
|
281
284
|
if (wireServices) {
|
|
282
285
|
await closeWireServices(singletonServices.logger, wireServices)
|
|
@@ -218,7 +218,9 @@ function pluckCLIData(
|
|
|
218
218
|
const funcMeta = pikkuState(null, 'function', 'meta')[funcName]
|
|
219
219
|
const schemaName = funcMeta?.inputSchemaName
|
|
220
220
|
const schema = schemaName
|
|
221
|
-
? pikkuState(null, 'misc', 'schemas').get(
|
|
221
|
+
? pikkuState(funcMeta?.packageName ?? null, 'misc', 'schemas').get(
|
|
222
|
+
schemaName
|
|
223
|
+
)
|
|
222
224
|
: null
|
|
223
225
|
|
|
224
226
|
if (schema && schema.properties) {
|
|
@@ -226,7 +228,13 @@ function pluckCLIData(
|
|
|
226
228
|
const result: Record<string, any> = {}
|
|
227
229
|
for (const key of Object.keys(schema.properties)) {
|
|
228
230
|
if (key in mergedData) {
|
|
229
|
-
|
|
231
|
+
let value = mergedData[key]
|
|
232
|
+
// CLI passes all values as strings — coerce to array when schema expects one
|
|
233
|
+
const propSchema = schema.properties[key]
|
|
234
|
+
if (propSchema?.type === 'array' && !Array.isArray(value)) {
|
|
235
|
+
value = typeof value === 'string' ? value.split(',') : [value]
|
|
236
|
+
}
|
|
237
|
+
result[key] = value
|
|
230
238
|
} else if (availableOptions[key]?.default !== undefined) {
|
|
231
239
|
// Apply default if not provided
|
|
232
240
|
result[key] = availableOptions[key].default
|
|
@@ -354,9 +362,11 @@ export async function runCLICommand({
|
|
|
354
362
|
wireMiddleware: allWireMiddleware,
|
|
355
363
|
inheritedPermissions: currentCommand.permissions,
|
|
356
364
|
wirePermissions: undefined,
|
|
365
|
+
coerceDataFromSchema: true,
|
|
357
366
|
tags: programData?.tags,
|
|
358
367
|
wire,
|
|
359
368
|
sessionService: userSession,
|
|
369
|
+
packageName: currentCommand.packageName,
|
|
360
370
|
})
|
|
361
371
|
|
|
362
372
|
// Apply renderer one final time with the final output (if renderer exists)
|
|
@@ -38,6 +38,7 @@ import { PikkuFetchHTTPResponse } from './pikku-fetch-http-response.js'
|
|
|
38
38
|
import { PikkuFetchHTTPRequest } from './pikku-fetch-http-request.js'
|
|
39
39
|
import type { PikkuChannel } from '../channel/channel.types.js'
|
|
40
40
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js'
|
|
41
|
+
import { applyWebResponse } from './web-request.js'
|
|
41
42
|
import { httpRouter } from './routers/http-router.js'
|
|
42
43
|
import { validateSchema } from '../../schema.js'
|
|
43
44
|
import { runMiddleware } from '../../middleware-runner.js'
|
|
@@ -396,10 +397,13 @@ const executeRoute = async (
|
|
|
396
397
|
tags: route.tags,
|
|
397
398
|
wire,
|
|
398
399
|
sessionService: userSession,
|
|
400
|
+
packageName: meta.packageName,
|
|
399
401
|
}
|
|
400
402
|
)
|
|
401
403
|
if (!matchedRoute.route.sse) {
|
|
402
|
-
if (result
|
|
404
|
+
if (result instanceof Response) {
|
|
405
|
+
await applyWebResponse(http!.response!, result)
|
|
406
|
+
} else if (result === undefined || result === null) {
|
|
403
407
|
http?.response?.status(204)
|
|
404
408
|
} else if (route.returnsJSON === false) {
|
|
405
409
|
http?.response?.arrayBuffer(result)
|
|
@@ -484,6 +488,7 @@ export const fetchData = async <In, Out>(
|
|
|
484
488
|
logWarningsForStatusCodes = [],
|
|
485
489
|
coerceDataFromSchema = true,
|
|
486
490
|
bubbleErrors = false,
|
|
491
|
+
exposeErrors = false,
|
|
487
492
|
generateRequestId,
|
|
488
493
|
}: RunHTTPWiringOptions = {}
|
|
489
494
|
): Promise<Out | void> => {
|
|
@@ -545,15 +550,35 @@ export const fetchData = async <In, Out>(
|
|
|
545
550
|
|
|
546
551
|
return result
|
|
547
552
|
} catch (e: any) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
553
|
+
if (matchedRoute?.route.sse) {
|
|
554
|
+
// For SSE routes, send error through the stream since the response is already in stream mode
|
|
555
|
+
singletonServices.logger.error(e instanceof Error ? e.message : e)
|
|
556
|
+
try {
|
|
557
|
+
response.arrayBuffer(
|
|
558
|
+
JSON.stringify({
|
|
559
|
+
type: 'error',
|
|
560
|
+
errorText: e instanceof Error ? e.message : String(e),
|
|
561
|
+
})
|
|
562
|
+
)
|
|
563
|
+
response.arrayBuffer('[DONE]')
|
|
564
|
+
} catch (streamErr: any) {
|
|
565
|
+
singletonServices.logger.error(
|
|
566
|
+
`SSE error while sending error payload: ${streamErr instanceof Error ? streamErr.message : String(streamErr)}`
|
|
567
|
+
)
|
|
568
|
+
}
|
|
569
|
+
response.close?.()
|
|
570
|
+
} else {
|
|
571
|
+
handleHTTPError(
|
|
572
|
+
e,
|
|
573
|
+
http,
|
|
574
|
+
requestId,
|
|
575
|
+
singletonServices.logger,
|
|
576
|
+
logWarningsForStatusCodes,
|
|
577
|
+
respondWith404,
|
|
578
|
+
bubbleErrors,
|
|
579
|
+
exposeErrors
|
|
580
|
+
)
|
|
581
|
+
}
|
|
557
582
|
} finally {
|
|
558
583
|
// Clean up any session-specific services created during processing
|
|
559
584
|
if (wireServices) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { SerializeOptions } from 'cookie'
|
|
2
2
|
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
|
3
|
-
import type { PikkuError } from '../../errors/error-handler.js'
|
|
4
3
|
import type {
|
|
5
4
|
CorePikkuMiddleware,
|
|
6
5
|
CommonWireMeta,
|
|
@@ -36,6 +35,7 @@ export type RunHTTPWiringOptions = Partial<{
|
|
|
36
35
|
logWarningsForStatusCodes: number[]
|
|
37
36
|
coerceDataFromSchema: boolean
|
|
38
37
|
bubbleErrors: boolean
|
|
38
|
+
exposeErrors: boolean
|
|
39
39
|
generateRequestId: () => string
|
|
40
40
|
}>
|
|
41
41
|
|
|
@@ -59,16 +59,6 @@ export type HTTPHeadersSchema = StandardSchemaV1<
|
|
|
59
59
|
Record<string, string | string[] | undefined>
|
|
60
60
|
>
|
|
61
61
|
|
|
62
|
-
/**
|
|
63
|
-
* Documentation config for OpenAPI generation
|
|
64
|
-
*/
|
|
65
|
-
export type HTTPRouteDocsConfig = {
|
|
66
|
-
description?: string
|
|
67
|
-
response?: string
|
|
68
|
-
errors?: Array<typeof PikkuError>
|
|
69
|
-
tags?: string[]
|
|
70
|
-
}
|
|
71
|
-
|
|
72
62
|
/**
|
|
73
63
|
* Common HTTP route configuration shared between wireHTTP and wireHTTPRoutes
|
|
74
64
|
*/
|
|
@@ -77,7 +67,6 @@ export type HTTPRouteBaseConfig = {
|
|
|
77
67
|
timeout?: number
|
|
78
68
|
tags?: string[]
|
|
79
69
|
headers?: HTTPHeadersSchema
|
|
80
|
-
docs?: HTTPRouteDocsConfig
|
|
81
70
|
}
|
|
82
71
|
|
|
83
72
|
/**
|
|
@@ -271,6 +260,7 @@ export interface PikkuHTTPRequest<In = unknown> {
|
|
|
271
260
|
data(): Promise<In>
|
|
272
261
|
json(): Promise<unknown>
|
|
273
262
|
arrayBuffer(): Promise<ArrayBuffer>
|
|
263
|
+
headers(): Record<string, string>
|
|
274
264
|
header(headerName: string): string | null
|
|
275
265
|
cookie(name?: string): string | null
|
|
276
266
|
params(): Partial<Record<string, string | string[]>>
|
|
@@ -293,6 +283,7 @@ export interface PikkuHTTPResponse<Out = unknown> {
|
|
|
293
283
|
| ReadableStream
|
|
294
284
|
): this
|
|
295
285
|
json(data: Out): this
|
|
286
|
+
send?(data: string | ArrayBuffer | Buffer): this
|
|
296
287
|
redirect(location: string, status?: number): this
|
|
297
288
|
close?: () => void
|
|
298
289
|
setMode?: (mode: 'stream') => void
|
|
@@ -11,12 +11,15 @@ export {
|
|
|
11
11
|
} from './http-runner.js'
|
|
12
12
|
|
|
13
13
|
export { wireHTTPRoutes, defineHTTPRoutes } from './http-routes.js'
|
|
14
|
+
export { toWebRequest, applyWebResponse } from './web-request.js'
|
|
14
15
|
|
|
15
16
|
export type {
|
|
16
17
|
AssertHTTPWiringParams,
|
|
17
18
|
CoreHTTPFunctionWiring,
|
|
18
19
|
HTTPMethod,
|
|
19
20
|
HTTPRouteBaseConfig,
|
|
21
|
+
HTTPRouteContract,
|
|
22
|
+
HTTPRouteMap,
|
|
20
23
|
HTTPWiringsMeta,
|
|
21
24
|
PikkuHTTPRequest,
|
|
22
25
|
PikkuHTTPResponse,
|
|
@@ -43,6 +43,10 @@ export class PikkuFetchHTTPRequest<In = unknown>
|
|
|
43
43
|
return this.request.arrayBuffer()
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
public headers(): Record<string, string> {
|
|
47
|
+
return Object.fromEntries(this.request.headers.entries())
|
|
48
|
+
}
|
|
49
|
+
|
|
46
50
|
/**
|
|
47
51
|
* Retrieves the value of a specific header.
|
|
48
52
|
* @param headerName - The name of the header to retrieve.
|
|
@@ -83,10 +83,10 @@ export class PikkuFetchHTTPResponse implements PikkuHTTPResponse {
|
|
|
83
83
|
return this
|
|
84
84
|
}
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
public send(data: any): this {
|
|
87
|
+
this.#body = data
|
|
88
|
+
return this
|
|
89
|
+
}
|
|
90
90
|
|
|
91
91
|
public redirect(location: string, status: number = 302): this {
|
|
92
92
|
if (
|