@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.
- package/AGENTS-blurb.md +123 -0
- package/LICENSE +42 -0
- package/README.md +177 -0
- package/THIRD_PARTY_NOTICES.md +16 -0
- package/bin/keystroke.mjs +107 -0
- package/dist/_manifest-JSRE3H8k.mjs +385 -0
- package/dist/agent-bundle-package-DWV6B_5q-BtV7Xycc.mjs +2344 -0
- package/dist/agent-manifest-CDnbkR2f.mjs +245 -0
- package/dist/agents-CZJGxVqV.mjs +228 -0
- package/dist/api-keys-D2lgguuY.mjs +40 -0
- package/dist/auth-DN2VusyU.mjs +59 -0
- package/dist/auth.handler-CT1BQUvu.mjs +340 -0
- package/dist/browser-qwFrUH82.mjs +24 -0
- package/dist/build-agents-BmM_AsSd-BGi9wtzt.mjs +514 -0
- package/dist/build-metadata-BWS7uhd_-DR8gJjTX.mjs +1422 -0
- package/dist/build-progress-DgYKb4hB.mjs +183 -0
- package/dist/build-tasks-CdihpudT-D5r5HUHe.mjs +91 -0
- package/dist/build-workflows-CfxBnIWh-CdYPv8w2.mjs +370 -0
- package/dist/build.handler-4799CjWH.mjs +36 -0
- package/dist/chunk-CH6r78ws.mjs +37 -0
- package/dist/clear-cache.handler-B9tqSoSM.mjs +11 -0
- package/dist/clear.handler-BTIXXPTJ.mjs +42 -0
- package/dist/clear.handler-BydlX-zE.mjs +11 -0
- package/dist/commander-DfTVqQ-3.mjs +133 -0
- package/dist/concurrency-gXn9Rw8x-DNl2YtrS.mjs +20 -0
- package/dist/connect-BUXkeH0F.mjs +43 -0
- package/dist/connect.handler-CYel9cy6.mjs +430 -0
- package/dist/constants-CPpPdSNg.mjs +8 -0
- package/dist/context-T7HZuB97.mjs +138 -0
- package/dist/credential-env-map-CI8yWHVy.mjs +28 -0
- package/dist/credential-schema-mismatch-BKo5PjcQ.mjs +76 -0
- package/dist/credentials-CvmjU0lK.mjs +171 -0
- package/dist/credentials-OfVHOtG3.mjs +151216 -0
- package/dist/current-deployment-workflow-poHt27i3.mjs +94 -0
- package/dist/current.handler-B8zKzfPp.mjs +21 -0
- package/dist/delete.handler-bAu1iXVQ.mjs +17 -0
- package/dist/deploy-7Jjls436.mjs +26 -0
- package/dist/deploy-BOPIpRWm.mjs +74 -0
- package/dist/deploy-progress-BmGUNFKg.mjs +70 -0
- package/dist/deploy.handler-BAzgiNhd.mjs +370 -0
- package/dist/detect-env-access-CwkOYeYM-D_BCZqV6.mjs +209 -0
- package/dist/diff-utils-NEfcjqxt.mjs +185 -0
- package/dist/diff.handler-Du7SY8K4.mjs +47 -0
- package/dist/dist-BkJUoBiG.mjs +1116 -0
- package/dist/dist-CUK7yBM0.mjs +308 -0
- package/dist/env-91KwMKov.mjs +140 -0
- package/dist/env.handler-BAzBuMzQ.mjs +277 -0
- package/dist/error-boundary-VL-JLfIa.mjs +34 -0
- package/dist/file-metadata-D1vm-XY2.mjs +191 -0
- package/dist/get-intrinsic-zLxwtrLK.mjs +658 -0
- package/dist/import-module-CV84H5fZ-B_CBCmb4.mjs +1747 -0
- package/dist/init-DpMCotSK.mjs +45 -0
- package/dist/init.handler-CPRnif52.mjs +585 -0
- package/dist/inspect.handler-DT_cD036.mjs +146 -0
- package/dist/integration-catalog-Bt-L3GjF.mjs +104 -0
- package/dist/integrations-DlatPK4W.mjs +79 -0
- package/dist/keystroke.d.mts +3 -0
- package/dist/keystroke.mjs +707 -0
- package/dist/layout-CbMtQ2tm.mjs +67 -0
- package/dist/list-enrichment-y-cwizLr.mjs +189 -0
- package/dist/list.handler-BTWvCyjA.mjs +52 -0
- package/dist/list.handler-CWF_Dj15.mjs +24 -0
- package/dist/list.handler-CZ6G2x_G.mjs +75 -0
- package/dist/list.handler-DWaQkJaR.mjs +51 -0
- package/dist/list.handler-DqbFcBW7.mjs +180 -0
- package/dist/list.handler-lq3ZGAn4.mjs +104 -0
- package/dist/logs-BEg9L5l8.mjs +28 -0
- package/dist/logs.handler-6hoMBzqw.mjs +35 -0
- package/dist/logs.handler-BD_dXiL1.mjs +231 -0
- package/dist/metadata-layout-GUYIUo0i-_aG2zjue.mjs +5877 -0
- package/dist/normalize-path-CojS-CgQ-DLCOvnD1.mjs +20 -0
- package/dist/options-CeaTcFxP.mjs +43 -0
- package/dist/org-xLzBtt2_.mjs +41 -0
- package/dist/output-DM4b7KgY.mjs +72 -0
- package/dist/oxc-B3KI3rf_-n9d1hKNq.mjs +119 -0
- package/dist/paused.handler-BMFm9Cff.mjs +94 -0
- package/dist/project-config-D1qsQlO7.mjs +107 -0
- package/dist/projects-CHkRE9rS.mjs +1574 -0
- package/dist/projects-Cjb7sovS.mjs +30 -0
- package/dist/read-credential-keys-77a91T8M-KA0Iw0Z1.mjs +9 -0
- package/dist/register.handler-BPCdor1_.mjs +86 -0
- package/dist/requirements.handler-DPXdSks3.mjs +201 -0
- package/dist/resolve-project-DDJ29sCF.mjs +35 -0
- package/dist/rolldown-runtime-twds-ZHy-BWWzu8VG.mjs +15 -0
- package/dist/run-polling-CAgFRdK3.mjs +20 -0
- package/dist/runs-D9hNLb9A.mjs +259 -0
- package/dist/schedule-BXx3uXwr.mjs +1142 -0
- package/dist/schema-17qMfNyI.mjs +18 -0
- package/dist/schema-display-CgmeKigW.mjs +130 -0
- package/dist/schemas-CDib1RhE.mjs +125 -0
- package/dist/skills-sync.handler-DIy8GR16.mjs +34 -0
- package/dist/skills.command-CrjI2dN9.mjs +35 -0
- package/dist/skills.handler-Bz8bJKql.mjs +9 -0
- package/dist/source-analysis-Cj-ADyu--BJQcFPCG.mjs +144 -0
- package/dist/spinner-progress-DMVwgqO9.mjs +173 -0
- package/dist/src-C0X6u_Mw.mjs +1340 -0
- package/dist/src-eHwu-Gfw.mjs +369 -0
- package/dist/status.handler-BO4nwvWn.mjs +101 -0
- package/dist/switch.handler-D_9213Vf.mjs +51 -0
- package/dist/sync-BL_Mo5st.mjs +39 -0
- package/dist/sync-keystroke-agent-skills-Kx_H7UTd.mjs +70 -0
- package/dist/sync.handler-BUFPdzWz.mjs +82 -0
- package/dist/task-B2sZMaZu.mjs +8 -0
- package/dist/task-target-build-CBeCKbu2.mjs +432 -0
- package/dist/task-target-deploy-C5X-USeR.mjs +4 -0
- package/dist/task-target-deploy-CA6elFpF-BEr4gkol.mjs +271 -0
- package/dist/task-target-deploy-runner.d.mts +3 -0
- package/dist/task-target-deploy-runner.mjs +202 -0
- package/dist/test-BHTgR3UA.mjs +698 -0
- package/dist/test.handler-BcPQ8b74.mjs +13 -0
- package/dist/trigger-artifacts-DQPbQNqC-B4yeeFBY.mjs +239 -0
- package/dist/trigger-manifest-CY7brZeg.mjs +30 -0
- package/dist/try-deploy.handler-DqybNhXx.mjs +490 -0
- package/dist/upload-CkU--iDC.mjs +207 -0
- package/dist/upload.handler-DCtiznQp.mjs +441 -0
- package/dist/utils-CywxCDM7.mjs +14 -0
- package/dist/validate.handler-DOcTaJL0.mjs +280 -0
- package/dist/workflow-build-DBQaBfnn.mjs +1819 -0
- package/dist/workflow-bundler-BPiqVscj-X1PFFAuP.mjs +167 -0
- package/dist/workflows-g9z87AJJ.mjs +799 -0
- package/dist/writer-BG8poUm3-BbXlU2kI.mjs +426 -0
- 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 };
|