@relayflows/surface 2.0.15 → 2.0.17

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 (276) hide show
  1. package/dist/completion.d.ts +3 -2
  2. package/dist/completion.d.ts.map +1 -1
  3. package/dist/completion.js +6 -0
  4. package/dist/completion.js.map +1 -1
  5. package/dist/context.d.ts +17 -0
  6. package/dist/context.d.ts.map +1 -1
  7. package/dist/flow.d.ts.map +1 -1
  8. package/dist/flow.js +19 -4
  9. package/dist/flow.js.map +1 -1
  10. package/dist/index.d.ts +4 -3
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/provider-trigger.d.ts +2 -2
  15. package/dist/provider-trigger.d.ts.map +1 -1
  16. package/dist/provider-trigger.js.map +1 -1
  17. package/dist/schedule.d.ts +76 -0
  18. package/dist/schedule.d.ts.map +1 -0
  19. package/dist/schedule.js +264 -0
  20. package/dist/schedule.js.map +1 -0
  21. package/dist/step.d.ts +20 -6
  22. package/dist/step.d.ts.map +1 -1
  23. package/dist/triggers/airtable.d.ts +13 -0
  24. package/dist/triggers/airtable.d.ts.map +1 -0
  25. package/dist/triggers/airtable.js +32 -0
  26. package/dist/triggers/airtable.js.map +1 -0
  27. package/dist/triggers/asana.d.ts +21 -0
  28. package/dist/triggers/asana.d.ts.map +1 -0
  29. package/dist/triggers/asana.js +56 -0
  30. package/dist/triggers/asana.js.map +1 -0
  31. package/dist/triggers/azure-blob.d.ts +7 -0
  32. package/dist/triggers/azure-blob.d.ts.map +1 -0
  33. package/dist/triggers/azure-blob.js +14 -0
  34. package/dist/triggers/azure-blob.js.map +1 -0
  35. package/dist/triggers/box.d.ts +7 -0
  36. package/dist/triggers/box.d.ts.map +1 -0
  37. package/dist/triggers/box.js +14 -0
  38. package/dist/triggers/box.js.map +1 -0
  39. package/dist/triggers/calendly.d.ts +16 -0
  40. package/dist/triggers/calendly.d.ts.map +1 -0
  41. package/dist/triggers/calendly.js +41 -0
  42. package/dist/triggers/calendly.js.map +1 -0
  43. package/dist/triggers/clickup.d.ts +16 -0
  44. package/dist/triggers/clickup.d.ts.map +1 -0
  45. package/dist/triggers/clickup.js +41 -0
  46. package/dist/triggers/clickup.js.map +1 -0
  47. package/dist/triggers/cloudflare.d.ts +12 -0
  48. package/dist/triggers/cloudflare.d.ts.map +1 -0
  49. package/dist/triggers/cloudflare.js +29 -0
  50. package/dist/triggers/cloudflare.js.map +1 -0
  51. package/dist/triggers/confluence.d.ts +10 -0
  52. package/dist/triggers/confluence.d.ts.map +1 -0
  53. package/dist/triggers/confluence.js +23 -0
  54. package/dist/triggers/confluence.js.map +1 -0
  55. package/dist/triggers/daytona.d.ts +11 -0
  56. package/dist/triggers/daytona.d.ts.map +1 -0
  57. package/dist/triggers/daytona.js +26 -0
  58. package/dist/triggers/daytona.js.map +1 -0
  59. package/dist/triggers/docker-hub.d.ts +5 -0
  60. package/dist/triggers/docker-hub.d.ts.map +1 -0
  61. package/dist/triggers/docker-hub.js +8 -0
  62. package/dist/triggers/docker-hub.js.map +1 -0
  63. package/dist/triggers/dropbox.d.ts +5 -0
  64. package/dist/triggers/dropbox.d.ts.map +1 -0
  65. package/dist/triggers/dropbox.js +8 -0
  66. package/dist/triggers/dropbox.js.map +1 -0
  67. package/dist/triggers/fathom.d.ts +5 -0
  68. package/dist/triggers/fathom.d.ts.map +1 -0
  69. package/dist/triggers/fathom.js +8 -0
  70. package/dist/triggers/fathom.js.map +1 -0
  71. package/dist/triggers/gcp.d.ts +13 -0
  72. package/dist/triggers/gcp.d.ts.map +1 -0
  73. package/dist/triggers/gcp.js +32 -0
  74. package/dist/triggers/gcp.js.map +1 -0
  75. package/dist/triggers/gcs.d.ts +7 -0
  76. package/dist/triggers/gcs.d.ts.map +1 -0
  77. package/dist/triggers/gcs.js +14 -0
  78. package/dist/triggers/gcs.js.map +1 -0
  79. package/dist/triggers/github.d.ts +22 -0
  80. package/dist/triggers/github.d.ts.map +1 -1
  81. package/dist/triggers/github.js +66 -0
  82. package/dist/triggers/github.js.map +1 -1
  83. package/dist/triggers/gitlab.d.ts +57 -0
  84. package/dist/triggers/gitlab.d.ts.map +1 -0
  85. package/dist/triggers/gitlab.js +164 -0
  86. package/dist/triggers/gitlab.js.map +1 -0
  87. package/dist/triggers/gmail.d.ts +7 -0
  88. package/dist/triggers/gmail.d.ts.map +1 -0
  89. package/dist/triggers/gmail.js +14 -0
  90. package/dist/triggers/gmail.js.map +1 -0
  91. package/dist/triggers/google-calendar.d.ts +7 -0
  92. package/dist/triggers/google-calendar.d.ts.map +1 -0
  93. package/dist/triggers/google-calendar.js +14 -0
  94. package/dist/triggers/google-calendar.js.map +1 -0
  95. package/dist/triggers/google-drive.d.ts +7 -0
  96. package/dist/triggers/google-drive.d.ts.map +1 -0
  97. package/dist/triggers/google-drive.js +14 -0
  98. package/dist/triggers/google-drive.js.map +1 -0
  99. package/dist/triggers/granola.d.ts +8 -0
  100. package/dist/triggers/granola.d.ts.map +1 -0
  101. package/dist/triggers/granola.js +17 -0
  102. package/dist/triggers/granola.js.map +1 -0
  103. package/dist/triggers/hubspot.d.ts +24 -0
  104. package/dist/triggers/hubspot.d.ts.map +1 -0
  105. package/dist/triggers/hubspot.js +65 -0
  106. package/dist/triggers/hubspot.js.map +1 -0
  107. package/dist/triggers/index.d.ts +92 -2
  108. package/dist/triggers/index.d.ts.map +1 -1
  109. package/dist/triggers/index.js +92 -2
  110. package/dist/triggers/index.js.map +1 -1
  111. package/dist/triggers/intercom.d.ts +22 -0
  112. package/dist/triggers/intercom.d.ts.map +1 -0
  113. package/dist/triggers/intercom.js +59 -0
  114. package/dist/triggers/intercom.js.map +1 -0
  115. package/dist/triggers/jira.d.ts +16 -0
  116. package/dist/triggers/jira.d.ts.map +1 -0
  117. package/dist/triggers/jira.js +41 -0
  118. package/dist/triggers/jira.js.map +1 -0
  119. package/dist/triggers/linear.d.ts +37 -0
  120. package/dist/triggers/linear.d.ts.map +1 -0
  121. package/dist/triggers/linear.js +104 -0
  122. package/dist/triggers/linear.js.map +1 -0
  123. package/dist/triggers/mailgun.d.ts +19 -0
  124. package/dist/triggers/mailgun.d.ts.map +1 -0
  125. package/dist/triggers/mailgun.js +50 -0
  126. package/dist/triggers/mailgun.js.map +1 -0
  127. package/dist/triggers/mixpanel.d.ts +16 -0
  128. package/dist/triggers/mixpanel.d.ts.map +1 -0
  129. package/dist/triggers/mixpanel.js +41 -0
  130. package/dist/triggers/mixpanel.js.map +1 -0
  131. package/dist/triggers/neon.d.ts +9 -0
  132. package/dist/triggers/neon.d.ts.map +1 -0
  133. package/dist/triggers/neon.js +20 -0
  134. package/dist/triggers/neon.js.map +1 -0
  135. package/dist/triggers/notion.d.ts +17 -0
  136. package/dist/triggers/notion.d.ts.map +1 -0
  137. package/dist/triggers/notion.js +44 -0
  138. package/dist/triggers/notion.js.map +1 -0
  139. package/dist/triggers/onedrive.d.ts +7 -0
  140. package/dist/triggers/onedrive.d.ts.map +1 -0
  141. package/dist/triggers/onedrive.js +14 -0
  142. package/dist/triggers/onedrive.js.map +1 -0
  143. package/dist/triggers/pipedrive.d.ts +18 -0
  144. package/dist/triggers/pipedrive.d.ts.map +1 -0
  145. package/dist/triggers/pipedrive.js +47 -0
  146. package/dist/triggers/pipedrive.js.map +1 -0
  147. package/dist/triggers/postgres.d.ts +7 -0
  148. package/dist/triggers/postgres.d.ts.map +1 -0
  149. package/dist/triggers/postgres.js +14 -0
  150. package/dist/triggers/postgres.js.map +1 -0
  151. package/dist/triggers/posthog.d.ts +6 -0
  152. package/dist/triggers/posthog.d.ts.map +1 -0
  153. package/dist/triggers/posthog.js +11 -0
  154. package/dist/triggers/posthog.js.map +1 -0
  155. package/dist/triggers/ramp.d.ts +51 -0
  156. package/dist/triggers/ramp.d.ts.map +1 -0
  157. package/dist/triggers/ramp.js +146 -0
  158. package/dist/triggers/ramp.js.map +1 -0
  159. package/dist/triggers/recall.d.ts +7 -0
  160. package/dist/triggers/recall.d.ts.map +1 -0
  161. package/dist/triggers/recall.js +14 -0
  162. package/dist/triggers/recall.js.map +1 -0
  163. package/dist/triggers/redis.d.ts +7 -0
  164. package/dist/triggers/redis.d.ts.map +1 -0
  165. package/dist/triggers/redis.js +14 -0
  166. package/dist/triggers/redis.js.map +1 -0
  167. package/dist/triggers/s3.d.ts +7 -0
  168. package/dist/triggers/s3.d.ts.map +1 -0
  169. package/dist/triggers/s3.js +14 -0
  170. package/dist/triggers/s3.js.map +1 -0
  171. package/dist/triggers/salesforce.d.ts +26 -0
  172. package/dist/triggers/salesforce.d.ts.map +1 -0
  173. package/dist/triggers/salesforce.js +71 -0
  174. package/dist/triggers/salesforce.js.map +1 -0
  175. package/dist/triggers/segment.d.ts +16 -0
  176. package/dist/triggers/segment.d.ts.map +1 -0
  177. package/dist/triggers/segment.js +41 -0
  178. package/dist/triggers/segment.js.map +1 -0
  179. package/dist/triggers/sendgrid.d.ts +21 -0
  180. package/dist/triggers/sendgrid.d.ts.map +1 -0
  181. package/dist/triggers/sendgrid.js +56 -0
  182. package/dist/triggers/sendgrid.js.map +1 -0
  183. package/dist/triggers/sharepoint.d.ts +7 -0
  184. package/dist/triggers/sharepoint.d.ts.map +1 -0
  185. package/dist/triggers/sharepoint.js +14 -0
  186. package/dist/triggers/sharepoint.js.map +1 -0
  187. package/dist/triggers/shopify.d.ts +28 -0
  188. package/dist/triggers/shopify.d.ts.map +1 -0
  189. package/dist/triggers/shopify.js +77 -0
  190. package/dist/triggers/shopify.js.map +1 -0
  191. package/dist/triggers/shortcut.d.ts +10 -0
  192. package/dist/triggers/shortcut.d.ts.map +1 -0
  193. package/dist/triggers/shortcut.js +23 -0
  194. package/dist/triggers/shortcut.js.map +1 -0
  195. package/dist/triggers/slack.d.ts +17 -0
  196. package/dist/triggers/slack.d.ts.map +1 -1
  197. package/dist/triggers/slack.js +51 -0
  198. package/dist/triggers/slack.js.map +1 -1
  199. package/dist/triggers/stripe.d.ts +25 -0
  200. package/dist/triggers/stripe.d.ts.map +1 -0
  201. package/dist/triggers/stripe.js +68 -0
  202. package/dist/triggers/stripe.js.map +1 -0
  203. package/dist/triggers/teams.d.ts +24 -0
  204. package/dist/triggers/teams.d.ts.map +1 -0
  205. package/dist/triggers/teams.js +65 -0
  206. package/dist/triggers/teams.js.map +1 -0
  207. package/dist/triggers/telegram.d.ts +29 -0
  208. package/dist/triggers/telegram.d.ts.map +1 -0
  209. package/dist/triggers/telegram.js +80 -0
  210. package/dist/triggers/telegram.js.map +1 -0
  211. package/dist/triggers/zendesk.d.ts +13 -0
  212. package/dist/triggers/zendesk.d.ts.map +1 -0
  213. package/dist/triggers/zendesk.js +32 -0
  214. package/dist/triggers/zendesk.js.map +1 -0
  215. package/dist/triggers.d.ts +5 -2
  216. package/dist/triggers.d.ts.map +1 -1
  217. package/dist/triggers.js.map +1 -1
  218. package/package.json +1 -1
  219. package/src/completion.ts +8 -2
  220. package/src/context.ts +18 -0
  221. package/src/flow.ts +17 -3
  222. package/src/index.ts +7 -2
  223. package/src/provider-trigger.ts +2 -2
  224. package/src/schedule.ts +282 -0
  225. package/src/step.ts +22 -6
  226. package/src/triggers/PROVIDERS.md +56 -0
  227. package/src/triggers/README.md +84 -8
  228. package/src/triggers/airtable.ts +34 -0
  229. package/src/triggers/asana.ts +58 -0
  230. package/src/triggers/azure-blob.ts +16 -0
  231. package/src/triggers/box.ts +16 -0
  232. package/src/triggers/calendly.ts +43 -0
  233. package/src/triggers/clickup.ts +43 -0
  234. package/src/triggers/cloudflare.ts +31 -0
  235. package/src/triggers/confluence.ts +25 -0
  236. package/src/triggers/daytona.ts +28 -0
  237. package/src/triggers/docker-hub.ts +10 -0
  238. package/src/triggers/dropbox.ts +10 -0
  239. package/src/triggers/fathom.ts +10 -0
  240. package/src/triggers/gcp.ts +34 -0
  241. package/src/triggers/gcs.ts +16 -0
  242. package/src/triggers/github.ts +66 -0
  243. package/src/triggers/gitlab.ts +166 -0
  244. package/src/triggers/gmail.ts +16 -0
  245. package/src/triggers/google-calendar.ts +16 -0
  246. package/src/triggers/google-drive.ts +16 -0
  247. package/src/triggers/granola.ts +19 -0
  248. package/src/triggers/hubspot.ts +67 -0
  249. package/src/triggers/index.ts +92 -2
  250. package/src/triggers/intercom.ts +61 -0
  251. package/src/triggers/jira.ts +43 -0
  252. package/src/triggers/linear.ts +106 -0
  253. package/src/triggers/mailgun.ts +52 -0
  254. package/src/triggers/mixpanel.ts +43 -0
  255. package/src/triggers/neon.ts +22 -0
  256. package/src/triggers/notion.ts +46 -0
  257. package/src/triggers/onedrive.ts +16 -0
  258. package/src/triggers/pipedrive.ts +49 -0
  259. package/src/triggers/postgres.ts +16 -0
  260. package/src/triggers/posthog.ts +13 -0
  261. package/src/triggers/ramp.ts +148 -0
  262. package/src/triggers/recall.ts +16 -0
  263. package/src/triggers/redis.ts +16 -0
  264. package/src/triggers/s3.ts +16 -0
  265. package/src/triggers/salesforce.ts +73 -0
  266. package/src/triggers/segment.ts +43 -0
  267. package/src/triggers/sendgrid.ts +58 -0
  268. package/src/triggers/sharepoint.ts +16 -0
  269. package/src/triggers/shopify.ts +79 -0
  270. package/src/triggers/shortcut.ts +25 -0
  271. package/src/triggers/slack.ts +51 -0
  272. package/src/triggers/stripe.ts +70 -0
  273. package/src/triggers/teams.ts +67 -0
  274. package/src/triggers/telegram.ts +82 -0
  275. package/src/triggers/zendesk.ts +34 -0
  276. package/src/triggers.ts +7 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zendesk.d.ts","sourceRoot":"","sources":["../../src/triggers/zendesk.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,eAAO,MAAM,OAAO;kCACY,aAAa;kCAGb,aAAa;kCAGb,aAAa;4BAGnB,aAAa;4BAGb,aAAa;4BAGb,aAAa;0BAGf,aAAa;0BAGb,aAAa;0BAGb,aAAa;EAGnC,CAAC"}
