@rk0429/agentic-relay 20.1.0 → 21.0.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.
Files changed (99) hide show
  1. package/dist/application/event-log-sink.d.ts +13 -9
  2. package/dist/application/event-log-sink.js +29 -22
  3. package/dist/application/event-log-sink.js.map +1 -1
  4. package/dist/application/housekeeping.js +8 -4
  5. package/dist/application/housekeeping.js.map +1 -1
  6. package/dist/application/projection-service.js +6 -3
  7. package/dist/application/projection-service.js.map +1 -1
  8. package/dist/application/routine-catalog-service.d.ts +36 -0
  9. package/dist/application/routine-catalog-service.js +90 -0
  10. package/dist/application/routine-catalog-service.js.map +1 -0
  11. package/dist/application/routine-daemon-service.d.ts +48 -0
  12. package/dist/application/routine-daemon-service.js +176 -0
  13. package/dist/application/routine-daemon-service.js.map +1 -0
  14. package/dist/application/routine-event-log-sink.d.ts +42 -0
  15. package/dist/application/routine-event-log-sink.js +82 -0
  16. package/dist/application/routine-event-log-sink.js.map +1 -0
  17. package/dist/application/routine-run-service.d.ts +56 -0
  18. package/dist/application/routine-run-service.js +370 -0
  19. package/dist/application/routine-run-service.js.map +1 -0
  20. package/dist/application/routine-scheduler.d.ts +34 -0
  21. package/dist/application/routine-scheduler.js +82 -0
  22. package/dist/application/routine-scheduler.js.map +1 -0
  23. package/dist/application/routine-status-query-service.d.ts +41 -0
  24. package/dist/application/routine-status-query-service.js +98 -0
  25. package/dist/application/routine-status-query-service.js.map +1 -0
  26. package/dist/application/spawn-agents-service.js +88 -37
  27. package/dist/application/spawn-agents-service.js.map +1 -1
  28. package/dist/application/workflow-execution-service.d.ts +5 -1
  29. package/dist/application/workflow-execution-service.js +82 -23
  30. package/dist/application/workflow-execution-service.js.map +1 -1
  31. package/dist/bin/relay.d.ts +58 -1
  32. package/dist/bin/relay.js +421 -50
  33. package/dist/bin/relay.js.map +1 -1
  34. package/dist/core/types.d.ts +8 -1
  35. package/dist/core/types.js +5 -0
  36. package/dist/core/types.js.map +1 -1
  37. package/dist/domain/loop-execution.d.ts +1 -1
  38. package/dist/domain/loop-execution.js +8 -4
  39. package/dist/domain/loop-execution.js.map +1 -1
  40. package/dist/domain/routine-definition.d.ts +18 -0
  41. package/dist/domain/routine-definition.js +19 -0
  42. package/dist/domain/routine-definition.js.map +1 -0
  43. package/dist/domain/routine-execution-state.d.ts +35 -0
  44. package/dist/domain/routine-execution-state.js +97 -0
  45. package/dist/domain/routine-execution-state.js.map +1 -0
  46. package/dist/domain/routine-firing.d.ts +23 -0
  47. package/dist/domain/routine-firing.js +47 -0
  48. package/dist/domain/routine-firing.js.map +1 -0
  49. package/dist/domain/routine-loader.d.ts +9 -0
  50. package/dist/domain/routine-loader.js +129 -0
  51. package/dist/domain/routine-loader.js.map +1 -0
  52. package/dist/domain/routine-name.d.ts +6 -0
  53. package/dist/domain/routine-name.js +31 -0
  54. package/dist/domain/routine-name.js.map +1 -0
  55. package/dist/domain/routine-schedule.d.ts +24 -0
  56. package/dist/domain/routine-schedule.js +126 -0
  57. package/dist/domain/routine-schedule.js.map +1 -0
  58. package/dist/domain/trigger-config.d.ts +25 -0
  59. package/dist/domain/trigger-config.js +86 -0
  60. package/dist/domain/trigger-config.js.map +1 -0
  61. package/dist/domain/workflow-loader.d.ts +2 -0
  62. package/dist/domain/workflow-loader.js +12 -2
  63. package/dist/domain/workflow-loader.js.map +1 -1
  64. package/dist/domain/workflow-schema.d.ts +20 -1
  65. package/dist/domain/workflow-schema.js +43 -7
  66. package/dist/domain/workflow-schema.js.map +1 -1
  67. package/dist/infrastructure/backends/cli-backend-executor.js +17 -0
  68. package/dist/infrastructure/backends/cli-backend-executor.js.map +1 -1
  69. package/dist/infrastructure/command-execution-gateway.d.ts +21 -0
  70. package/dist/infrastructure/command-execution-gateway.js +24 -0
  71. package/dist/infrastructure/command-execution-gateway.js.map +1 -0
  72. package/dist/infrastructure/diagnostics/codex-bootstrap.d.ts +3 -0
  73. package/dist/infrastructure/diagnostics/codex-bootstrap.js +35 -1
  74. package/dist/infrastructure/diagnostics/codex-bootstrap.js.map +1 -1
  75. package/dist/infrastructure/store/file-utils.d.ts +2 -0
  76. package/dist/infrastructure/store/file-utils.js +23 -0
  77. package/dist/infrastructure/store/file-utils.js.map +1 -0
  78. package/dist/infrastructure/store/relay-store.d.ts +1 -0
  79. package/dist/infrastructure/store/relay-store.js +6 -22
  80. package/dist/infrastructure/store/relay-store.js.map +1 -1
  81. package/dist/infrastructure/store/routine-execution-lease-repository.d.ts +31 -0
  82. package/dist/infrastructure/store/routine-execution-lease-repository.js +191 -0
  83. package/dist/infrastructure/store/routine-execution-lease-repository.js.map +1 -0
  84. package/dist/infrastructure/store/routine-runtime-projection-repository.d.ts +25 -0
  85. package/dist/infrastructure/store/routine-runtime-projection-repository.js +126 -0
  86. package/dist/infrastructure/store/routine-runtime-projection-repository.js.map +1 -0
  87. package/dist/infrastructure/store/routine-state-repository.d.ts +21 -0
  88. package/dist/infrastructure/store/routine-state-repository.js +139 -0
  89. package/dist/infrastructure/store/routine-state-repository.js.map +1 -0
  90. package/dist/interfaces/cli/loop-progress-renderer.js +3 -1
  91. package/dist/interfaces/cli/loop-progress-renderer.js.map +1 -1
  92. package/dist/interfaces/cli/relay-cli-args.d.ts +18 -2
  93. package/dist/interfaces/cli/relay-cli-args.js +171 -50
  94. package/dist/interfaces/cli/relay-cli-args.js.map +1 -1
  95. package/dist/interfaces/mcp/relay-mcp-server.js +2 -2
  96. package/dist/interfaces/mcp/relay-mcp-server.js.map +1 -1
  97. package/dist/interfaces/vscode/extension.js +3 -3
  98. package/dist/interfaces/vscode/extension.js.map +1 -1
  99. package/package.json +2 -1
