automate.ax 0.1.3

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 (162) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/automation/actions.d.ts +200 -0
  4. package/dist/automation/actions.d.ts.map +1 -0
  5. package/dist/automation/actions.js +286 -0
  6. package/dist/automation/automation.d.ts +16 -0
  7. package/dist/automation/automation.d.ts.map +1 -0
  8. package/dist/automation/automation.js +10 -0
  9. package/dist/automation/integrations.d.ts +63 -0
  10. package/dist/automation/integrations.d.ts.map +1 -0
  11. package/dist/automation/integrations.js +58 -0
  12. package/dist/automation/runtime.d.ts +73 -0
  13. package/dist/automation/runtime.d.ts.map +1 -0
  14. package/dist/automation/runtime.js +92 -0
  15. package/dist/automation/signal.d.ts +58 -0
  16. package/dist/automation/signal.d.ts.map +1 -0
  17. package/dist/automation/signal.js +80 -0
  18. package/dist/automation/subscribe.d.ts +10 -0
  19. package/dist/automation/subscribe.d.ts.map +1 -0
  20. package/dist/automation/subscribe.js +16 -0
  21. package/dist/cli/command-names.d.ts +46 -0
  22. package/dist/cli/command-names.d.ts.map +1 -0
  23. package/dist/cli/command-names.js +46 -0
  24. package/dist/cli/commands/accept.d.ts +20 -0
  25. package/dist/cli/commands/accept.d.ts.map +1 -0
  26. package/dist/cli/commands/accept.js +42 -0
  27. package/dist/cli/commands/debug.d.ts +4 -0
  28. package/dist/cli/commands/debug.d.ts.map +1 -0
  29. package/dist/cli/commands/debug.js +52 -0
  30. package/dist/cli/commands/deploy.d.ts +24 -0
  31. package/dist/cli/commands/deploy.d.ts.map +1 -0
  32. package/dist/cli/commands/deploy.js +292 -0
  33. package/dist/cli/commands/login.d.ts +20 -0
  34. package/dist/cli/commands/login.d.ts.map +1 -0
  35. package/dist/cli/commands/login.js +145 -0
  36. package/dist/cli/commands/logout.d.ts +4 -0
  37. package/dist/cli/commands/logout.d.ts.map +1 -0
  38. package/dist/cli/commands/logout.js +32 -0
  39. package/dist/cli/commands/me.d.ts +4 -0
  40. package/dist/cli/commands/me.d.ts.map +1 -0
  41. package/dist/cli/commands/me.js +48 -0
  42. package/dist/cli/commands/org-api-key-create.d.ts +26 -0
  43. package/dist/cli/commands/org-api-key-create.d.ts.map +1 -0
  44. package/dist/cli/commands/org-api-key-create.js +51 -0
  45. package/dist/cli/commands/org-api-key-delete.d.ts +33 -0
  46. package/dist/cli/commands/org-api-key-delete.d.ts.map +1 -0
  47. package/dist/cli/commands/org-api-key-delete.js +57 -0
  48. package/dist/cli/commands/org-api-key-list.d.ts +16 -0
  49. package/dist/cli/commands/org-api-key-list.d.ts.map +1 -0
  50. package/dist/cli/commands/org-api-key-list.js +58 -0
  51. package/dist/cli/commands/org-api-key-rename.d.ts +32 -0
  52. package/dist/cli/commands/org-api-key-rename.d.ts.map +1 -0
  53. package/dist/cli/commands/org-api-key-rename.js +54 -0
  54. package/dist/cli/commands/org-api-key.d.ts +2 -0
  55. package/dist/cli/commands/org-api-key.d.ts.map +1 -0
  56. package/dist/cli/commands/org-api-key.js +18 -0
  57. package/dist/cli/commands/org-billing.d.ts +16 -0
  58. package/dist/cli/commands/org-billing.d.ts.map +1 -0
  59. package/dist/cli/commands/org-billing.js +78 -0
  60. package/dist/cli/commands/org-create.d.ts +20 -0
  61. package/dist/cli/commands/org-create.d.ts.map +1 -0
  62. package/dist/cli/commands/org-create.js +64 -0
  63. package/dist/cli/commands/org-delete.d.ts +27 -0
  64. package/dist/cli/commands/org-delete.d.ts.map +1 -0
  65. package/dist/cli/commands/org-delete.js +53 -0
  66. package/dist/cli/commands/org-invite.d.ts +39 -0
  67. package/dist/cli/commands/org-invite.d.ts.map +1 -0
  68. package/dist/cli/commands/org-invite.js +66 -0
  69. package/dist/cli/commands/org-leave.d.ts +27 -0
  70. package/dist/cli/commands/org-leave.d.ts.map +1 -0
  71. package/dist/cli/commands/org-leave.js +56 -0
  72. package/dist/cli/commands/org-list.d.ts +4 -0
  73. package/dist/cli/commands/org-list.d.ts.map +1 -0
  74. package/dist/cli/commands/org-list.js +36 -0
  75. package/dist/cli/commands/org-remove.d.ts +33 -0
  76. package/dist/cli/commands/org-remove.d.ts.map +1 -0
  77. package/dist/cli/commands/org-remove.js +66 -0
  78. package/dist/cli/commands/org-rename.d.ts +26 -0
  79. package/dist/cli/commands/org-rename.d.ts.map +1 -0
  80. package/dist/cli/commands/org-rename.js +58 -0
  81. package/dist/cli/commands/org-show.d.ts +16 -0
  82. package/dist/cli/commands/org-show.d.ts.map +1 -0
  83. package/dist/cli/commands/org-show.js +48 -0
  84. package/dist/cli/commands/org-upgrade.d.ts +42 -0
  85. package/dist/cli/commands/org-upgrade.d.ts.map +1 -0
  86. package/dist/cli/commands/org-upgrade.js +171 -0
  87. package/dist/cli/commands/org.d.ts +2 -0
  88. package/dist/cli/commands/org.d.ts.map +1 -0
  89. package/dist/cli/commands/org.js +32 -0
  90. package/dist/cli/commands/project-create.d.ts +27 -0
  91. package/dist/cli/commands/project-create.d.ts.map +1 -0
  92. package/dist/cli/commands/project-create.js +61 -0
  93. package/dist/cli/commands/project-delete.d.ts +27 -0
  94. package/dist/cli/commands/project-delete.d.ts.map +1 -0
  95. package/dist/cli/commands/project-delete.js +55 -0
  96. package/dist/cli/commands/project-list.d.ts +17 -0
  97. package/dist/cli/commands/project-list.d.ts.map +1 -0
  98. package/dist/cli/commands/project-list.js +89 -0
  99. package/dist/cli/commands/project-rename.d.ts +26 -0
  100. package/dist/cli/commands/project-rename.d.ts.map +1 -0
  101. package/dist/cli/commands/project-rename.js +60 -0
  102. package/dist/cli/commands/project-show.d.ts +16 -0
  103. package/dist/cli/commands/project-show.d.ts.map +1 -0
  104. package/dist/cli/commands/project-show.js +37 -0
  105. package/dist/cli/commands/project.d.ts +2 -0
  106. package/dist/cli/commands/project.d.ts.map +1 -0
  107. package/dist/cli/commands/project.js +20 -0
  108. package/dist/cli/index.d.ts +19 -0
  109. package/dist/cli/index.d.ts.map +1 -0
  110. package/dist/cli/index.js +63 -0
  111. package/dist/cli/lib/api-client.d.ts +3 -0
  112. package/dist/cli/lib/api-client.d.ts.map +1 -0
  113. package/dist/cli/lib/api-client.js +14 -0
  114. package/dist/cli/lib/auth-client.d.ts +80 -0
  115. package/dist/cli/lib/auth-client.d.ts.map +1 -0
  116. package/dist/cli/lib/auth-client.js +61 -0
  117. package/dist/cli/lib/automation-build.d.ts +30 -0
  118. package/dist/cli/lib/automation-build.d.ts.map +1 -0
  119. package/dist/cli/lib/automation-build.js +90 -0
  120. package/dist/cli/lib/config-dir.d.ts +47 -0
  121. package/dist/cli/lib/config-dir.d.ts.map +1 -0
  122. package/dist/cli/lib/config-dir.js +146 -0
  123. package/dist/cli/lib/detail-block.d.ts +16 -0
  124. package/dist/cli/lib/detail-block.d.ts.map +1 -0
  125. package/dist/cli/lib/detail-block.js +25 -0
  126. package/dist/cli/lib/env.d.ts +4 -0
  127. package/dist/cli/lib/env.d.ts.map +1 -0
  128. package/dist/cli/lib/env.js +7 -0
  129. package/dist/cli/lib/hijack-clack-logger.d.ts +2 -0
  130. package/dist/cli/lib/hijack-clack-logger.d.ts.map +1 -0
  131. package/dist/cli/lib/hijack-clack-logger.js +8 -0
  132. package/dist/cli/lib/io.d.ts +19 -0
  133. package/dist/cli/lib/io.d.ts.map +1 -0
  134. package/dist/cli/lib/io.js +87 -0
  135. package/dist/cli/lib/json-output.d.ts +9 -0
  136. package/dist/cli/lib/json-output.d.ts.map +1 -0
  137. package/dist/cli/lib/json-output.js +12 -0
  138. package/dist/cli/lib/organization-detail-block.d.ts +30 -0
  139. package/dist/cli/lib/organization-detail-block.d.ts.map +1 -0
  140. package/dist/cli/lib/organization-detail-block.js +72 -0
  141. package/dist/cli/lib/project-config.d.ts +10 -0
  142. package/dist/cli/lib/project-config.d.ts.map +1 -0
  143. package/dist/cli/lib/project-config.js +21 -0
  144. package/dist/cli/lib/spinner.d.ts +18 -0
  145. package/dist/cli/lib/spinner.d.ts.map +1 -0
  146. package/dist/cli/lib/spinner.js +111 -0
  147. package/dist/cli/usage.d.ts +9 -0
  148. package/dist/cli/usage.d.ts.map +1 -0
  149. package/dist/cli/usage.js +468 -0
  150. package/dist/cli/utils.d.ts +291 -0
  151. package/dist/cli/utils.d.ts.map +1 -0
  152. package/dist/cli/utils.js +561 -0
  153. package/dist/cli.d.ts +3 -0
  154. package/dist/cli.d.ts.map +1 -0
  155. package/dist/cli.js +5 -0
  156. package/dist/config.d.ts +11 -0
  157. package/dist/config.d.ts.map +1 -0
  158. package/dist/config.js +9 -0
  159. package/dist/index.d.ts +8 -0
  160. package/dist/index.d.ts.map +1 -0
  161. package/dist/index.js +7 -0
  162. package/package.json +92 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Zach Sents
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # `automate.ax`
2
+
3
+ Happy-path Automate.ax package for automation authors. It provides the `automate` CLI plus the public helpers used in `automate.config.ts` and automation files.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun add automate.ax
9
+ bun add @automate.ax/components-core
10
+ ```
11
+
12
+ ## CLI
13
+
14
+ ```bash
15
+ bunx automate.ax --help
16
+ bunx automate.ax login
17
+ bunx automate.ax deploy --dir ./my-app
18
+ bunx automate.ax org apikey create --org <organization>
19
+ bunx automate.ax org apikey list --org <organization>
20
+ ```
21
+
22
+ The published CLI defaults to `https://automate.ax`. From this repo, use
23
+ `bun run cli:local -- <command>` to run against `http://localhost:3000`.
24
+ Organization API key commands also support `rename` and `delete`; created
25
+ secrets are shown once.
26
+
27
+ ## Config
28
+
29
+ ```ts
30
+ import { defineConfig } from "automate.ax"
31
+
32
+ export default defineConfig({
33
+ projectId: "project_...",
34
+ })
35
+ ```
36
+
37
+ `automate deploy` resolves the Automate.ax directory from `--dir`, the current directory,
38
+ the nearest parent config, or a bounded downward config search.
39
+ It writes local build artifacts to `.automate/build` and uploads bundled
40
+ JavaScript artifacts to Automate.ax. Deployment fails when no `*.automation.ts`
41
+ files are found. The CLI then polls the Graphile-backed snapshot, planning,
42
+ configuration, and cleanup stages every two seconds. If account bindings are
43
+ missing, interactive deployments prompt for eligible connected accounts; JSON
44
+ output returns the authorization state. Ctrl-C detaches without cancelling the
45
+ deployment.
46
+
47
+ ## Automation
48
+
49
+ ```ts
50
+ import { log, onHttpRequest } from "@automate.ax/components-core"
51
+ import { automation, transform } from "automate.ax"
52
+
53
+ export default automation("When a request is received", () => {
54
+ const request = onHttpRequest({ scope: "automation" })
55
+ const method = request.method
56
+ const path = request.path
57
+ const message = transform(
58
+ [method, path],
59
+ (resolvedMethod, resolvedPath) =>
60
+ `${resolvedMethod} request to ${resolvedPath}`,
61
+ )
62
+
63
+ log({ value: message })
64
+ })
65
+ ```
66
+
67
+ `automation()` attaches a `.description` metadata field and runs the same bundle
68
+ in planning, orchestration, and execution phases.
69
+
70
+ `transform(signals, fn)` records its signal inputs as graph edges. Orchestration walks
71
+ those inputs to durable event and action leaves without calling `fn`; execution
72
+ materializes the inputs and then calls it. Transform results stay in memory and
73
+ may be any value. `signal.transform(fn)` is the unary convenience form, and
74
+ `signal.property` is shorthand for
75
+ `signal.transform((value) => value.property)`. Property access composes across
76
+ objects and primitives, so `request.path.length` is a `Signal<number>`.
77
+
78
+ Declare custom actions at the top level, then call them inside an automation:
79
+
80
+ ```ts
81
+ import { defineAction } from "automate.ax"
82
+ import { z } from "zod"
83
+
84
+ const notify = defineAction("Notify")
85
+ .describe("Sends a notification")
86
+ .input(
87
+ z.object({
88
+ message: z.string(),
89
+ }),
90
+ )
91
+ .output(z.void())
92
+ .handler(({ input }) => {
93
+ console.log(input.message)
94
+ })
95
+ ```
96
+
97
+ Omitting `input` uses an empty-object schema, and omitting `output` uses a void
98
+ schema. `describe`, `input`, and `output` can be called in any order or repeated
99
+ before `handler`; the latest value for each replaces the previous one. The
100
+ resulting action exposes its display metadata through `.meta`. Orchestration
101
+ snapshots that metadata onto each action invocation for display and debugging.
102
+ During execution, handlers receive a `runtime` object containing the platform
103
+ capabilities available to action code. Orchestration and invocation transport
104
+ methods are internal to the SDK. The current capabilities are
105
+ `runtime.sendOutput({ type, data })` and `runtime.sendEmail(input)`.
106
+
107
+ `runtime.sendOutput({ type, data })` requires a string discriminator and
108
+ encodable data. It durably emits the output without ending the automation. A
109
+ handler may emit multiple ordered outputs; call positions make retries
110
+ idempotent. Outputs do not enter the trigger event bus.
111
+
112
+ ## Package Role
113
+
114
+ Use `automate.ax` for app projects, automation and component authoring,
115
+ deploy-time subscriptions, and the `automate` CLI. Install component packages
116
+ such as `@automate.ax/components-core` for platform-provided actions and triggers.
117
+ HTTP triggers return `202` immediately unless configured with
118
+ `waitForResponse: true`; responding automations use the platform-provided
119
+ `respondToHttpRequest` action.
@@ -0,0 +1,200 @@
1
+ import { type Encodable, type ObjectProducingSchema, type ProducingSchema } from "@automate.ax/codec";
2
+ import type { StandardSchemaV1 } from "@standard-schema/spec";
3
+ import { type AccountAuthorizationAction, type IntegrationAccountReference, type IntegrationScopeRequirement, type ResolvedIntegrationAccount } from "./integrations.js";
4
+ import type { Signal } from "./signal.js";
5
+ declare const DEFAULT_ACTION_INPUT_SCHEMA: StandardSchemaV1<Record<string, never>>;
6
+ declare const DEFAULT_ACTION_OUTPUT_SCHEMA: StandardSchemaV1<void>;
7
+ /**
8
+ * Executor-only platform capabilities available to action handlers.
9
+ *
10
+ * These methods perform platform-managed effects without exposing credentials
11
+ * or execution infrastructure to the action.
12
+ */
13
+ export interface ActionRuntime {
14
+ /**
15
+ * Emits a typed value from the current action execution.
16
+ *
17
+ * @param output - Value and application-defined type used to classify it.
18
+ * @param output.data - Encodable payload to emit.
19
+ * @param output.type - Application-defined output type.
20
+ */
21
+ sendOutput(output: {
22
+ /** Encodable payload to emit. */
23
+ data: Encodable;
24
+ /** Application-defined output type. */
25
+ type: string;
26
+ }): Promise<void>;
27
+ /**
28
+ * Sends a plain-text email through the platform.
29
+ *
30
+ * Resolves with the provider's message ID when one is available.
31
+ *
32
+ * @param input - Email fields.
33
+ * @param input.subject - Email subject line.
34
+ * @param input.text - Plain-text message body.
35
+ * @param input.to - Recipient email address.
36
+ */
37
+ sendEmail(input: {
38
+ /** Email subject line. */
39
+ subject: string;
40
+ /** Plain-text message body. */
41
+ text: string;
42
+ /** Recipient email address. */
43
+ to: string;
44
+ }): Promise<{
45
+ /** Provider message ID, or `null` when the provider supplies none. */
46
+ id: string | null;
47
+ }>;
48
+ }
49
+ /**
50
+ * Implements an action after its input and account selection are materialized.
51
+ *
52
+ * The handler receives schema-validated input and, for account-backed actions,
53
+ * the resolved account secret. Its result is subsequently validated by the
54
+ * action's output schema.
55
+ *
56
+ * @template TInputSchema - Schema used to validate materialized action input.
57
+ * @template TOutputSchema - Schema used to validate the handler result.
58
+ * @template TAccountServiceId - Required integration service, or `never` when
59
+ * the action does not use an account.
60
+ */
61
+ export type ActionHandler<TInputSchema extends ObjectProducingSchema<unknown> = ObjectProducingSchema<unknown>, TOutputSchema extends ProducingSchema<Encodable> = ProducingSchema<Encodable>, TAccountServiceId extends string = never> = (options: {
62
+ /** Parsed input produced by the action's input schema. */
63
+ input: StandardSchemaV1.InferOutput<TInputSchema>;
64
+ /** Platform-managed capabilities available during execution. */
65
+ runtime: ActionRuntime;
66
+ } & ([TAccountServiceId] extends [never] ? object : {
67
+ /**
68
+ * Resolved credentials for the integration service required by the
69
+ * action.
70
+ */
71
+ account: ResolvedIntegrationAccount<TAccountServiceId>;
72
+ })) => Promise<StandardSchemaV1.InferInput<TOutputSchema>> | StandardSchemaV1.InferInput<TOutputSchema>;
73
+ /** Display metadata attached to a defined action. */
74
+ export interface ActionMetadata {
75
+ /** Optional explanation of what the action does. */
76
+ readonly description?: string;
77
+ /** Human-readable action name. */
78
+ readonly name: string;
79
+ }
80
+ /**
81
+ * Fluent definition state for an action.
82
+ *
83
+ * The generic state records the configured schemas and account requirement so
84
+ * the final handler and callable action remain fully inferred.
85
+ *
86
+ * @template TInputSchema - Currently configured input schema.
87
+ * @template TOutputSchema - Currently configured output schema.
88
+ * @template TAccountServiceId - Required integration service, or `never` for an
89
+ * action without an account requirement.
90
+ */
91
+ export interface ActionBuilder<TInputSchema extends ObjectProducingSchema<unknown> = typeof DEFAULT_ACTION_INPUT_SCHEMA, TOutputSchema extends ProducingSchema<Encodable> = typeof DEFAULT_ACTION_OUTPUT_SCHEMA, TAccountServiceId extends string = never> {
92
+ /**
93
+ * Requires an integration account when planning and executing the action.
94
+ *
95
+ * @template TNextAccountServiceId - Integration service required by the
96
+ * resulting builder.
97
+ * @param serviceId - Stable identifier of the required integration service.
98
+ * @param requiredScopes - Provider scopes the selected account must satisfy.
99
+ */
100
+ account<TNextAccountServiceId extends string>(serviceId: TNextAccountServiceId, requiredScopes?: IntegrationScopeRequirement[]): ActionBuilder<TInputSchema, TOutputSchema, TNextAccountServiceId>;
101
+ /**
102
+ * Adds a human-readable description to action metadata.
103
+ *
104
+ * @param description - Explanation shown to users and planning tools.
105
+ */
106
+ describe(description: string): ActionBuilder<TInputSchema, TOutputSchema, TAccountServiceId>;
107
+ /**
108
+ * Sets the schema used to validate materialized action input.
109
+ *
110
+ * @template TNextInputSchema - Input schema stored by the resulting builder.
111
+ * @param schema - Standard Schema-compatible schema producing an object.
112
+ */
113
+ input<TNextInputSchema extends ObjectProducingSchema<unknown>>(schema: TNextInputSchema): ActionBuilder<TNextInputSchema, TOutputSchema, TAccountServiceId>;
114
+ /**
115
+ * Sets the schema used to validate the action handler's result.
116
+ *
117
+ * @template TNextOutputSchema - Output schema stored by the resulting
118
+ * builder.
119
+ * @param schema - Standard Schema-compatible output schema.
120
+ */
121
+ output<TNextOutputSchema extends ProducingSchema<Encodable>>(schema: TNextOutputSchema): ActionBuilder<TInputSchema, TNextOutputSchema, TAccountServiceId>;
122
+ /**
123
+ * Completes the definition with its execution implementation.
124
+ *
125
+ * @param handler - Implementation invoked with validated input and runtime
126
+ * capabilities.
127
+ */
128
+ handler(handler: ActionHandler<TInputSchema, TOutputSchema, TAccountServiceId>): DefinedAction<TInputSchema, TOutputSchema, TAccountServiceId>;
129
+ }
130
+ /**
131
+ * Object shape accepted from callers before action input is parsed.
132
+ *
133
+ * Schemas with an object-shaped declared input preserve that input type so
134
+ * coercions and transforms remain callable. Schemas whose declared input is
135
+ * broader use their known object output shape instead.
136
+ *
137
+ * @template TInputSchema - Object-producing action input schema.
138
+ */
139
+ export type ActionSchemaInput<TInputSchema extends ObjectProducingSchema<unknown>> = StandardSchemaV1.InferInput<TInputSchema> extends Record<string, unknown> ? StandardSchemaV1.InferInput<TInputSchema> : StandardSchemaV1.InferOutput<TInputSchema>;
140
+ /**
141
+ * Per-field inputs accepted when invoking an action.
142
+ *
143
+ * Each field may be supplied directly or as a signal that is resolved before
144
+ * schema validation.
145
+ *
146
+ * @template TInputSchema - Object-producing action input schema.
147
+ */
148
+ export type ActionCallInput<TInputSchema extends ObjectProducingSchema<unknown>> = {
149
+ [TKey in keyof ActionSchemaInput<TInputSchema>]: ActionSchemaInput<TInputSchema>[TKey] | Signal<ActionSchemaInput<TInputSchema>[TKey]>;
150
+ };
151
+ /**
152
+ * Optional account selection added to account-backed action calls.
153
+ *
154
+ * The selection may be a binding name, a typed account reference, or a signal
155
+ * resolving to either. Omitting it selects the project's default binding.
156
+ *
157
+ * @template TAccountServiceId - Required integration service.
158
+ */
159
+ type ActionAccountCallInput<TAccountServiceId extends string> = {
160
+ /** Project account binding to use for this invocation. */
161
+ account?: string | IntegrationAccountReference<TAccountServiceId> | Signal<string> | Signal<IntegrationAccountReference<TAccountServiceId>> | Signal<string | IntegrationAccountReference<TAccountServiceId>>;
162
+ };
163
+ type ActionInvocationInput<TInputSchema extends ObjectProducingSchema<unknown>, TAccountServiceId extends string> = [TAccountServiceId] extends [never] ? ActionCallInput<TInputSchema> : [TInputSchema] extends [typeof DEFAULT_ACTION_INPUT_SCHEMA] ? ActionAccountCallInput<TAccountServiceId> : ActionCallInput<TInputSchema> & ActionAccountCallInput<TAccountServiceId>;
164
+ /**
165
+ * Callable action produced by a completed action definition.
166
+ *
167
+ * Calling it registers an invocation and returns a signal for the eventual
168
+ * validated output. Account-backed actions also carry their authorization
169
+ * requirement for planning.
170
+ *
171
+ * @template TInputSchema - Schema governing invocation input.
172
+ * @template TOutputSchema - Schema governing the resulting signal value.
173
+ * @template TAccountServiceId - Required integration service, or `never` for
174
+ * accountless actions.
175
+ */
176
+ export type DefinedAction<TInputSchema extends ObjectProducingSchema<unknown> = ObjectProducingSchema<unknown>, TOutputSchema extends ProducingSchema<Encodable> = ProducingSchema<Encodable>, TAccountServiceId extends string = never> = {
177
+ /**
178
+ * Registers an invocation and exposes its eventual output.
179
+ *
180
+ * @param input - Literal and signal-backed fields supplied to the action.
181
+ */
182
+ (input: ActionInvocationInput<TInputSchema, TAccountServiceId>): Signal<StandardSchemaV1.InferOutput<TOutputSchema>>;
183
+ /** Display metadata configured while defining the action. */
184
+ readonly meta: ActionMetadata;
185
+ } & ([TAccountServiceId] extends [never] ? object : AccountAuthorizationAction<TAccountServiceId>);
186
+ /**
187
+ * Starts a fluent action definition.
188
+ *
189
+ * @param name - Human-readable action name.
190
+ */
191
+ export declare function defineAction(name: string): ActionBuilder;
192
+ /**
193
+ * Creates a string signal by interpolating in-memory values and signals.
194
+ *
195
+ * @param strings - Static portions of the tagged template.
196
+ * @param values - Dynamic values interleaved between static portions.
197
+ */
198
+ export declare function t(strings: TemplateStringsArray, ...values: unknown[]): Signal<string>;
199
+ export {};
200
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/automation/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,286 @@
1
+ import { mapValues } from "@zachsents/zippy";
2
+ import { omit, pick } from "remeda";
3
+ import { z } from "zod";
4
+ import { actionAccountRequirementDefinition, DEFAULT_ACCOUNT_BINDING, isIntegrationAccountReference, serializedIntegrationAccountDefinition, } from "./integrations.js";
5
+ import { actionProvenance, createActionSignal, isSignal, signalTransform, subscriptionProvenance, transform, } from "./signal.js";
6
+ import { consumeHookSlot } from "./runtime.js";
7
+ const DEFAULT_ACTION_INPUT_SCHEMA = z.record(z.string(), z.never());
8
+ const DEFAULT_ACTION_OUTPUT_SCHEMA = z.void();
9
+ /**
10
+ * Starts a fluent action definition.
11
+ *
12
+ * @param name - Human-readable action name.
13
+ */
14
+ export function defineAction(name) {
15
+ return createActionBuilder({
16
+ input: DEFAULT_ACTION_INPUT_SCHEMA,
17
+ meta: { name },
18
+ output: DEFAULT_ACTION_OUTPUT_SCHEMA,
19
+ });
20
+ }
21
+ /**
22
+ * Creates a builder carrying the action metadata and latest configured schemas.
23
+ *
24
+ * @param definition - Metadata and schemas configured by prior builder calls.
25
+ * @param definition.account - Optional integration account requirement.
26
+ * @param definition.account.requiredScopes - Required provider scopes.
27
+ * @param definition.account.serviceId - Required integration service.
28
+ * @param definition.input - Current input schema.
29
+ * @param definition.meta - Display metadata for the action.
30
+ * @param definition.output - Current output schema.
31
+ */
32
+ function createActionBuilder(definition) {
33
+ return {
34
+ account(serviceId, requiredScopes = []) {
35
+ return createActionBuilder({
36
+ ...definition,
37
+ account: { requiredScopes, serviceId },
38
+ });
39
+ },
40
+ describe(description) {
41
+ return createActionBuilder({
42
+ ...definition,
43
+ meta: { ...definition.meta, description },
44
+ });
45
+ },
46
+ input(input) {
47
+ return createActionBuilder({ ...definition, input });
48
+ },
49
+ output(output) {
50
+ return createActionBuilder({ ...definition, output });
51
+ },
52
+ handler(handler) {
53
+ return Object.assign((input) => invokeAction({
54
+ ...pick(definition, ["account", "meta"]),
55
+ handler,
56
+ input: definition.input,
57
+ output: definition.output,
58
+ }, input), { meta: definition.meta }, definition.account && {
59
+ [actionAccountRequirementDefinition]: definition.account,
60
+ });
61
+ },
62
+ };
63
+ }
64
+ /**
65
+ * Registers an action invocation and returns a signal for its eventual output.
66
+ *
67
+ * @param options - Schemas and handler that define the action.
68
+ * @param input - Literal and signal-backed values supplied by the caller.
69
+ */
70
+ function invokeAction(options, input) {
71
+ const slot = consumeHookSlot();
72
+ const accountInput = options.account && "account" in input ? input.account : undefined;
73
+ const schemaInput = options.account ? omit(input, ["account"]) : input;
74
+ const planningContext = globalThis.__AUTOMATION_PLANNING_CONTEXT__;
75
+ if (planningContext && options.account) {
76
+ planningContext.accountUses.push({
77
+ ...getPlannedAccountSelection(accountInput, options.account.serviceId),
78
+ requiredScopes: options.account.requiredScopes,
79
+ serviceId: options.account.serviceId,
80
+ });
81
+ }
82
+ const state = globalThis.__AUTOMATION_RUNTIME_STATE__;
83
+ if (state?.phase === "orchestrate") {
84
+ // This action has not already completed in this automation context
85
+ if (!state.context.actionOutputs.some((output) => output.slot === slot)) {
86
+ const actionDependencyIds = new Set();
87
+ const eventDependencyIds = new Set();
88
+ if (Object.values(input).every((value) => !isSignal(value) ||
89
+ collectSignalDependencies(value, state.context, actionDependencyIds, eventDependencyIds))) {
90
+ state.actionInvocations.push({
91
+ actionDependencyIds: [...actionDependencyIds],
92
+ eventDependencyIds: [...eventDependencyIds],
93
+ name: options.meta.name,
94
+ description: options.meta.description ?? null,
95
+ slot,
96
+ });
97
+ }
98
+ }
99
+ }
100
+ else if (state?.phase === "execute" && state.invocation.slot === slot) {
101
+ const materialized = mapValues(schemaInput, (v) => isSignal(v) ? resolveSignal(v, state.invocation.context) : v);
102
+ const materializedAccount = isSignal(accountInput)
103
+ ? resolveSignal(accountInput, state.invocation.context)
104
+ : accountInput;
105
+ state.executed = true;
106
+ state.effects.push((async () => {
107
+ const account = options.account === undefined
108
+ ? undefined
109
+ : await resolveActionAccount(materializedAccount, options.account, state.resolveAccountInput);
110
+ await state.completeInvocation({
111
+ output: await validateStandardSchema(options.output,
112
+ // REVIEW: Account presence follows the builder's conditional handler type.
113
+ // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- Runtime branch and builder type share the same account declaration.
114
+ await options.handler({
115
+ ...(account && { account }),
116
+ input: await validateStandardSchema(options.input, materialized, "Action input"),
117
+ runtime: state.runtime,
118
+ }), "Action output"),
119
+ });
120
+ })());
121
+ }
122
+ return createActionSignal(slot);
123
+ }
124
+ /**
125
+ * Resolves a materialized account selection through its current project
126
+ * binding.
127
+ *
128
+ * @param value - Literal or signal-produced account selection.
129
+ * @param requirement - Service declared by the action.
130
+ * @param requirement.serviceId - Integration service required by the action.
131
+ * @param resolveAccountInput - Private runtime transport for credential
132
+ * loading.
133
+ * @throws When the value is not a compatible bound account for the action.
134
+ */
135
+ async function resolveActionAccount(value, requirement, resolveAccountInput) {
136
+ if (value !== undefined &&
137
+ typeof value !== "string" &&
138
+ !isIntegrationAccountReference(value)) {
139
+ throw new Error("Action account input is not a named integration account binding.");
140
+ }
141
+ const accountDefinition = isIntegrationAccountReference(value)
142
+ ? value[serializedIntegrationAccountDefinition]
143
+ : undefined;
144
+ if (accountDefinition &&
145
+ accountDefinition.serviceId !== requirement.serviceId) {
146
+ throw new Error(`Action requires a ${requirement.serviceId} account, but received a ${accountDefinition.serviceId} account.`);
147
+ }
148
+ return await resolveAccountInput({
149
+ binding: typeof value === "string"
150
+ ? value
151
+ : accountDefinition?.binding === undefined
152
+ ? DEFAULT_ACCOUNT_BINDING
153
+ : accountDefinition.binding,
154
+ serviceId: requirement.serviceId,
155
+ });
156
+ }
157
+ /**
158
+ * Classifies an action account input without evaluating signal transforms.
159
+ *
160
+ * @param value - Account selection supplied to the action.
161
+ * @param serviceId - Integration service required by the action.
162
+ * @throws When the input is not a compatible account selection.
163
+ */
164
+ function getPlannedAccountSelection(value, serviceId) {
165
+ if (isSignal(value)) {
166
+ return { dynamic: true };
167
+ }
168
+ if (value === undefined || typeof value === "string") {
169
+ return {
170
+ binding: value ?? DEFAULT_ACCOUNT_BINDING,
171
+ dynamic: false,
172
+ };
173
+ }
174
+ if (!isIntegrationAccountReference(value)) {
175
+ throw new Error("Action account input is not a named integration account binding.");
176
+ }
177
+ const definition = value[serializedIntegrationAccountDefinition];
178
+ if (definition.serviceId !== serviceId) {
179
+ throw new Error(`Action requires a ${serviceId} account, but received a ${definition.serviceId} account.`);
180
+ }
181
+ return {
182
+ binding: definition.binding,
183
+ dynamic: false,
184
+ };
185
+ }
186
+ /**
187
+ * Creates a string signal by interpolating in-memory values and signals.
188
+ *
189
+ * @param strings - Static portions of the tagged template.
190
+ * @param values - Dynamic values interleaved between static portions.
191
+ */
192
+ export function t(strings, ...values) {
193
+ return transform(values.filter(isSignal), (...resolvedSignals) => {
194
+ let signalIndex = 0;
195
+ return (values.reduce((result, value, index) => result +
196
+ (strings[index] ?? "") +
197
+ String(isSignal(value) ? resolvedSignals[signalIndex++] : value), "") + (strings[strings.length - 1] ?? ""));
198
+ });
199
+ }
200
+ /**
201
+ * Resolves a signal against executor-loaded dependency values.
202
+ *
203
+ * @param signal - Signal to resolve.
204
+ * @param context - Dependency values loaded for the action executor.
205
+ * @throws When an expected execution dependency is missing.
206
+ */
207
+ function resolveSignal(signal, context) {
208
+ const subscription = signal[subscriptionProvenance];
209
+ if (subscription) {
210
+ const match = context.events.find((event) => event.slot === subscription.slot);
211
+ if (!match) {
212
+ throw new Error(`Missing subscription dependency for slot ${subscription.slot}.`);
213
+ }
214
+ return match.payload;
215
+ }
216
+ const action = signal[actionProvenance];
217
+ if (action) {
218
+ const match = context.actionOutputs.find((output) => output.slot === action.slot);
219
+ if (!match) {
220
+ throw new Error(`Missing action dependency for slot ${action.slot}.`);
221
+ }
222
+ return match.output;
223
+ }
224
+ const transformation = signal[signalTransform];
225
+ if (!transformation) {
226
+ throw new Error("Signal has no runtime provenance or transform.");
227
+ }
228
+ return transformation.transform(...transformation.inputs.map((input) => resolveSignal(input, context)));
229
+ }
230
+ /**
231
+ * Adds a signal's boundary dependencies without evaluating its transforms.
232
+ *
233
+ * @param signal - Signal whose durable inputs should be collected.
234
+ * @param context - Available dependency metadata for the current context.
235
+ * @param actionDependencyIds - Prior action invocation IDs collected so far.
236
+ * @param eventDependencyIds - Automation event IDs collected so far.
237
+ * @throws When the signal has no runtime provenance or transform.
238
+ */
239
+ function collectSignalDependencies(signal, context, actionDependencyIds, eventDependencyIds) {
240
+ const subscription = signal[subscriptionProvenance];
241
+ if (subscription) {
242
+ const match = context.events.find((event) => event.slot === subscription.slot);
243
+ if (!match)
244
+ return false;
245
+ eventDependencyIds.add(match.automationEventId);
246
+ return true;
247
+ }
248
+ const action = signal[actionProvenance];
249
+ if (action) {
250
+ const match = context.actionOutputs.find((output) => output.slot === action.slot);
251
+ if (!match)
252
+ return false;
253
+ actionDependencyIds.add(match.actionInvocationId);
254
+ return true;
255
+ }
256
+ const transformation = signal[signalTransform];
257
+ if (!transformation) {
258
+ throw new Error("Signal has no runtime provenance or transform.");
259
+ }
260
+ return transformation.inputs.every((input) => collectSignalDependencies(input, context, actionDependencyIds, eventDependencyIds));
261
+ }
262
+ /**
263
+ * Validates a value through a Standard Schema implementation.
264
+ *
265
+ * @param schema - Standard Schema validator to invoke.
266
+ * @param value - Unknown value to validate.
267
+ * @param label - Label included in validation errors.
268
+ * @throws When validation reports one or more issues.
269
+ */
270
+ async function validateStandardSchema(schema, value, label) {
271
+ const result = await schema["~standard"].validate(value);
272
+ if (result.issues) {
273
+ const details = result.issues
274
+ .map((issue) => {
275
+ const path = issue.path
276
+ ?.map((segment) => typeof segment === "object" ? String(segment.key) : String(segment))
277
+ .join(".");
278
+ return path ? `${path}: ${issue.message}` : issue.message;
279
+ })
280
+ .join("; ");
281
+ throw new Error(details.length > 0
282
+ ? `${label} validation failed: ${details}`
283
+ : `${label} validation failed.`);
284
+ }
285
+ return result.value;
286
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Describes an automation — the function that the orchestrator will execute in
3
+ * various contexts (plan, execute, deploy, authz).
4
+ */
5
+ export interface AutomationDescriptor {
6
+ (): Promise<void> | void;
7
+ description: string;
8
+ }
9
+ /**
10
+ * Defines a top-level automation for the runtime to invoke.
11
+ *
12
+ * @param description - Human-readable summary of the automation.
13
+ * @param fn - Automation body to run in the active runtime phase.
14
+ */
15
+ export declare function automation(description: AutomationDescriptor["description"], fn: () => void): AutomationDescriptor;
16
+ //# sourceMappingURL=automation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"automation.d.ts","sourceRoot":"","sources":["../../src/automation/automation.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,WAAW,EAAE,oBAAoB,CAAC,aAAa,CAAC,EAChD,EAAE,EAAE,MAAM,IAAI,GACb,oBAAoB,CAEtB"}
@@ -0,0 +1,10 @@
1
+ import { runAutomationFunction } from "./runtime.js";
2
+ /**
3
+ * Defines a top-level automation for the runtime to invoke.
4
+ *
5
+ * @param description - Human-readable summary of the automation.
6
+ * @param fn - Automation body to run in the active runtime phase.
7
+ */
8
+ export function automation(description, fn) {
9
+ return Object.assign(() => runAutomationFunction(fn), { description });
10
+ }