@@ -0,0 +1,32 @@
1
+ // GENERATED by scripts/generate-triggers.mjs — do not edit.
2
+ import { providerTrigger } from "../provider-trigger.js";
3
+ export const zendesk = Object.freeze({
4
+ organization_created(filter) {
5
+ return providerTrigger("zendesk", "organization.created", filter);
6
+ },
7
+ organization_deleted(filter) {
8
+ return providerTrigger("zendesk", "organization.deleted", filter);
9
+ },
10
+ organization_updated(filter) {
11
+ return providerTrigger("zendesk", "organization.updated", filter);
12
+ },
13
+ ticket_created(filter) {
14
+ return providerTrigger("zendesk", "ticket.created", filter);
15
+ },
16
+ ticket_deleted(filter) {
17
+ return providerTrigger("zendesk", "ticket.deleted", filter);
18
+ },
19
+ ticket_updated(filter) {
20
+ return providerTrigger("zendesk", "ticket.updated", filter);
21
+ },
22
+ user_created(filter) {
23
+ return providerTrigger("zendesk", "user.created", filter);
24
+ },
25
+ user_deleted(filter) {
26
+ return providerTrigger("zendesk", "user.deleted", filter);
27
+ },
28
+ user_updated(filter) {
29
+ return providerTrigger("zendesk", "user.updated", filter);
30
+ },
31
+ });
32
+ //# sourceMappingURL=zendesk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zendesk.js","sourceRoot":"","sources":["../../src/triggers/zendesk.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAE5D,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAGzD,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC;IACnC,oBAAoB,CAAC,MAAsB;QACzC,OAAO,eAAe,CAAC,SAAS,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;IACD,oBAAoB,CAAC,MAAsB;QACzC,OAAO,eAAe,CAAC,SAAS,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;IACD,oBAAoB,CAAC,MAAsB;QACzC,OAAO,eAAe,CAAC,SAAS,EAAE,sBAAsB,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC;IACD,cAAc,CAAC,MAAsB;QACnC,OAAO,eAAe,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC;IACD,cAAc,CAAC,MAAsB;QACnC,OAAO,eAAe,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC;IACD,cAAc,CAAC,MAAsB;QACnC,OAAO,eAAe,CAAC,SAAS,EAAE,gBAAgB,EAAE,MAAM,CAAC,CAAC;IAC9D,CAAC;IACD,YAAY,CAAC,MAAsB;QACjC,OAAO,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,YAAY,CAAC,MAAsB;QACjC,OAAO,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;IACD,YAAY,CAAC,MAAsB;QACjC,OAAO,eAAe,CAAC,SAAS,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;IAC5D,CAAC;CACF,CAAC,CAAC"}
@@ -1,3 +1,4 @@
1
+ import type { ScheduleTriggerSource } from "./schedule.js";
1
2
  export type WebhookValue = null | boolean | number | string | readonly WebhookValue[] | {
2
3
  readonly [key: string]: WebhookValue;
3
4
  };
