Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
a7237f2
feat(api chart): allow customizing api chart with query or body param…
arnaud-moncel Mar 18, 2026
50c9268
chore(release): @forestadmin/datasource-toolkit@1.53.0 [skip ci]
forest-bot Mar 18, 2026
05835cb
chore(release): @forestadmin/ai-proxy@1.6.2 [skip ci]
forest-bot Mar 18, 2026
b420042
chore(release): @forestadmin/datasource-customizer@1.69.0 [skip ci]
forest-bot Mar 18, 2026
9235d0e
chore(release): @forestadmin/datasource-dummy@1.1.66 [skip ci]
forest-bot Mar 18, 2026
b9beeac
chore(release): @forestadmin/datasource-mongoose@1.13.3 [skip ci]
forest-bot Mar 18, 2026
de58a28
chore(release): @forestadmin/datasource-sequelize@1.13.6 [skip ci]
forest-bot Mar 18, 2026
0279778
chore(release): @forestadmin/datasource-sql@1.17.8 [skip ci]
forest-bot Mar 18, 2026
e028364
chore(release): @forestadmin/forestadmin-client@1.37.18 [skip ci]
forest-bot Mar 18, 2026
8f04f32
chore(release): @forestadmin/plugin-aws-s3@1.5.10 [skip ci]
forest-bot Mar 18, 2026
b587a4c
chore(release): @forestadmin/plugin-export-advanced@1.1.40 [skip ci]
forest-bot Mar 18, 2026
f5147e8
chore(release): @forestadmin/plugin-flattener@1.4.24 [skip ci]
forest-bot Mar 18, 2026
42210e3
chore(release): @forestadmin/agent-client@1.4.14 [skip ci]
forest-bot Mar 18, 2026
4e67f35
chore(release): @forestadmin/datasource-replica@1.8.4 [skip ci]
forest-bot Mar 18, 2026
70d91c6
chore(release): @forestadmin/datasource-mongo@1.6.7 [skip ci]
forest-bot Mar 18, 2026
bb8872a
chore(release): @forestadmin/mcp-server@1.8.9 [skip ci]
forest-bot Mar 18, 2026
62b37ee
chore(release): @forestadmin/agent@1.75.0 [skip ci]
forest-bot Mar 18, 2026
44a16db
chore(release): @forestadmin/agent-testing@1.0.23 [skip ci]
forest-bot Mar 18, 2026
cb18439
chore(release): @forestadmin/forest-cloud@1.12.98 [skip ci]
forest-bot Mar 18, 2026
79056f7
fix(capabilities): fix aggregation validation on computed field (#1519)
arnaud-moncel Mar 31, 2026
75473ff
chore(release): @forestadmin/datasource-customizer@1.69.1 [skip ci]
forest-bot Mar 31, 2026
0ec787c
chore(release): @forestadmin/datasource-dummy@1.1.67 [skip ci]
forest-bot Mar 31, 2026
8b88b21
chore(release): @forestadmin/plugin-aws-s3@1.5.11 [skip ci]
forest-bot Mar 31, 2026
38df6ba
chore(release): @forestadmin/plugin-export-advanced@1.1.41 [skip ci]
forest-bot Mar 31, 2026
c6f42c2
chore(release): @forestadmin/plugin-flattener@1.4.25 [skip ci]
forest-bot Mar 31, 2026
7dd269e
chore(release): @forestadmin/datasource-replica@1.8.5 [skip ci]
forest-bot Mar 31, 2026
4485af3
chore(release): @forestadmin/agent@1.75.1 [skip ci]
forest-bot Mar 31, 2026
9caf746
chore(release): @forestadmin/agent-testing@1.0.24 [skip ci]
forest-bot Mar 31, 2026
7bd9a9e
chore(release): @forestadmin/forest-cloud@1.12.99 [skip ci]
forest-bot Mar 31, 2026
c52b1e1
fix: address security vulnerabilities in dependencies (#1516)
PMerlet Mar 31, 2026
50157ef
chore(release): @forestadmin/ai-proxy@1.6.3 [skip ci]
forest-bot Mar 31, 2026
a69693b
chore(release): @forestadmin/datasource-sequelize@1.13.7 [skip ci]
forest-bot Mar 31, 2026
34ebccc
chore(release): @forestadmin/datasource-sql@1.17.9 [skip ci]
forest-bot Mar 31, 2026
58dc06a
chore(release): @forestadmin/forestadmin-client@1.37.19 [skip ci]
forest-bot Mar 31, 2026
d68aeeb
chore(release): @forestadmin/agent-client@1.4.15 [skip ci]
forest-bot Mar 31, 2026
77dfadd
chore(release): @forestadmin/datasource-replica@1.8.6 [skip ci]
forest-bot Mar 31, 2026
9946156
chore(release): @forestadmin/mcp-server@1.8.10 [skip ci]
forest-bot Mar 31, 2026
c660a4f
chore(release): @forestadmin/agent@1.75.2 [skip ci]
forest-bot Mar 31, 2026
44802f4
chore(release): @forestadmin/agent-testing@1.0.25 [skip ci]
forest-bot Mar 31, 2026
fd3c9f7
chore(release): @forestadmin/forest-cloud@1.12.100 [skip ci]
forest-bot Mar 31, 2026
6181114
feat(ai-proxy): add forest connectors (#1505)
nbouliol Mar 31, 2026
869a0f5
chore(release): @forestadmin/agent-toolkit@1.2.0 [skip ci]
forest-bot Mar 31, 2026
f3e9aed
chore(release): @forestadmin/datasource-toolkit@1.53.1 [skip ci]
forest-bot Mar 31, 2026
20e9836
chore(release): @forestadmin/ai-proxy@1.7.0 [skip ci]
forest-bot Mar 31, 2026
79e8b69
chore(release): @forestadmin/datasource-customizer@1.69.2 [skip ci]
forest-bot Mar 31, 2026
c5ea5ef
chore(release): @forestadmin/datasource-dummy@1.1.68 [skip ci]
forest-bot Mar 31, 2026
d9bd2d7
chore(release): @forestadmin/datasource-mongoose@1.13.4 [skip ci]
forest-bot Mar 31, 2026
4ac2a2c
chore(release): @forestadmin/datasource-sequelize@1.13.8 [skip ci]
forest-bot Mar 31, 2026
0f50307
chore(release): @forestadmin/datasource-sql@1.17.10 [skip ci]
forest-bot Mar 31, 2026
1546862
chore(release): @forestadmin/forestadmin-client@1.38.0 [skip ci]
forest-bot Mar 31, 2026
85165c4
chore(release): @forestadmin/plugin-aws-s3@1.5.12 [skip ci]
forest-bot Mar 31, 2026
09f86e2
chore(release): @forestadmin/plugin-export-advanced@1.1.42 [skip ci]
forest-bot Mar 31, 2026
e688f61
chore(release): @forestadmin/plugin-flattener@1.4.26 [skip ci]
forest-bot Mar 31, 2026
9e0ada3
chore(release): @forestadmin/agent-client@1.4.16 [skip ci]
forest-bot Mar 31, 2026
606020d
chore(release): @forestadmin/datasource-replica@1.8.7 [skip ci]
forest-bot Mar 31, 2026
dc2a0f0
chore(release): @forestadmin/datasource-mongo@1.6.8 [skip ci]
forest-bot Mar 31, 2026
b625bc3
chore(release): @forestadmin/mcp-server@1.8.11 [skip ci]
forest-bot Mar 31, 2026
16c03ab
chore(release): @forestadmin/agent@1.76.0 [skip ci]
forest-bot Mar 31, 2026
234b71a
chore(release): @forestadmin/agent-testing@1.1.0 [skip ci]
forest-bot Mar 31, 2026
2ce5c0c
chore(release): @forestadmin/forest-cloud@1.12.101 [skip ci]
forest-bot Mar 31, 2026
54ff837
fix(ai-proxy): use proper AI error classes instead of generic Error (…
Scra3 Mar 31, 2026
7919e47
chore(release): @forestadmin/ai-proxy@1.7.1 [skip ci]
forest-bot Mar 31, 2026
88652fe
chore(release): @forestadmin/forestadmin-client@1.38.1 [skip ci]
forest-bot Mar 31, 2026
f2c40f8
chore(release): @forestadmin/agent-client@1.4.17 [skip ci]
forest-bot Mar 31, 2026
211f01c
chore(release): @forestadmin/mcp-server@1.8.12 [skip ci]
forest-bot Mar 31, 2026
4b4631b
chore(release): @forestadmin/agent@1.76.1 [skip ci]
forest-bot Mar 31, 2026
5a22b1f
chore(release): @forestadmin/agent-testing@1.1.1 [skip ci]
forest-bot Mar 31, 2026
dc5d9c4
chore(release): @forestadmin/forest-cloud@1.12.102 [skip ci]
forest-bot Mar 31, 2026
7113983
fix(ai-proxy): throw on duplicate tool names, add source-id disambigu…
Scra3 Apr 1, 2026
2800b71
chore(release): @forestadmin/ai-proxy@1.7.2 [skip ci]
forest-bot Apr 1, 2026
5184fa0
chore(release): @forestadmin/forestadmin-client@1.38.2 [skip ci]
forest-bot Apr 1, 2026
0d2d4e4
chore(release): @forestadmin/agent-client@1.4.18 [skip ci]
forest-bot Apr 1, 2026
8d0a311
chore(release): @forestadmin/mcp-server@1.8.13 [skip ci]
forest-bot Apr 1, 2026
527e259
chore(release): @forestadmin/agent@1.76.2 [skip ci]
forest-bot Apr 1, 2026
c7d99c5
chore(release): @forestadmin/agent-testing@1.1.2 [skip ci]
forest-bot Apr 1, 2026
2692773
chore(release): @forestadmin/forest-cloud@1.12.103 [skip ci]
forest-bot Apr 1, 2026
34f8242
feat(workflow-executor): scaffold @forestadmin/workflow-executor package
matthv Mar 17, 2026
754783f
feat(workflow-executor): finalize scaffold — clean CLAUDE.md, remove …
Mar 17, 2026
b151c36
fix(workflow-executor): address review — lint test dir, improve test,…
Mar 17, 2026
dd83ec0
feat(workflow-executor): define foundational types and port interface…
Scra3 Mar 18, 2026
2562a1d
feat(workflow-executor): implement condition step executor (AI-only) …
Scra3 Mar 18, 2026
ea772f8
feat(workflow-executor): implement AgentPort adapter using agent-clie…
matthv Mar 18, 2026
492ca3e
feat(ai-proxy): add programmatic API to aiClient (#1492)
Scra3 Mar 18, 2026
e7390a1
feat(workflow-executor): implement WorkflowPort adapter using foresta…
matthv Mar 18, 2026
c7da8d7
feat(workflow-executor): add ReadRecordStepExecutor (#1497)
Scra3 Mar 19, 2026
b8bbc81
feat(workflow-executor): add HTTP server and WorkflowRunner scaffold …
matthv Mar 20, 2026
fd7fd62
refactor(workflow-executor): workflow steps (#1502)
Scra3 Mar 24, 2026
6f1f240
feat(workflow-executor): add JWT auth and secret validation to HTTP s…
matthv Mar 24, 2026
f9f918c
refactor(workflow-executor): move userConfirmed to RunStore pendingDa…
Scra3 Mar 25, 2026
a8ba26b
feat(workflow-executor): add RunStore implementations (InMemoryStore …
matthv Mar 25, 2026
5bf306c
feat(workflow-executor): type-specific PATCH body validation (#1508)
Scra3 Mar 25, 2026
6bead7b
refactor(workflow-executor): encapsulate pending-data business logic …
Scra3 Mar 25, 2026
9113f43
docs(workflow-executor): update contract to match implementation (#1511)
Scra3 Mar 25, 2026
87118c1
feat(workflow-executor): add buildInMemoryExecutor and buildDatabaseE…
Scra3 Mar 26, 2026
bb8cfea
feat(workflow-executor): add graceful shutdown with in-flight step dr…
matthv Mar 27, 2026
2aef70e
feat(workflow-executor): add info logging around step execution (#1514)
Scra3 Mar 30, 2026
24d7639
feat(workflow-executor): add pre-recorded AI decisions for record ste…
Scra3 Mar 31, 2026
dbe12b4
refactor(workflow-executor): remove redundant Task from all naming (#…
Scra3 Mar 31, 2026
876341e
feat(workflow-executor): add example setup with Docker and buildDatab…
matthv Apr 1, 2026
2ea7e95
fix: resolve rebase conflicts for workflow-executor onto main
matthv Apr 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ jobs:
- plugin-aws-s3
- plugin-export-advanced
- plugin-flattener
- workflow-executor
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
Expand Down
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ yarn workspace @forestadmin/agent test
5. Are edge cases handled?
6. Is the naming clear and consistent?

## Git Workflow

The **main working branch** for workflow-executor development is `feat/prd-214-setup-workflow-executor-package`.
All feature branches for this area should be based on and PRs targeted at this branch (not `main`).

## Linear Tickets

### MCP Setup
Expand Down
285 changes: 285 additions & 0 deletions WORKFLOW-EXECUTOR-CONTRACT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
# Workflow Executor — Contract Types

> Types exchanged between the **orchestrator (server)**, the **executor (agent-nodejs)**, and the **frontend**.
> Last updated: 2026-03-26

---

## 1. Polling

**`GET /liana/v1/workflow-step-executions/pending?runId=<runId>`**

The executor polls for the current pending step of a run. The server must return **one object** (not an array), or `null` if the run is not found.

```typescript
interface StepUser {
id: number;
email: string;
firstName: string;
lastName: string;
team: string;
renderingId: number;
role: string;
permissionLevel: string;
tags: Record<string, string>;
}

interface PendingStepExecution {
runId: string;
stepId: string;
stepIndex: number;
baseRecordRef: RecordRef;
stepDefinition: StepDefinition;
previousSteps: Step[];
user: StepUser; // identity of the user who initiated the step
}
```

> **`null` response** → executor throws `RunNotFoundError` → HTTP 404 returned to caller.

### CollectionSchema

Schema of a collection, returned by the orchestrator via `GET /liana/v1/collections/:collectionName`. Used by the executor to resolve primary keys and action endpoints.

```typescript
interface CollectionSchema {
collectionName: string;
collectionDisplayName: string;
primaryKeyFields: string[];
fields: FieldSchema[];
actions: ActionSchema[];
}

interface FieldSchema {
fieldName: string;
displayName: string;
isRelationship: boolean;
relationType?: "BelongsTo" | "HasMany" | "HasOne";
relatedCollectionName?: string;
}

interface ActionSchema {
name: string;
displayName: string;
endpoint: string; // route path used by the agent to execute the action
}
```

### RecordRef

Lightweight pointer to a specific record.

```typescript
interface RecordRef {
collectionName: string;
recordId: Array<string | number>;
stepIndex: number; // index of the workflow step that loaded this record
}
```

### Step

History entry for an already-executed step (used in `previousSteps`).

```typescript
interface Step {
stepDefinition: StepDefinition;
stepOutcome: StepOutcome;
}
```

### StepDefinition

Discriminated union on `type`.

```typescript
type StepDefinition =
| ConditionStepDefinition
| RecordTaskStepDefinition
| McpTaskStepDefinition;

interface ConditionStepDefinition {
type: "condition";
options: [string, ...string[]]; // at least one option required
prompt?: string;
aiConfigName?: string;
}

interface RecordTaskStepDefinition {
type: "read-record"
| "update-record"
| "trigger-action"
| "load-related-record";
prompt?: string;
aiConfigName?: string;
automaticExecution?: boolean;
}

interface McpTaskStepDefinition {
type: "mcp-task";
mcpServerId?: string;
prompt?: string;
aiConfigName?: string;
automaticExecution?: boolean;
}
```

### StepOutcome

What the executor previously reported for each past step (used in `previousSteps`).

```typescript
type StepOutcome =
| ConditionStepOutcome
| RecordTaskStepOutcome
| McpTaskStepOutcome;

interface ConditionStepOutcome {
type: "condition";
stepId: string;
stepIndex: number;
status: "success" | "error";
selectedOption?: string; // present when status = "success"
error?: string; // present when status = "error"
}

interface RecordTaskStepOutcome {
type: "record-task";
stepId: string;
stepIndex: number;
status: "success" | "error" | "awaiting-input";
error?: string; // present when status = "error"
}

interface McpTaskStepOutcome {
type: "mcp-task";
stepId: string;
stepIndex: number;
status: "success" | "error" | "awaiting-input";
error?: string; // present when status = "error"
}
```

---

## 2. Step Result

**`POST /liana/v1/workflow-step-executions/<runId>/complete`**

After executing a step, the executor posts the outcome back to the server. The body is one of the `StepOutcome` shapes above.

> **NEVER contains client data** (field values, AI reasoning, etc.) — those stay in the `RunStore` on the client side.

---

## 3. Pending Data

Steps that require user input pause with `status: "awaiting-input"`. The executor writes its AI-selected data to `pendingData` in the RunStore. The frontend can then override fields and confirm via the pending-data endpoint.

**`PATCH /runs/:runId/steps/:stepIndex/pending-data`**

The frontend writes user overrides + confirmation to the executor HTTP server. Request bodies are validated per step type with strict Zod schemas — unknown fields are rejected with `400`.

Once written, the frontend calls `POST /runs/:runId/trigger`. On the next execution, the executor reads `pendingData` from the RunStore and checks `userConfirmed`:
- `undefined` → returns `awaiting-input` again (the step is not yet actionable)
- `true` → execute the confirmed action
- `false` → skip the step (mark as success)

### update-record — user picks a field + value to write

The executor writes the AI's field selection to `pendingData`. The frontend can override `value` and confirm.

Stored in RunStore:
```typescript
interface UpdateRecordPendingData {
name: string; // technical field name (set by executor)
displayName: string; // label shown in the UI (set by executor)
value: string; // AI-proposed value; overridable by frontend
userConfirmed?: boolean; // set by frontend via PATCH
}
```

PATCH request body:
```typescript
{
userConfirmed: boolean;
value?: string; // optional override of AI-proposed value
}
```

### trigger-action & mcp-task — user confirmation only

The executor selects the action (or MCP tool) and writes `pendingData` to the RunStore. The frontend cannot override any executor-selected data — it only confirms or rejects.

PATCH request body (same for both types):
```typescript
{
userConfirmed: boolean;
}
```

### load-related-record — user picks the relation and/or the record

The executor writes the AI's relation selection to `pendingData`. The frontend can override the relation, the selected record, or both.

Stored in RunStore:
```typescript
interface LoadRelatedRecordPendingData {
name: string; // technical relation name
displayName: string; // label shown in the UI
suggestedFields?: string[]; // fields suggested for display (set by executor)
selectedRecordId: Array<string|number>; // AI's pick; overridable by frontend
userConfirmed?: boolean; // set by frontend via PATCH
}
```

> `relatedCollectionName` is **not** stored in `pendingData` — the executor re-derives it from the `FieldSchema` at execution time using the (possibly overridden) relation `name`.

PATCH request body:
```typescript
{
userConfirmed: boolean;
name?: string; // override relation
displayName?: string; // override relation label
selectedRecordId?: Array<string|number>; // override selected record (min 1 element)
}
```

### Responses

| Status | Meaning |
|---|---|
| `204 No Content` | Pending data updated successfully |
| `400` | Invalid body — type mismatch, unknown fields, or empty `selectedRecordId` |
| `404` | Step not found, no `pendingData`, or step type does not support confirmation |

---

## Flow Summary

```
Orchestrator ──► GET pending?runId=X ──► Executor
executes step
┌───────────────┴───────────────┐
needs input done
│ │
status: awaiting-input POST /complete
│ (StepOutcome)
Executor writes pendingData
to RunStore (AI selection)
Frontend reads pendingData
via GET /runs/:runId
Frontend overrides + confirms
PATCH /runs/:runId/steps/:stepIndex/pending-data
{ userConfirmed: true/false } → 204
POST /runs/:runId/trigger
Executor resumes
(reads userConfirmed from pendingData)
```
9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"semantic-release-slack-bot": "^4.0.2",
"ts-jest": "^29.0.4",
"ts-node": "^10.9.1",
"typedoc": "^0.28.15",
"typedoc": "^0.28.18",
"typescript": "^5.6.3"
},
"scripts": {
Expand All @@ -53,15 +53,12 @@
"packages/*"
],
"resolutions": {
"tar": "^7.5.8",
"tar": ">=7.5.11",
"lerna/**/glob": ">=10.5.0",
"micromatch": "^4.0.8",
"semantic-release": "^25.0.0",
"qs": ">=6.14.1",
"lerna/js-yaml": "4.1.1",
"@lerna/create/js-yaml": "4.1.1",
"hono": ">=4.11.10",
"markdown-it": ">=14.1.1",
"@aws-sdk/xml-builder": ">=3.972.9"
"@lerna/create/js-yaml": "4.1.1"
}
}
2 changes: 1 addition & 1 deletion packages/_example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"pg": "^8.8.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.0",
"sequelize": "^6.37.5",
"sequelize": "^6.37.8",
"sqlite3": "^5.1.4",
"superagent": "^10.3.0",
"tedious": "^18.6.1"
Expand Down
52 changes: 52 additions & 0 deletions packages/agent-client/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,55 @@
## @forestadmin/agent-client [1.4.18](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.4.17...@forestadmin/agent-client@1.4.18) (2026-04-01)





### Dependencies

* **@forestadmin/forestadmin-client:** upgraded to 1.38.2

## @forestadmin/agent-client [1.4.17](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.4.16...@forestadmin/agent-client@1.4.17) (2026-03-31)





### Dependencies

* **@forestadmin/forestadmin-client:** upgraded to 1.38.1

## @forestadmin/agent-client [1.4.16](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.4.15...@forestadmin/agent-client@1.4.16) (2026-03-31)





### Dependencies

* **@forestadmin/datasource-toolkit:** upgraded to 1.53.1
* **@forestadmin/forestadmin-client:** upgraded to 1.38.0

## @forestadmin/agent-client [1.4.15](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.4.14...@forestadmin/agent-client@1.4.15) (2026-03-31)





### Dependencies

* **@forestadmin/forestadmin-client:** upgraded to 1.37.19

## @forestadmin/agent-client [1.4.14](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.4.13...@forestadmin/agent-client@1.4.14) (2026-03-18)





### Dependencies

* **@forestadmin/datasource-toolkit:** upgraded to 1.53.0
* **@forestadmin/forestadmin-client:** upgraded to 1.37.18

## @forestadmin/agent-client [1.4.13](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/agent-client@1.4.12...@forestadmin/agent-client@1.4.13) (2026-03-04)


Expand Down
Loading
Loading