@bluelibs/runner-dev 5.1.0 → 6.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 (154) hide show
  1. package/AI.md +80 -6
  2. package/README.md +216 -22
  3. package/dist/cli/generators/scaffold/templates/package.json.d.ts +2 -2
  4. package/dist/cli/generators/scaffold/templates/package.json.js +2 -2
  5. package/dist/cli/generators/scaffold.js +1 -135
  6. package/dist/cli/generators/scaffold.js.map +1 -1
  7. package/dist/cli/generators/templates.js +2 -1
  8. package/dist/cli/generators/templates.js.map +1 -1
  9. package/dist/generated/resolvers-types.d.ts +545 -112
  10. package/dist/index.d.ts +39 -39
  11. package/dist/resources/cli.config.resource.d.ts +1 -1
  12. package/dist/resources/cli.config.resource.js +2 -2
  13. package/dist/resources/cli.config.resource.js.map +1 -1
  14. package/dist/resources/coverage.resource.d.ts +2 -2
  15. package/dist/resources/coverage.resource.js +3 -3
  16. package/dist/resources/coverage.resource.js.map +1 -1
  17. package/dist/resources/dev.resource.d.ts +1 -1
  18. package/dist/resources/dev.resource.js +2 -2
  19. package/dist/resources/dev.resource.js.map +1 -1
  20. package/dist/resources/docs.generator.resource.d.ts +4 -3
  21. package/dist/resources/docs.generator.resource.js +2 -2
  22. package/dist/resources/docs.generator.resource.js.map +1 -1
  23. package/dist/resources/graphql-accumulator.resource.d.ts +2 -2
  24. package/dist/resources/graphql-accumulator.resource.js +7 -3
  25. package/dist/resources/graphql-accumulator.resource.js.map +1 -1
  26. package/dist/resources/graphql.cli.resource.d.ts +1 -1
  27. package/dist/resources/graphql.cli.resource.js +2 -2
  28. package/dist/resources/graphql.cli.resource.js.map +1 -1
  29. package/dist/resources/graphql.query.cli.task.d.ts +14 -16
  30. package/dist/resources/graphql.query.cli.task.js +3 -3
  31. package/dist/resources/graphql.query.cli.task.js.map +1 -1
  32. package/dist/resources/graphql.query.task.d.ts +18 -18
  33. package/dist/resources/graphql.query.task.js +4 -4
  34. package/dist/resources/graphql.query.task.js.map +1 -1
  35. package/dist/resources/http.tag.d.ts +1 -1
  36. package/dist/resources/http.tag.js +2 -2
  37. package/dist/resources/http.tag.js.map +1 -1
  38. package/dist/resources/introspector.cli.resource.d.ts +2 -2
  39. package/dist/resources/introspector.cli.resource.js +37 -3
  40. package/dist/resources/introspector.cli.resource.js.map +1 -1
  41. package/dist/resources/introspector.resource.d.ts +3 -2
  42. package/dist/resources/introspector.resource.js +6 -6
  43. package/dist/resources/introspector.resource.js.map +1 -1
  44. package/dist/resources/live.resource.d.ts +7 -6
  45. package/dist/resources/live.resource.js +64 -25
  46. package/dist/resources/live.resource.js.map +1 -1
  47. package/dist/resources/models/Introspector.d.ts +59 -15
  48. package/dist/resources/models/Introspector.js +467 -137
  49. package/dist/resources/models/Introspector.js.map +1 -1
  50. package/dist/resources/models/durable.runtime.d.ts +1 -1
  51. package/dist/resources/models/durable.runtime.js +53 -2
  52. package/dist/resources/models/durable.runtime.js.map +1 -1
  53. package/dist/resources/models/durable.tools.d.ts +1 -1
  54. package/dist/resources/models/durable.tools.js +6 -3
  55. package/dist/resources/models/durable.tools.js.map +1 -1
  56. package/dist/resources/models/initializeFromStore.js +126 -19
  57. package/dist/resources/models/initializeFromStore.js.map +1 -1
  58. package/dist/resources/models/initializeFromStore.utils.d.ts +12 -7
  59. package/dist/resources/models/initializeFromStore.utils.js +319 -23
  60. package/dist/resources/models/initializeFromStore.utils.js.map +1 -1
  61. package/dist/resources/models/introspector.tools.js +18 -6
  62. package/dist/resources/models/introspector.tools.js.map +1 -1
  63. package/dist/resources/routeHandlers/createLiveStreamHandler.d.ts +16 -0
  64. package/dist/resources/routeHandlers/createLiveStreamHandler.js +127 -0
  65. package/dist/resources/routeHandlers/createLiveStreamHandler.js.map +1 -0
  66. package/dist/resources/routeHandlers/getDocsData.d.ts +4 -0
  67. package/dist/resources/routeHandlers/getDocsData.js +28 -0
  68. package/dist/resources/routeHandlers/getDocsData.js.map +1 -1
  69. package/dist/resources/routeHandlers/registerHttpRoutes.hook.d.ts +26 -23
  70. package/dist/resources/routeHandlers/registerHttpRoutes.hook.js +10 -9
  71. package/dist/resources/routeHandlers/registerHttpRoutes.hook.js.map +1 -1
  72. package/dist/resources/routeHandlers/requestCorrelation.d.ts +11 -0
  73. package/dist/resources/routeHandlers/requestCorrelation.js +29 -0
  74. package/dist/resources/routeHandlers/requestCorrelation.js.map +1 -0
  75. package/dist/resources/server.resource.d.ts +20 -20
  76. package/dist/resources/server.resource.js +17 -5
  77. package/dist/resources/server.resource.js.map +1 -1
  78. package/dist/resources/swap.cli.resource.d.ts +4 -4
  79. package/dist/resources/swap.cli.resource.js +2 -2
  80. package/dist/resources/swap.cli.resource.js.map +1 -1
  81. package/dist/resources/swap.resource.d.ts +7 -6
  82. package/dist/resources/swap.resource.js +188 -38
  83. package/dist/resources/swap.resource.js.map +1 -1
  84. package/dist/resources/swap.tools.d.ts +3 -2
  85. package/dist/resources/swap.tools.js +27 -27
  86. package/dist/resources/swap.tools.js.map +1 -1
  87. package/dist/resources/telemetry.resource.d.ts +1 -1
  88. package/dist/resources/telemetry.resource.js +46 -43
  89. package/dist/resources/telemetry.resource.js.map +1 -1
  90. package/dist/runner-compat.d.ts +85 -0
  91. package/dist/runner-compat.js +178 -0
  92. package/dist/runner-compat.js.map +1 -0
  93. package/dist/runner-node-compat.d.ts +2 -0
  94. package/dist/runner-node-compat.js +28 -0
  95. package/dist/runner-node-compat.js.map +1 -0
  96. package/dist/schema/index.js +8 -8
  97. package/dist/schema/index.js.map +1 -1
  98. package/dist/schema/model.d.ts +100 -20
  99. package/dist/schema/model.js.map +1 -1
  100. package/dist/schema/query.js +25 -1
  101. package/dist/schema/query.js.map +1 -1
  102. package/dist/schema/types/AllType.js +13 -2
  103. package/dist/schema/types/AllType.js.map +1 -1
  104. package/dist/schema/types/BaseElementCommon.js +10 -0
  105. package/dist/schema/types/BaseElementCommon.js.map +1 -1
  106. package/dist/schema/types/ErrorType.js +1 -1
  107. package/dist/schema/types/ErrorType.js.map +1 -1
  108. package/dist/schema/types/EventType.js +19 -2
  109. package/dist/schema/types/EventType.js.map +1 -1
  110. package/dist/schema/types/InterceptorOwnersType.d.ts +2 -0
  111. package/dist/schema/types/InterceptorOwnersType.js +63 -0
  112. package/dist/schema/types/InterceptorOwnersType.js.map +1 -0
  113. package/dist/schema/types/LaneSummaryTypes.d.ts +3 -0
  114. package/dist/schema/types/LaneSummaryTypes.js +19 -0
  115. package/dist/schema/types/LaneSummaryTypes.js.map +1 -0
  116. package/dist/schema/types/LiveType.js +81 -76
  117. package/dist/schema/types/LiveType.js.map +1 -1
  118. package/dist/schema/types/ResourceType.js +101 -15
  119. package/dist/schema/types/ResourceType.js.map +1 -1
  120. package/dist/schema/types/RunOptionsType.d.ts +2 -0
  121. package/dist/schema/types/RunOptionsType.js +107 -0
  122. package/dist/schema/types/RunOptionsType.js.map +1 -0
  123. package/dist/schema/types/TagType.js +35 -4
  124. package/dist/schema/types/TagType.js.map +1 -1
  125. package/dist/schema/types/TaskType.js +20 -0
  126. package/dist/schema/types/TaskType.js.map +1 -1
  127. package/dist/schema/types/index.d.ts +4 -2
  128. package/dist/schema/types/index.js +10 -7
  129. package/dist/schema/types/index.js.map +1 -1
  130. package/dist/schema/types/middleware/common.d.ts +3 -2
  131. package/dist/schema/types/middleware/common.js +19 -13
  132. package/dist/schema/types/middleware/common.js.map +1 -1
  133. package/dist/ui/.vite/manifest.json +2 -2
  134. package/dist/ui/assets/docs-Btkv97Ls.js +302 -0
  135. package/dist/ui/assets/docs-Btkv97Ls.js.map +1 -0
  136. package/dist/ui/assets/docs-CipvKUxZ.css +1 -0
  137. package/dist/utils/healthCollectors.d.ts +37 -0
  138. package/dist/utils/healthCollectors.js +147 -0
  139. package/dist/utils/healthCollectors.js.map +1 -0
  140. package/dist/utils/lane-resources.d.ts +55 -0
  141. package/dist/utils/lane-resources.js +143 -0
  142. package/dist/utils/lane-resources.js.map +1 -0
  143. package/dist/utils/zod.js +36 -3
  144. package/dist/utils/zod.js.map +1 -1
  145. package/dist/version.d.ts +1 -1
  146. package/dist/version.js +1 -1
  147. package/package.json +4 -6
  148. package/readmes/runner-AI.md +740 -0
  149. package/readmes/runner-durable-workflows.md +2247 -0
  150. package/readmes/runner-full-guide.md +5869 -0
  151. package/readmes/runner-remote-lanes.md +909 -0
  152. package/dist/ui/assets/docs-B_-zFz4-.css +0 -1
  153. package/dist/ui/assets/docs-Be-GHfZi.js +0 -353
  154. package/dist/ui/assets/docs-Be-GHfZi.js.map +0 -1