@@ -5,11 +6,13 @@ export type WebhookValue = null | boolean | number | string | readonly WebhookVa
5
6
  export type WebhookFilter = {
6
7
  readonly [key: string]: WebhookValue;
7
8
  };
8
- export interface TriggerSource {
9
+ export interface WebhookTriggerSource {
9
10
  readonly kind: "webhook";
10
11
  readonly name: string;
11
12
  readonly filter?: WebhookFilter;
12
13
  }
14
+ /** A webhook inbox subscription, or a `schedule.*` tick subscription. */
15
+ export type TriggerSource = WebhookTriggerSource | ScheduleTriggerSource;
13
16
  /** Plain, immutable data. Constructing a source opens no receiver. */
14
- export declare function webhook(name: string, filter?: WebhookFilter): TriggerSource;
17
+ export declare function webhook(name: string, filter?: WebhookFilter): WebhookTriggerSource;
15
18
  //# sourceMappingURL=triggers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GACvD,SAAS,YAAY,EAAE,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAEvE,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAErE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;CACjC;AAED,sEAAsE;AACtE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,aAAa,CAS3E"}
1
+ {"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GACvD,SAAS,YAAY,EAAE,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAEvE,sEAAsE;AACtE,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAAA;CAAE,CAAC;AAErE,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;CACjC;AAED,yEAAyE;AACzE,MAAM,MAAM,aAAa,GAAG,oBAAoB,GAAG,qBAAqB,CAAC;AAEzE,sEAAsE;AACtE,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,GAAG,oBAAoB,CASlF"}
@@ -1 +1 @@
1
- {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@relayflows/surface",
3
- "version": "2.0.15",
3
+ "version": "2.0.17",
4
4
  "description": "TypeScript authoring surface for Relayflows.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/completion.ts CHANGED
@@ -23,5 +23,11 @@ export const RUN_COMPLETION_REASONS = [
23
23
 
24
24
  export type RunCompletionReason = (typeof RUN_COMPLETION_REASONS)[number];
25
25
 
26
- /** Authored outcomes include a human handoff; it is not a kernel terminal reason. */
27
- export type FlowCompletionReason = RunCompletionReason | 'needs_human';
26
+ /** Authored verdicts include handoff and declination without widening kernel facts. */
27
+ export const FLOW_COMPLETION_REASONS = [
28
+ ...RUN_COMPLETION_REASONS,
29
+ 'needs_human',
30
+ 'declined',
31
+ ] as const;
32
+
33
+ export type FlowCompletionReason = (typeof FLOW_COMPLETION_REASONS)[number];
package/src/context.ts CHANGED
@@ -6,12 +6,30 @@ import type { Step } from "./step.js";
6
6
 
7
7
  export interface AgentResult {
8
8
  summary: string;
9
+ /**
10
+ * Files the agent created or changed under its working directory,
11
+ * cwd-relative POSIX paths, sorted — as journaled by the worker that spawned
12
+ * the CLI on the step's `step.completed`, never re-measured later. Empty
13
+ * for the relay transport (the agent ran elsewhere) and for an agent whose
14
+ * final message is a JSON object (that object is the output, unmodified).
15
+ */
9
16
  artifacts: string[];
10
17
  }
11
18
 
19
+ /** Per-step declarations: validated and recorded, not currently enforced (gate 8 / #442).
20
+ * Separate from flow-wide FlowHeader.workspace / tools.fs scopes.
21
+ */
22
+ export interface PermissionsSpec {
23
+ fileGlobs?: string[];
24
+ networkAllowlist?: string[];
25
+ accessPreset?: 'readonly' | 'readwrite';
26
+ }
27
+
12
28
  export interface AgentOptions {
13
29
  task: string;
14
30
  workspace?: string;
31
+ /** Validated declaration only; not currently enforced (gate 8 / #442). */
32
+ permissions?: PermissionsSpec;
15
33
  cli?: string;
16
34
  model?: string;
17
35
  /** Working directory for the CLI subprocess; defaults to the flow-runner's cwd. */
package/src/flow.ts CHANGED
@@ -3,6 +3,7 @@ import type { Helpers } from "./helpers/index.js";
3
3
  type HelperTools = Partial<Record<keyof Helpers, boolean>>;
4
4
  import type { Ctx } from "./context.js";
5
5
  import { webhook, type TriggerSource } from "./triggers.js";
6
+ import { schedule } from "./schedule.js";
6
7
 
7
8
  /** Optional escalation header; the empty header is the common case. */
8
9
  export interface FlowHeader {
@@ -91,9 +92,22 @@ function makeHandle(definition: AuthoredFlowDefinition): FlowHandle {
91
92
  value: <Event>(trigger: TriggerSource, body: FlowBody<Event>): TriggeredFlowHandle => {
92
93
  if (typeof body !== "function") throw new TypeError("trigger handler requires a body");
93
94
  assertHeaderObject(trigger, "trigger");
94
- assertKnownKeys(trigger, ["kind", "name", "filter"], "trigger");
95
- if (trigger.kind !== "webhook") throw new TypeError("unsupported trigger kind");
96
- const source = webhook(trigger.name, trigger.filter);
95
+ let source: TriggerSource;
96
+ if (trigger.kind === "schedule") {
97
+ assertKnownKeys(trigger, ["kind", "name", "cron", "tz", "intervalMs", "epochMs"], "trigger");
98
+ // Re-derive from the declaration rather than trusting the object: the
99
+ // parsed form is what the SDK lowers, so it must be one this module made.
100
+ source = trigger.cron !== undefined
101
+ ? schedule.cron(trigger.cron, trigger.tz === undefined ? {} : { tz: trigger.tz })
102
+ : schedule.every(`${Math.round((trigger.intervalMs ?? 0) / 1000)}s`);
103
+ if (source.intervalMs !== trigger.intervalMs || source.epochMs !== trigger.epochMs) {
104
+ throw new TypeError("schedule trigger grid does not match its declaration");
105
+ }
106
+ } else {
107
+ assertKnownKeys(trigger, ["kind", "name", "filter"], "trigger");
108
+ if (trigger.kind !== "webhook") throw new TypeError("unsupported trigger kind");
109
+ source = webhook(trigger.name, trigger.filter);
110
+ }
97
111
  return makeHandle(Object.freeze({
98
112
  ...definition,
99
113
  handlers: Object.freeze([...definition.handlers, Object.freeze({ trigger: source, body: body as FlowBody })]),
package/src/index.ts CHANGED
@@ -7,10 +7,11 @@ export type {
7
7
  WorkerSummary,
8
8
  CloudHelper,
9
9
  } from "./cloud.js";
10
- export type { AgentOptions, AgentResult, LlmOptions, Ctx } from "./context.js";
10
+ export type { AgentOptions, AgentResult, PermissionsSpec, LlmOptions, Ctx } from "./context.js";
11
11
  export {
12
12
  COMPLETION_REASONS,
13
13
  RUN_COMPLETION_REASONS,
14
+ FLOW_COMPLETION_REASONS,
14
15
  type CompletionReason,
15
16
  type RunCompletionReason,
16
17
  type FlowCompletionReason,
@@ -40,7 +41,11 @@ export {
40
41
  } from "./slack.js";
41
42
  export type { Helpers } from "./helpers/index.js";
42
43
  export type { MemoryHelper, MemoryFinding, MemoryRecallOptions, HistoryEntry, TrajectoryEntry } from "./memory.js";
43
- export { webhook, type TriggerSource, type WebhookFilter, type WebhookValue } from "./triggers.js";
44
+ export { webhook, type TriggerSource, type WebhookTriggerSource, type WebhookFilter, type WebhookValue } from "./triggers.js";
45
+ export {
46
+ schedule, scheduleIdFor, parseCron, cronGrid, cronFixedIntervalMs, cronMaxGapMs, everyToMs,
47
+ type ScheduleTriggerSource, type ScheduleCronOptions, type CronFields, type CronGrid,
48
+ } from "./schedule.js";
44
49
  export * from "./triggers/index.js";
45
50
  export type { ProviderTriggerSource } from "./provider-trigger.js";
46
51
  export type { PluginMethod, PluginPrimitive } from './plugin-contract.js';
@@ -1,7 +1,7 @@
1
- import { webhook, type TriggerSource, type WebhookFilter } from "./triggers.js";
1
+ import { webhook, type WebhookTriggerSource, type WebhookFilter } from "./triggers.js";
2
2
 
3
3
  /** A provider inbox subscription over an envelope's type and payload. */
4
- export interface ProviderTriggerSource<Provider extends string, Event extends string> extends TriggerSource {
4
+ export interface ProviderTriggerSource<Provider extends string, Event extends string> extends WebhookTriggerSource {
5
5
  readonly name: Provider;
6
6
  readonly filter: WebhookFilter & { readonly provider: Provider; readonly type: Event };
7
7
  }
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Schedule triggers. Hand-written, unlike the provider namespaces under
3
+ * `triggers/`, because a schedule is not a provider event: there is no inbox
4
+ * and no upstream mapping to generate from. A schedule is an event source —
5
+ * locally the `flows tick` runner, on Cloud a relaycron cron — that submits
6
+ * `flows.tick` events, and this namespace declares which ticks a flow wants.
7
+ *
8
+ * Constructing a source opens nothing. The SDK lowers it to the same
9
+ * `flows.tick` subscription `testdata/tick-heartbeat.flow.yaml` writes by
10
+ * hand (`scheduleTriggerSpec`), and `flows schedule` sends the cron to Cloud.
11
+ */
12
+
13
+ export interface ScheduleTriggerSource {
14
+ readonly kind: "schedule";
15
+ /** Fixed: every schedule is delivered as a `flows.tick` event. */
16
+ readonly name: "flows.tick";
17
+ /** A 5-field cron expression, when declared with `schedule.cron`. */
18
+ readonly cron?: string;
19
+ /** IANA zone for `cron`; defaults to UTC. */
20
+ readonly tz?: string;
21
+ /** Fixed interval in milliseconds, when declared with `schedule.every` or when `cron` is exactly a tick grid. */
22
+ readonly intervalMs?: number;
23
+ /** Phase of that grid: the first fire is `epochMs` past the Unix epoch; present exactly when `intervalMs` is. */
24
+ readonly epochMs?: number;
25
+ }
26
+
27
+ export interface ScheduleCronOptions {
28
+ readonly tz?: string;
29
+ }
30
+
31
+ const EVERY = /^(\d+)(s|m|h|d)$/u;
32
+ const UNIT_MS = { s: 1_000, m: 60_000, h: 3_600_000, d: 86_400_000 } as const;
33
+
34
+ /** `every("5m")` — a fixed interval. Units: s, m, h, d. Minimum one second. */
35
+ export function everyToMs(value: string): number {
36
+ const match = typeof value === "string" ? EVERY.exec(value.trim()) : null;
37
+ if (!match) throw new TypeError(`schedule.every expects <n><s|m|h|d>, got ${JSON.stringify(value)}`);
38
+ const ms = Number(match[1]) * UNIT_MS[match[2] as keyof typeof UNIT_MS];
39
+ if (!Number.isSafeInteger(ms) || ms < 1_000) throw new TypeError("schedule.every must be at least 1s");
40
+ return ms;
41
+ }
42
+
43
+ export interface CronFields {
44
+ readonly minute: string;
45
+ readonly hour: string;
46
+ readonly dayOfMonth: string;
47
+ readonly month: string;
48
+ readonly dayOfWeek: string;
49
+ }
50
+
51
+ const FIELD_RANGES = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 7]] as const;
52
+ const NAMES: Record<number, readonly string[]> = {
53
+ 3: ["jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"],
54
+ 4: ["sun", "mon", "tue", "wed", "thu", "fri", "sat"],
55
+ };
56
+
57
+ /**
58
+ * Standard five-field cron. Accepts `*`, values, ranges, lists and `/step`,
59
+ * plus month and weekday names; refuses anything outside each field's range.
60
+ * Validation, not evaluation — the schedule's clock is the runner's.
61
+ */
62
+ export function parseCron(expression: string): CronFields {
63
+ const fields = typeof expression === "string" ? expression.trim().split(/\s+/u) : [];
64
+ if (fields.length !== 5) {
65
+ throw new TypeError(`cron expression must have five fields (minute hour day-of-month month day-of-week), got ${JSON.stringify(expression)}`);
66
+ }
67
+ fields.forEach((field, index) => {
68
+ const [low, high] = FIELD_RANGES[index]!;
69
+ for (const part of field.split(",")) {
70
+ const pieces = part.split("/");
71
+ if (pieces.length > 2 || part.length === 0) throw new TypeError(`cron field ${index + 1}: invalid ${JSON.stringify(part)}`);
72
+ const [range, step] = pieces;
73
+ if (step !== undefined && (!/^\d+$/u.test(step) || Number(step) < 1)) {
74
+ throw new TypeError(`cron field ${index + 1}: invalid step in ${JSON.stringify(part)}`);
75
+ }
76
+ if (range === "*") continue;
77
+ const bounds = range!.split("-");
78
+ if (bounds.length > 2) throw new TypeError(`cron field ${index + 1}: invalid range ${JSON.stringify(part)}`);
79
+ for (const bound of bounds) {
80
+ // Month names are 1-based (jan = 1); weekday names are 0-based (sun = 0).
81
+ const named = NAMES[index]?.indexOf(bound.toLowerCase());
82
+ const value = /^\d+$/u.test(bound) ? Number(bound)
83
+ : named === undefined || named === -1 ? undefined : named + (index === 3 ? 1 : 0);
84
+ if (value === undefined || value < low || value > high) {
85
+ throw new TypeError(`cron field ${index + 1}: ${JSON.stringify(bound)} is outside ${low}-${high}`);
86
+ }
87
+ }
88
+ }
89
+ });
90
+ return Object.freeze({
91
+ minute: fields[0]!, hour: fields[1]!, dayOfMonth: fields[2]!, month: fields[3]!, dayOfWeek: fields[4]!,
92
+ });
93
+ }
94
+
95
+ /** A tick grid that reproduces a cron exactly: fire every `intervalMs`, phase-aligned at `epochMs` past the Unix epoch. */
96
+ export interface CronGrid {
97
+ readonly intervalMs: number;
98
+ readonly epochMs: number;
99
+ }
100
+
101
+ // The tick grid a cron expression amounts to, when one reproduces it exactly.
102
+ // The tick source fires at epochMs + k*intervalMs, so a cron is representable
103
+ // only when its period divides the next field's cycle (every N minutes with
104
+ // 60 % N == 0, every N hours with 24 % N == 0) and its phase is a single
105
+ // fixed value in the finer fields. `*/7 * * * *` is not (cron restarts the
106
+ // minute count each hour, a grid does not); `15 * * * *` is, with a 15-minute
107
+ // phase. Anything with day, month or weekday constraints, lists or ranges is
108
+ // not a grid — only a cron-aware runner (Cloud's relaycron) can drive it.
109
+ // Time zones: a grid is anchored in UTC, so only UTC schedules qualify; an
110
+ // offset zone would shift the phase and a DST zone would move it twice a year.
111
+ export function cronGrid(fields: CronFields, tz?: string): CronGrid | undefined {
112
+ const { minute, hour, dayOfMonth, month, dayOfWeek } = fields;
113
+ if (dayOfMonth !== "*" || month !== "*" || dayOfWeek !== "*") return undefined;
114
+ if (tz !== undefined && tz !== "UTC" && tz !== "Etc/UTC") return undefined;
115
+ const every = (field: string, cycle: number): number | undefined => {
116
+ if (field === "*") return 1;
117
+ const match = /^\*\/(\d+)$/u.exec(field);
118
+ if (!match) return undefined;
119
+ const step = Number(match[1]);
120
+ return step >= 1 && cycle % step === 0 ? step : undefined;
121
+ };
122
+ const fixed = (field: string): number | undefined => (/^\d+$/u.test(field) ? Number(field) : undefined);
123
+ const minuteStep = every(minute, 60);
124
+ if (minuteStep !== undefined && hour === "*") return { intervalMs: minuteStep * UNIT_MS.m, epochMs: 0 };
125
+ const minutePhase = fixed(minute);
126
+ const hourStep = every(hour, 24);
127
+ if (minutePhase !== undefined && hourStep !== undefined) {
128
+ return { intervalMs: hourStep * UNIT_MS.h, epochMs: minutePhase * UNIT_MS.m };
129
+ }
130
+ const hourPhase = fixed(hour);
131
+ if (minutePhase !== undefined && hourPhase !== undefined) {
132
+ return { intervalMs: UNIT_MS.d, epochMs: hourPhase * UNIT_MS.h + minutePhase * UNIT_MS.m };
133
+ }
134
+ return undefined;
135
+ }
136
+
137
+ /** The fixed interval of a cron, when `cronGrid` finds one. Kept for callers that only need the period. */
138
+ export function cronFixedIntervalMs(fields: CronFields, tz?: string): number | undefined {
139
+ return cronGrid(fields, tz)?.intervalMs;
140
+ }
141
+
142
+ function cronFieldMatches(field: string, value: number, index: number): boolean {
143
+ const [low, high] = FIELD_RANGES[index]!;
144
+ const named = (bound: string): number => {
145
+ if (/^\d+$/u.test(bound)) return Number(bound);
146
+ return NAMES[index]!.indexOf(bound.toLowerCase()) + (index === 3 ? 1 : 0);
147
+ };
148
+ return field.split(",").some((part) => {
149
+ const [range, step] = part.split("/");
150
+ const stride = step === undefined ? 1 : Number(step);
151
+ let from: number;
152
+ let to: number;
153
+ // `N/step` runs from N to the field's maximum — for weekdays that is 7,
154
+ // so `1/2` reaches Sunday-as-7 and the normalisation below applies.
155
+ if (range === "*") { from = low; to = index === 4 ? 6 : high; }
156
+ else {
157
+ const bounds = range!.split("-").map(named);
158
+ from = bounds[0]!;
159
+ to = bounds.length === 2 ? bounds[1]! : step === undefined ? bounds[0]! : high;
160
+ }
161
+ // Weekday 7 is Sunday, as 0 is. A lone `7` or a range ending in 7 is
162
+ // tested against Sunday-as-0 as well, so a stride counted from the
163
+ // range start still lands on it: `1-7/2` fires Mon, Wed, Fri, Sun.
164
+ if (index === 4 && to === 7) {
165
+ if (from === 7) return value === 0;
166
+ if (value === 0 && (7 - from) % stride === 0) return true;
167
+ to = 6;
168
+ }
169
+ return value >= from && value <= to && (value - from) % stride === 0;
170
+ });
171
+ }
172
+
173
+ /**
174
+ * The longest gap between consecutive fires over two calendar years (one of
175
+ * them leap), in milliseconds — a cron's natural quiet period. Evaluated on
176
+ * the UTC calendar minute by minute; a zone offset does not change gap
177
+ * lengths, and a DST shift changes one gap by at most an hour, which the
178
+ * callers' multiple absorbs. An expression that fires at most once in the
179
+ * span reports the whole span. Returns undefined when it never fires.
180
+ */
181
+ export function cronMaxGapMs(fields: CronFields): number | undefined {
182
+ const start = Date.UTC(2024, 0, 1);
183
+ const end = Date.UTC(2026, 0, 1);
184
+ let previous: number | undefined;
185
+ let first: number | undefined;
186
+ let maxGap = 0;
187
+ for (let t = start; t < end; t += UNIT_MS.m) {
188
+ const d = new Date(t);
189
+ const dom = fields.dayOfMonth === "*";
190
+ const dow = fields.dayOfWeek === "*";
191
+ const dayMatches = dom && dow
192
+ ? true
193
+ // POSIX: when both day fields are restricted, either matching fires.
194
+ : dom !== dow
195
+ ? (dom ? cronFieldMatches(fields.dayOfWeek, d.getUTCDay(), 4) : cronFieldMatches(fields.dayOfMonth, d.getUTCDate(), 2))
196
+ : cronFieldMatches(fields.dayOfMonth, d.getUTCDate(), 2) || cronFieldMatches(fields.dayOfWeek, d.getUTCDay(), 4);
197
+ if (!dayMatches || !cronFieldMatches(fields.month, d.getUTCMonth() + 1, 3)
198
+ || !cronFieldMatches(fields.hour, d.getUTCHours(), 1) || !cronFieldMatches(fields.minute, d.getUTCMinutes(), 0)) continue;
199
+ if (previous !== undefined) maxGap = Math.max(maxGap, t - previous);
200
+ else first = t;
201
+ previous = t;
202
+ }
203
+ if (first === undefined || previous === undefined) return undefined;
204
+ return maxGap > 0 ? maxGap : end - start;
205
+ }
206
+
207
+ function assertTimeZone(tz: string): string {
208
+ if (typeof tz !== "string" || tz.trim().length === 0) throw new TypeError("schedule tz must be an IANA zone name");
209
+ try {
210
+ new Intl.DateTimeFormat("en-US", { timeZone: tz });
211
+ } catch {
212
+ throw new TypeError(`schedule tz ${JSON.stringify(tz)} is not a known IANA zone`);
213
+ }
214
+ return tz;
215
+ }
216
+
217
+ export const schedule = Object.freeze({
218
+ /** A five-field cron, evaluated in `tz` (default UTC). */
219
+ cron(expression: string, options: ScheduleCronOptions = {}): ScheduleTriggerSource {
220
+ const fields = parseCron(expression);
221
+ const tz = options.tz === undefined ? undefined : assertTimeZone(options.tz);
222
+ const grid = cronGrid(fields, tz);
223
+ return Object.freeze({
224
+ kind: "schedule", name: "flows.tick",
225
+ cron: expression.trim().split(/\s+/u).join(" "),
226
+ ...(tz === undefined ? {} : { tz }),
227
+ ...(grid === undefined ? {} : { intervalMs: grid.intervalMs, epochMs: grid.epochMs }),
228
+ });
229
+ },
230
+ /** A fixed interval: `every("5m")`, `every("2h")`. Units s, m, h, d. */
231
+ every(interval: string): ScheduleTriggerSource {
232
+ return Object.freeze({ kind: "schedule", name: "flows.tick", intervalMs: everyToMs(interval), epochMs: 0 });
233
+ },
234
+ });
235
+
236
+ /** UTF-8 code units of a string, without TextEncoder: this package compiles against no DOM or Node lib. */
237
+ function utf8Bytes(text: string): number[] {
238
+ const bytes: number[] = [];
239
+ for (const char of text) {
240
+ const cp = char.codePointAt(0)!;
241
+ if (cp < 0x80) bytes.push(cp);
242
+ else if (cp < 0x800) bytes.push(0xc0 | (cp >> 6), 0x80 | (cp & 0x3f));
243
+ else if (cp < 0x10000) bytes.push(0xe0 | (cp >> 12), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
244
+ else bytes.push(0xf0 | (cp >> 18), 0x80 | ((cp >> 12) & 0x3f), 0x80 | ((cp >> 6) & 0x3f), 0x80 | (cp & 0x3f));
245
+ }
246
+ return bytes;
247
+ }
248
+
249
+ /** 64-bit FNV-1a over UTF-8, as 16 hex characters. Dependency-free; not a security hash, an identity. */
250
+ function fnv1a64(text: string): string {
251
+ let hi = 0xcbf29ce4, lo = 0x84222325;
252
+ for (const byte of utf8Bytes(text)) {
253
+ lo ^= byte;
254
+ // (hi:lo) * 0x100000001b3 mod 2^64, in 16-bit limbs to stay exact in doubles.
255
+ const l0 = lo & 0xffff, l1 = lo >>> 16, h0 = hi & 0xffff, h1 = hi >>> 16;
256
+ let a = l0 * 0x01b3;
257
+ let b = l1 * 0x01b3 + (a >>> 16);
258
+ let c = h0 * 0x01b3 + (b >>> 16) + l0;
259
+ let d = h1 * 0x01b3 + (c >>> 16) + l1;
260
+ lo = ((b & 0xffff) << 16 | (a & 0xffff)) >>> 0;
261
+ hi = ((d & 0xffff) << 16 | (c & 0xffff)) >>> 0;
262
+ }
263
+ return hi.toString(16).padStart(8, "0") + lo.toString(16).padStart(8, "0");
264
+ }
265
+
266
+ /**
267
+ * The `schedule_id` a flow's schedule subscribes to. Deterministic from the
268
+ * flow name and the declaration, so the local runner, `flows check` and the
269
+ * journal all name the same slot stream without a registry — and injective:
270
+ * a readable slug for humans, plus a hash of the exact declaration so
271
+ * `1-5` and `1,5`, or two zones, or two long names sharing a prefix, never
272
+ * share a stream (the kernel dispatches an event to its first matching
273
+ * subscription only).
274
+ */
275
+ export function scheduleIdFor(flowName: string, source: ScheduleTriggerSource): string {
276
+ const canonical = JSON.stringify([flowName, source.cron ?? null, source.tz ?? null, source.intervalMs ?? null, source.epochMs ?? null]);
277
+ const spec = source.cron !== undefined
278
+ ? `cron-${source.cron}${source.tz === undefined ? "" : `-${source.tz}`}`
279
+ : `every-${source.intervalMs}ms`;
280
+ const slug = `${flowName}-${spec}`.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-|-$/gu, "").slice(0, 96);
281
+ return `${slug}-${fnv1a64(canonical)}`;
282
+ }
package/src/step.ts CHANGED
@@ -8,11 +8,14 @@ export interface Step<T> extends PromiseLike<T> {
8
8
  */
9
9
  gate(config: NamedGate): Step<T>;
10
10
  /**
11
- * Predicate gates cannot be journaled the JavaScript closure would not
12
- * survive replay so the executor refuses this branch with
13
- * `unsupported_gate`. Use a `NamedGate` config-object gate above, or the
14
- * declarative `verification:` field on the compiled step spec, when you
15
- * need journal-honest verification.
11
+ * Predicate gate: author code, run once by the runtime after the step
12
+ * completes, on the value the journal handed back. The closure itself is
13
+ * never serialized; its VERDICT is journaled as a lowered `<step>.gate`
14
+ * deterministic step that succeeds or fails, so resume and replay read the
15
+ * recorded verdict and never re-run the function. A false verdict fails the
16
+ * run as `gate_failed`, carrying `because`. `flows check` cannot prove a
17
+ * predicate (docs/SURFACE.md §6); use a `NamedGate` when the check must be
18
+ * inspectable before execution. One `.gate()` per step.
16
19
  */
17
20
  gate(predicate: (value: T) => boolean, because?: string): Step<T>;
18
21
  }
@@ -27,7 +30,20 @@ export type NamedGate =
27
30
  | ReferencesInputNamedGate
28
31
  | SubprocessNamedGate
29
32
  | WordCountBoundsNamedGate
30
- | RegexMatchNamedGate;
33
+ | RegexMatchNamedGate
34
+ | ArtifactExistsNamedGate;
35
+
36
+ /**
37
+ * Passes when the step's journaled `artifacts` lists `path` — a file the
38
+ * agent's worker measured as created or changed under its working directory.
39
+ * The check reads the journal, so replay and resume see the verdict that was
40
+ * recorded, never a fresh look at the disk.
41
+ */
42
+ export interface ArtifactExistsNamedGate {
43
+ type: 'artifact_exists';
44
+ /** Working-directory-relative POSIX path, e.g. `review/security.md`. */
45
+ path: string;
46
+ }
31
47
 
32
48
  export interface ReferencesInputNamedGate {
33
49
  type: 'references_input';
@@ -0,0 +1,56 @@
1
+ <!-- GENERATED by scripts/generate-triggers.mjs — do not edit. -->
2
+ # Provider trigger namespaces
3
+
4
+ 47 providers, 570 events. `mapping` rows come from the adapter's `webhooks:` block (payload-aware signatures); `catalog` rows come from `KNOWN_TRIGGER_CATALOG` (`supportedEvents()`) only. Every provider also includes its catalog events, so the count is what ingress delivers.
5
+
6
+ | Provider | Namespace | Events | Source | Registry-only events |
7
+ |---|---|---:|---|---|
8
+ | `airtable` | `airtable` | 9 | catalog | |
9
+ | `asana` | `asana` | 17 | catalog | |
10
+ | `azure-blob` | `azure_blob` | 3 | mapping | |
11
+ | `box` | `box` | 3 | mapping | |
12
+ | `calendly` | `calendly` | 12 | catalog | |
13
+ | `clickup` | `clickup` | 12 | catalog | |
14
+ | `cloudflare` | `cloudflare` | 8 | mapping | |
15
+ | `confluence` | `confluence` | 6 | catalog | |
16
+ | `daytona` | `daytona` | 7 | mapping | |
17
+ | `docker-hub` | `docker_hub` | 1 | catalog | |
18
+ | `dropbox` | `dropbox` | 1 | mapping | |
19
+ | `fathom` | `fathom` | 1 | mapping | |
20
+ | `gcp` | `gcp` | 9 | mapping | |
21
+ | `gcs` | `gcs` | 3 | mapping | |
22
+ | `github` | `github` | 26 | mapping | |
23
+ | `gitlab` | `gitlab` | 53 | mapping | |
24
+ | `gmail` | `gmail` | 3 | mapping | |
25
+ | `google-calendar` | `google_calendar` | 3 | catalog | |
26
+ | `google-drive` | `google_drive` | 3 | mapping | |
27
+ | `granola` | `granola` | 4 | mapping | |
28
+ | `hubspot` | `hubspot` | 20 | catalog | |
29
+ | `intercom` | `intercom` | 18 | catalog | |
30
+ | `jira` | `jira` | 12 | catalog | |
31
+ | `linear` | `linear` | 33 | catalog | |
32
+ | `mailgun` | `mailgun` | 15 | catalog | |
33
+ | `mixpanel` | `mixpanel` | 12 | catalog | |
34
+ | `neon` | `neon` | 5 | mapping | |
35
+ | `notion` | `notion` | 13 | mapping | |
36
+ | `onedrive` | `onedrive` | 3 | mapping | |
37
+ | `pipedrive` | `pipedrive` | 14 | catalog | |
38
+ | `postgres` | `postgres` | 3 | mapping | |
39
+ | `posthog` | `posthog` | 2 | mapping | |
40
+ | `ramp` | `ramp` | 47 | mapping | |
41
+ | `recall` | `recall` | 3 | mapping | |
42
+ | `redis` | `redis` | 3 | mapping | |
43
+ | `s3` | `s3` | 3 | mapping | |
44
+ | `salesforce` | `salesforce` | 22 | catalog | |
45
+ | `segment` | `segment` | 12 | catalog | |
46
+ | `sendgrid` | `sendgrid` | 17 | catalog | |
47
+ | `sharepoint` | `sharepoint` | 3 | mapping | |
48
+ | `shopify` | `shopify` | 24 | catalog | |
49
+ | `shortcut` | `shortcut` | 6 | mapping | |
50
+ | `slack` | `slack` | 21 | mapping | `reaction.added` |
51
+ | `stripe` | `stripe` | 21 | catalog | |
52
+ | `teams` | `teams` | 20 | catalog | |
53
+ | `telegram` | `telegram` | 25 | catalog | |
54
+ | `zendesk` | `zendesk` | 9 | catalog | |
55
+
56
+ Registry-only events share an identifier with another event of the same provider; subscribe with `webhook(provider, { provider, type })`.