@@ -0,0 +1,129 @@
1
+ import { resolve } from "node:path";
2
+ import { parseDocument, stringify } from "yaml";
3
+ import { z } from "zod";
4
+ import { ValidationError } from "../core/errors.js";
5
+ import { RoutineDefinition } from "./routine-definition.js";
6
+ import { RoutineName } from "./routine-name.js";
7
+ import { loadWorkflow, } from "./workflow-loader.js";
8
+ import { CatchUpLimit, CronExpression, TriggerConfig, } from "./trigger-config.js";
9
+ const rawTriggerSchema = z.object({
10
+ schedule: z.string().trim().min(1),
11
+ missed_policy: z.enum(["catch_up", "skip"]).default("skip"),
12
+ catch_up_limit: z.number().int().min(1).default(1),
13
+ });
14
+ const routineYamlSchema = z.object({
15
+ name: z.string(),
16
+ description: z.string().trim().min(1).optional(),
17
+ trigger: rawTriggerSchema.optional(),
18
+ loop: z.unknown().optional(),
19
+ });
20
+ export async function loadRoutine(yamlPath, repo, vars = {}) {
21
+ const canonicalPath = resolve(yamlPath);
22
+ if (!(await repo.exists(canonicalPath))) {
23
+ throw new ValidationError(`Routine file does not exist: ${canonicalPath}`, {
24
+ recoveryHint: "Provide a valid routine YAML path.",
25
+ });
26
+ }
27
+ const source = await repo.read(canonicalPath);
28
+ const document = parseDocument(source);
29
+ if (document.errors.length > 0) {
30
+ throw new ValidationError(document.errors.map((error) => error.message).join("\n"), {
31
+ causeData: {
32
+ errors: document.errors.map((error) => error.message),
33
+ },
34
+ recoveryHint: "Fix the YAML syntax and try again.",
35
+ });
36
+ }
37
+ const rawValue = document.toJS();
38
+ const parsed = validateRoutineYaml(rawValue);
39
+ const routineName = validateRoutineName(parsed.name);
40
+ const trigger = parsed.trigger ? mapTriggerConfig(parsed.trigger) : undefined;
41
+ const hasExplicitLoop = isRecord(rawValue) && "loop" in rawValue;
42
+ const normalizedRoot = parsed.loop === undefined
43
+ ? {
44
+ ...(isRecord(rawValue) ? rawValue : {}),
45
+ loop: {
46
+ max_iterations: 1,
47
+ exit_conditions: [],
48
+ },
49
+ }
50
+ : rawValue;
51
+ const workflowRepo = parsed.loop === undefined
52
+ ? createNormalizedRootRepo(canonicalPath, stringify(normalizedRoot), repo)
53
+ : repo;
54
+ const loaded = await loadWorkflow(canonicalPath, workflowRepo, undefined, vars);
55
+ return {
56
+ routineDefinition: new RoutineDefinition({
57
+ name: routineName,
58
+ description: parsed.description,
59
+ trigger,
60
+ workflow: loaded.workflow,
61
+ }),
62
+ capabilitySummary: loaded.capabilitySummary,
63
+ workflowLoadResult: loaded,
64
+ hasExplicitLoop,
65
+ };
66
+ }
67
+ function validateRoutineYaml(input) {
68
+ const result = routineYamlSchema.safeParse(input);
69
+ if (!result.success) {
70
+ throw new ValidationError(result.error.issues
71
+ .map((issue) => `${formatIssuePath(issue.path)}: ${issue.message}`)
72
+ .join("\n"), {
73
+ causeData: {
74
+ issues: result.error.issues,
75
+ },
76
+ recoveryHint: "Fix the routine definition and try again.",
77
+ });
78
+ }
79
+ return result.data;
80
+ }
81
+ function validateRoutineName(value) {
82
+ try {
83
+ return new RoutineName(value);
84
+ }
85
+ catch (error) {
86
+ if (error instanceof ValidationError) {
87
+ throw new ValidationError(`name: ${error.message}`, {
88
+ causeData: error.causeData,
89
+ recoveryHint: error.recoveryHint,
90
+ });
91
+ }
92
+ throw error;
93
+ }
94
+ }
95
+ function mapTriggerConfig(raw) {
96
+ return new TriggerConfig({
97
+ schedule: new CronExpression(raw.schedule),
98
+ missedPolicy: raw.missed_policy,
99
+ catchUpLimit: new CatchUpLimit(raw.catch_up_limit),
100
+ });
101
+ }
102
+ function createNormalizedRootRepo(rootPath, normalizedRootSource, repo) {
103
+ return {
104
+ async read(filePath) {
105
+ return resolve(filePath) === rootPath
106
+ ? normalizedRootSource
107
+ : repo.read(filePath);
108
+ },
109
+ async exists(filePath) {
110
+ return resolve(filePath) === rootPath ? true : repo.exists(filePath);
111
+ },
112
+ };
113
+ }
114
+ function formatIssuePath(path) {
115
+ if (path.length === 0) {
116
+ return "(root)";
117
+ }
118
+ return path.reduce((formatted, segment) => {
119
+ if (typeof segment === "number") {
120
+ return `${formatted}[${segment}]`;
121
+ }
122
+ const value = String(segment);
123
+ return formatted.length === 0 ? value : `${formatted}.${value}`;
124
+ }, "");
125
+ }
126
+ function isRecord(value) {
127
+ return typeof value === "object" && value !== null;
128
+ }
129
+ //# sourceMappingURL=routine-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routine-loader.js","sourceRoot":"","sources":["../../src/domain/routine-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export declare class RoutineName {
2
+ readonly value: string;
3
+ constructor(value: string);
4
+ equals(other: RoutineName): boolean;
5
+ toString(): string;
6
+ }
@@ -0,0 +1,31 @@
1
+ import { ValidationError } from "../core/errors.js";
2
+ const ROUTINE_NAME_PATTERN = /^[a-z0-9][a-z0-9_-]*$/;
3
+ const MAX_ROUTINE_NAME_LENGTH = 128;
4
+ export class RoutineName {
5
+ value;
6
+ constructor(value) {
7
+ if (typeof value !== "string") {
8
+ throw new ValidationError(`Invalid routine name: ${String(value)}`, {
9
+ recoveryHint: "Routine names must be strings matching [a-z0-9][a-z0-9_-]* and be at most 128 characters long.",
10
+ });
11
+ }
12
+ if (value.length === 0 || value.length > MAX_ROUTINE_NAME_LENGTH) {
13
+ throw new ValidationError(`Invalid routine name length: ${value.length}`, {
14
+ recoveryHint: "Routine names must be between 1 and 128 characters long.",
15
+ });
16
+ }
17
+ if (!ROUTINE_NAME_PATTERN.test(value)) {
18
+ throw new ValidationError(`Invalid routine name: ${value}`, {
19
+ recoveryHint: "Routine names must match [a-z0-9][a-z0-9_-]* and contain only lowercase letters, digits, underscores, and hyphens.",
20
+ });
21
+ }
22
+ this.value = value;
23
+ }
24
+ equals(other) {
25
+ return this.value === other.value;
26
+ }
27
+ toString() {
28
+ return this.value;
29
+ }
30
+ }
31
+ //# sourceMappingURL=routine-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routine-name.js","sourceRoot":"","sources":["../../src/domain/routine-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,oBAAoB,GAAG,uBAAuB,CAAC;AACrD,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAEpC,MAAM,OAAO,WAAW;IACN,KAAK,CAAS;IAE9B,YAAmB,KAAa;QAC9B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,eAAe,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;gBAClE,YAAY,EACV,gGAAgG;aACnG,CAAC,CAAC;QACL,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,uBAAuB,EAAE,CAAC;YACjE,MAAM,IAAI,eAAe,CAAC,gCAAgC,KAAK,CAAC,MAAM,EAAE,EAAE;gBACxE,YAAY,EACV,0DAA0D;aAC7D,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,eAAe,CAAC,yBAAyB,KAAK,EAAE,EAAE;gBAC1D,YAAY,EACV,oHAAoH;aACvH,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAEM,MAAM,CAAC,KAAkB;QAC9B,OAAO,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,KAAK,CAAC;IACpC,CAAC;IAEM,QAAQ;QACb,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ import { type RoutineRunId, RoutineExecutionState } from "./routine-execution-state.js";
2
+ import { TriggerConfig } from "./trigger-config.js";
3
+ export interface MissedFireEvaluation {
4
+ firesToExecute: Date[];
5
+ skippedSchedules: Date[];
6
+ }
7
+ export declare class RoutineSchedule {
8
+ private readonly triggerConfigValue;
9
+ private executionStateValue;
10
+ private activeFiring;
11
+ constructor(triggerConfigValue: TriggerConfig | null, executionState?: RoutineExecutionState);
12
+ get triggerConfig(): TriggerConfig | null;
13
+ get executionState(): RoutineExecutionState;
14
+ evaluateMissedFires(now: Date): MissedFireEvaluation;
15
+ canFire(): boolean;
16
+ markFiring(runId: RoutineRunId, scheduledTime: Date, options?: {
17
+ isManual?: boolean;
18
+ }): void;
19
+ markCompleted(runId: RoutineRunId, completedAt?: Date): void;
20
+ markFailed(runId: RoutineRunId, failedAt?: Date): void;
21
+ markSkipped(scheduledTime: Date): void;
22
+ private requireActiveRun;
23
+ private advanceScheduleCursor;
24
+ }
@@ -0,0 +1,126 @@
1
+ import { ValidationError } from "../core/errors.js";
2
+ import { RoutineExecutionState, } from "./routine-execution-state.js";
3
+ export class RoutineSchedule {
4
+ triggerConfigValue;
5
+ executionStateValue;
6
+ activeFiring = null;
7
+ constructor(triggerConfigValue, executionState = RoutineExecutionState.create()) {
8
+ this.triggerConfigValue = triggerConfigValue;
9
+ this.executionStateValue = executionState;
10
+ }
11
+ get triggerConfig() {
12
+ return this.triggerConfigValue;
13
+ }
14
+ get executionState() {
15
+ return this.executionStateValue;
16
+ }
17
+ evaluateMissedFires(now) {
18
+ assertValidDate(now, "now");
19
+ if (this.triggerConfigValue === null) {
20
+ return emptyMissedFireEvaluation();
21
+ }
22
+ const missed = this.executionStateValue.lastScheduledAt === null
23
+ ? resolveInitialMissedFire(this.triggerConfigValue, now)
24
+ : this.triggerConfigValue.schedule.allBetween(this.executionStateValue.lastScheduledAt, now);
25
+ if (missed.length === 0) {
26
+ return emptyMissedFireEvaluation();
27
+ }
28
+ if (this.triggerConfigValue.missedPolicy === "skip") {
29
+ return {
30
+ firesToExecute: [],
31
+ skippedSchedules: missed,
32
+ };
33
+ }
34
+ const catchUpLimit = this.triggerConfigValue.catchUpLimit;
35
+ if (!catchUpLimit.isEffective() || missed.length <= catchUpLimit.value) {
36
+ return {
37
+ firesToExecute: missed,
38
+ skippedSchedules: [],
39
+ };
40
+ }
41
+ return {
42
+ firesToExecute: missed.slice(-catchUpLimit.value),
43
+ skippedSchedules: missed.slice(0, -catchUpLimit.value),
44
+ };
45
+ }
46
+ canFire() {
47
+ return this.activeFiring === null;
48
+ }
49
+ markFiring(runId, scheduledTime, options = {}) {
50
+ assertValidDate(scheduledTime, "scheduledTime");
51
+ if (!this.canFire()) {
52
+ throw new ValidationError("Routine is already executing.", {
53
+ recoveryHint: "Wait for the current run to finish before firing again.",
54
+ });
55
+ }
56
+ this.activeFiring = {
57
+ runId,
58
+ scheduledTime: new Date(scheduledTime.getTime()),
59
+ isManual: options.isManual ?? false,
60
+ };
61
+ }
62
+ markCompleted(runId, completedAt = new Date()) {
63
+ assertValidDate(completedAt, "completedAt");
64
+ const firing = this.requireActiveRun(runId);
65
+ this.executionStateValue = this.executionStateValue.with({
66
+ lastExecutedAt: completedAt,
67
+ lastStatus: "completed",
68
+ ...(firing.isManual ? {} : this.advanceScheduleCursor(firing.scheduledTime)),
69
+ });
70
+ this.activeFiring = null;
71
+ }
72
+ markFailed(runId, failedAt = new Date()) {
73
+ assertValidDate(failedAt, "failedAt");
74
+ const firing = this.requireActiveRun(runId);
75
+ this.executionStateValue = this.executionStateValue.with({
76
+ lastExecutedAt: failedAt,
77
+ lastStatus: "failed",
78
+ ...(firing.isManual ? {} : this.advanceScheduleCursor(firing.scheduledTime)),
79
+ });
80
+ this.activeFiring = null;
81
+ }
82
+ markSkipped(scheduledTime) {
83
+ assertValidDate(scheduledTime, "scheduledTime");
84
+ this.executionStateValue = this.executionStateValue.with({
85
+ ...this.advanceScheduleCursor(scheduledTime),
86
+ lastStatus: "skipped",
87
+ });
88
+ }
89
+ requireActiveRun(runId) {
90
+ if (this.activeFiring === null) {
91
+ throw new ValidationError("Routine is not executing.", {
92
+ recoveryHint: "Call markFiring before completing or failing a run.",
93
+ });
94
+ }
95
+ if (this.activeFiring.runId !== runId) {
96
+ throw new ValidationError("Routine run id does not match the active execution.", {
97
+ recoveryHint: "Pass the same runId returned by markFiring.",
98
+ });
99
+ }
100
+ return this.activeFiring;
101
+ }
102
+ advanceScheduleCursor(scheduledTime) {
103
+ return {
104
+ lastScheduledAt: new Date(scheduledTime.getTime()),
105
+ nextScheduledAt: this.triggerConfigValue?.schedule.nextAfter(scheduledTime) ?? null,
106
+ };
107
+ }
108
+ }
109
+ function emptyMissedFireEvaluation() {
110
+ return {
111
+ firesToExecute: [],
112
+ skippedSchedules: [],
113
+ };
114
+ }
115
+ function resolveInitialMissedFire(triggerConfig, now) {
116
+ const latest = triggerConfig.schedule.latestBefore(now);
117
+ return latest === null ? [] : [latest];
118
+ }
119
+ function assertValidDate(value, field) {
120
+ if (!(value instanceof Date) || Number.isNaN(value.getTime())) {
121
+ throw new ValidationError(`Invalid ${field}: ${String(value)}`, {
122
+ recoveryHint: `${field} must be a valid Date.`,
123
+ });
124
+ }
125
+ }
126
+ //# sourceMappingURL=routine-schedule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routine-schedule.js","sourceRoot":"","sources":["../../src/domain/routine-schedule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAEL,qBAAqB,GACtB,MAAM,8BAA8B,CAAC;AActC,MAAM,OAAO,eAAe;IAKP;IAJX,mBAAmB,CAAwB;IAC3C,YAAY,GAAwB,IAAI,CAAC;IAEjD,YACmB,kBAAwC,EACzD,cAAc,GAAG,qBAAqB,CAAC,MAAM,EAAE;QAD9B,uBAAkB,GAAlB,kBAAkB,CAAsB;QAGzD,IAAI,CAAC,mBAAmB,GAAG,cAAc,CAAC;IAC5C,CAAC;IAED,IAAW,aAAa;QACtB,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAED,IAAW,cAAc;QACvB,OAAO,IAAI,CAAC,mBAAmB,CAAC;IAClC,CAAC;IAEM,mBAAmB,CAAC,GAAS;QAClC,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAE5B,IAAI,IAAI,CAAC,kBAAkB,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,yBAAyB,EAAE,CAAC;QACrC,CAAC;QAED,MAAM,MAAM,GACV,IAAI,CAAC,mBAAmB,CAAC,eAAe,KAAK,IAAI;YAC/C,CAAC,CAAC,wBAAwB,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,CAAC;YACxD,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CACzC,IAAI,CAAC,mBAAmB,CAAC,eAAe,EACxC,GAAG,CACJ,CAAC;QAER,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,yBAAyB,EAAE,CAAC;QACrC,CAAC;QAED,IAAI,IAAI,CAAC,kBAAkB,CAAC,YAAY,KAAK,MAAM,EAAE,CAAC;YACpD,OAAO;gBACL,cAAc,EAAE,EAAE;gBAClB,gBAAgB,EAAE,MAAM;aACzB,CAAC;QACJ,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,YAAY,CAAC;QAC1D,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,MAAM,IAAI,YAAY,CAAC,KAAK,EAAE,CAAC;YACvE,OAAO;gBACL,cAAc,EAAE,MAAM;gBACtB,gBAAgB,EAAE,EAAE;aACrB,CAAC;QACJ,CAAC;QAED,OAAO;YACL,cAAc,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC;YACjD,gBAAgB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC;SACvD,CAAC;IACJ,CAAC;IAEM,OAAO;QACZ,OAAO,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC;IACpC,CAAC;IAEM,UAAU,CACf,KAAmB,EACnB,aAAmB,EACnB,UAAkC,EAAE;QAEpC,eAAe,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;QAEhD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACpB,MAAM,IAAI,eAAe,CAAC,+BAA+B,EAAE;gBACzD,YAAY,EAAE,yDAAyD;aACxE,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,YAAY,GAAG;YAClB,KAAK;YACL,aAAa,EAAE,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;YAChD,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,KAAK;SACpC,CAAC;IACJ,CAAC;IAEM,aAAa,CAAC,KAAmB,EAAE,WAAW,GAAG,IAAI,IAAI,EAAE;QAChE,eAAe,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QAC5C,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE5C,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;YACvD,cAAc,EAAE,WAAW;YAC3B,UAAU,EAAE,WAAW;YACvB,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;SAC7E,CAAC,CAAC;QACH,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAEM,UAAU,CAAC,KAAmB,EAAE,QAAQ,GAAG,IAAI,IAAI,EAAE;QAC1D,eAAe,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE5C,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;YACvD,cAAc,EAAE,QAAQ;YACxB,UAAU,EAAE,QAAQ;YACpB,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;SAC7E,CAAC,CAAC;QACH,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAEM,WAAW,CAAC,aAAmB;QACpC,eAAe,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;QAEhD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC;YACvD,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,CAAC;YAC5C,UAAU,EAAE,SAAS;SACtB,CAAC,CAAC;IACL,CAAC;IAEO,gBAAgB,CAAC,KAAmB;QAC1C,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/B,MAAM,IAAI,eAAe,CAAC,2BAA2B,EAAE;gBACrD,YAAY,EAAE,qDAAqD;aACpE,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;YACtC,MAAM,IAAI,eAAe,CAAC,qDAAqD,EAAE;gBAC/E,YAAY,EAAE,6CAA6C;aAC5D,CAAC,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAEO,qBAAqB,CAC3B,aAAmB;QAKnB,OAAO;YACL,eAAe,EAAE,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;YAClD,eAAe,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,IAAI;SACpF,CAAC;IACJ,CAAC;CACF;AAED,SAAS,yBAAyB;IAChC,OAAO;QACL,cAAc,EAAE,EAAE;QAClB,gBAAgB,EAAE,EAAE;KACrB,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAC/B,aAA4B,EAC5B,GAAS;IAET,MAAM,MAAM,GAAG,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,eAAe,CAAC,KAAW,EAAE,KAAa;IACjD,IAAI,CAAC,CAAC,KAAK,YAAY,IAAI,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,eAAe,CAAC,WAAW,KAAK,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;YAC9D,YAAY,EAAE,GAAG,KAAK,wBAAwB;SAC/C,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ export type MissedPolicy = "catch_up" | "skip";
2
+ export declare class CronExpression {
3
+ readonly value: string;
4
+ private readonly cron;
5
+ constructor(value: string);
6
+ nextAfter(from: Date): Date | null;
7
+ latestBefore(from: Date): Date | null;
8
+ allBetween(from: Date, to: Date): Date[];
9
+ toString(): string;
10
+ }
11
+ export declare class CatchUpLimit {
12
+ readonly value: number;
13
+ constructor(value: number);
14
+ isEffective(): boolean;
15
+ }
16
+ export declare class TriggerConfig {
17
+ readonly schedule: CronExpression;
18
+ readonly missedPolicy: MissedPolicy;
19
+ readonly catchUpLimit: CatchUpLimit;
20
+ constructor(options: {
21
+ schedule: CronExpression;
22
+ missedPolicy: MissedPolicy;
23
+ catchUpLimit: CatchUpLimit;
24
+ });
25
+ }
@@ -0,0 +1,86 @@
1
+ import { Cron } from "croner";
2
+ import { ValidationError } from "../core/errors.js";
3
+ export class CronExpression {
4
+ value;
5
+ cron;
6
+ constructor(value) {
7
+ if (typeof value !== "string" || value.trim().length === 0) {
8
+ throw new ValidationError(`Invalid cron expression: ${String(value)}`, {
9
+ recoveryHint: "Cron expressions must be non-empty strings in standard 5-field format.",
10
+ });
11
+ }
12
+ try {
13
+ this.cron = new Cron(value, {
14
+ paused: true,
15
+ mode: "5-part",
16
+ });
17
+ }
18
+ catch (error) {
19
+ throw new ValidationError(`Invalid cron expression: ${value}`, {
20
+ causeData: error,
21
+ recoveryHint: "Use a valid 5-field cron expression such as '*/15 * * * *'.",
22
+ });
23
+ }
24
+ this.value = value;
25
+ }
26
+ nextAfter(from) {
27
+ assertValidDate(from, "from");
28
+ return this.cron.nextRun(from);
29
+ }
30
+ latestBefore(from) {
31
+ assertValidDate(from, "from");
32
+ return this.cron.previousRuns(1, from)[0] ?? null;
33
+ }
34
+ allBetween(from, to) {
35
+ assertValidDate(from, "from");
36
+ assertValidDate(to, "to");
37
+ if (to.getTime() <= from.getTime()) {
38
+ return [];
39
+ }
40
+ const runs = [];
41
+ let cursor = from;
42
+ while (true) {
43
+ const next = this.cron.nextRun(cursor);
44
+ if (next === null || next.getTime() > to.getTime()) {
45
+ return runs;
46
+ }
47
+ runs.push(next);
48
+ cursor = next;
49
+ }
50
+ }
51
+ toString() {
52
+ return this.value;
53
+ }
54
+ }
55
+ export class CatchUpLimit {
56
+ value;
57
+ constructor(value) {
58
+ if (!Number.isInteger(value) || value <= 0) {
59
+ throw new ValidationError(`Invalid catch-up limit: ${value}`, {
60
+ recoveryHint: "catch_up_limit must be a positive integer.",
61
+ });
62
+ }
63
+ this.value = value;
64
+ }
65
+ isEffective() {
66
+ return this.value > 0;
67
+ }
68
+ }
69
+ export class TriggerConfig {
70
+ schedule;
71
+ missedPolicy;
72
+ catchUpLimit;
73
+ constructor(options) {
74
+ this.schedule = options.schedule;
75
+ this.missedPolicy = options.missedPolicy;
76
+ this.catchUpLimit = options.catchUpLimit;
77
+ }
78
+ }
79
+ function assertValidDate(value, field) {
80
+ if (!(value instanceof Date) || Number.isNaN(value.getTime())) {
81
+ throw new ValidationError(`Invalid ${field}: ${String(value)}`, {
82
+ recoveryHint: `${field} must be a valid Date.`,
83
+ });
84
+ }
85
+ }
86
+ //# sourceMappingURL=trigger-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trigger-config.js","sourceRoot":"","sources":["../../src/domain/trigger-config.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,8 @@ export interface WorkflowCapabilitySummary {
11
11
  export interface WorkflowLoadResult {
12
12
  workflow: WorkflowDefinition;
13
13
  capabilitySummary: WorkflowCapabilitySummary;
14
+ workflowPath: string;
15
+ workflowDigest: string;
14
16
  }
