@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.
- package/dist/completion.d.ts +3 -2
- package/dist/completion.d.ts.map +1 -1
- package/dist/completion.js +6 -0
- package/dist/completion.js.map +1 -1
- package/dist/context.d.ts +17 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/flow.d.ts.map +1 -1
- package/dist/flow.js +19 -4
- package/dist/flow.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/provider-trigger.d.ts +2 -2
- package/dist/provider-trigger.d.ts.map +1 -1
- package/dist/provider-trigger.js.map +1 -1
- package/dist/schedule.d.ts +76 -0
- package/dist/schedule.d.ts.map +1 -0
- package/dist/schedule.js +264 -0
- package/dist/schedule.js.map +1 -0
- package/dist/step.d.ts +20 -6
- package/dist/step.d.ts.map +1 -1
- package/dist/triggers/airtable.d.ts +13 -0
- package/dist/triggers/airtable.d.ts.map +1 -0
- package/dist/triggers/airtable.js +32 -0
- package/dist/triggers/airtable.js.map +1 -0
- package/dist/triggers/asana.d.ts +21 -0
- package/dist/triggers/asana.d.ts.map +1 -0
- package/dist/triggers/asana.js +56 -0
- package/dist/triggers/asana.js.map +1 -0
- package/dist/triggers/azure-blob.d.ts +7 -0
- package/dist/triggers/azure-blob.d.ts.map +1 -0
- package/dist/triggers/azure-blob.js +14 -0
- package/dist/triggers/azure-blob.js.map +1 -0
- package/dist/triggers/box.d.ts +7 -0
- package/dist/triggers/box.d.ts.map +1 -0
- package/dist/triggers/box.js +14 -0
- package/dist/triggers/box.js.map +1 -0
- package/dist/triggers/calendly.d.ts +16 -0
- package/dist/triggers/calendly.d.ts.map +1 -0
- package/dist/triggers/calendly.js +41 -0
- package/dist/triggers/calendly.js.map +1 -0
- package/dist/triggers/clickup.d.ts +16 -0
- package/dist/triggers/clickup.d.ts.map +1 -0
- package/dist/triggers/clickup.js +41 -0
- package/dist/triggers/clickup.js.map +1 -0
- package/dist/triggers/cloudflare.d.ts +12 -0
- package/dist/triggers/cloudflare.d.ts.map +1 -0
- package/dist/triggers/cloudflare.js +29 -0
- package/dist/triggers/cloudflare.js.map +1 -0
- package/dist/triggers/confluence.d.ts +10 -0
- package/dist/triggers/confluence.d.ts.map +1 -0
- package/dist/triggers/confluence.js +23 -0
- package/dist/triggers/confluence.js.map +1 -0
- package/dist/triggers/daytona.d.ts +11 -0
- package/dist/triggers/daytona.d.ts.map +1 -0
- package/dist/triggers/daytona.js +26 -0
- package/dist/triggers/daytona.js.map +1 -0
- package/dist/triggers/docker-hub.d.ts +5 -0
- package/dist/triggers/docker-hub.d.ts.map +1 -0
- package/dist/triggers/docker-hub.js +8 -0
- package/dist/triggers/docker-hub.js.map +1 -0
- package/dist/triggers/dropbox.d.ts +5 -0
- package/dist/triggers/dropbox.d.ts.map +1 -0
- package/dist/triggers/dropbox.js +8 -0
- package/dist/triggers/dropbox.js.map +1 -0
- package/dist/triggers/fathom.d.ts +5 -0
- package/dist/triggers/fathom.d.ts.map +1 -0
- package/dist/triggers/fathom.js +8 -0
- package/dist/triggers/fathom.js.map +1 -0
- package/dist/triggers/gcp.d.ts +13 -0
- package/dist/triggers/gcp.d.ts.map +1 -0
- package/dist/triggers/gcp.js +32 -0
- package/dist/triggers/gcp.js.map +1 -0
- package/dist/triggers/gcs.d.ts +7 -0
- package/dist/triggers/gcs.d.ts.map +1 -0
- package/dist/triggers/gcs.js +14 -0
- package/dist/triggers/gcs.js.map +1 -0
- package/dist/triggers/github.d.ts +22 -0
- package/dist/triggers/github.d.ts.map +1 -1
- package/dist/triggers/github.js +66 -0
- package/dist/triggers/github.js.map +1 -1
- package/dist/triggers/gitlab.d.ts +57 -0
- package/dist/triggers/gitlab.d.ts.map +1 -0
- package/dist/triggers/gitlab.js +164 -0
- package/dist/triggers/gitlab.js.map +1 -0
- package/dist/triggers/gmail.d.ts +7 -0
- package/dist/triggers/gmail.d.ts.map +1 -0
- package/dist/triggers/gmail.js +14 -0
- package/dist/triggers/gmail.js.map +1 -0
- package/dist/triggers/google-calendar.d.ts +7 -0
- package/dist/triggers/google-calendar.d.ts.map +1 -0
- package/dist/triggers/google-calendar.js +14 -0
- package/dist/triggers/google-calendar.js.map +1 -0
- package/dist/triggers/google-drive.d.ts +7 -0
- package/dist/triggers/google-drive.d.ts.map +1 -0
- package/dist/triggers/google-drive.js +14 -0
- package/dist/triggers/google-drive.js.map +1 -0
- package/dist/triggers/granola.d.ts +8 -0
- package/dist/triggers/granola.d.ts.map +1 -0
- package/dist/triggers/granola.js +17 -0
- package/dist/triggers/granola.js.map +1 -0
- package/dist/triggers/hubspot.d.ts +24 -0
- package/dist/triggers/hubspot.d.ts.map +1 -0
- package/dist/triggers/hubspot.js +65 -0
- package/dist/triggers/hubspot.js.map +1 -0
- package/dist/triggers/index.d.ts +92 -2
- package/dist/triggers/index.d.ts.map +1 -1
- package/dist/triggers/index.js +92 -2
- package/dist/triggers/index.js.map +1 -1
- package/dist/triggers/intercom.d.ts +22 -0
- package/dist/triggers/intercom.d.ts.map +1 -0
- package/dist/triggers/intercom.js +59 -0
- package/dist/triggers/intercom.js.map +1 -0
- package/dist/triggers/jira.d.ts +16 -0
- package/dist/triggers/jira.d.ts.map +1 -0
- package/dist/triggers/jira.js +41 -0
- package/dist/triggers/jira.js.map +1 -0
- package/dist/triggers/linear.d.ts +37 -0
- package/dist/triggers/linear.d.ts.map +1 -0
- package/dist/triggers/linear.js +104 -0
- package/dist/triggers/linear.js.map +1 -0
- package/dist/triggers/mailgun.d.ts +19 -0
- package/dist/triggers/mailgun.d.ts.map +1 -0
- package/dist/triggers/mailgun.js +50 -0
- package/dist/triggers/mailgun.js.map +1 -0
- package/dist/triggers/mixpanel.d.ts +16 -0
- package/dist/triggers/mixpanel.d.ts.map +1 -0
- package/dist/triggers/mixpanel.js +41 -0
- package/dist/triggers/mixpanel.js.map +1 -0
- package/dist/triggers/neon.d.ts +9 -0
- package/dist/triggers/neon.d.ts.map +1 -0
- package/dist/triggers/neon.js +20 -0
- package/dist/triggers/neon.js.map +1 -0
- package/dist/triggers/notion.d.ts +17 -0
- package/dist/triggers/notion.d.ts.map +1 -0
- package/dist/triggers/notion.js +44 -0
- package/dist/triggers/notion.js.map +1 -0
- package/dist/triggers/onedrive.d.ts +7 -0
- package/dist/triggers/onedrive.d.ts.map +1 -0
- package/dist/triggers/onedrive.js +14 -0
- package/dist/triggers/onedrive.js.map +1 -0
- package/dist/triggers/pipedrive.d.ts +18 -0
- package/dist/triggers/pipedrive.d.ts.map +1 -0
- package/dist/triggers/pipedrive.js +47 -0
- package/dist/triggers/pipedrive.js.map +1 -0
- package/dist/triggers/postgres.d.ts +7 -0
- package/dist/triggers/postgres.d.ts.map +1 -0
- package/dist/triggers/postgres.js +14 -0
- package/dist/triggers/postgres.js.map +1 -0
- package/dist/triggers/posthog.d.ts +6 -0
- package/dist/triggers/posthog.d.ts.map +1 -0
- package/dist/triggers/posthog.js +11 -0
- package/dist/triggers/posthog.js.map +1 -0
- package/dist/triggers/ramp.d.ts +51 -0
- package/dist/triggers/ramp.d.ts.map +1 -0
- package/dist/triggers/ramp.js +146 -0
- package/dist/triggers/ramp.js.map +1 -0
- package/dist/triggers/recall.d.ts +7 -0
- package/dist/triggers/recall.d.ts.map +1 -0
- package/dist/triggers/recall.js +14 -0
- package/dist/triggers/recall.js.map +1 -0
- package/dist/triggers/redis.d.ts +7 -0
- package/dist/triggers/redis.d.ts.map +1 -0
- package/dist/triggers/redis.js +14 -0
- package/dist/triggers/redis.js.map +1 -0
- package/dist/triggers/s3.d.ts +7 -0
- package/dist/triggers/s3.d.ts.map +1 -0
- package/dist/triggers/s3.js +14 -0
- package/dist/triggers/s3.js.map +1 -0
- package/dist/triggers/salesforce.d.ts +26 -0
- package/dist/triggers/salesforce.d.ts.map +1 -0
- package/dist/triggers/salesforce.js +71 -0
- package/dist/triggers/salesforce.js.map +1 -0
- package/dist/triggers/segment.d.ts +16 -0
- package/dist/triggers/segment.d.ts.map +1 -0
- package/dist/triggers/segment.js +41 -0
- package/dist/triggers/segment.js.map +1 -0
- package/dist/triggers/sendgrid.d.ts +21 -0
- package/dist/triggers/sendgrid.d.ts.map +1 -0
- package/dist/triggers/sendgrid.js +56 -0
- package/dist/triggers/sendgrid.js.map +1 -0
- package/dist/triggers/sharepoint.d.ts +7 -0
- package/dist/triggers/sharepoint.d.ts.map +1 -0
- package/dist/triggers/sharepoint.js +14 -0
- package/dist/triggers/sharepoint.js.map +1 -0
- package/dist/triggers/shopify.d.ts +28 -0
- package/dist/triggers/shopify.d.ts.map +1 -0
- package/dist/triggers/shopify.js +77 -0
- package/dist/triggers/shopify.js.map +1 -0
- package/dist/triggers/shortcut.d.ts +10 -0
- package/dist/triggers/shortcut.d.ts.map +1 -0
- package/dist/triggers/shortcut.js +23 -0
- package/dist/triggers/shortcut.js.map +1 -0
- package/dist/triggers/slack.d.ts +17 -0
- package/dist/triggers/slack.d.ts.map +1 -1
- package/dist/triggers/slack.js +51 -0
- package/dist/triggers/slack.js.map +1 -1
- package/dist/triggers/stripe.d.ts +25 -0
- package/dist/triggers/stripe.d.ts.map +1 -0
- package/dist/triggers/stripe.js +68 -0
- package/dist/triggers/stripe.js.map +1 -0
- package/dist/triggers/teams.d.ts +24 -0
- package/dist/triggers/teams.d.ts.map +1 -0
- package/dist/triggers/teams.js +65 -0
- package/dist/triggers/teams.js.map +1 -0
- package/dist/triggers/telegram.d.ts +29 -0
- package/dist/triggers/telegram.d.ts.map +1 -0
- package/dist/triggers/telegram.js +80 -0
- package/dist/triggers/telegram.js.map +1 -0
- package/dist/triggers/zendesk.d.ts +13 -0
- package/dist/triggers/zendesk.d.ts.map +1 -0
- package/dist/triggers/zendesk.js +32 -0
- package/dist/triggers/zendesk.js.map +1 -0
- package/dist/triggers.d.ts +5 -2
- package/dist/triggers.d.ts.map +1 -1
- package/dist/triggers.js.map +1 -1
- package/package.json +1 -1
- package/src/completion.ts +8 -2
- package/src/context.ts +18 -0
- package/src/flow.ts +17 -3
- package/src/index.ts +7 -2
- package/src/provider-trigger.ts +2 -2
- package/src/schedule.ts +282 -0
- package/src/step.ts +22 -6
- package/src/triggers/PROVIDERS.md +56 -0
- package/src/triggers/README.md +84 -8
- package/src/triggers/airtable.ts +34 -0
- package/src/triggers/asana.ts +58 -0
- package/src/triggers/azure-blob.ts +16 -0
- package/src/triggers/box.ts +16 -0
- package/src/triggers/calendly.ts +43 -0
- package/src/triggers/clickup.ts +43 -0
- package/src/triggers/cloudflare.ts +31 -0
- package/src/triggers/confluence.ts +25 -0
- package/src/triggers/daytona.ts +28 -0
- package/src/triggers/docker-hub.ts +10 -0
- package/src/triggers/dropbox.ts +10 -0
- package/src/triggers/fathom.ts +10 -0
- package/src/triggers/gcp.ts +34 -0
- package/src/triggers/gcs.ts +16 -0
- package/src/triggers/github.ts +66 -0
- package/src/triggers/gitlab.ts +166 -0
- package/src/triggers/gmail.ts +16 -0
- package/src/triggers/google-calendar.ts +16 -0
- package/src/triggers/google-drive.ts +16 -0
- package/src/triggers/granola.ts +19 -0
- package/src/triggers/hubspot.ts +67 -0
- package/src/triggers/index.ts +92 -2
- package/src/triggers/intercom.ts +61 -0
- package/src/triggers/jira.ts +43 -0
- package/src/triggers/linear.ts +106 -0
- package/src/triggers/mailgun.ts +52 -0
- package/src/triggers/mixpanel.ts +43 -0
- package/src/triggers/neon.ts +22 -0
- package/src/triggers/notion.ts +46 -0
- package/src/triggers/onedrive.ts +16 -0
- package/src/triggers/pipedrive.ts +49 -0
- package/src/triggers/postgres.ts +16 -0
- package/src/triggers/posthog.ts +13 -0
- package/src/triggers/ramp.ts +148 -0
- package/src/triggers/recall.ts +16 -0
- package/src/triggers/redis.ts +16 -0
- package/src/triggers/s3.ts +16 -0
- package/src/triggers/salesforce.ts +73 -0
- package/src/triggers/segment.ts +43 -0
- package/src/triggers/sendgrid.ts +58 -0
- package/src/triggers/sharepoint.ts +16 -0
- package/src/triggers/shopify.ts +79 -0
- package/src/triggers/shortcut.ts +25 -0
- package/src/triggers/slack.ts +51 -0
- package/src/triggers/stripe.ts +70 -0
- package/src/triggers/teams.ts +67 -0
- package/src/triggers/telegram.ts +82 -0
- package/src/triggers/zendesk.ts +34 -0
- 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"}
|
package/dist/triggers.d.ts
CHANGED
|
@@ -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
|
|
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):
|
|
17
|
+
export declare function webhook(name: string, filter?: WebhookFilter): WebhookTriggerSource;
|
|
15
18
|
//# sourceMappingURL=triggers.d.ts.map
|
package/dist/triggers.d.ts.map
CHANGED
|
@@ -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,
|
|
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"}
|
package/dist/triggers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"triggers.js","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"triggers.js","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
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
|
|
27
|
-
export
|
|
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
|
-
|
|
95
|
-
if (trigger.kind
|
|
96
|
-
|
|
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';
|
package/src/provider-trigger.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { webhook, type
|
|
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
|
|
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
|
}
|
package/src/schedule.ts
ADDED
|
@@ -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
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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 })`.
|