@pikku/core 0.12.14 → 0.12.16
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 +36 -0
- package/dist/errors/errors.d.ts +4 -0
- package/dist/errors/errors.js +12 -0
- package/dist/function/function-runner.js +2 -1
- package/dist/function/functions.types.js +1 -0
- package/dist/function/index.d.ts +2 -1
- package/dist/function/index.js +1 -0
- package/dist/handle-error.d.ts +2 -2
- package/dist/handle-error.js +8 -8
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -2
- package/dist/middleware/index.d.ts +3 -0
- package/dist/middleware/index.js +3 -0
- package/dist/middleware/remote-auth.js +5 -2
- package/dist/middleware/telemetry.d.ts +47 -0
- package/dist/middleware/telemetry.js +106 -0
- package/dist/middleware-runner.js +31 -4
- package/dist/permissions.d.ts +13 -1
- package/dist/permissions.js +51 -0
- package/dist/pikku-state.d.ts +0 -1
- package/dist/pikku-state.js +1 -4
- package/dist/remote.d.ts +10 -0
- package/dist/remote.js +32 -0
- package/dist/schema.js +2 -0
- package/dist/services/deployment-service.d.ts +12 -1
- package/dist/services/in-memory-queue-service.d.ts +7 -0
- package/dist/services/in-memory-queue-service.js +28 -0
- package/dist/services/index.d.ts +4 -1
- package/dist/services/index.js +2 -1
- package/dist/services/logger-console.d.ts +26 -40
- package/dist/services/logger-console.js +102 -46
- package/dist/services/logger.d.ts +5 -0
- package/dist/services/meta-service.d.ts +175 -0
- package/dist/services/meta-service.js +310 -0
- package/dist/services/workflow-service.d.ts +6 -1
- package/dist/testing/service-tests.js +0 -8
- package/dist/types/core.types.d.ts +21 -0
- package/dist/types/core.types.js +7 -1
- package/dist/types/state.types.d.ts +2 -2
- package/dist/wirings/ai-agent/ai-agent-prepare.js +42 -21
- package/dist/wirings/ai-agent/ai-agent-registry.js +2 -2
- package/dist/wirings/ai-agent/ai-agent-runner.js +18 -1
- package/dist/wirings/ai-agent/ai-agent-stream.js +1 -0
- package/dist/wirings/ai-agent/ai-agent.types.d.ts +5 -3
- package/dist/wirings/channel/channel-runner.js +3 -3
- package/dist/wirings/cli/cli-runner.js +5 -3
- package/dist/wirings/cli/command-parser.js +7 -3
- package/dist/wirings/http/http-runner.d.ts +1 -1
- package/dist/wirings/http/http-runner.js +23 -11
- package/dist/wirings/http/http.types.d.ts +3 -0
- package/dist/wirings/http/pikku-fetch-http-response.d.ts +1 -0
- package/dist/wirings/http/pikku-fetch-http-response.js +3 -0
- package/dist/wirings/mcp/mcp-runner.js +5 -3
- package/dist/wirings/mcp/mcp.types.d.ts +1 -1
- package/dist/wirings/queue/queue-runner.d.ts +3 -1
- package/dist/wirings/queue/queue-runner.js +7 -3
- package/dist/wirings/rpc/rpc-runner.js +56 -90
- package/dist/wirings/scheduler/scheduler-runner.d.ts +3 -1
- package/dist/wirings/scheduler/scheduler-runner.js +9 -5
- package/dist/wirings/trigger/trigger-runner.js +4 -2
- package/dist/wirings/workflow/dsl/workflow-runner.d.ts +1 -1
- package/dist/wirings/workflow/dsl/workflow-runner.js +6 -9
- package/dist/wirings/workflow/graph/graph-runner.d.ts +1 -1
- package/dist/wirings/workflow/graph/graph-runner.js +18 -4
- package/dist/wirings/workflow/index.d.ts +4 -2
- package/dist/wirings/workflow/index.js +4 -2
- package/dist/wirings/workflow/pikku-workflow-service.d.ts +16 -4
- package/dist/wirings/workflow/pikku-workflow-service.js +216 -24
- package/dist/wirings/workflow/workflow-queue-workers.d.ts +40 -0
- package/dist/wirings/workflow/workflow-queue-workers.js +41 -0
- package/dist/wirings/workflow/workflow.types.d.ts +17 -1
- package/package.json +4 -1
- package/src/errors/errors.ts +12 -0
- package/src/function/function-runner.ts +5 -4
- package/src/function/functions.types.ts +1 -0
- package/src/function/index.ts +10 -0
- package/src/handle-error.test.ts +2 -2
- package/src/handle-error.ts +8 -8
- package/src/index.ts +2 -2
- package/src/middleware/index.ts +3 -0
- package/src/middleware/remote-auth.test.ts +4 -4
- package/src/middleware/remote-auth.ts +7 -2
- package/src/middleware/telemetry.ts +110 -0
- package/src/middleware-runner.test.ts +149 -1
- package/src/middleware-runner.ts +48 -4
- package/src/permissions.ts +70 -0
- package/src/pikku-state.test.ts +0 -26
- package/src/pikku-state.ts +1 -5
- package/src/remote.ts +46 -0
- package/src/schema.ts +1 -0
- package/src/services/deployment-service.ts +17 -1
- package/src/services/in-memory-queue-service.ts +46 -0
- package/src/services/index.ts +21 -1
- package/src/services/logger-console.ts +127 -47
- package/src/services/logger.ts +6 -0
- package/src/services/meta-service.ts +523 -0
- package/src/services/workflow-service.ts +8 -0
- package/src/testing/service-tests.ts +0 -10
- package/src/types/core.types.ts +36 -1
- package/src/types/state.types.ts +2 -2
- package/src/wirings/ai-agent/ai-agent-prepare.ts +51 -40
- package/src/wirings/ai-agent/ai-agent-registry.ts +3 -3
- package/src/wirings/ai-agent/ai-agent-runner.ts +16 -1
- package/src/wirings/ai-agent/ai-agent-stream.ts +8 -0
- package/src/wirings/ai-agent/ai-agent.types.ts +5 -3
- package/src/wirings/channel/channel-runner.ts +4 -5
- package/src/wirings/channel/local/local-channel-runner.test.ts +5 -1
- package/src/wirings/cli/cli-runner.test.ts +8 -7
- package/src/wirings/cli/cli-runner.ts +6 -4
- package/src/wirings/cli/command-parser.ts +8 -3
- package/src/wirings/http/http-runner.ts +27 -11
- package/src/wirings/http/http.types.ts +3 -0
- package/src/wirings/http/pikku-fetch-http-response.ts +4 -0
- package/src/wirings/mcp/mcp-runner.ts +7 -9
- package/src/wirings/mcp/mcp.types.ts +1 -1
- package/src/wirings/queue/queue-runner.test.ts +5 -11
- package/src/wirings/queue/queue-runner.ts +11 -3
- package/src/wirings/rpc/rpc-runner.ts +82 -115
- package/src/wirings/scheduler/scheduler-runner.test.ts +5 -11
- package/src/wirings/scheduler/scheduler-runner.ts +13 -5
- package/src/wirings/trigger/trigger-runner.test.ts +10 -11
- package/src/wirings/trigger/trigger-runner.ts +6 -4
- package/src/wirings/workflow/dsl/workflow-runner.ts +11 -10
- package/src/wirings/workflow/graph/graph-runner.ts +19 -4
- package/src/wirings/workflow/index.ts +17 -6
- package/src/wirings/workflow/pikku-workflow-service.ts +284 -24
- package/src/wirings/workflow/workflow-queue-workers.ts +85 -0
- package/src/wirings/workflow/workflow.types.ts +16 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/dist/wirings/ai-agent/agent-dynamic-workflow.d.ts +0 -6
- package/dist/wirings/ai-agent/agent-dynamic-workflow.js +0 -468
- package/dist/wirings/workflow/workflow-helpers.d.ts +0 -36
- package/dist/wirings/workflow/workflow-helpers.js +0 -38
- package/src/wirings/ai-agent/agent-dynamic-workflow.ts +0 -610
- package/src/wirings/workflow/workflow-helpers.test.ts +0 -129
- package/src/wirings/workflow/workflow-helpers.ts +0 -79
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { readFile, readdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Node.js filesystem implementation of MetaService.
|
|
5
|
+
* Reads .gen.json files from a local .pikku directory.
|
|
6
|
+
*/
|
|
7
|
+
export class LocalMetaService {
|
|
8
|
+
basePath;
|
|
9
|
+
httpMetaCache = null;
|
|
10
|
+
channelsMetaCache = null;
|
|
11
|
+
schedulerMetaCache = null;
|
|
12
|
+
queueMetaCache = null;
|
|
13
|
+
cliMetaCache = null;
|
|
14
|
+
mcpMetaCache = null;
|
|
15
|
+
rpcMetaCache = null;
|
|
16
|
+
workflowMetaCache = null;
|
|
17
|
+
triggerMetaCache = null;
|
|
18
|
+
triggerSourceMetaCache = null;
|
|
19
|
+
functionsMetaCache = null;
|
|
20
|
+
servicesMetaCache = null;
|
|
21
|
+
secretsMetaCache = null;
|
|
22
|
+
credentialsMetaCache = null;
|
|
23
|
+
variablesMetaCache = null;
|
|
24
|
+
middlewareGroupsMetaCache = null;
|
|
25
|
+
permissionsGroupsMetaCache = null;
|
|
26
|
+
agentsMetaCache = null;
|
|
27
|
+
schemaCache = new Map();
|
|
28
|
+
constructor(basePath) {
|
|
29
|
+
this.basePath = basePath;
|
|
30
|
+
}
|
|
31
|
+
async readFile(relativePath) {
|
|
32
|
+
try {
|
|
33
|
+
return await readFile(join(this.basePath, relativePath), 'utf-8');
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async readDir(relativePath) {
|
|
40
|
+
try {
|
|
41
|
+
return await readdir(join(this.basePath, relativePath));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return [];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
clearCache() {
|
|
48
|
+
this.httpMetaCache = null;
|
|
49
|
+
this.channelsMetaCache = null;
|
|
50
|
+
this.schedulerMetaCache = null;
|
|
51
|
+
this.queueMetaCache = null;
|
|
52
|
+
this.cliMetaCache = null;
|
|
53
|
+
this.mcpMetaCache = null;
|
|
54
|
+
this.rpcMetaCache = null;
|
|
55
|
+
this.workflowMetaCache = null;
|
|
56
|
+
this.triggerMetaCache = null;
|
|
57
|
+
this.triggerSourceMetaCache = null;
|
|
58
|
+
this.functionsMetaCache = null;
|
|
59
|
+
this.servicesMetaCache = null;
|
|
60
|
+
this.secretsMetaCache = null;
|
|
61
|
+
this.credentialsMetaCache = null;
|
|
62
|
+
this.variablesMetaCache = null;
|
|
63
|
+
this.middlewareGroupsMetaCache = null;
|
|
64
|
+
this.permissionsGroupsMetaCache = null;
|
|
65
|
+
this.agentsMetaCache = null;
|
|
66
|
+
this.schemaCache.clear();
|
|
67
|
+
}
|
|
68
|
+
// -- Private helpers --
|
|
69
|
+
async readMetaJson(dir, baseName) {
|
|
70
|
+
const verbose = await this.readFile(`${dir}/${baseName}-verbose.gen.json`);
|
|
71
|
+
if (verbose)
|
|
72
|
+
return verbose;
|
|
73
|
+
const minimal = await this.readFile(`${dir}/${baseName}.gen.json`);
|
|
74
|
+
if (minimal)
|
|
75
|
+
return minimal;
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
// -- Typed metadata accessors --
|
|
79
|
+
async getHttpMeta() {
|
|
80
|
+
if (this.httpMetaCache)
|
|
81
|
+
return this.httpMetaCache;
|
|
82
|
+
const content = await this.readMetaJson('http', 'pikku-http-wirings-meta');
|
|
83
|
+
this.httpMetaCache = content
|
|
84
|
+
? JSON.parse(content)
|
|
85
|
+
: {
|
|
86
|
+
get: {},
|
|
87
|
+
post: {},
|
|
88
|
+
put: {},
|
|
89
|
+
delete: {},
|
|
90
|
+
patch: {},
|
|
91
|
+
head: {},
|
|
92
|
+
options: {},
|
|
93
|
+
};
|
|
94
|
+
return this.httpMetaCache;
|
|
95
|
+
}
|
|
96
|
+
async getChannelsMeta() {
|
|
97
|
+
if (this.channelsMetaCache)
|
|
98
|
+
return this.channelsMetaCache;
|
|
99
|
+
const content = await this.readMetaJson('channel', 'pikku-channels-meta');
|
|
100
|
+
this.channelsMetaCache = content ? JSON.parse(content) : {};
|
|
101
|
+
return this.channelsMetaCache;
|
|
102
|
+
}
|
|
103
|
+
async getSchedulerMeta() {
|
|
104
|
+
if (this.schedulerMetaCache)
|
|
105
|
+
return this.schedulerMetaCache;
|
|
106
|
+
const content = await this.readMetaJson('scheduler', 'pikku-schedulers-wirings-meta');
|
|
107
|
+
this.schedulerMetaCache = content ? JSON.parse(content) : {};
|
|
108
|
+
return this.schedulerMetaCache;
|
|
109
|
+
}
|
|
110
|
+
async getQueueMeta() {
|
|
111
|
+
if (this.queueMetaCache)
|
|
112
|
+
return this.queueMetaCache;
|
|
113
|
+
const content = await this.readMetaJson('queue', 'pikku-queue-workers-wirings-meta');
|
|
114
|
+
this.queueMetaCache = content ? JSON.parse(content) : {};
|
|
115
|
+
return this.queueMetaCache;
|
|
116
|
+
}
|
|
117
|
+
async getCliMeta() {
|
|
118
|
+
if (this.cliMetaCache)
|
|
119
|
+
return this.cliMetaCache;
|
|
120
|
+
const content = await this.readMetaJson('cli', 'pikku-cli-wirings-meta');
|
|
121
|
+
this.cliMetaCache = content
|
|
122
|
+
? JSON.parse(content)
|
|
123
|
+
: { programs: {}, renderers: {} };
|
|
124
|
+
return this.cliMetaCache;
|
|
125
|
+
}
|
|
126
|
+
async getMcpMeta() {
|
|
127
|
+
if (this.mcpMetaCache)
|
|
128
|
+
return this.mcpMetaCache;
|
|
129
|
+
const content = await this.readMetaJson('mcp', 'pikku-mcp-wirings-meta');
|
|
130
|
+
if (content) {
|
|
131
|
+
const mcpData = JSON.parse(content);
|
|
132
|
+
this.mcpMetaCache = {
|
|
133
|
+
resources: mcpData.resourcesMeta || {},
|
|
134
|
+
tools: mcpData.toolsMeta || {},
|
|
135
|
+
prompts: mcpData.promptsMeta || {},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
this.mcpMetaCache = { resources: {}, tools: {}, prompts: {} };
|
|
140
|
+
}
|
|
141
|
+
return this.mcpMetaCache;
|
|
142
|
+
}
|
|
143
|
+
async getRpcMeta() {
|
|
144
|
+
if (this.rpcMetaCache)
|
|
145
|
+
return this.rpcMetaCache;
|
|
146
|
+
try {
|
|
147
|
+
const content = await this.readFile('rpc/pikku-rpc-wirings-meta.gen.json');
|
|
148
|
+
this.rpcMetaCache = content ? JSON.parse(content) : {};
|
|
149
|
+
return this.rpcMetaCache;
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
console.error('Error reading RPC wirings metadata:', error);
|
|
153
|
+
this.rpcMetaCache = {};
|
|
154
|
+
return this.rpcMetaCache;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async getWorkflowMeta() {
|
|
158
|
+
if (this.workflowMetaCache)
|
|
159
|
+
return this.workflowMetaCache;
|
|
160
|
+
try {
|
|
161
|
+
const files = await this.readDir('workflow/meta');
|
|
162
|
+
const jsonFiles = files.filter((f) => f.endsWith('.gen.json'));
|
|
163
|
+
const verboseFiles = jsonFiles.filter((f) => f.includes('-verbose'));
|
|
164
|
+
const minimalFiles = jsonFiles.filter((f) => !f.includes('-verbose'));
|
|
165
|
+
const verboseNames = new Set(verboseFiles.map((f) => f.replace('-verbose.gen.json', '')));
|
|
166
|
+
const filesToRead = [
|
|
167
|
+
...verboseFiles,
|
|
168
|
+
...minimalFiles.filter((f) => !verboseNames.has(f.replace('.gen.json', ''))),
|
|
169
|
+
];
|
|
170
|
+
const result = {};
|
|
171
|
+
await Promise.all(filesToRead.map(async (file) => {
|
|
172
|
+
const content = await this.readFile(`workflow/meta/${file}`);
|
|
173
|
+
if (content) {
|
|
174
|
+
const meta = JSON.parse(content);
|
|
175
|
+
result[meta.name] = meta;
|
|
176
|
+
}
|
|
177
|
+
}));
|
|
178
|
+
this.workflowMetaCache = result;
|
|
179
|
+
return this.workflowMetaCache;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
console.error('Error reading Workflow wirings metadata:', error);
|
|
183
|
+
this.workflowMetaCache = {};
|
|
184
|
+
return this.workflowMetaCache;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async getTriggerMeta() {
|
|
188
|
+
if (this.triggerMetaCache)
|
|
189
|
+
return this.triggerMetaCache;
|
|
190
|
+
const content = await this.readMetaJson('trigger', 'pikku-trigger-wirings-meta');
|
|
191
|
+
this.triggerMetaCache = content ? JSON.parse(content) : {};
|
|
192
|
+
return this.triggerMetaCache;
|
|
193
|
+
}
|
|
194
|
+
async getTriggerSourceMeta() {
|
|
195
|
+
if (this.triggerSourceMetaCache)
|
|
196
|
+
return this.triggerSourceMetaCache;
|
|
197
|
+
const content = await this.readMetaJson('trigger', 'pikku-trigger-sources-meta');
|
|
198
|
+
this.triggerSourceMetaCache = content ? JSON.parse(content) : {};
|
|
199
|
+
return this.triggerSourceMetaCache;
|
|
200
|
+
}
|
|
201
|
+
async getFunctionsMeta() {
|
|
202
|
+
if (this.functionsMetaCache)
|
|
203
|
+
return this.functionsMetaCache;
|
|
204
|
+
const content = await this.readMetaJson('function', 'pikku-functions-meta');
|
|
205
|
+
this.functionsMetaCache = content ? JSON.parse(content) : {};
|
|
206
|
+
return this.functionsMetaCache;
|
|
207
|
+
}
|
|
208
|
+
async getMiddlewareGroupsMeta() {
|
|
209
|
+
if (this.middlewareGroupsMetaCache)
|
|
210
|
+
return this.middlewareGroupsMetaCache;
|
|
211
|
+
const content = await this.readMetaJson('middleware', 'pikku-middleware-groups-meta');
|
|
212
|
+
this.middlewareGroupsMetaCache = content
|
|
213
|
+
? JSON.parse(content)
|
|
214
|
+
: { definitions: {}, instances: {}, httpGroups: {}, tagGroups: {} };
|
|
215
|
+
return this.middlewareGroupsMetaCache;
|
|
216
|
+
}
|
|
217
|
+
async getPermissionsGroupsMeta() {
|
|
218
|
+
if (this.permissionsGroupsMetaCache)
|
|
219
|
+
return this.permissionsGroupsMetaCache;
|
|
220
|
+
const content = await this.readMetaJson('permissions', 'pikku-permissions-groups-meta');
|
|
221
|
+
this.permissionsGroupsMetaCache = content
|
|
222
|
+
? JSON.parse(content)
|
|
223
|
+
: { definitions: {}, httpGroups: {}, tagGroups: {} };
|
|
224
|
+
return this.permissionsGroupsMetaCache;
|
|
225
|
+
}
|
|
226
|
+
async getAgentsMeta() {
|
|
227
|
+
if (this.agentsMetaCache)
|
|
228
|
+
return this.agentsMetaCache;
|
|
229
|
+
const content = await this.readMetaJson('agent', 'pikku-agent-wirings-meta');
|
|
230
|
+
if (content) {
|
|
231
|
+
const parsed = JSON.parse(content);
|
|
232
|
+
this.agentsMetaCache = parsed.agentsMeta || parsed;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
this.agentsMetaCache = {};
|
|
236
|
+
}
|
|
237
|
+
return this.agentsMetaCache;
|
|
238
|
+
}
|
|
239
|
+
async getSecretsMeta() {
|
|
240
|
+
if (this.secretsMetaCache)
|
|
241
|
+
return this.secretsMetaCache;
|
|
242
|
+
const content = await this.readFile('secrets/pikku-secrets-meta.gen.json');
|
|
243
|
+
this.secretsMetaCache = content ? JSON.parse(content) : {};
|
|
244
|
+
return this.secretsMetaCache;
|
|
245
|
+
}
|
|
246
|
+
async getCredentialsMeta() {
|
|
247
|
+
if (this.credentialsMetaCache)
|
|
248
|
+
return this.credentialsMetaCache;
|
|
249
|
+
const content = await this.readFile('credentials/pikku-credentials-meta.gen.json');
|
|
250
|
+
this.credentialsMetaCache = content ? JSON.parse(content) : {};
|
|
251
|
+
return this.credentialsMetaCache;
|
|
252
|
+
}
|
|
253
|
+
async getVariablesMeta() {
|
|
254
|
+
if (this.variablesMetaCache)
|
|
255
|
+
return this.variablesMetaCache;
|
|
256
|
+
const content = await this.readFile('variables/pikku-variables-meta.gen.json');
|
|
257
|
+
this.variablesMetaCache = content ? JSON.parse(content) : {};
|
|
258
|
+
return this.variablesMetaCache;
|
|
259
|
+
}
|
|
260
|
+
async getServicesMeta() {
|
|
261
|
+
if (this.servicesMetaCache)
|
|
262
|
+
return this.servicesMetaCache;
|
|
263
|
+
try {
|
|
264
|
+
const files = await this.readDir('services');
|
|
265
|
+
const jsonFiles = files.filter((f) => f.endsWith('.gen.json'));
|
|
266
|
+
const result = {};
|
|
267
|
+
await Promise.all(jsonFiles.map(async (file) => {
|
|
268
|
+
const content = await this.readFile(`services/${file}`);
|
|
269
|
+
if (content) {
|
|
270
|
+
const meta = JSON.parse(content);
|
|
271
|
+
result[meta.name] = meta;
|
|
272
|
+
}
|
|
273
|
+
}));
|
|
274
|
+
this.servicesMetaCache = result;
|
|
275
|
+
return this.servicesMetaCache;
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
console.error('Error reading Services metadata:', error);
|
|
279
|
+
this.servicesMetaCache = {};
|
|
280
|
+
return this.servicesMetaCache;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
async getSchema(schemaName) {
|
|
284
|
+
if (this.schemaCache.has(schemaName)) {
|
|
285
|
+
return this.schemaCache.get(schemaName);
|
|
286
|
+
}
|
|
287
|
+
if (!/^[a-zA-Z0-9_\-\.]+$/.test(schemaName)) {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
try {
|
|
291
|
+
const content = await this.readFile(`schemas/schemas/${schemaName}.schema.json`);
|
|
292
|
+
if (!content)
|
|
293
|
+
return null;
|
|
294
|
+
const schema = JSON.parse(content);
|
|
295
|
+
this.schemaCache.set(schemaName, schema);
|
|
296
|
+
return schema;
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
console.error(`Error reading schema ${schemaName}:`, error);
|
|
300
|
+
return null;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
async getSchemas(schemaNames) {
|
|
304
|
+
const results = {};
|
|
305
|
+
await Promise.all(schemaNames.map(async (name) => {
|
|
306
|
+
results[name] = await this.getSchema(name);
|
|
307
|
+
}));
|
|
308
|
+
return results;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SerializedError } from '../types/core.types.js';
|
|
2
|
-
import type { WorkflowRun, WorkflowRunWire, StepState, WorkflowStatus, WorkflowVersionStatus } from '../wirings/workflow/workflow.types.js';
|
|
2
|
+
import type { WorkflowRun, WorkflowRunWire, WorkflowRunStatus, StepState, WorkflowStatus, WorkflowVersionStatus } from '../wirings/workflow/workflow.types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Interface for workflow orchestration
|
|
5
5
|
* Handles workflow execution, replay, orchestration logic, and run-level state
|
|
@@ -7,6 +7,7 @@ import type { WorkflowRun, WorkflowRunWire, StepState, WorkflowStatus, WorkflowV
|
|
|
7
7
|
export interface WorkflowService {
|
|
8
8
|
createRun(workflowName: string, input: any, inline: boolean, graphHash: string, wire: WorkflowRunWire): Promise<string>;
|
|
9
9
|
getRun(id: string): Promise<WorkflowRun | null>;
|
|
10
|
+
getRunStatus(id: string): Promise<WorkflowRunStatus | null>;
|
|
10
11
|
getRunHistory(runId: string): Promise<Array<StepState & {
|
|
11
12
|
stepName: string;
|
|
12
13
|
}>>;
|
|
@@ -20,6 +21,10 @@ export interface WorkflowService {
|
|
|
20
21
|
}): Promise<{
|
|
21
22
|
runId: string;
|
|
22
23
|
}>;
|
|
24
|
+
runToCompletion<I>(name: string, input: I, rpcService: any, options?: {
|
|
25
|
+
pollIntervalMs?: number;
|
|
26
|
+
wire?: WorkflowRunWire;
|
|
27
|
+
}): Promise<unknown>;
|
|
23
28
|
runWorkflowJob(runId: string, rpcService: any): Promise<void>;
|
|
24
29
|
orchestrateWorkflow(runId: string, rpcService: any): Promise<void>;
|
|
25
30
|
executeWorkflowSleepCompleted(runId: string, stepId: string): Promise<void>;
|
|
@@ -482,14 +482,6 @@ export function defineServiceTests(config) {
|
|
|
482
482
|
endpoint: 'http://localhost:3000',
|
|
483
483
|
functions: ['funcA', 'funcB'],
|
|
484
484
|
});
|
|
485
|
-
const infos = await service.findFunction('funcA');
|
|
486
|
-
assert.ok(infos.length >= 1);
|
|
487
|
-
assert.equal(infos[0].deploymentId, 'deploy-1');
|
|
488
|
-
assert.equal(infos[0].endpoint, 'http://localhost:3000');
|
|
489
|
-
});
|
|
490
|
-
test('findFunction returns empty for unknown function', async () => {
|
|
491
|
-
const infos = await service.findFunction('unknown-func');
|
|
492
|
-
assert.deepEqual(infos, []);
|
|
493
485
|
});
|
|
494
486
|
});
|
|
495
487
|
}
|
|
@@ -24,6 +24,7 @@ import type { AgentRunService } from '../wirings/ai-agent/ai-agent.types.js';
|
|
|
24
24
|
import type { PikkuAIMiddlewareHooks } from '../wirings/ai-agent/ai-agent.types.js';
|
|
25
25
|
import type { WorkflowRunService } from '../wirings/workflow/workflow.types.js';
|
|
26
26
|
import type { CredentialService } from '../services/credential-service.js';
|
|
27
|
+
import type { MetaService } from '../services/meta-service.js';
|
|
27
28
|
export type PikkuWiringTypes = 'http' | 'scheduler' | 'trigger' | 'channel' | 'rpc' | 'queue' | 'mcp' | 'cli' | 'workflow' | 'agent' | 'gateway';
|
|
28
29
|
export interface FunctionServicesMeta {
|
|
29
30
|
optimized: boolean;
|
|
@@ -75,6 +76,7 @@ export type FunctionRuntimeMeta = {
|
|
|
75
76
|
remote?: boolean;
|
|
76
77
|
mcp?: boolean;
|
|
77
78
|
readonly?: boolean;
|
|
79
|
+
deploy?: 'serverless' | 'server' | 'auto';
|
|
78
80
|
sessionless?: boolean;
|
|
79
81
|
version?: number;
|
|
80
82
|
approvalRequired?: boolean;
|
|
@@ -94,6 +96,8 @@ export type FunctionMeta = FunctionRuntimeMeta & Partial<{
|
|
|
94
96
|
middleware: MiddlewareMetadata[];
|
|
95
97
|
permissions: PermissionMetadata[];
|
|
96
98
|
isDirectFunction: boolean;
|
|
99
|
+
sourceFile: string;
|
|
100
|
+
exportedName: string;
|
|
97
101
|
} & CommonWireMeta>;
|
|
98
102
|
export type FunctionsRuntimeMeta = Record<string, FunctionRuntimeMeta>;
|
|
99
103
|
export type FunctionsMeta = Record<string, FunctionMeta>;
|
|
@@ -175,6 +179,8 @@ export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
|
|
|
175
179
|
workflowRunService?: WorkflowRunService;
|
|
176
180
|
/** Credential service for dynamic/managed credentials (OAuth tokens, per-user API keys) */
|
|
177
181
|
credentialService?: CredentialService;
|
|
182
|
+
/** Meta service for reading .pikku metadata files (filesystem on Node, R2/KV on CF) */
|
|
183
|
+
metaService?: MetaService;
|
|
178
184
|
}
|
|
179
185
|
/**
|
|
180
186
|
* Represents different forms of wire within Pikku and the outside world.
|
|
@@ -182,6 +188,8 @@ export interface CoreSingletonServices<Config extends CoreConfig = CoreConfig> {
|
|
|
182
188
|
export type PikkuWire<In = unknown, Out = unknown, HasInitialSession extends boolean = false, UserSession extends CoreUserSession = CoreUserSession, TypedRPC extends PikkuRPC = PikkuRPC, IsChannel extends true | null = null, MCPTools extends string | never = never, TypedWorkflow extends PikkuWorkflowWire | never = PikkuWorkflowWire, TriggerOutput = unknown> = Partial<{
|
|
183
189
|
wireType: PikkuWiringTypes;
|
|
184
190
|
wireId: string;
|
|
191
|
+
/** Trace ID for distributed tracing — propagated across remote RPC calls via x-trace-id header */
|
|
192
|
+
traceId: string;
|
|
185
193
|
http: PikkuHTTP<In>;
|
|
186
194
|
mcp: PikkuMCP<MCPTools>;
|
|
187
195
|
rpc: TypedRPC;
|
|
@@ -216,6 +224,17 @@ export type PikkuWire<In = unknown, Out = unknown, HasInitialSession extends boo
|
|
|
216
224
|
* A function that can wrap an wire and be called before or after
|
|
217
225
|
*/
|
|
218
226
|
export type CorePikkuMiddleware<SingletonServices extends CoreSingletonServices = CoreSingletonServices, UserSession extends CoreUserSession = CoreUserSession> = (services: SingletonServices, wires: PikkuWire<unknown, unknown, false, UserSession>, next: () => Promise<void>) => Promise<void>;
|
|
227
|
+
/**
|
|
228
|
+
* Priority levels for middleware execution order.
|
|
229
|
+
* Lower priority runs first (outermost in the onion model).
|
|
230
|
+
*
|
|
231
|
+
* - `highest` — Runs first (outermost). Use for telemetry, request tracing.
|
|
232
|
+
* - `high` — Runs early. Use for CORS, rate limiting.
|
|
233
|
+
* - `medium` — Default. Use for auth, most user middleware.
|
|
234
|
+
* - `low` — Runs late. Use for post-auth processing.
|
|
235
|
+
* - `lowest` — Runs last (innermost, closest to function). Use for inner telemetry.
|
|
236
|
+
*/
|
|
237
|
+
export type MiddlewarePriority = 'highest' | 'high' | 'medium' | 'low' | 'lowest';
|
|
219
238
|
/**
|
|
220
239
|
* Configuration object for creating middleware with metadata
|
|
221
240
|
*
|
|
@@ -229,6 +248,8 @@ export type CorePikkuMiddlewareConfig<SingletonServices extends CoreSingletonSer
|
|
|
229
248
|
name?: string;
|
|
230
249
|
/** Optional description of what the middleware does */
|
|
231
250
|
description?: string;
|
|
251
|
+
/** Execution priority. Lower runs first (outermost). Defaults to 'medium'. */
|
|
252
|
+
priority?: MiddlewarePriority;
|
|
232
253
|
};
|
|
233
254
|
/**
|
|
234
255
|
* A factory function that takes input and returns middleware
|
package/dist/types/core.types.js
CHANGED
|
@@ -24,7 +24,13 @@
|
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
export const pikkuMiddleware = (middleware) => {
|
|
27
|
-
|
|
27
|
+
if (typeof middleware === 'function')
|
|
28
|
+
return middleware;
|
|
29
|
+
const func = middleware.func;
|
|
30
|
+
if (middleware.priority) {
|
|
31
|
+
func.__priority = middleware.priority;
|
|
32
|
+
}
|
|
33
|
+
return func;
|
|
28
34
|
};
|
|
29
35
|
/**
|
|
30
36
|
* Factory function for creating middleware factories
|
|
@@ -130,8 +130,6 @@ export interface PikkuPackageState {
|
|
|
130
130
|
} | null;
|
|
131
131
|
/** Cached singleton services for this package */
|
|
132
132
|
singletonServices: CoreSingletonServices | null;
|
|
133
|
-
/** Absolute path to this package's .pikku directory */
|
|
134
|
-
metaDir: string | null;
|
|
135
133
|
/** Credential metadata for this addon package */
|
|
136
134
|
credentialsMeta: Record<string, {
|
|
137
135
|
name: string;
|
|
@@ -139,5 +137,7 @@ export interface PikkuPackageState {
|
|
|
139
137
|
type: string;
|
|
140
138
|
oauth2?: boolean;
|
|
141
139
|
}> | null;
|
|
140
|
+
/** Services this addon needs from the parent project */
|
|
141
|
+
requiredParentServices: string[] | null;
|
|
142
142
|
};
|
|
143
143
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PikkuError } from '../../errors/error-handler.js';
|
|
2
|
+
import { checkAuthPermissions } from '../../permissions.js';
|
|
2
3
|
import { AIProviderNotConfiguredError } from '../../errors/errors.js';
|
|
3
4
|
import { pikkuState, getSingletonServices } from '../../pikku-state.js';
|
|
4
5
|
import { createMiddlewareSessionWireProps } from '../../services/user-session-service.js';
|
|
@@ -6,7 +7,6 @@ import { randomUUID } from 'crypto';
|
|
|
6
7
|
import { streamAIAgent } from './ai-agent-stream.js';
|
|
7
8
|
import { runAIAgent } from './ai-agent-runner.js';
|
|
8
9
|
import { resolveNamespace, ContextAwareRPCService, } from '../../wirings/rpc/rpc-runner.js';
|
|
9
|
-
import { buildDynamicWorkflowInstructions, buildWorkflowTools, } from './agent-dynamic-workflow.js';
|
|
10
10
|
import { resolveMemoryServices, loadContextMessages, trimMessages, } from './ai-agent-memory.js';
|
|
11
11
|
import { resolveModelConfig } from './ai-agent-model-config.js';
|
|
12
12
|
export class ToolApprovalRequired extends PikkuError {
|
|
@@ -75,6 +75,10 @@ export function getAddonCredentialRequirements(toolNames) {
|
|
|
75
75
|
return [...requirements.values()];
|
|
76
76
|
}
|
|
77
77
|
export const resolveAgent = (agentName) => {
|
|
78
|
+
if (!agentName) {
|
|
79
|
+
console.error('[resolveAgent] agentName is undefined/null! Stack:', new Error().stack);
|
|
80
|
+
throw new Error('resolveAgent called with undefined agentName');
|
|
81
|
+
}
|
|
78
82
|
const mainAgent = pikkuState(null, 'agent', 'agents').get(agentName);
|
|
79
83
|
if (mainAgent) {
|
|
80
84
|
return { agent: mainAgent, packageName: null, resolvedName: agentName };
|
|
@@ -100,10 +104,23 @@ export const resolveAgent = (agentName) => {
|
|
|
100
104
|
};
|
|
101
105
|
export async function buildInstructions(agentName, packageName) {
|
|
102
106
|
const meta = pikkuState(packageName, 'agent', 'agentsMeta')[agentName];
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
const parts = [];
|
|
108
|
+
if (meta?.role)
|
|
109
|
+
parts.push(meta.role);
|
|
110
|
+
if (meta?.personality)
|
|
111
|
+
parts.push(meta.personality);
|
|
112
|
+
if (meta?.goal)
|
|
113
|
+
parts.push(meta.goal);
|
|
114
|
+
let instructions = parts.join('\n\n');
|
|
115
|
+
if (meta?.tools?.length) {
|
|
116
|
+
instructions +=
|
|
117
|
+
'\n\nTool usage rules:\n' +
|
|
118
|
+
'- Act immediately with the information given. Do NOT ask clarifying questions unless a required field is truly missing.\n' +
|
|
119
|
+
'- Only use fields defined in your tool schemas. Never mention or ask for fields that do not exist.\n' +
|
|
120
|
+
'- Never fill optional fields with placeholder or zero values. Omit them entirely unless the user provides a real value.\n' +
|
|
121
|
+
'- Never stuff unrelated information into the wrong field.\n' +
|
|
122
|
+
'- Keep responses concise.';
|
|
123
|
+
}
|
|
107
124
|
if (meta?.agents?.length) {
|
|
108
125
|
instructions +=
|
|
109
126
|
'\n\nWhen calling a sub-agent, provide a short session name that describes the task. ' +
|
|
@@ -111,9 +128,6 @@ export async function buildInstructions(agentName, packageName) {
|
|
|
111
128
|
'Use a new session name for a new independent task. ' +
|
|
112
129
|
'When a request involves multiple actions for the same domain, combine them into a single sub-agent call rather than making separate calls.';
|
|
113
130
|
}
|
|
114
|
-
if (meta?.dynamicWorkflows && meta.tools?.length) {
|
|
115
|
-
instructions += buildDynamicWorkflowInstructions(meta.tools, meta.dynamicWorkflows);
|
|
116
|
-
}
|
|
117
131
|
return instructions;
|
|
118
132
|
}
|
|
119
133
|
export function createScopedChannel(parent, agentName, session) {
|
|
@@ -165,6 +179,10 @@ export async function buildToolDefs(params, agentSessionMap, resourceId, agentNa
|
|
|
165
179
|
const meta = pikkuState(packageName, 'agent', 'agentsMeta')[agentName];
|
|
166
180
|
if (!meta)
|
|
167
181
|
return { tools, missingRpcs };
|
|
182
|
+
// Get session for permission filtering
|
|
183
|
+
const session = params.sessionService
|
|
184
|
+
? await params.sessionService.get()
|
|
185
|
+
: null;
|
|
168
186
|
const metaTools = meta.tools;
|
|
169
187
|
const metaAgents = meta.agents;
|
|
170
188
|
if (metaTools?.length) {
|
|
@@ -196,6 +214,14 @@ export async function buildToolDefs(params, agentSessionMap, resourceId, agentNa
|
|
|
196
214
|
missingRpcs.push(toolName);
|
|
197
215
|
continue;
|
|
198
216
|
}
|
|
217
|
+
// Filter out tools the user doesn't have auth for
|
|
218
|
+
if (fnMeta.permissions?.length) {
|
|
219
|
+
if (!session)
|
|
220
|
+
continue;
|
|
221
|
+
const allowed = await checkAuthPermissions(fnMeta.permissions, session, singletonServices, resolvedPkg);
|
|
222
|
+
if (!allowed)
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
199
225
|
const inputSchemaName = fnMeta?.inputSchemaName;
|
|
200
226
|
let inputSchema = inputSchemaName
|
|
201
227
|
? schemas.get(inputSchemaName)
|
|
@@ -251,6 +277,14 @@ export async function buildToolDefs(params, agentSessionMap, resourceId, agentNa
|
|
|
251
277
|
singletonServices.logger.warn(`Sub-agent '${subAgentName}' not found in agent registry`);
|
|
252
278
|
continue;
|
|
253
279
|
}
|
|
280
|
+
// Filter out sub-agents the user doesn't have auth for
|
|
281
|
+
if (subMeta.permissions?.length) {
|
|
282
|
+
if (!session)
|
|
283
|
+
continue;
|
|
284
|
+
const allowed = await checkAuthPermissions(subMeta.permissions, session, singletonServices);
|
|
285
|
+
if (!allowed)
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
254
288
|
tools.push({
|
|
255
289
|
name: subAgentName,
|
|
256
290
|
description: subMeta.description,
|
|
@@ -339,10 +373,6 @@ export async function buildToolDefs(params, agentSessionMap, resourceId, agentNa
|
|
|
339
373
|
});
|
|
340
374
|
}
|
|
341
375
|
}
|
|
342
|
-
if (meta.dynamicWorkflows) {
|
|
343
|
-
const workflowTools = buildWorkflowTools(agentName, packageName, meta.tools ?? [], meta.dynamicWorkflows, streamContext, params.sessionService);
|
|
344
|
-
tools.push(...workflowTools);
|
|
345
|
-
}
|
|
346
376
|
const hasToolHooks = aiMiddlewares?.some((mw) => mw.beforeToolCall || mw.afterToolCall);
|
|
347
377
|
if (hasToolHooks) {
|
|
348
378
|
for (const tool of tools) {
|
|
@@ -405,15 +435,6 @@ export async function prepareAgentRun(agentName, input, params, agentSessionMap,
|
|
|
405
435
|
if (!agentRunner) {
|
|
406
436
|
throw new AIProviderNotConfiguredError();
|
|
407
437
|
}
|
|
408
|
-
if (agent.dynamicWorkflows && singletonServices.workflowService) {
|
|
409
|
-
const persisted = await singletonServices.workflowService.getAIGeneratedWorkflows(resolvedName);
|
|
410
|
-
const allMeta = pikkuState(null, 'workflows', 'meta');
|
|
411
|
-
for (const wf of persisted) {
|
|
412
|
-
if (!allMeta[wf.workflowName]) {
|
|
413
|
-
allMeta[wf.workflowName] = wf.graph;
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
438
|
const { storage } = resolveMemoryServices(agent, singletonServices);
|
|
418
439
|
const memoryConfig = agent.memory;
|
|
419
440
|
const threadId = input.threadId;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { pikkuState } from '../../pikku-state.js';
|
|
2
|
-
import { PikkuMissingMetaError } from '../../errors/errors.js';
|
|
3
2
|
export const addAIAgent = (agentName, agent, packageName = null) => {
|
|
4
3
|
const agentsMeta = pikkuState(packageName, 'agent', 'agentsMeta');
|
|
5
4
|
const agentMeta = agentsMeta[agentName];
|
|
6
5
|
if (!agentMeta) {
|
|
7
|
-
|
|
6
|
+
console.warn(`[pikku] Skipping AI agent '${agentName}' — metadata not found. Consider moving this wiring to its own file.`);
|
|
7
|
+
return;
|
|
8
8
|
}
|
|
9
9
|
const agents = pikkuState(packageName, 'agent', 'agents');
|
|
10
10
|
if (agents.has(agentName)) {
|
|
@@ -4,6 +4,21 @@ import { checkForApprovals, appendStepMessages } from './ai-agent-stream.js';
|
|
|
4
4
|
import { pikkuState, getSingletonServices } from '../../pikku-state.js';
|
|
5
5
|
import { resolveModelConfig } from './ai-agent-model-config.js';
|
|
6
6
|
import { AIProviderNotConfiguredError } from '../../errors/errors.js';
|
|
7
|
+
function stripNulls(obj) {
|
|
8
|
+
if (obj === null)
|
|
9
|
+
return undefined;
|
|
10
|
+
if (Array.isArray(obj))
|
|
11
|
+
return obj.map(stripNulls);
|
|
12
|
+
if (typeof obj !== 'object')
|
|
13
|
+
return obj;
|
|
14
|
+
const result = {};
|
|
15
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
16
|
+
if (value !== null) {
|
|
17
|
+
result[key] = stripNulls(value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return result;
|
|
21
|
+
}
|
|
7
22
|
import { randomUUID } from 'crypto';
|
|
8
23
|
export async function runAIAgent(agentName, input, params, agentSessionMap) {
|
|
9
24
|
const sessionMap = agentSessionMap ?? new Map();
|
|
@@ -287,9 +302,11 @@ export async function resumeAIAgentSync(runId, approvals, params, expectedAgentN
|
|
|
287
302
|
if (!matchingTool) {
|
|
288
303
|
throw new Error(`Tool "${pending.toolName}" not found in agent definition`);
|
|
289
304
|
}
|
|
290
|
-
const
|
|
305
|
+
const rawArgs = typeof pending.args === 'string'
|
|
291
306
|
? JSON.parse(pending.args)
|
|
292
307
|
: pending.args;
|
|
308
|
+
// Strip null values recursively — LLMs send null for optional fields but Zod expects undefined
|
|
309
|
+
const toolArgs = stripNulls(rawArgs) ?? {};
|
|
293
310
|
try {
|
|
294
311
|
const toolResult = await matchingTool.execute(toolArgs);
|
|
295
312
|
resultStr =
|
|
@@ -733,6 +733,7 @@ async function continueAfterToolResult(run, agent, packageName, resolvedName, st
|
|
|
733
733
|
const streamContext = { channel, options };
|
|
734
734
|
const resumeTools = (await buildToolDefs(params, new Map(), run.resourceId, resolvedName, packageName, streamContext, aiMiddlewares)).tools;
|
|
735
735
|
const resolved = resolveModelConfig(resolvedName, agent);
|
|
736
|
+
console.log('[DEBUG resume] resolvedName:', resolvedName, 'agent.model:', agent.model, 'resolved.model:', resolved.model);
|
|
736
737
|
const maxSteps = resolved.maxSteps ?? 10;
|
|
737
738
|
const runnerParams = {
|
|
738
739
|
model: resolved.model,
|
|
@@ -183,7 +183,9 @@ export type CoreAIAgent<PikkuPermission = CorePikkuPermission<any, any>, PikkuMi
|
|
|
183
183
|
description: string;
|
|
184
184
|
summary?: string;
|
|
185
185
|
errors?: string[];
|
|
186
|
-
|
|
186
|
+
role?: string;
|
|
187
|
+
personality?: string;
|
|
188
|
+
goal: string;
|
|
187
189
|
model: string;
|
|
188
190
|
temperature?: number;
|
|
189
191
|
tools?: unknown[];
|
|
@@ -192,7 +194,6 @@ export type CoreAIAgent<PikkuPermission = CorePikkuPermission<any, any>, PikkuMi
|
|
|
192
194
|
memory?: AIAgentMemoryConfig;
|
|
193
195
|
maxSteps?: number;
|
|
194
196
|
toolChoice?: 'auto' | 'required' | 'none';
|
|
195
|
-
dynamicWorkflows?: 'read' | 'always' | 'ask';
|
|
196
197
|
input?: unknown;
|
|
197
198
|
output?: unknown;
|
|
198
199
|
tags?: string[];
|
|
@@ -382,5 +383,6 @@ export type AIAgentMeta = Record<string, Omit<CoreAIAgent, 'input' | 'output' |
|
|
|
382
383
|
channelMiddleware?: MiddlewareMetadata[];
|
|
383
384
|
aiMiddleware?: MiddlewareMetadata[];
|
|
384
385
|
permissions?: PermissionMetadata[];
|
|
385
|
-
|
|
386
|
+
sourceFile?: string;
|
|
387
|
+
exportedName?: string;
|
|
386
388
|
}>;
|