@cuylabs/agent-runtime 0.11.0 → 0.12.0
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/dist/{chunk-U7M333GT.js → chunk-DRMXPKPK.js} +196 -109
- package/dist/{chunk-ZVISWF7S.js → chunk-PXXGA4YJ.js} +15 -4
- package/dist/{chunk-DBQSJ476.js → chunk-RCSNDSHJ.js} +5 -2
- package/dist/drivers/in-memory.js +2 -2
- package/dist/index.js +31 -12
- package/dist/orchestration/index.js +2 -2
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeNextRunAtMs,
|
|
3
3
|
normalizeSchedule
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PXXGA4YJ.js";
|
|
5
5
|
|
|
6
6
|
// src/orchestration/types.ts
|
|
7
7
|
var TERMINAL_STATUSES = {
|
|
@@ -85,7 +85,9 @@ function normalizeExecutionTimeoutMs(value) {
|
|
|
85
85
|
return DEFAULT_EXECUTION_TIMEOUT_MS;
|
|
86
86
|
}
|
|
87
87
|
if (!Number.isFinite(value)) {
|
|
88
|
-
throw new Error(
|
|
88
|
+
throw new Error(
|
|
89
|
+
`executionTimeoutMs must be a finite number. Received: ${String(value)}`
|
|
90
|
+
);
|
|
89
91
|
}
|
|
90
92
|
const normalized = Math.floor(value);
|
|
91
93
|
if (normalized <= 0) {
|
|
@@ -98,7 +100,9 @@ function normalizeMaxQueuedDispatches(value) {
|
|
|
98
100
|
return void 0;
|
|
99
101
|
}
|
|
100
102
|
if (!Number.isFinite(value)) {
|
|
101
|
-
throw new Error(
|
|
103
|
+
throw new Error(
|
|
104
|
+
`maxQueuedDispatches must be a finite number. Received: ${String(value)}`
|
|
105
|
+
);
|
|
102
106
|
}
|
|
103
107
|
return Math.max(0, Math.floor(value));
|
|
104
108
|
}
|
|
@@ -158,17 +162,23 @@ function normalizeRetryPolicy(policy) {
|
|
|
158
162
|
return void 0;
|
|
159
163
|
}
|
|
160
164
|
if (!Number.isFinite(policy.maxAttempts)) {
|
|
161
|
-
throw new Error(
|
|
165
|
+
throw new Error(
|
|
166
|
+
`retryPolicy.maxAttempts must be a finite number. Received: ${String(policy.maxAttempts)}`
|
|
167
|
+
);
|
|
162
168
|
}
|
|
163
169
|
const maxAttempts = Math.max(1, Math.floor(policy.maxAttempts));
|
|
164
170
|
const strategy = policy.strategy ?? "fixed";
|
|
165
171
|
if (strategy !== "fixed" && strategy !== "exponential") {
|
|
166
|
-
throw new Error(
|
|
172
|
+
throw new Error(
|
|
173
|
+
`retryPolicy.strategy must be "fixed" or "exponential". Received: ${String(policy.strategy)}`
|
|
174
|
+
);
|
|
167
175
|
}
|
|
168
176
|
let backoffMs;
|
|
169
177
|
if (policy.backoffMs !== void 0) {
|
|
170
178
|
if (!Number.isFinite(policy.backoffMs) || policy.backoffMs < 0) {
|
|
171
|
-
throw new Error(
|
|
179
|
+
throw new Error(
|
|
180
|
+
`retryPolicy.backoffMs must be a non-negative finite number. Received: ${String(policy.backoffMs)}`
|
|
181
|
+
);
|
|
172
182
|
}
|
|
173
183
|
backoffMs = Math.floor(policy.backoffMs);
|
|
174
184
|
}
|
|
@@ -241,9 +251,13 @@ var WorkloadRuntime = class {
|
|
|
241
251
|
1,
|
|
242
252
|
Math.floor(options.maxConcurrentRuns ?? DEFAULT_MAX_CONCURRENT_RUNS)
|
|
243
253
|
);
|
|
244
|
-
this.maxQueuedDispatches = normalizeMaxQueuedDispatches(
|
|
254
|
+
this.maxQueuedDispatches = normalizeMaxQueuedDispatches(
|
|
255
|
+
options.maxQueuedDispatches
|
|
256
|
+
);
|
|
245
257
|
this.createId = options.createId ?? (() => randomUUID());
|
|
246
|
-
this.executionTimeoutMs = normalizeExecutionTimeoutMs(
|
|
258
|
+
this.executionTimeoutMs = normalizeExecutionTimeoutMs(
|
|
259
|
+
options.executionTimeoutMs
|
|
260
|
+
);
|
|
247
261
|
this.abortInFlightOnStop = options.abortInFlightOnStop ?? DEFAULT_ABORT_IN_FLIGHT_ON_STOP;
|
|
248
262
|
this.onDeadLetter = options.onDeadLetter;
|
|
249
263
|
this.observers = options.observers ?? [];
|
|
@@ -273,12 +287,16 @@ var WorkloadRuntime = class {
|
|
|
273
287
|
return await this.dispatchDue(jobId);
|
|
274
288
|
}
|
|
275
289
|
});
|
|
276
|
-
await this.forEachObserver(
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
290
|
+
await this.forEachObserver(
|
|
291
|
+
"runtime start",
|
|
292
|
+
{ driver: this.driver.name },
|
|
293
|
+
async (observer) => {
|
|
294
|
+
await observer.notifyRuntimeStart?.({
|
|
295
|
+
driver: this.driver.name,
|
|
296
|
+
at: Date.now()
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
);
|
|
282
300
|
this.logger.info("Runtime started", { driver: this.driver.name });
|
|
283
301
|
} catch (error) {
|
|
284
302
|
this.started = false;
|
|
@@ -315,18 +333,25 @@ var WorkloadRuntime = class {
|
|
|
315
333
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
316
334
|
}
|
|
317
335
|
if (this.inFlight.size > 0) {
|
|
318
|
-
this.logger.warn(
|
|
319
|
-
|
|
320
|
-
|
|
336
|
+
this.logger.warn(
|
|
337
|
+
"Drain timeout reached, stopping with in-flight jobs",
|
|
338
|
+
{
|
|
339
|
+
remaining: this.inFlight.size
|
|
340
|
+
}
|
|
341
|
+
);
|
|
321
342
|
}
|
|
322
343
|
}
|
|
323
344
|
await this.driver.stop();
|
|
324
|
-
await this.forEachObserver(
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
345
|
+
await this.forEachObserver(
|
|
346
|
+
"runtime stop",
|
|
347
|
+
{ driver: this.driver.name },
|
|
348
|
+
async (observer) => {
|
|
349
|
+
await observer.notifyRuntimeStop?.({
|
|
350
|
+
driver: this.driver.name,
|
|
351
|
+
at: Date.now()
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
);
|
|
330
355
|
this.logger.info("Runtime stopped", { driver: this.driver.name });
|
|
331
356
|
}
|
|
332
357
|
status() {
|
|
@@ -356,7 +381,9 @@ var WorkloadRuntime = class {
|
|
|
356
381
|
const jobId = normalizeJobId(input.id ?? this.createId());
|
|
357
382
|
const name = normalizeJobName(input.name);
|
|
358
383
|
const metadata = input.metadata ?? existing?.metadata;
|
|
359
|
-
const retryPolicy = normalizeRetryPolicy(
|
|
384
|
+
const retryPolicy = normalizeRetryPolicy(
|
|
385
|
+
input.retryPolicy ?? existing?.retryPolicy
|
|
386
|
+
);
|
|
360
387
|
validateMetadata(metadata);
|
|
361
388
|
let enabled = input.enabled ?? existing?.enabled ?? true;
|
|
362
389
|
let nextRunAtMs = enabled ? computeNextRunAtMs(schedule, now) : void 0;
|
|
@@ -386,7 +413,9 @@ var WorkloadRuntime = class {
|
|
|
386
413
|
const now = Date.now();
|
|
387
414
|
const name = normalizeJobName(patch.name ?? current.name);
|
|
388
415
|
const nextSchedule = patch.schedule ? normalizeSchedule(patch.schedule) : current.schedule;
|
|
389
|
-
const retryPolicy = normalizeRetryPolicy(
|
|
416
|
+
const retryPolicy = normalizeRetryPolicy(
|
|
417
|
+
patch.retryPolicy ?? current.retryPolicy
|
|
418
|
+
);
|
|
390
419
|
let enabled = patch.enabled ?? current.enabled;
|
|
391
420
|
const metadata = patch.metadata ?? current.metadata;
|
|
392
421
|
validateMetadata(metadata);
|
|
@@ -593,9 +622,13 @@ var WorkloadRuntime = class {
|
|
|
593
622
|
}
|
|
594
623
|
async emitDeadLetter(event) {
|
|
595
624
|
if (!this.onDeadLetter) {
|
|
596
|
-
await this.forEachObserver(
|
|
597
|
-
|
|
598
|
-
|
|
625
|
+
await this.forEachObserver(
|
|
626
|
+
"dead letter",
|
|
627
|
+
{ jobId: event.job.id },
|
|
628
|
+
async (observer) => {
|
|
629
|
+
await observer.notifyDeadLetter?.(event);
|
|
630
|
+
}
|
|
631
|
+
);
|
|
599
632
|
return;
|
|
600
633
|
}
|
|
601
634
|
try {
|
|
@@ -606,9 +639,13 @@ var WorkloadRuntime = class {
|
|
|
606
639
|
error: String(error)
|
|
607
640
|
});
|
|
608
641
|
}
|
|
609
|
-
await this.forEachObserver(
|
|
610
|
-
|
|
611
|
-
|
|
642
|
+
await this.forEachObserver(
|
|
643
|
+
"dead letter",
|
|
644
|
+
{ jobId: event.job.id },
|
|
645
|
+
async (observer) => {
|
|
646
|
+
await observer.notifyDeadLetter?.(event);
|
|
647
|
+
}
|
|
648
|
+
);
|
|
612
649
|
}
|
|
613
650
|
async executeReservedJob(jobId, trigger) {
|
|
614
651
|
const startedAt = Date.now();
|
|
@@ -646,13 +683,17 @@ var WorkloadRuntime = class {
|
|
|
646
683
|
error: String(error)
|
|
647
684
|
});
|
|
648
685
|
});
|
|
649
|
-
await this.forEachObserver(
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
686
|
+
await this.forEachObserver(
|
|
687
|
+
"run start",
|
|
688
|
+
{ jobId, trigger },
|
|
689
|
+
async (observer) => {
|
|
690
|
+
await observer.notifyRunStart?.({
|
|
691
|
+
job,
|
|
692
|
+
trigger,
|
|
693
|
+
startedAt
|
|
694
|
+
});
|
|
695
|
+
}
|
|
696
|
+
);
|
|
656
697
|
const retryPolicy = normalizeRetryPolicy(job.retryPolicy);
|
|
657
698
|
const maxAttempts = retryPolicy?.maxAttempts ?? 1;
|
|
658
699
|
const abortController = new AbortController();
|
|
@@ -686,7 +727,12 @@ var WorkloadRuntime = class {
|
|
|
686
727
|
});
|
|
687
728
|
await this.forEachObserver(
|
|
688
729
|
"run retry",
|
|
689
|
-
{
|
|
730
|
+
{
|
|
731
|
+
jobId,
|
|
732
|
+
trigger,
|
|
733
|
+
attempt: attemptCount,
|
|
734
|
+
nextAttempt: attemptCount + 1
|
|
735
|
+
},
|
|
690
736
|
async (observer) => {
|
|
691
737
|
await observer.notifyRunRetry?.({
|
|
692
738
|
job,
|
|
@@ -862,7 +908,9 @@ function normalizeLimit(value) {
|
|
|
862
908
|
return void 0;
|
|
863
909
|
}
|
|
864
910
|
if (!Number.isFinite(value)) {
|
|
865
|
-
throw new Error(
|
|
911
|
+
throw new Error(
|
|
912
|
+
`limit must be a finite number. Received: ${String(value)}`
|
|
913
|
+
);
|
|
866
914
|
}
|
|
867
915
|
return Math.max(0, Math.floor(value));
|
|
868
916
|
}
|
|
@@ -871,7 +919,9 @@ function normalizeScheduleAheadMs(value) {
|
|
|
871
919
|
return DEFAULT_SCHEDULE_AHEAD_MS;
|
|
872
920
|
}
|
|
873
921
|
if (!Number.isFinite(value)) {
|
|
874
|
-
throw new Error(
|
|
922
|
+
throw new Error(
|
|
923
|
+
`scheduleAheadMs must be a finite number. Received: ${String(value)}`
|
|
924
|
+
);
|
|
875
925
|
}
|
|
876
926
|
return Math.max(1, Math.floor(value));
|
|
877
927
|
}
|
|
@@ -920,7 +970,10 @@ var AgentOrchestrator = class {
|
|
|
920
970
|
this.store = options.store ?? new InMemoryOrchestratorRunStore();
|
|
921
971
|
this.logger = options.logger ?? options.runtime?.logger ?? silentRuntimeLogger;
|
|
922
972
|
this.createId = options.createId ?? (() => randomUUID2());
|
|
923
|
-
this.jobIdPrefix = normalizeNonEmpty(
|
|
973
|
+
this.jobIdPrefix = normalizeNonEmpty(
|
|
974
|
+
options.jobIdPrefix ?? DEFAULT_JOB_ID_PREFIX,
|
|
975
|
+
"jobIdPrefix"
|
|
976
|
+
);
|
|
924
977
|
this.runLabelPrefix = normalizeNonEmpty(
|
|
925
978
|
options.runLabelPrefix ?? DEFAULT_RUN_LABEL_PREFIX,
|
|
926
979
|
"runLabelPrefix"
|
|
@@ -972,9 +1025,12 @@ var AgentOrchestrator = class {
|
|
|
972
1025
|
if (!runtimeError) {
|
|
973
1026
|
throw error;
|
|
974
1027
|
}
|
|
975
|
-
this.logger.error(
|
|
976
|
-
|
|
977
|
-
|
|
1028
|
+
this.logger.error(
|
|
1029
|
+
"Failed to stop orchestrator run store after runtime stop failure",
|
|
1030
|
+
{
|
|
1031
|
+
error: toErrorMessage(error)
|
|
1032
|
+
}
|
|
1033
|
+
);
|
|
978
1034
|
}
|
|
979
1035
|
if (runtimeError) {
|
|
980
1036
|
throw runtimeError;
|
|
@@ -1008,7 +1064,10 @@ var AgentOrchestrator = class {
|
|
|
1008
1064
|
const now = Date.now();
|
|
1009
1065
|
const run = {
|
|
1010
1066
|
id: runId,
|
|
1011
|
-
label: normalizeNonEmpty(
|
|
1067
|
+
label: normalizeNonEmpty(
|
|
1068
|
+
input.label ?? `${this.runLabelPrefix}:${runId}`,
|
|
1069
|
+
"label"
|
|
1070
|
+
),
|
|
1012
1071
|
input: input.input,
|
|
1013
1072
|
parentRunId: input.parentRunId?.trim() || void 0,
|
|
1014
1073
|
metadata: input.metadata,
|
|
@@ -1031,7 +1090,9 @@ var AgentOrchestrator = class {
|
|
|
1031
1090
|
});
|
|
1032
1091
|
} catch (error) {
|
|
1033
1092
|
await this.failRunLaunch(run, error, "Failed to schedule run");
|
|
1034
|
-
throw new Error(
|
|
1093
|
+
throw new Error(
|
|
1094
|
+
`Failed to schedule run "${runId}": ${toErrorMessage(error)}`
|
|
1095
|
+
);
|
|
1035
1096
|
}
|
|
1036
1097
|
return {
|
|
1037
1098
|
run: await this.requireRun(runId),
|
|
@@ -1067,60 +1128,72 @@ var AgentOrchestrator = class {
|
|
|
1067
1128
|
if (isTerminalRunStatus(current.state.status)) {
|
|
1068
1129
|
return current;
|
|
1069
1130
|
}
|
|
1070
|
-
return await new Promise(
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
options.signal
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1131
|
+
return await new Promise(
|
|
1132
|
+
(resolve, reject) => {
|
|
1133
|
+
const timeoutRef = {};
|
|
1134
|
+
let abortHandler;
|
|
1135
|
+
const cleanup = () => {
|
|
1136
|
+
if (timeoutRef.current) {
|
|
1137
|
+
clearTimeout(timeoutRef.current);
|
|
1138
|
+
}
|
|
1139
|
+
if (abortHandler && options.signal) {
|
|
1140
|
+
options.signal.removeEventListener("abort", abortHandler);
|
|
1141
|
+
}
|
|
1142
|
+
const currentGroup = this.waiters.get(normalizedRunId);
|
|
1143
|
+
currentGroup?.delete(waiter);
|
|
1144
|
+
if (currentGroup && currentGroup.size === 0) {
|
|
1145
|
+
this.waiters.delete(normalizedRunId);
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
const waiter = {
|
|
1149
|
+
resolve: (record) => {
|
|
1150
|
+
cleanup();
|
|
1151
|
+
resolve(record);
|
|
1152
|
+
},
|
|
1153
|
+
reject: (error) => {
|
|
1154
|
+
cleanup();
|
|
1155
|
+
reject(error);
|
|
1156
|
+
}
|
|
1157
|
+
};
|
|
1158
|
+
const group = this.waiters.get(normalizedRunId) ?? /* @__PURE__ */ new Set();
|
|
1159
|
+
group.add(waiter);
|
|
1160
|
+
this.waiters.set(normalizedRunId, group);
|
|
1161
|
+
if (options.signal) {
|
|
1162
|
+
abortHandler = () => {
|
|
1163
|
+
waiter.reject(
|
|
1164
|
+
new Error(`Waiting for run "${normalizedRunId}" aborted`)
|
|
1165
|
+
);
|
|
1166
|
+
};
|
|
1167
|
+
if (options.signal.aborted) {
|
|
1168
|
+
abortHandler();
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
options.signal.addEventListener("abort", abortHandler, {
|
|
1172
|
+
once: true
|
|
1173
|
+
});
|
|
1084
1174
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
resolve: (record) => {
|
|
1088
|
-
cleanup();
|
|
1089
|
-
resolve(record);
|
|
1090
|
-
},
|
|
1091
|
-
reject: (error) => {
|
|
1092
|
-
cleanup();
|
|
1093
|
-
reject(error);
|
|
1175
|
+
if (options.timeoutMs === void 0) {
|
|
1176
|
+
return;
|
|
1094
1177
|
}
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
waiter.reject(new Error(`Waiting for run "${normalizedRunId}" aborted`));
|
|
1102
|
-
};
|
|
1103
|
-
if (options.signal.aborted) {
|
|
1104
|
-
abortHandler();
|
|
1178
|
+
if (!Number.isFinite(options.timeoutMs) || options.timeoutMs <= 0) {
|
|
1179
|
+
waiter.reject(
|
|
1180
|
+
new Error(
|
|
1181
|
+
`timeoutMs must be greater than zero. Received: ${String(options.timeoutMs)}`
|
|
1182
|
+
)
|
|
1183
|
+
);
|
|
1105
1184
|
return;
|
|
1106
1185
|
}
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
);
|
|
1116
|
-
return;
|
|
1186
|
+
const timeoutMs = Math.floor(options.timeoutMs);
|
|
1187
|
+
timeoutRef.current = setTimeout(() => {
|
|
1188
|
+
waiter.reject(
|
|
1189
|
+
new Error(
|
|
1190
|
+
`Timed out waiting for run "${normalizedRunId}" after ${timeoutMs}ms`
|
|
1191
|
+
)
|
|
1192
|
+
);
|
|
1193
|
+
}, timeoutMs);
|
|
1194
|
+
timeoutRef.current.unref?.();
|
|
1117
1195
|
}
|
|
1118
|
-
|
|
1119
|
-
timeoutRef.current = setTimeout(() => {
|
|
1120
|
-
waiter.reject(new Error(`Timed out waiting for run "${normalizedRunId}" after ${timeoutMs}ms`));
|
|
1121
|
-
}, timeoutMs);
|
|
1122
|
-
timeoutRef.current.unref?.();
|
|
1123
|
-
});
|
|
1196
|
+
);
|
|
1124
1197
|
}
|
|
1125
1198
|
async close(runId, options = {}) {
|
|
1126
1199
|
const normalizedRunId = normalizeId(runId, "runId");
|
|
@@ -1165,7 +1238,9 @@ var AgentOrchestrator = class {
|
|
|
1165
1238
|
const guideMessage = normalizeNonEmpty(input.message, "message");
|
|
1166
1239
|
const run = await this.requireRun(runId);
|
|
1167
1240
|
if (isTerminalRunStatus(run.state.status)) {
|
|
1168
|
-
throw new Error(
|
|
1241
|
+
throw new Error(
|
|
1242
|
+
`Cannot guide terminal run "${runId}" (${run.state.status})`
|
|
1243
|
+
);
|
|
1169
1244
|
}
|
|
1170
1245
|
const nextInput = input.input ?? this.resolveGuidedInput({
|
|
1171
1246
|
run,
|
|
@@ -1206,13 +1281,17 @@ var AgentOrchestrator = class {
|
|
|
1206
1281
|
});
|
|
1207
1282
|
} catch (error) {
|
|
1208
1283
|
await this.failRunLaunch(next, error, "Failed to relaunch guided run");
|
|
1209
|
-
throw new Error(
|
|
1284
|
+
throw new Error(
|
|
1285
|
+
`Failed to relaunch guided run "${runId}": ${toErrorMessage(error)}`
|
|
1286
|
+
);
|
|
1210
1287
|
}
|
|
1211
1288
|
return await this.requireRun(runId);
|
|
1212
1289
|
}
|
|
1213
1290
|
ensureStarted() {
|
|
1214
1291
|
if (!this.runtime.status().started) {
|
|
1215
|
-
throw new Error(
|
|
1292
|
+
throw new Error(
|
|
1293
|
+
"Orchestrator runtime is not started. Call start() before this operation."
|
|
1294
|
+
);
|
|
1216
1295
|
}
|
|
1217
1296
|
}
|
|
1218
1297
|
toJobId(runId) {
|
|
@@ -1311,7 +1390,11 @@ var AgentOrchestrator = class {
|
|
|
1311
1390
|
jobId,
|
|
1312
1391
|
error: toErrorMessage(error)
|
|
1313
1392
|
});
|
|
1314
|
-
void this.failPendingRunLaunch(
|
|
1393
|
+
void this.failPendingRunLaunch(
|
|
1394
|
+
run.id,
|
|
1395
|
+
error,
|
|
1396
|
+
"Run dispatch failed"
|
|
1397
|
+
).catch((persistError) => {
|
|
1315
1398
|
this.logger.error("Failed to persist run dispatch failure", {
|
|
1316
1399
|
runId: run.id,
|
|
1317
1400
|
jobId,
|
|
@@ -1367,7 +1450,9 @@ var AgentOrchestrator = class {
|
|
|
1367
1450
|
await this.store.upsert(running);
|
|
1368
1451
|
const runController = new AbortController();
|
|
1369
1452
|
const onRuntimeAbort = () => runController.abort();
|
|
1370
|
-
runtimeContext.signal.addEventListener("abort", onRuntimeAbort, {
|
|
1453
|
+
runtimeContext.signal.addEventListener("abort", onRuntimeAbort, {
|
|
1454
|
+
once: true
|
|
1455
|
+
});
|
|
1371
1456
|
this.runControllers.set(run.id, runController);
|
|
1372
1457
|
try {
|
|
1373
1458
|
const result = await this.executeRun(running, {
|
|
@@ -1431,14 +1516,16 @@ var AgentOrchestrator = class {
|
|
|
1431
1516
|
runId: queued.id,
|
|
1432
1517
|
error: toErrorMessage(retryError)
|
|
1433
1518
|
});
|
|
1434
|
-
void this.failRunLaunch(
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1519
|
+
void this.failRunLaunch(
|
|
1520
|
+
queued,
|
|
1521
|
+
retryError,
|
|
1522
|
+
"Failed to relaunch guided run"
|
|
1523
|
+
).catch((persistError) => {
|
|
1524
|
+
this.logger.error("Failed to persist guided relaunch failure", {
|
|
1525
|
+
runId: queued.id,
|
|
1526
|
+
error: toErrorMessage(persistError)
|
|
1527
|
+
});
|
|
1528
|
+
});
|
|
1442
1529
|
});
|
|
1443
1530
|
}, 0);
|
|
1444
1531
|
retryTimer.unref?.();
|
|
@@ -44,17 +44,25 @@ function normalizeSchedule(input) {
|
|
|
44
44
|
if (input.kind === "every") {
|
|
45
45
|
const everyMs = Math.floor(input.everyMs);
|
|
46
46
|
if (!Number.isFinite(everyMs) || everyMs <= 0) {
|
|
47
|
-
throw new Error(
|
|
47
|
+
throw new Error(
|
|
48
|
+
`Invalid every-schedule interval: ${String(input.everyMs)}`
|
|
49
|
+
);
|
|
48
50
|
}
|
|
49
51
|
let anchorMs;
|
|
50
52
|
if (input.anchorMs !== void 0) {
|
|
51
53
|
const nextAnchor = Math.floor(input.anchorMs);
|
|
52
54
|
if (!Number.isFinite(nextAnchor) || nextAnchor < 0) {
|
|
53
|
-
throw new Error(
|
|
55
|
+
throw new Error(
|
|
56
|
+
`Invalid every-schedule anchor: ${String(input.anchorMs)}`
|
|
57
|
+
);
|
|
54
58
|
}
|
|
55
59
|
anchorMs = nextAnchor;
|
|
56
60
|
}
|
|
57
|
-
return {
|
|
61
|
+
return {
|
|
62
|
+
kind: "every",
|
|
63
|
+
everyMs,
|
|
64
|
+
...anchorMs !== void 0 ? { anchorMs } : {}
|
|
65
|
+
};
|
|
58
66
|
}
|
|
59
67
|
const expr = input.expr.trim();
|
|
60
68
|
if (!expr) {
|
|
@@ -76,7 +84,10 @@ function computeNextRunAtMs(schedule, nowMs) {
|
|
|
76
84
|
return anchor;
|
|
77
85
|
}
|
|
78
86
|
const elapsed = nowMs - anchor;
|
|
79
|
-
const steps = Math.max(
|
|
87
|
+
const steps = Math.max(
|
|
88
|
+
1,
|
|
89
|
+
Math.floor((elapsed + schedule.everyMs - 1) / schedule.everyMs)
|
|
90
|
+
);
|
|
80
91
|
return anchor + steps * schedule.everyMs;
|
|
81
92
|
}
|
|
82
93
|
const cron = resolveCachedCron(schedule);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computeNextRunAtMs
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-PXXGA4YJ.js";
|
|
4
4
|
|
|
5
5
|
// src/drivers/in-memory.ts
|
|
6
6
|
import { Cron } from "croner";
|
|
@@ -15,7 +15,10 @@ var InMemoryRuntimeDriver = class {
|
|
|
15
15
|
context;
|
|
16
16
|
started = false;
|
|
17
17
|
constructor(options = {}) {
|
|
18
|
-
this.maxTimerDelayMs = Math.max(
|
|
18
|
+
this.maxTimerDelayMs = Math.max(
|
|
19
|
+
1e3,
|
|
20
|
+
Math.floor(options.maxTimerDelayMs ?? 6e4)
|
|
21
|
+
);
|
|
19
22
|
}
|
|
20
23
|
async start(context) {
|
|
21
24
|
if (this.started) {
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
InMemoryRuntimeDriver
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RCSNDSHJ.js";
|
|
4
4
|
import {
|
|
5
5
|
AgentOrchestrator,
|
|
6
6
|
InMemoryOrchestratorRunStore,
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
createWorkloadRuntime,
|
|
11
11
|
isTerminalRunStatus,
|
|
12
12
|
silentRuntimeLogger
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DRMXPKPK.js";
|
|
14
14
|
import {
|
|
15
15
|
computeNextRunAtMs,
|
|
16
16
|
normalizeSchedule
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-PXXGA4YJ.js";
|
|
18
18
|
import {
|
|
19
19
|
createRuntimeWorkloadContext,
|
|
20
20
|
createRuntimeWorkloadExecutor
|
|
@@ -39,14 +39,18 @@ var PROMETHEUS_TEXT_CONTENT_TYPE = "text/plain; version=0.0.4; charset=utf-8";
|
|
|
39
39
|
function normalizeMetricPrefix(value) {
|
|
40
40
|
const normalized = (value ?? DEFAULT_METRIC_PREFIX).trim().replace(/[^a-zA-Z0-9_:]/g, "_").replace(/^[^a-zA-Z_:]+/, "");
|
|
41
41
|
if (!normalized) {
|
|
42
|
-
throw new Error(
|
|
42
|
+
throw new Error(
|
|
43
|
+
"metricPrefix must contain at least one valid Prometheus metric character"
|
|
44
|
+
);
|
|
43
45
|
}
|
|
44
46
|
return normalized;
|
|
45
47
|
}
|
|
46
48
|
function normalizeDurationBuckets(value) {
|
|
47
49
|
const buckets = [...value ?? DEFAULT_DURATION_BUCKETS_MS].map((bucket) => Math.floor(bucket)).filter((bucket) => Number.isFinite(bucket) && bucket > 0).sort((left, right) => left - right);
|
|
48
50
|
if (buckets.length === 0) {
|
|
49
|
-
throw new Error(
|
|
51
|
+
throw new Error(
|
|
52
|
+
"durationBucketsMs must include at least one positive bucket"
|
|
53
|
+
);
|
|
50
54
|
}
|
|
51
55
|
return [...new Set(buckets)];
|
|
52
56
|
}
|
|
@@ -62,7 +66,9 @@ function cloneLabels(labels) {
|
|
|
62
66
|
);
|
|
63
67
|
}
|
|
64
68
|
function serializeLabels(labels) {
|
|
65
|
-
const entries = Object.entries(labels).sort(
|
|
69
|
+
const entries = Object.entries(labels).sort(
|
|
70
|
+
([left], [right]) => left.localeCompare(right)
|
|
71
|
+
);
|
|
66
72
|
return entries.map(([key, value]) => `${key}="${escapeLabelValue(value)}"`).join(",");
|
|
67
73
|
}
|
|
68
74
|
function labelsKey(labels) {
|
|
@@ -259,7 +265,10 @@ function createPrometheusRuntimeMetrics(options = {}) {
|
|
|
259
265
|
mergeLabels(defaultLabels, { trigger: event.trigger })
|
|
260
266
|
);
|
|
261
267
|
adjustGauge(inFlightGauge, baseGaugeLabels, 1);
|
|
262
|
-
const queueDepth = getOrCreateMetricEntry(
|
|
268
|
+
const queueDepth = getOrCreateMetricEntry(
|
|
269
|
+
queueDepthGauge,
|
|
270
|
+
baseGaugeLabels
|
|
271
|
+
);
|
|
263
272
|
if (queueDepth.value > 0) {
|
|
264
273
|
queueDepth.value -= 1;
|
|
265
274
|
}
|
|
@@ -333,7 +342,9 @@ function createPrometheusRuntimeMetrics(options = {}) {
|
|
|
333
342
|
};
|
|
334
343
|
const render = () => {
|
|
335
344
|
const lines = [];
|
|
336
|
-
for (const [name, store] of [...counters.entries()].sort(
|
|
345
|
+
for (const [name, store] of [...counters.entries()].sort(
|
|
346
|
+
([left], [right]) => left.localeCompare(right)
|
|
347
|
+
)) {
|
|
337
348
|
lines.push(`# HELP ${name} ${escapeMetricHelp(store.help)}`);
|
|
338
349
|
lines.push(`# TYPE ${name} ${store.type}`);
|
|
339
350
|
for (const entry of sortMetricEntries(store.entries.values())) {
|
|
@@ -341,7 +352,9 @@ function createPrometheusRuntimeMetrics(options = {}) {
|
|
|
341
352
|
lines.push(`${name}${labels ? `{${labels}}` : ""} ${entry.value}`);
|
|
342
353
|
}
|
|
343
354
|
}
|
|
344
|
-
for (const [name, store] of [...gauges.entries()].sort(
|
|
355
|
+
for (const [name, store] of [...gauges.entries()].sort(
|
|
356
|
+
([left], [right]) => left.localeCompare(right)
|
|
357
|
+
)) {
|
|
345
358
|
lines.push(`# HELP ${name} ${escapeMetricHelp(store.help)}`);
|
|
346
359
|
lines.push(`# TYPE ${name} ${store.type}`);
|
|
347
360
|
for (const entry of sortMetricEntries(store.entries.values())) {
|
|
@@ -349,7 +362,9 @@ function createPrometheusRuntimeMetrics(options = {}) {
|
|
|
349
362
|
lines.push(`${name}${labels ? `{${labels}}` : ""} ${entry.value}`);
|
|
350
363
|
}
|
|
351
364
|
}
|
|
352
|
-
for (const [name, store] of [...histograms.entries()].sort(
|
|
365
|
+
for (const [name, store] of [...histograms.entries()].sort(
|
|
366
|
+
([left], [right]) => left.localeCompare(right)
|
|
367
|
+
)) {
|
|
353
368
|
lines.push(`# HELP ${name} ${escapeMetricHelp(store.help)}`);
|
|
354
369
|
lines.push(`# TYPE ${name} ${store.type}`);
|
|
355
370
|
for (const entry of sortMetricEntries(store.entries.values())) {
|
|
@@ -367,8 +382,12 @@ function createPrometheusRuntimeMetrics(options = {}) {
|
|
|
367
382
|
});
|
|
368
383
|
const seriesLabels = serializeLabels(baseLabels);
|
|
369
384
|
lines.push(`${name}_bucket{${infiniteLabels}} ${entry.count}`);
|
|
370
|
-
lines.push(
|
|
371
|
-
|
|
385
|
+
lines.push(
|
|
386
|
+
`${name}_sum${seriesLabels ? `{${seriesLabels}}` : ""} ${entry.sum}`
|
|
387
|
+
);
|
|
388
|
+
lines.push(
|
|
389
|
+
`${name}_count${seriesLabels ? `{${seriesLabels}}` : ""} ${entry.count}`
|
|
390
|
+
);
|
|
372
391
|
}
|
|
373
392
|
}
|
|
374
393
|
return `${lines.join("\n")}
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
InMemoryOrchestratorRunStore,
|
|
4
4
|
createAgentOrchestrator,
|
|
5
5
|
isTerminalRunStatus
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-DRMXPKPK.js";
|
|
7
|
+
import "../chunk-PXXGA4YJ.js";
|
|
8
8
|
export {
|
|
9
9
|
AgentOrchestrator,
|
|
10
10
|
InMemoryOrchestratorRunStore,
|
package/package.json
CHANGED