@forestadmin/workflow-executor 1.13.0 → 1.14.0
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/README.md +4 -0
- package/dist/adapters/ai-client-adapter.d.ts +5 -1
- package/dist/adapters/ai-client-adapter.js +4 -1
- package/dist/adapters/always-error-ai-model-port.d.ts +5 -1
- package/dist/adapters/always-error-ai-model-port.js +6 -1
- package/dist/adapters/server-ai-adapter.d.ts +5 -1
- package/dist/adapters/server-ai-adapter.js +4 -1
- package/dist/adapters/step-outcome-to-update-step-mapper.js +4 -1
- package/dist/build-workflow-executor.js +87 -2
- package/dist/crypto/credential-encryption.d.ts +10 -0
- package/dist/crypto/credential-encryption.js +75 -0
- package/dist/defaults.d.ts +1 -0
- package/dist/defaults.js +5 -2
- package/dist/errors.d.ts +18 -0
- package/dist/errors.js +50 -2
- package/dist/executors/mcp-step-executor.d.ts +7 -2
- package/dist/executors/mcp-step-executor.js +78 -14
- package/dist/executors/step-executor-factory.d.ts +1 -1
- package/dist/executors/step-executor-factory.js +24 -3
- package/dist/http/executor-http-server.d.ts +12 -0
- package/dist/http/executor-http-server.js +90 -1
- package/dist/http/mcp-oauth-credentials.d.ts +24 -0
- package/dist/http/mcp-oauth-credentials.js +77 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.js +10 -3
- package/dist/oauth/keyed-mutex.d.ts +5 -0
- package/dist/oauth/keyed-mutex.js +27 -0
- package/dist/oauth/refresh-grant.d.ts +15 -0
- package/dist/oauth/refresh-grant.js +112 -0
- package/dist/oauth/token-endpoint-url.d.ts +2 -0
- package/dist/oauth/token-endpoint-url.js +103 -0
- package/dist/oauth/token-service.d.ts +34 -0
- package/dist/oauth/token-service.js +172 -0
- package/dist/ports/ai-model-port.d.ts +5 -1
- package/dist/ports/mcp-oauth-credentials-store.d.ts +24 -0
- package/dist/ports/mcp-oauth-credentials-store.js +3 -0
- package/dist/ports/run-store.d.ts +1 -0
- package/dist/remote-tool-fetcher.d.ts +7 -2
- package/dist/remote-tool-fetcher.js +53 -6
- package/dist/runner.d.ts +2 -0
- package/dist/runner.js +3 -3
- package/dist/stores/database-mcp-oauth-credentials-store.d.ts +22 -0
- package/dist/stores/database-mcp-oauth-credentials-store.js +188 -0
- package/dist/stores/database-store.d.ts +1 -1
- package/dist/stores/database-store.js +17 -50
- package/dist/stores/in-memory-mcp-oauth-credentials-store.d.ts +13 -0
- package/dist/stores/in-memory-mcp-oauth-credentials-store.js +44 -0
- package/dist/stores/in-memory-store.d.ts +1 -0
- package/dist/stores/in-memory-store.js +6 -1
- package/dist/stores/schema-migrations.d.ts +19 -0
- package/dist/stores/schema-migrations.js +69 -0
- package/dist/types/validated/execution.d.ts +6 -0
- package/dist/types/validated/step-outcome.d.ts +10 -0
- package/dist/types/validated/step-outcome.js +7 -2
- package/package.json +4 -4
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// In-memory MCP OAuth credentials store for --in-memory / dev. Same throwaway semantics as
|
|
4
|
+
// InMemoryStore (the run store): state is lost on restart. It holds the already-encrypted Buffers
|
|
5
|
+
// produced by buildMcpOAuthCredentialInput — there is no crypto here, just a Map keyed by
|
|
6
|
+
// (userId, mcpServerId), mirroring the DB store's one-row-per-key contract.
|
|
7
|
+
class InMemoryMcpOAuthCredentialsStore {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.data = new Map();
|
|
10
|
+
this.nextId = 1;
|
|
11
|
+
}
|
|
12
|
+
async init() {
|
|
13
|
+
// No-op: nothing to migrate for an in-memory store.
|
|
14
|
+
}
|
|
15
|
+
async close() {
|
|
16
|
+
// No-op: nothing to close.
|
|
17
|
+
}
|
|
18
|
+
async get(userId, mcpServerId) {
|
|
19
|
+
return this.data.get(InMemoryMcpOAuthCredentialsStore.key(userId, mcpServerId)) ?? null;
|
|
20
|
+
}
|
|
21
|
+
async upsert(credential) {
|
|
22
|
+
// Overwrite in place — one row per (userId, mcpServerId). A fresh id each time mirrors the DB
|
|
23
|
+
// store's delete-then-insert; nothing relies on id stability.
|
|
24
|
+
const key = InMemoryMcpOAuthCredentialsStore.key(credential.userId, credential.mcpServerId);
|
|
25
|
+
this.data.set(key, { ...credential, id: this.nextId });
|
|
26
|
+
this.nextId += 1;
|
|
27
|
+
}
|
|
28
|
+
async updateIfPresent(id, credential) {
|
|
29
|
+
const key = InMemoryMcpOAuthCredentialsStore.key(credential.userId, credential.mcpServerId);
|
|
30
|
+
const existing = this.data.get(key);
|
|
31
|
+
// Only update the exact row the caller read; a re-created row has a new id, so skip it.
|
|
32
|
+
if (!existing || existing.id !== id)
|
|
33
|
+
return;
|
|
34
|
+
this.data.set(key, { ...credential, id });
|
|
35
|
+
}
|
|
36
|
+
async delete(userId, mcpServerId) {
|
|
37
|
+
this.data.delete(InMemoryMcpOAuthCredentialsStore.key(userId, mcpServerId));
|
|
38
|
+
}
|
|
39
|
+
static key(userId, mcpServerId) {
|
|
40
|
+
return `${userId}:${mcpServerId}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.default = InMemoryMcpOAuthCredentialsStore;
|
|
44
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW4tbWVtb3J5LW1jcC1vYXV0aC1jcmVkZW50aWFscy1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdG9yZXMvaW4tbWVtb3J5LW1jcC1vYXV0aC1jcmVkZW50aWFscy1zdG9yZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQU1BLDJGQUEyRjtBQUMzRixrR0FBa0c7QUFDbEcsMEZBQTBGO0FBQzFGLDRFQUE0RTtBQUM1RSxNQUFxQixnQ0FBZ0M7SUFBckQ7UUFDbUIsU0FBSSxHQUFHLElBQUksR0FBRyxFQUFvQyxDQUFDO1FBQzVELFdBQU0sR0FBRyxDQUFDLENBQUM7SUFzQ3JCLENBQUM7SUFwQ0MsS0FBSyxDQUFDLElBQUk7UUFDUixvREFBb0Q7SUFDdEQsQ0FBQztJQUVELEtBQUssQ0FBQyxLQUFLO1FBQ1QsMkJBQTJCO0lBQzdCLENBQUM7SUFFRCxLQUFLLENBQUMsR0FBRyxDQUFDLE1BQWMsRUFBRSxXQUFtQjtRQUMzQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGdDQUFnQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsV0FBVyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUM7SUFDMUYsQ0FBQztJQUVELEtBQUssQ0FBQyxNQUFNLENBQUMsVUFBbUM7UUFDOUMsOEZBQThGO1FBQzlGLDhEQUE4RDtRQUM5RCxNQUFNLEdBQUcsR0FBRyxnQ0FBZ0MsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUYsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEVBQUUsR0FBRyxVQUFVLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO0lBQ25CLENBQUM7SUFFRCxLQUFLLENBQUMsZUFBZSxDQUFDLEVBQVUsRUFBRSxVQUFtQztRQUNuRSxNQUFNLEdBQUcsR0FBRyxnQ0FBZ0MsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDNUYsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEMsd0ZBQXdGO1FBQ3hGLElBQUksQ0FBQyxRQUFRLElBQUksUUFBUSxDQUFDLEVBQUUsS0FBSyxFQUFFO1lBQUUsT0FBTztRQUU1QyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxHQUFHLFVBQVUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQzVDLENBQUM7SUFFRCxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQWMsRUFBRSxXQUFtQjtRQUM5QyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQ0FBZ0MsQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVPLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBYyxFQUFFLFdBQW1CO1FBQ3BELE9BQU8sR0FBRyxNQUFNLElBQUksV0FBVyxFQUFFLENBQUM7SUFDcEMsQ0FBQztDQUNGO0FBeENELG1EQXdDQyJ9
|
|
@@ -6,6 +6,7 @@ export default class InMemoryStore implements RunStore {
|
|
|
6
6
|
close(): Promise<void>;
|
|
7
7
|
getStepExecutions(runId: string): Promise<StepExecutionData[]>;
|
|
8
8
|
saveStepExecution(runId: string, stepExecution: StepExecutionData): Promise<void>;
|
|
9
|
+
deleteStepExecution(runId: string, stepIndex: number): Promise<void>;
|
|
9
10
|
private callPort;
|
|
10
11
|
}
|
|
11
12
|
//# sourceMappingURL=in-memory-store.d.ts.map
|
|
@@ -33,6 +33,11 @@ class InMemoryStore {
|
|
|
33
33
|
runData.set(stepExecution.stepIndex, stepExecution);
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
|
+
async deleteStepExecution(runId, stepIndex) {
|
|
37
|
+
return this.callPort('deleteStepExecution', async () => {
|
|
38
|
+
this.data.get(runId)?.delete(stepIndex);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
36
41
|
async callPort(operation, fn) {
|
|
37
42
|
try {
|
|
38
43
|
return await fn();
|
|
@@ -45,4 +50,4 @@ class InMemoryStore {
|
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
52
|
exports.default = InMemoryStore;
|
|
48
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW4tbWVtb3J5LXN0b3JlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3Jlcy9pbi1tZW1vcnktc3RvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFHQSxzQ0FBcUU7QUFFckUsTUFBcUIsYUFBYTtJQUFsQztRQUNtQixTQUFJLEdBQUcsSUFBSSxHQUFHLEVBQTBDLENBQUM7SUFtRDVFLENBQUM7SUFqREMsS0FBSyxDQUFDLElBQUk7UUFDUixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3RDLG9EQUFvRDtRQUN0RCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsS0FBSztRQUNULE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDdkMsNkJBQTZCO1FBQy9CLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxLQUFhO1FBQ25DLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVyQyxJQUFJLENBQUMsT0FBTztnQkFBRSxPQUFPLEVBQUUsQ0FBQztZQUV4QixPQUFPLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUN6RSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxLQUFLLENBQUMsaUJBQWlCLENBQUMsS0FBYSxFQUFFLGFBQWdDO1FBQ3JFLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxtQkFBbUIsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRCxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUVuQyxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2IsT0FBTyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7Z0JBQ3BCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQztZQUNoQyxDQUFDO1lBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsU0FBUyxFQUFFLGFBQWEsQ0FBQyxDQUFDO1FBQ3RELENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxLQUFhLEVBQUUsU0FBaUI7UUFDeEQsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLHFCQUFxQixFQUFFLEtBQUssSUFBSSxFQUFFO1lBQ3JELElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxQyxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxLQUFLLENBQUMsUUFBUSxDQUFJLFNBQWlCLEVBQUUsRUFBb0I7UUFDL0QsSUFBSSxDQUFDO1lBQ0gsT0FBTyxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ3BCLENBQUM7UUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1lBQ2YsSUFBSSxLQUFLLFlBQVksOEJBQXFCO2dCQUFFLE1BQU0sS0FBSyxDQUFDO1lBQ3hELE1BQU0sSUFBSSwwQkFBaUIsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDaEQsQ0FBQztJQUNILENBQUM7Q0FDRjtBQXBERCxnQ0FvREMifQ==
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Logger } from '../ports/logger-port';
|
|
2
|
+
import type { Sequelize } from 'sequelize';
|
|
3
|
+
export declare const DEFAULT_SCHEMA = "forest";
|
|
4
|
+
export declare function resolveSchema(sequelize: Sequelize, configured?: string): string | undefined;
|
|
5
|
+
export declare function tableId(schema: string | undefined, tableName: string): string | {
|
|
6
|
+
tableName: string;
|
|
7
|
+
schema: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function tableReference(schema: string | undefined, tableName: string): string;
|
|
10
|
+
export declare function runMigrations({ sequelize, umzug, schema, logger, failMessage, }: {
|
|
11
|
+
sequelize: Sequelize;
|
|
12
|
+
umzug: {
|
|
13
|
+
up: () => Promise<unknown>;
|
|
14
|
+
};
|
|
15
|
+
schema: string | undefined;
|
|
16
|
+
logger?: Logger;
|
|
17
|
+
failMessage: string;
|
|
18
|
+
}): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=schema-migrations.d.ts.map
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_SCHEMA = void 0;
|
|
4
|
+
exports.resolveSchema = resolveSchema;
|
|
5
|
+
exports.tableId = tableId;
|
|
6
|
+
exports.tableReference = tableReference;
|
|
7
|
+
exports.runMigrations = runMigrations;
|
|
8
|
+
const errors_1 = require("../errors");
|
|
9
|
+
// The schema both executor tables live under, so a shared customer database stays safe: the executor
|
|
10
|
+
// never touches `public`, and its umzug `SequelizeMeta` registries can't collide with the
|
|
11
|
+
// agent/server's own. Skipped on SQLite (test suite), which has no schema support.
|
|
12
|
+
exports.DEFAULT_SCHEMA = 'forest';
|
|
13
|
+
// Must stay constant across releases, or an old and a new deploy could migrate concurrently. Shared
|
|
14
|
+
// by every executor migration runner so all of them serialize against one another on cold start.
|
|
15
|
+
const MIGRATION_ADVISORY_LOCK_KEY = 6438071259157;
|
|
16
|
+
function resolveSchema(sequelize, configured) {
|
|
17
|
+
if (sequelize.getDialect() === 'sqlite')
|
|
18
|
+
return undefined;
|
|
19
|
+
return configured || exports.DEFAULT_SCHEMA;
|
|
20
|
+
}
|
|
21
|
+
function tableId(schema, tableName) {
|
|
22
|
+
return schema ? { tableName, schema } : tableName;
|
|
23
|
+
}
|
|
24
|
+
function tableReference(schema, tableName) {
|
|
25
|
+
return schema ? `"${schema}"."${tableName}"` : `"${tableName}"`;
|
|
26
|
+
}
|
|
27
|
+
// Serializes booting instances via a transaction-scoped advisory lock: auto-releases at commit and
|
|
28
|
+
// is pooler-safe (RDS Proxy / PgBouncer), unlike a session lock which would leak there.
|
|
29
|
+
async function withMigrationLock(sequelize, run) {
|
|
30
|
+
await sequelize.transaction(async (transaction) => {
|
|
31
|
+
// Stop a client idle-in-transaction timeout from killing this idle txn mid-migration, which
|
|
32
|
+
// would drop the lock.
|
|
33
|
+
await sequelize.query('SET LOCAL idle_in_transaction_session_timeout = 0', { transaction });
|
|
34
|
+
await sequelize.query('SELECT pg_advisory_xact_lock($1)', {
|
|
35
|
+
bind: [MIGRATION_ADVISORY_LOCK_KEY],
|
|
36
|
+
transaction,
|
|
37
|
+
});
|
|
38
|
+
await run(transaction);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
// Runs an umzug migration set under the executor's shared-database safety rules: on Postgres the
|
|
42
|
+
// `forest` schema is created and migrations run behind the advisory lock (one writer across booting
|
|
43
|
+
// replicas); on other dialects (SQLite) it just runs. Logs `failMessage` and rethrows on failure.
|
|
44
|
+
async function runMigrations({ sequelize, umzug, schema, logger, failMessage, }) {
|
|
45
|
+
try {
|
|
46
|
+
if (sequelize.getDialect() !== 'postgres') {
|
|
47
|
+
await umzug.up();
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// The migration lock holds one pool connection while umzug opens a second.
|
|
51
|
+
const { pool } = sequelize.connectionManager;
|
|
52
|
+
// With replication configured, `pool` splits into write/read sub-pools and `maxSize` is
|
|
53
|
+
// undefined; the migration lock runs on the write pool, so size the check against it.
|
|
54
|
+
const poolMax = pool?.maxSize ?? pool?.write?.maxSize ?? pool?.read?.maxSize ?? 1;
|
|
55
|
+
if (poolMax < 2) {
|
|
56
|
+
throw new Error('workflow-executor requires pool.max >= 2 on Postgres: the migration lock holds one connection while migrations run on another');
|
|
57
|
+
}
|
|
58
|
+
// Schema in its own committed transaction so umzug (on other connections) sees it.
|
|
59
|
+
if (schema) {
|
|
60
|
+
await withMigrationLock(sequelize, transaction => sequelize.query(`CREATE SCHEMA IF NOT EXISTS "${schema}"`, { transaction }));
|
|
61
|
+
}
|
|
62
|
+
await withMigrationLock(sequelize, () => umzug.up());
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
logger?.('Error', failMessage, { error: (0, errors_1.extractErrorMessage)(error) });
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLW1pZ3JhdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RvcmVzL3NjaGVtYS1taWdyYXRpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWNBLHNDQUlDO0FBRUQsMEJBS0M7QUFFRCx3Q0FFQztBQXVCRCxzQ0E4Q0M7QUEvRkQsc0NBQWdEO0FBRWhELHFHQUFxRztBQUNyRywwRkFBMEY7QUFDMUYsbUZBQW1GO0FBQ3RFLFFBQUEsY0FBYyxHQUFHLFFBQVEsQ0FBQztBQUV2QyxvR0FBb0c7QUFDcEcsaUdBQWlHO0FBQ2pHLE1BQU0sMkJBQTJCLEdBQUcsYUFBaUIsQ0FBQztBQUV0RCxTQUFnQixhQUFhLENBQUMsU0FBb0IsRUFBRSxVQUFtQjtJQUNyRSxJQUFJLFNBQVMsQ0FBQyxVQUFVLEVBQUUsS0FBSyxRQUFRO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFFMUQsT0FBTyxVQUFVLElBQUksc0JBQWMsQ0FBQztBQUN0QyxDQUFDO0FBRUQsU0FBZ0IsT0FBTyxDQUNyQixNQUEwQixFQUMxQixTQUFpQjtJQUVqQixPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUNwRCxDQUFDO0FBRUQsU0FBZ0IsY0FBYyxDQUFDLE1BQTBCLEVBQUUsU0FBaUI7SUFDMUUsT0FBTyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksTUFBTSxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLFNBQVMsR0FBRyxDQUFDO0FBQ2xFLENBQUM7QUFFRCxtR0FBbUc7QUFDbkcsd0ZBQXdGO0FBQ3hGLEtBQUssVUFBVSxpQkFBaUIsQ0FDOUIsU0FBb0IsRUFDcEIsR0FBbUQ7SUFFbkQsTUFBTSxTQUFTLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBQyxXQUFXLEVBQUMsRUFBRTtRQUM5Qyw0RkFBNEY7UUFDNUYsdUJBQXVCO1FBQ3ZCLE1BQU0sU0FBUyxDQUFDLEtBQUssQ0FBQyxtREFBbUQsRUFBRSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUM7UUFDNUYsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUFDLGtDQUFrQyxFQUFFO1lBQ3hELElBQUksRUFBRSxDQUFDLDJCQUEyQixDQUFDO1lBQ25DLFdBQVc7U0FDWixDQUFDLENBQUM7UUFDSCxNQUFNLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUN6QixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxpR0FBaUc7QUFDakcsb0dBQW9HO0FBQ3BHLGtHQUFrRztBQUMzRixLQUFLLFVBQVUsYUFBYSxDQUFDLEVBQ2xDLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLE1BQU0sRUFDTixXQUFXLEdBT1o7SUFDQyxJQUFJLENBQUM7UUFDSCxJQUFJLFNBQVMsQ0FBQyxVQUFVLEVBQUUsS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUMxQyxNQUFNLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUVqQixPQUFPO1FBQ1QsQ0FBQztRQUVELDJFQUEyRTtRQUMzRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsU0FBUyxDQUFDLGlCQUUxQixDQUFDO1FBQ0Ysd0ZBQXdGO1FBQ3hGLHNGQUFzRjtRQUN0RixNQUFNLE9BQU8sR0FBRyxJQUFJLEVBQUUsT0FBTyxJQUFJLElBQUksRUFBRSxLQUFLLEVBQUUsT0FBTyxJQUFJLElBQUksRUFBRSxJQUFJLEVBQUUsT0FBTyxJQUFJLENBQUMsQ0FBQztRQUVsRixJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNoQixNQUFNLElBQUksS0FBSyxDQUNiLCtIQUErSCxDQUNoSSxDQUFDO1FBQ0osQ0FBQztRQUVELG1GQUFtRjtRQUNuRixJQUFJLE1BQU0sRUFBRSxDQUFDO1lBQ1gsTUFBTSxpQkFBaUIsQ0FBQyxTQUFTLEVBQUUsV0FBVyxDQUFDLEVBQUUsQ0FDL0MsU0FBUyxDQUFDLEtBQUssQ0FBQyxnQ0FBZ0MsTUFBTSxHQUFHLEVBQUUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUM1RSxDQUFDO1FBQ0osQ0FBQztRQUVELE1BQU0saUJBQWlCLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxFQUFFLENBQUMsT0FBTyxFQUFFLFdBQVcsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFBLDRCQUFtQixFQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUN0RSxNQUFNLEtBQUssQ0FBQztJQUNkLENBQUM7QUFDSCxDQUFDIn0=
|
|
@@ -122,6 +122,9 @@ export declare const StepSchema: z.ZodObject<{
|
|
|
122
122
|
error: "error";
|
|
123
123
|
"awaiting-input": "awaiting-input";
|
|
124
124
|
}>;
|
|
125
|
+
awaitingInputReason: z.ZodOptional<z.ZodEnum<{
|
|
126
|
+
"needs-oauth-reauth": "needs-oauth-reauth";
|
|
127
|
+
}>>;
|
|
125
128
|
stepId: z.ZodString;
|
|
126
129
|
stepIndex: z.ZodNumber;
|
|
127
130
|
error: z.ZodOptional<z.ZodString>;
|
|
@@ -339,6 +342,9 @@ export declare const AvailableStepExecutionSchema: z.ZodObject<{
|
|
|
339
342
|
error: "error";
|
|
340
343
|
"awaiting-input": "awaiting-input";
|
|
341
344
|
}>;
|
|
345
|
+
awaitingInputReason: z.ZodOptional<z.ZodEnum<{
|
|
346
|
+
"needs-oauth-reauth": "needs-oauth-reauth";
|
|
347
|
+
}>>;
|
|
342
348
|
stepId: z.ZodString;
|
|
343
349
|
stepIndex: z.ZodNumber;
|
|
344
350
|
error: z.ZodOptional<z.ZodString>;
|
|
@@ -11,6 +11,10 @@ export declare const RecordStepStatusSchema: z.ZodEnum<{
|
|
|
11
11
|
"awaiting-input": "awaiting-input";
|
|
12
12
|
}>;
|
|
13
13
|
export type RecordStepStatus = z.infer<typeof RecordStepStatusSchema>;
|
|
14
|
+
export declare const AwaitingInputReasonSchema: z.ZodEnum<{
|
|
15
|
+
"needs-oauth-reauth": "needs-oauth-reauth";
|
|
16
|
+
}>;
|
|
17
|
+
export type AwaitingInputReason = z.infer<typeof AwaitingInputReasonSchema>;
|
|
14
18
|
export type StepStatus = BaseStepStatus | RecordStepStatus;
|
|
15
19
|
export declare const ConditionStepOutcomeSchema: z.ZodObject<{
|
|
16
20
|
type: z.ZodLiteral<"condition">;
|
|
@@ -47,6 +51,9 @@ export declare const McpStepOutcomeSchema: z.ZodObject<{
|
|
|
47
51
|
error: "error";
|
|
48
52
|
"awaiting-input": "awaiting-input";
|
|
49
53
|
}>;
|
|
54
|
+
awaitingInputReason: z.ZodOptional<z.ZodEnum<{
|
|
55
|
+
"needs-oauth-reauth": "needs-oauth-reauth";
|
|
56
|
+
}>>;
|
|
50
57
|
stepId: z.ZodString;
|
|
51
58
|
stepIndex: z.ZodNumber;
|
|
52
59
|
error: z.ZodOptional<z.ZodString>;
|
|
@@ -95,6 +102,9 @@ export declare const StepOutcomeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
95
102
|
error: "error";
|
|
96
103
|
"awaiting-input": "awaiting-input";
|
|
97
104
|
}>;
|
|
105
|
+
awaitingInputReason: z.ZodOptional<z.ZodEnum<{
|
|
106
|
+
"needs-oauth-reauth": "needs-oauth-reauth";
|
|
107
|
+
}>>;
|
|
98
108
|
stepId: z.ZodString;
|
|
99
109
|
stepIndex: z.ZodNumber;
|
|
100
110
|
error: z.ZodOptional<z.ZodString>;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.StepOutcomeSchema = exports.GuidanceStepOutcomeSchema = exports.McpStepOutcomeSchema = exports.RecordStepOutcomeSchema = exports.ConditionStepOutcomeSchema = exports.RecordStepStatusSchema = exports.BaseStepStatusSchema = void 0;
|
|
3
|
+
exports.StepOutcomeSchema = exports.GuidanceStepOutcomeSchema = exports.McpStepOutcomeSchema = exports.RecordStepOutcomeSchema = exports.ConditionStepOutcomeSchema = exports.AwaitingInputReasonSchema = exports.RecordStepStatusSchema = exports.BaseStepStatusSchema = void 0;
|
|
4
4
|
exports.stepTypeToOutcomeType = stepTypeToOutcomeType;
|
|
5
5
|
const zod_1 = require("zod");
|
|
6
6
|
const step_definition_1 = require("./step-definition");
|
|
7
7
|
exports.BaseStepStatusSchema = zod_1.z.enum(['success', 'error']);
|
|
8
8
|
// AI steps can pause mid-execution to await user input (awaiting-input).
|
|
9
9
|
exports.RecordStepStatusSchema = zod_1.z.enum(['success', 'error', 'awaiting-input']);
|
|
10
|
+
// Typed reason for an awaiting-input pause the user must resolve out of band: the Forest server
|
|
11
|
+
// validates it and the front reads it to prompt the matching action.
|
|
12
|
+
exports.AwaitingInputReasonSchema = zod_1.z.enum(['needs-oauth-reauth']);
|
|
10
13
|
/**
|
|
11
14
|
* StepOutcome is sent to the orchestrator — it must NEVER contain client data.
|
|
12
15
|
* Any privacy-sensitive information (e.g. AI reasoning) must stay in
|
|
@@ -40,6 +43,8 @@ exports.McpStepOutcomeSchema = zod_1.z
|
|
|
40
43
|
...baseOutcomeFields,
|
|
41
44
|
type: zod_1.z.literal('mcp'),
|
|
42
45
|
status: exports.RecordStepStatusSchema,
|
|
46
|
+
/** Present when status is 'awaiting-input' because the step paused for re-authentication. */
|
|
47
|
+
awaitingInputReason: exports.AwaitingInputReasonSchema.optional(),
|
|
43
48
|
})
|
|
44
49
|
.strict();
|
|
45
50
|
exports.GuidanceStepOutcomeSchema = zod_1.z
|
|
@@ -64,4 +69,4 @@ function stepTypeToOutcomeType(type) {
|
|
|
64
69
|
return 'guidance';
|
|
65
70
|
return 'record';
|
|
66
71
|
}
|
|
67
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
72
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC1vdXRjb21lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3R5cGVzL3ZhbGlkYXRlZC9zdGVwLW91dGNvbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBK0VBLHNEQU1DO0FBckZELDZCQUF3QjtBQUV4Qix1REFBNkM7QUFFaEMsUUFBQSxvQkFBb0IsR0FBRyxPQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFHakUseUVBQXlFO0FBQzVELFFBQUEsc0JBQXNCLEdBQUcsT0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDO0FBR3JGLGdHQUFnRztBQUNoRyxxRUFBcUU7QUFDeEQsUUFBQSx5QkFBeUIsR0FBRyxPQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUFDO0FBS3hFOzs7O0dBSUc7QUFDSCxNQUFNLGlCQUFpQixHQUFHO0lBQ3hCLE1BQU0sRUFBRSxPQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN6QixTQUFTLEVBQUUsT0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDLFdBQVcsRUFBRTtJQUN6QyxzQ0FBc0M7SUFDdEMsS0FBSyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDN0IsQ0FBQztBQUVXLFFBQUEsMEJBQTBCLEdBQUcsT0FBQztLQUN4QyxNQUFNLENBQUM7SUFDTixHQUFHLGlCQUFpQjtJQUNwQixJQUFJLEVBQUUsT0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUM7SUFDNUIsTUFBTSxFQUFFLDhCQUFzQjtJQUM5Qix3Q0FBd0M7SUFDeEMsY0FBYyxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUU7Q0FDdEMsQ0FBQztLQUNELE1BQU0sRUFBRSxDQUFDO0FBR0MsUUFBQSx1QkFBdUIsR0FBRyxPQUFDO0tBQ3JDLE1BQU0sQ0FBQztJQUNOLEdBQUcsaUJBQWlCO0lBQ3BCLElBQUksRUFBRSxPQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQztJQUN6QixNQUFNLEVBQUUsOEJBQXNCO0lBQzlCLGVBQWUsRUFBRSxPQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLE9BQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFO0NBQ3pELENBQUM7S0FDRCxNQUFNLEVBQUUsQ0FBQztBQUdDLFFBQUEsb0JBQW9CLEdBQUcsT0FBQztLQUNsQyxNQUFNLENBQUM7SUFDTixHQUFHLGlCQUFpQjtJQUNwQixJQUFJLEVBQUUsT0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7SUFDdEIsTUFBTSxFQUFFLDhCQUFzQjtJQUM5Qiw2RkFBNkY7SUFDN0YsbUJBQW1CLEVBQUUsaUNBQXlCLENBQUMsUUFBUSxFQUFFO0NBQzFELENBQUM7S0FDRCxNQUFNLEVBQUUsQ0FBQztBQUdDLFFBQUEseUJBQXlCLEdBQUcsT0FBQztLQUN2QyxNQUFNLENBQUM7SUFDTixHQUFHLGlCQUFpQjtJQUNwQixJQUFJLEVBQUUsT0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUM7SUFDM0IsTUFBTSxFQUFFLDhCQUFzQjtDQUMvQixDQUFDO0tBQ0QsTUFBTSxFQUFFLENBQUM7QUFHQyxRQUFBLGlCQUFpQixHQUFHLE9BQUMsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLEVBQUU7SUFDNUQsa0NBQTBCO0lBQzFCLCtCQUF1QjtJQUN2Qiw0QkFBb0I7SUFDcEIsaUNBQXlCO0NBQzFCLENBQUMsQ0FBQztBQUdILFNBQWdCLHFCQUFxQixDQUFDLElBQWM7SUFDbEQsSUFBSSxJQUFJLEtBQUssMEJBQVEsQ0FBQyxTQUFTO1FBQUUsT0FBTyxXQUFXLENBQUM7SUFDcEQsSUFBSSxJQUFJLEtBQUssMEJBQVEsQ0FBQyxHQUFHO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDeEMsSUFBSSxJQUFJLEtBQUssMEJBQVEsQ0FBQyxRQUFRO1FBQUUsT0FBTyxVQUFVLENBQUM7SUFFbEQsT0FBTyxRQUFRLENBQUM7QUFDbEIsQ0FBQyJ9
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forestadmin/workflow-executor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"forest-workflow-executor": "dist/cli.js"
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"test": "jest"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@forestadmin/agent-client": "1.10.
|
|
33
|
-
"@forestadmin/ai-proxy": "1.
|
|
34
|
-
"@forestadmin/forestadmin-client": "1.40.
|
|
32
|
+
"@forestadmin/agent-client": "1.10.1",
|
|
33
|
+
"@forestadmin/ai-proxy": "1.12.0",
|
|
34
|
+
"@forestadmin/forestadmin-client": "1.40.4",
|
|
35
35
|
"@koa/bodyparser": "^6.1.0",
|
|
36
36
|
"@koa/router": "^15.6.0",
|
|
37
37
|
"jsonwebtoken": "^9.0.3",
|