@osolmaz/pi-workflows 0.2.0 → 0.3.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 (133) hide show
  1. package/README.md +71 -5
  2. package/dist/builtins/monitor.workflow.d.ts +71 -0
  3. package/dist/builtins/monitor.workflow.js +234 -0
  4. package/dist/builtins/monitor.workflow.js.map +1 -0
  5. package/dist/controllers/conditions.d.ts +6 -0
  6. package/dist/controllers/conditions.js +68 -0
  7. package/dist/controllers/conditions.js.map +1 -0
  8. package/dist/controllers/definition.d.ts +6 -0
  9. package/dist/controllers/definition.js +45 -0
  10. package/dist/controllers/definition.js.map +1 -0
  11. package/dist/controllers/effects.d.ts +14 -0
  12. package/dist/controllers/effects.js +104 -0
  13. package/dist/controllers/effects.js.map +1 -0
  14. package/dist/controllers/errors.d.ts +12 -0
  15. package/dist/controllers/errors.js +25 -0
  16. package/dist/controllers/errors.js.map +1 -0
  17. package/dist/controllers/index.d.ts +13 -0
  18. package/dist/controllers/index.js +13 -0
  19. package/dist/controllers/index.js.map +1 -0
  20. package/dist/controllers/json.d.ts +5 -0
  21. package/dist/controllers/json.js +57 -0
  22. package/dist/controllers/json.js.map +1 -0
  23. package/dist/controllers/loader.d.ts +23 -0
  24. package/dist/controllers/loader.js +74 -0
  25. package/dist/controllers/loader.js.map +1 -0
  26. package/dist/controllers/manager.d.ts +58 -0
  27. package/dist/controllers/manager.js +399 -0
  28. package/dist/controllers/manager.js.map +1 -0
  29. package/dist/controllers/results.d.ts +5 -0
  30. package/dist/controllers/results.js +32 -0
  31. package/dist/controllers/results.js.map +1 -0
  32. package/dist/controllers/sqlite.d.ts +212 -0
  33. package/dist/controllers/sqlite.js +1009 -0
  34. package/dist/controllers/sqlite.js.map +1 -0
  35. package/dist/controllers/store.d.ts +112 -0
  36. package/dist/controllers/store.js +32 -0
  37. package/dist/controllers/store.js.map +1 -0
  38. package/dist/controllers/types.d.ts +159 -0
  39. package/dist/controllers/types.js +2 -0
  40. package/dist/controllers/types.js.map +1 -0
  41. package/dist/controllers/workflow-engine-scheduler.d.ts +25 -0
  42. package/dist/controllers/workflow-engine-scheduler.js +93 -0
  43. package/dist/controllers/workflow-engine-scheduler.js.map +1 -0
  44. package/dist/controllers/workflows.d.ts +27 -0
  45. package/dist/controllers/workflows.js +109 -0
  46. package/dist/controllers/workflows.js.map +1 -0
  47. package/dist/extension/controller-host.d.ts +47 -0
  48. package/dist/extension/controller-host.js +110 -0
  49. package/dist/extension/controller-host.js.map +1 -0
  50. package/dist/extension/executor.js +1 -1
  51. package/dist/extension/executor.js.map +1 -1
  52. package/dist/extension/index.d.ts +7 -0
  53. package/dist/extension/index.js +1053 -96
  54. package/dist/extension/index.js.map +1 -1
  55. package/dist/extension/recorder.d.ts +6 -0
  56. package/dist/extension/recorder.js +20 -8
  57. package/dist/extension/recorder.js.map +1 -1
  58. package/dist/extension/workflow-tool.d.ts +28 -0
  59. package/dist/extension/workflow-tool.js +33 -0
  60. package/dist/extension/workflow-tool.js.map +1 -0
  61. package/dist/host/processes.d.ts +24 -0
  62. package/dist/host/processes.js +114 -0
  63. package/dist/host/processes.js.map +1 -0
  64. package/dist/host/rpc-bridge.d.ts +9 -0
  65. package/dist/host/rpc-bridge.js +39 -0
  66. package/dist/host/rpc-bridge.js.map +1 -0
  67. package/dist/host/rpc-executor.d.ts +38 -0
  68. package/dist/host/rpc-executor.js +254 -0
  69. package/dist/host/rpc-executor.js.map +1 -0
  70. package/dist/host/runner.d.ts +49 -0
  71. package/dist/host/runner.js +350 -0
  72. package/dist/host/runner.js.map +1 -0
  73. package/dist/viewer/cli.d.ts +7 -3
  74. package/dist/viewer/cli.js +150 -19
  75. package/dist/viewer/cli.js.map +1 -1
  76. package/dist/workflows/engine.d.ts +36 -0
  77. package/dist/workflows/engine.js +244 -14
  78. package/dist/workflows/engine.js.map +1 -1
  79. package/dist/workflows/errors.d.ts +23 -0
  80. package/dist/workflows/errors.js +38 -0
  81. package/dist/workflows/errors.js.map +1 -1
  82. package/dist/workflows/graph.js +0 -5
  83. package/dist/workflows/graph.js.map +1 -1
  84. package/dist/workflows/loader.d.ts +5 -3
  85. package/dist/workflows/loader.js +10 -1
  86. package/dist/workflows/loader.js.map +1 -1
  87. package/dist/workflows/schema.js +1 -1
  88. package/dist/workflows/schema.js.map +1 -1
  89. package/dist/workflows/store.d.ts +50 -6
  90. package/dist/workflows/store.js +446 -51
  91. package/dist/workflows/store.js.map +1 -1
  92. package/dist/workflows/types.d.ts +10 -0
  93. package/docs/CONTROLLERS.md +215 -0
  94. package/docs/development.md +12 -9
  95. package/docs/plans/2026-08-04-controller-runtime-plan.md +169 -0
  96. package/docs/plans/2026-08-05-always-on-workflows-plan.md +125 -0
  97. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +184 -0
  98. package/docs/run-bundles.md +66 -27
  99. package/docs/workflows.md +131 -11
  100. package/examples/controllers/pull-request.controller.ts +215 -0
  101. package/package.json +10 -2
  102. package/src/builtins/monitor.workflow.ts +278 -0
  103. package/src/controllers/conditions.ts +110 -0
  104. package/src/controllers/definition.ts +65 -0
  105. package/src/controllers/effects.ts +123 -0
  106. package/src/controllers/errors.ts +27 -0
  107. package/src/controllers/index.ts +90 -0
  108. package/src/controllers/json.ts +62 -0
  109. package/src/controllers/loader.ts +104 -0
  110. package/src/controllers/manager.ts +533 -0
  111. package/src/controllers/results.ts +46 -0
  112. package/src/controllers/sqlite.ts +1427 -0
  113. package/src/controllers/store.ts +160 -0
  114. package/src/controllers/types.ts +183 -0
  115. package/src/controllers/workflow-engine-scheduler.ts +145 -0
  116. package/src/controllers/workflows.ts +152 -0
  117. package/src/extension/controller-host.ts +163 -0
  118. package/src/extension/executor.ts +1 -1
  119. package/src/extension/index.ts +1243 -117
  120. package/src/extension/recorder.ts +65 -36
  121. package/src/extension/workflow-tool.ts +59 -0
  122. package/src/host/processes.ts +119 -0
  123. package/src/host/rpc-bridge.ts +44 -0
  124. package/src/host/rpc-executor.ts +299 -0
  125. package/src/host/runner.ts +406 -0
  126. package/src/viewer/cli.ts +167 -21
  127. package/src/workflows/engine.ts +327 -13
  128. package/src/workflows/errors.ts +45 -0
  129. package/src/workflows/graph.ts +0 -5
  130. package/src/workflows/loader.ts +13 -3
  131. package/src/workflows/schema.ts +1 -1
  132. package/src/workflows/store.ts +555 -46
  133. package/src/workflows/types.ts +10 -0
