@lssm/lib.contracts 0.0.0-canary-20251217062943 → 0.0.0-canary-20251217072406

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 (237) hide show
  1. package/dist/app-config/app-config.feature.js +53 -1
  2. package/dist/app-config/contracts.d.ts +50 -50
  3. package/dist/app-config/contracts.js +396 -1
  4. package/dist/app-config/docs/app-config.docblock.js +22 -220
  5. package/dist/app-config/events.js +168 -1
  6. package/dist/app-config/index.js +8 -1
  7. package/dist/app-config/lifecycle-contracts.js +441 -1
  8. package/dist/app-config/runtime.js +617 -1
  9. package/dist/app-config/spec.js +36 -1
  10. package/dist/app-config/validation.js +538 -1
  11. package/dist/capabilities/docs/capabilities.docblock.js +22 -1
  12. package/dist/capabilities/openbanking.js +92 -1
  13. package/dist/capabilities.js +50 -1
  14. package/dist/client/index.js +9 -1
  15. package/dist/client/react/drivers/rn-reusables.js +21 -1
  16. package/dist/client/react/drivers/shadcn.js +11 -1
  17. package/dist/client/react/feature-render.js +43 -1
  18. package/dist/client/react/form-render.js +298 -1
  19. package/dist/client/react/index.js +8 -1
  20. package/dist/contract-registry/index.js +3 -1
  21. package/dist/contract-registry/schemas.js +61 -1
  22. package/dist/contracts-adapter-hydration.js +41 -1
  23. package/dist/contracts-adapter-input.js +77 -1
  24. package/dist/data-views/docs/data-views.docblock.js +22 -1
  25. package/dist/data-views/query-generator.js +48 -1
  26. package/dist/data-views/runtime.js +39 -1
  27. package/dist/data-views.js +35 -1
  28. package/dist/docs/PUBLISHING.docblock.js +17 -76
  29. package/dist/docs/accessibility_wcag_compliance_specs.docblock.js +17 -350
  30. package/dist/docs/index.js +33 -1
  31. package/dist/docs/meta.docs.js +15 -2
  32. package/dist/docs/presentations.js +77 -1
  33. package/dist/docs/registry.js +51 -1
  34. package/dist/docs/tech/PHASE_1_QUICKSTART.docblock.js +17 -383
  35. package/dist/docs/tech/PHASE_2_AI_NATIVE_OPERATIONS.docblock.js +17 -68
  36. package/dist/docs/tech/PHASE_3_AUTO_EVOLUTION.docblock.js +17 -140
  37. package/dist/docs/tech/PHASE_4_PERSONALIZATION_ENGINE.docblock.js +17 -86
  38. package/dist/docs/tech/PHASE_5_ZERO_TOUCH_OPERATIONS.docblock.js +17 -1
  39. package/dist/docs/tech/auth/better-auth-nextjs.docblock.js +25 -2
  40. package/dist/docs/tech/contracts/README.docblock.js +21 -1
  41. package/dist/docs/tech/contracts/create-subscription.docblock.js +21 -1
  42. package/dist/docs/tech/contracts/graphql-typed-outputs.docblock.js +21 -180
  43. package/dist/docs/tech/contracts/migrations.docblock.js +21 -1
  44. package/dist/docs/tech/contracts/openapi-export.docblock.js +22 -2
  45. package/dist/docs/tech/contracts/ops-to-presentation-linking.docblock.js +19 -60
  46. package/dist/docs/tech/contracts/overlays.docblock.js +21 -68
  47. package/dist/docs/tech/contracts/tests.docblock.js +21 -132
  48. package/dist/docs/tech/contracts/themes.docblock.js +21 -1
  49. package/dist/docs/tech/contracts/vertical-pocket-family-office.docblock.js +21 -106
  50. package/dist/docs/tech/lifecycle-stage-system.docblock.js +17 -213
  51. package/dist/docs/tech/llm/llm-integration.docblock.js +74 -5
  52. package/dist/docs/tech/mcp-endpoints.docblock.js +38 -1
  53. package/dist/docs/tech/presentation-runtime.docblock.js +17 -1
  54. package/dist/docs/tech/schema/README.docblock.js +21 -262
  55. package/dist/docs/tech/studio/learning-events.docblock.js +49 -1
  56. package/dist/docs/tech/studio/learning-journeys.docblock.js +25 -2
  57. package/dist/docs/tech/studio/platform-admin-panel.docblock.js +24 -2
  58. package/dist/docs/tech/studio/project-access-teams.docblock.js +26 -16
  59. package/dist/docs/tech/studio/project-routing.docblock.js +68 -1
  60. package/dist/docs/tech/studio/sandbox-unlogged.docblock.js +23 -2
  61. package/dist/docs/tech/studio/team-invitations.docblock.js +41 -36
  62. package/dist/docs/tech/studio/workspace-ops.docblock.js +48 -1
  63. package/dist/docs/tech/studio/workspaces.docblock.js +24 -2
  64. package/dist/docs/tech/telemetry-ingest.docblock.js +37 -3
  65. package/dist/docs/tech/templates/runtime.docblock.js +21 -1
  66. package/dist/docs/tech/vscode-extension.docblock.js +37 -3
  67. package/dist/docs/tech/workflows/overview.docblock.js +21 -1
  68. package/dist/docs/tech-contracts.docs.js +19 -2
  69. package/dist/events.js +12 -1
  70. package/dist/experiments/docs/experiments.docblock.js +22 -128
  71. package/dist/experiments/evaluator.js +101 -1
  72. package/dist/experiments/spec.js +33 -1
  73. package/dist/features.js +68 -1
  74. package/dist/forms/docs/forms.docblock.js +22 -1
  75. package/dist/forms.js +119 -1
  76. package/dist/index.js +107 -1
  77. package/dist/install.js +40 -1
  78. package/dist/integrations/contracts.d.ts +102 -102
  79. package/dist/integrations/contracts.js +388 -1
  80. package/dist/integrations/docs/integrations.docblock.js +95 -1
  81. package/dist/integrations/health.js +69 -1
  82. package/dist/integrations/index.js +23 -1
  83. package/dist/integrations/openbanking/contracts/accounts.d.ts +66 -66
  84. package/dist/integrations/openbanking/contracts/accounts.js +237 -1
  85. package/dist/integrations/openbanking/contracts/balances.d.ts +34 -34
  86. package/dist/integrations/openbanking/contracts/balances.js +167 -1
  87. package/dist/integrations/openbanking/contracts/index.js +12 -1
  88. package/dist/integrations/openbanking/contracts/transactions.d.ts +48 -48
  89. package/dist/integrations/openbanking/contracts/transactions.js +218 -1
  90. package/dist/integrations/openbanking/guards.js +32 -1
  91. package/dist/integrations/openbanking/models.d.ts +55 -55
  92. package/dist/integrations/openbanking/models.js +242 -1
  93. package/dist/integrations/openbanking/openbanking.feature.js +68 -1
  94. package/dist/integrations/openbanking/telemetry.js +39 -1
  95. package/dist/integrations/providers/elevenlabs.js +56 -1
  96. package/dist/integrations/providers/gcs-storage.js +79 -1
  97. package/dist/integrations/providers/gmail.js +91 -1
  98. package/dist/integrations/providers/google-calendar.js +70 -1
  99. package/dist/integrations/providers/impls/elevenlabs-voice.js +95 -1
  100. package/dist/integrations/providers/impls/gcs-storage.js +88 -1
  101. package/dist/integrations/providers/impls/gmail-inbound.js +200 -1
  102. package/dist/integrations/providers/impls/gmail-outbound.js +104 -5
  103. package/dist/integrations/providers/impls/google-calendar.js +154 -1
  104. package/dist/integrations/providers/impls/index.js +16 -1
  105. package/dist/integrations/providers/impls/mistral-embedding.js +41 -1
  106. package/dist/integrations/providers/impls/mistral-llm.js +247 -1
  107. package/dist/integrations/providers/impls/postmark-email.js +55 -1
  108. package/dist/integrations/providers/impls/powens-client.js +171 -1
  109. package/dist/integrations/providers/impls/powens-openbanking.js +218 -1
  110. package/dist/integrations/providers/impls/provider-factory.js +142 -1
  111. package/dist/integrations/providers/impls/qdrant-vector.js +69 -1
  112. package/dist/integrations/providers/impls/stripe-payments.js +202 -1
  113. package/dist/integrations/providers/impls/twilio-sms.js +58 -1
  114. package/dist/integrations/providers/index.js +13 -1
  115. package/dist/integrations/providers/mistral.js +72 -1
  116. package/dist/integrations/providers/postmark.js +72 -1
  117. package/dist/integrations/providers/powens.js +120 -1
  118. package/dist/integrations/providers/qdrant.js +77 -1
  119. package/dist/integrations/providers/registry.js +34 -1
  120. package/dist/integrations/providers/stripe.js +87 -1
  121. package/dist/integrations/providers/twilio-sms.js +65 -1
  122. package/dist/integrations/runtime.js +186 -1
  123. package/dist/integrations/secrets/aws-secret-manager.js +231 -1
  124. package/dist/integrations/secrets/env-secret-provider.js +81 -1
  125. package/dist/integrations/secrets/gcp-secret-manager.js +229 -1
  126. package/dist/integrations/secrets/index.js +8 -1
  127. package/dist/integrations/secrets/manager.js +103 -1
  128. package/dist/integrations/secrets/provider.js +58 -1
  129. package/dist/integrations/secrets/scaleway-secret-manager.js +247 -1
  130. package/dist/integrations/spec.js +39 -1
  131. package/dist/jobs/define-job.js +16 -1
  132. package/dist/jobs/gcp-cloud-tasks.js +53 -1
  133. package/dist/jobs/gcp-pubsub.js +39 -1
  134. package/dist/jobs/handlers/gmail-sync-handler.js +9 -1
  135. package/dist/jobs/handlers/index.js +12 -1
  136. package/dist/jobs/handlers/ping-handler.js +15 -1
  137. package/dist/jobs/handlers/storage-document-handler.js +14 -1
  138. package/dist/jobs/index.js +4 -1
  139. package/dist/jobs/memory-queue.js +71 -1
  140. package/dist/jobs/queue.js +33 -1
  141. package/dist/jobs/scaleway-sqs-queue.js +153 -1
  142. package/dist/jsonschema.d.ts +3 -3
  143. package/dist/jsonschema.js +32 -1
  144. package/dist/knowledge/contracts.d.ts +66 -66
  145. package/dist/knowledge/contracts.js +317 -1
  146. package/dist/knowledge/docs/knowledge.docblock.js +22 -138
  147. package/dist/knowledge/index.js +10 -1
  148. package/dist/knowledge/ingestion/document-processor.js +54 -1
  149. package/dist/knowledge/ingestion/embedding-service.js +25 -1
  150. package/dist/knowledge/ingestion/gmail-adapter.js +50 -5
  151. package/dist/knowledge/ingestion/index.js +7 -1
  152. package/dist/knowledge/ingestion/storage-adapter.js +26 -1
  153. package/dist/knowledge/ingestion/vector-indexer.js +32 -1
  154. package/dist/knowledge/query/index.js +3 -1
  155. package/dist/knowledge/query/service.js +64 -2
  156. package/dist/knowledge/runtime.js +49 -1
  157. package/dist/knowledge/spaces/email-threads.js +38 -1
  158. package/dist/knowledge/spaces/financial-docs.js +38 -1
  159. package/dist/knowledge/spaces/financial-overview.js +42 -1
  160. package/dist/knowledge/spaces/index.js +8 -1
  161. package/dist/knowledge/spaces/product-canon.js +38 -1
  162. package/dist/knowledge/spaces/support-faq.js +41 -1
  163. package/dist/knowledge/spaces/uploaded-docs.js +38 -1
  164. package/dist/knowledge/spec.js +39 -1
  165. package/dist/llm/exporters.js +541 -8
  166. package/dist/llm/index.js +4 -1
  167. package/dist/llm/prompts.js +246 -56
  168. package/dist/markdown.js +116 -3
  169. package/dist/migrations.js +33 -1
  170. package/dist/onboarding-base.d.ts +29 -29
  171. package/dist/onboarding-base.js +196 -1
  172. package/dist/openapi.js +75 -1
  173. package/dist/openbanking/docs/openbanking.docblock.js +22 -109
  174. package/dist/ownership.js +40 -1
  175. package/dist/policy/docs/policy.docblock.js +22 -1
  176. package/dist/policy/engine.js +223 -1
  177. package/dist/policy/opa-adapter.js +71 -1
  178. package/dist/policy/spec.js +33 -1
  179. package/dist/presentations/docs/presentations-conventions.docblock.js +21 -7
  180. package/dist/presentations.backcompat.js +47 -1
  181. package/dist/presentations.d.ts +3 -3
  182. package/dist/presentations.js +66 -1
  183. package/dist/presentations.v2.js +278 -6
  184. package/dist/prompt.js +10 -1
  185. package/dist/promptRegistry.js +34 -1
  186. package/dist/regenerator/docs/regenerator.docblock.js +22 -184
  187. package/dist/regenerator/executor.js +86 -1
  188. package/dist/regenerator/index.js +6 -1
  189. package/dist/regenerator/service.js +92 -1
  190. package/dist/regenerator/sinks.js +32 -1
  191. package/dist/regenerator/utils.js +51 -1
  192. package/dist/registry.js +208 -1
  193. package/dist/resources.js +47 -1
  194. package/dist/schema/dist/EnumType.js +2 -1
  195. package/dist/schema/dist/FieldType.js +49 -1
  196. package/dist/schema/dist/ScalarTypeEnum.js +236 -1
  197. package/dist/schema/dist/SchemaModel.js +39 -1
  198. package/dist/schema/dist/entity/defineEntity.js +1 -1
  199. package/dist/schema/dist/entity/index.js +2 -1
  200. package/dist/schema/dist/entity/types.js +1 -1
  201. package/dist/schema/dist/index.js +6 -1
  202. package/dist/schema-to-markdown.js +214 -10
  203. package/dist/server/graphql-pothos.js +128 -1
  204. package/dist/server/index.js +10 -1
  205. package/dist/server/mcp/createMcpServer.js +28 -1
  206. package/dist/server/mcp/registerPresentations.js +151 -1
  207. package/dist/server/mcp/registerPrompts.js +36 -2
  208. package/dist/server/mcp/registerResources.js +35 -1
  209. package/dist/server/mcp/registerTools.js +22 -1
  210. package/dist/server/provider-mcp.js +3 -1
  211. package/dist/server/rest-elysia.js +20 -1
  212. package/dist/server/rest-express.js +39 -1
  213. package/dist/server/rest-generic.js +125 -1
  214. package/dist/server/rest-next-app.js +38 -1
  215. package/dist/server/rest-next-mcp.js +45 -1
  216. package/dist/server/rest-next-pages.js +25 -1
  217. package/dist/spec.js +35 -1
  218. package/dist/telemetry/anomaly.js +48 -1
  219. package/dist/telemetry/docs/telemetry.docblock.js +22 -139
  220. package/dist/telemetry/index.js +5 -1
  221. package/dist/telemetry/spec.js +69 -1
  222. package/dist/telemetry/tracker.js +76 -1
  223. package/dist/tests/index.js +4 -1
  224. package/dist/tests/runner.js +150 -1
  225. package/dist/tests/spec.js +33 -1
  226. package/dist/themes.js +39 -1
  227. package/dist/workflow/adapters/db-adapter.js +83 -1
  228. package/dist/workflow/adapters/file-adapter.js +11 -1
  229. package/dist/workflow/adapters/index.js +5 -1
  230. package/dist/workflow/adapters/memory-store.js +58 -1
  231. package/dist/workflow/expression.js +98 -1
  232. package/dist/workflow/index.js +9 -1
  233. package/dist/workflow/runner.js +337 -1
  234. package/dist/workflow/sla-monitor.js +47 -1
  235. package/dist/workflow/spec.js +32 -1
  236. package/dist/workflow/validation.js +175 -1
  237. package/package.json +11 -4