@@ -3,8 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Introspector = void 0;
4
4
  const introspector_tools_1 = require("./introspector.tools");
5
5
  const durable_tools_1 = require("./durable.tools");
6
- const extractTunnelInfo_1 = require("./extractTunnelInfo");
7
- const tunnel_tools_1 = require("./tunnel.tools");
6
+ const lane_resources_1 = require("../../utils/lane-resources");
8
7
  class Introspector {
9
8
  tasks = [];
10
9
  hooks = [];
@@ -17,7 +16,18 @@ class Introspector {
17
16
  errors = [];
18
17
  asyncContexts = [];
19
18
  store = null;
19
+ runtime = null;
20
20
  rootId = null;
21
+ runOptions = null;
22
+ interceptorOwners = {
23
+ tasksById: {},
24
+ middleware: {
25
+ globalTaskInterceptorOwnerIds: [],
26
+ globalResourceInterceptorOwnerIds: [],
27
+ perTaskMiddlewareInterceptorOwnerIds: {},
28
+ perResourceMiddlewareInterceptorOwnerIds: {},
29
+ },
30
+ };
21
31
  taskMap = new Map();
22
32
  hookMap = new Map();
23
33
  resourceMap = new Map();
@@ -28,27 +38,150 @@ class Introspector {
28
38
  asyncContextMap = new Map();
29
39
  constructor(input) {
30
40
  if ("store" in input) {
31
- // this.store = input.store;
32
- // this.initializeFromStore();
41
+ this.store = input.store;
42
+ this.runtime = input.runtime ?? null;
43
+ this.runOptions = input.runOptions ?? null;
33
44
  }
34
45
  else {
35
46
  this.store = null;
47
+ this.runtime = null;
36
48
  this.initializeFromData(input.data);
37
49
  }
38
50
  }
51
+ idsMatch(candidateId, referenceId) {
52
+ return (candidateId === referenceId || candidateId.endsWith(`.${referenceId}`));
53
+ }
54
+ resolveCanonicalId(referenceId, candidateIds) {
55
+ const direct = candidateIds.find((candidateId) => candidateId === referenceId);
56
+ if (direct)
57
+ return direct;
58
+ const suffixMatch = candidateIds.find((candidateId) => this.idsMatch(candidateId, referenceId));
59
+ return suffixMatch ?? referenceId;
60
+ }
61
+ canonicalizeReferenceArray(ids, candidateIds) {
62
+ return (0, introspector_tools_1.ensureStringArray)(ids).map((referenceId) => this.resolveCanonicalId(referenceId, candidateIds));
63
+ }
64
+ findByIdLike(collection, id) {
65
+ return collection.find((entry) => this.idsMatch(entry.id, id)) ?? null;
66
+ }
67
+ idsContainLike(ids, candidateId) {
68
+ return (0, introspector_tools_1.ensureStringArray)(ids).some((id) => this.idsMatch(candidateId, id));
69
+ }
70
+ normalizeMetaTags(node, tagIds) {
71
+ const meta = node.meta;
72
+ if (!meta)
73
+ return;
74
+ const normalizedDetailed = Array.isArray(meta.tagsDetailed)
75
+ ? meta.tagsDetailed.map((entry) => ({
76
+ ...entry,
77
+ id: this.resolveCanonicalId(entry.id, tagIds),
78
+ }))
79
+ : meta.tagsDetailed;
80
+ node.meta = {
81
+ ...meta,
82
+ tags: this.canonicalizeReferenceArray(meta.tags, tagIds),
83
+ tagsDetailed: normalizedDetailed,
84
+ };
85
+ }
86
+ normalizeRelationIds() {
87
+ const taskIds = this.tasks.map((entry) => entry.id);
88
+ const hookIds = this.hooks.map((entry) => entry.id);
89
+ const resourceIds = this.resources.map((entry) => entry.id);
90
+ const eventIds = this.events.map((entry) => entry.id);
91
+ const middlewareIds = this.middlewares.map((entry) => entry.id);
92
+ const tagIds = this.tags.map((entry) => entry.id);
93
+ const errorIds = this.errors.map((entry) => entry.id);
94
+ const asyncContextIds = this.asyncContexts.map((entry) => entry.id);
95
+ const allDependencyIds = [
96
+ ...taskIds,
97
+ ...hookIds,
98
+ ...resourceIds,
99
+ ...eventIds,
100
+ ...middlewareIds,
101
+ ...tagIds,
102
+ ...errorIds,
103
+ ...asyncContextIds,
104
+ ];
105
+ const taskLikeIds = [...taskIds, ...hookIds];
106
+ const taskHookResourceMiddlewareIds = [
107
+ ...taskIds,
108
+ ...hookIds,
109
+ ...resourceIds,
110
+ ...middlewareIds,
111
+ ];
112
+ for (const task of this.tasks) {
113
+ task.dependsOn = this.canonicalizeReferenceArray(task.dependsOn, allDependencyIds);
114
+ task.tags = this.canonicalizeReferenceArray(task.tags, tagIds);
115
+ task.emits = this.canonicalizeReferenceArray(task.emits, eventIds);
116
+ task.middleware = this.canonicalizeReferenceArray(task.middleware, middlewareIds);
117
+ this.normalizeMetaTags(task, tagIds);
118
+ }
119
+ for (const hook of this.hooks) {
120
+ hook.dependsOn = this.canonicalizeReferenceArray(hook.dependsOn, allDependencyIds);
121
+ hook.tags = this.canonicalizeReferenceArray(hook.tags, tagIds);
122
+ hook.emits = this.canonicalizeReferenceArray(hook.emits, eventIds);
123
+ hook.events = this.canonicalizeReferenceArray(hook.events, eventIds);
124
+ const hookWithMiddleware = hook;
125
+ hookWithMiddleware.middleware = this.canonicalizeReferenceArray(hookWithMiddleware.middleware, middlewareIds);
126
+ this.normalizeMetaTags(hook, tagIds);
127
+ }
128
+ for (const resource of this.resources) {
129
+ resource.dependsOn = this.canonicalizeReferenceArray(resource.dependsOn, allDependencyIds);
130
+ resource.tags = this.canonicalizeReferenceArray(resource.tags, tagIds);
131
+ resource.emits = this.canonicalizeReferenceArray(resource.emits, eventIds);
132
+ resource.middleware = this.canonicalizeReferenceArray(resource.middleware, middlewareIds);
133
+ resource.overrides = this.canonicalizeReferenceArray(resource.overrides, taskHookResourceMiddlewareIds);
134
+ resource.registers = this.canonicalizeReferenceArray(resource.registers, taskHookResourceMiddlewareIds);
135
+ this.normalizeMetaTags(resource, tagIds);
136
+ }
137
+ for (const middleware of this.middlewares) {
138
+ middleware.tags = this.canonicalizeReferenceArray(middleware.tags, tagIds);
139
+ const middlewareWithEmits = middleware;
140
+ middlewareWithEmits.emits = this.canonicalizeReferenceArray(middlewareWithEmits.emits, eventIds);
141
+ middleware.usedByTasks = this.canonicalizeReferenceArray(middleware.usedByTasks, taskLikeIds);
142
+ middleware.usedByResources = this.canonicalizeReferenceArray(middleware.usedByResources, resourceIds);
143
+ this.normalizeMetaTags(middleware, tagIds);
144
+ }
145
+ for (const event of this.events) {
146
+ event.tags = this.canonicalizeReferenceArray(event.tags, tagIds);
147
+ event.listenedToBy = this.canonicalizeReferenceArray(event.listenedToBy, hookIds);
148
+ this.normalizeMetaTags(event, tagIds);
149
+ }
150
+ for (const error of this.errors) {
151
+ error.tags = this.canonicalizeReferenceArray(error.tags, tagIds);
152
+ error.thrownBy = this.canonicalizeReferenceArray(error.thrownBy, taskHookResourceMiddlewareIds);
153
+ this.normalizeMetaTags(error, tagIds);
154
+ }
155
+ for (const asyncContext of this.asyncContexts) {
156
+ asyncContext.usedBy = this.canonicalizeReferenceArray(asyncContext.usedBy, taskHookResourceMiddlewareIds);
157
+ asyncContext.requiredBy = this.canonicalizeReferenceArray(asyncContext.requiredBy, taskIds);
158
+ asyncContext.providedBy = this.canonicalizeReferenceArray(asyncContext.providedBy, resourceIds);
159
+ this.normalizeMetaTags(asyncContext, tagIds);
160
+ }
161
+ }
162
+ finalizeDerivedState() {
163
+ this.normalizeRelationIds();
164
+ this.populateErrorThrownBy();
165
+ }
39
166
  initializeFromData(data) {
40
167
  this.tasks = Array.isArray(data.tasks) ? data.tasks : [];
41
168
  this.hooks = Array.isArray(data.hooks) ? data.hooks : [];
42
169
  this.resources = Array.isArray(data.resources) ? data.resources : [];
43
170
  this.events = Array.isArray(data.events) ? data.events : [];
44
- this.taskMiddlewares = [];
45
- this.resourceMiddlewares = [];
46
171
  this.middlewares = Array.isArray(data.middlewares) ? data.middlewares : [];
172
+ const splitMiddlewares = this.splitMiddlewaresByType(this.middlewares);
173
+ this.taskMiddlewares = splitMiddlewares.taskMiddlewares;
174
+ this.resourceMiddlewares = splitMiddlewares.resourceMiddlewares;
47
175
  this.errors = Array.isArray(data.errors) ? data.errors : [];
48
176
  this.asyncContexts = Array.isArray(data.asyncContexts)
49
177
  ? data.asyncContexts
50
178
  : [];
179
+ this.tags = Array.isArray(data.tags) ? data.tags : [];
51
180
  this.rootId = data.rootId ?? null;
181
+ this.runOptions = data.runOptions
182
+ ? this.normalizeRunOptions(data.runOptions)
183
+ : null;
184
+ this.interceptorOwners = data.interceptorOwners ?? this.interceptorOwners;
52
185
  // Maps
53
186
  this.taskMap = (0, introspector_tools_1.buildIdMap)(this.tasks);
54
187
  this.hookMap = (0, introspector_tools_1.buildIdMap)(this.hooks);
@@ -57,20 +190,39 @@ class Introspector {
57
190
  this.middlewareMap = (0, introspector_tools_1.buildIdMap)(this.middlewares);
58
191
  this.errorMap = (0, introspector_tools_1.buildIdMap)(this.errors);
59
192
  this.asyncContextMap = (0, introspector_tools_1.buildIdMap)(this.asyncContexts);
60
- // Populate thrownBy for errors based on dependencies (after maps are built)
61
- this.populateErrorThrownBy();
62
- // Tags
63
- const _getTasksWithTag = (tagId) => this.tasks.filter((t) => (0, introspector_tools_1.ensureStringArray)(t.tags).includes(tagId));
64
- const _getHooksWithTag = (tagId) => this.hooks.filter((h) => (0, introspector_tools_1.ensureStringArray)(h.tags).includes(tagId));
65
- const _getResourcesWithTag = (tagId) => this.resources.filter((r) => (0, introspector_tools_1.ensureStringArray)(r.tags).includes(tagId));
66
- const _getMiddlewaresWithTag = (tagId) => this.middlewares.filter((m) => (0, introspector_tools_1.ensureStringArray)(m.tags).includes(tagId));
67
- const _getEventsWithTag = (tagId) => this.events.filter((e) => (0, introspector_tools_1.ensureStringArray)(e.tags).includes(tagId));
68
- this.tags = data.tags;
193
+ this.finalizeDerivedState();
69
194
  this.tagMap = new Map();
70
195
  for (const tag of this.tags) {
71
196
  this.tagMap.set(tag.id, tag);
72
197
  }
73
198
  }
199
+ splitMiddlewaresByType(middlewares) {
200
+ const taskMiddlewares = [];
201
+ const resourceMiddlewares = [];
202
+ for (const middleware of middlewares) {
203
+ if (middleware.type === "task") {
204
+ taskMiddlewares.push(middleware);
205
+ continue;
206
+ }
207
+ if (middleware.type === "resource") {
208
+ resourceMiddlewares.push(middleware);
209
+ continue;
210
+ }
211
+ const usedByTasksLength = Array.isArray(middleware.usedByTasks)
212
+ ? middleware.usedByTasks.length
213
+ : 0;
214
+ const usedByResourcesLength = Array.isArray(middleware.usedByResources)
215
+ ? middleware.usedByResources.length
216
+ : 0;
217
+ if (usedByTasksLength > 0 || usedByResourcesLength === 0) {
218
+ taskMiddlewares.push(middleware);
219
+ }
220
+ else {
221
+ resourceMiddlewares.push(middleware);
222
+ }
223
+ }
224
+ return { taskMiddlewares, resourceMiddlewares };
225
+ }
74
226
  // Helper function for building runs options
75
227
  buildRunsOptions(nodeId, args) {
76
228
  const opts = {};
@@ -94,13 +246,146 @@ class Introspector {
94
246
  }
95
247
  // API Methods
96
248
  getRoot() {
97
- const s = this.store;
98
- const idFromStore = s?.root?.resource?.id
99
- ? String(s.root.resource.id)
249
+ const idFromStore = this.store?.root?.resource?.id
250
+ ? String(this.store.root.resource.id)
100
251
  : null;
101
252
  const id = idFromStore ?? this.rootId ?? this.resources[0]?.id;
102
253
  return (0, introspector_tools_1.stampElementKind)(this.resourceMap.get(String(id)), "RESOURCE");
103
254
  }
255
+ /**
256
+ * Returns the effective run options that were used when the application was started.
257
+ * When a live store is available, options are derived from it; otherwise
258
+ * the previously serialized snapshot is used.
259
+ */
260
+ normalizeRunOptions(runOptions) {
261
+ const legacyRunOptions = runOptions;
262
+ const mode = runOptions.mode ?? "dev";
263
+ const debug = Boolean(runOptions.debug);
264
+ const rootId = runOptions.rootId ?? this.rootId ?? "";
265
+ const logsPrintThreshold = runOptions.logsPrintThreshold !== undefined
266
+ ? runOptions.logsPrintThreshold
267
+ : "info";
268
+ const dispose = runOptions.dispose ??
269
+ {
270
+ totalBudgetMs: typeof legacyRunOptions.disposeBudgetMs === "number"
271
+ ? legacyRunOptions.disposeBudgetMs
272
+ : null,
273
+ drainingBudgetMs: typeof legacyRunOptions.disposeDrainBudgetMs === "number"
274
+ ? legacyRunOptions.disposeDrainBudgetMs
275
+ : null,
276
+ cooldownWindowMs: null,
277
+ };
278
+ const executionContext = runOptions.executionContext ??
279
+ {
280
+ enabled: false,
281
+ cycleDetection: typeof legacyRunOptions.runtimeEventCycleDetection === "boolean"
282
+ ? legacyRunOptions.runtimeEventCycleDetection
283
+ : null,
284
+ };
285
+ return {
286
+ mode,
287
+ debug,
288
+ debugMode: runOptions.debugMode ?? (debug ? "normal" : "disabled"),
289
+ logsEnabled: typeof runOptions.logsEnabled === "boolean"
290
+ ? runOptions.logsEnabled
291
+ : logsPrintThreshold !== null,
292
+ logsPrintThreshold,
293
+ logsPrintStrategy: runOptions.logsPrintStrategy !== undefined
294
+ ? runOptions.logsPrintStrategy
295
+ : "pretty",
296
+ logsBuffer: Boolean(runOptions.logsBuffer),
297
+ errorBoundary: runOptions.errorBoundary !== undefined
298
+ ? runOptions.errorBoundary
299
+ : null,
300
+ shutdownHooks: runOptions.shutdownHooks !== undefined
301
+ ? runOptions.shutdownHooks
302
+ : null,
303
+ dryRun: Boolean(runOptions.dryRun),
304
+ lazy: Boolean(runOptions.lazy),
305
+ lifecycleMode: runOptions.lifecycleMode === "parallel" ? "parallel" : "sequential",
306
+ dispose,
307
+ executionContext,
308
+ hasOnUnhandledError: Boolean(runOptions.hasOnUnhandledError),
309
+ rootId,
310
+ };
311
+ }
312
+ getRunOptions() {
313
+ if (this.store) {
314
+ const rootId = this.store.root?.resource?.id != null
315
+ ? String(this.store.root.resource.id)
316
+ : this.rootId ?? "";
317
+ const hasDebug = this.store.resources.has("runner.debug");
318
+ const debugResource = this.store.resources.get("runner.debug");
319
+ const debugConfig = debugResource?.config;
320
+ const debugMode = !hasDebug
321
+ ? "disabled"
322
+ : debugConfig === true
323
+ ? "normal"
324
+ : typeof debugConfig === "string"
325
+ ? debugConfig
326
+ : debugConfig && typeof debugConfig === "object"
327
+ ? "custom"
328
+ : "normal";
329
+ const loggerResource = this.store.resources.get("runner.logger");
330
+ const logger = loggerResource?.value;
331
+ const logsPrintThresholdRaw = logger?.printThreshold;
332
+ const logsPrintStrategyRaw = logger?.printStrategy;
333
+ const logsBufferRaw = logger?.bufferLogs;
334
+ const logsPrintThreshold = logsPrintThresholdRaw == null ? null : String(logsPrintThresholdRaw);
335
+ const logsPrintStrategy = logsPrintStrategyRaw == null ? null : String(logsPrintStrategyRaw);
336
+ const logsBuffer = Boolean(logsBufferRaw);
337
+ const runtimeRunOptions = this.runtime?.runOptions;
338
+ return this.normalizeRunOptions({
339
+ mode: this.store.mode ?? "dev",
340
+ debug: hasDebug,
341
+ debugMode,
342
+ logsEnabled: logsPrintThreshold !== null,
343
+ logsPrintThreshold,
344
+ logsPrintStrategy,
345
+ logsBuffer,
346
+ errorBoundary: typeof runtimeRunOptions?.errorBoundary === "boolean"
347
+ ? runtimeRunOptions.errorBoundary
348
+ : null,
349
+ shutdownHooks: typeof runtimeRunOptions?.shutdownHooks === "boolean"
350
+ ? runtimeRunOptions.shutdownHooks
351
+ : null,
352
+ dryRun: Boolean(runtimeRunOptions?.dryRun),
353
+ lazy: Boolean(runtimeRunOptions?.lazy),
354
+ lifecycleMode: runtimeRunOptions?.lifecycleMode === "parallel"
355
+ ? "parallel"
356
+ : "sequential",
357
+ dispose: {
358
+ totalBudgetMs: typeof runtimeRunOptions?.dispose?.totalBudgetMs === "number"
359
+ ? runtimeRunOptions.dispose.totalBudgetMs
360
+ : null,
361
+ drainingBudgetMs: typeof runtimeRunOptions?.dispose?.drainingBudgetMs === "number"
362
+ ? runtimeRunOptions.dispose.drainingBudgetMs
363
+ : null,
364
+ cooldownWindowMs: typeof runtimeRunOptions?.dispose?.cooldownWindowMs === "number"
365
+ ? runtimeRunOptions.dispose.cooldownWindowMs
366
+ : null,
367
+ },
368
+ executionContext: {
369
+ enabled: runtimeRunOptions?.executionContext != null,
370
+ cycleDetection: runtimeRunOptions?.executionContext == null
371
+ ? null
372
+ : typeof runtimeRunOptions.executionContext.cycleDetection ===
373
+ "boolean"
374
+ ? runtimeRunOptions.executionContext.cycleDetection
375
+ : runtimeRunOptions.executionContext.cycleDetection != null,
376
+ },
377
+ hasOnUnhandledError: typeof this.store.onUnhandledError === "function",
378
+ rootId,
379
+ });
380
+ }
381
+ if (this.runOptions)
382
+ return this.normalizeRunOptions(this.runOptions);
383
+ return this.normalizeRunOptions({
384
+ mode: "dev",
385
+ debug: false,
386
+ rootId: this.rootId ?? "",
387
+ });
388
+ }
104
389
  getAll() {
105
390
  return [
106
391
  ...this.tasks,
@@ -115,9 +400,9 @@ class Introspector {
115
400
  populateErrorThrownBy() {
116
401
  // Create error ID map for quick lookup
117
402
  const errorIds = new Set(this.errors.map((e) => e.id));
118
- // Clear existing thrownBy arrays
403
+ // Preserve preloaded producer data and only append derived dependencies.
119
404
  this.errors.forEach((error) => {
120
- error.thrownBy = [];
405
+ error.thrownBy = (0, introspector_tools_1.ensureStringArray)(error.thrownBy);
121
406
  });
122
407
  // Check tasks
123
408
  this.tasks.forEach((task) => {
@@ -180,29 +465,28 @@ class Introspector {
180
465
  return this.resources;
181
466
  }
182
467
  getEvent(id) {
183
- return this.eventMap.get(id) ?? null;
468
+ return this.eventMap.get(id) ?? this.findByIdLike(this.events, id);
184
469
  }
185
470
  getTask(id) {
186
- return this.taskMap.get(id) ?? null;
471
+ return this.taskMap.get(id) ?? this.findByIdLike(this.tasks, id);
187
472
  }
188
473
  getHook(id) {
189
- return this.hookMap.get(id) ?? null;
474
+ return this.hookMap.get(id) ?? this.findByIdLike(this.hooks, id);
190
475
  }
191
476
  getMiddleware(id) {
192
- return this.middlewareMap.get(id) ?? null;
477
+ return (this.middlewareMap.get(id) ?? this.findByIdLike(this.middlewares, id));
193
478
  }
194
479
  getResource(id) {
195
- return this.resourceMap.get(id) ?? null;
480
+ return this.resourceMap.get(id) ?? this.findByIdLike(this.resources, id);
196
481
  }
197
482
  getDependencies(node) {
198
483
  const depends = (0, introspector_tools_1.ensureStringArray)(node.dependsOn);
199
- const tasksDeps = this.tasks.filter((t) => depends.includes(t.id));
200
- const hooksDeps = this.hooks.filter((l) => depends.includes(l.id));
201
- const resourcesDeps = this.resources.filter((r) => depends.includes(r.id));
202
- const errorDeps = this.errors.filter((e) => depends.includes(e.id));
203
- // Only Task and Hook have emits, Resource doesn't
484
+ const tasksDeps = this.tasks.filter((t) => this.idsContainLike(depends, t.id));
485
+ const hooksDeps = this.hooks.filter((l) => this.idsContainLike(depends, l.id));
486
+ const resourcesDeps = this.resources.filter((r) => this.idsContainLike(depends, r.id));
487
+ const errorDeps = this.errors.filter((e) => this.idsContainLike(depends, e.id));
204
488
  const emitIds = (0, introspector_tools_1.ensureStringArray)(node.emits);
205
- const emitEvents = this.events.filter((e) => emitIds.includes(e.id));
489
+ const emitEvents = this.events.filter((e) => this.idsContainLike(emitIds, e.id));
206
490
  return {
207
491
  tasks: tasksDeps,
208
492
  hooks: hooksDeps,
@@ -213,33 +497,28 @@ class Introspector {
213
497
  }
214
498
  getEmittedEvents(node) {
215
499
  const emits = (0, introspector_tools_1.ensureStringArray)(node.emits);
216
- return this.events.filter((e) => emits.includes(e.id));
500
+ return this.events.filter((e) => this.idsContainLike(emits, e.id));
217
501
  }
218
502
  getMiddlewaresByIds(ids) {
219
- const set = new Set((0, introspector_tools_1.ensureStringArray)(ids));
220
- return this.middlewares.filter((m) => set.has(m.id));
503
+ return this.middlewares.filter((m) => this.idsContainLike(ids, m.id));
221
504
  }
222
505
  getResourcesByIds(ids) {
223
- const set = new Set((0, introspector_tools_1.ensureStringArray)(ids));
224
- return this.resources.filter((r) => set.has(r.id));
506
+ return this.resources.filter((r) => this.idsContainLike(ids, r.id));
225
507
  }
226
508
  getTasksByIds(ids) {
227
- const set = new Set((0, introspector_tools_1.ensureStringArray)(ids));
228
- return this.tasks.filter((t) => set.has(t.id));
509
+ return this.tasks.filter((t) => this.idsContainLike(ids, t.id));
229
510
  }
230
511
  getHooksByIds(ids) {
231
- const set = new Set((0, introspector_tools_1.ensureStringArray)(ids));
232
- return this.hooks.filter((l) => set.has(l.id));
512
+ return this.hooks.filter((l) => this.idsContainLike(ids, l.id));
233
513
  }
234
514
  getEventsByIds(ids) {
235
- const set = new Set((0, introspector_tools_1.ensureStringArray)(ids));
236
- return this.events.filter((e) => set.has(e.id));
515
+ return this.events.filter((e) => this.idsContainLike(ids, e.id));
237
516
  }
238
517
  getTasksUsingResource(resourceId) {
239
- return [...this.tasks, ...this.hooks].filter((t) => (0, introspector_tools_1.ensureStringArray)(t.dependsOn).includes(resourceId));
518
+ return [...this.tasks, ...this.hooks].filter((t) => this.idsContainLike(t.dependsOn, resourceId));
240
519
  }
241
520
  getTasksUsingMiddleware(middlewareId) {
242
- return this.tasks.filter((t) => (0, introspector_tools_1.ensureStringArray)(t.middleware).includes(middlewareId));
521
+ return this.tasks.filter((t) => this.idsContainLike(t.middleware, middlewareId));
243
522
  }
244
523
  // Backward-compat for schema fields expecting this name
245
524
  // Returns only task-like nodes (tasks and hooks)
@@ -247,10 +526,10 @@ class Introspector {
247
526
  return this.getTasksUsingMiddleware(middlewareId);
248
527
  }
249
528
  getEmittersOfEvent(eventId) {
250
- return [...this.tasks, ...this.hooks, ...this.resources].filter((t) => (0, introspector_tools_1.ensureStringArray)(t.emits).includes(eventId));
529
+ return [...this.tasks, ...this.hooks, ...this.resources].filter((t) => this.idsContainLike(t.emits, eventId));
251
530
  }
252
531
  getHooksOfEvent(eventId) {
253
- return this.hooks.filter((l) => l.events.includes(eventId));
532
+ return this.hooks.filter((l) => this.idsContainLike(l.events, eventId));
254
533
  }
255
534
  getMiddlewareEmittedEvents(middlewareId) {
256
535
  const taskLikes = this.getTasksUsingMiddleware(middlewareId);
@@ -264,8 +543,12 @@ class Introspector {
264
543
  }
265
544
  getMiddlewareUsagesForTask(taskId) {
266
545
  const task = this.taskMap.get(taskId);
267
- if (!task)
268
- return [];
546
+ if (!task) {
547
+ const resolvedTask = this.getTask(taskId);
548
+ if (!resolvedTask)
549
+ return [];
550
+ return this.getMiddlewareUsagesForTask(resolvedTask.id);
551
+ }
269
552
  const detailed = task.middlewareDetailed ?? [];
270
553
  return detailed
271
554
  .map((d) => ({
@@ -277,8 +560,12 @@ class Introspector {
277
560
  }
278
561
  getMiddlewareUsagesForResource(resourceId) {
279
562
  const res = this.resourceMap.get(resourceId);
280
- if (!res)
281
- return [];
563
+ if (!res) {
564
+ const resolvedResource = this.getResource(resourceId);
565
+ if (!resolvedResource)
566
+ return [];
567
+ return this.getMiddlewareUsagesForResource(resolvedResource.id);
568
+ }
282
569
  const detailed = res.middlewareDetailed ?? [];
283
570
  return detailed
284
571
  .map((d) => ({
@@ -292,9 +579,8 @@ class Introspector {
292
579
  const result = [];
293
580
  const addFrom = (arr) => {
294
581
  for (const tl of arr) {
295
- if ((tl.middleware || []).includes(middlewareId)) {
296
- const conf = (tl.middlewareDetailed || []).find((m) => m.id === middlewareId)
297
- ?.config ?? null;
582
+ if (this.idsContainLike(tl.middleware, middlewareId)) {
583
+ const conf = (tl.middlewareDetailed || []).find((m) => this.idsMatch(this.resolveCanonicalId(m.id, this.middlewares.map((entry) => entry.id)), middlewareId))?.config ?? null;
298
584
  result.push({ id: tl.id, config: conf ?? null, node: tl });
299
585
  }
300
586
  }
@@ -305,9 +591,8 @@ class Introspector {
305
591
  getResourcesUsingMiddlewareDetailed(middlewareId) {
306
592
  const result = [];
307
593
  for (const r of this.resources) {
308
- if ((r.middleware || []).includes(middlewareId)) {
309
- const conf = (r.middlewareDetailed || []).find((m) => m.id === middlewareId)
310
- ?.config ?? null;
594
+ if (this.idsContainLike(r.middleware, middlewareId)) {
595
+ const conf = (r.middlewareDetailed || []).find((m) => this.idsMatch(this.resolveCanonicalId(m.id, this.middlewares.map((entry) => entry.id)), middlewareId))?.config ?? null;
311
596
  result.push({ id: r.id, config: conf ?? null, node: r });
312
597
  }
313
598
  }
@@ -324,25 +609,44 @@ class Introspector {
324
609
  }
325
610
  // Tags API
326
611
  getTasksWithTag(tagId) {
327
- return this.tasks.filter((t) => (0, introspector_tools_1.ensureStringArray)(t.tags).includes(tagId));
612
+ return this.tasks.filter((t) => this.idsContainLike(t.tags, tagId));
328
613
  }
329
614
  getHooksWithTag(tagId) {
330
- return this.hooks.filter((h) => (0, introspector_tools_1.ensureStringArray)(h.tags).includes(tagId));
615
+ return this.hooks.filter((h) => this.idsContainLike(h.tags, tagId));
331
616
  }
332
617
  getResourcesWithTag(tagId) {
333
- return this.resources.filter((r) => (0, introspector_tools_1.ensureStringArray)(r.tags).includes(tagId));
618
+ return this.resources.filter((r) => this.idsContainLike(r.tags, tagId));
334
619
  }
335
620
  getMiddlewaresWithTag(tagId) {
336
- return this.middlewares.filter((m) => (0, introspector_tools_1.ensureStringArray)(m.tags).includes(tagId));
621
+ return this.middlewares.filter((m) => this.idsContainLike(m.tags, tagId));
622
+ }
623
+ getTaskMiddlewaresWithTag(tagId) {
624
+ return this.taskMiddlewares.filter((m) => this.idsContainLike(m.tags, tagId));
625
+ }
626
+ getResourceMiddlewaresWithTag(tagId) {
627
+ return this.resourceMiddlewares.filter((m) => this.idsContainLike(m.tags, tagId));
337
628
  }
338
629
  getEventsWithTag(tagId) {
339
- return this.events.filter((e) => (0, introspector_tools_1.ensureStringArray)(e.tags).includes(tagId));
630
+ return this.events.filter((e) => this.idsContainLike(e.tags, tagId));
631
+ }
632
+ getErrorsWithTag(tagId) {
633
+ return this.errors
634
+ .filter((e) => this.idsContainLike(e.tags, tagId))
635
+ .map((error) => (0, introspector_tools_1.stampElementKind)(error, "ERROR"));
636
+ }
637
+ getTagHandlers(tagId) {
638
+ const dependsOnTag = (item) => this.idsContainLike(item.dependsOn, tagId);
639
+ return {
640
+ tasks: this.tasks.filter(dependsOnTag),
641
+ hooks: this.hooks.filter(dependsOnTag),
642
+ resources: this.resources.filter(dependsOnTag),
643
+ };
340
644
  }
341
645
  getAllTags() {
342
646
  return this.tags;
343
647
  }
344
648
  getTag(id) {
345
- return this.tagMap.get(id) ?? null;
649
+ return this.tagMap.get(id) ?? this.findByIdLike(this.tags, id);
346
650
  }
347
651
  getTagsByIds(ids) {
348
652
  return ids
@@ -379,34 +683,35 @@ class Introspector {
379
683
  }
380
684
  // Error-related methods
381
685
  getErrors() {
382
- return this.errors;
686
+ return this.errors.map((error) => (0, introspector_tools_1.stampElementKind)(error, "ERROR"));
383
687
  }
384
688
  getError(id) {
385
- return this.errorMap.get(id) ?? null;
689
+ const error = this.errorMap.get(id) ?? this.findByIdLike(this.errors, id);
690
+ return error ? (0, introspector_tools_1.stampElementKind)(error, "ERROR") : null;
386
691
  }
387
692
  getTasksUsingError(errorId) {
388
- const error = this.errorMap.get(errorId);
693
+ const error = this.getError(errorId);
389
694
  if (!error?.thrownBy)
390
695
  return [];
391
- return this.tasks.filter((task) => error.thrownBy.includes(task.id));
696
+ return this.tasks.filter((task) => this.idsContainLike(error.thrownBy, task.id));
392
697
  }
393
698
  getResourcesUsingError(errorId) {
394
- const error = this.errorMap.get(errorId);
699
+ const error = this.getError(errorId);
395
700
  if (!error?.thrownBy)
396
701
  return [];
397
- return this.resources.filter((resource) => error.thrownBy.includes(resource.id));
702
+ return this.resources.filter((resource) => this.idsContainLike(error.thrownBy, resource.id));
398
703
  }
399
704
  getHooksUsingError(errorId) {
400
- const error = this.errorMap.get(errorId);
705
+ const error = this.getError(errorId);
401
706
  if (!error?.thrownBy)
402
707
  return [];
403
- return this.hooks.filter((hook) => error.thrownBy.includes(hook.id));
708
+ return this.hooks.filter((hook) => this.idsContainLike(error.thrownBy, hook.id));
404
709
  }
405
710
  getMiddlewaresUsingError(errorId) {
406
- const error = this.errorMap.get(errorId);
711
+ const error = this.getError(errorId);
407
712
  if (!error?.thrownBy)
408
713
  return [];
409
- return this.middlewares.filter((middleware) => error.thrownBy.includes(middleware.id));
714
+ return this.middlewares.filter((middleware) => this.idsContainLike(error.thrownBy, middleware.id));
410
715
  }
411
716
  getAllUsingError(errorId) {
412
717
  return [
@@ -421,37 +726,37 @@ class Introspector {
421
726
  return this.asyncContexts;
422
727
  }
423
728
  getAsyncContext(id) {
424
- return this.asyncContextMap.get(id) ?? null;
729
+ return (this.asyncContextMap.get(id) ?? this.findByIdLike(this.asyncContexts, id));
425
730
  }
426
731
  getTasksUsingContext(contextId) {
427
- const context = this.asyncContextMap.get(contextId);
732
+ const context = this.getAsyncContext(contextId);
428
733
  if (!context?.usedBy)
429
734
  return [];
430
- return this.tasks.filter((task) => context.usedBy.includes(task.id));
735
+ return this.tasks.filter((task) => this.idsContainLike(context.usedBy, task.id));
431
736
  }
432
737
  getResourcesUsingContext(contextId) {
433
- const context = this.asyncContextMap.get(contextId);
738
+ const context = this.getAsyncContext(contextId);
434
739
  if (!context?.usedBy)
435
740
  return [];
436
- return this.resources.filter((resource) => context.usedBy.includes(resource.id));
741
+ return this.resources.filter((resource) => this.idsContainLike(context.usedBy, resource.id));
437
742
  }
438
743
  getResourcesProvidingContext(contextId) {
439
- const context = this.asyncContextMap.get(contextId);
744
+ const context = this.getAsyncContext(contextId);
440
745
  if (!context?.providedBy)
441
746
  return [];
442
- return this.resources.filter((resource) => context.providedBy.includes(resource.id));
747
+ return this.resources.filter((resource) => this.idsContainLike(context.providedBy, resource.id));
443
748
  }
444
749
  getHooksUsingContext(contextId) {
445
- const context = this.asyncContextMap.get(contextId);
750
+ const context = this.getAsyncContext(contextId);
446
751
  if (!context?.usedBy)
447
752
  return [];
448
- return this.hooks.filter((hook) => context.usedBy.includes(hook.id));
753
+ return this.hooks.filter((hook) => this.idsContainLike(context.usedBy, hook.id));
449
754
  }
450
755
  getMiddlewaresUsingContext(contextId) {
451
- const context = this.asyncContextMap.get(contextId);
756
+ const context = this.getAsyncContext(contextId);
452
757
  if (!context?.usedBy)
453
758
  return [];
454
- return this.middlewares.filter((middleware) => context.usedBy.includes(middleware.id));
759
+ return this.middlewares.filter((middleware) => this.idsContainLike(context.usedBy, middleware.id));
455
760
  }
456
761
  getAllUsingContext(contextId) {
457
762
  return [
@@ -465,73 +770,57 @@ class Introspector {
465
770
  * Returns tasks that use `.require()` for a given async context.
466
771
  */
467
772
  getTasksRequiringContext(contextId) {
468
- const context = this.asyncContextMap.get(contextId);
773
+ const context = this.getAsyncContext(contextId);
469
774
  if (!context?.requiredBy)
470
775
  return [];
471
- return this.tasks.filter((task) => context.requiredBy.includes(task.id));
776
+ return this.tasks.filter((task) => this.idsContainLike(context.requiredBy, task.id));
472
777
  }
473
778
  /**
474
779
  * Checks whether a given element uses `.require()` for a specific async context.
475
780
  */
476
781
  isContextRequiredBy(contextId, elementId) {
477
- const context = this.asyncContextMap.get(contextId);
478
- return context?.requiredBy?.includes(elementId) ?? false;
782
+ const context = this.getAsyncContext(contextId);
783
+ return this.idsContainLike(context?.requiredBy, elementId);
479
784
  }
480
- // Tunnel-related methods (enhance existing methods)
481
- getTunnelResources() {
482
- // Resources with populated tunnelInfo (set during store initialization)
483
- return this.resources.filter((resource) => resource.tunnelInfo != null);
785
+ // RPC lane-related methods
786
+ getRpcLanesResources() {
787
+ return this.resources.filter((resource) => (0, lane_resources_1.isRpcLanesResource)(resource));
484
788
  }
485
- getTunneledTasks(tunnelResourceId) {
486
- const tunnel = this.getResource(tunnelResourceId);
487
- if (!tunnel?.tunnelInfo?.tasks)
488
- return [];
489
- return this.getTasksByIds(tunnel.tunnelInfo.tasks);
789
+ getTasksByRpcLane(rpcLaneId) {
790
+ return this.tasks.filter((task) => task.rpcLane?.laneId === rpcLaneId);
490
791
  }
491
- getTunneledEvents(tunnelResourceId) {
492
- const tunnel = this.getResource(tunnelResourceId);
493
- if (!tunnel?.tunnelInfo?.events)
494
- return [];
495
- return this.getEventsByIds(tunnel.tunnelInfo.events);
792
+ getEventsByRpcLane(rpcLaneId) {
793
+ return this.events.filter((event) => event.rpcLane?.laneId === rpcLaneId);
496
794
  }
497
- getTunnelForTask(taskId) {
498
- const task = this.getTask(taskId);
499
- if (!task)
795
+ getRpcLaneForTask(taskId) {
796
+ return this.getTask(taskId)?.rpcLane?.laneId ?? null;
797
+ }
798
+ getRpcLaneForEvent(eventId) {
799
+ return this.getEvent(eventId)?.rpcLane?.laneId ?? null;
800
+ }
801
+ getRpcLaneResourceForTask(taskId) {
802
+ const laneId = this.getRpcLaneForTask(taskId);
803
+ if (!laneId)
500
804
  return null;
501
- // Find tunnel resource that owns this task
502
- return (this.getTunnelResources().find((tunnel) => tunnel.tunnelInfo?.tasks?.includes(taskId)) ?? null);
805
+ return this.findRpcLanesResourceByLaneId(laneId);
503
806
  }
504
- getTunnelForEvent(eventId) {
505
- // Find tunnel resource that tunnels this event
506
- return (this.getTunnelResources().find((tunnel) => tunnel.tunnelInfo?.events?.includes(eventId)) ?? null);
807
+ getRpcLaneResourceForEvent(eventId) {
808
+ const laneId = this.getRpcLaneForEvent(eventId);
809
+ if (!laneId)
810
+ return null;
811
+ return this.findRpcLanesResourceByLaneId(laneId);
507
812
  }
508
- /**
509
- * Populates tunnelInfo for resources with the tunnel tag.
510
- * Call this method after all resources have been initialized to ensure
511
- * tunnel resource values are available.
512
- */
513
- populateTunnelInfo() {
514
- const s = this.store;
515
- if (!s?.resources)
516
- return;
517
- const allTaskIds = this.tasks.map((t) => t.id);
518
- const allEventIds = this.events.map((e) => e.id);
519
- for (const storeEntry of s.resources.values()) {
520
- const resourceDef = storeEntry.resource;
521
- const resourceValue = storeEntry.value;
522
- const resourceId = String(resourceDef.id);
523
- // Find the corresponding model resource
524
- const modelResource = this.resources.find((r) => r.id === resourceId);
525
- if (!modelResource)
526
- continue;
527
- // Check if resource has tunnel tag using the already-normalized tags
528
- if ((0, tunnel_tools_1.hasTunnelTag)(modelResource.tags) && resourceValue) {
529
- const tunnelInfo = (0, extractTunnelInfo_1.extractTunnelInfo)(resourceValue, allTaskIds, allEventIds);
530
- if (tunnelInfo) {
531
- modelResource.tunnelInfo = tunnelInfo;
532
- }
533
- }
813
+ findRpcLanesResourceByLaneId(laneId) {
814
+ const rpcLanesResources = this.getRpcLanesResources();
815
+ if (rpcLanesResources.length === 0)
816
+ return null;
817
+ for (const resource of rpcLanesResources) {
818
+ const laneIds = (0, lane_resources_1.collectRpcLaneIdsFromResourceConfig)(resource.config);
819
+ if (laneIds.has(laneId))
820
+ return resource;
534
821
  }
822
+ // Fallback: if exactly one rpcLanes resource exists, prefer it.
823
+ return rpcLanesResources.length === 1 ? rpcLanesResources[0] : null;
535
824
  }
536
825
  // Durable workflow-related methods
537
826
  /**
@@ -539,7 +828,7 @@ class Introspector {
539
828
  * A task is durable if it has the durable workflow tag (current: `globals.tags.durableWorkflow`, legacy: `durable.workflow`).
540
829
  */
541
830
  isDurableTask(taskId) {
542
- const task = this.taskMap.get(taskId);
831
+ const task = this.getTask(taskId);
543
832
  if (!task)
544
833
  return false;
545
834
  return (0, durable_tools_1.hasDurableWorkflowTag)(task.tags);
@@ -554,7 +843,7 @@ class Introspector {
554
843
  * Returns the durable resource a task depends on, if any.
555
844
  */
556
845
  getDurableResourceForTask(taskId) {
557
- const task = this.taskMap.get(taskId);
846
+ const task = this.getTask(taskId);
558
847
  if (!task)
559
848
  return null;
560
849
  if (!this.isDurableTask(taskId))
@@ -564,6 +853,45 @@ class Introspector {
564
853
  return durableDepId ? this.getResource(durableDepId) : null;
565
854
  }
566
855
  // Serialization API
856
+ getInterceptorOwnersSnapshot() {
857
+ return this.interceptorOwners;
858
+ }
859
+ getTaskInterceptorOwnerIds(taskId) {
860
+ const taskInterceptors = this.getTaskInterceptorsFromLiveStore(taskId);
861
+ if (taskInterceptors != null) {
862
+ return Array.from(new Set(taskInterceptors
863
+ .map((record) => record.ownerResourceId)
864
+ .filter((value) => Boolean(value))));
865
+ }
866
+ return this.interceptorOwners.tasksById[taskId] ?? [];
867
+ }
868
+ getTaskInterceptorCount(taskId) {
869
+ const taskInterceptors = this.getTaskInterceptorsFromLiveStore(taskId);
870
+ if (taskInterceptors != null) {
871
+ return taskInterceptors.length;
872
+ }
873
+ const task = this.taskMap.get(taskId);
874
+ if (typeof task?.interceptorCount === "number") {
875
+ return task.interceptorCount;
876
+ }
877
+ return (this.interceptorOwners.tasksById[taskId] ?? []).length;
878
+ }
879
+ hasTaskInterceptors(taskId) {
880
+ return this.getTaskInterceptorCount(taskId) > 0;
881
+ }
882
+ getMiddlewareInterceptorOwnerIds(middlewareId) {
883
+ const taskOwners = this.interceptorOwners.middleware.perTaskMiddlewareInterceptorOwnerIds[middlewareId] ?? [];
884
+ const resourceOwners = this.interceptorOwners.middleware
885
+ .perResourceMiddlewareInterceptorOwnerIds[middlewareId] ?? [];
886
+ return Array.from(new Set([...taskOwners, ...resourceOwners]));
887
+ }
888
+ getTaskInterceptorsFromLiveStore(taskId) {
889
+ const taskStoreEntry = this.store?.tasks.get(taskId);
890
+ if (!taskStoreEntry || !Array.isArray(taskStoreEntry.interceptors)) {
891
+ return null;
892
+ }
893
+ return taskStoreEntry.interceptors;
894
+ }
567
895
  serialize() {
568
896
  return {
569
897
  tasks: this.tasks,
@@ -584,6 +912,8 @@ class Introspector {
584
912
  rootId: this.store?.root?.resource?.id != null
585
913
  ? String(this.store.root.resource.id)
586
914
  : this.rootId,
915
+ runOptions: this.getRunOptions(),
916
+ interceptorOwners: this.getInterceptorOwnersSnapshot(),
587
917
  };
588
918
  }
589
919
  static deserialize(data) {