@keystrokehq/keystroke 0.1.19 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.cjs +72 -54
- package/dist/agent.cjs.map +1 -1
- package/dist/agent.d.cts +2 -2
- package/dist/agent.d.mts +2 -2
- package/dist/agent.mjs +71 -52
- package/dist/agent.mjs.map +1 -1
- package/dist/{dist-KpQEao0i.mjs → dist-B1Pjv-cM.mjs} +666 -21
- package/dist/dist-B1Pjv-cM.mjs.map +1 -0
- package/dist/dist-BKL5duJl.cjs.map +1 -1
- package/dist/{dist-BFCT4aiu.cjs → dist-D69ocJ7u.cjs} +728 -23
- package/dist/dist-D69ocJ7u.cjs.map +1 -0
- package/dist/dist-_i6Rguqn.mjs.map +1 -1
- package/dist/{index-Dlu1kaci.d.cts → index-BQOZkLWG.d.cts} +10 -34
- package/dist/index-BQOZkLWG.d.cts.map +1 -0
- package/dist/{index-I9DneAMW.d.mts → index-CGf1NwA4.d.mts} +10 -34
- package/dist/index-CGf1NwA4.d.mts.map +1 -0
- package/dist/index-CeRtE5Gn.d.cts.map +1 -1
- package/dist/{index-BUYoOHa1.d.mts → index-WHR4qX4x.d.mts} +10 -3
- package/dist/index-WHR4qX4x.d.mts.map +1 -0
- package/dist/index-w8mrqxo3.d.mts.map +1 -1
- package/dist/index-wVbZ-JO2.d.cts.map +1 -1
- package/dist/index-wVbZ-JO2.d.mts.map +1 -1
- package/dist/{index-Dzm0OSN4.d.cts → index-wpyFrBvl.d.cts} +10 -3
- package/dist/index-wpyFrBvl.d.cts.map +1 -0
- package/dist/{token-dA7JRmgB.cjs → token-DZEJHEnH.cjs} +2 -2
- package/dist/{token-dA7JRmgB.cjs.map → token-DZEJHEnH.cjs.map} +1 -1
- package/dist/{token-shJjdG3B.mjs → token-D_x8iwF8.mjs} +2 -2
- package/dist/{token-shJjdG3B.mjs.map → token-D_x8iwF8.mjs.map} +1 -1
- package/dist/trigger.cjs +1 -1
- package/dist/trigger.d.cts +2 -2
- package/dist/trigger.d.mts +2 -2
- package/dist/trigger.mjs +1 -1
- package/dist/workflow.cjs +3 -1
- package/dist/workflow.d.cts +2 -2
- package/dist/workflow.d.mts +2 -2
- package/dist/workflow.mjs +2 -2
- package/package.json +2 -2
- package/dist/dist-BFCT4aiu.cjs.map +0 -1
- package/dist/dist-BekOBuw8.cjs +0 -665
- package/dist/dist-BekOBuw8.cjs.map +0 -1
- package/dist/dist-C-1uJk5f.mjs +0 -612
- package/dist/dist-C-1uJk5f.mjs.map +0 -1
- package/dist/dist-KpQEao0i.mjs.map +0 -1
- package/dist/index-BUYoOHa1.d.mts.map +0 -1
- package/dist/index-Dlu1kaci.d.cts.map +0 -1
- package/dist/index-Dzm0OSN4.d.cts.map +0 -1
- package/dist/index-I9DneAMW.d.mts.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { n as __require, r as __toESM, t as __commonJSMin } from "./chunk-DnnnRqeS.mjs";
|
|
2
|
-
import { _ as normalizeCredentialList, a as buildConnectDeeplink, h as mcpEntityId } from "./dist-_i6Rguqn.mjs";
|
|
2
|
+
import { _ as normalizeCredentialList, a as buildConnectDeeplink, h as mcpEntityId, l as defineTool } from "./dist-_i6Rguqn.mjs";
|
|
3
|
+
import { _ as runWithMcpCredentialContext, a as getActionCredentialRequirements, c as getRunSignal, i as executeAction, l as getWorkflowRunHandle, m as registerWorkflowRunGetter } from "./dist-CAZlfg_P.mjs";
|
|
3
4
|
import { createRequire } from "node:module";
|
|
4
5
|
import { z } from "zod";
|
|
5
6
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -2179,7 +2180,7 @@ function asSchema(schema) {
|
|
|
2179
2180
|
type: "object",
|
|
2180
2181
|
properties: {},
|
|
2181
2182
|
additionalProperties: false
|
|
2182
|
-
}) : isSchema(schema) ? schema : "~standard" in schema ? schema["~standard"].vendor === "zod" ? zodSchema(schema) : standardSchema(schema) : schema();
|
|
2183
|
+
}) : isSchema(schema) ? schema : "~standard" in schema ? schema["~standard"].vendor === "zod" ? zodSchema$1(schema) : standardSchema(schema) : schema();
|
|
2183
2184
|
}
|
|
2184
2185
|
function standardSchema(standardSchema2) {
|
|
2185
2186
|
return jsonSchema(() => addAdditionalPropertiesToJsonSchema(standardSchema2["~standard"].jsonSchema.input({ target: "draft-07" })), { validate: async (value) => {
|
|
@@ -2231,7 +2232,7 @@ function zod4Schema(zodSchema2, options) {
|
|
|
2231
2232
|
function isZod4Schema(zodSchema2) {
|
|
2232
2233
|
return "_zod" in zodSchema2;
|
|
2233
2234
|
}
|
|
2234
|
-
function zodSchema(zodSchema2, options) {
|
|
2235
|
+
function zodSchema$1(zodSchema2, options) {
|
|
2235
2236
|
if (isZod4Schema(zodSchema2)) return zod4Schema(zodSchema2, options);
|
|
2236
2237
|
else return zod3Schema(zodSchema2, options);
|
|
2237
2238
|
}
|
|
@@ -2692,7 +2693,7 @@ var require_get_vercel_oidc_token = /* @__PURE__ */ __commonJSMin(((exports, mod
|
|
|
2692
2693
|
err = error;
|
|
2693
2694
|
}
|
|
2694
2695
|
try {
|
|
2695
|
-
const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await Promise.resolve().then(() => /* @__PURE__ */ __toESM(require_token_util())), await import("./token-
|
|
2696
|
+
const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([await Promise.resolve().then(() => /* @__PURE__ */ __toESM(require_token_util())), await import("./token-D_x8iwF8.mjs").then((m) => /* @__PURE__ */ __toESM(m.default))]);
|
|
2696
2697
|
if (!token || isExpired(getTokenPayload(token), options?.expirationBufferMs)) {
|
|
2697
2698
|
await refreshToken(options);
|
|
2698
2699
|
token = getVercelOidcTokenSync();
|
|
@@ -3276,7 +3277,7 @@ var GatewayRateLimitError = class extends (_b4 = GatewayError, _a4$1 = symbol4$1
|
|
|
3276
3277
|
var name4$1 = "GatewayModelNotFoundError";
|
|
3277
3278
|
var marker5$1 = `vercel.ai.gateway.error.${name4$1}`;
|
|
3278
3279
|
var symbol5$1 = Symbol.for(marker5$1);
|
|
3279
|
-
var modelNotFoundParamSchema = lazySchema(() => zodSchema(z$1.object({ modelId: z$1.string() })));
|
|
3280
|
+
var modelNotFoundParamSchema = lazySchema(() => zodSchema$1(z$1.object({ modelId: z$1.string() })));
|
|
3280
3281
|
var _a5$1, _b5;
|
|
3281
3282
|
var GatewayModelNotFoundError = class extends (_b5 = GatewayError, _a5$1 = symbol5$1, _b5) {
|
|
3282
3283
|
constructor({ message = "Model not found", statusCode = 404, modelId, cause, generationId } = {}) {
|
|
@@ -3457,7 +3458,7 @@ async function createGatewayErrorFromResponse({ response, statusCode, defaultMes
|
|
|
3457
3458
|
});
|
|
3458
3459
|
}
|
|
3459
3460
|
}
|
|
3460
|
-
var gatewayErrorResponseSchema = lazySchema(() => zodSchema(z$1.object({
|
|
3461
|
+
var gatewayErrorResponseSchema = lazySchema(() => zodSchema$1(z$1.object({
|
|
3461
3462
|
error: z$1.object({
|
|
3462
3463
|
message: z$1.string(),
|
|
3463
3464
|
type: z$1.string().nullish(),
|
|
@@ -3555,7 +3556,7 @@ async function parseAuthMethod(headers) {
|
|
|
3555
3556
|
});
|
|
3556
3557
|
return result.success ? result.value : void 0;
|
|
3557
3558
|
}
|
|
3558
|
-
var gatewayAuthMethodSchema = lazySchema(() => zodSchema(z$1.union([z$1.literal("api-key"), z$1.literal("oidc")])));
|
|
3559
|
+
var gatewayAuthMethodSchema = lazySchema(() => zodSchema$1(z$1.union([z$1.literal("api-key"), z$1.literal("oidc")])));
|
|
3559
3560
|
var KNOWN_MODEL_TYPES = [
|
|
3560
3561
|
"embedding",
|
|
3561
3562
|
"image",
|
|
@@ -3605,7 +3606,7 @@ var GatewayFetchMetadata = class {
|
|
|
3605
3606
|
}
|
|
3606
3607
|
}
|
|
3607
3608
|
};
|
|
3608
|
-
var gatewayAvailableModelsResponseSchema = lazySchema(() => zodSchema(z$1.object({ models: z$1.array(z$1.object({
|
|
3609
|
+
var gatewayAvailableModelsResponseSchema = lazySchema(() => zodSchema$1(z$1.object({ models: z$1.array(z$1.object({
|
|
3609
3610
|
id: z$1.string(),
|
|
3610
3611
|
name: z$1.string(),
|
|
3611
3612
|
description: z$1.string().nullish(),
|
|
@@ -3627,7 +3628,7 @@ var gatewayAvailableModelsResponseSchema = lazySchema(() => zodSchema(z$1.object
|
|
|
3627
3628
|
}),
|
|
3628
3629
|
modelType: z$1.string().nullish()
|
|
3629
3630
|
})).transform((models) => models.filter((m) => m.modelType == null || KNOWN_MODEL_TYPES.includes(m.modelType))) })));
|
|
3630
|
-
var gatewayCreditsResponseSchema = lazySchema(() => zodSchema(z$1.object({
|
|
3631
|
+
var gatewayCreditsResponseSchema = lazySchema(() => zodSchema$1(z$1.object({
|
|
3631
3632
|
balance: z$1.string(),
|
|
3632
3633
|
total_used: z$1.string()
|
|
3633
3634
|
}).transform(({ balance, total_used }) => ({
|
|
@@ -3667,7 +3668,7 @@ var GatewaySpendReport = class {
|
|
|
3667
3668
|
}
|
|
3668
3669
|
}
|
|
3669
3670
|
};
|
|
3670
|
-
var gatewaySpendReportResponseSchema = lazySchema(() => zodSchema(z$1.object({ results: z$1.array(z$1.object({
|
|
3671
|
+
var gatewaySpendReportResponseSchema = lazySchema(() => zodSchema$1(z$1.object({ results: z$1.array(z$1.object({
|
|
3671
3672
|
day: z$1.string().optional(),
|
|
3672
3673
|
hour: z$1.string().optional(),
|
|
3673
3674
|
user: z$1.string().optional(),
|
|
@@ -3717,7 +3718,7 @@ var GatewayGenerationInfoFetcher = class {
|
|
|
3717
3718
|
}
|
|
3718
3719
|
}
|
|
3719
3720
|
};
|
|
3720
|
-
var gatewayGenerationInfoResponseSchema = lazySchema(() => zodSchema(z$1.object({ data: z$1.object({
|
|
3721
|
+
var gatewayGenerationInfoResponseSchema = lazySchema(() => zodSchema$1(z$1.object({ data: z$1.object({
|
|
3721
3722
|
id: z$1.string(),
|
|
3722
3723
|
total_cost: z$1.number(),
|
|
3723
3724
|
upstream_inference_cost: z$1.number(),
|
|
@@ -3969,7 +3970,7 @@ var gatewayEmbeddingWarningSchema = z$1.discriminatedUnion("type", [
|
|
|
3969
3970
|
message: z$1.string()
|
|
3970
3971
|
})
|
|
3971
3972
|
]);
|
|
3972
|
-
var gatewayEmbeddingResponseSchema = lazySchema(() => zodSchema(z$1.object({
|
|
3973
|
+
var gatewayEmbeddingResponseSchema = lazySchema(() => zodSchema$1(z$1.object({
|
|
3973
3974
|
embeddings: z$1.array(z$1.array(z$1.number())),
|
|
3974
3975
|
usage: z$1.object({ tokens: z$1.number() }).nullish(),
|
|
3975
3976
|
warnings: z$1.array(gatewayEmbeddingWarningSchema).optional(),
|
|
@@ -4321,7 +4322,7 @@ var gatewayRerankingWarningSchema = z$1.discriminatedUnion("type", [
|
|
|
4321
4322
|
message: z$1.string()
|
|
4322
4323
|
})
|
|
4323
4324
|
]);
|
|
4324
|
-
var gatewayRerankingResponseSchema = lazySchema(() => zodSchema(z$1.object({
|
|
4325
|
+
var gatewayRerankingResponseSchema = lazySchema(() => zodSchema$1(z$1.object({
|
|
4325
4326
|
ranking: z$1.array(z$1.object({
|
|
4326
4327
|
index: z$1.number(),
|
|
4327
4328
|
relevanceScore: z$1.number()
|
|
@@ -4556,7 +4557,7 @@ function toGatewayRealtimeUrl(baseURL, modelId) {
|
|
|
4556
4557
|
}
|
|
4557
4558
|
var exaSearchToolFactory = createProviderExecutedToolFactory({
|
|
4558
4559
|
id: "gateway.exa_search",
|
|
4559
|
-
inputSchema: lazySchema(() => zodSchema(z.object({
|
|
4560
|
+
inputSchema: lazySchema(() => zodSchema$1(z.object({
|
|
4560
4561
|
query: z.string().describe("Natural-language web search query. This is required."),
|
|
4561
4562
|
type: z.enum([
|
|
4562
4563
|
"auto",
|
|
@@ -4619,7 +4620,7 @@ var exaSearchToolFactory = createProviderExecutedToolFactory({
|
|
|
4619
4620
|
}).optional()
|
|
4620
4621
|
}).optional().describe("Controls extracted page content and freshness.")
|
|
4621
4622
|
}))),
|
|
4622
|
-
outputSchema: lazySchema(() => zodSchema(z.union([z.object({
|
|
4623
|
+
outputSchema: lazySchema(() => zodSchema$1(z.union([z.object({
|
|
4623
4624
|
requestId: z.string(),
|
|
4624
4625
|
searchType: z.string().optional(),
|
|
4625
4626
|
resolvedSearchType: z.string().optional(),
|
|
@@ -4662,7 +4663,7 @@ var exaSearchToolFactory = createProviderExecutedToolFactory({
|
|
|
4662
4663
|
var exaSearch = (config = {}) => exaSearchToolFactory(config);
|
|
4663
4664
|
var parallelSearchToolFactory = createProviderExecutedToolFactory({
|
|
4664
4665
|
id: "gateway.parallel_search",
|
|
4665
|
-
inputSchema: lazySchema(() => zodSchema(z.object({
|
|
4666
|
+
inputSchema: lazySchema(() => zodSchema$1(z.object({
|
|
4666
4667
|
objective: z.string().describe("Natural-language description of the web research goal, including source or freshness guidance and broader context from the task. Maximum 5000 characters."),
|
|
4667
4668
|
search_queries: z.array(z.string()).optional().describe("Optional search queries to supplement the objective. Maximum 200 characters per query."),
|
|
4668
4669
|
mode: z.enum(["one-shot", "agentic"]).optional().describe("Mode preset: \"one-shot\" for comprehensive results with longer excerpts (default), \"agentic\" for concise, token-efficient results for multi-step workflows."),
|
|
@@ -4678,7 +4679,7 @@ var parallelSearchToolFactory = createProviderExecutedToolFactory({
|
|
|
4678
4679
|
}).optional().describe("Excerpt configuration for controlling result length."),
|
|
4679
4680
|
fetch_policy: z.object({ max_age_seconds: z.number().optional().describe("Maximum age in seconds for cached content. Set to 0 to always fetch fresh content.") }).optional().describe("Fetch policy for controlling content freshness.")
|
|
4680
4681
|
}))),
|
|
4681
|
-
outputSchema: lazySchema(() => zodSchema(z.union([z.object({
|
|
4682
|
+
outputSchema: lazySchema(() => zodSchema$1(z.union([z.object({
|
|
4682
4683
|
searchId: z.string(),
|
|
4683
4684
|
results: z.array(z.object({
|
|
4684
4685
|
url: z.string(),
|
|
@@ -4703,7 +4704,7 @@ var parallelSearchToolFactory = createProviderExecutedToolFactory({
|
|
|
4703
4704
|
var parallelSearch = (config = {}) => parallelSearchToolFactory(config);
|
|
4704
4705
|
var perplexitySearchToolFactory = createProviderExecutedToolFactory({
|
|
4705
4706
|
id: "gateway.perplexity_search",
|
|
4706
|
-
inputSchema: lazySchema(() => zodSchema(z.object({
|
|
4707
|
+
inputSchema: lazySchema(() => zodSchema$1(z.object({
|
|
4707
4708
|
query: z.union([z.string(), z.array(z.string())]).describe("Search query (string) or multiple queries (array of up to 5 strings). Multi-query searches return combined results from all queries."),
|
|
4708
4709
|
max_results: z.number().optional().describe("Maximum number of search results to return (1-20, default: 10)"),
|
|
4709
4710
|
max_tokens_per_page: z.number().optional().describe("Maximum number of tokens to extract per search result page (256-2048, default: 2048)"),
|
|
@@ -4722,7 +4723,7 @@ var perplexitySearchToolFactory = createProviderExecutedToolFactory({
|
|
|
4722
4723
|
"year"
|
|
4723
4724
|
]).optional().describe("Filter results by relative time period. Cannot be used with search_after_date or search_before_date.")
|
|
4724
4725
|
}))),
|
|
4725
|
-
outputSchema: lazySchema(() => zodSchema(z.union([z.object({
|
|
4726
|
+
outputSchema: lazySchema(() => zodSchema$1(z.union([z.object({
|
|
4726
4727
|
results: z.array(z.object({
|
|
4727
4728
|
title: z.string(),
|
|
4728
4729
|
url: z.string(),
|
|
@@ -46107,6 +46108,650 @@ async function resolveActionCredentials(requirements, options) {
|
|
|
46107
46108
|
return parseResolvedCredentials(requirements, await resolveCredentials(requirements, options.consumer, options.contextOverride));
|
|
46108
46109
|
}
|
|
46109
46110
|
//#endregion
|
|
46110
|
-
|
|
46111
|
+
//#region ../workflow/dist/index.mjs
|
|
46112
|
+
var RunCanceledError = class extends Error {
|
|
46113
|
+
constructor(runId) {
|
|
46114
|
+
super(runId ? `Workflow run ${runId} was canceled` : "Workflow run was canceled");
|
|
46115
|
+
this.name = "RunCanceledError";
|
|
46116
|
+
}
|
|
46117
|
+
};
|
|
46118
|
+
function isRunCanceledError(error) {
|
|
46119
|
+
return error instanceof RunCanceledError;
|
|
46120
|
+
}
|
|
46121
|
+
function executeWorkflowStep(state) {
|
|
46122
|
+
const handle = getWorkflowRunHandle();
|
|
46123
|
+
if (!handle?.workflowRunner) throw new Error(`Workflow "${state.workflow.slug}" can only be called as a step inside a running workflow. Run it standalone with executeWorkflow(...).`);
|
|
46124
|
+
return handle.workflowRunner(state.workflow, state.input, { id: state.id });
|
|
46125
|
+
}
|
|
46126
|
+
function createWorkflowStepInvocation(state) {
|
|
46127
|
+
return {
|
|
46128
|
+
stepId(id) {
|
|
46129
|
+
return createWorkflowStepInvocation({
|
|
46130
|
+
...state,
|
|
46131
|
+
id
|
|
46132
|
+
});
|
|
46133
|
+
},
|
|
46134
|
+
then(onfulfilled, onrejected) {
|
|
46135
|
+
return executeWorkflowStep(state).then(onfulfilled, onrejected);
|
|
46136
|
+
}
|
|
46137
|
+
};
|
|
46138
|
+
}
|
|
46139
|
+
const zodSchema = z.custom((v) => v instanceof z.ZodType, "must be a Zod schema");
|
|
46140
|
+
/** Runtime validation for an unbranded workflow definition. */
|
|
46141
|
+
const workflowCoreSchema = z.object({
|
|
46142
|
+
slug: z.string().trim().min(1),
|
|
46143
|
+
name: z.string().optional(),
|
|
46144
|
+
description: z.string().optional(),
|
|
46145
|
+
subscription: z.object({ mode: z.enum(["system", "subscribable"]).optional() }).optional(),
|
|
46146
|
+
input: zodSchema,
|
|
46147
|
+
output: zodSchema,
|
|
46148
|
+
run: z.function()
|
|
46149
|
+
});
|
|
46150
|
+
const WORKFLOW = Symbol.for("keystroke.workflow");
|
|
46151
|
+
/**
|
|
46152
|
+
* Validates brand + shape via `workflowCoreSchema` so discovery and guards
|
|
46153
|
+
* reject malformed definitions.
|
|
46154
|
+
*/
|
|
46155
|
+
function isWorkflow(value) {
|
|
46156
|
+
if (typeof value !== "object" || value === null) return false;
|
|
46157
|
+
if (!(WORKFLOW in value) || value[WORKFLOW] !== true) return false;
|
|
46158
|
+
return workflowCoreSchema.safeParse(value).success;
|
|
46159
|
+
}
|
|
46160
|
+
function defineWorkflow(def) {
|
|
46161
|
+
const result = workflowCoreSchema.safeParse(def);
|
|
46162
|
+
if (!result.success) throw new Error(`Invalid workflow definition: ${formatIssues(result.error.issues)}`);
|
|
46163
|
+
const body = def.run;
|
|
46164
|
+
const workflow = {
|
|
46165
|
+
...result.data,
|
|
46166
|
+
[WORKFLOW]: true
|
|
46167
|
+
};
|
|
46168
|
+
workflow.run = ((input, ctx) => {
|
|
46169
|
+
if (ctx !== void 0) return body(input, ctx);
|
|
46170
|
+
return createWorkflowStepInvocation({
|
|
46171
|
+
workflow,
|
|
46172
|
+
input
|
|
46173
|
+
});
|
|
46174
|
+
});
|
|
46175
|
+
return workflow;
|
|
46176
|
+
}
|
|
46177
|
+
function formatIssues(issues) {
|
|
46178
|
+
return issues.map((issue) => {
|
|
46179
|
+
return `${issue.path.length > 0 ? `${issue.path.join(".")}: ` : ""}${issue.message}`;
|
|
46180
|
+
}).join("; ");
|
|
46181
|
+
}
|
|
46182
|
+
function serializeWorkflowError(error) {
|
|
46183
|
+
if (error instanceof Error) return {
|
|
46184
|
+
name: error.name,
|
|
46185
|
+
message: error.message
|
|
46186
|
+
};
|
|
46187
|
+
return { message: String(error) };
|
|
46188
|
+
}
|
|
46189
|
+
/** Rebuild an Error from a recorded error so replay re-raises the same failure. */
|
|
46190
|
+
function deserializeWorkflowError(data) {
|
|
46191
|
+
const serialized = data;
|
|
46192
|
+
const error = new Error(serialized?.message ?? "Workflow step failed");
|
|
46193
|
+
if (serialized?.name) error.name = serialized.name;
|
|
46194
|
+
return error;
|
|
46195
|
+
}
|
|
46196
|
+
const UNIT_MS = {
|
|
46197
|
+
ms: 1,
|
|
46198
|
+
s: 1e3,
|
|
46199
|
+
m: 6e4,
|
|
46200
|
+
h: 36e5,
|
|
46201
|
+
d: 864e5
|
|
46202
|
+
};
|
|
46203
|
+
/** Resolve a sleep duration to an absolute resume time. */
|
|
46204
|
+
function resolveResumeAt(duration, now = /* @__PURE__ */ new Date()) {
|
|
46205
|
+
if (duration instanceof Date) return duration;
|
|
46206
|
+
if (typeof duration === "number") return new Date(now.getTime() + Math.max(0, duration));
|
|
46207
|
+
return new Date(now.getTime() + parseDurationToMs(duration));
|
|
46208
|
+
}
|
|
46209
|
+
function parseDurationToMs(value) {
|
|
46210
|
+
const match = /^(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)$/.exec(value.trim());
|
|
46211
|
+
if (!match) throw new Error(`Invalid sleep duration "${value}". Use a number of ms, a Date, or a string like "5s", "10m", "1h".`);
|
|
46212
|
+
const amount = Number(match[1]);
|
|
46213
|
+
const unit = match[2];
|
|
46214
|
+
return Math.round(amount * UNIT_MS[unit]);
|
|
46215
|
+
}
|
|
46216
|
+
/** Indexes replay events by correlationId for O(1) cache-hit checks during replay. */
|
|
46217
|
+
var EventsConsumer = class {
|
|
46218
|
+
byCorrelationId = /* @__PURE__ */ new Map();
|
|
46219
|
+
constructor(events) {
|
|
46220
|
+
for (const event of events) {
|
|
46221
|
+
if (!event.correlationId) continue;
|
|
46222
|
+
const list = this.byCorrelationId.get(event.correlationId);
|
|
46223
|
+
if (list) list.push(event);
|
|
46224
|
+
else this.byCorrelationId.set(event.correlationId, [event]);
|
|
46225
|
+
}
|
|
46226
|
+
}
|
|
46227
|
+
events(correlationId) {
|
|
46228
|
+
return this.byCorrelationId.get(correlationId) ?? [];
|
|
46229
|
+
}
|
|
46230
|
+
hasEventType(correlationId, type) {
|
|
46231
|
+
return this.events(correlationId).some((event) => event.type === type);
|
|
46232
|
+
}
|
|
46233
|
+
/**
|
|
46234
|
+
* Cache lookup for a step. Returns the recorded output on a `step_completed`,
|
|
46235
|
+
* re-raises the recorded error on a terminal `step_failed` (so a permanently
|
|
46236
|
+
* failed step is not re-executed), and otherwise reports a miss — including
|
|
46237
|
+
* when only `step_retrying` events exist (the step re-runs on the next pass).
|
|
46238
|
+
*/
|
|
46239
|
+
getStepResult(correlationId) {
|
|
46240
|
+
const events = this.events(correlationId);
|
|
46241
|
+
const failed = events.find((event) => event.type === "step_failed");
|
|
46242
|
+
if (failed) throw deserializeWorkflowError(failed.data);
|
|
46243
|
+
const completed = events.find((event) => event.type === "step_completed");
|
|
46244
|
+
if (completed) return {
|
|
46245
|
+
completed: true,
|
|
46246
|
+
result: completed.data
|
|
46247
|
+
};
|
|
46248
|
+
return { completed: false };
|
|
46249
|
+
}
|
|
46250
|
+
/** Number of prior `step_retrying` events recorded for a step (= failed attempts so far). */
|
|
46251
|
+
countRetrying(correlationId) {
|
|
46252
|
+
return this.events(correlationId).filter((event) => event.type === "step_retrying").length;
|
|
46253
|
+
}
|
|
46254
|
+
isSleepCompleted(correlationId) {
|
|
46255
|
+
return this.hasEventType(correlationId, "sleep_completed");
|
|
46256
|
+
}
|
|
46257
|
+
/** Returns the persisted resumeAt for a scheduled-but-not-completed sleep, if any. */
|
|
46258
|
+
getSleepResumeAt(correlationId) {
|
|
46259
|
+
const scheduled = this.events(correlationId).find((event) => event.type === "sleep_scheduled");
|
|
46260
|
+
if (!scheduled) return;
|
|
46261
|
+
const data = scheduled.data;
|
|
46262
|
+
return data?.resumeAt ? new Date(data.resumeAt) : void 0;
|
|
46263
|
+
}
|
|
46264
|
+
getHookToken(correlationId) {
|
|
46265
|
+
return (this.events(correlationId).find((event) => event.type === "hook_created")?.data)?.token;
|
|
46266
|
+
}
|
|
46267
|
+
getHookResult(correlationId) {
|
|
46268
|
+
const resumed = this.events(correlationId).find((event) => event.type === "hook_resumed");
|
|
46269
|
+
if (!resumed) return { resolved: false };
|
|
46270
|
+
return {
|
|
46271
|
+
resolved: true,
|
|
46272
|
+
payload: resumed.data?.payload
|
|
46273
|
+
};
|
|
46274
|
+
}
|
|
46275
|
+
};
|
|
46276
|
+
/** A promise that never settles — returned by a suspending primitive so the body parks. */
|
|
46277
|
+
function createPendingPromise() {
|
|
46278
|
+
return new Promise(() => {});
|
|
46279
|
+
}
|
|
46280
|
+
/**
|
|
46281
|
+
* Collects pending items requested within a single tick and resolves once, so
|
|
46282
|
+
* parallel suspensions (e.g. Promise.all of two sleeps) batch into one suspension.
|
|
46283
|
+
*/
|
|
46284
|
+
var SuspensionCoordinator = class {
|
|
46285
|
+
items = /* @__PURE__ */ new Map();
|
|
46286
|
+
scheduled = false;
|
|
46287
|
+
resolve;
|
|
46288
|
+
promise;
|
|
46289
|
+
constructor() {
|
|
46290
|
+
this.promise = new Promise((resolve) => {
|
|
46291
|
+
this.resolve = resolve;
|
|
46292
|
+
});
|
|
46293
|
+
}
|
|
46294
|
+
request(item) {
|
|
46295
|
+
this.items.set(item.correlationId, item);
|
|
46296
|
+
if (!this.scheduled) {
|
|
46297
|
+
this.scheduled = true;
|
|
46298
|
+
queueMicrotask(() => {
|
|
46299
|
+
this.resolve([...this.items.values()]);
|
|
46300
|
+
});
|
|
46301
|
+
}
|
|
46302
|
+
}
|
|
46303
|
+
waitForSuspension() {
|
|
46304
|
+
return this.promise;
|
|
46305
|
+
}
|
|
46306
|
+
};
|
|
46307
|
+
function createReplayState(params) {
|
|
46308
|
+
return {
|
|
46309
|
+
runId: params.runId,
|
|
46310
|
+
consumer: params.consumer,
|
|
46311
|
+
coordinator: params.coordinator,
|
|
46312
|
+
eventLog: params.eventLog,
|
|
46313
|
+
newEvents: [],
|
|
46314
|
+
now: params.now ?? /* @__PURE__ */ new Date(),
|
|
46315
|
+
hookBaseUrl: params.hookBaseUrl,
|
|
46316
|
+
sleepCounter: 0,
|
|
46317
|
+
hookCounter: 0,
|
|
46318
|
+
stepOccurrences: /* @__PURE__ */ new Map(),
|
|
46319
|
+
stepCorrelationIds: /* @__PURE__ */ new Set()
|
|
46320
|
+
};
|
|
46321
|
+
}
|
|
46322
|
+
/**
|
|
46323
|
+
* Allocate the correlation id for a step. An explicit `.stepId(x)` maps to
|
|
46324
|
+
* `step:x` (and must be unique within a run); otherwise the key is
|
|
46325
|
+
* `step:<actionKey>#<occurrence>` so that two calls to the same action get
|
|
46326
|
+
* distinct, replay-stable ids and inserting an unrelated call never shifts the
|
|
46327
|
+
* ids of later calls (unlike a single global ordinal).
|
|
46328
|
+
*/
|
|
46329
|
+
function nextStepCorrelationId(state, actionKey, explicitId) {
|
|
46330
|
+
if (explicitId !== void 0) {
|
|
46331
|
+
const correlationId = `step:${explicitId}`;
|
|
46332
|
+
if (state.stepCorrelationIds.has(correlationId)) throw new Error(`Duplicate step id "${explicitId}" in workflow run ${state.runId}`);
|
|
46333
|
+
state.stepCorrelationIds.add(correlationId);
|
|
46334
|
+
return correlationId;
|
|
46335
|
+
}
|
|
46336
|
+
const occurrence = state.stepOccurrences.get(actionKey) ?? 0;
|
|
46337
|
+
state.stepOccurrences.set(actionKey, occurrence + 1);
|
|
46338
|
+
const correlationId = `step:${actionKey}#${occurrence}`;
|
|
46339
|
+
state.stepCorrelationIds.add(correlationId);
|
|
46340
|
+
return correlationId;
|
|
46341
|
+
}
|
|
46342
|
+
function createSleep(state) {
|
|
46343
|
+
return function sleep(duration) {
|
|
46344
|
+
const correlationId = `sleep#${state.sleepCounter++}`;
|
|
46345
|
+
if (state.consumer.isSleepCompleted(correlationId)) return Promise.resolve();
|
|
46346
|
+
const scheduledResumeAt = state.consumer.getSleepResumeAt(correlationId);
|
|
46347
|
+
const resumeAt = scheduledResumeAt ?? resolveResumeAt(duration, state.now);
|
|
46348
|
+
if (scheduledResumeAt && resumeAt.getTime() <= state.now.getTime()) {
|
|
46349
|
+
state.newEvents.push({
|
|
46350
|
+
id: `sleep_completed:${state.runId}:${correlationId}`,
|
|
46351
|
+
runId: state.runId,
|
|
46352
|
+
type: "sleep_completed",
|
|
46353
|
+
correlationId
|
|
46354
|
+
});
|
|
46355
|
+
return Promise.resolve();
|
|
46356
|
+
}
|
|
46357
|
+
if (!scheduledResumeAt) state.newEvents.push({
|
|
46358
|
+
id: `sleep_scheduled:${state.runId}:${correlationId}`,
|
|
46359
|
+
runId: state.runId,
|
|
46360
|
+
type: "sleep_scheduled",
|
|
46361
|
+
correlationId,
|
|
46362
|
+
data: { resumeAt: resumeAt.toISOString() }
|
|
46363
|
+
});
|
|
46364
|
+
state.coordinator.request({
|
|
46365
|
+
kind: "sleep",
|
|
46366
|
+
correlationId,
|
|
46367
|
+
resumeAt
|
|
46368
|
+
});
|
|
46369
|
+
return createPendingPromise();
|
|
46370
|
+
};
|
|
46371
|
+
}
|
|
46372
|
+
function createHook(state) {
|
|
46373
|
+
return function hook(options) {
|
|
46374
|
+
const correlationId = `hook#${state.hookCounter++}`;
|
|
46375
|
+
const token = options?.token ?? state.consumer.getHookToken(correlationId) ?? `hook_${crypto.randomUUID()}`;
|
|
46376
|
+
const resumeUrl = state.hookBaseUrl ? `${state.hookBaseUrl}/hooks/${token}/resume` : `/hooks/${token}/resume`;
|
|
46377
|
+
const schema = options?.schema ? z.toJSONSchema(options.schema) : void 0;
|
|
46378
|
+
return {
|
|
46379
|
+
token,
|
|
46380
|
+
resumeUrl,
|
|
46381
|
+
then(onFulfilled, onRejected) {
|
|
46382
|
+
const result = state.consumer.getHookResult(correlationId);
|
|
46383
|
+
if (result.resolved) {
|
|
46384
|
+
const payload = options?.schema ? options.schema.parse(result.payload) : result.payload;
|
|
46385
|
+
return Promise.resolve(payload).then(onFulfilled, onRejected);
|
|
46386
|
+
}
|
|
46387
|
+
if (!state.consumer.hasEventType(correlationId, "hook_created")) state.newEvents.push({
|
|
46388
|
+
id: `hook_created:${state.runId}:${correlationId}`,
|
|
46389
|
+
runId: state.runId,
|
|
46390
|
+
type: "hook_created",
|
|
46391
|
+
correlationId,
|
|
46392
|
+
data: schema ? {
|
|
46393
|
+
token,
|
|
46394
|
+
schema
|
|
46395
|
+
} : { token }
|
|
46396
|
+
});
|
|
46397
|
+
state.coordinator.request({
|
|
46398
|
+
kind: "hook",
|
|
46399
|
+
correlationId,
|
|
46400
|
+
token,
|
|
46401
|
+
...schema ? { schema } : {}
|
|
46402
|
+
});
|
|
46403
|
+
return createPendingPromise().then(onFulfilled, onRejected);
|
|
46404
|
+
}
|
|
46405
|
+
};
|
|
46406
|
+
};
|
|
46407
|
+
}
|
|
46408
|
+
/**
|
|
46409
|
+
* Shared durable-step shell: resolve a stable `correlation_id`, short-circuit
|
|
46410
|
+
* from the event log on a cache hit, otherwise execute and append
|
|
46411
|
+
* `step_completed` immediately (per-step crash durability). A thrown step
|
|
46412
|
+
* appends `step_retrying` (non-fatal, re-run on the next attempt) and
|
|
46413
|
+
* rethrows; the terminal `step_failed` is written by the job handler once the
|
|
46414
|
+
* queue exhausts retries.
|
|
46415
|
+
*/
|
|
46416
|
+
async function runDurableStep(state, options) {
|
|
46417
|
+
const { runId, consumer, eventLog } = state;
|
|
46418
|
+
getRunSignal().throwIfAborted();
|
|
46419
|
+
const correlationId = nextStepCorrelationId(state, options.key, options.id);
|
|
46420
|
+
const cached = consumer.getStepResult(correlationId);
|
|
46421
|
+
const metadata = {
|
|
46422
|
+
runId,
|
|
46423
|
+
[options.metadataKey]: options.key,
|
|
46424
|
+
correlationId
|
|
46425
|
+
};
|
|
46426
|
+
if (cached.completed) {
|
|
46427
|
+
await withSpan({
|
|
46428
|
+
kind: options.kind,
|
|
46429
|
+
name: options.key,
|
|
46430
|
+
refId: `${runId}:${correlationId}`,
|
|
46431
|
+
metadata: {
|
|
46432
|
+
...metadata,
|
|
46433
|
+
replayed: true
|
|
46434
|
+
}
|
|
46435
|
+
}, async () => {
|
|
46436
|
+
await logSystem("info", options.replayMessage, metadata);
|
|
46437
|
+
});
|
|
46438
|
+
return options.parseCached ? options.parseCached(cached.result) : cached.result;
|
|
46439
|
+
}
|
|
46440
|
+
return withSpan({
|
|
46441
|
+
kind: options.kind,
|
|
46442
|
+
name: options.key,
|
|
46443
|
+
refId: `${runId}:${correlationId}`,
|
|
46444
|
+
metadata
|
|
46445
|
+
}, async () => captureConsole(async () => {
|
|
46446
|
+
try {
|
|
46447
|
+
const result = await options.execute(correlationId);
|
|
46448
|
+
await eventLog.append({
|
|
46449
|
+
id: `step_completed:${runId}:${correlationId}`,
|
|
46450
|
+
runId,
|
|
46451
|
+
type: "step_completed",
|
|
46452
|
+
correlationId,
|
|
46453
|
+
data: result
|
|
46454
|
+
});
|
|
46455
|
+
return result;
|
|
46456
|
+
} catch (error) {
|
|
46457
|
+
const attempt = consumer.countRetrying(correlationId);
|
|
46458
|
+
await eventLog.append({
|
|
46459
|
+
id: `step_retrying:${runId}:${correlationId}:${attempt}`,
|
|
46460
|
+
runId,
|
|
46461
|
+
type: "step_retrying",
|
|
46462
|
+
correlationId,
|
|
46463
|
+
data: serializeWorkflowError(error)
|
|
46464
|
+
});
|
|
46465
|
+
state.failedCorrelationId = correlationId;
|
|
46466
|
+
throw error;
|
|
46467
|
+
}
|
|
46468
|
+
}));
|
|
46469
|
+
}
|
|
46470
|
+
function withCredentialScopeOverride(requirements, scope) {
|
|
46471
|
+
if (!requirements || !scope) return requirements;
|
|
46472
|
+
return normalizeCredentialList(requirements).map((requirement) => ({
|
|
46473
|
+
...requirement,
|
|
46474
|
+
scope
|
|
46475
|
+
}));
|
|
46476
|
+
}
|
|
46477
|
+
/** Builds the per-run action runner; durability lives in {@link runDurableStep}. */
|
|
46478
|
+
function createActionRunner(state, options = {}) {
|
|
46479
|
+
return (action, input, runOptions) => runDurableStep(state, {
|
|
46480
|
+
kind: "action",
|
|
46481
|
+
key: action.slug,
|
|
46482
|
+
id: runOptions?.id,
|
|
46483
|
+
metadataKey: "actionKey",
|
|
46484
|
+
replayMessage: "action replayed from checkpoint",
|
|
46485
|
+
parseCached: (cached) => action.output.parse(cached),
|
|
46486
|
+
execute: async (correlationId) => {
|
|
46487
|
+
const requirements = withCredentialScopeOverride(getActionCredentialRequirements(action), runOptions?.credentialScope);
|
|
46488
|
+
const credentials = requirements?.length ? await resolveActionCredentials(requirements, {
|
|
46489
|
+
resolveCredentials: options.resolveCredentials,
|
|
46490
|
+
context: options.credentialContext,
|
|
46491
|
+
oauthAdapter: options.oauthAdapter,
|
|
46492
|
+
consumer: {
|
|
46493
|
+
kind: "action",
|
|
46494
|
+
name: action.slug,
|
|
46495
|
+
id: correlationId
|
|
46496
|
+
}
|
|
46497
|
+
}) : {};
|
|
46498
|
+
return runWithMcpCredentialContext({
|
|
46499
|
+
...options.mcpCredentialContext,
|
|
46500
|
+
consumerId: correlationId
|
|
46501
|
+
}, () => executeAction(action, input, credentials));
|
|
46502
|
+
}
|
|
46503
|
+
});
|
|
46504
|
+
}
|
|
46505
|
+
/**
|
|
46506
|
+
* Builds the per-run agent runner: each `agent.prompt()` in a workflow body
|
|
46507
|
+
* becomes a durable step keyed `step:<agentKey>#<occurrence>` (same scheme as
|
|
46508
|
+
* actions). The actual prompt execution is delegated to `runAgent`, supplied
|
|
46509
|
+
* by the host (server) via `executeWorkflow({ runAgent })`.
|
|
46510
|
+
*/
|
|
46511
|
+
function createAgentStepRunner(state, runAgent) {
|
|
46512
|
+
return (agent, input, options) => {
|
|
46513
|
+
const slug = agent.slug;
|
|
46514
|
+
return runDurableStep(state, {
|
|
46515
|
+
kind: "agent_session",
|
|
46516
|
+
key: slug,
|
|
46517
|
+
id: options?.id,
|
|
46518
|
+
metadataKey: "agentKey",
|
|
46519
|
+
replayMessage: "agent step replayed from checkpoint",
|
|
46520
|
+
execute: (_correlationId) => runAgent(agent, input, options?.runPrompt)
|
|
46521
|
+
});
|
|
46522
|
+
};
|
|
46523
|
+
}
|
|
46524
|
+
/**
|
|
46525
|
+
* Builds the per-run LLM runner: each `promptLlm()` in a workflow body becomes a
|
|
46526
|
+
* durable step keyed `step:promptLlm#<occurrence>`. The actual LLM call is
|
|
46527
|
+
* delegated to `runLlm`, supplied by the host (server) via `executeWorkflow({ runLlm })`.
|
|
46528
|
+
*/
|
|
46529
|
+
function createLlmStepRunner(state, runLlm) {
|
|
46530
|
+
return (opts) => runDurableStep(state, {
|
|
46531
|
+
kind: "llm",
|
|
46532
|
+
key: "promptLlm",
|
|
46533
|
+
id: opts.stepId,
|
|
46534
|
+
metadataKey: "llmKey",
|
|
46535
|
+
replayMessage: "llm step replayed from checkpoint",
|
|
46536
|
+
parseCached: (cached) => opts.outputSchema ? opts.outputSchema.parse(cached) : cached,
|
|
46537
|
+
execute: (_correlationId) => runLlm(opts)
|
|
46538
|
+
});
|
|
46539
|
+
}
|
|
46540
|
+
/**
|
|
46541
|
+
* Builds the per-run sub-workflow runner: each `workflow.run(input)` inside a
|
|
46542
|
+
* workflow body becomes a durable step keyed `step:<slug>#<occurrence>`. The
|
|
46543
|
+
* sub-workflow's body runs inline in the same replay state (its action/agent/
|
|
46544
|
+
* LLM steps and `ctx.sleep`/`ctx.hook` stay durable), and its validated output
|
|
46545
|
+
* is checkpointed so a replay skips the whole sub-workflow once it completes.
|
|
46546
|
+
*/
|
|
46547
|
+
function createWorkflowStepRunner(state, ctx) {
|
|
46548
|
+
return (workflowUnknown, input, options) => {
|
|
46549
|
+
const workflow = workflowUnknown;
|
|
46550
|
+
const parsedInput = workflow.input.parse(input);
|
|
46551
|
+
return runDurableStep(state, {
|
|
46552
|
+
kind: "workflow_run",
|
|
46553
|
+
key: workflow.slug,
|
|
46554
|
+
id: options?.id,
|
|
46555
|
+
metadataKey: "workflowKey",
|
|
46556
|
+
replayMessage: "workflow step replayed from checkpoint",
|
|
46557
|
+
parseCached: (cached) => workflow.output.parse(cached),
|
|
46558
|
+
execute: async () => {
|
|
46559
|
+
const output = await workflow.run(parsedInput, ctx);
|
|
46560
|
+
return workflow.output.parse(output);
|
|
46561
|
+
}
|
|
46562
|
+
});
|
|
46563
|
+
};
|
|
46564
|
+
}
|
|
46565
|
+
const storage = new AsyncLocalStorage();
|
|
46566
|
+
registerWorkflowRunGetter(() => {
|
|
46567
|
+
const store = storage.getStore();
|
|
46568
|
+
if (!store) return;
|
|
46569
|
+
return {
|
|
46570
|
+
actionRunner: store.actionRunner,
|
|
46571
|
+
agentRunner: store.agentRunner,
|
|
46572
|
+
llmRunner: store.llmRunner,
|
|
46573
|
+
workflowRunner: store.workflowRunner
|
|
46574
|
+
};
|
|
46575
|
+
});
|
|
46576
|
+
function runWithWorkflowContext(store, fn) {
|
|
46577
|
+
return storage.run(store, fn);
|
|
46578
|
+
}
|
|
46579
|
+
/** In-memory durable log for inline execution and tests. */
|
|
46580
|
+
var MemoryEventLog = class {
|
|
46581
|
+
events = [];
|
|
46582
|
+
ids = /* @__PURE__ */ new Set();
|
|
46583
|
+
async append(event) {
|
|
46584
|
+
const id = event.id ?? crypto.randomUUID();
|
|
46585
|
+
if (this.ids.has(id)) return false;
|
|
46586
|
+
this.ids.add(id);
|
|
46587
|
+
this.events.push({
|
|
46588
|
+
id,
|
|
46589
|
+
runId: event.runId,
|
|
46590
|
+
seq: this.events.length,
|
|
46591
|
+
type: event.type,
|
|
46592
|
+
correlationId: event.correlationId ?? null,
|
|
46593
|
+
data: event.data ?? null
|
|
46594
|
+
});
|
|
46595
|
+
return true;
|
|
46596
|
+
}
|
|
46597
|
+
async listReplay(runId) {
|
|
46598
|
+
return this.events.filter((event) => event.runId === runId).map((event) => ({ ...event }));
|
|
46599
|
+
}
|
|
46600
|
+
};
|
|
46601
|
+
/**
|
|
46602
|
+
* The single way to run a workflow: replay its event log from the top, execute
|
|
46603
|
+
* un-cached primitives, and either complete/fail or suspend at the first
|
|
46604
|
+
* un-satisfied sleep/hook. New events (sleep_scheduled/sleep_completed/
|
|
46605
|
+
* hook_created/run_completed/run_failed) are flushed before returning.
|
|
46606
|
+
*
|
|
46607
|
+
* Durability comes entirely from the log — a suspended run resumes by calling
|
|
46608
|
+
* this again with the same `runId` and event log once the sleep is due or the
|
|
46609
|
+
* hook is resumed.
|
|
46610
|
+
*/
|
|
46611
|
+
async function executeWorkflow(workflow, input, options = {}) {
|
|
46612
|
+
const runId = options.runId ?? crypto.randomUUID();
|
|
46613
|
+
const eventLog = options.eventLog ?? new MemoryEventLog();
|
|
46614
|
+
const signal = getRunSignal();
|
|
46615
|
+
const consumer = new EventsConsumer(await eventLog.listReplay(runId));
|
|
46616
|
+
const coordinator = new SuspensionCoordinator();
|
|
46617
|
+
const state = createReplayState({
|
|
46618
|
+
runId,
|
|
46619
|
+
consumer,
|
|
46620
|
+
coordinator,
|
|
46621
|
+
eventLog,
|
|
46622
|
+
hookBaseUrl: options.hookBaseUrl,
|
|
46623
|
+
now: options.now
|
|
46624
|
+
});
|
|
46625
|
+
const actionRunner = createActionRunner(state, {
|
|
46626
|
+
resolveCredentials: options.resolveCredentials,
|
|
46627
|
+
credentialContext: options.credentialContext,
|
|
46628
|
+
oauthAdapter: options.oauthAdapter,
|
|
46629
|
+
mcpCredentialContext: { assignmentTarget: {
|
|
46630
|
+
type: "workflow",
|
|
46631
|
+
key: workflow.slug
|
|
46632
|
+
} }
|
|
46633
|
+
});
|
|
46634
|
+
const ctx = {
|
|
46635
|
+
runId,
|
|
46636
|
+
sleep: createSleep(state),
|
|
46637
|
+
hook: createHook(state),
|
|
46638
|
+
...options.context
|
|
46639
|
+
};
|
|
46640
|
+
const agentRunner = options.runAgent ? createAgentStepRunner(state, options.runAgent) : void 0;
|
|
46641
|
+
const llmRunner = options.runLlm ? createLlmStepRunner(state, options.runLlm) : void 0;
|
|
46642
|
+
const workflowRunner = createWorkflowStepRunner(state, ctx);
|
|
46643
|
+
const validatedInput = workflow.input.parse(input);
|
|
46644
|
+
const bodyPromise = runWithWorkflowContext({
|
|
46645
|
+
actionRunner,
|
|
46646
|
+
agentRunner,
|
|
46647
|
+
llmRunner,
|
|
46648
|
+
workflowRunner,
|
|
46649
|
+
runId
|
|
46650
|
+
}, () => captureConsole(async () => workflow.run(validatedInput, ctx)));
|
|
46651
|
+
let onAbort;
|
|
46652
|
+
const waitForAbort = signal.aborted ? Promise.resolve({ type: "canceled" }) : new Promise((resolve) => {
|
|
46653
|
+
onAbort = () => resolve({ type: "canceled" });
|
|
46654
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
46655
|
+
});
|
|
46656
|
+
const outcome = await Promise.race([
|
|
46657
|
+
bodyPromise.then((output) => ({
|
|
46658
|
+
type: "done",
|
|
46659
|
+
output
|
|
46660
|
+
}), (error) => ({
|
|
46661
|
+
type: "error",
|
|
46662
|
+
error
|
|
46663
|
+
})),
|
|
46664
|
+
coordinator.waitForSuspension().then((items) => ({
|
|
46665
|
+
type: "suspended",
|
|
46666
|
+
items
|
|
46667
|
+
})),
|
|
46668
|
+
waitForAbort
|
|
46669
|
+
]);
|
|
46670
|
+
if (onAbort) signal.removeEventListener("abort", onAbort);
|
|
46671
|
+
let result;
|
|
46672
|
+
if (outcome.type === "suspended") {
|
|
46673
|
+
bodyPromise.catch(() => {});
|
|
46674
|
+
result = {
|
|
46675
|
+
status: "suspended",
|
|
46676
|
+
items: outcome.items
|
|
46677
|
+
};
|
|
46678
|
+
} else if (outcome.type === "done") {
|
|
46679
|
+
const output = workflow.output.parse(outcome.output);
|
|
46680
|
+
state.newEvents.push({
|
|
46681
|
+
id: `run_completed:${runId}`,
|
|
46682
|
+
runId,
|
|
46683
|
+
type: "run_completed",
|
|
46684
|
+
data: { output }
|
|
46685
|
+
});
|
|
46686
|
+
result = {
|
|
46687
|
+
status: "completed",
|
|
46688
|
+
output
|
|
46689
|
+
};
|
|
46690
|
+
} else if (outcome.type === "canceled" || isRunCanceledError(outcome.error)) {
|
|
46691
|
+
bodyPromise.catch(() => {});
|
|
46692
|
+
state.newEvents.push({
|
|
46693
|
+
id: `run_canceled:${runId}`,
|
|
46694
|
+
runId,
|
|
46695
|
+
type: "run_canceled"
|
|
46696
|
+
});
|
|
46697
|
+
result = { status: "canceled" };
|
|
46698
|
+
} else result = {
|
|
46699
|
+
status: "failed",
|
|
46700
|
+
error: outcome.error,
|
|
46701
|
+
failedCorrelationId: state.failedCorrelationId
|
|
46702
|
+
};
|
|
46703
|
+
for (const event of state.newEvents) await eventLog.append(event);
|
|
46704
|
+
return result;
|
|
46705
|
+
}
|
|
46706
|
+
function promptLlm(prompt, opts) {
|
|
46707
|
+
const handle = getWorkflowRunHandle();
|
|
46708
|
+
if (!handle?.llmRunner) throw new Error("promptLlm must run inside a workflow with an injected llm executor (executeWorkflow({ runLlm })).");
|
|
46709
|
+
return handle.llmRunner({
|
|
46710
|
+
prompt,
|
|
46711
|
+
...opts
|
|
46712
|
+
});
|
|
46713
|
+
}
|
|
46714
|
+
let executor;
|
|
46715
|
+
function registerWorkflowToolExecutor(fn) {
|
|
46716
|
+
if (executor) throw new Error("workflow tool executor already registered");
|
|
46717
|
+
executor = fn;
|
|
46718
|
+
}
|
|
46719
|
+
function getWorkflowToolExecutor() {
|
|
46720
|
+
if (!executor) throw new Error("workflow tool executor not registered");
|
|
46721
|
+
return executor;
|
|
46722
|
+
}
|
|
46723
|
+
function assertWorkflowToolInput(workflow) {
|
|
46724
|
+
if (!("shape" in workflow.input) || typeof workflow.input.shape !== "object") throw new Error(`Workflow "${workflow.slug}" cannot be used as an agent tool: input schema must be a Zod object.`);
|
|
46725
|
+
}
|
|
46726
|
+
function resolveWorkflowTool(workflow) {
|
|
46727
|
+
assertWorkflowToolInput(workflow);
|
|
46728
|
+
const key = workflow.slug;
|
|
46729
|
+
return defineTool({
|
|
46730
|
+
name: key,
|
|
46731
|
+
label: key,
|
|
46732
|
+
description: workflow.description ?? key,
|
|
46733
|
+
parameters: workflow.input,
|
|
46734
|
+
async execute(toolCallId, params) {
|
|
46735
|
+
const output = await withSpan({
|
|
46736
|
+
kind: "tool_call",
|
|
46737
|
+
name: key,
|
|
46738
|
+
refId: toolCallId,
|
|
46739
|
+
metadata: {
|
|
46740
|
+
tool: key,
|
|
46741
|
+
type: "workflow"
|
|
46742
|
+
}
|
|
46743
|
+
}, () => getWorkflowToolExecutor()(workflow, params, { workflowKey: key }));
|
|
46744
|
+
return {
|
|
46745
|
+
content: [{
|
|
46746
|
+
type: "text",
|
|
46747
|
+
text: JSON.stringify(output)
|
|
46748
|
+
}],
|
|
46749
|
+
details: output
|
|
46750
|
+
};
|
|
46751
|
+
}
|
|
46752
|
+
});
|
|
46753
|
+
}
|
|
46754
|
+
//#endregion
|
|
46755
|
+
export { require_token_error as $, output_exports as A, getProjectScopeId as B, defineMcp as C, generateObject as D, convertToModelMessages as E, appendEvent as F, setSessionLiveMessage as G, listMessageEvents as H, clearLiveMessage as I, captureConsole as J, setSessionTitle as K, createSession as L, toUIMessageStream as M, MESSAGE_EVENT_TYPE as N, generateText as O, addAgentSessionDuration as P, require_token_util as Q, failAgentSession as R, connectMcpStdio as S, ToolLoopAgent as T, recordLlmUsageFromAssistantMessage as U, getSession as V, resolveRunSourceFromTraceContext as W, withSpan as X, getTraceContext as Y, createGateway as Z, resolveActionCredentials as _, executeWorkflow as a, connectMcpDefinition as b, promptLlm as c, serializeWorkflowError as d, generateId as et, buildCredentialRunContext as f, isCredentialError as g, enrichCredentialError as h, deserializeWorkflowError as i, readUIMessageStream as j, isFileUIPart as k, registerWorkflowToolExecutor as l, createCredentialResolver as m, RunCanceledError as n, tool as nt, isRunCanceledError as o, captureCredentialToolErrors as p, touchSession as q, defineWorkflow as r, isWorkflow as s, MemoryEventLog as t, jsonSchema as tt, resolveWorkflowTool as u, resolveMcpTools as v, isMcp as w, connectMcpServer as x, withCredentialAssignments as y, getAgentByRoute as z };
|
|
46111
46756
|
|
|
46112
|
-
//# sourceMappingURL=dist-
|
|
46757
|
+
//# sourceMappingURL=dist-B1Pjv-cM.mjs.map
|