@pikku/core 0.12.14 → 0.12.15
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 +30 -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 +1 -2
- package/dist/index.js +1 -2
- package/dist/middleware/index.d.ts +2 -0
- package/dist/middleware/index.js +2 -0
- package/dist/middleware/remote-auth.js +5 -2
- 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 +8 -0
- 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 +3 -2
- 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 +2 -0
- package/dist/wirings/mcp/mcp-runner.js +5 -3
- 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 +1 -2
- package/src/middleware/index.ts +2 -0
- package/src/middleware/remote-auth.test.ts +4 -4
- package/src/middleware/remote-auth.ts +7 -2
- 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 +8 -0
- 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/cli/cli-runner.test.ts +8 -7
- package/src/wirings/cli/cli-runner.ts +4 -3
- 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 +2 -0
- package/src/wirings/mcp/mcp-runner.ts +7 -9
- 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
|
@@ -3,7 +3,6 @@ import { pikkuState } from '../../pikku-state.js';
|
|
|
3
3
|
import { ForbiddenError } from '../../errors/errors.js';
|
|
4
4
|
import { PikkuError, addError } from '../../errors/error-handler.js';
|
|
5
5
|
import { parseVersionedId } from '../../version.js';
|
|
6
|
-
import { encryptJSON } from '../../crypto-utils.js';
|
|
7
6
|
export class RPCNotFoundError extends PikkuError {
|
|
8
7
|
rpcName;
|
|
9
8
|
constructor(rpcName) {
|
|
@@ -95,17 +94,38 @@ export class ContextAwareRPCService {
|
|
|
95
94
|
}
|
|
96
95
|
: undefined,
|
|
97
96
|
};
|
|
98
|
-
// Check
|
|
97
|
+
// Check addon namespace first (e.g. 'stripe:createCharge')
|
|
99
98
|
if (funcName.includes(':')) {
|
|
100
|
-
|
|
99
|
+
try {
|
|
100
|
+
return await this.invokeAddonFunction(funcName, data, updatedWire);
|
|
101
|
+
}
|
|
102
|
+
catch (addonErr) {
|
|
103
|
+
if (!(addonErr instanceof RPCNotFoundError))
|
|
104
|
+
throw addonErr;
|
|
105
|
+
// Not an addon — fall through to local lookup
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Try local function, then fall back to deployment service (remote)
|
|
109
|
+
try {
|
|
110
|
+
return await runPikkuFunc('rpc', funcName, getPikkuFunctionName(funcName), {
|
|
111
|
+
auth: this.options.requiresAuth,
|
|
112
|
+
singletonServices: this.services,
|
|
113
|
+
data: () => data,
|
|
114
|
+
wire: updatedWire,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
catch (e) {
|
|
118
|
+
if (e instanceof RPCNotFoundError) {
|
|
119
|
+
// Fall back to deployment service (e.g. CF service binding, Lambda Invoke)
|
|
120
|
+
if (this.services.deploymentService) {
|
|
121
|
+
const session = this.wire.getSession && typeof this.wire.getSession === 'function'
|
|
122
|
+
? await this.wire.getSession()
|
|
123
|
+
: this.wire.session;
|
|
124
|
+
return this.services.deploymentService.invoke(funcName, data, session, this.wire.traceId);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
throw e;
|
|
101
128
|
}
|
|
102
|
-
// Main package function
|
|
103
|
-
return runPikkuFunc('rpc', funcName, getPikkuFunctionName(funcName), {
|
|
104
|
-
auth: this.options.requiresAuth,
|
|
105
|
-
singletonServices: this.services,
|
|
106
|
-
data: () => data,
|
|
107
|
-
wire: updatedWire,
|
|
108
|
-
});
|
|
109
129
|
}
|
|
110
130
|
/**
|
|
111
131
|
* Invoke a function from an addon package
|
|
@@ -117,16 +137,14 @@ export class ContextAwareRPCService {
|
|
|
117
137
|
// Resolve namespace to package name
|
|
118
138
|
const resolved = resolveNamespace(namespacedFunction);
|
|
119
139
|
if (!resolved) {
|
|
120
|
-
throw new
|
|
121
|
-
`Make sure the package is registered in addons config.`);
|
|
140
|
+
throw new RPCNotFoundError(namespacedFunction);
|
|
122
141
|
}
|
|
123
142
|
// Get the function meta from the addon package
|
|
124
143
|
// Addon packages use function meta, not RPC meta
|
|
125
144
|
const addonFunctionMeta = pikkuState(resolved.package, 'function', 'meta');
|
|
126
145
|
const funcMeta = addonFunctionMeta[resolved.function];
|
|
127
146
|
if (!funcMeta) {
|
|
128
|
-
throw new
|
|
129
|
-
`Available functions: ${Object.keys(addonFunctionMeta).join(', ') || '(none)'}`);
|
|
147
|
+
throw new RPCNotFoundError(namespacedFunction);
|
|
130
148
|
}
|
|
131
149
|
const funcName = funcMeta.pikkuFuncId || resolved.function;
|
|
132
150
|
const auth = resolved.addonConfig?.auth ?? this.options.requiresAuth;
|
|
@@ -162,12 +180,23 @@ export class ContextAwareRPCService {
|
|
|
162
180
|
if (rpcName.includes(':')) {
|
|
163
181
|
return this.invokeAddonFunction(rpcName, data, mergedWire);
|
|
164
182
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
183
|
+
try {
|
|
184
|
+
return await runPikkuFunc('rpc', rpcName, getPikkuFunctionName(rpcName), {
|
|
185
|
+
auth: this.options.requiresAuth,
|
|
186
|
+
singletonServices: this.services,
|
|
187
|
+
data: () => data,
|
|
188
|
+
wire: mergedWire,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
catch (e) {
|
|
192
|
+
if (e instanceof RPCNotFoundError && this.services.deploymentService) {
|
|
193
|
+
const session = this.wire.getSession && typeof this.wire.getSession === 'function'
|
|
194
|
+
? await this.wire.getSession()
|
|
195
|
+
: this.wire.session;
|
|
196
|
+
return this.services.deploymentService.invoke(rpcName, data, session, this.wire.traceId);
|
|
197
|
+
}
|
|
198
|
+
throw e;
|
|
199
|
+
}
|
|
171
200
|
}
|
|
172
201
|
async startWorkflow(workflowName, input, options) {
|
|
173
202
|
if (!this.services.workflowService) {
|
|
@@ -227,77 +256,14 @@ export class ContextAwareRPCService {
|
|
|
227
256
|
};
|
|
228
257
|
}
|
|
229
258
|
async remote(funcName, data) {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
};
|
|
234
|
-
const colonIndex = funcName.indexOf(':');
|
|
235
|
-
if (colonIndex !== -1) {
|
|
236
|
-
const namespace = funcName.substring(0, colonIndex);
|
|
237
|
-
const addons = pikkuState(null, 'addons', 'packages');
|
|
238
|
-
const pkgConfig = addons.get(namespace);
|
|
239
|
-
endpoint = pkgConfig?.rpcEndpoint;
|
|
240
|
-
}
|
|
241
|
-
if (!endpoint && this.services.deploymentService) {
|
|
242
|
-
const deployments = await this.services.deploymentService.findFunction(funcName);
|
|
243
|
-
if (deployments.length > 0) {
|
|
244
|
-
endpoint = deployments[0].endpoint;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
if (!endpoint) {
|
|
248
|
-
throw new Error(`No endpoint configured for remote RPC: ${funcName}. ` +
|
|
249
|
-
`Configure rpcEndpoint in addons config or set up a DeploymentService.`);
|
|
250
|
-
}
|
|
251
|
-
let secret;
|
|
252
|
-
if (this.services.secrets) {
|
|
253
|
-
try {
|
|
254
|
-
secret = await this.services.secrets.getSecret('PIKKU_REMOTE_SECRET');
|
|
255
|
-
}
|
|
256
|
-
catch { }
|
|
257
|
-
}
|
|
258
|
-
if (secret) {
|
|
259
|
-
if (!this.services.jwt) {
|
|
260
|
-
throw new Error('PIKKU_REMOTE_SECRET is set but JWT service is not available');
|
|
261
|
-
}
|
|
262
|
-
const session = this.wire.getSession && typeof this.wire.getSession === 'function'
|
|
263
|
-
? await this.wire.getSession()
|
|
264
|
-
: this.wire.session;
|
|
265
|
-
const sessionEnc = session
|
|
266
|
-
? await encryptJSON(secret, { session })
|
|
267
|
-
: undefined;
|
|
268
|
-
const token = await this.services.jwt.encode({ value: 5, unit: 'minute' }, {
|
|
269
|
-
aud: 'pikku-remote',
|
|
270
|
-
fn: funcName,
|
|
271
|
-
iat: Date.now(),
|
|
272
|
-
session: sessionEnc,
|
|
273
|
-
});
|
|
274
|
-
headers.Authorization = `Bearer ${token}`;
|
|
275
|
-
}
|
|
276
|
-
const url = `${endpoint}/rpc/${encodeURIComponent(funcName)}`;
|
|
277
|
-
const timeoutMs = 30_000;
|
|
278
|
-
const response = await fetch(url, {
|
|
279
|
-
method: 'POST',
|
|
280
|
-
headers,
|
|
281
|
-
body: JSON.stringify({ data }),
|
|
282
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
283
|
-
});
|
|
284
|
-
if (!response.ok) {
|
|
285
|
-
let errorBody;
|
|
286
|
-
try {
|
|
287
|
-
errorBody = JSON.stringify(await response.json());
|
|
288
|
-
}
|
|
289
|
-
catch {
|
|
290
|
-
errorBody = await response.text();
|
|
291
|
-
}
|
|
292
|
-
throw new Error(`Remote RPC call failed: ${response.status} ${response.statusText}. ${errorBody}`);
|
|
293
|
-
}
|
|
294
|
-
try {
|
|
295
|
-
return (await response.json());
|
|
296
|
-
}
|
|
297
|
-
catch {
|
|
298
|
-
const text = await response.text();
|
|
299
|
-
throw new Error(`Remote RPC call returned non-JSON response: ${response.status} ${response.statusText}. ${text}`);
|
|
259
|
+
if (!this.services.deploymentService) {
|
|
260
|
+
throw new Error(`No DeploymentService configured for remote RPC: ${funcName}. ` +
|
|
261
|
+
`Set up a DeploymentService to enable remote function calls.`);
|
|
300
262
|
}
|
|
263
|
+
const session = this.wire.getSession && typeof this.wire.getSession === 'function'
|
|
264
|
+
? await this.wire.getSession()
|
|
265
|
+
: this.wire.session;
|
|
266
|
+
return this.services.deploymentService.invoke(funcName, data, session, this.wire.traceId);
|
|
301
267
|
}
|
|
302
268
|
}
|
|
303
269
|
// RPC Service class for the global interface
|
|
@@ -4,7 +4,9 @@ import type { CorePikkuFunctionConfig, CorePikkuFunctionSessionless } from '../.
|
|
|
4
4
|
export type RunScheduledTasksParams = {
|
|
5
5
|
name: string;
|
|
6
6
|
session?: CoreUserSession;
|
|
7
|
+
/** Pre-resolved trace ID */
|
|
8
|
+
traceId?: string;
|
|
7
9
|
};
|
|
8
10
|
export declare const wireScheduler: <PikkuFunctionConfig extends CorePikkuFunctionConfig<CorePikkuFunctionSessionless<void, void>>>(scheduledTask: CoreScheduledTask<PikkuFunctionConfig>) => void;
|
|
9
|
-
export declare function runScheduledTask({ name, session, }: RunScheduledTasksParams): Promise<void>;
|
|
11
|
+
export declare function runScheduledTask({ name, session, traceId, }: RunScheduledTasksParams): Promise<void>;
|
|
10
12
|
export declare const getScheduledTasks: () => Map<string, CoreScheduledTask>;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { getErrorResponse, PikkuError } from '../../errors/error-handler.js';
|
|
2
|
-
import { PikkuMissingMetaError } from '../../errors/errors.js';
|
|
3
2
|
import { getSingletonServices, getCreateWireServices, pikkuState, } from '../../pikku-state.js';
|
|
4
3
|
import { addFunction, runPikkuFunc } from '../../function/function-runner.js';
|
|
5
4
|
import { PikkuSessionService, createMiddlewareSessionWireProps, } from '../../services/user-session-service.js';
|
|
@@ -7,7 +6,8 @@ export const wireScheduler = (scheduledTask) => {
|
|
|
7
6
|
const meta = pikkuState(null, 'scheduler', 'meta');
|
|
8
7
|
const taskMeta = meta[scheduledTask.name];
|
|
9
8
|
if (!taskMeta) {
|
|
10
|
-
|
|
9
|
+
console.warn(`[pikku] Skipping scheduled task '${scheduledTask.name}' — metadata not found. Consider moving this wiring to its own file.`);
|
|
10
|
+
return;
|
|
11
11
|
}
|
|
12
12
|
addFunction(taskMeta.pikkuFuncId, {
|
|
13
13
|
func: scheduledTask.func.func,
|
|
@@ -33,9 +33,12 @@ class ScheduledTaskSkippedError extends PikkuError {
|
|
|
33
33
|
this.name = 'ScheduledTaskSkippedError';
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
export async function runScheduledTask({ name, session, }) {
|
|
36
|
+
export async function runScheduledTask({ name, session, traceId, }) {
|
|
37
37
|
const singletonServices = getSingletonServices();
|
|
38
38
|
const createWireServices = getCreateWireServices();
|
|
39
|
+
const resolvedTraceId = traceId ?? `cron-${name}-${Date.now()}`;
|
|
40
|
+
const scopedLogger = singletonServices.logger.scope?.(resolvedTraceId) ??
|
|
41
|
+
singletonServices.logger;
|
|
39
42
|
const task = pikkuState(null, 'scheduler', 'tasks').get(name);
|
|
40
43
|
const meta = pikkuState(null, 'scheduler', 'meta')[name];
|
|
41
44
|
const userSession = new PikkuSessionService();
|
|
@@ -50,6 +53,7 @@ export async function runScheduledTask({ name, session, }) {
|
|
|
50
53
|
}
|
|
51
54
|
// Create the scheduled task wire object
|
|
52
55
|
const wire = {
|
|
56
|
+
traceId: resolvedTraceId,
|
|
53
57
|
scheduledTask: {
|
|
54
58
|
name,
|
|
55
59
|
schedule: task.schedule,
|
|
@@ -61,7 +65,7 @@ export async function runScheduledTask({ name, session, }) {
|
|
|
61
65
|
...createMiddlewareSessionWireProps(userSession),
|
|
62
66
|
};
|
|
63
67
|
try {
|
|
64
|
-
|
|
68
|
+
scopedLogger.info(`Running schedule task: ${name} | schedule: ${task.schedule}`);
|
|
65
69
|
await runPikkuFunc('scheduler', meta.name, meta.pikkuFuncId, {
|
|
66
70
|
singletonServices,
|
|
67
71
|
createWireServices,
|
|
@@ -78,7 +82,7 @@ export async function runScheduledTask({ name, session, }) {
|
|
|
78
82
|
catch (e) {
|
|
79
83
|
const errorResponse = getErrorResponse(e);
|
|
80
84
|
if (errorResponse != null) {
|
|
81
|
-
|
|
85
|
+
scopedLogger.error(e);
|
|
82
86
|
}
|
|
83
87
|
throw e;
|
|
84
88
|
}
|
|
@@ -10,7 +10,8 @@ export const wireTrigger = (trigger) => {
|
|
|
10
10
|
const meta = pikkuState(null, 'trigger', 'meta');
|
|
11
11
|
const triggerMeta = meta[trigger.name];
|
|
12
12
|
if (!triggerMeta) {
|
|
13
|
-
|
|
13
|
+
console.warn(`[pikku] Skipping trigger '${trigger.name}' — metadata not found. Consider moving this wiring to its own file.`);
|
|
14
|
+
return;
|
|
14
15
|
}
|
|
15
16
|
addFunction(triggerMeta.pikkuFuncId, trigger.func);
|
|
16
17
|
const triggers = pikkuState(null, 'trigger', 'triggers');
|
|
@@ -25,7 +26,8 @@ export const wireTriggerSource = (source) => {
|
|
|
25
26
|
const sourceMeta = pikkuState(null, 'trigger', 'sourceMeta');
|
|
26
27
|
const triggerSourceMeta = sourceMeta[source.name];
|
|
27
28
|
if (!triggerSourceMeta) {
|
|
28
|
-
|
|
29
|
+
console.warn(`[pikku] Skipping trigger source '${source.name}' — metadata not found. Consider moving this wiring to its own file.`);
|
|
30
|
+
return;
|
|
29
31
|
}
|
|
30
32
|
const triggerSources = pikkuState(null, 'trigger', 'triggerSources');
|
|
31
33
|
if (triggerSources.has(source.name)) {
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Add a workflow to the system
|
|
3
3
|
* This is called by the generated workflow wirings
|
|
4
4
|
*/
|
|
5
|
-
export declare const addWorkflow: (workflowName: string, workflowFunc: any) => void;
|
|
5
|
+
export declare const addWorkflow: (workflowName: string, workflowFunc: any, packageName?: string | null) => void;
|
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
import { pikkuState } from '../../../pikku-state.js';
|
|
2
2
|
import { addFunction } from '../../../function/function-runner.js';
|
|
3
|
-
import { PikkuMissingMetaError } from '../../../errors/errors.js';
|
|
4
3
|
/**
|
|
5
4
|
* Add a workflow to the system
|
|
6
5
|
* This is called by the generated workflow wirings
|
|
7
6
|
*/
|
|
8
|
-
export const addWorkflow = (workflowName, workflowFunc) => {
|
|
9
|
-
|
|
10
|
-
const meta = pikkuState(null, 'workflows', 'meta');
|
|
7
|
+
export const addWorkflow = (workflowName, workflowFunc, packageName = null) => {
|
|
8
|
+
const meta = pikkuState(packageName, 'workflows', 'meta');
|
|
11
9
|
const workflowMeta = meta[workflowName];
|
|
12
10
|
if (!workflowMeta) {
|
|
13
|
-
|
|
11
|
+
console.warn(`[pikku] Skipping workflow '${workflowName}' — metadata not found. Consider moving this wiring to its own file.`);
|
|
12
|
+
return;
|
|
14
13
|
}
|
|
15
|
-
|
|
16
|
-
const registrations = pikkuState(null, 'workflows', 'registrations');
|
|
14
|
+
const registrations = pikkuState(packageName, 'workflows', 'registrations');
|
|
17
15
|
registrations.set(workflowName, {
|
|
18
16
|
name: workflowName,
|
|
19
17
|
func: workflowFunc,
|
|
20
18
|
});
|
|
21
|
-
|
|
22
|
-
addFunction(workflowMeta.pikkuFuncId, workflowFunc);
|
|
19
|
+
addFunction(workflowMeta.pikkuFuncId, workflowFunc, packageName);
|
|
23
20
|
};
|
|
@@ -11,6 +11,6 @@ export declare function continueGraph(workflowService: PikkuWorkflowService, run
|
|
|
11
11
|
export declare function executeGraphStep(workflowService: PikkuWorkflowService, rpcService: any, runId: string, stepId: string, nodeId: string, rpcName: string, data: any, graphName: string): Promise<any>;
|
|
12
12
|
export declare function onGraphNodeComplete(workflowService: PikkuWorkflowService, runId: string, graphName: string): Promise<void>;
|
|
13
13
|
export declare function runFromMeta(workflowService: PikkuWorkflowService, runId: string, meta: WorkflowRuntimeMeta, _rpcService: any): Promise<void>;
|
|
14
|
-
export declare function runWorkflowGraph(workflowService: PikkuWorkflowService, graphName: string, triggerInput: any, rpcService?: any, inline?: boolean, startNode?: string, wire?: WorkflowRunWire): Promise<{
|
|
14
|
+
export declare function runWorkflowGraph(workflowService: PikkuWorkflowService, graphName: string, triggerInput: any, rpcService?: any, inline?: boolean, startNode?: string, wire?: WorkflowRunWire, overrideMeta?: WorkflowRuntimeMeta): Promise<{
|
|
15
15
|
runId: string;
|
|
16
16
|
}>;
|
|
@@ -90,8 +90,22 @@ function isTemplate(value) {
|
|
|
90
90
|
typeof value.$template === 'object');
|
|
91
91
|
}
|
|
92
92
|
function getWorkflowMeta(name) {
|
|
93
|
-
const
|
|
94
|
-
|
|
93
|
+
const rootMeta = pikkuState(null, 'workflows', 'meta');
|
|
94
|
+
if (rootMeta[name])
|
|
95
|
+
return rootMeta[name];
|
|
96
|
+
const colonIndex = name.indexOf(':');
|
|
97
|
+
if (colonIndex !== -1) {
|
|
98
|
+
const namespace = name.substring(0, colonIndex);
|
|
99
|
+
const localName = name.substring(colonIndex + 1);
|
|
100
|
+
const addons = pikkuState(null, 'addons', 'packages');
|
|
101
|
+
const pkgConfig = addons?.get(namespace);
|
|
102
|
+
if (pkgConfig) {
|
|
103
|
+
const addonMeta = pikkuState(pkgConfig.package, 'workflows', 'meta');
|
|
104
|
+
if (addonMeta?.[localName])
|
|
105
|
+
return addonMeta[localName];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return undefined;
|
|
95
109
|
}
|
|
96
110
|
function resolveNextFromConfig(next, branchKey) {
|
|
97
111
|
if (!next)
|
|
@@ -543,8 +557,8 @@ async function continueGraphInline(workflowService, rpcService, runId, graphName
|
|
|
543
557
|
}));
|
|
544
558
|
}
|
|
545
559
|
}
|
|
546
|
-
export async function runWorkflowGraph(workflowService, graphName, triggerInput, rpcService, inline, startNode, wire) {
|
|
547
|
-
const meta = getWorkflowMeta(graphName);
|
|
560
|
+
export async function runWorkflowGraph(workflowService, graphName, triggerInput, rpcService, inline, startNode, wire, overrideMeta) {
|
|
561
|
+
const meta = overrideMeta ?? getWorkflowMeta(graphName);
|
|
548
562
|
if (!meta?.nodes) {
|
|
549
563
|
throw new Error(`Workflow graph '${graphName}' not found`);
|
|
550
564
|
}
|
|
@@ -5,6 +5,8 @@ export { PikkuWorkflowService, WorkflowCancelledException, WorkflowSuspendedExce
|
|
|
5
5
|
export { addWorkflow } from './dsl/workflow-runner.js';
|
|
6
6
|
export { template, type TemplateString } from './graph/template.js';
|
|
7
7
|
export { pikkuWorkflowGraph, type PikkuWorkflowGraphConfig, type PikkuWorkflowGraphResult, } from './graph/wire-workflow-graph.js';
|
|
8
|
-
export {
|
|
9
|
-
export
|
|
8
|
+
export { validateWorkflowWiring, computeEntryNodeIds, } from './graph/graph-validation.js';
|
|
9
|
+
export { pikkuWorkflowWorkerFunc, pikkuWorkflowOrchestratorFunc, pikkuWorkflowSleeperFunc, } from './workflow-queue-workers.js';
|
|
10
|
+
export type { WorkflowStepInput as WorkflowStepQueueInput, PikkuWorkflowOrchestratorInput, PikkuWorkflowSleeperInput, } from './workflow-queue-workers.js';
|
|
11
|
+
export type { WorkflowService, WorkflowServiceConfig, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, StepStatus, WorkflowRun, WorkflowRunStatus, StepState, WorkflowRunService, CoreWorkflow, PikkuWorkflow, ContextVariable, WorkflowContext, WorkflowsMeta, WorkflowRuntimeMeta, WorkflowsRuntimeMeta, WorkflowStepInput, WorkflowOrchestratorInput, WorkflowSleeperInput, } from './workflow.types.js';
|
|
10
12
|
export type { WorkflowStepOptions, WorkflowWireDoRPC, WorkflowWireDoInline, WorkflowWireSleep, WorkflowWireSuspend, InputSource, OutputBinding, RpcStepMeta, SimpleCondition, Condition, BranchCase, BranchStepMeta, ParallelGroupStepMeta, FanoutStepMeta, ReturnStepMeta, InlineStepMeta, SleepStepMeta, CancelStepMeta, SetStepMeta, SwitchCaseMeta, SwitchStepMeta, FilterStepMeta, ArrayPredicateStepMeta, WorkflowStepMeta, WorkflowStepWire, PikkuWorkflowWire, } from './workflow.types.js';
|
|
@@ -7,5 +7,7 @@ export { addWorkflow } from './dsl/workflow-runner.js';
|
|
|
7
7
|
// Graph helpers (template, pikkuWorkflowGraph)
|
|
8
8
|
export { template } from './graph/template.js';
|
|
9
9
|
export { pikkuWorkflowGraph, } from './graph/wire-workflow-graph.js';
|
|
10
|
-
//
|
|
11
|
-
export {
|
|
10
|
+
// Graph validation and dynamic workflow utilities
|
|
11
|
+
export { validateWorkflowWiring, computeEntryNodeIds, } from './graph/graph-validation.js';
|
|
12
|
+
// Queue worker functions (registered by codegen, executed at runtime)
|
|
13
|
+
export { pikkuWorkflowWorkerFunc, pikkuWorkflowOrchestratorFunc, pikkuWorkflowSleeperFunc, } from './workflow-queue-workers.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { SerializedError } from '../../types/core.types.js';
|
|
2
|
-
import type { PikkuWorkflowWire, StepState, WorkflowRun, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, WorkflowStepOptions } from './workflow.types.js';
|
|
2
|
+
import type { PikkuWorkflowWire, StepState, WorkflowRun, WorkflowRunStatus, WorkflowRunWire, WorkflowStatus, WorkflowVersionStatus, WorkflowStepOptions } from './workflow.types.js';
|
|
3
3
|
import type { WorkflowService } from '../../services/workflow-service.js';
|
|
4
4
|
import { PikkuError } from '../../errors/error-handler.js';
|
|
5
5
|
/**
|
|
@@ -69,6 +69,11 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
69
69
|
* @returns Workflow run or null if not found
|
|
70
70
|
*/
|
|
71
71
|
abstract getRun(id: string): Promise<WorkflowRun | null>;
|
|
72
|
+
/**
|
|
73
|
+
* Get minimal workflow run status with step summaries.
|
|
74
|
+
* Used by the public API — the console addon provides the full verbose view.
|
|
75
|
+
*/
|
|
76
|
+
getRunStatus(id: string): Promise<WorkflowRunStatus | null>;
|
|
72
77
|
/**
|
|
73
78
|
* Get workflow run history (all step attempts in chronological order)
|
|
74
79
|
* @param runId - Run ID
|
|
@@ -219,7 +224,7 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
219
224
|
* Resume a paused workflow by triggering the orchestrator
|
|
220
225
|
* @param runId - Run ID
|
|
221
226
|
*/
|
|
222
|
-
resumeWorkflow(runId: string): Promise<void>;
|
|
227
|
+
resumeWorkflow(runId: string, workflowName?: string): Promise<void>;
|
|
223
228
|
queueStepWorker(runId: string, stepName: string, rpcName: string, data: any): Promise<void>;
|
|
224
229
|
/**
|
|
225
230
|
* Execute a workflow sleep step completion
|
|
@@ -232,7 +237,7 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
232
237
|
* @param runId - Run ID
|
|
233
238
|
* @param retryDelay - Delay in milliseconds or duration string (optional)
|
|
234
239
|
*/
|
|
235
|
-
protected scheduleOrchestratorRetry(runId: string, retryDelay?: number | string): Promise<void>;
|
|
240
|
+
protected scheduleOrchestratorRetry(runId: string, retryDelay?: number | string, workflowName?: string): Promise<void>;
|
|
236
241
|
/**
|
|
237
242
|
* Start a new workflow run
|
|
238
243
|
* Automatically detects workflow type (DSL or graph) from meta and executes accordingly
|
|
@@ -269,7 +274,14 @@ export declare abstract class PikkuWorkflowService implements WorkflowService {
|
|
|
269
274
|
private sleepStep;
|
|
270
275
|
private getSuspendStepName;
|
|
271
276
|
private suspendStep;
|
|
272
|
-
createWorkflowWire(name: string, runId: string, rpcService: any): PikkuWorkflowWire;
|
|
277
|
+
createWorkflowWire(name: string, runId: string, rpcService: any, addonNamespace?: string | null): PikkuWorkflowWire;
|
|
273
278
|
private verifyStepName;
|
|
274
279
|
private getConfig;
|
|
280
|
+
/**
|
|
281
|
+
* Get the orchestrator queue name for a specific workflow.
|
|
282
|
+
* Checks queue meta for a per-workflow queue first (e.g. wf-orchestrator-{name}),
|
|
283
|
+
* falls back to the shared orchestrator queue.
|
|
284
|
+
*/
|
|
285
|
+
protected getOrchestratorQueueName(workflowName?: string): string;
|
|
286
|
+
protected getStepWorkerQueueName(rpcName?: string): string;
|
|
275
287
|
}
|