15
17
  export declare function loadWorkflow(rootPath: string, repo: WorkflowFileRepository, nestDepth?: NestDepth, vars?: Record<string, string>): Promise<WorkflowLoadResult>;
16
18
  export declare function computeWorkflowDigest(yamlContent: string): string;
@@ -2,7 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { dirname, isAbsolute, relative, resolve } from "node:path";
3
3
  import { ValidationError } from "../core/errors.js";
4
4
  import { NestDepth } from "./loop-execution.js";
5
- import { interpolateWorkflowVars, isWorkflowStep, parseWorkflowYaml, } from "./workflow-schema.js";
5
+ import { isCommandStep, interpolateWorkflowVars, isWorkflowStep, parseWorkflowYaml, } from "./workflow-schema.js";
6
6
  export async function loadWorkflow(rootPath, repo, nestDepth = new NestDepth(0), vars = {}) {
7
7
  const canonicalRootPath = resolve(rootPath);
8
8
  const context = {
@@ -22,12 +22,20 @@ export async function loadWorkflow(rootPath, repo, nestDepth = new NestDepth(0),
22
22
  recoveryHint: "Fix the workflow definition and try again.",
23
23
  });
24
24
  }
25
+ const rootFrame = context.cache.get(canonicalRootPath);
26
+ if (!rootFrame) {
27
+ throw new ValidationError(`Workflow file does not exist: ${canonicalRootPath}`, {
28
+ recoveryHint: "Provide a valid workflow YAML path.",
29
+ });
30
+ }
25
31
  return {
26
32
  workflow,
27
33
  capabilitySummary: {
28
34
  hasCommandRun: context.commandRunWorkflowPaths.size > 0,
29
35
  commandRunWorkflowPaths: [...context.commandRunWorkflowPaths].sort(),
30
36
  },
37
+ workflowPath: canonicalRootPath,
38
+ workflowDigest: rootFrame.digest,
31
39
  };