@@ -0,0 +1,104 @@
1
+ import { jsonFingerprint } from "./json.js";
2
+ export class ControllerEffectService {
3
+ store;
4
+ resource;
5
+ signal;
6
+ used = false;
7
+ constructor(store, resource, signal) {
8
+ this.store = store;
9
+ this.resource = resource;
10
+ this.signal = signal;
11
+ }
12
+ async ensure(definition) {
13
+ if (this.used) {
14
+ throw new Error("A reconciliation pass may ensure only one external effect");
15
+ }
16
+ this.used = true;
17
+ const requestFingerprint = jsonFingerprint(definition.request);
18
+ const reservation = this.store.reserveEffect({
19
+ key: definition.key,
20
+ resourceUid: this.resource.metadata.uid,
21
+ generation: this.resource.metadata.generation,
22
+ kind: definition.kind,
23
+ requestFingerprint,
24
+ });
25
+ if (reservation.record.state === "applied" || reservation.record.state === "rejected") {
26
+ return reservation.record;
27
+ }
28
+ if (!reservation.created) {
29
+ const observed = await this.observe(definition);
30
+ const recovered = this.applyObservation(definition.key, observed);
31
+ if (recovered !== undefined) {
32
+ return recovered;
33
+ }
34
+ }
35
+ return await this.apply(definition);
36
+ }
37
+ async observe(definition) {
38
+ try {
39
+ return await definition.observe(this.signal);
40
+ }
41
+ catch (error) {
42
+ this.recordEvent("effect_observe_failed", definition.key, {
43
+ error: boundedError(error),
44
+ });
45
+ throw error;
46
+ }
47
+ }
48
+ applyObservation(key, observation) {
49
+ if (observation.state === "not_applied") {
50
+ return undefined;
51
+ }
52
+ const record = this.store.updateEffect({
53
+ resourceUid: this.resource.metadata.uid,
54
+ key,
55
+ state: observation.state === "applied" ? "applied" : "indeterminate",
56
+ ...("externalRef" in observation && observation.externalRef !== undefined
57
+ ? { externalRef: observation.externalRef }
58
+ : {}),
59
+ });
60
+ this.recordEvent(observation.state === "applied" ? "effect_recovered" : "effect_indeterminate", key);
61
+ return record;
62
+ }
63
+ async apply(definition) {
64
+ let result;
65
+ try {
66
+ result = await definition.apply(this.signal);
67
+ }
68
+ catch (error) {
69
+ const message = boundedError(error);
70
+ const record = this.store.updateEffect({
71
+ resourceUid: this.resource.metadata.uid,
72
+ key: definition.key,
73
+ state: "indeterminate",
74
+ error: message,
75
+ });
76
+ this.recordEvent("effect_indeterminate", definition.key, { error: message });
77
+ return record;
78
+ }
79
+ const record = this.store.updateEffect({
80
+ resourceUid: this.resource.metadata.uid,
81
+ key: definition.key,
82
+ state: result.state,
83
+ ...(result.state === "applied" && result.externalRef !== undefined
84
+ ? { externalRef: result.externalRef }
85
+ : {}),
86
+ ...(result.state !== "applied" && result.error !== undefined ? { error: result.error } : {}),
87
+ });
88
+ this.recordEvent(`effect_${result.state}`, definition.key);
89
+ return record;
90
+ }
91
+ recordEvent(type, effectKey, extra = {}) {
92
+ this.store.recordEvent({
93
+ controller: this.resource.metadata.controller,
94
+ key: this.resource.metadata.key,
95
+ type,
96
+ payload: { effectKey, ...extra },
97
+ });
98
+ }
99
+ }
100
+ function boundedError(error) {
101
+ const message = error instanceof Error ? error.message : String(error);
102
+ return message.length <= 8_192 ? message : `${message.slice(0, 8_192)}…`;
103
+ }
104
+ //# sourceMappingURL=effects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"effects.js","sourceRoot":"","sources":["../../src/controllers/effects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export declare class ResourceConflictError extends Error {
2
+ constructor(controller: string, key: string);
3
+ }
4
+ export declare class ResourceNotFoundError extends Error {
5
+ constructor(controller: string, key: string);
6
+ }
7
+ export declare class EffectRequestConflictError extends Error {
8
+ constructor(key: string);
9
+ }
10
+ export declare class WorkflowRequestConflictError extends Error {
11
+ constructor(key: string);
12
+ }
@@ -0,0 +1,25 @@
1
+ export class ResourceConflictError extends Error {
2
+ constructor(controller, key) {
3
+ super(`Controller resource ${controller}/${key} changed during reconciliation`);
4
+ this.name = "ResourceConflictError";
5
+ }
6
+ }
7
+ export class ResourceNotFoundError extends Error {
8
+ constructor(controller, key) {
9
+ super(`Controller resource not found: ${controller}/${key}`);
10
+ this.name = "ResourceNotFoundError";
11
+ }
12
+ }
13
+ export class EffectRequestConflictError extends Error {
14
+ constructor(key) {
15
+ super(`Effect key ${JSON.stringify(key)} was reused with a different request`);
16
+ this.name = "EffectRequestConflictError";
17
+ }
18
+ }
19
+ export class WorkflowRequestConflictError extends Error {
20
+ constructor(key) {
21
+ super(`Workflow request key ${JSON.stringify(key)} was reused with different input`);
22
+ this.name = "WorkflowRequestConflictError";
23
+ }
24
+ }
25
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/controllers/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,UAAkB,EAAE,GAAW;QACzC,KAAK,CAAC,uBAAuB,UAAU,IAAI,GAAG,gCAAgC,CAAC,CAAC;QAChF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAC9C,YAAY,UAAkB,EAAE,GAAW;QACzC,KAAK,CAAC,kCAAkC,UAAU,IAAI,GAAG,EAAE,CAAC,CAAC;QAC7D,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,KAAK;IACnD,YAAY,GAAW;QACrB,KAAK,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QAC/E,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrD,YAAY,GAAW;QACrB,KAAK,CAAC,wBAAwB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;QACrF,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;IAC7C,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ export { assertValidControllerDefinition, defineController, isControllerDefinition, } from "./definition.js";
2
+ export { applyStatusPatch, conditionFalse, conditionTrue, conditionUnknown, mergeConditions, } from "./conditions.js";
3
+ export { EffectRequestConflictError, ResourceConflictError, ResourceNotFoundError, WorkflowRequestConflictError, } from "./errors.js";
4
+ export { ControllerEffectService } from "./effects.js";
5
+ export { canonicalJson, jsonFingerprint } from "./json.js";
6
+ export { ControllerManager, type ControllerManagerOptions } from "./manager.js";
7
+ export { createResultHelpers, requeue, requeueAfter, settled } from "./results.js";
8
+ export { SqliteControllerStore, type RunEventRecord, type WorkflowRunQueueRecord, } from "./sqlite.js";
9
+ export { CONTROLLER_STORE_SCHEMA, controllerProjectScope, controllerStoreBaseDir, controllerStorePath, projectControllerStoreBaseDir, projectControllerStorePath, type ControllerStore, type EffectReservation, type QueueItem, type QueueRequeueOptions, type WorkflowRecordUpdate, type WorkflowReservation, } from "./store.js";
10
+ export { controllerFileStem, controllerSearchDirs, discoverControllers, loadControllerFile, loadDiscoveredControllers, type DiscoveredController, } from "./loader.js";
11
+ export { WorkflowEngineScheduler, type ResolvedChildWorkflow, type WorkflowEngineSchedulerOptions, } from "./workflow-engine-scheduler.js";
12
+ export { ControllerWorkflowCoordinator, type ControllerWorkflowScheduler, type WorkflowSchedulerRequest, type WorkflowSchedulerResult, } from "./workflows.js";
13
+ export type { AnyControllerDefinition, ChildWorkflowRecord, ChildWorkflowReference, ChildWorkflowRequest, ChildWorkflowState, ControllerCondition, ControllerConditionInput, ControllerConditionStatus, ControllerDefinition, ControllerEffects, ControllerEvent, ControllerQueueClaim, ControllerResource, ControllerResourceRef, ControllerResourceStatus, ControllerStatusPatch, ControllerWorkflows, EffectApplication, EffectDefinition, EffectObservation, EffectRecord, EffectState, JsonObject, JsonPrimitive, JsonValue, MaybePromise, ReconcileContext, ReconcileResult, } from "./types.js";
@@ -0,0 +1,13 @@
1
+ export { assertValidControllerDefinition, defineController, isControllerDefinition, } from "./definition.js";
2
+ export { applyStatusPatch, conditionFalse, conditionTrue, conditionUnknown, mergeConditions, } from "./conditions.js";
3
+ export { EffectRequestConflictError, ResourceConflictError, ResourceNotFoundError, WorkflowRequestConflictError, } from "./errors.js";
4
+ export { ControllerEffectService } from "./effects.js";
5
+ export { canonicalJson, jsonFingerprint } from "./json.js";
6
+ export { ControllerManager } from "./manager.js";
7
+ export { createResultHelpers, requeue, requeueAfter, settled } from "./results.js";
8
+ export { SqliteControllerStore, } from "./sqlite.js";
9
+ export { CONTROLLER_STORE_SCHEMA, controllerProjectScope, controllerStoreBaseDir, controllerStorePath, projectControllerStoreBaseDir, projectControllerStorePath, } from "./store.js";
10
+ export { controllerFileStem, controllerSearchDirs, discoverControllers, loadControllerFile, loadDiscoveredControllers, } from "./loader.js";
11
+ export { WorkflowEngineScheduler, } from "./workflow-engine-scheduler.js";
12
+ export { ControllerWorkflowCoordinator, } from "./workflows.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/controllers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,+BAA+B,EAC/B,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAiC,MAAM,cAAc,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnF,OAAO,EACL,qBAAqB,GAGtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,mBAAmB,EACnB,6BAA6B,EAC7B,0BAA0B,GAO3B,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,GAE1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,uBAAuB,GAGxB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,6BAA6B,GAI9B,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { JsonValue } from "./types.js";
2
+ export declare function assertJsonValue(value: unknown, description: string): asserts value is JsonValue;
3
+ export declare function canonicalJson(value: unknown, description?: string): string;
4
+ export declare function jsonFingerprint(value: unknown): string;
5
+ export declare function parseStoredJson<T>(value: string, description: string): T;
@@ -0,0 +1,57 @@
1
+ import { createHash } from "node:crypto";
2
+ export function assertJsonValue(value, description) {
3
+ normalizeJson(value, description, new Set());
4
+ }
5
+ export function canonicalJson(value, description = "value") {
6
+ return JSON.stringify(normalizeJson(value, description, new Set()));
7
+ }
8
+ export function jsonFingerprint(value) {
9
+ return createHash("sha256").update(canonicalJson(value)).digest("hex");
10
+ }
11
+ export function parseStoredJson(value, description) {
12
+ let parsed;
13
+ try {
14
+ parsed = JSON.parse(value);
15
+ }
16
+ catch (error) {
17
+ throw new Error(`${description} contains invalid JSON: ${error instanceof Error ? error.message : String(error)}`);
18
+ }
19
+ assertJsonValue(parsed, description);
20
+ return parsed;
21
+ }
22
+ function normalizeJson(value, path, seen) {
23
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
24
+ return value;
25
+ }
26
+ if (typeof value === "number") {
27
+ if (!Number.isFinite(value)) {
28
+ throw new Error(`${path} contains a non-finite number`);
29
+ }
30
+ return value;
31
+ }
32
+ if (typeof value !== "object") {
33
+ throw new Error(`${path} is not JSON-serializable`);
34
+ }
35
+ if (seen.has(value)) {
36
+ throw new Error(`${path} contains a cycle`);
37
+ }
38
+ seen.add(value);
39
+ try {
40
+ if (Array.isArray(value)) {
41
+ return value.map((item, index) => normalizeJson(item, `${path}[${index}]`, seen));
42
+ }
43
+ const prototype = Object.getPrototypeOf(value);
44
+ if (prototype !== Object.prototype && prototype !== null) {
45
+ throw new Error(`${path} must contain only plain objects and arrays`);
46
+ }
47
+ const result = {};
48
+ for (const key of Object.keys(value).sort()) {
49
+ result[key] = normalizeJson(value[key], `${path}.${key}`, seen);
50
+ }
51
+ return result;
52
+ }
53
+ finally {
54
+ seen.delete(value);
55
+ }
56
+ }
57
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/controllers/json.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { AnyControllerDefinition } from "./types.js";
2
+ export type DiscoveredController = {
3
+ name: string;
4
+ path: string;
5
+ source: "project" | "global";
6
+ };
7
+ export declare function controllerSearchDirs(options: {
8
+ cwd: string;
9
+ homeDir?: string;
10
+ }): {
11
+ dir: string;
12
+ source: DiscoveredController["source"];
13
+ }[];
14
+ export declare function controllerFileStem(filePath: string): string;
15
+ export declare function loadControllerFile(filePath: string): Promise<AnyControllerDefinition>;
16
+ export declare function discoverControllers(options: {
17
+ cwd: string;
18
+ homeDir?: string;
19
+ }): Promise<DiscoveredController[]>;
20
+ export declare function loadDiscoveredControllers(options: {
21
+ cwd: string;
22
+ homeDir?: string;
23
+ }): Promise<AnyControllerDefinition[]>;
@@ -0,0 +1,74 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+ import { createJiti } from "jiti";
6
+ import { isControllerDefinition } from "./definition.js";
7
+ const CONTROLLER_FILE_SUFFIXES = [
8
+ ".controller.ts",
9
+ ".controller.js",
10
+ ".controller.mts",
11
+ ".controller.mjs",
12
+ ];
13
+ export function controllerSearchDirs(options) {
14
+ const homeDir = options.homeDir ?? os.homedir();
15
+ return [
16
+ { dir: path.join(options.cwd, ".pi", "controllers"), source: "project" },
17
+ { dir: path.join(homeDir, ".pi", "agent", "controllers"), source: "global" },
18
+ ];
19
+ }
20
+ export function controllerFileStem(filePath) {
21
+ const base = path.basename(filePath);
22
+ const suffix = CONTROLLER_FILE_SUFFIXES.find((candidate) => base.endsWith(candidate));
23
+ return suffix === undefined ? base : base.slice(0, -suffix.length);
24
+ }
25
+ const CONTROLLER_ENTRY = path.join(path.dirname(fileURLToPath(import.meta.url)), "index");
26
+ const WORKFLOW_ENTRY = path.join(path.dirname(fileURLToPath(import.meta.url)), "../workflows/index");
27
+ export async function loadControllerFile(filePath) {
28
+ const absolutePath = path.resolve(filePath);
29
+ const jiti = createJiti(pathToFileURL(absolutePath).href, {
30
+ interopDefault: true,
31
+ moduleCache: false,
32
+ alias: {
33
+ "@osolmaz/pi-workflows/controllers": CONTROLLER_ENTRY,
34
+ "@osolmaz/pi-workflows": WORKFLOW_ENTRY,
35
+ },
36
+ });
37
+ const loaded = (await jiti.import(absolutePath, { default: true }));
38
+ if (!isControllerDefinition(loaded)) {
39
+ throw new Error(`Controller module must default-export defineController(...): ${absolutePath}`);
40
+ }
41
+ return loaded;
42
+ }
43
+ export async function discoverControllers(options) {
44
+ const discovered = [];
45
+ const seen = new Set();
46
+ for (const { dir, source } of controllerSearchDirs(options)) {
47
+ for (const filePath of await listControllerFiles(dir)) {
48
+ const name = controllerFileStem(filePath);
49
+ if (seen.has(name)) {
50
+ continue;
51
+ }
52
+ seen.add(name);
53
+ discovered.push({ name, path: filePath, source });
54
+ }
55
+ }
56
+ return discovered;
57
+ }
58
+ export async function loadDiscoveredControllers(options) {
59
+ return await Promise.all((await discoverControllers(options)).map(async (entry) => await loadControllerFile(entry.path)));
60
+ }
61
+ async function listControllerFiles(dir) {
62
+ let entries;
63
+ try {
64
+ entries = await fs.readdir(dir, { withFileTypes: true });
65
+ }
66
+ catch {
67
+ return [];
68
+ }
69
+ return entries
70
+ .filter((entry) => entry.isFile() && CONTROLLER_FILE_SUFFIXES.some((suffix) => entry.name.endsWith(suffix)))
71
+ .map((entry) => path.join(dir, entry.name))
72
+ .sort();
73
+ }
74
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/controllers/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ import type { ControllerStore } from "./store.js";
2
+ import type { AnyControllerDefinition, ControllerDefinition, ControllerResource, ControllerResourceRef } from "./types.js";
3
+ import { ControllerWorkflowCoordinator, type ControllerWorkflowScheduler } from "./workflows.js";
4
+ export type ControllerManagerOptions = {
5
+ store: ControllerStore;
6
+ controllers: AnyControllerDefinition[];
7
+ workflowScheduler?: ControllerWorkflowScheduler;
8
+ maxConcurrent?: number;
9
+ controllerConcurrency?: Record<string, number>;
10
+ defaultTimeoutMs?: number;
11
+ leaseMs?: number;
12
+ pollIntervalMs?: number;
13
+ baseBackoffMs?: number;
14
+ maxBackoffMs?: number;
15
+ jitterRatio?: number;
16
+ now?: () => Date;
17
+ random?: () => number;
18
+ };
19
+ export declare class ControllerManager {
20
+ readonly store: ControllerStore;
21
+ private readonly definitions;
22
+ private readonly workflowCoordinator;
23
+ private readonly maxConcurrent;
24
+ private readonly controllerConcurrency;
25
+ private readonly defaultTimeoutMs;
26
+ private readonly leaseMs;
27
+ private readonly pollIntervalMs;
28
+ private readonly baseBackoffMs;
29
+ private readonly maxBackoffMs;
30
+ private readonly jitterRatio;
31
+ private readonly now;
32
+ private readonly random;
33
+ private readonly activeByController;
34
+ private readonly activeReconciles;
35
+ private runAbort;
36
+ private workerTasks;
37
+ constructor(options: ControllerManagerOptions);
38
+ putResource<TSpec, TStatus>(definition: ControllerDefinition<TSpec, TStatus>, key: string, spec: TSpec): ControllerResource<TSpec, TStatus>;
39
+ putResourceByName(controller: string, key: string, spec: unknown): ControllerResource;
40
+ requestDeletion(ref: ControllerResourceRef): ControllerResource;
41
+ enqueue(ref: ControllerResourceRef, afterMs?: number): void;
42
+ start(): void;
43
+ stop(): Promise<void>;
44
+ runOne(): Promise<boolean>;
45
+ runUntilIdle(maxReconciles?: number): Promise<number>;
46
+ get workflowRequests(): ControllerWorkflowCoordinator;
47
+ private workerLoop;
48
+ private claimNext;
49
+ private eligibleControllers;
50
+ private processClaim;
51
+ private reconcileClaim;
52
+ private callReconciler;
53
+ private finishSuccessfulClaim;
54
+ private finishFailedClaim;
55
+ private backoffMs;
56
+ private readyQueueExists;
57
+ private recordEvent;
58
+ }