@keystrokehq/cli 0.0.1

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 (122) hide show
  1. package/AGENTS-blurb.md +123 -0
  2. package/LICENSE +42 -0
  3. package/README.md +177 -0
  4. package/THIRD_PARTY_NOTICES.md +16 -0
  5. package/bin/keystroke.mjs +107 -0
  6. package/dist/_manifest-JSRE3H8k.mjs +385 -0
  7. package/dist/agent-bundle-package-DWV6B_5q-BtV7Xycc.mjs +2344 -0
  8. package/dist/agent-manifest-CDnbkR2f.mjs +245 -0
  9. package/dist/agents-CZJGxVqV.mjs +228 -0
  10. package/dist/api-keys-D2lgguuY.mjs +40 -0
  11. package/dist/auth-DN2VusyU.mjs +59 -0
  12. package/dist/auth.handler-CT1BQUvu.mjs +340 -0
  13. package/dist/browser-qwFrUH82.mjs +24 -0
  14. package/dist/build-agents-BmM_AsSd-BGi9wtzt.mjs +514 -0
  15. package/dist/build-metadata-BWS7uhd_-DR8gJjTX.mjs +1422 -0
  16. package/dist/build-progress-DgYKb4hB.mjs +183 -0
  17. package/dist/build-tasks-CdihpudT-D5r5HUHe.mjs +91 -0
  18. package/dist/build-workflows-CfxBnIWh-CdYPv8w2.mjs +370 -0
  19. package/dist/build.handler-4799CjWH.mjs +36 -0
  20. package/dist/chunk-CH6r78ws.mjs +37 -0
  21. package/dist/clear-cache.handler-B9tqSoSM.mjs +11 -0
  22. package/dist/clear.handler-BTIXXPTJ.mjs +42 -0
  23. package/dist/clear.handler-BydlX-zE.mjs +11 -0
  24. package/dist/commander-DfTVqQ-3.mjs +133 -0
  25. package/dist/concurrency-gXn9Rw8x-DNl2YtrS.mjs +20 -0
  26. package/dist/connect-BUXkeH0F.mjs +43 -0
  27. package/dist/connect.handler-CYel9cy6.mjs +430 -0
  28. package/dist/constants-CPpPdSNg.mjs +8 -0
  29. package/dist/context-T7HZuB97.mjs +138 -0
  30. package/dist/credential-env-map-CI8yWHVy.mjs +28 -0
  31. package/dist/credential-schema-mismatch-BKo5PjcQ.mjs +76 -0
  32. package/dist/credentials-CvmjU0lK.mjs +171 -0
  33. package/dist/credentials-OfVHOtG3.mjs +151216 -0
  34. package/dist/current-deployment-workflow-poHt27i3.mjs +94 -0
  35. package/dist/current.handler-B8zKzfPp.mjs +21 -0
  36. package/dist/delete.handler-bAu1iXVQ.mjs +17 -0
  37. package/dist/deploy-7Jjls436.mjs +26 -0
  38. package/dist/deploy-BOPIpRWm.mjs +74 -0
  39. package/dist/deploy-progress-BmGUNFKg.mjs +70 -0
  40. package/dist/deploy.handler-BAzgiNhd.mjs +370 -0
  41. package/dist/detect-env-access-CwkOYeYM-D_BCZqV6.mjs +209 -0
  42. package/dist/diff-utils-NEfcjqxt.mjs +185 -0
  43. package/dist/diff.handler-Du7SY8K4.mjs +47 -0
  44. package/dist/dist-BkJUoBiG.mjs +1116 -0
  45. package/dist/dist-CUK7yBM0.mjs +308 -0
  46. package/dist/env-91KwMKov.mjs +140 -0
  47. package/dist/env.handler-BAzBuMzQ.mjs +277 -0
  48. package/dist/error-boundary-VL-JLfIa.mjs +34 -0
  49. package/dist/file-metadata-D1vm-XY2.mjs +191 -0
  50. package/dist/get-intrinsic-zLxwtrLK.mjs +658 -0
  51. package/dist/import-module-CV84H5fZ-B_CBCmb4.mjs +1747 -0
  52. package/dist/init-DpMCotSK.mjs +45 -0
  53. package/dist/init.handler-CPRnif52.mjs +585 -0
  54. package/dist/inspect.handler-DT_cD036.mjs +146 -0
  55. package/dist/integration-catalog-Bt-L3GjF.mjs +104 -0
  56. package/dist/integrations-DlatPK4W.mjs +79 -0
  57. package/dist/keystroke.d.mts +3 -0
  58. package/dist/keystroke.mjs +707 -0
  59. package/dist/layout-CbMtQ2tm.mjs +67 -0
  60. package/dist/list-enrichment-y-cwizLr.mjs +189 -0
  61. package/dist/list.handler-BTWvCyjA.mjs +52 -0
  62. package/dist/list.handler-CWF_Dj15.mjs +24 -0
  63. package/dist/list.handler-CZ6G2x_G.mjs +75 -0
  64. package/dist/list.handler-DWaQkJaR.mjs +51 -0
  65. package/dist/list.handler-DqbFcBW7.mjs +180 -0
  66. package/dist/list.handler-lq3ZGAn4.mjs +104 -0
  67. package/dist/logs-BEg9L5l8.mjs +28 -0
  68. package/dist/logs.handler-6hoMBzqw.mjs +35 -0
  69. package/dist/logs.handler-BD_dXiL1.mjs +231 -0
  70. package/dist/metadata-layout-GUYIUo0i-_aG2zjue.mjs +5877 -0
  71. package/dist/normalize-path-CojS-CgQ-DLCOvnD1.mjs +20 -0
  72. package/dist/options-CeaTcFxP.mjs +43 -0
  73. package/dist/org-xLzBtt2_.mjs +41 -0
  74. package/dist/output-DM4b7KgY.mjs +72 -0
  75. package/dist/oxc-B3KI3rf_-n9d1hKNq.mjs +119 -0
  76. package/dist/paused.handler-BMFm9Cff.mjs +94 -0
  77. package/dist/project-config-D1qsQlO7.mjs +107 -0
  78. package/dist/projects-CHkRE9rS.mjs +1574 -0
  79. package/dist/projects-Cjb7sovS.mjs +30 -0
  80. package/dist/read-credential-keys-77a91T8M-KA0Iw0Z1.mjs +9 -0
  81. package/dist/register.handler-BPCdor1_.mjs +86 -0
  82. package/dist/requirements.handler-DPXdSks3.mjs +201 -0
  83. package/dist/resolve-project-DDJ29sCF.mjs +35 -0
  84. package/dist/rolldown-runtime-twds-ZHy-BWWzu8VG.mjs +15 -0
  85. package/dist/run-polling-CAgFRdK3.mjs +20 -0
  86. package/dist/runs-D9hNLb9A.mjs +259 -0
  87. package/dist/schedule-BXx3uXwr.mjs +1142 -0
  88. package/dist/schema-17qMfNyI.mjs +18 -0
  89. package/dist/schema-display-CgmeKigW.mjs +130 -0
  90. package/dist/schemas-CDib1RhE.mjs +125 -0
  91. package/dist/skills-sync.handler-DIy8GR16.mjs +34 -0
  92. package/dist/skills.command-CrjI2dN9.mjs +35 -0
  93. package/dist/skills.handler-Bz8bJKql.mjs +9 -0
  94. package/dist/source-analysis-Cj-ADyu--BJQcFPCG.mjs +144 -0
  95. package/dist/spinner-progress-DMVwgqO9.mjs +173 -0
  96. package/dist/src-C0X6u_Mw.mjs +1340 -0
  97. package/dist/src-eHwu-Gfw.mjs +369 -0
  98. package/dist/status.handler-BO4nwvWn.mjs +101 -0
  99. package/dist/switch.handler-D_9213Vf.mjs +51 -0
  100. package/dist/sync-BL_Mo5st.mjs +39 -0
  101. package/dist/sync-keystroke-agent-skills-Kx_H7UTd.mjs +70 -0
  102. package/dist/sync.handler-BUFPdzWz.mjs +82 -0
  103. package/dist/task-B2sZMaZu.mjs +8 -0
  104. package/dist/task-target-build-CBeCKbu2.mjs +432 -0
  105. package/dist/task-target-deploy-C5X-USeR.mjs +4 -0
  106. package/dist/task-target-deploy-CA6elFpF-BEr4gkol.mjs +271 -0
  107. package/dist/task-target-deploy-runner.d.mts +3 -0
  108. package/dist/task-target-deploy-runner.mjs +202 -0
  109. package/dist/test-BHTgR3UA.mjs +698 -0
  110. package/dist/test.handler-BcPQ8b74.mjs +13 -0
  111. package/dist/trigger-artifacts-DQPbQNqC-B4yeeFBY.mjs +239 -0
  112. package/dist/trigger-manifest-CY7brZeg.mjs +30 -0
  113. package/dist/try-deploy.handler-DqybNhXx.mjs +490 -0
  114. package/dist/upload-CkU--iDC.mjs +207 -0
  115. package/dist/upload.handler-DCtiznQp.mjs +441 -0
  116. package/dist/utils-CywxCDM7.mjs +14 -0
  117. package/dist/validate.handler-DOcTaJL0.mjs +280 -0
  118. package/dist/workflow-build-DBQaBfnn.mjs +1819 -0
  119. package/dist/workflow-bundler-BPiqVscj-X1PFFAuP.mjs +167 -0
  120. package/dist/workflows-g9z87AJJ.mjs +799 -0
  121. package/dist/writer-BG8poUm3-BbXlU2kI.mjs +426 -0
  122. package/package.json +87 -0
