@donkeylabs/server 2.0.24 → 2.0.26
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/package.json
CHANGED
|
@@ -91,6 +91,27 @@ async function main(): Promise<void> {
|
|
|
91
91
|
plugins: bootstrap.manager.getServices(),
|
|
92
92
|
events: createIpcEventBridge(socket, instanceId),
|
|
93
93
|
pollInterval: 1000,
|
|
94
|
+
emitCustomEvent: async (payload) => {
|
|
95
|
+
sendEvent(socket, {
|
|
96
|
+
type: "event",
|
|
97
|
+
instanceId: payload.instanceId,
|
|
98
|
+
workflowName: payload.workflowName,
|
|
99
|
+
timestamp: Date.now(),
|
|
100
|
+
event: payload.event,
|
|
101
|
+
data: payload.data,
|
|
102
|
+
});
|
|
103
|
+
},
|
|
104
|
+
emitLog: async (payload) => {
|
|
105
|
+
sendEvent(socket, {
|
|
106
|
+
type: "log",
|
|
107
|
+
instanceId: payload.instanceId,
|
|
108
|
+
workflowName: payload.workflowName,
|
|
109
|
+
timestamp: Date.now(),
|
|
110
|
+
level: payload.level,
|
|
111
|
+
message: payload.message,
|
|
112
|
+
data: payload.data,
|
|
113
|
+
});
|
|
114
|
+
},
|
|
94
115
|
});
|
|
95
116
|
|
|
96
117
|
sendEvent(socket, {
|
|
@@ -11,6 +11,8 @@ import { createServer as createNetServer } from "node:net";
|
|
|
11
11
|
// Message Protocol Types
|
|
12
12
|
// ============================================
|
|
13
13
|
|
|
14
|
+
import type { LogLevel } from "./logger";
|
|
15
|
+
|
|
14
16
|
export type WorkflowEventType =
|
|
15
17
|
| "ready"
|
|
16
18
|
| "started"
|
|
@@ -20,11 +22,14 @@ export type WorkflowEventType =
|
|
|
20
22
|
| "step.failed"
|
|
21
23
|
| "progress"
|
|
22
24
|
| "completed"
|
|
23
|
-
| "failed"
|
|
25
|
+
| "failed"
|
|
26
|
+
| "event"
|
|
27
|
+
| "log";
|
|
24
28
|
|
|
25
29
|
export interface WorkflowEvent {
|
|
26
30
|
type: WorkflowEventType;
|
|
27
31
|
instanceId: string;
|
|
32
|
+
workflowName?: string;
|
|
28
33
|
timestamp: number;
|
|
29
34
|
stepName?: string;
|
|
30
35
|
/** Step type (for step.started events) */
|
|
@@ -36,6 +41,14 @@ export interface WorkflowEvent {
|
|
|
36
41
|
totalSteps?: number;
|
|
37
42
|
/** Next step to execute (for step.completed events) */
|
|
38
43
|
nextStep?: string;
|
|
44
|
+
/** Custom event name (for event type) */
|
|
45
|
+
event?: string;
|
|
46
|
+
/** Custom event payload or log data */
|
|
47
|
+
data?: Record<string, any>;
|
|
48
|
+
/** Log level (for log type) */
|
|
49
|
+
level?: LogLevel;
|
|
50
|
+
/** Log message (for log type) */
|
|
51
|
+
message?: string;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
export interface ProxyRequest {
|
|
@@ -45,6 +45,19 @@ export interface StateMachineConfig {
|
|
|
45
45
|
jobs?: Jobs;
|
|
46
46
|
/** Poll interval for checking job completion (ms) */
|
|
47
47
|
pollInterval?: number;
|
|
48
|
+
emitCustomEvent?: (payload: {
|
|
49
|
+
instanceId: string;
|
|
50
|
+
workflowName: string;
|
|
51
|
+
event: string;
|
|
52
|
+
data?: Record<string, any>;
|
|
53
|
+
}) => Promise<void>;
|
|
54
|
+
emitLog?: (payload: {
|
|
55
|
+
instanceId: string;
|
|
56
|
+
workflowName: string;
|
|
57
|
+
level: LogLevel;
|
|
58
|
+
message: string;
|
|
59
|
+
data?: Record<string, any>;
|
|
60
|
+
}) => Promise<void>;
|
|
48
61
|
}
|
|
49
62
|
|
|
50
63
|
// ============================================
|
|
@@ -58,6 +71,8 @@ export class WorkflowStateMachine {
|
|
|
58
71
|
private events: StateMachineEvents;
|
|
59
72
|
private jobs?: Jobs;
|
|
60
73
|
private pollInterval: number;
|
|
74
|
+
private emitCustomEvent?: StateMachineConfig["emitCustomEvent"];
|
|
75
|
+
private emitLog?: StateMachineConfig["emitLog"];
|
|
61
76
|
private cancelledInstances = new Set<string>();
|
|
62
77
|
|
|
63
78
|
constructor(config: StateMachineConfig) {
|
|
@@ -67,6 +82,8 @@ export class WorkflowStateMachine {
|
|
|
67
82
|
this.events = config.events;
|
|
68
83
|
this.jobs = config.jobs;
|
|
69
84
|
this.pollInterval = config.pollInterval ?? 1000;
|
|
85
|
+
this.emitCustomEvent = config.emitCustomEvent;
|
|
86
|
+
this.emitLog = config.emitLog;
|
|
70
87
|
}
|
|
71
88
|
|
|
72
89
|
/**
|
|
@@ -484,26 +501,39 @@ export class WorkflowStateMachine {
|
|
|
484
501
|
const instanceId = instance.id;
|
|
485
502
|
|
|
486
503
|
const scopedLogger = this.core?.logger?.scoped("workflow", instance.id);
|
|
487
|
-
const emit =
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
};
|
|
504
|
+
const emit = async (event: string, data?: Record<string, any>) => {
|
|
505
|
+
const payload = {
|
|
506
|
+
instanceId: instance.id,
|
|
507
|
+
workflowName: instance.workflowName,
|
|
508
|
+
event,
|
|
509
|
+
data,
|
|
510
|
+
};
|
|
495
511
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
|
|
512
|
+
if (this.core?.events) {
|
|
513
|
+
await this.core.events.emit("workflow.event", payload);
|
|
514
|
+
await this.core.events.emit(`workflow.${instance.workflowName}.event`, payload);
|
|
515
|
+
await this.core.events.emit(`workflow.${instance.id}.event`, payload);
|
|
516
|
+
}
|
|
501
517
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
518
|
+
if (this.emitCustomEvent) {
|
|
519
|
+
await this.emitCustomEvent(payload);
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
const log = (level: LogLevel, message: string, data?: Record<string, any>) => {
|
|
524
|
+
if (scopedLogger) {
|
|
525
|
+
scopedLogger[level](message, data);
|
|
526
|
+
}
|
|
527
|
+
if (this.emitLog) {
|
|
528
|
+
return this.emitLog({
|
|
529
|
+
instanceId: instance.id,
|
|
530
|
+
workflowName: instance.workflowName,
|
|
531
|
+
level,
|
|
532
|
+
message,
|
|
533
|
+
data,
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
};
|
|
507
537
|
|
|
508
538
|
const core = this.core
|
|
509
539
|
? {
|
package/src/core/workflows.ts
CHANGED
|
@@ -1475,6 +1475,70 @@ class WorkflowsImpl implements Workflows {
|
|
|
1475
1475
|
break;
|
|
1476
1476
|
}
|
|
1477
1477
|
|
|
1478
|
+
case "event": {
|
|
1479
|
+
const workflowName = event.workflowName ?? (await this.adapter.getInstance(instanceId))?.workflowName;
|
|
1480
|
+
const payload = {
|
|
1481
|
+
instanceId,
|
|
1482
|
+
workflowName,
|
|
1483
|
+
event: event.event,
|
|
1484
|
+
data: event.data,
|
|
1485
|
+
};
|
|
1486
|
+
|
|
1487
|
+
const ssePayload = {
|
|
1488
|
+
id: `workflow_event_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
1489
|
+
event: event.event,
|
|
1490
|
+
stepName: event.data?.stepName,
|
|
1491
|
+
data: event.data,
|
|
1492
|
+
createdAt: new Date().toISOString(),
|
|
1493
|
+
};
|
|
1494
|
+
|
|
1495
|
+
await this.emitEvent("workflow.event", payload);
|
|
1496
|
+
if (workflowName) {
|
|
1497
|
+
await this.emitEvent(`workflow.${workflowName}.event`, payload);
|
|
1498
|
+
}
|
|
1499
|
+
await this.emitEvent(`workflow.${instanceId}.event`, payload);
|
|
1500
|
+
|
|
1501
|
+
if (this.sse) {
|
|
1502
|
+
this.sse.broadcast(`workflow:${instanceId}`, "event", ssePayload);
|
|
1503
|
+
this.sse.broadcast("workflows:all", "workflow.event", {
|
|
1504
|
+
...ssePayload,
|
|
1505
|
+
instanceId,
|
|
1506
|
+
workflowName,
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
break;
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
case "log": {
|
|
1513
|
+
const workflowName = event.workflowName ?? (await this.adapter.getInstance(instanceId))?.workflowName;
|
|
1514
|
+
|
|
1515
|
+
const ssePayload = {
|
|
1516
|
+
id: `workflow_log_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
1517
|
+
level: event.level,
|
|
1518
|
+
event: "log",
|
|
1519
|
+
stepName: event.data?.stepName,
|
|
1520
|
+
message: event.message,
|
|
1521
|
+
data: event.data,
|
|
1522
|
+
createdAt: new Date().toISOString(),
|
|
1523
|
+
};
|
|
1524
|
+
|
|
1525
|
+
if (this.core?.logs && event.level && event.message) {
|
|
1526
|
+
this.core.logs.write({
|
|
1527
|
+
level: event.level,
|
|
1528
|
+
message: event.message,
|
|
1529
|
+
source: "workflow",
|
|
1530
|
+
sourceId: instanceId,
|
|
1531
|
+
data: event.data,
|
|
1532
|
+
context: workflowName ? { workflowName } : undefined,
|
|
1533
|
+
});
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
if (this.sse) {
|
|
1537
|
+
this.sse.broadcast(`workflow:${instanceId}`, "log", ssePayload);
|
|
1538
|
+
}
|
|
1539
|
+
break;
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1478
1542
|
case "completed": {
|
|
1479
1543
|
// Clean up isolated process tracking
|
|
1480
1544
|
this.cleanupIsolatedProcess(instanceId);
|