@@ -1 +1,47 @@
1
- var e=class{constructor(e){this.eventEmitter=e}check(e,t){let n=t.definition.sla;if(!n)return;let r=new Date().getTime();if(n.totalDurationMs){let t=r-e.createdAt.getTime();t>n.totalDurationMs&&(e.status===`running`||e.status===`paused`)&&this.eventEmitter(`workflow.sla_breach`,{workflowId:e.workflowId,workflowName:e.workflowName,type:`workflow_duration`,expectedMs:n.totalDurationMs,actualMs:t,breachedAt:new Date})}if(n.stepDurationMs&&e.status===`running`&&e.currentStep){let t=e.history.find(t=>t.stepId===e.currentStep&&t.status===`running`);if(t){let i=n.stepDurationMs[e.currentStep];if(i){let n=r-t.startedAt.getTime();n>i&&this.eventEmitter(`workflow.sla_breach`,{workflowId:e.workflowId,workflowName:e.workflowName,type:`step_duration`,stepId:e.currentStep,expectedMs:i,actualMs:n,breachedAt:new Date})}}}}};export{e as SLAMonitor};
1
+ //#region src/workflow/sla-monitor.ts
2
+ var SLAMonitor = class {
3
+ constructor(eventEmitter) {
4
+ this.eventEmitter = eventEmitter;
5
+ }
6
+ check(state, spec) {
7
+ const sla = spec.definition.sla;
8
+ if (!sla) return;
9
+ const now = (/* @__PURE__ */ new Date()).getTime();
10
+ if (sla.totalDurationMs) {
11
+ const duration = now - state.createdAt.getTime();
12
+ if (duration > sla.totalDurationMs) {
13
+ if (state.status === "running" || state.status === "paused") this.eventEmitter("workflow.sla_breach", {
14
+ workflowId: state.workflowId,
15
+ workflowName: state.workflowName,
16
+ type: "workflow_duration",
17
+ expectedMs: sla.totalDurationMs,
18
+ actualMs: duration,
19
+ breachedAt: /* @__PURE__ */ new Date()
20
+ });
21
+ }
22
+ }
23
+ if (sla.stepDurationMs) {
24
+ if (state.status === "running" && state.currentStep) {
25
+ const currentExecution = state.history.find((h) => h.stepId === state.currentStep && h.status === "running");
26
+ if (currentExecution) {
27
+ const stepLimit = sla.stepDurationMs[state.currentStep];
28
+ if (stepLimit) {
29
+ const stepDuration = now - currentExecution.startedAt.getTime();
30
+ if (stepDuration > stepLimit) this.eventEmitter("workflow.sla_breach", {
31
+ workflowId: state.workflowId,
32
+ workflowName: state.workflowName,
33
+ type: "step_duration",
34
+ stepId: state.currentStep,
35
+ expectedMs: stepLimit,
36
+ actualMs: stepDuration,
37
+ breachedAt: /* @__PURE__ */ new Date()
38
+ });
39
+ }
40
+ }
41
+ }
42
+ }
43
+ }
44
+ };
45
+
46
+ //#endregion
47
+ export { SLAMonitor };
@@ -1 +1,32 @@
1
- function e(e){return`${e.name}.v${e.version}`}var t=class{items=new Map;register(t){let n=e(t.meta);if(this.items.has(n))throw Error(`Duplicate workflow ${n}`);return this.items.set(n,t),this}list(){return[...this.items.values()]}get(e,t){if(t!=null)return this.items.get(`${e}.v${t}`);let n,r=-1/0;for(let t of this.items.values())t.meta.name===e&&t.meta.version>r&&(r=t.meta.version,n=t);return n}};export{t as WorkflowRegistry};
1
+ //#region src/workflow/spec.ts
2
+ function workflowKey(meta) {
3
+ return `${meta.name}.v${meta.version}`;
4
+ }
5
+ var WorkflowRegistry = class {
6
+ items = /* @__PURE__ */ new Map();
7
+ register(spec) {
8
+ const key = workflowKey(spec.meta);
9
+ if (this.items.has(key)) throw new Error(`Duplicate workflow ${key}`);
10
+ this.items.set(key, spec);
11
+ return this;
12
+ }
13
+ list() {
14
+ return [...this.items.values()];
15
+ }
16
+ get(name, version) {
17
+ if (version != null) return this.items.get(`${name}.v${version}`);
18
+ let candidate;
19
+ let max = -Infinity;
20
+ for (const spec of this.items.values()) {
21
+ if (spec.meta.name !== name) continue;
22
+ if (spec.meta.version > max) {
23
+ max = spec.meta.version;
24
+ candidate = spec;
25
+ }
26
+ }
27
+ return candidate;
28
+ }
29
+ };
30
+
31
+ //#endregion
32
+ export { WorkflowRegistry };
@@ -1 +1,175 @@
1
- var e=class extends Error{constructor(e,t){super(e),this.issues=t,this.name=`WorkflowValidationError`}};function t(e,t={}){let n=[],{definition:a}=e;if(!a.steps.length)return n.push({level:`error`,message:`Workflow must declare at least one step.`}),n;let l=r(a,n),u=a.entryStepId??a.steps[0]?.id??null;u?l.has(u)||n.push({level:`error`,message:`Entry step "${u}" is not defined in steps.`}):n.push({level:`error`,message:`Workflow requires an entry step (definition.entryStepId).`});let d=i(a,l,n);return o(a.steps,t,n),s(u,l,d,n),c(d,n),n}function n(n,r={}){let i=t(n,r);if(i.filter(e=>e.level===`error`).length)throw new e(`Workflow ${n.meta.name}.v${n.meta.version} is invalid`,i)}function r(e,t){let n=new Map;for(let r of e.steps){if(n.has(r.id)){t.push({level:`error`,message:`Duplicate step id "${r.id}" detected.`});continue}n.set(r.id,r),r.type===`automation`&&!r.action?.operation&&t.push({level:`warning`,message:`Automation step "${r.id}" does not declare an operation.`}),r.type===`human`&&!r.action?.form&&t.push({level:`warning`,message:`Human step "${r.id}" does not declare a form.`}),r.guard&&!r.guard.value.trim()&&t.push({level:`error`,message:`Guard for step "${r.id}" must have a non-empty value.`})}return n}function i(e,t,n){let r=new Map,i=new Map;for(let e of t.keys())r.set(e,new Set),i.set(e,0);for(let o of e.transitions){let e=t.get(o.from),s=t.get(o.to);if(!e){n.push({level:`error`,message:`Transition refers to unknown "from" step "${o.from}".`});continue}if(!s){n.push({level:`error`,message:`Transition refers to unknown "to" step "${o.to}".`});continue}r.get(o.from)?.add(o.to),i.set(o.to,(i.get(o.to)??0)+1),a(o,n)}let o=[...i.entries()].filter(([,e])=>e===0).map(([e])=>e);return o.length>1&&n.push({level:`warning`,message:`Workflow has multiple potential entry steps: ${o.join(`, `)}`}),r}function a(e,t){e.condition&&!e.condition.trim()&&t.push({level:`error`,message:`Transition ${e.from} -> ${e.to} declares an empty condition.`})}function o(e,t,n){for(let r of e){let e=r.action;e&&(e.operation&&t.operations&&(t.operations.getSpec(e.operation.name,e.operation.version)||n.push({level:`error`,message:`Step "${r.id}" references unknown operation ${e.operation.name}.v${e.operation.version}.`})),e.form&&t.forms&&(t.forms.get(e.form.key,e.form.version)||n.push({level:`error`,message:`Step "${r.id}" references unknown form ${e.form.key}.v${e.form.version}.`})))}}function s(e,t,n,r){if(!e||!t.has(e))return;let i=new Set,a=[e];for(i.add(e);a.length;){let e=a.shift(),t=n.get(e);if(t)for(let e of t)i.has(e)||(i.add(e),a.push(e))}for(let n of t.keys())i.has(n)||r.push({level:`error`,message:`Step "${n}" is unreachable from entry step "${e}".`})}function c(e,t){let n=new Set,r=new Set,i=!1,a=o=>{if(r.has(o)){i||=(t.push({level:`error`,message:`Workflow contains a cycle involving step "${o}".`}),!0);return}if(n.has(o))return;r.add(o);let s=e.get(o);if(s)for(let e of s)a(e);r.delete(o),n.add(o)};for(let t of e.keys())a(t)}export{e as WorkflowValidationError,n as assertWorkflowSpecValid,t as validateWorkflowSpec};
1
+ //#region src/workflow/validation.ts
2
+ var WorkflowValidationError = class extends Error {
3
+ constructor(message, issues) {
4
+ super(message);
5
+ this.issues = issues;
6
+ this.name = "WorkflowValidationError";
7
+ }
8
+ };
9
+ /**
10
+ * Validate workflow structure, references, and reachability.
11
+ * Returns the collected issues. Consumers may call {@link assertWorkflowSpecValid}
12
+ * to throw on validation errors.
13
+ */
14
+ function validateWorkflowSpec(spec, options = {}) {
15
+ const issues = [];
16
+ const { definition } = spec;
17
+ if (!definition.steps.length) {
18
+ issues.push({
19
+ level: "error",
20
+ message: "Workflow must declare at least one step."
21
+ });
22
+ return issues;
23
+ }
24
+ const stepsById = indexSteps(definition, issues);
25
+ const entryStepId = definition.entryStepId ?? definition.steps[0]?.id ?? null;
26
+ if (!entryStepId) issues.push({
27
+ level: "error",
28
+ message: "Workflow requires an entry step (definition.entryStepId)."
29
+ });
30
+ else if (!stepsById.has(entryStepId)) issues.push({
31
+ level: "error",
32
+ message: `Entry step "${entryStepId}" is not defined in steps.`
33
+ });
34
+ const adjacency = buildAdjacency(definition, stepsById, issues);
35
+ validateStepActions(definition.steps, options, issues);
36
+ validateReachability(entryStepId, stepsById, adjacency, issues);
37
+ detectCycles(adjacency, issues);
38
+ return issues;
39
+ }
40
+ function assertWorkflowSpecValid(spec, options = {}) {
41
+ const issues = validateWorkflowSpec(spec, options);
42
+ if (issues.filter((issue) => issue.level === "error").length) throw new WorkflowValidationError(`Workflow ${spec.meta.name}.v${spec.meta.version} is invalid`, issues);
43
+ }
44
+ function indexSteps(definition, issues) {
45
+ const stepsById = /* @__PURE__ */ new Map();
46
+ for (const step of definition.steps) {
47
+ if (stepsById.has(step.id)) {
48
+ issues.push({
49
+ level: "error",
50
+ message: `Duplicate step id "${step.id}" detected.`
51
+ });
52
+ continue;
53
+ }
54
+ stepsById.set(step.id, step);
55
+ if (step.type === "automation" && !step.action?.operation) issues.push({
56
+ level: "warning",
57
+ message: `Automation step "${step.id}" does not declare an operation.`
58
+ });
59
+ if (step.type === "human" && !step.action?.form) issues.push({
60
+ level: "warning",
61
+ message: `Human step "${step.id}" does not declare a form.`
62
+ });
63
+ if (step.guard && !step.guard.value.trim()) issues.push({
64
+ level: "error",
65
+ message: `Guard for step "${step.id}" must have a non-empty value.`
66
+ });
67
+ }
68
+ return stepsById;
69
+ }
70
+ function buildAdjacency(definition, stepsById, issues) {
71
+ const adjacency = /* @__PURE__ */ new Map();
72
+ const incoming = /* @__PURE__ */ new Map();
73
+ for (const stepId of stepsById.keys()) {
74
+ adjacency.set(stepId, /* @__PURE__ */ new Set());
75
+ incoming.set(stepId, 0);
76
+ }
77
+ for (const transition of definition.transitions) {
78
+ const from = stepsById.get(transition.from);
79
+ const to = stepsById.get(transition.to);
80
+ if (!from) {
81
+ issues.push({
82
+ level: "error",
83
+ message: `Transition refers to unknown "from" step "${transition.from}".`
84
+ });
85
+ continue;
86
+ }
87
+ if (!to) {
88
+ issues.push({
89
+ level: "error",
90
+ message: `Transition refers to unknown "to" step "${transition.to}".`
91
+ });
92
+ continue;
93
+ }
94
+ adjacency.get(transition.from)?.add(transition.to);
95
+ incoming.set(transition.to, (incoming.get(transition.to) ?? 0) + 1);
96
+ validateTransition(transition, issues);
97
+ }
98
+ const roots = [...incoming.entries()].filter(([, count]) => count === 0).map(([id]) => id);
99
+ if (roots.length > 1) issues.push({
100
+ level: "warning",
101
+ message: `Workflow has multiple potential entry steps: ${roots.join(", ")}`
102
+ });
103
+ return adjacency;
104
+ }
105
+ function validateTransition(transition, issues) {
106
+ if (transition.condition && !transition.condition.trim()) issues.push({
107
+ level: "error",
108
+ message: `Transition ${transition.from} -> ${transition.to} declares an empty condition.`
109
+ });
110
+ }
111
+ function validateStepActions(steps, options, issues) {
112
+ for (const step of steps) {
113
+ const action = step.action;
114
+ if (!action) continue;
115
+ if (action.operation && options.operations) {
116
+ if (!options.operations.getSpec(action.operation.name, action.operation.version)) issues.push({
117
+ level: "error",
118
+ message: `Step "${step.id}" references unknown operation ${action.operation.name}.v${action.operation.version}.`
119
+ });
120
+ }
121
+ if (action.form && options.forms) {
122
+ if (!options.forms.get(action.form.key, action.form.version)) issues.push({
123
+ level: "error",
124
+ message: `Step "${step.id}" references unknown form ${action.form.key}.v${action.form.version}.`
125
+ });
126
+ }
127
+ }
128
+ }
129
+ function validateReachability(entryStepId, stepsById, adjacency, issues) {
130
+ if (!entryStepId || !stepsById.has(entryStepId)) return;
131
+ const visited = /* @__PURE__ */ new Set();
132
+ const queue = [entryStepId];
133
+ visited.add(entryStepId);
134
+ while (queue.length) {
135
+ const current = queue.shift();
136
+ const neighbours = adjacency.get(current);
137
+ if (!neighbours) continue;
138
+ for (const next of neighbours) {
139
+ if (visited.has(next)) continue;
140
+ visited.add(next);
141
+ queue.push(next);
142
+ }
143
+ }
144
+ for (const stepId of stepsById.keys()) if (!visited.has(stepId)) issues.push({
145
+ level: "error",
146
+ message: `Step "${stepId}" is unreachable from entry step "${entryStepId}".`
147
+ });
148
+ }
149
+ function detectCycles(adjacency, issues) {
150
+ const visited = /* @__PURE__ */ new Set();
151
+ const stack = /* @__PURE__ */ new Set();
152
+ let cycleReported = false;
153
+ const dfs = (node) => {
154
+ if (stack.has(node)) {
155
+ if (!cycleReported) {
156
+ issues.push({
157
+ level: "error",
158
+ message: `Workflow contains a cycle involving step "${node}".`
159
+ });
160
+ cycleReported = true;
161
+ }
162
+ return;
163
+ }
164
+ if (visited.has(node)) return;
165
+ stack.add(node);
166
+ const neighbours = adjacency.get(node);
167
+ if (neighbours) for (const next of neighbours) dfs(next);
168
+ stack.delete(node);
169
+ visited.add(node);
170
+ };
171
+ for (const node of adjacency.keys()) dfs(node);
172
+ }
173
+
174
+ //#endregion
175
+ export { WorkflowValidationError, assertWorkflowSpecValid, validateWorkflowSpec };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/lib.contracts",
3
- "version": "0.0.0-canary-20251217062943",
3
+ "version": "0.0.0-canary-20251217072406",
4
4
  "scripts": {
5
5
  "publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
6
6
  "publish:pkg:canary": "bun publish:pkg --tag canary",
@@ -16,20 +16,27 @@
16
16
  "test": "bun run"
17
17
  },