@@ -0,0 +1,1340 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { A as idNoSpacesString, B as RetryConfigSchema, C as CredentialSetManifestSchema, D as anyZodSchemaSchema, E as CREDENTIAL_VISIBILITIES, F as schemaToJsonSchema, I as trimmedNonEmptyString, M as jsonValueSchema, N as optionalDescriptionString, O as createStructuralSchema, P as optionalTrimmedNonEmptyString, R as validateConfig, T as CREDENTIAL_KINDS, i as parseDurationToMs, j as jsonSchemaObject, k as descriptionString, n as IANATimezoneSchema, r as ScheduleSchema, t as DurationSchema, w as credentialSetConfigSchema } from "./schedule-BXx3uXwr.mjs";
4
+ import { r as toDeclaredCredentialRequirements } from "./_manifest-JSRE3H8k.mjs";
5
+ import { n as TriggerRuntimeDescriptorSchema, r as triggerBaseConfigSchema } from "./schemas-CDib1RhE.mjs";
6
+ import { z } from "zod";
7
+ import { AsyncLocalStorage } from "node:async_hooks";
8
+ //#region ../../packages/workflow-core/src/internal/runtime-call-interceptor.ts
9
+ const ASYNC_STORAGE_KEY = "__ks_runtime_call_interceptor_async_storage";
10
+ const STACK_KEY = "__ks_runtime_call_interceptor_stack";
11
+ function getAsyncStorage() {
12
+ const g = globalThis;
13
+ if (ASYNC_STORAGE_KEY in g) return g[ASYNC_STORAGE_KEY];
14
+ const AsyncLocalStorage = g.process?.getBuiltinModule?.("async_hooks")?.AsyncLocalStorage;
15
+ const storage = AsyncLocalStorage ? new AsyncLocalStorage() : void 0;
16
+ g[ASYNC_STORAGE_KEY] = storage;
17
+ return storage;
18
+ }
19
+ function getStack() {
20
+ const g = globalThis;
21
+ if (!g[STACK_KEY]) g[STACK_KEY] = [];
22
+ return g[STACK_KEY];
23
+ }
24
+ function getActiveRuntimeCallInterceptor() {
25
+ const asyncStorage = getAsyncStorage();
26
+ if (asyncStorage) return asyncStorage.getStore()?.at(-1);
27
+ const stack = getStack();
28
+ return stack.length > 0 ? stack[stack.length - 1] : void 0;
29
+ }
30
+ //#endregion
31
+ //#region ../../packages/workflow-core/src/operation/integration-metadata-registry.ts
32
+ const REGISTRY_KEY$2 = "__ks_official_integration_metadata_registry";
33
+ function getRegistry$2() {
34
+ const g = globalThis;
35
+ if (!g[REGISTRY_KEY$2]) g[REGISTRY_KEY$2] = /* @__PURE__ */ new WeakMap();
36
+ return g[REGISTRY_KEY$2];
37
+ }
38
+ /** Register by instance identity. Parameters use `object` so consumers are not blocked when `.d.ts` bundles duplicate `Operation` (e.g. `_runtime` vs `./operation`). */
39
+ function registerOfficialIntegrationOperation(operation, metadata) {
40
+ getRegistry$2().set(operation, Object.freeze({ ...metadata }));
41
+ }
42
+ function getOfficialIntegrationMetadata(operation) {
43
+ return getRegistry$2().get(operation);
44
+ }
45
+ //#endregion
46
+ //#region ../../packages/workflow-core/src/shared/primitive.ts
47
+ /**
48
+ * Base class for all Keystroke primitives. The `kind` discriminator lets
49
+ * downstream code narrow primitive unions (e.g. `AnyAgentToolEntry =
50
+ * AnyOperation | AnyWorkflow`) without resorting to structural `'x' in tool`
51
+ * checks. Each subclass declares a literal `kind` matching its identity.
52
+ */
53
+ var Primitive = class {};
54
+ //#endregion
55
+ //#region ../../packages/workflow-core/src/internal/execution-scope.ts
56
+ const SCOPE_STACK_KEY = "__ks_execution_scope_stack__";
57
+ function getScopeStack() {
58
+ const g = globalThis;
59
+ if (!g[SCOPE_STACK_KEY]) g[SCOPE_STACK_KEY] = [];
60
+ return g[SCOPE_STACK_KEY];
61
+ }
62
+ function getCurrentScope() {
63
+ const stack = getScopeStack();
64
+ return stack[stack.length - 1] ?? getDefaultScope();
65
+ }
66
+ const DEFAULT_SCOPE_KEY = "__ks_execution_scope_default__";
67
+ function getDefaultScope() {
68
+ const g = globalThis;
69
+ if (!g[DEFAULT_SCOPE_KEY]) g[DEFAULT_SCOPE_KEY] = { stepContextProviders: [] };
70
+ return g[DEFAULT_SCOPE_KEY];
71
+ }
72
+ function getExecutionScopeWorkflowRuntime() {
73
+ return getCurrentScope().workflowRuntimeProvider?.();
74
+ }
75
+ function setExecutionScopeWorkflowRuntime(provider) {
76
+ const scope = getCurrentScope();
77
+ scope.workflowRuntimeProvider = provider;
78
+ }
79
+ function pushExecutionScopeStepContext(provider) {
80
+ const scope = getCurrentScope();
81
+ scope.stepContextProviders = [...scope.stepContextProviders, provider];
82
+ }
83
+ function clearExecutionScopeStepContexts() {
84
+ const scope = getCurrentScope();
85
+ scope.stepContextProviders = [];
86
+ }
87
+ function getExecutionScopeStepContextProvider() {
88
+ return getCurrentScope().stepContextProviders.at(-1);
89
+ }
90
+ function setExecutionScopeStepCredentialResolver(resolver) {
91
+ const scope = getCurrentScope();
92
+ scope.stepCredentialResolver = resolver;
93
+ }
94
+ function getExecutionScopeStepCredentialResolver() {
95
+ return getCurrentScope().stepCredentialResolver;
96
+ }
97
+ //#endregion
98
+ //#region ../../packages/workflow-core/src/workflow/context-registry.ts
99
+ function registerRuntime(registry) {
100
+ setExecutionScopeWorkflowRuntime(registry.getRuntime);
101
+ }
102
+ function clearRuntime() {
103
+ setExecutionScopeWorkflowRuntime(void 0);
104
+ }
105
+ function getRegisteredRuntime() {
106
+ return getExecutionScopeWorkflowRuntime();
107
+ }
108
+ //#endregion
109
+ //#region ../../packages/workflow-core/src/mcp-server/schemas.ts
110
+ const credentialSetInstanceSchema$3 = createStructuralSchema([
111
+ "id",
112
+ "auth",
113
+ "needsResolve"
114
+ ], "a CredentialSet instance");
115
+ const McpTransportSchema = z.discriminatedUnion("type", [
116
+ z.object({
117
+ type: z.literal("stdio"),
118
+ command: trimmedNonEmptyString("Command"),
119
+ args: z.array(z.string()).optional(),
120
+ env: z.record(z.string(), z.string()).optional()
121
+ }),
122
+ z.object({
123
+ type: z.literal("http"),
124
+ url: trimmedNonEmptyString("URL"),
125
+ headers: z.record(z.string(), z.string()).optional()
126
+ }),
127
+ z.object({
128
+ type: z.literal("sse"),
129
+ url: trimmedNonEmptyString("URL"),
130
+ headers: z.record(z.string(), z.string()).optional()
131
+ })
132
+ ]);
133
+ z.object({
134
+ id: trimmedNonEmptyString("MCP server ID"),
135
+ name: optionalTrimmedNonEmptyString("MCP server name"),
136
+ description: optionalDescriptionString("MCP server description"),
137
+ transport: McpTransportSchema,
138
+ credentialSets: z.array(credentialSetInstanceSchema$3).optional(),
139
+ credentials: z.function().optional()
140
+ });
141
+ const McpServerManifestSchema = z.object({
142
+ manifestVersion: z.literal(1),
143
+ type: z.literal("mcpServer"),
144
+ id: z.string().min(1),
145
+ name: z.string().min(1),
146
+ description: z.string().optional(),
147
+ transport: McpTransportSchema,
148
+ credentialSets: z.array(CredentialSetManifestSchema),
149
+ credentialInjection: z.object({
150
+ env: z.record(z.string(), z.object({
151
+ credentialSetId: z.string().min(1),
152
+ key: z.string().min(1)
153
+ })).optional(),
154
+ headers: z.record(z.string(), z.object({
155
+ credentialSetId: z.string().min(1),
156
+ key: z.string().min(1)
157
+ })).optional()
158
+ }).optional()
159
+ });
160
+ //#endregion
161
+ //#region ../../packages/workflow-core/src/messaging-gateway/schemas.ts
162
+ const credentialSetInstanceSchema$2 = createStructuralSchema([
163
+ "id",
164
+ "auth",
165
+ "needsResolve"
166
+ ], "a CredentialSet instance");
167
+ const MessagingGatewayModeSchema = z.enum(["platform", "custom"]);
168
+ const MessagingGatewayCredentialScopeSchema = z.enum(["organization", "project"]);
169
+ z.object({
170
+ id: idNoSpacesString("MessagingGateway id"),
171
+ name: optionalDescriptionString("MessagingGateway name"),
172
+ description: optionalDescriptionString("MessagingGateway description"),
173
+ provider: z.string().min(1, "MessagingGateway provider is required"),
174
+ mode: MessagingGatewayModeSchema,
175
+ credentialSet: credentialSetInstanceSchema$2,
176
+ credentialScope: MessagingGatewayCredentialScopeSchema.optional(),
177
+ appRef: z.string().min(1).optional()
178
+ });
179
+ const MessagingGatewayManifestSchema = z.object({
180
+ manifestVersion: z.literal(1),
181
+ type: z.literal("messaging-gateway"),
182
+ id: z.string().min(1),
183
+ name: z.string().min(1),
184
+ description: z.string().optional(),
185
+ provider: z.string().min(1),
186
+ mode: MessagingGatewayModeSchema,
187
+ credentialSet: CredentialSetManifestSchema,
188
+ credentialScope: MessagingGatewayCredentialScopeSchema.optional(),
189
+ appRef: z.string().min(1).optional()
190
+ });
191
+ //#endregion
192
+ //#region ../../packages/workflow-core/src/sandbox/schemas.ts
193
+ /**
194
+ * `workdir` must be `/workspace` or a subdirectory so it lands inside the
195
+ * persistent bind mount used by `bootSandbox`. Anything outside `/workspace`
196
+ * is ephemeral today (and not captured by future snapshots' instance state).
197
+ */
198
+ const WorkdirSchema = z.string().trim().min(1).refine((value) => value === "/workspace" || value.startsWith("/workspace/"), { error: "workdir must be \"/workspace\" or a subdirectory of \"/workspace\"" });
199
+ const SandboxRuntimeSchema = z.object({
200
+ /**
201
+ * Commands the runtime executes inside the sandbox on EVERY boot, after
202
+ * `setupCommands` (and after a snapshot warm-boot, where setupCommands are
203
+ * skipped). Use for `git pull`, `pnpm build`, or anything that should
204
+ * refresh on each invocation. Each command runs with `cwd = workdir`.
205
+ */
206
+ runCommands: z.array(z.string().trim().min(1)).default([]),
207
+ env: z.record(z.string(), z.string()).default({}),
208
+ workdir: WorkdirSchema.optional()
209
+ });
210
+ const SandboxFileSourceSchema = z.discriminatedUnion("type", [z.object({
211
+ type: z.literal("git"),
212
+ /** Remote git URL to clone. */
213
+ url: trimmedNonEmptyString("Git URL"),
214
+ /** Branch to clone. Omit for default branch. */
215
+ branch: z.string().optional(),
216
+ /**
217
+ * Where to clone inside the VM. Relative paths resolve against the
218
+ * sandbox `workdir`; absolute paths must stay under `/workspace`. Omit
219
+ * to default to `<workdir>/<repo-basename>`.
220
+ */
221
+ target: z.string().optional()
222
+ }), z.object({
223
+ type: z.literal("local"),
224
+ /** Source path on the host (the dev's machine), resolved against project root. */
225
+ path: trimmedNonEmptyString("Local path"),
226
+ /**
227
+ * Where the file/dir lands inside the VM. Relative paths resolve
228
+ * against the sandbox `workdir`; absolute paths must stay under
229
+ * `/workspace`. Omit to default to `<workdir>/<basename(path)>`.
230
+ */
231
+ target: z.string().optional()
232
+ })]);
233
+ z.object({
234
+ id: optionalTrimmedNonEmptyString("Sandbox ID"),
235
+ name: optionalTrimmedNonEmptyString("Sandbox name"),
236
+ description: optionalDescriptionString("Sandbox description"),
237
+ runtime: SandboxRuntimeSchema.optional(),
238
+ fileSources: z.array(SandboxFileSourceSchema).optional(),
239
+ setupCommands: z.array(z.string()).optional()
240
+ });
241
+ const SandboxManifestSchema = z.object({
242
+ manifestVersion: z.literal(1),
243
+ type: z.literal("sandbox"),
244
+ id: z.string().min(1),
245
+ name: z.string().min(1),
246
+ description: z.string().optional(),
247
+ runtime: SandboxRuntimeSchema,
248
+ fileSources: z.array(SandboxFileSourceSchema),
249
+ setupCommands: z.array(z.string())
250
+ });
251
+ //#endregion
252
+ //#region ../../packages/workflow-core/src/agent/types.ts
253
+ const AGENT_RUNTIME_KIND_DECLARATIVE = "declarative";
254
+ const AGENT_RUNTIME_KIND_RUNNABLE = "runnable";
255
+ //#endregion
256
+ //#region ../../packages/workflow-core/src/agent/schemas.ts
257
+ const AgentThinkingLevelSchema = z.enum([
258
+ "off",
259
+ "minimal",
260
+ "low",
261
+ "medium",
262
+ "high",
263
+ "xhigh"
264
+ ]);
265
+ const mcpServerInstanceSchema = createStructuralSchema([
266
+ "id",
267
+ "transport",
268
+ "credentialSets"
269
+ ], "a McpServer instance");
270
+ const sandboxInstanceSchema = createStructuralSchema([
271
+ "id",
272
+ "runtime",
273
+ "fileSources",
274
+ "setupCommands"
275
+ ], "a Sandbox instance");
276
+ const messagingGatewayInstanceSchema = createStructuralSchema([
277
+ "id",
278
+ "provider",
279
+ "mode",
280
+ "credentialSet"
281
+ ], "a MessagingGateway instance");
282
+ const SkillSourceSchema = z.object({ path: z.string() });
283
+ const AgentHooksSchema = z.object({
284
+ onToolStart: z.function().optional(),
285
+ onToolEnd: z.function().optional(),
286
+ onStep: z.function().optional()
287
+ }).strict();
288
+ const AgentToolSourceKindSchema = z.enum(["operation", "workflow"]);
289
+ const AgentToolCredentialSetReferenceSchema = z.object({
290
+ id: z.string(),
291
+ required: z.boolean()
292
+ });
293
+ z.object({
294
+ id: trimmedNonEmptyString("Agent ID"),
295
+ name: trimmedNonEmptyString("Agent name"),
296
+ description: optionalDescriptionString("Agent description"),
297
+ systemPrompt: z.string().min(1, { error: "System prompt is required" }),
298
+ model: trimmedNonEmptyString("Model"),
299
+ thinkingLevel: AgentThinkingLevelSchema.optional(),
300
+ input: anyZodSchemaSchema.optional(),
301
+ output: anyZodSchemaSchema.optional(),
302
+ tools: z.array(z.unknown()).optional(),
303
+ mcpServers: z.array(mcpServerInstanceSchema).optional(),
304
+ sandbox: sandboxInstanceSchema.optional(),
305
+ skills: z.array(SkillSourceSchema).optional(),
306
+ enableMemory: z.boolean().default(true),
307
+ enableDatabase: z.boolean().default(true),
308
+ messaging: z.array(messagingGatewayInstanceSchema).optional(),
309
+ maxSteps: z.number().int().nonnegative().optional(),
310
+ hooks: AgentHooksSchema.optional(),
311
+ run: z.function().optional(),
312
+ stream: z.function().optional()
313
+ });
314
+ const AgentManifestSchema = z.object({
315
+ manifestVersion: z.literal(1),
316
+ type: z.literal("agent"),
317
+ id: z.string().min(1),
318
+ authoredAgentId: z.string().min(1),
319
+ name: z.string().min(1),
320
+ runtimeKind: z.enum([AGENT_RUNTIME_KIND_DECLARATIVE, AGENT_RUNTIME_KIND_RUNNABLE]),
321
+ description: z.string().optional(),
322
+ systemPrompt: z.string(),
323
+ model: z.string(),
324
+ thinkingLevel: AgentThinkingLevelSchema,
325
+ input: jsonSchemaObject,
326
+ output: jsonSchemaObject,
327
+ maxSteps: z.number(),
328
+ credentialSets: z.array(CredentialSetManifestSchema).optional(),
329
+ tools: z.array(z.object({
330
+ id: z.string(),
331
+ displayName: z.string(),
332
+ description: z.string().optional(),
333
+ sourceKind: AgentToolSourceKindSchema,
334
+ authoredOperationId: z.string().optional(),
335
+ authoredWorkflowId: z.string().optional(),
336
+ integrationId: z.string().optional(),
337
+ largeResultMode: z.enum(["reject", "ref"]).optional(),
338
+ midSessionSnapshot: z.boolean().optional(),
339
+ credentialSets: z.array(AgentToolCredentialSetReferenceSchema).optional()
340
+ })),
341
+ skills: z.array(SkillSourceSchema).optional(),
342
+ enableMemory: z.boolean().default(true),
343
+ enableDatabase: z.boolean().default(true),
344
+ mcpServers: z.array(McpServerManifestSchema),
345
+ sandbox: SandboxManifestSchema.optional(),
346
+ messaging: z.array(MessagingGatewayManifestSchema).optional()
347
+ });
348
+ z.string();
349
+ z.unknown();
350
+ //#endregion
351
+ //#region ../../packages/workflow-core/src/credential-set/zod-shape.ts
352
+ /**
353
+ * Shape-reflection helpers for `CredentialSet` schemas.
354
+ *
355
+ * Shared between the `CredentialSet` constructor (which memoizes the key
356
+ * lists onto the instance) and the construction-time identity registry
357
+ * (which hashes the same shape into a fingerprint). Kept in its own
358
+ * module to avoid an import cycle between `CredentialSet.ts` and
359
+ * `registry.ts`.
360
+ */
361
+ /**
362
+ * Inspect a `z.ZodObject` once and return its sorted property keys plus the
363
+ * subset wrapped in `.optional()` / `.default()`.
364
+ *
365
+ * Tolerates both the Zod v3 `.shape` getter and the Zod v4 `_def.shape`
366
+ * thunk so the helper stays stable across schema versions.
367
+ */
368
+ function readZodObjectKeyMetadata(schema) {
369
+ const resolvedShape = resolveZodObjectShape(schema);
370
+ if (resolvedShape === null || typeof resolvedShape !== "object") return {
371
+ all: [],
372
+ optional: []
373
+ };
374
+ const entries = Object.entries(resolvedShape);
375
+ return {
376
+ all: entries.map(([key]) => key).sort(),
377
+ optional: entries.filter(([, field]) => field instanceof z.ZodOptional || field instanceof z.ZodDefault).map(([key]) => key).sort()
378
+ };
379
+ }
380
+ /**
381
+ * Resolve the raw shape record of a `z.ZodObject` tolerating v3 and v4
382
+ * internal layouts. Returns `null` when the object cannot be reflected.
383
+ */
384
+ function resolveZodObjectShape(schema) {
385
+ const internals = schema;
386
+ const rawShape = internals._def?.shape ?? internals.shape;
387
+ const resolved = typeof rawShape === "function" ? rawShape() : rawShape;
388
+ if (resolved === null || typeof resolved !== "object") return null;
389
+ return resolved;
390
+ }
391
+ //#endregion
392
+ //#region ../../packages/workflow-core/src/credential-set/registry.ts
393
+ /**
394
+ * The backing map is keyed on `globalThis` under a well-known
395
+ * `Symbol.for(...)` so (a) multiple bundles/subpaths of this package share
396
+ * a single registry instance at runtime and (b) host-side test harnesses
397
+ * that cannot take a direct dependency on `@keystroke/workflow-core`
398
+ * (e.g. `@keystroke/test-utils`, which would otherwise form a cycle
399
+ * through `@keystroke/local-memory`) can still drive the reset hook by
400
+ * clearing the same `Map` via the exported {@link CREDENTIAL_SET_REGISTRY_SYMBOL}.
401
+ */
402
+ const CREDENTIAL_SET_REGISTRY_SYMBOL = Symbol.for("@keystroke/workflow-core/credential-set-registry");
403
+ function getRegistry$1() {
404
+ const globalWithRegistry = globalThis;
405
+ const existing = globalWithRegistry[CREDENTIAL_SET_REGISTRY_SYMBOL];
406
+ if (existing) return existing;
407
+ const fresh = /* @__PURE__ */ new Map();
408
+ globalWithRegistry[CREDENTIAL_SET_REGISTRY_SYMBOL] = fresh;
409
+ return fresh;
410
+ }
411
+ /**
412
+ * Thrown when two `CredentialSet` instances share the same
413
+ * `resolvedCredentialSetId` but declare different shapes.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * new CredentialSet({ id: 'stripe', auth: z.object({ STRIPE_SECRET_KEY: z.string() }) });
418
+ * // later, in a maintenance script:
419
+ * new CredentialSet({ id: 'stripe', auth: z.object({ STRIPE_API_KEY: z.string() }) });
420
+ * // -> throws DuplicateCredentialSetDefinitionError
421
+ * ```
422
+ */
423
+ var DuplicateCredentialSetDefinitionError = class extends Error {
424
+ manifestId;
425
+ firstDeclaredAt;
426
+ secondDeclaredAt;
427
+ firstFingerprint;
428
+ secondFingerprint;
429
+ constructor(options) {
430
+ super([
431
+ `Two CredentialSet instances were declared with the same manifestId "${options.manifestId}",`,
432
+ `but they have different shapes:`,
433
+ ` first (${options.firstDeclaredAt}): ${options.firstFingerprint}`,
434
+ ` second (${options.secondDeclaredAt}): ${options.secondFingerprint}`,
435
+ "",
436
+ "If you meant to share these credentials, import the same instance from a single module.",
437
+ "If you meant two distinct credential sets, give them different ids (or namespaces)."
438
+ ].join("\n"));
439
+ this.name = "DuplicateCredentialSetDefinitionError";
440
+ this.manifestId = options.manifestId;
441
+ this.firstDeclaredAt = options.firstDeclaredAt;
442
+ this.secondDeclaredAt = options.secondDeclaredAt;
443
+ this.firstFingerprint = options.firstFingerprint;
444
+ this.secondFingerprint = options.secondFingerprint;
445
+ }
446
+ };
447
+ /**
448
+ * Register a newly constructed credential set by its
449
+ * `resolvedCredentialSetId`. Called once per `CredentialSet` constructor.
450
+ *
451
+ * @throws {DuplicateCredentialSetDefinitionError} when the id was
452
+ * previously registered with a different schema fingerprint.
453
+ */
454
+ function registerCredentialSet(params) {
455
+ const registry = getRegistry$1();
456
+ const existing = registry.get(params.manifestId);
457
+ if (existing && existing.fingerprint !== params.fingerprint) throw new DuplicateCredentialSetDefinitionError({
458
+ manifestId: params.manifestId,
459
+ firstDeclaredAt: existing.sourceHint,
460
+ secondDeclaredAt: params.sourceHint,
461
+ firstFingerprint: existing.fingerprint,
462
+ secondFingerprint: params.fingerprint
463
+ });
464
+ registry.set(params.manifestId, {
465
+ fingerprint: params.fingerprint,
466
+ sourceHint: params.sourceHint
467
+ });
468
+ }
469
+ /**
470
+ * Produce a deterministic fingerprint of a `CredentialSet`'s auth (and
471
+ * `stored`, when present) schema. The fingerprint is a stable string of
472
+ * sorted `key:typeTag` pairs separated by `|`, with the stored shape
473
+ * concatenated after a `#` delimiter when the credential set declares a
474
+ * `stored` schema.
475
+ *
476
+ * Refinements (`.min(1)`, regex, etc.) are intentionally ignored — they
477
+ * are not breaking changes for vault compatibility. Structural changes
478
+ * (added keys, renamed keys, changed underlying Zod types, flipping
479
+ * required ↔ optional) produce a different fingerprint.
480
+ *
481
+ * @see registerCredentialSet
482
+ */
483
+ function fingerprintAuthShape(auth, stored) {
484
+ const authPart = shapeSignature(auth);
485
+ if (!stored) return authPart;
486
+ return `${authPart}#${shapeSignature(stored)}`;
487
+ }
488
+ function shapeSignature(schema) {
489
+ const resolvedShape = resolveZodObjectShape(schema);
490
+ if (!resolvedShape) return "";
491
+ return readZodObjectKeyMetadata(schema).all.map((key) => `${key}:${typeTag(resolvedShape[key])}`).sort().join("|");
492
+ }
493
+ function typeTag(zodType) {
494
+ if (zodType === null || zodType === void 0) return "Unknown";
495
+ const def = zodType._def;
496
+ return def?.typeName ?? def?.type ?? "Unknown";
497
+ }
498
+ /**
499
+ * Best-effort source hint — a short file:line string recovered from a
500
+ * lightweight stack trace at call time. Used only in the error message;
501
+ * does not affect correctness of the registry comparison.
502
+ *
503
+ * @remarks
504
+ * The hint format is `path/to/file.ts:line:col` when a repo frame can
505
+ * be isolated, and `'unknown'` otherwise. Callers should treat the
506
+ * value as opaque.
507
+ */
508
+ function captureStackOrigin() {
509
+ const frame = ((/* @__PURE__ */ new Error()).stack?.split("\n") ?? []).slice(1).find((line) => (line.includes("/packages/") || line.includes("/apps/")) && !/\/credential-set\/registry\.[mc]?[jt]s/.test(line) && !/\/credential-set\/CredentialSet\.[mc]?[jt]s/.test(line));
510
+ if (!frame) return "unknown";
511
+ const parens = frame.match(/\(([^)]+)\)/);
512
+ if (parens?.[1]) return parens[1];
513
+ const bare = frame.match(/at\s+(.+)$/);
514
+ if (bare?.[1]) return bare[1];
515
+ return "unknown";
516
+ }
517
+ //#endregion
518
+ //#region ../../packages/workflow-core/src/credential-set/CredentialSet.ts
519
+ var CredentialSet = class extends Primitive {
520
+ kind = "credential-set";
521
+ id;
522
+ /** Optional namespace. Official Keystroke integrations use 'keystroke'. */
523
+ namespace;
524
+ /**
525
+ * Computed namespaced identifier used for storage and manifest-facing wiring.
526
+ *
527
+ * Use this value for DB storage, manifest entries, and explicit credential
528
+ * bindings. Do not use it as the runtime `ctx.credentials` key inside authored
529
+ * code.
530
+ *
531
+ * @remarks
532
+ * Runtime credential context is keyed by the raw `id`, not this field. That
533
+ * is why `ctx.credentials.slack` uses `slack` rather than `keystroke:slack`.
534
+ */
535
+ resolvedCredentialSetId;
536
+ name;
537
+ description;
538
+ auth;
539
+ stored;
540
+ resolve;
541
+ /**
542
+ * Run-scoped cache TTL in milliseconds for the {@link resolve} output.
543
+ *
544
+ * Always a number; `0` means "no cache". Consumed by the credential
545
+ * runtime's `ResolveCache` when present.
546
+ *
547
+ * @see {@link CredentialSetConfig.resolveCacheMs}
548
+ */
549
+ resolveCacheMs;
550
+ /**
551
+ * Platform-side `stored`→`auth` transform. Mutually exclusive with
552
+ * {@link resolve}. Runs on the trusted host via
553
+ * `@keystroke/credential-runtime`'s `executePlatformResolve` helper.
554
+ *
555
+ * @see {@link resolveLocation}
556
+ * @see {@link platformEnvAllowlist}
557
+ */
558
+ resolveAtPlatform;
559
+ /**
560
+ * Resolved description of where the `stored`→`auth` transform runs.
561
+ *
562
+ * Computed at construction as `'platform'` when `resolveAtPlatform`
563
+ * is declared, `'sandbox'` when `resolve` is declared, `'none'`
564
+ * otherwise. The credential runtime's phase 3 branches on this value
565
+ * to pick the right execution location.
566
+ *
567
+ * @see {@link CredentialResolveLocation}
568
+ */
569
+ resolveLocation;
570
+ /**
571
+ * Env-var names `resolveAtPlatform` may read through `ctx.env`.
572
+ * Frozen at construction. Empty when `resolveLocation !== 'platform'`.
573
+ *
574
+ * @see {@link PlatformResolveContext.env}
575
+ */
576
+ platformEnvAllowlist;
577
+ needsResolve;
578
+ /** Required when namespace is 'keystroke'. Optional for user-authored credential sets. */
579
+ platformMetadata;
580
+ proxy;
581
+ needsRawSecret;
582
+ /**
583
+ * Policy when a step throws `CredentialRevokedError` against this credential set.
584
+ *
585
+ * @see {@link import('./types').CredentialSetConfig.onCredentialRevoked}
586
+ */
587
+ onCredentialRevoked;
588
+ /**
589
+ * Describe the optional user-facing connect flow for this credential set.
590
+ *
591
+ * Set this when the credential should be uploaded through a manual form or an
592
+ * OAuth handshake. Omit it for platform-seeded or internal credentials that do
593
+ * not expose a user-facing connect flow.
594
+ *
595
+ * @see {@link CredentialSetConfig.connection}
596
+ */
597
+ connection;
598
+ /** Sorted keys declared on the `auth` schema. Source of truth for what the
599
+ * built manifest advertises this credential set requires. Memoized at
600
+ * construction so neither the build pipeline nor the runtime needs to walk
601
+ * the Zod schema again. */
602
+ credentialKeys;
603
+ /** Subset of `credentialKeys` declared as `z.optional()` / `z.default()` on
604
+ * `auth`. Used by the build pipeline to record which vault keys may be
605
+ * absent without failing manifest declaration. */
606
+ optionalCredentialKeys;
607
+ /** Sorted keys declared on `stored` (or `auth` when no `stored` schema is
608
+ * provided). This is what the runtime credential resolver actually fetches
609
+ * from the vault, since `stored` represents the persisted shape. */
610
+ storedCredentialKeys;
611
+ /** Subset of `storedCredentialKeys` declared as `z.optional()` /
612
+ * `z.default()`. Tells the runtime resolver which vault keys are allowed to
613
+ * be missing. */
614
+ optionalStoredCredentialKeys;
615
+ #manifest;
616
+ constructor(config) {
617
+ super();
618
+ const validatedConfig = validateConfig(credentialSetConfigSchema, (() => {
619
+ if (config.platformMetadata !== void 0) return config;
620
+ if (config.namespace === "keystroke") return config;
621
+ if (config.connection !== void 0) return {
622
+ ...config,
623
+ platformMetadata: {
624
+ kind: CREDENTIAL_KINDS["user-connection"],
625
+ visibility: CREDENTIAL_VISIBILITIES["user-visible"]
626
+ }
627
+ };
628
+ return config;
629
+ })());
630
+ const hasStored = validatedConfig.stored !== void 0;
631
+ const hasResolve = validatedConfig.resolve !== void 0;
632
+ const hasResolveAtPlatform = validatedConfig.resolveAtPlatform !== void 0;
633
+ if (hasResolve && hasResolveAtPlatform) throw new Error(`CredentialSet "${validatedConfig.id}": "resolve" and "resolveAtPlatform" are mutually exclusive.`);
634
+ if ((hasResolve || hasResolveAtPlatform) && !hasStored) throw new Error(`CredentialSet "${validatedConfig.id}": "resolve" / "resolveAtPlatform" require "stored".`);
635
+ if (hasStored && !hasResolve && !hasResolveAtPlatform) throw new Error(`CredentialSet "${validatedConfig.id}": "stored" requires either "resolve" or "resolveAtPlatform".`);
636
+ if (validatedConfig.platformEnvAllowlist !== void 0 && validatedConfig.platformEnvAllowlist.length > 0 && !hasResolveAtPlatform) throw new Error(`CredentialSet "${validatedConfig.id}": "platformEnvAllowlist" requires "resolveAtPlatform".`);
637
+ this.id = validatedConfig.id;
638
+ this.namespace = validatedConfig.namespace;
639
+ this.resolvedCredentialSetId = this.namespace ? `${this.namespace}:${this.id}` : this.id;
640
+ registerCredentialSet({
641
+ manifestId: this.resolvedCredentialSetId,
642
+ fingerprint: fingerprintAuthShape(validatedConfig.auth, validatedConfig.stored),
643
+ sourceHint: captureStackOrigin()
644
+ });
645
+ this.name = validatedConfig.name ?? validatedConfig.id;
646
+ this.description = validatedConfig.description;
647
+ this.auth = validatedConfig.auth;
648
+ this.stored = validatedConfig.stored;
649
+ this.resolve = validatedConfig.resolve;
650
+ this.resolveCacheMs = hasResolve && typeof validatedConfig.resolveCacheMs === "number" ? validatedConfig.resolveCacheMs : 0;
651
+ this.resolveAtPlatform = validatedConfig.resolveAtPlatform;
652
+ this.resolveLocation = hasResolve ? "sandbox" : hasResolveAtPlatform ? "platform" : "none";
653
+ this.platformEnvAllowlist = Object.freeze(validatedConfig.platformEnvAllowlist ? [...validatedConfig.platformEnvAllowlist] : []);
654
+ this.needsResolve = hasStored && (hasResolve || hasResolveAtPlatform);
655
+ this.platformMetadata = validatedConfig.platformMetadata;
656
+ this.proxy = validatedConfig.proxy;
657
+ this.needsRawSecret = validatedConfig.needsRawSecret;
658
+ this.onCredentialRevoked = validatedConfig.onCredentialRevoked;
659
+ this.connection = validatedConfig.connection;
660
+ if (this.onCredentialRevoked === "retry-once" && !this.resolve) warnRetryOnceWithoutResolve(this.resolvedCredentialSetId);
661
+ const authKeyMetadata = readZodObjectKeyMetadata(this.auth);
662
+ const storedKeyMetadata = this.stored ? readZodObjectKeyMetadata(this.stored) : authKeyMetadata;
663
+ this.credentialKeys = Object.freeze(authKeyMetadata.all);
664
+ this.optionalCredentialKeys = Object.freeze(authKeyMetadata.optional);
665
+ this.storedCredentialKeys = Object.freeze(storedKeyMetadata.all);
666
+ this.optionalStoredCredentialKeys = Object.freeze(storedKeyMetadata.optional);
667
+ if (this.connection?.kind === "oauth") {
668
+ assertDeclarativeVaultKeysAreKnown(validatedConfig.id, this.connection.vault, this.storedCredentialKeys);
669
+ assertOAuthClientSourceIsWellFormed(validatedConfig.id, this.connection);
670
+ }
671
+ this.#manifest = Object.freeze(CredentialSetManifestSchema.parse({
672
+ manifestVersion: 1,
673
+ type: "credentialSet",
674
+ id: this.id,
675
+ namespace: this.namespace,
676
+ resolvedCredentialSetId: this.resolvedCredentialSetId,
677
+ name: this.name,
678
+ auth: schemaToJsonSchema(this.auth),
679
+ ...this.description ? { description: this.description } : {},
680
+ ...this.stored ? { stored: schemaToJsonSchema(this.stored) } : {},
681
+ ...this.needsResolve ? { needsResolve: true } : {},
682
+ ...this.resolveCacheMs > 0 ? { resolveCacheMs: this.resolveCacheMs } : {},
683
+ ...this.resolveLocation !== "none" ? { resolveLocation: this.resolveLocation } : {},
684
+ ...this.platformEnvAllowlist.length > 0 ? { platformEnvAllowlist: [...this.platformEnvAllowlist] } : {},
685
+ ...this.platformMetadata ? { platformMetadata: this.platformMetadata } : {},
686
+ ...this.proxy ? { proxy: this.proxy } : {},
687
+ ...this.needsRawSecret === true ? { needsRawSecret: true } : {},
688
+ ...this.onCredentialRevoked ? { onCredentialRevoked: this.onCredentialRevoked } : {},
689
+ ...this.connection ? { connection: serializeConnectionForManifest(this.connection) } : {}
690
+ }));
691
+ Object.freeze(this);
692
+ }
693
+ describe() {
694
+ return `CredentialSet "${this.name}" (${this.resolvedCredentialSetId})`;
695
+ }
696
+ toManifest() {
697
+ return this.#manifest;
698
+ }
699
+ };
700
+ /** Strip runtime hooks from the connection config before serializing to the
701
+ * manifest. Hooks are functions and not manifest-safe; the manifest captures
702
+ * only declarative metadata (kind, URLs, scopes, etc.).
703
+ *
704
+ * Declarative {@link Vault} mappings serialize as-is. Function-form vault
705
+ * mappings cannot be serialized (they are runtime closures); the serialized
706
+ * manifest records only the kind marker so the shape stays well-typed. */
707
+ function serializeConnectionForManifest(connection) {
708
+ if (connection.kind === "manual") return {
709
+ kind: "manual",
710
+ ...connection.instructions ? { instructions: connection.instructions } : {}
711
+ };
712
+ if (connection.kind === "oauth") return {
713
+ kind: "oauth",
714
+ authUrl: connection.authUrl,
715
+ tokenUrl: connection.tokenUrl,
716
+ scopes: connection.scopes,
717
+ tokenType: connection.tokenType,
718
+ vault: serializeVaultForManifest(connection.vault),
719
+ ...connection.revokeUrl !== void 0 ? { revokeUrl: connection.revokeUrl } : {},
720
+ ...connection.pkce === true ? { pkce: true } : {},
721
+ ...typeof connection.defaultExpiresInSeconds === "number" ? { defaultExpiresInSeconds: connection.defaultExpiresInSeconds } : {},
722
+ ...connection.oauthClientSource ? { oauthClientSource: serializeOAuthClientSourceForManifest(connection.oauthClientSource) } : {}
723
+ };
724
+ if (connection.kind === "credentials-exchange") return {
725
+ kind: "credentials-exchange",
726
+ input: schemaToJsonSchema(connection.input),
727
+ ...connection.instructions ? { instructions: connection.instructions } : {}
728
+ };
729
+ throw new Error(`Unknown connection kind: ${JSON.stringify(connection)}`);
730
+ }
731
+ /** Project the live {@link OAuthClientSource} into its manifest-safe form.
732
+ * The workspace variant substitutes the object reference with the
733
+ * referenced credential set's `resolvedCredentialSetId` so the manifest
734
+ * carries a stable, persistable id instead of a closure-backed object. */
735
+ function serializeOAuthClientSourceForManifest(source) {
736
+ if (source.kind === "keystroke-platform") return { kind: "keystroke-platform" };
737
+ return {
738
+ kind: "workspace-provider-app",
739
+ credentialSetId: source.credentialSet.resolvedCredentialSetId,
740
+ ...source.keyMap ? { keyMap: source.keyMap } : {}
741
+ };
742
+ }
743
+ function serializeVaultForManifest(vault) {
744
+ if ("build" in vault) return {
745
+ kind: "function",
746
+ accessTokenKey: vault.accessTokenKey
747
+ };
748
+ return {
749
+ kind: "declarative",
750
+ accessToken: vault.accessToken,
751
+ ...vault.instanceUrl !== void 0 ? { instanceUrl: vault.instanceUrl } : {},
752
+ ...vault.raw !== void 0 ? { raw: { ...vault.raw } } : {}
753
+ };
754
+ }
755
+ /** Tracks credential-set ids that already emitted the `retry-once + no resolve`
756
+ * construction warning so repeated tree-shake re-registration in the same
757
+ * process does not spam the log. */
758
+ const warnedRetryOnceWithoutResolve = /* @__PURE__ */ new Set();
759
+ function warnRetryOnceWithoutResolve(resolvedCredentialSetId) {
760
+ if (warnedRetryOnceWithoutResolve.has(resolvedCredentialSetId)) return;
761
+ warnedRetryOnceWithoutResolve.add(resolvedCredentialSetId);
762
+ console.warn(`CredentialSet "${resolvedCredentialSetId}": onCredentialRevoked: 'retry-once' is set but no resolve is declared. The retry will be a no-op because re-resolving stored values would produce the same result.`);
763
+ }
764
+ /** Runtime safety net: the referenced `clientApp` for a
765
+ * `workspace-provider-app` `oauthClientSource` must declare both the
766
+ * clientId and clientSecret keys (either under the default names or via
767
+ * `keyMap` aliases). The `visibility: 'internal'` check happens earlier at
768
+ * the Zod refinement layer; this validator covers the deeper schema-shape
769
+ * check so authors catch mismatches at construction rather than at
770
+ * handshake time. */
771
+ function assertOAuthClientSourceIsWellFormed(credentialSetId, connection) {
772
+ const source = connection.oauthClientSource;
773
+ if (!source || source.kind !== "workspace-provider-app") return;
774
+ const clientIdKey = source.keyMap?.clientId ?? "clientId";
775
+ const clientSecretKey = source.keyMap?.clientSecret ?? "clientSecret";
776
+ const referenced = source.credentialSet;
777
+ const keys = new Set(referenced.credentialKeys);
778
+ const missing = [];
779
+ if (!keys.has(clientIdKey)) missing.push(`clientId key "${clientIdKey}"`);
780
+ if (!keys.has(clientSecretKey)) missing.push(`clientSecret key "${clientSecretKey}"`);
781
+ if (missing.length > 0) throw new Error(`CredentialSet "${credentialSetId}": oauthClientSource.credentialSet "${referenced.id}" does not declare ${missing.join(" or ")}. Adjust the referenced credential set's auth schema or pass an explicit keyMap.`);
782
+ }
783
+ /** Runtime safety net: when a caller constructs with a typed-erased shape
784
+ * (e.g. via `as never`), verify every declared vault slot still maps to a
785
+ * known stored/auth schema key. The static `CredentialVaultKeys` parameter on
786
+ * `CredentialSetConfig.connection` catches typos at the construction site;
787
+ * this runtime check catches the erased case. */
788
+ function assertDeclarativeVaultKeysAreKnown(credentialSetId, vault, knownKeys) {
789
+ if ("build" in vault) return;
790
+ const known = new Set(knownKeys);
791
+ const invalid = [];
792
+ if (!known.has(vault.accessToken)) invalid.push(`vault.accessToken="${vault.accessToken}"`);
793
+ if (vault.instanceUrl !== void 0 && !known.has(vault.instanceUrl)) invalid.push(`vault.instanceUrl="${vault.instanceUrl}"`);
794
+ if (vault.raw) {
795
+ for (const rawKey of Object.keys(vault.raw)) if (!known.has(rawKey)) invalid.push(`vault.raw.${rawKey}`);
796
+ }
797
+ if (invalid.length > 0) throw new Error(`CredentialSet "${credentialSetId}": OAuth vault references unknown credential keys (${invalid.join(", ")}). Valid keys are [${[...known].sort().join(", ")}].`);
798
+ }
799
+ //#endregion
800
+ //#region ../../packages/workflow-core/src/shared/credential-sets.ts
801
+ function cloneCredentialSets(credentialSets) {
802
+ return credentialSets ? [...credentialSets] : void 0;
803
+ }
804
+ function assertUniqueCredentialSetIds(credentialSets, ownerKind, ownerName) {
805
+ const seenCredentialSetIds = /* @__PURE__ */ new Set();
806
+ for (const credentialSet of credentialSets) {
807
+ if (seenCredentialSetIds.has(credentialSet.id)) throw new Error(`${ownerKind} "${ownerName}" declares duplicate credential set id "${credentialSet.id}".`);
808
+ seenCredentialSetIds.add(credentialSet.id);
809
+ }
810
+ }
811
+ //#endregion
812
+ //#region ../../packages/workflow-core/src/operation/context-registry.ts
813
+ function getCurrentRegistry() {
814
+ const provider = getExecutionScopeStepContextProvider();
815
+ if (!provider) return;
816
+ return { getOperationContext: provider };
817
+ }
818
+ function registerOperationContext(registry) {
819
+ pushExecutionScopeStepContext(registry.getOperationContext);
820
+ }
821
+ function clearOperationContext() {
822
+ clearExecutionScopeStepContexts();
823
+ }
824
+ function getRegisteredOperationContext(operation) {
825
+ return getCurrentRegistry()?.getOperationContext(operation);
826
+ }
827
+ //#endregion
828
+ //#region ../../packages/workflow-core/src/operation/credential-resolver-registry.ts
829
+ function registerOperationCredentialResolver(resolver) {
830
+ setExecutionScopeStepCredentialResolver(resolver.resolveOperationCredentials);
831
+ }
832
+ function clearOperationCredentialResolver() {
833
+ setExecutionScopeStepCredentialResolver(void 0);
834
+ }
835
+ function getRegisteredOperationCredentialResolver() {
836
+ const resolveOperationCredentials = getExecutionScopeStepCredentialResolver();
837
+ if (!resolveOperationCredentials) return;
838
+ return { resolveOperationCredentials };
839
+ }
840
+ async function resolveRegisteredOperationCredentials(operation, partialContext) {
841
+ return getRegisteredOperationCredentialResolver()?.resolveOperationCredentials(operation, partialContext);
842
+ }
843
+ //#endregion
844
+ //#region ../../packages/workflow-core/src/operation/hosted-action-dispatcher-registry.ts
845
+ const REGISTRY_KEY$1 = "__ks_hosted_action_dispatcher";
846
+ const EXECUTION_POLICY_KEY = "__ks_hosted_action_execution_policy";
847
+ function registerHostedActionDispatcher(dispatcher) {
848
+ globalThis[REGISTRY_KEY$1] = dispatcher;
849
+ }
850
+ function clearHostedActionDispatcher() {
851
+ globalThis[REGISTRY_KEY$1] = void 0;
852
+ }
853
+ function getRegisteredHostedActionDispatcher() {
854
+ return globalThis[REGISTRY_KEY$1];
855
+ }
856
+ function registerHostedActionExecutionPolicy(policy) {
857
+ globalThis[EXECUTION_POLICY_KEY] = policy;
858
+ }
859
+ function clearHostedActionExecutionPolicy() {
860
+ globalThis[EXECUTION_POLICY_KEY] = void 0;
861
+ }
862
+ function getHostedActionExecutionPolicy() {
863
+ return globalThis[EXECUTION_POLICY_KEY] ?? "permissive";
864
+ }
865
+ //#endregion
866
+ //#region ../../packages/workflow-core/src/operation/nesting-guard.ts
867
+ const NESTING_GUARD_KEY = "__ks_operation_nesting_guard__";
868
+ function getStorage() {
869
+ const g = globalThis;
870
+ if (!g[NESTING_GUARD_KEY]) g[NESTING_GUARD_KEY] = new AsyncLocalStorage();
871
+ return g[NESTING_GUARD_KEY];
872
+ }
873
+ function getActiveOperationRun() {
874
+ return getStorage().getStore()?.operationName;
875
+ }
876
+ function runWithOperationScope(operationName, fn) {
877
+ return getStorage().run({ operationName }, fn);
878
+ }
879
+ //#endregion
880
+ //#region ../../packages/workflow-core/src/operation/schemas.ts
881
+ const credentialSetInstanceSchema$1 = createStructuralSchema([
882
+ "id",
883
+ "auth",
884
+ "needsResolve"
885
+ ], "a CredentialSet instance");
886
+ const operationConfigSchema = z.object({
887
+ credentialSets: z.array(credentialSetInstanceSchema$1).optional(),
888
+ description: descriptionString("Operation description"),
889
+ id: trimmedNonEmptyString("Operation id"),
890
+ input: anyZodSchemaSchema,
891
+ name: trimmedNonEmptyString("Operation name"),
892
+ needsApproval: z.boolean().optional(),
893
+ output: anyZodSchemaSchema,
894
+ requiredOAuthScopes: z.array(z.string()).optional(),
895
+ retries: RetryConfigSchema.optional(),
896
+ run: z.function(),
897
+ tags: z.array(z.string()).optional(),
898
+ timeout: DurationSchema.optional(),
899
+ maxDurationMs: z.number().int().positive().optional(),
900
+ workflowGlobals: anyZodSchemaSchema.optional()
901
+ });
902
+ const OperationManifestSchema = z.object({
903
+ manifestVersion: z.literal(1),
904
+ type: z.literal("operation"),
905
+ name: trimmedNonEmptyString("Operation name"),
906
+ id: trimmedNonEmptyString("Operation id"),
907
+ description: descriptionString("Operation description"),
908
+ credentialSets: z.array(CredentialSetManifestSchema),
909
+ input: jsonSchemaObject,
910
+ output: jsonSchemaObject,
911
+ timeout: DurationSchema.optional(),
912
+ tags: z.array(z.string()).optional(),
913
+ retries: RetryConfigSchema.optional(),
914
+ needsApproval: z.boolean().optional(),
915
+ requiredOAuthScopes: z.array(z.string()).optional(),
916
+ maxDurationMs: z.number().int().positive().optional(),
917
+ workflowGlobals: jsonSchemaObject.optional()
918
+ });
919
+ //#endregion
920
+ //#region ../../packages/workflow-core/src/operation/step-registry.ts
921
+ const REGISTRY_KEY = "__ks_step_registry";
922
+ function getRegistry() {
923
+ const g = globalThis;
924
+ if (!g[REGISTRY_KEY]) g[REGISTRY_KEY] = [];
925
+ return g[REGISTRY_KEY];
926
+ }
927
+ function registerStep(step) {
928
+ getRegistry().push(step);
929
+ }
930
+ //#endregion
931
+ //#region ../../packages/workflow-core/src/operation/Operation.ts
932
+ function createHostedOperationExecutionError(integrationId, detail) {
933
+ return /* @__PURE__ */ new Error(`Hosted integration "${integrationId}" cannot run locally in this environment. ${detail}`);
934
+ }
935
+ var Operation = class Operation extends Primitive {
936
+ kind = "operation";
937
+ credentialSets;
938
+ description;
939
+ id;
940
+ input;
941
+ name;
942
+ needsApproval;
943
+ output;
944
+ requiredOAuthScopes;
945
+ retries;
946
+ tags;
947
+ timeout;
948
+ /**
949
+ * Upper bound on the operation's expected duration, in milliseconds.
950
+ * See {@link OperationConfig.maxDurationMs}.
951
+ */
952
+ maxDurationMs;
953
+ workflowGlobals;
954
+ #manifest;
955
+ #runImplementation;
956
+ #config;
957
+ constructor(config) {
958
+ super();
959
+ const validatedConfig = validateConfig(operationConfigSchema, {
960
+ ...config,
961
+ credentialSets: cloneCredentialSets(config.credentialSets),
962
+ tags: config.tags ? [...config.tags] : void 0,
963
+ requiredOAuthScopes: config.requiredOAuthScopes ? [...config.requiredOAuthScopes] : void 0
964
+ });
965
+ this.#config = {
966
+ ...config,
967
+ ...validatedConfig,
968
+ credentialSets: validatedConfig.credentialSets ?? config.credentialSets ?? [],
969
+ timeout: validatedConfig.timeout,
970
+ input: validatedConfig.input,
971
+ output: validatedConfig.output,
972
+ run: config.run,
973
+ workflowGlobals: validatedConfig.workflowGlobals
974
+ };
975
+ this.credentialSets = this.#config.credentialSets ?? [];
976
+ assertUniqueCredentialSetIds(this.credentialSets, "Operation", this.#config.name);
977
+ this.description = validatedConfig.description;
978
+ this.id = validatedConfig.id;
979
+ this.input = this.#config.input;
980
+ this.name = validatedConfig.name;
981
+ this.needsApproval = validatedConfig.needsApproval;
982
+ this.output = this.#config.output;
983
+ this.requiredOAuthScopes = validatedConfig.requiredOAuthScopes ? [...validatedConfig.requiredOAuthScopes] : void 0;
984
+ this.retries = validatedConfig.retries;
985
+ this.tags = [...validatedConfig.tags ?? []];
986
+ this.timeout = validatedConfig.timeout;
987
+ this.maxDurationMs = validatedConfig.maxDurationMs;
988
+ this.workflowGlobals = this.#config.workflowGlobals;
989
+ this.#runImplementation = this.#config.run;
990
+ registerStep(this);
991
+ this.#manifest = Object.freeze(OperationManifestSchema.parse({
992
+ manifestVersion: 1,
993
+ type: "operation",
994
+ name: this.name,
995
+ id: this.id,
996
+ description: this.description,
997
+ credentialSets: this.credentialSets.map((cs) => cs.toManifest()),
998
+ input: schemaToJsonSchema(this.input),
999
+ output: schemaToJsonSchema(this.output),
1000
+ tags: [...this.tags],
1001
+ ...this.timeout ? { timeout: this.timeout } : {},
1002
+ ...this.retries ? { retries: this.retries } : {},
1003
+ ...typeof this.maxDurationMs === "number" ? { maxDurationMs: this.maxDurationMs } : {},
1004
+ ...this.needsApproval !== void 0 ? { needsApproval: this.needsApproval } : {},
1005
+ ...this.requiredOAuthScopes?.length ? { requiredOAuthScopes: [...this.requiredOAuthScopes] } : {},
1006
+ ...this.workflowGlobals ? { workflowGlobals: schemaToJsonSchema(this.workflowGlobals) } : {}
1007
+ }));
1008
+ Object.freeze(this);
1009
+ }
1010
+ withTimeout(duration) {
1011
+ return new Operation({
1012
+ ...this.#config,
1013
+ timeout: duration
1014
+ });
1015
+ }
1016
+ retry(policy) {
1017
+ return new Operation({
1018
+ ...this.#config,
1019
+ retries: policy
1020
+ });
1021
+ }
1022
+ configure(config) {
1023
+ return new Operation({
1024
+ ...this.#config,
1025
+ ...config
1026
+ });
1027
+ }
1028
+ getCredentialRequirements() {
1029
+ return toDeclaredCredentialRequirements(this.credentialSets);
1030
+ }
1031
+ /** @internal Used by the flow graph builder for nesting detection. */
1032
+ getRunFunctionSource() {
1033
+ return this.#runImplementation.toString();
1034
+ }
1035
+ mapInput(schema, fn) {
1036
+ const originalRun = this.#runImplementation;
1037
+ return new Operation({
1038
+ ...this.#config,
1039
+ input: schema,
1040
+ run: async (input, ctx) => {
1041
+ return originalRun(fn(input), ctx);
1042
+ }
1043
+ });
1044
+ }
1045
+ mapOutput(schema, fn) {
1046
+ const originalRun = this.#runImplementation;
1047
+ return new Operation({
1048
+ ...this.#config,
1049
+ output: schema,
1050
+ run: async (input, ctx) => {
1051
+ return fn(await originalRun(input, ctx));
1052
+ }
1053
+ });
1054
+ }
1055
+ async run(input, ctx) {
1056
+ const parsedInput = this.input.parse(input);
1057
+ const interceptor = getActiveRuntimeCallInterceptor();
1058
+ if (interceptor) {
1059
+ const intercepted = await interceptor({
1060
+ instance: this,
1061
+ kind: "workflow-step",
1062
+ name: this.name,
1063
+ input: parsedInput,
1064
+ outputSchema: this.output
1065
+ });
1066
+ return this.output.parse(intercepted);
1067
+ }
1068
+ if (!ctx) {
1069
+ const workflowRuntime = getRegisteredRuntime();
1070
+ if (workflowRuntime?.handleStep) {
1071
+ const intercepted = await workflowRuntime.handleStep(this, parsedInput);
1072
+ return this.output.parse(intercepted);
1073
+ }
1074
+ }
1075
+ const integrationMetadata = getOfficialIntegrationMetadata(this);
1076
+ if (integrationMetadata?.hosted) {
1077
+ const hostedActionExecutionPolicy = getHostedActionExecutionPolicy();
1078
+ const dispatcher = getRegisteredHostedActionDispatcher();
1079
+ if (!dispatcher) {
1080
+ if (hostedActionExecutionPolicy === "strict") throw createHostedOperationExecutionError(integrationMetadata.integrationId, "Use `keystrokeTestPlugin()` in auto mode, run `keystroke auth`, and ensure the Keystroke dev server is running.");
1081
+ } else {
1082
+ const dispatchResult = await dispatcher.dispatch(this, integrationMetadata.integrationId, parsedInput);
1083
+ if (dispatchResult.handled) return this.output.parse(dispatchResult.result);
1084
+ if (hostedActionExecutionPolicy === "strict") throw createHostedOperationExecutionError(integrationMetadata.integrationId, "The hosted-action dispatcher declined execution. Hosted integrations must execute through the Keystroke dev server.");
1085
+ }
1086
+ }
1087
+ const execute = async () => {
1088
+ const parentOperation = getActiveOperationRun();
1089
+ if (parentOperation) throw new Error(`Operation "${this.name}" was called inside the run function of "${parentOperation}". Steps and Operations cannot call other Operations inside their run function. Move the "${this.name}" call into the Workflow's run function, or use a plain async helper function instead of a Step.`);
1090
+ return runWithOperationScope(this.name, async () => {
1091
+ const result = await this.#runImplementation(parsedInput, await this.#resolveRuntimeContext(ctx));
1092
+ return this.output.parse(result);
1093
+ });
1094
+ };
1095
+ if (this.timeout) {
1096
+ const ms = parseDurationToMs(this.timeout);
1097
+ return Promise.race([execute(), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`Operation "${this.name}" timed out after ${ms}ms`)), ms))]);
1098
+ }
1099
+ return execute();
1100
+ }
1101
+ /**
1102
+ * Execute the step implementation directly, bypassing interceptors and
1103
+ * runtime checks. Used by the inline step execution runtime to avoid
1104
+ * recursion through handleStep.
1105
+ * @internal
1106
+ */
1107
+ async executeDirectly(input, ctx) {
1108
+ const parsedInput = this.input.parse(input);
1109
+ const result = await this.#runImplementation(parsedInput, await this.#resolveRuntimeContext(ctx));
1110
+ return this.output.parse(result);
1111
+ }
1112
+ describe() {
1113
+ return `Operation "${this.name}"`;
1114
+ }
1115
+ toManifest() {
1116
+ return this.#manifest;
1117
+ }
1118
+ #createImplicitRuntimeContext() {
1119
+ return {
1120
+ credentials: {},
1121
+ workflowGlobals: void 0
1122
+ };
1123
+ }
1124
+ #normalizeRuntimeContext(ctx) {
1125
+ const tracing = ctx;
1126
+ return {
1127
+ attempt: ctx.attempt,
1128
+ credentials: ctx.credentials ?? {},
1129
+ maxAttempts: ctx.maxAttempts,
1130
+ stepId: ctx.stepId,
1131
+ toolCallId: tracing.toolCallId,
1132
+ traceparent: tracing.traceparent,
1133
+ tracestate: tracing.tracestate,
1134
+ workflowGlobals: ctx.workflowGlobals
1135
+ };
1136
+ }
1137
+ async #resolveRuntimeContext(ctx) {
1138
+ const runtimeContext = ctx ?? getRegisteredOperationContext(this);
1139
+ if (runtimeContext) {
1140
+ const normalizedContext = this.#normalizeRuntimeContext(runtimeContext);
1141
+ return this.#validateRuntimeContext(await this.#resolveMissingCredentials(normalizedContext));
1142
+ }
1143
+ if (this.credentialSets.length === 0 && !this.workflowGlobals) return this.#createImplicitRuntimeContext();
1144
+ throw new Error(`Operation "${this.name}" was executed without a runtime context. Pass one explicitly to .run(input, ctx), or use keystrokeTestPlugin() from "@keystroke/workflow-core/vitest" in Vitest.`);
1145
+ }
1146
+ async #resolveMissingCredentials(ctx) {
1147
+ if (this.credentialSets.map((credentialSet) => credentialSet.id).filter((credentialSetId) => ctx.credentials[credentialSetId] === void 0).length === 0) return ctx;
1148
+ const resolvedCredentials = await resolveRegisteredOperationCredentials(this, ctx);
1149
+ if (!resolvedCredentials) return ctx;
1150
+ return {
1151
+ ...ctx,
1152
+ credentials: {
1153
+ ...resolvedCredentials,
1154
+ ...ctx.credentials
1155
+ }
1156
+ };
1157
+ }
1158
+ #validateRuntimeContext(ctx) {
1159
+ const validatedCredentials = {};
1160
+ for (const credentialSet of this.credentialSets) {
1161
+ const credentialId = credentialSet.id;
1162
+ const rawCredential = ctx.credentials[credentialId];
1163
+ validatedCredentials[credentialSet.id] = credentialSet.auth.parse(rawCredential);
1164
+ }
1165
+ return {
1166
+ attempt: ctx.attempt,
1167
+ credentials: validatedCredentials,
1168
+ maxAttempts: ctx.maxAttempts,
1169
+ stepId: ctx.stepId,
1170
+ ...ctx.toolCallId !== void 0 ? { toolCallId: ctx.toolCallId } : {},
1171
+ ...ctx.traceparent !== void 0 ? { traceparent: ctx.traceparent } : {},
1172
+ ...ctx.tracestate !== void 0 ? { tracestate: ctx.tracestate } : {},
1173
+ workflowGlobals: this.workflowGlobals ? this.workflowGlobals.parse(ctx.workflowGlobals) : ctx.workflowGlobals
1174
+ };
1175
+ }
1176
+ };
1177
+ triggerBaseConfigSchema.extend({
1178
+ input: anyZodSchemaSchema,
1179
+ payload: z.custom((value) => {
1180
+ return jsonValueSchema.safeParse(value).success;
1181
+ }, "Expected a JSON-serializable payload"),
1182
+ schedule: ScheduleSchema,
1183
+ timezone: IANATimezoneSchema.optional()
1184
+ });
1185
+ const cronTriggerRuntimeSchema = TriggerRuntimeDescriptorSchema.extend({
1186
+ input: jsonSchemaObject,
1187
+ payloadMode: z.literal("static"),
1188
+ schedule: z.string(),
1189
+ timezone: z.string().optional()
1190
+ });
1191
+ const cronTriggerManifestSchema = z.object({
1192
+ manifestVersion: z.literal(1),
1193
+ type: z.literal("trigger"),
1194
+ triggerType: z.literal("cron"),
1195
+ name: trimmedNonEmptyString("Trigger name"),
1196
+ description: descriptionString("Trigger description"),
1197
+ enabled: z.boolean(),
1198
+ modeDefault: z.enum(["managed", "subscribable"]),
1199
+ executionIdentityPolicy: triggerBaseConfigSchema.shape.executionIdentityPolicy,
1200
+ credentialSets: z.array(CredentialSetManifestSchema).optional(),
1201
+ runtime: cronTriggerRuntimeSchema,
1202
+ /** Static payload for cron triggers — the workflow input when this trigger fires */
1203
+ payload: jsonValueSchema.optional()
1204
+ });
1205
+ z.object({
1206
+ lastPolledAt: z.string().optional(),
1207
+ lastResponse: z.unknown().optional()
1208
+ });
1209
+ triggerBaseConfigSchema.extend({
1210
+ poll: z.function(),
1211
+ filter: z.function().optional(),
1212
+ idempotencyKey: z.function().optional(),
1213
+ response: anyZodSchemaSchema,
1214
+ schedule: ScheduleSchema
1215
+ });
1216
+ const pollingTriggerRuntimeSchema = TriggerRuntimeDescriptorSchema.extend({
1217
+ response: jsonSchemaObject,
1218
+ schedule: z.string(),
1219
+ state: z.object({
1220
+ lastPolledAt: z.literal(true),
1221
+ lastResponse: z.literal(true)
1222
+ })
1223
+ });
1224
+ const pollingTriggerManifestSchema = z.object({
1225
+ manifestVersion: z.literal(1),
1226
+ type: z.literal("trigger"),
1227
+ triggerType: z.literal("polling"),
1228
+ name: trimmedNonEmptyString("Trigger name"),
1229
+ description: descriptionString("Trigger description"),
1230
+ enabled: z.boolean(),
1231
+ modeDefault: z.enum(["managed", "subscribable"]),
1232
+ executionIdentityPolicy: triggerBaseConfigSchema.shape.executionIdentityPolicy,
1233
+ credentialSets: z.array(CredentialSetManifestSchema).optional(),
1234
+ runtime: pollingTriggerRuntimeSchema
1235
+ });
1236
+ //#endregion
1237
+ //#region ../../packages/workflow-core/src/trigger/webhook/schemas.ts
1238
+ const WebhookMethodSchema = z.enum([
1239
+ "PATCH",
1240
+ "POST",
1241
+ "PUT"
1242
+ ]);
1243
+ z.object({
1244
+ method: z.string(),
1245
+ path: z.string(),
1246
+ query: z.record(z.string(), z.union([
1247
+ z.string(),
1248
+ z.array(z.string()),
1249
+ z.undefined()
1250
+ ])),
1251
+ headers: z.record(z.string(), z.string().optional()),
1252
+ rawBody: z.string()
1253
+ });
1254
+ const WebhookResponseConfigSchema = z.object({
1255
+ ignoredBody: jsonValueSchema.optional(),
1256
+ ignoredStatus: z.number().int().positive().optional(),
1257
+ successBody: jsonValueSchema.optional(),
1258
+ successStatus: z.number().int().positive().optional()
1259
+ });
1260
+ /**
1261
+ * Custom webhook trigger paths describe the suffix that a request URL has
1262
+ * after the organization id. The router serves these triggers at
1263
+ * `/api/v1/webhooks/{orgId}{path}` (e.g. `path: '/orders'` → request
1264
+ * `/api/v1/webhooks/{orgId}/orders`). Authors must therefore supply only the
1265
+ * trailing path segment, not the `/webhooks/` prefix that the route already
1266
+ * provides.
1267
+ */
1268
+ const webhookPathSchema = z.string().trim().min(1, { error: "Webhook path cannot be empty" }).max(50, { error: "Webhook path cannot exceed 50 characters" }).refine((s) => !/\s/.test(s), { error: "Webhook path cannot contain spaces or whitespace" }).refine((s) => s.startsWith("/"), { error: "Webhook path must start with /" }).refine((s) => s.length > 1, { error: "Webhook path must include a path segment after the leading \"/\"" }).refine((s) => !/^\/webhooks(\/|$)/i.test(s), { error: "Webhook path must not start with \"/webhooks\". Provide just the suffix that follows the organization id in the URL — e.g. use \"/orders\" for a webhook served at \"/api/v1/webhooks/{orgId}/orders\"." });
1269
+ const credentialSetInstanceSchema = createStructuralSchema([
1270
+ "id",
1271
+ "auth",
1272
+ "needsResolve"
1273
+ ], "a CredentialSet instance");
1274
+ const webhookCustomSourceConfigSchema = z.object({
1275
+ type: z.literal("custom"),
1276
+ method: WebhookMethodSchema,
1277
+ path: webhookPathSchema,
1278
+ verify: z.function().optional(),
1279
+ response: WebhookResponseConfigSchema.optional(),
1280
+ credentialSets: z.array(credentialSetInstanceSchema).optional()
1281
+ });
1282
+ const webhookAppSourceConfigSchema = z.object({
1283
+ type: z.literal("app"),
1284
+ appRef: trimmedNonEmptyString("appRef")
1285
+ });
1286
+ const webhookSourceConfigSchema = z.discriminatedUnion("type", [webhookCustomSourceConfigSchema, webhookAppSourceConfigSchema]);
1287
+ const webhookCustomSourceManifestSchema = z.object({
1288
+ type: z.literal("custom"),
1289
+ method: WebhookMethodSchema,
1290
+ path: z.string().min(1).max(1024),
1291
+ response: WebhookResponseConfigSchema.optional()
1292
+ });
1293
+ const webhookAppSourceManifestSchema = z.object({
1294
+ type: z.literal("app"),
1295
+ appRef: trimmedNonEmptyString("appRef")
1296
+ });
1297
+ const WebhookSourceManifestSchema = z.discriminatedUnion("type", [webhookCustomSourceManifestSchema, webhookAppSourceManifestSchema]);
1298
+ triggerBaseConfigSchema.omit({ credentialSets: true }).extend({
1299
+ source: webhookSourceConfigSchema,
1300
+ payload: anyZodSchemaSchema.optional(),
1301
+ filter: z.function().optional(),
1302
+ idempotencyKey: z.function().optional()
1303
+ });
1304
+ const webhookTriggerRuntimeSchema = TriggerRuntimeDescriptorSchema.extend({
1305
+ source: WebhookSourceManifestSchema,
1306
+ payload: jsonSchemaObject
1307
+ });
1308
+ const webhookTriggerManifestSchema = z.object({
1309
+ manifestVersion: z.literal(1),
1310
+ type: z.literal("trigger"),
1311
+ triggerType: z.literal("webhook"),
1312
+ name: trimmedNonEmptyString("Trigger name"),
1313
+ description: descriptionString("Trigger description"),
1314
+ enabled: z.boolean(),
1315
+ modeDefault: z.enum(["managed", "subscribable"]),
1316
+ executionIdentityPolicy: triggerBaseConfigSchema.shape.executionIdentityPolicy,
1317
+ credentialSets: z.array(CredentialSetManifestSchema).optional(),
1318
+ runtime: webhookTriggerRuntimeSchema
1319
+ });
1320
+ z.unknown();
1321
+ z.object({
1322
+ author: optionalTrimmedNonEmptyString("Workflow author"),
1323
+ description: optionalDescriptionString("Workflow description"),
1324
+ id: idNoSpacesString("Workflow id"),
1325
+ input: anyZodSchemaSchema,
1326
+ name: trimmedNonEmptyString("Workflow name"),
1327
+ output: anyZodSchemaSchema,
1328
+ timeout: DurationSchema.optional(),
1329
+ largeResultMode: z.enum(["reject", "ref"]).optional(),
1330
+ midSessionSnapshot: z.boolean().optional(),
1331
+ retries: RetryConfigSchema.optional(),
1332
+ tags: z.array(z.string()).optional(),
1333
+ version: optionalTrimmedNonEmptyString("Workflow version"),
1334
+ workflowGlobals: anyZodSchemaSchema.optional()
1335
+ }).extend({
1336
+ run: z.function(),
1337
+ triggers: z.array(z.unknown()).optional()
1338
+ });
1339
+ //#endregion
1340
+ export { getOfficialIntegrationMetadata as _, clearHostedActionDispatcher as a, registerHostedActionExecutionPolicy as c, clearOperationContext as d, registerOperationContext as f, registerRuntime as g, clearRuntime as h, Operation as i, clearOperationCredentialResolver as l, AgentManifestSchema as m, pollingTriggerManifestSchema as n, clearHostedActionExecutionPolicy as o, CredentialSet as p, cronTriggerManifestSchema as r, registerHostedActionDispatcher as s, webhookTriggerManifestSchema as t, registerOperationCredentialResolver as u, registerOfficialIntegrationOperation as v };