32
40
  }
33
41
  export function computeWorkflowDigest(yamlContent) {
@@ -103,7 +111,9 @@ function validateWorkflowGraph(workflowPath, workflow, errors) {
103
111
  }
104
112
  }
105
113
  function recordCapabilities(workflowPath, workflow, commandRunWorkflowPaths) {
106
- if (workflow.loop.exitConditions?.some((condition) => condition.type === "command")) {
114
+ const hasCommandRun = workflow.loop.exitConditions?.some((condition) => condition.type === "command") ||
115
+ workflow.steps.some((step) => isCommandStep(step));
116
+ if (hasCommandRun) {
107
117
  commandRunWorkflowPaths.add(workflowPath);
108
118
  }
109
119
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-loader.js","sourceRoot":"","sources":["../../src/domain/workflow-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"workflow-loader.js","sourceRoot":"","sources":["../../src/domain/workflow-loader.ts"],"names":[],"mappings":"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"}
@@ -39,11 +39,23 @@ export interface WorkflowStepDefinition {
39
39
  id: StepId;
40
40
  prompt?: never;
41
41
  workflow: string;
42
+ command?: never;
42
43
  backend?: never;
43
44
  role?: never;
44
45
  session?: SessionConfig;
45
46
  }
46
- export type StepDefinition = PromptStepDefinition | WorkflowStepDefinition;
47
+ export interface CommandStepDefinition {
48
+ id: StepId;
49
+ prompt?: never;
50
+ workflow?: never;
51
+ command: {
52
+ run: string;
53
+ };
54
+ backend?: never;
55
+ role?: never;
56
+ session?: SessionConfig;
57
+ }
58
+ export type StepDefinition = PromptStepDefinition | WorkflowStepDefinition | CommandStepDefinition;
47
59
  export interface WorkflowDefinition {
48
60
  name: string;
49
61
  description?: string;
@@ -111,6 +123,9 @@ export declare const workflowDefinitionSchema: z.ZodPipe<z.ZodObject<{
111
123
  id: z.ZodString;
112
124
  prompt: z.ZodOptional<z.ZodString>;
113
125
  workflow: z.ZodOptional<z.ZodString>;
126
+ command: z.ZodOptional<z.ZodObject<{
127
+ run: z.ZodString;
128
+ }, z.core.$strip>>;
114
129
  backend: z.ZodOptional<z.ZodEnum<{
115
130
  claude: "claude";
116
131
  codex: "codex";
@@ -144,6 +159,9 @@ export declare const workflowDefinitionSchema: z.ZodPipe<z.ZodObject<{
144
159
  id: string;
145
160
  prompt?: string | undefined;
146
161
  workflow?: string | undefined;
162
+ command?: {
163
+ run: string;
164
+ } | undefined;
147
165
  backend?: "claude" | "codex" | "gemini" | undefined;
148
166
  role?: string | undefined;
149
167
  session?: {
@@ -156,5 +174,6 @@ export declare const workflowDefinitionSchema: z.ZodPipe<z.ZodObject<{
156
174
  export declare function parseWorkflowYaml(source: string): WorkflowDefinition;
157
175
  export declare function validateWorkflowDefinition(input: unknown): WorkflowDefinition;
158
176
  export declare function isWorkflowStep(step: StepDefinition): step is WorkflowStepDefinition;
177
+ export declare function isCommandStep(step: StepDefinition): step is CommandStepDefinition;
159
178
  export declare function formatWorkflowSchemaIssues(error: z.ZodError): string;
160
179
  export declare function interpolateWorkflowVars(workflow: WorkflowDefinition, cliVars: Record<string, string>): WorkflowDefinition;