18
18
  "devDependencies": {
19
- "@lssm/tool.tsdown": "0.0.0-canary-20251217062943",
20
- "@lssm/tool.typescript": "0.0.0-canary-20251217062943",
19
+ "@lssm/tool.tsdown": "0.0.0-canary-20251217072406",
20
+ "@lssm/tool.typescript": "0.0.0-canary-20251217072406",
21
21
  "@types/express": "^5.0.3",
22
22
  "@types/turndown": "^5.0.6",
23
23
  "tsdown": "^0.17.4",
24
24
  "typescript": "^5.9.3"
25
25
  },
26
26
  "dependencies": {
27
+ "@pothos/core": "^4.9.1",
28
+ "@pothos/plugin-complexity": "^4.1.2",
29
+ "@pothos/plugin-dataloader": "^4.4.2",
30
+ "@pothos/plugin-prisma": "^4.14.0",
31
+ "@pothos/plugin-relay": "^4.4.3",
32
+ "@pothos/plugin-tracing": "^1.1.2",
27
33
  "@aws-sdk/client-secrets-manager": "^3.950.0",
28
34
  "@aws-sdk/client-sqs": "^3.948.0",
29
35
  "@elevenlabs/elevenlabs-js": "^2.27.0",
30
36
  "@google-cloud/secret-manager": "^6.1.1",
31
37
  "@google-cloud/storage": "^7.18.0",
32
- "@lssm/lib.schema": "0.0.0-canary-20251217062943",
38
+ "@lssm/lib.logger": "0.0.0-canary-20251217072406",
39
+ "@lssm/lib.schema": "0.0.0-canary-20251217072406",
33
40
  "@mistralai/mistralai": "^1.2.3",
34
41
  "@modelcontextprotocol/sdk": "^1.24.3",
35
42
  "@qdrant/js-client-rest": "^1.16.2",