@pikku/core 0.12.1 → 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 +34 -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/middleware-runner.js +1 -0
- package/dist/permissions.js +1 -0
- package/dist/pikku-state.js +7 -1
- package/dist/schema.js +1 -1
- package/dist/services/gateway-service.d.ts +19 -0
- package/dist/services/gateway-service.js +1 -0
- package/dist/services/in-memory-workflow-service.d.ts +8 -2
- package/dist/services/in-memory-workflow-service.js +28 -1
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +1 -0
- package/dist/services/local-gateway-service.d.ts +22 -0
- package/dist/services/local-gateway-service.js +51 -0
- 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 +12 -2
- package/dist/types/state.types.d.ts +9 -2
- package/dist/utils/hash.d.ts +2 -0
- package/dist/utils/hash.js +23 -0
- package/dist/utils.js +1 -1
- 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 +19 -7
- package/dist/wirings/ai-agent/ai-agent-prepare.d.ts +10 -7
- package/dist/wirings/ai-agent/ai-agent-prepare.js +141 -48
- 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 +126 -48
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +57 -3
- package/dist/wirings/ai-agent/index.d.ts +2 -3
- package/dist/wirings/ai-agent/index.js +1 -2
- package/dist/wirings/channel/channel-handler.d.ts +5 -2
- package/dist/wirings/channel/channel-handler.js +16 -2
- package/dist/wirings/channel/channel-middleware-runner.js +1 -0
- package/dist/wirings/channel/channel.types.d.ts +7 -7
- package/dist/wirings/channel/index.d.ts +1 -1
- package/dist/wirings/channel/local/local-channel-handler.d.ts +8 -1
- package/dist/wirings/channel/local/local-channel-handler.js +22 -3
- package/dist/wirings/channel/local/local-channel-runner.js +28 -5
- 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.js +5 -2
- package/dist/wirings/cli/cli-runner.js +13 -2
- package/dist/wirings/cli/cli.types.d.ts +1 -0
- 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/gateway.types.js +1 -0
- package/dist/wirings/gateway/index.d.ts +2 -0
- package/dist/wirings/gateway/index.js +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 +28 -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 +6 -3
- 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/middleware-runner.ts +1 -0
- package/src/permissions.ts +1 -0
- package/src/pikku-state.ts +8 -1
- package/src/schema.ts +1 -1
- package/src/services/gateway-service.ts +20 -0
- package/src/services/in-memory-workflow-service.ts +45 -2
- package/src/services/index.ts +2 -0
- package/src/services/local-gateway-service.ts +62 -0
- 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 +12 -1
- package/src/types/state.types.ts +12 -2
- package/src/utils/hash.test.ts +68 -0
- package/src/utils/hash.ts +26 -0
- package/src/utils.ts +1 -1
- package/src/wirings/ai-agent/agent-dynamic-workflow.ts +469 -0
- package/src/wirings/ai-agent/ai-agent-memory.ts +17 -7
- package/src/wirings/ai-agent/ai-agent-prepare.ts +194 -62
- 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 +195 -91
- package/src/wirings/ai-agent/ai-agent.types.ts +57 -3
- package/src/wirings/ai-agent/index.ts +3 -5
- package/src/wirings/channel/channel-handler.ts +41 -4
- package/src/wirings/channel/channel-middleware-runner.ts +1 -0
- package/src/wirings/channel/channel.types.ts +12 -7
- package/src/wirings/channel/index.ts +1 -0
- package/src/wirings/channel/local/local-channel-handler.ts +31 -3
- package/src/wirings/channel/local/local-channel-runner.ts +32 -8
- 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 +5 -2
- package/src/wirings/cli/cli-runner.ts +15 -2
- package/src/wirings/cli/cli.types.ts +1 -0
- 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.ts +0 -1
- package/src/wirings/http/http-runner.ts +38 -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 -146
- package/src/wirings/ai-agent/ai-agent-assistant-ui.test.ts +0 -363
- package/src/wirings/ai-agent/ai-agent-assistant-ui.ts +0 -214
|
@@ -3,7 +3,6 @@ import { combineChannelMiddleware, wrapChannelWithMiddleware, } from '../channel
|
|
|
3
3
|
import { randomUUID } from 'crypto';
|
|
4
4
|
import { parseWorkingMemory, deepMergeWorkingMemory, resolveMemoryServices, loadContextMessages, trimMessages, } from './ai-agent-memory.js';
|
|
5
5
|
import { prepareAgentRun, resolveAgent, buildInstructions, buildToolDefs, createScopedChannel, ToolApprovalRequired, } from './ai-agent-prepare.js';
|
|
6
|
-
import { createAssistantUIChannel, parseAssistantUIInput, } from './ai-agent-assistant-ui.js';
|
|
7
6
|
import { resolveModelConfig } from './ai-agent-model-config.js';
|
|
8
7
|
function createPersistingChannel(parent, storage, threadId) {
|
|
9
8
|
let fullText = '';
|
|
@@ -57,6 +56,7 @@ function createPersistingChannel(parent, storage, threadId) {
|
|
|
57
56
|
},
|
|
58
57
|
flush: flushStep,
|
|
59
58
|
close: () => parent.close(),
|
|
59
|
+
sendBinary: (data) => parent.sendBinary(data),
|
|
60
60
|
send: (event) => {
|
|
61
61
|
if (storage) {
|
|
62
62
|
switch (event.type) {
|
|
@@ -180,31 +180,52 @@ async function runStreamStepLoop(params) {
|
|
|
180
180
|
}
|
|
181
181
|
if (stepResult.toolCalls.length === 0)
|
|
182
182
|
break;
|
|
183
|
-
const
|
|
184
|
-
if (
|
|
185
|
-
|
|
183
|
+
const approvalsNeeded = checkForApprovals(stepResult, runnerParams.tools, runId);
|
|
184
|
+
if (approvalsNeeded.length > 0) {
|
|
185
|
+
// For each approval, call approvalDescriptionFn if available
|
|
186
|
+
for (const approval of approvalsNeeded) {
|
|
187
|
+
const toolDef = runnerParams.tools.find((t) => t.name === approval.toolName);
|
|
188
|
+
if (toolDef?.approvalDescriptionFn && !approval.reason) {
|
|
189
|
+
try {
|
|
190
|
+
approval.reason = await toolDef.approvalDescriptionFn(approval.args);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
// If description generation fails, continue without it
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return { outcome: 'approval', approvals: approvalsNeeded };
|
|
186
198
|
}
|
|
187
199
|
appendStepMessages(runnerParams, stepResult);
|
|
188
200
|
}
|
|
189
201
|
return { outcome: 'done' };
|
|
190
202
|
}
|
|
191
|
-
function
|
|
203
|
+
export function checkForApprovals(stepResult, tools, runId) {
|
|
204
|
+
const approvals = [];
|
|
192
205
|
for (const tc of stepResult.toolCalls) {
|
|
193
206
|
const toolDef = tools.find((t) => t.name === tc.toolName);
|
|
194
207
|
if (toolDef?.needsApproval) {
|
|
195
|
-
|
|
208
|
+
approvals.push(new ToolApprovalRequired(tc.toolCallId, tc.toolName, tc.args));
|
|
209
|
+
continue;
|
|
196
210
|
}
|
|
197
211
|
const tr = stepResult.toolResults.find((r) => r.toolCallId === tc.toolCallId);
|
|
198
212
|
if (tr?.result &&
|
|
199
213
|
typeof tr.result === 'object' &&
|
|
200
214
|
'__approvalRequired' in tr.result) {
|
|
201
215
|
const r = tr.result;
|
|
202
|
-
|
|
216
|
+
if (r.subApprovals?.length) {
|
|
217
|
+
for (const sub of r.subApprovals) {
|
|
218
|
+
approvals.push(new ToolApprovalRequired(sub.toolCallId, r.toolName, r.args, undefined, sub.toolName, sub.args, r.agentRunId));
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
approvals.push(new ToolApprovalRequired(tc.toolCallId, r.toolName, r.args, r.reason, r.displayToolName, r.displayArgs, r.agentRunId));
|
|
223
|
+
}
|
|
203
224
|
}
|
|
204
225
|
}
|
|
205
|
-
return
|
|
226
|
+
return approvals;
|
|
206
227
|
}
|
|
207
|
-
function appendStepMessages(runnerParams, stepResult) {
|
|
228
|
+
export function appendStepMessages(runnerParams, stepResult) {
|
|
208
229
|
const assistantMsg = {
|
|
209
230
|
id: randomUUID(),
|
|
210
231
|
role: 'assistant',
|
|
@@ -233,10 +254,10 @@ function appendStepMessages(runnerParams, stepResult) {
|
|
|
233
254
|
runnerParams.messages.push(toolMsg);
|
|
234
255
|
}
|
|
235
256
|
}
|
|
236
|
-
function
|
|
257
|
+
function handleApprovals(approvals, runId, channel, aiRunState, persistingChannel) {
|
|
237
258
|
return (async () => {
|
|
238
259
|
await persistingChannel.flush();
|
|
239
|
-
const
|
|
260
|
+
const pendingApprovals = approvals.map((err) => err.agentRunId
|
|
240
261
|
? {
|
|
241
262
|
type: 'agent-call',
|
|
242
263
|
toolCallId: err.toolCallId,
|
|
@@ -250,40 +271,32 @@ function handleApproval(err, runId, channel, aiRunState, persistingChannel) {
|
|
|
250
271
|
toolCallId: err.toolCallId,
|
|
251
272
|
toolName: err.toolName,
|
|
252
273
|
args: err.args,
|
|
253
|
-
};
|
|
274
|
+
});
|
|
254
275
|
await aiRunState.updateRun(runId, {
|
|
255
276
|
status: 'suspended',
|
|
256
277
|
suspendReason: 'approval',
|
|
257
|
-
pendingApprovals
|
|
278
|
+
pendingApprovals,
|
|
258
279
|
});
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
280
|
+
for (const err of approvals) {
|
|
281
|
+
const approvalEvent = {
|
|
282
|
+
type: 'approval-request',
|
|
283
|
+
toolCallId: err.toolCallId,
|
|
284
|
+
toolName: err.displayToolName ?? err.toolName,
|
|
285
|
+
args: err.displayArgs ?? err.args,
|
|
286
|
+
reason: err.reason,
|
|
287
|
+
runId,
|
|
288
|
+
};
|
|
289
|
+
channel.send(approvalEvent);
|
|
290
|
+
}
|
|
268
291
|
channel.send({ type: 'done' });
|
|
269
292
|
channel.close();
|
|
270
293
|
})();
|
|
271
294
|
}
|
|
272
295
|
export async function streamAIAgent(agentName, input, channel, params, agentSessionMap, options) {
|
|
273
296
|
const sessionMap = agentSessionMap ?? new Map();
|
|
274
|
-
const
|
|
275
|
-
const inputRecord = input;
|
|
276
|
-
const useUIMessageStream = resolvedAgentForProtocol.protocol === 'ui-message-stream' ||
|
|
277
|
-
Array.isArray(inputRecord.messages);
|
|
278
|
-
let normalizedInput;
|
|
279
|
-
if (useUIMessageStream) {
|
|
280
|
-
normalizedInput = parseAssistantUIInput(inputRecord);
|
|
281
|
-
channel = createAssistantUIChannel(channel);
|
|
282
|
-
}
|
|
283
|
-
else {
|
|
284
|
-
normalizedInput = input;
|
|
285
|
-
}
|
|
297
|
+
const normalizedInput = input;
|
|
286
298
|
const streamContext = { channel, options };
|
|
299
|
+
// delegateState is attached after prepareAgentRun resolves the agent config
|
|
287
300
|
const { agent, packageName, resolvedName, agentRunner, storage, memoryConfig, threadId, userMessage, runnerParams, maxSteps, missingRpcs, workingMemorySchemaName, } = await prepareAgentRun(agentName, normalizedInput, params, sessionMap, streamContext);
|
|
288
301
|
const singletonServices = getSingletonServices();
|
|
289
302
|
const { aiRunState } = singletonServices;
|
|
@@ -304,7 +317,7 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
304
317
|
});
|
|
305
318
|
channel.send({ type: 'suspended', reason: 'rpc-missing', missingRpcs });
|
|
306
319
|
channel.send({ type: 'done' });
|
|
307
|
-
return;
|
|
320
|
+
return '';
|
|
308
321
|
}
|
|
309
322
|
const aiMiddlewares = agent.aiMiddleware ?? [];
|
|
310
323
|
let modifiedMessages = runnerParams.messages;
|
|
@@ -345,8 +358,15 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
345
358
|
allEvents,
|
|
346
359
|
state,
|
|
347
360
|
});
|
|
348
|
-
if (result
|
|
361
|
+
if (result == null)
|
|
362
|
+
return;
|
|
363
|
+
if (Array.isArray(result)) {
|
|
364
|
+
for (const r of result)
|
|
365
|
+
await next(r);
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
349
368
|
await next(result);
|
|
369
|
+
}
|
|
350
370
|
};
|
|
351
371
|
});
|
|
352
372
|
const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta');
|
|
@@ -361,7 +381,28 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
361
381
|
const wrappedChannel = allChannelMiddleware.length > 0
|
|
362
382
|
? wrapChannelWithMiddleware({ channel }, singletonServices, allChannelMiddleware).channel
|
|
363
383
|
: channel;
|
|
364
|
-
|
|
384
|
+
// In delegate mode (default), suppress parent's text from reaching the client
|
|
385
|
+
// AFTER a sub-agent has been called. If the parent responds directly (no delegation),
|
|
386
|
+
// its text goes through normally. Sub-agent text bypasses this path entirely
|
|
387
|
+
// (goes through subChannel → channel directly).
|
|
388
|
+
const isDelegateMode = agent.agentMode !== 'supervise' && meta.agents?.length;
|
|
389
|
+
const delegateState = { delegated: false };
|
|
390
|
+
if (isDelegateMode) {
|
|
391
|
+
streamContext.delegateState = delegateState;
|
|
392
|
+
}
|
|
393
|
+
const outputChannel = isDelegateMode
|
|
394
|
+
? {
|
|
395
|
+
...wrappedChannel,
|
|
396
|
+
send: (event) => {
|
|
397
|
+
if (delegateState.delegated &&
|
|
398
|
+
(event.type === 'text-delta' || event.type === 'reasoning-delta'))
|
|
399
|
+
return;
|
|
400
|
+
wrappedChannel.send(event);
|
|
401
|
+
},
|
|
402
|
+
delegateState,
|
|
403
|
+
}
|
|
404
|
+
: wrappedChannel;
|
|
405
|
+
const persistingChannel = createPersistingChannel(outputChannel, storage, threadId);
|
|
365
406
|
try {
|
|
366
407
|
const loopResult = await runStreamStepLoop({
|
|
367
408
|
agent,
|
|
@@ -374,12 +415,13 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
374
415
|
aiMiddlewares,
|
|
375
416
|
});
|
|
376
417
|
if (loopResult.outcome === 'approval') {
|
|
377
|
-
await
|
|
378
|
-
return;
|
|
418
|
+
await handleApprovals(loopResult.approvals, runId, channel, aiRunState, persistingChannel);
|
|
419
|
+
return persistingChannel.fullText;
|
|
379
420
|
}
|
|
380
421
|
await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, storage, memoryConfig, threadId, workingMemorySchemaName, runnerParams.messages, aiRunState, runId);
|
|
381
422
|
channel.send({ type: 'done' });
|
|
382
423
|
channel.close();
|
|
424
|
+
return persistingChannel.fullText;
|
|
383
425
|
}
|
|
384
426
|
catch (err) {
|
|
385
427
|
for (const mw of aiMiddlewares) {
|
|
@@ -396,13 +438,17 @@ export async function streamAIAgent(agentName, input, channel, params, agentSess
|
|
|
396
438
|
}
|
|
397
439
|
}
|
|
398
440
|
}
|
|
399
|
-
await aiRunState.updateRun(runId, {
|
|
441
|
+
await aiRunState.updateRun(runId, {
|
|
442
|
+
status: 'failed',
|
|
443
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
444
|
+
});
|
|
400
445
|
channel.send({
|
|
401
446
|
type: 'error',
|
|
402
447
|
message: err instanceof Error ? err.message : String(err),
|
|
403
448
|
});
|
|
404
449
|
channel.send({ type: 'done' });
|
|
405
450
|
channel.close();
|
|
451
|
+
return persistingChannel.fullText;
|
|
406
452
|
}
|
|
407
453
|
}
|
|
408
454
|
export async function resumeAIAgent(input, channel, params, options) {
|
|
@@ -431,7 +477,7 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
431
477
|
if (pending.type === 'agent-call') {
|
|
432
478
|
await aiRunState.updateRun(pending.agentRunId, { status: 'failed' });
|
|
433
479
|
}
|
|
434
|
-
const denialResult = '
|
|
480
|
+
const denialResult = 'The user explicitly declined this action. Inform them that it was declined and do not retry.';
|
|
435
481
|
if (storage) {
|
|
436
482
|
await storage.saveMessages(run.threadId, [
|
|
437
483
|
{
|
|
@@ -450,6 +496,15 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
450
496
|
},
|
|
451
497
|
]);
|
|
452
498
|
}
|
|
499
|
+
// Check remaining pending approvals
|
|
500
|
+
const updatedRun = await aiRunState.getRun(run.runId);
|
|
501
|
+
const remaining = updatedRun?.pendingApprovals ?? [];
|
|
502
|
+
if (remaining.length > 0) {
|
|
503
|
+
// Still waiting for more approvals - don't continue step loop
|
|
504
|
+
channel.send({ type: 'done' });
|
|
505
|
+
channel.close();
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
453
508
|
await aiRunState.updateRun(run.runId, { status: 'running' });
|
|
454
509
|
await continueAfterToolResult(run, agent, packageName, resolvedName, storage, memoryConfig, agentRunner, channel, params, aiRunState, options);
|
|
455
510
|
return;
|
|
@@ -459,7 +514,8 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
459
514
|
if (!subRun) {
|
|
460
515
|
throw new Error(`Sub-agent run not found: ${pending.agentRunId}`);
|
|
461
516
|
}
|
|
462
|
-
const subPending = subRun.pendingApprovals?.
|
|
517
|
+
const subPending = subRun.pendingApprovals?.find((p) => p.toolCallId === input.toolCallId) ??
|
|
518
|
+
subRun.pendingApprovals?.[0];
|
|
463
519
|
if (!subPending) {
|
|
464
520
|
throw new Error(`No pending approval on sub-agent run ${pending.agentRunId}`);
|
|
465
521
|
}
|
|
@@ -504,18 +560,20 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
504
560
|
options: { ...options, requiresToolApproval: false },
|
|
505
561
|
};
|
|
506
562
|
const aiMiddlewaresForResume = agent.aiMiddleware ?? [];
|
|
507
|
-
const { tools } = buildToolDefs(params, new Map(), run.resourceId, resolvedName, packageName, streamContext, aiMiddlewaresForResume);
|
|
563
|
+
const { tools } = await buildToolDefs(params, new Map(), run.resourceId, resolvedName, packageName, streamContext, aiMiddlewaresForResume);
|
|
508
564
|
const matchingTool = tools.find((t) => t.name === pending.toolName);
|
|
509
565
|
if (!matchingTool) {
|
|
510
566
|
throw new Error(`Tool "${pending.toolName}" not found in agent definition`);
|
|
511
567
|
}
|
|
512
568
|
const toolArgs = typeof pending.args === 'string' ? JSON.parse(pending.args) : pending.args;
|
|
513
569
|
let toolResult;
|
|
570
|
+
let isError = false;
|
|
514
571
|
try {
|
|
515
572
|
toolResult = await matchingTool.execute(toolArgs);
|
|
516
573
|
}
|
|
517
574
|
catch (execErr) {
|
|
518
575
|
toolResult = `Error: ${execErr instanceof Error ? execErr.message : String(execErr)}`;
|
|
576
|
+
isError = true;
|
|
519
577
|
}
|
|
520
578
|
const resultStr = typeof toolResult === 'string' ? toolResult : JSON.stringify(toolResult);
|
|
521
579
|
if (storage) {
|
|
@@ -539,8 +597,18 @@ export async function resumeAIAgent(input, channel, params, options) {
|
|
|
539
597
|
toolCallId: input.toolCallId,
|
|
540
598
|
toolName: pending.toolName,
|
|
541
599
|
result: toolResult,
|
|
600
|
+
...(isError ? { isError: true } : {}),
|
|
542
601
|
});
|
|
543
602
|
}
|
|
603
|
+
// Check remaining pending approvals after processing this one
|
|
604
|
+
const updatedRun = await aiRunState.getRun(run.runId);
|
|
605
|
+
const remaining = updatedRun?.pendingApprovals ?? [];
|
|
606
|
+
if (remaining.length > 0) {
|
|
607
|
+
// Still waiting for more approvals - don't continue step loop
|
|
608
|
+
channel.send({ type: 'done' });
|
|
609
|
+
channel.close();
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
544
612
|
await aiRunState.updateRun(run.runId, { status: 'running' });
|
|
545
613
|
await continueAfterToolResult(run, agent, packageName, resolvedName, storage, memoryConfig, agentRunner, channel, params, aiRunState, options);
|
|
546
614
|
}
|
|
@@ -560,7 +628,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
560
628
|
const contextMessages = await loadContextMessages(memoryConfig, storage, { message: '', threadId: run.threadId, resourceId: run.resourceId }, workingMemoryJsonSchema);
|
|
561
629
|
const allMessages = [...contextMessages, ...messages];
|
|
562
630
|
const trimmedMessages = trimMessages(allMessages);
|
|
563
|
-
const instructions = buildInstructions(resolvedName, packageName);
|
|
631
|
+
const instructions = await buildInstructions(resolvedName, packageName);
|
|
564
632
|
const aiMiddlewares = agent.aiMiddleware ?? [];
|
|
565
633
|
let modifiedMessages = trimmedMessages;
|
|
566
634
|
let modifiedInstructions = instructions;
|
|
@@ -586,8 +654,15 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
586
654
|
allEvents,
|
|
587
655
|
state,
|
|
588
656
|
});
|
|
589
|
-
if (result
|
|
657
|
+
if (result == null)
|
|
658
|
+
return;
|
|
659
|
+
if (Array.isArray(result)) {
|
|
660
|
+
for (const r of result)
|
|
661
|
+
await next(r);
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
590
664
|
await next(result);
|
|
665
|
+
}
|
|
591
666
|
};
|
|
592
667
|
});
|
|
593
668
|
const allChannelMiddleware = combineChannelMiddleware('agent', `stream:${run.agentName}`, {
|
|
@@ -602,7 +677,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
602
677
|
: channel;
|
|
603
678
|
const persistingChannel = createPersistingChannel(wrappedChannel, storage, run.threadId);
|
|
604
679
|
const streamContext = { channel, options };
|
|
605
|
-
const resumeTools = buildToolDefs(params, new Map(), run.resourceId, resolvedName, packageName, streamContext, aiMiddlewares).tools;
|
|
680
|
+
const resumeTools = (await buildToolDefs(params, new Map(), run.resourceId, resolvedName, packageName, streamContext, aiMiddlewares)).tools;
|
|
606
681
|
const resolved = resolveModelConfig(resolvedName, agent);
|
|
607
682
|
const maxSteps = resolved.maxSteps ?? 10;
|
|
608
683
|
const runnerParams = {
|
|
@@ -629,7 +704,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
629
704
|
aiMiddlewares,
|
|
630
705
|
});
|
|
631
706
|
if (loopResult.outcome === 'approval') {
|
|
632
|
-
await
|
|
707
|
+
await handleApprovals(loopResult.approvals, run.runId, channel, aiRunState, persistingChannel);
|
|
633
708
|
return;
|
|
634
709
|
}
|
|
635
710
|
await postStreamCleanup(persistingChannel, aiMiddlewares, singletonServices, storage, memoryConfig, run.threadId, workingMemorySchemaName, runnerParams.messages, aiRunState, run.runId);
|
|
@@ -651,7 +726,10 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
651
726
|
}
|
|
652
727
|
}
|
|
653
728
|
}
|
|
654
|
-
await aiRunState.updateRun(run.runId, {
|
|
729
|
+
await aiRunState.updateRun(run.runId, {
|
|
730
|
+
status: 'failed',
|
|
731
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
732
|
+
});
|
|
655
733
|
channel.send({
|
|
656
734
|
type: 'error',
|
|
657
735
|
message: err instanceof Error ? err.message : String(err),
|
|
@@ -10,6 +10,21 @@ export interface AIThread {
|
|
|
10
10
|
createdAt: Date;
|
|
11
11
|
updatedAt: Date;
|
|
12
12
|
}
|
|
13
|
+
export type AIContentPart = {
|
|
14
|
+
type: 'text';
|
|
15
|
+
text: string;
|
|
16
|
+
} | {
|
|
17
|
+
type: 'image';
|
|
18
|
+
data?: string;
|
|
19
|
+
url?: string;
|
|
20
|
+
mediaType?: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'file';
|
|
23
|
+
data?: string;
|
|
24
|
+
url?: string;
|
|
25
|
+
mediaType: string;
|
|
26
|
+
filename?: string;
|
|
27
|
+
};
|
|
13
28
|
export interface AIToolCall {
|
|
14
29
|
id: string;
|
|
15
30
|
name: string;
|
|
@@ -23,7 +38,7 @@ export interface AIToolResult {
|
|
|
23
38
|
export interface AIMessage {
|
|
24
39
|
id: string;
|
|
25
40
|
role: 'system' | 'user' | 'assistant' | 'tool';
|
|
26
|
-
content?: string;
|
|
41
|
+
content?: string | AIContentPart[];
|
|
27
42
|
toolCalls?: AIToolCall[];
|
|
28
43
|
toolResults?: AIToolResult[];
|
|
29
44
|
createdAt: Date;
|
|
@@ -39,10 +54,20 @@ export interface AIAgentStep {
|
|
|
39
54
|
result: string;
|
|
40
55
|
}[];
|
|
41
56
|
}
|
|
57
|
+
export interface AIAgentInputAttachment {
|
|
58
|
+
type: 'image' | 'file';
|
|
59
|
+
data?: string;
|
|
60
|
+
url?: string;
|
|
61
|
+
mediaType?: string;
|
|
62
|
+
filename?: string;
|
|
63
|
+
}
|
|
42
64
|
export interface AIAgentInput {
|
|
43
65
|
message: string;
|
|
44
66
|
threadId: string;
|
|
45
67
|
resourceId: string;
|
|
68
|
+
attachments?: AIAgentInputAttachment[];
|
|
69
|
+
model?: string;
|
|
70
|
+
temperature?: number;
|
|
46
71
|
}
|
|
47
72
|
export interface AIAgentOutput {
|
|
48
73
|
runId: string;
|
|
@@ -54,6 +79,14 @@ export interface AIAgentOutput {
|
|
|
54
79
|
inputTokens: number;
|
|
55
80
|
outputTokens: number;
|
|
56
81
|
};
|
|
82
|
+
status?: 'completed' | 'suspended';
|
|
83
|
+
pendingApprovals?: Array<{
|
|
84
|
+
toolCallId: string;
|
|
85
|
+
toolName: string;
|
|
86
|
+
args: unknown;
|
|
87
|
+
reason?: string;
|
|
88
|
+
runId: string;
|
|
89
|
+
}>;
|
|
57
90
|
}
|
|
58
91
|
export interface AIAgentToolDef {
|
|
59
92
|
name: string;
|
|
@@ -61,6 +94,7 @@ export interface AIAgentToolDef {
|
|
|
61
94
|
inputSchema: Record<string, unknown>;
|
|
62
95
|
execute: (input: unknown) => Promise<unknown>;
|
|
63
96
|
needsApproval?: boolean;
|
|
97
|
+
approvalDescriptionFn?: (input: unknown) => Promise<string>;
|
|
64
98
|
}
|
|
65
99
|
export interface PikkuAIMiddlewareHooks<State extends Record<string, unknown> = Record<string, unknown>, Services = any> {
|
|
66
100
|
modifyInput?: (services: Services, ctx: {
|
|
@@ -77,7 +111,7 @@ export interface PikkuAIMiddlewareHooks<State extends Record<string, unknown> =
|
|
|
77
111
|
event: AIStreamEvent;
|
|
78
112
|
allEvents: readonly AIStreamEvent[];
|
|
79
113
|
state: State;
|
|
80
|
-
}) => Promise<AIStreamEvent | null> | AIStreamEvent | null;
|
|
114
|
+
}) => Promise<AIStreamEvent | AIStreamEvent[] | null> | AIStreamEvent | AIStreamEvent[] | null;
|
|
81
115
|
modifyOutput?: (services: Services, ctx: {
|
|
82
116
|
text: string;
|
|
83
117
|
messages: AIMessage[];
|
|
@@ -154,13 +188,14 @@ export type CoreAIAgent<PikkuPermission = CorePikkuPermission<any, any>, PikkuMi
|
|
|
154
188
|
temperature?: number;
|
|
155
189
|
tools?: unknown[];
|
|
156
190
|
agents?: unknown[];
|
|
191
|
+
agentMode?: 'delegate' | 'supervise';
|
|
157
192
|
memory?: AIAgentMemoryConfig;
|
|
158
193
|
maxSteps?: number;
|
|
159
194
|
toolChoice?: 'auto' | 'required' | 'none';
|
|
195
|
+
dynamicWorkflows?: 'read' | 'always' | 'ask';
|
|
160
196
|
input?: unknown;
|
|
161
197
|
output?: unknown;
|
|
162
198
|
tags?: string[];
|
|
163
|
-
protocol?: 'ui-message-stream';
|
|
164
199
|
prepareStep?: (ctx: {
|
|
165
200
|
stepNumber: number;
|
|
166
201
|
messages: AIMessage[];
|
|
@@ -235,6 +270,22 @@ export type AIStreamEvent = {
|
|
|
235
270
|
message: string;
|
|
236
271
|
agent?: string;
|
|
237
272
|
session?: string;
|
|
273
|
+
} | {
|
|
274
|
+
type: 'audio-delta';
|
|
275
|
+
data: string;
|
|
276
|
+
format: string;
|
|
277
|
+
agent?: string;
|
|
278
|
+
session?: string;
|
|
279
|
+
} | {
|
|
280
|
+
type: 'audio-done';
|
|
281
|
+
agent?: string;
|
|
282
|
+
session?: string;
|
|
283
|
+
} | {
|
|
284
|
+
type: 'workflow-created';
|
|
285
|
+
workflowName: string;
|
|
286
|
+
graph: any;
|
|
287
|
+
agent?: string;
|
|
288
|
+
session?: string;
|
|
238
289
|
} | {
|
|
239
290
|
type: 'suspended';
|
|
240
291
|
reason: 'rpc-missing';
|
|
@@ -263,6 +314,7 @@ export interface AgentRunState {
|
|
|
263
314
|
threadId: string;
|
|
264
315
|
resourceId: string;
|
|
265
316
|
status: 'running' | 'suspended' | 'completed' | 'failed';
|
|
317
|
+
errorMessage?: string;
|
|
266
318
|
suspendReason?: 'approval' | 'rpc-missing';
|
|
267
319
|
missingRpcs?: string[];
|
|
268
320
|
pendingApprovals?: PendingApproval[];
|
|
@@ -280,6 +332,7 @@ export interface AgentRunRow {
|
|
|
280
332
|
threadId: string;
|
|
281
333
|
resourceId: string;
|
|
282
334
|
status: string;
|
|
335
|
+
errorMessage?: string;
|
|
283
336
|
suspendReason?: string;
|
|
284
337
|
missingRpcs?: string[];
|
|
285
338
|
usageInputTokens: number;
|
|
@@ -310,4 +363,5 @@ export type AIAgentMeta = Record<string, Omit<CoreAIAgent, 'input' | 'output' |
|
|
|
310
363
|
channelMiddleware?: MiddlewareMetadata[];
|
|
311
364
|
aiMiddleware?: MiddlewareMetadata[];
|
|
312
365
|
permissions?: PermissionMetadata[];
|
|
366
|
+
dynamicWorkflows?: 'read' | 'always' | 'ask';
|
|
313
367
|
}>;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export { agent, agentStream, agentResume, agentApprove, } from './ai-agent-helpers.js';
|
|
2
|
-
export { runAIAgent } from './ai-agent-runner.js';
|
|
2
|
+
export { runAIAgent, resumeAIAgentSync } from './ai-agent-runner.js';
|
|
3
3
|
export { streamAIAgent, resumeAIAgent } from './ai-agent-stream.js';
|
|
4
|
-
export { createAssistantUIChannel, parseAssistantUIInput, } from './ai-agent-assistant-ui.js';
|
|
5
4
|
export { type RunAIAgentParams, type StreamAIAgentOptions, ToolApprovalRequired, } from './ai-agent-prepare.js';
|
|
6
5
|
export { addAIAgent, approveAIAgent, getAIAgents, getAIAgentsMeta, } from './ai-agent-registry.js';
|
|
7
|
-
export type { AIAgentInput, AIAgentMeta, AIAgentMemoryConfig, AIAgentStep, AgentRunRow, AgentRunService, AgentRunState, AIMessage, AIStreamChannel, AIStreamEvent, AIThread, CoreAIAgent, PendingApproval, PikkuAIMiddlewareHooks, } from './ai-agent.types.js';
|
|
6
|
+
export type { AIAgentInput, AIAgentInputAttachment, AIAgentMeta, AIAgentMemoryConfig, AIAgentStep, AIContentPart, AgentRunRow, AgentRunService, AgentRunState, AIMessage, AIStreamChannel, AIStreamEvent, AIThread, CoreAIAgent, PendingApproval, PikkuAIMiddlewareHooks, } from './ai-agent.types.js';
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
export { agent, agentStream, agentResume, agentApprove, } from './ai-agent-helpers.js';
|
|
2
|
-
export { runAIAgent } from './ai-agent-runner.js';
|
|
2
|
+
export { runAIAgent, resumeAIAgentSync } from './ai-agent-runner.js';
|
|
3
3
|
export { streamAIAgent, resumeAIAgent } from './ai-agent-stream.js';
|
|
4
|
-
export { createAssistantUIChannel, parseAssistantUIInput, } from './ai-agent-assistant-ui.js';
|
|
5
4
|
export { ToolApprovalRequired, } from './ai-agent-prepare.js';
|
|
6
5
|
export { addAIAgent, approveAIAgent, getAIAgents, getAIAgentsMeta, } from './ai-agent-registry.js';
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import type { CoreServices, CoreUserSession } from '../../types/core.types.js';
|
|
2
|
-
import type { CoreChannel, PikkuChannelHandler } from './channel.types.js';
|
|
2
|
+
import type { BinaryData, CoreChannel, PikkuChannelHandler } from './channel.types.js';
|
|
3
3
|
import type { SessionService } from '../../services/user-session-service.js';
|
|
4
|
-
export declare const processMessageHandlers: (services: CoreServices, channelConfig: CoreChannel<any, any>, channelHandler: PikkuChannelHandler, userSession?: SessionService<CoreUserSession>) =>
|
|
4
|
+
export declare const processMessageHandlers: (services: CoreServices, channelConfig: CoreChannel<any, any>, channelHandler: PikkuChannelHandler, userSession?: SessionService<CoreUserSession>) => {
|
|
5
|
+
onMessage: (rawData: unknown) => Promise<unknown>;
|
|
6
|
+
onBinaryMessage: ((data: BinaryData) => Promise<BinaryData | void>) | undefined;
|
|
7
|
+
};
|
|
@@ -48,7 +48,9 @@ export const processMessageHandlers = (services, channelConfig, channelHandler,
|
|
|
48
48
|
channelHandler.getChannel().send(`Unauthorized for ${routeMessage}`);
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
-
const
|
|
51
|
+
const routeMeta = getRouteMeta(channelConfig.name, routingProperty, routerValue);
|
|
52
|
+
const { packageName, middleware: routeInheritedMiddleware, permissions: inheritedPermissions, } = routeMeta;
|
|
53
|
+
const pikkuFuncId = routeMeta.pikkuFuncId;
|
|
52
54
|
// Get wire middleware: channel-level middleware + message-specific middleware
|
|
53
55
|
const channelWireMiddleware = channelConfig.middleware || [];
|
|
54
56
|
// Check if onMessage is a wrapper object vs direct function config:
|
|
@@ -83,15 +85,17 @@ export const processMessageHandlers = (services, channelConfig, channelHandler,
|
|
|
83
85
|
wireChannelMiddleware: wireChannelMiddleware,
|
|
84
86
|
inheritedPermissions,
|
|
85
87
|
wirePermissions,
|
|
88
|
+
coerceDataFromSchema: true,
|
|
86
89
|
tags: channelConfig.tags,
|
|
87
90
|
sessionService: userSession,
|
|
88
91
|
wire: {
|
|
89
92
|
channel: channelHandler.getChannel(),
|
|
90
93
|
...(userSession && createMiddlewareSessionWireProps(userSession)),
|
|
91
94
|
},
|
|
95
|
+
packageName,
|
|
92
96
|
});
|
|
93
97
|
};
|
|
94
|
-
|
|
98
|
+
const onMessage = async (rawData) => {
|
|
95
99
|
let result;
|
|
96
100
|
let processed = false;
|
|
97
101
|
// Route-specific handling
|
|
@@ -134,4 +138,14 @@ export const processMessageHandlers = (services, channelConfig, channelHandler,
|
|
|
134
138
|
}
|
|
135
139
|
return result;
|
|
136
140
|
};
|
|
141
|
+
const onBinaryMessage = channelConfig.onBinaryMessage
|
|
142
|
+
? async (data) => {
|
|
143
|
+
if (!validateAuth(requiresSession, userSession?.get(), channelConfig)) {
|
|
144
|
+
logger.error(`Channel ${channelConfig.name} with id ${channelHandler.getChannel().channelId} requires a session for binary message`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
return channelConfig.onBinaryMessage(services, data, channelHandler.getChannel());
|
|
148
|
+
}
|
|
149
|
+
: undefined;
|
|
150
|
+
return { onMessage, onBinaryMessage };
|
|
137
151
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { PikkuError } from '../../errors/error-handler.js';
|
|
2
1
|
import type { HTTPFunctionMetaInputTypes, PikkuHTTPRequest, PikkuHTTPResponse } from '../http/http.types.js';
|
|
3
2
|
import type { CorePikkuMiddleware, MiddlewareMetadata, PermissionMetadata } from '../../types/core.types.js';
|
|
3
|
+
export type BinaryData = ArrayBuffer | Uint8Array;
|
|
4
4
|
export type CorePikkuChannelMiddleware<Services = any, Event = unknown> = (services: Services, event: Event, next: (event: Event | Event[] | null) => Promise<void> | void) => Promise<void> | void;
|
|
5
5
|
export type CorePikkuChannelMiddlewareFactory<In = any, Services = any, Event = unknown> = (input: In) => CorePikkuChannelMiddleware<Services, Event>;
|
|
6
6
|
import type { CorePermissionGroup, CorePikkuFunction, CorePikkuFunctionConfig, CorePikkuFunctionSessionless, CorePikkuPermission } from '../../function/functions.types.js';
|
|
@@ -18,6 +18,7 @@ export type RunChannelParams<ChannelData> = {
|
|
|
18
18
|
};
|
|
19
19
|
export interface ChannelMessageMeta {
|
|
20
20
|
pikkuFuncId: string;
|
|
21
|
+
packageName?: string;
|
|
21
22
|
summary?: string;
|
|
22
23
|
description?: string;
|
|
23
24
|
errors?: string[];
|
|
@@ -36,6 +37,7 @@ export interface ChannelMeta {
|
|
|
36
37
|
disconnect: ChannelMessageMeta | null;
|
|
37
38
|
message: ChannelMessageMeta | null;
|
|
38
39
|
messageWirings: Record<string, Record<string, ChannelMessageMeta>>;
|
|
40
|
+
binary?: boolean | null;
|
|
39
41
|
summary?: string;
|
|
40
42
|
description?: string;
|
|
41
43
|
errors?: string[];
|
|
@@ -67,23 +69,21 @@ export type CoreChannel<ChannelData, Channel extends string, ChannelConnect = Co
|
|
|
67
69
|
channelMiddleware?: Array<CorePikkuChannelMiddleware | CorePikkuChannelMiddlewareFactory>;
|
|
68
70
|
permissions?: CorePermissionGroup<PikkuPermission>;
|
|
69
71
|
auth?: boolean;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
response: string;
|
|
73
|
-
errors: Array<typeof PikkuError>;
|
|
74
|
-
tags: string[];
|
|
75
|
-
}>;
|
|
72
|
+
binary?: boolean | null;
|
|
73
|
+
onBinaryMessage?: (services: any, data: BinaryData, channel: PikkuChannel<ChannelData, any>) => Promise<BinaryData | void> | BinaryData | void;
|
|
76
74
|
tags?: string[];
|
|
77
75
|
};
|
|
78
76
|
export interface PikkuChannel<OpeningData, out Out> {
|
|
79
77
|
channelId: string;
|
|
80
78
|
openingData: OpeningData;
|
|
81
79
|
send(data: Out, isBinary?: boolean): Promise<void> | void;
|
|
80
|
+
sendBinary(data: BinaryData): Promise<void> | void;
|
|
82
81
|
close(): Promise<void> | void;
|
|
83
82
|
state: 'initial' | 'open' | 'closed';
|
|
84
83
|
}
|
|
85
84
|
export interface PikkuChannelHandler<OpeningData = unknown, Out = unknown> {
|
|
86
85
|
send(message: Out, isBinary?: boolean): Promise<void> | void;
|
|
86
|
+
sendBinary(data: BinaryData): Promise<void> | void;
|
|
87
87
|
getChannel(): PikkuChannel<OpeningData, Out>;
|
|
88
88
|
}
|
|
89
89
|
export type PikkuChannelHandlerFactory<OpeningData = unknown, Out = unknown> = (channelId: string, channelName: string, openingData: OpeningData) => PikkuChannelHandler<OpeningData, Out>;
|
|
@@ -6,5 +6,5 @@ export type { EventHubService } from './eventhub-service.js';
|
|
|
6
6
|
export { ChannelStore } from './channel-store.js';
|
|
7
7
|
export type { Channel } from './channel-store.js';
|
|
8
8
|
export { EventHubStore } from './eventhub-store.js';
|
|
9
|
-
export type { ChannelsMeta, CoreChannel, CorePikkuChannelMiddleware, CorePikkuChannelMiddlewareFactory, ChannelMessageMeta, ChannelMeta, PikkuChannel, PikkuChannelHandlerFactory, } from './channel.types.js';
|
|
9
|
+
export type { BinaryData, ChannelsMeta, CoreChannel, CorePikkuChannelMiddleware, CorePikkuChannelMiddlewareFactory, ChannelMessageMeta, ChannelMeta, PikkuChannel, PikkuChannelHandlerFactory, } from './channel.types.js';
|
|
10
10
|
export { defineChannelRoutes } from './define-channel-routes.js';
|