mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-07 05:05:15 -05:00
Compare commits
10 Commits
fix/cmdk
...
fix/previe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37f4f7d09d | ||
|
|
fc7194b170 | ||
|
|
e13bbc1cdd | ||
|
|
12f36871d9 | ||
|
|
c89ae23edb | ||
|
|
8a10e9fc93 | ||
|
|
ed5ed97c07 | ||
|
|
65de27330e | ||
|
|
c0b22a6490 | ||
|
|
9dcf92bd14 |
@@ -320,6 +320,7 @@ Search for issues in Linear using full-text search
|
|||||||
| `teamId` | string | No | Filter by team ID |
|
| `teamId` | string | No | Filter by team ID |
|
||||||
| `includeArchived` | boolean | No | Include archived issues in search results |
|
| `includeArchived` | boolean | No | Include archived issues in search results |
|
||||||
| `first` | number | No | Number of results to return \(default: 50\) |
|
| `first` | number | No | Number of results to return \(default: 50\) |
|
||||||
|
| `after` | string | No | Cursor for pagination |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|
||||||
@@ -754,6 +755,10 @@ List all labels in Linear workspace or team
|
|||||||
| ↳ `name` | string | Label name |
|
| ↳ `name` | string | Label name |
|
||||||
| ↳ `color` | string | Label color \(hex\) |
|
| ↳ `color` | string | Label color \(hex\) |
|
||||||
| ↳ `description` | string | Label description |
|
| ↳ `description` | string | Label description |
|
||||||
|
| ↳ `isGroup` | boolean | Whether this label is a group |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team object |
|
| ↳ `team` | object | Team object |
|
||||||
| ↳ `id` | string | Team ID |
|
| ↳ `id` | string | Team ID |
|
||||||
| ↳ `name` | string | Team name |
|
| ↳ `name` | string | Team name |
|
||||||
@@ -780,6 +785,10 @@ Create a new label in Linear
|
|||||||
| ↳ `name` | string | Label name |
|
| ↳ `name` | string | Label name |
|
||||||
| ↳ `color` | string | Label color \(hex\) |
|
| ↳ `color` | string | Label color \(hex\) |
|
||||||
| ↳ `description` | string | Label description |
|
| ↳ `description` | string | Label description |
|
||||||
|
| ↳ `isGroup` | boolean | Whether this label is a group |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team object |
|
| ↳ `team` | object | Team object |
|
||||||
| ↳ `id` | string | Team ID |
|
| ↳ `id` | string | Team ID |
|
||||||
| ↳ `name` | string | Team name |
|
| ↳ `name` | string | Team name |
|
||||||
@@ -806,6 +815,10 @@ Update an existing label in Linear
|
|||||||
| ↳ `name` | string | Label name |
|
| ↳ `name` | string | Label name |
|
||||||
| ↳ `color` | string | Label color \(hex\) |
|
| ↳ `color` | string | Label color \(hex\) |
|
||||||
| ↳ `description` | string | Label description |
|
| ↳ `description` | string | Label description |
|
||||||
|
| ↳ `isGroup` | boolean | Whether this label is a group |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team object |
|
| ↳ `team` | object | Team object |
|
||||||
| ↳ `id` | string | Team ID |
|
| ↳ `id` | string | Team ID |
|
||||||
| ↳ `name` | string | Team name |
|
| ↳ `name` | string | Team name |
|
||||||
@@ -849,9 +862,13 @@ List all workflow states (statuses) in Linear
|
|||||||
| `states` | array | Array of workflow states |
|
| `states` | array | Array of workflow states |
|
||||||
| ↳ `id` | string | State ID |
|
| ↳ `id` | string | State ID |
|
||||||
| ↳ `name` | string | State name \(e.g., "Todo", "In Progress"\) |
|
| ↳ `name` | string | State name \(e.g., "Todo", "In Progress"\) |
|
||||||
| ↳ `type` | string | State type \(unstarted, started, completed, canceled\) |
|
| ↳ `description` | string | State description |
|
||||||
|
| ↳ `type` | string | State type \(triage, backlog, unstarted, started, completed, canceled\) |
|
||||||
| ↳ `color` | string | State color \(hex\) |
|
| ↳ `color` | string | State color \(hex\) |
|
||||||
| ↳ `position` | number | State position in workflow |
|
| ↳ `position` | number | State position in workflow |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team object |
|
| ↳ `team` | object | Team object |
|
||||||
| ↳ `id` | string | Team ID |
|
| ↳ `id` | string | Team ID |
|
||||||
| ↳ `name` | string | Team name |
|
| ↳ `name` | string | Team name |
|
||||||
@@ -877,11 +894,17 @@ Create a new workflow state (status) in Linear
|
|||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `state` | object | The created workflow state |
|
| `state` | object | The created workflow state |
|
||||||
| ↳ `id` | string | State ID |
|
| ↳ `id` | string | State ID |
|
||||||
| ↳ `name` | string | State name |
|
| ↳ `name` | string | State name \(e.g., "Todo", "In Progress"\) |
|
||||||
| ↳ `type` | string | State type |
|
| ↳ `description` | string | State description |
|
||||||
| ↳ `color` | string | State color |
|
| ↳ `type` | string | State type \(triage, backlog, unstarted, started, completed, canceled\) |
|
||||||
| ↳ `position` | number | State position |
|
| ↳ `color` | string | State color \(hex\) |
|
||||||
| ↳ `team` | object | Team this state belongs to |
|
| ↳ `position` | number | State position in workflow |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `team` | object | Team object |
|
||||||
|
| ↳ `id` | string | Team ID |
|
||||||
|
| ↳ `name` | string | Team name |
|
||||||
|
|
||||||
### `linear_update_workflow_state`
|
### `linear_update_workflow_state`
|
||||||
|
|
||||||
@@ -903,10 +926,17 @@ Update an existing workflow state in Linear
|
|||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `state` | object | The updated workflow state |
|
| `state` | object | The updated workflow state |
|
||||||
| ↳ `id` | string | State ID |
|
| ↳ `id` | string | State ID |
|
||||||
| ↳ `name` | string | State name |
|
| ↳ `name` | string | State name \(e.g., "Todo", "In Progress"\) |
|
||||||
| ↳ `type` | string | State type |
|
| ↳ `description` | string | State description |
|
||||||
| ↳ `color` | string | State color |
|
| ↳ `type` | string | State type \(triage, backlog, unstarted, started, completed, canceled\) |
|
||||||
| ↳ `position` | number | State position |
|
| ↳ `color` | string | State color \(hex\) |
|
||||||
|
| ↳ `position` | number | State position in workflow |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `team` | object | Team object |
|
||||||
|
| ↳ `id` | string | Team ID |
|
||||||
|
| ↳ `name` | string | Team name |
|
||||||
|
|
||||||
### `linear_list_cycles`
|
### `linear_list_cycles`
|
||||||
|
|
||||||
@@ -935,6 +965,7 @@ List cycles (sprints/iterations) in Linear
|
|||||||
| ↳ `endsAt` | string | End date \(ISO 8601\) |
|
| ↳ `endsAt` | string | End date \(ISO 8601\) |
|
||||||
| ↳ `completedAt` | string | Completion date \(ISO 8601\) |
|
| ↳ `completedAt` | string | Completion date \(ISO 8601\) |
|
||||||
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team object |
|
| ↳ `team` | object | Team object |
|
||||||
| ↳ `id` | string | Team ID |
|
| ↳ `id` | string | Team ID |
|
||||||
| ↳ `name` | string | Team name |
|
| ↳ `name` | string | Team name |
|
||||||
@@ -961,6 +992,7 @@ Get a single cycle by ID from Linear
|
|||||||
| ↳ `endsAt` | string | End date \(ISO 8601\) |
|
| ↳ `endsAt` | string | End date \(ISO 8601\) |
|
||||||
| ↳ `completedAt` | string | Completion date \(ISO 8601\) |
|
| ↳ `completedAt` | string | Completion date \(ISO 8601\) |
|
||||||
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team object |
|
| ↳ `team` | object | Team object |
|
||||||
| ↳ `id` | string | Team ID |
|
| ↳ `id` | string | Team ID |
|
||||||
| ↳ `name` | string | Team name |
|
| ↳ `name` | string | Team name |
|
||||||
@@ -986,9 +1018,14 @@ Create a new cycle (sprint/iteration) in Linear
|
|||||||
| ↳ `id` | string | Cycle ID |
|
| ↳ `id` | string | Cycle ID |
|
||||||
| ↳ `number` | number | Cycle number |
|
| ↳ `number` | number | Cycle number |
|
||||||
| ↳ `name` | string | Cycle name |
|
| ↳ `name` | string | Cycle name |
|
||||||
| ↳ `startsAt` | string | Start date |
|
| ↳ `startsAt` | string | Start date \(ISO 8601\) |
|
||||||
| ↳ `endsAt` | string | End date |
|
| ↳ `endsAt` | string | End date \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team this cycle belongs to |
|
| ↳ `completedAt` | string | Completion date \(ISO 8601\) |
|
||||||
|
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `team` | object | Team object |
|
||||||
|
| ↳ `id` | string | Team ID |
|
||||||
|
| ↳ `name` | string | Team name |
|
||||||
|
|
||||||
### `linear_get_active_cycle`
|
### `linear_get_active_cycle`
|
||||||
|
|
||||||
@@ -1008,10 +1045,14 @@ Get the currently active cycle for a team
|
|||||||
| ↳ `id` | string | Cycle ID |
|
| ↳ `id` | string | Cycle ID |
|
||||||
| ↳ `number` | number | Cycle number |
|
| ↳ `number` | number | Cycle number |
|
||||||
| ↳ `name` | string | Cycle name |
|
| ↳ `name` | string | Cycle name |
|
||||||
| ↳ `startsAt` | string | Start date |
|
| ↳ `startsAt` | string | Start date \(ISO 8601\) |
|
||||||
| ↳ `endsAt` | string | End date |
|
| ↳ `endsAt` | string | End date \(ISO 8601\) |
|
||||||
| ↳ `progress` | number | Progress percentage |
|
| ↳ `completedAt` | string | Completion date \(ISO 8601\) |
|
||||||
| ↳ `team` | object | Team this cycle belongs to |
|
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `team` | object | Team object |
|
||||||
|
| ↳ `id` | string | Team ID |
|
||||||
|
| ↳ `name` | string | Team name |
|
||||||
|
|
||||||
### `linear_create_attachment`
|
### `linear_create_attachment`
|
||||||
|
|
||||||
@@ -1334,8 +1375,12 @@ Create a new customer in Linear
|
|||||||
| ↳ `domains` | array | Associated domains |
|
| ↳ `domains` | array | Associated domains |
|
||||||
| ↳ `externalIds` | array | External IDs from other systems |
|
| ↳ `externalIds` | array | External IDs from other systems |
|
||||||
| ↳ `logoUrl` | string | Logo URL |
|
| ↳ `logoUrl` | string | Logo URL |
|
||||||
|
| ↳ `slugId` | string | Unique URL slug |
|
||||||
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
||||||
|
| ↳ `revenue` | number | Annual revenue |
|
||||||
|
| ↳ `size` | number | Organization size |
|
||||||
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_list_customers`
|
### `linear_list_customers`
|
||||||
@@ -1363,8 +1408,12 @@ List all customers in Linear
|
|||||||
| ↳ `domains` | array | Associated domains |
|
| ↳ `domains` | array | Associated domains |
|
||||||
| ↳ `externalIds` | array | External IDs from other systems |
|
| ↳ `externalIds` | array | External IDs from other systems |
|
||||||
| ↳ `logoUrl` | string | Logo URL |
|
| ↳ `logoUrl` | string | Logo URL |
|
||||||
|
| ↳ `slugId` | string | Unique URL slug |
|
||||||
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
||||||
|
| ↳ `revenue` | number | Annual revenue |
|
||||||
|
| ↳ `size` | number | Organization size |
|
||||||
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_create_customer_request`
|
### `linear_create_customer_request`
|
||||||
@@ -1480,8 +1529,12 @@ Get a single customer by ID in Linear
|
|||||||
| ↳ `domains` | array | Associated domains |
|
| ↳ `domains` | array | Associated domains |
|
||||||
| ↳ `externalIds` | array | External IDs from other systems |
|
| ↳ `externalIds` | array | External IDs from other systems |
|
||||||
| ↳ `logoUrl` | string | Logo URL |
|
| ↳ `logoUrl` | string | Logo URL |
|
||||||
|
| ↳ `slugId` | string | Unique URL slug |
|
||||||
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
||||||
|
| ↳ `revenue` | number | Annual revenue |
|
||||||
|
| ↳ `size` | number | Organization size |
|
||||||
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_update_customer`
|
### `linear_update_customer`
|
||||||
@@ -1513,8 +1566,12 @@ Update a customer in Linear
|
|||||||
| ↳ `domains` | array | Associated domains |
|
| ↳ `domains` | array | Associated domains |
|
||||||
| ↳ `externalIds` | array | External IDs from other systems |
|
| ↳ `externalIds` | array | External IDs from other systems |
|
||||||
| ↳ `logoUrl` | string | Logo URL |
|
| ↳ `logoUrl` | string | Logo URL |
|
||||||
|
| ↳ `slugId` | string | Unique URL slug |
|
||||||
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
| ↳ `approximateNeedCount` | number | Number of customer needs |
|
||||||
|
| ↳ `revenue` | number | Annual revenue |
|
||||||
|
| ↳ `size` | number | Organization size |
|
||||||
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_delete_customer`
|
### `linear_delete_customer`
|
||||||
@@ -1560,8 +1617,8 @@ Create a new customer status in Linear
|
|||||||
| --------- | ---- | -------- | ----------- |
|
| --------- | ---- | -------- | ----------- |
|
||||||
| `name` | string | Yes | Customer status name |
|
| `name` | string | Yes | Customer status name |
|
||||||
| `color` | string | Yes | Status color \(hex code\) |
|
| `color` | string | Yes | Status color \(hex code\) |
|
||||||
| `displayName` | string | No | Display name for the status |
|
|
||||||
| `description` | string | No | Status description |
|
| `description` | string | No | Status description |
|
||||||
|
| `displayName` | string | No | Display name for the status |
|
||||||
| `position` | number | No | Position in status list |
|
| `position` | number | No | Position in status list |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
@@ -1571,11 +1628,12 @@ Create a new customer status in Linear
|
|||||||
| `customerStatus` | object | The created customer status |
|
| `customerStatus` | object | The created customer status |
|
||||||
| ↳ `id` | string | Customer status ID |
|
| ↳ `id` | string | Customer status ID |
|
||||||
| ↳ `name` | string | Status name |
|
| ↳ `name` | string | Status name |
|
||||||
| ↳ `displayName` | string | Display name |
|
|
||||||
| ↳ `description` | string | Status description |
|
| ↳ `description` | string | Status description |
|
||||||
| ↳ `color` | string | Status color \(hex\) |
|
| ↳ `color` | string | Status color \(hex\) |
|
||||||
| ↳ `position` | number | Position in list |
|
| ↳ `position` | number | Position in list |
|
||||||
|
| ↳ `type` | string | Status type \(active, inactive\) |
|
||||||
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last updated timestamp \(ISO 8601\) |
|
||||||
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_update_customer_status`
|
### `linear_update_customer_status`
|
||||||
@@ -1589,8 +1647,8 @@ Update a customer status in Linear
|
|||||||
| `statusId` | string | Yes | Customer status ID to update |
|
| `statusId` | string | Yes | Customer status ID to update |
|
||||||
| `name` | string | No | Updated status name |
|
| `name` | string | No | Updated status name |
|
||||||
| `color` | string | No | Updated status color |
|
| `color` | string | No | Updated status color |
|
||||||
| `displayName` | string | No | Updated display name |
|
|
||||||
| `description` | string | No | Updated description |
|
| `description` | string | No | Updated description |
|
||||||
|
| `displayName` | string | No | Updated display name |
|
||||||
| `position` | number | No | Updated position |
|
| `position` | number | No | Updated position |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
@@ -1598,6 +1656,15 @@ Update a customer status in Linear
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `customerStatus` | object | The updated customer status |
|
| `customerStatus` | object | The updated customer status |
|
||||||
|
| ↳ `id` | string | Customer status ID |
|
||||||
|
| ↳ `name` | string | Status name |
|
||||||
|
| ↳ `description` | string | Status description |
|
||||||
|
| ↳ `color` | string | Status color \(hex\) |
|
||||||
|
| ↳ `position` | number | Position in list |
|
||||||
|
| ↳ `type` | string | Status type \(active, inactive\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last updated timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_delete_customer_status`
|
### `linear_delete_customer_status`
|
||||||
|
|
||||||
@@ -1623,19 +1690,25 @@ List all customer statuses in Linear
|
|||||||
|
|
||||||
| Parameter | Type | Required | Description |
|
| Parameter | Type | Required | Description |
|
||||||
| --------- | ---- | -------- | ----------- |
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `first` | number | No | Number of statuses to return \(default: 50\) |
|
||||||
|
| `after` | string | No | Cursor for pagination |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
|
| `pageInfo` | object | Pagination information |
|
||||||
|
| ↳ `hasNextPage` | boolean | Whether there are more results |
|
||||||
|
| ↳ `endCursor` | string | Cursor for the next page |
|
||||||
| `customerStatuses` | array | List of customer statuses |
|
| `customerStatuses` | array | List of customer statuses |
|
||||||
| ↳ `id` | string | Customer status ID |
|
| ↳ `id` | string | Customer status ID |
|
||||||
| ↳ `name` | string | Status name |
|
| ↳ `name` | string | Status name |
|
||||||
| ↳ `displayName` | string | Display name |
|
|
||||||
| ↳ `description` | string | Status description |
|
| ↳ `description` | string | Status description |
|
||||||
| ↳ `color` | string | Status color \(hex\) |
|
| ↳ `color` | string | Status color \(hex\) |
|
||||||
| ↳ `position` | number | Position in list |
|
| ↳ `position` | number | Position in list |
|
||||||
|
| ↳ `type` | string | Status type \(active, inactive\) |
|
||||||
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last updated timestamp \(ISO 8601\) |
|
||||||
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_create_customer_tier`
|
### `linear_create_customer_tier`
|
||||||
@@ -1711,11 +1784,16 @@ List all customer tiers in Linear
|
|||||||
|
|
||||||
| Parameter | Type | Required | Description |
|
| Parameter | Type | Required | Description |
|
||||||
| --------- | ---- | -------- | ----------- |
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `first` | number | No | Number of tiers to return \(default: 50\) |
|
||||||
|
| `after` | string | No | Cursor for pagination |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
|
| `pageInfo` | object | Pagination information |
|
||||||
|
| ↳ `hasNextPage` | boolean | Whether there are more results |
|
||||||
|
| ↳ `endCursor` | string | Cursor for the next page |
|
||||||
| `customerTiers` | array | List of customer tiers |
|
| `customerTiers` | array | List of customer tiers |
|
||||||
| ↳ `id` | string | Customer tier ID |
|
| ↳ `id` | string | Customer tier ID |
|
||||||
| ↳ `name` | string | Tier name |
|
| ↳ `name` | string | Tier name |
|
||||||
@@ -1761,6 +1839,14 @@ Create a new project label in Linear
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `projectLabel` | object | The created project label |
|
| `projectLabel` | object | The created project label |
|
||||||
|
| ↳ `id` | string | Project label ID |
|
||||||
|
| ↳ `name` | string | Label name |
|
||||||
|
| ↳ `description` | string | Label description |
|
||||||
|
| ↳ `color` | string | Label color \(hex\) |
|
||||||
|
| ↳ `isGroup` | boolean | Whether this label is a group |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_update_project_label`
|
### `linear_update_project_label`
|
||||||
|
|
||||||
@@ -1780,6 +1866,14 @@ Update a project label in Linear
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `projectLabel` | object | The updated project label |
|
| `projectLabel` | object | The updated project label |
|
||||||
|
| ↳ `id` | string | Project label ID |
|
||||||
|
| ↳ `name` | string | Label name |
|
||||||
|
| ↳ `description` | string | Label description |
|
||||||
|
| ↳ `color` | string | Label color \(hex\) |
|
||||||
|
| ↳ `isGroup` | boolean | Whether this label is a group |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_delete_project_label`
|
### `linear_delete_project_label`
|
||||||
|
|
||||||
@@ -1806,12 +1900,25 @@ List all project labels in Linear
|
|||||||
| Parameter | Type | Required | Description |
|
| Parameter | Type | Required | Description |
|
||||||
| --------- | ---- | -------- | ----------- |
|
| --------- | ---- | -------- | ----------- |
|
||||||
| `projectId` | string | No | Optional project ID to filter labels for a specific project |
|
| `projectId` | string | No | Optional project ID to filter labels for a specific project |
|
||||||
|
| `first` | number | No | Number of labels to return \(default: 50\) |
|
||||||
|
| `after` | string | No | Cursor for pagination |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
|
| `pageInfo` | object | Pagination information |
|
||||||
|
| ↳ `hasNextPage` | boolean | Whether there are more results |
|
||||||
|
| ↳ `endCursor` | string | Cursor for the next page |
|
||||||
| `projectLabels` | array | List of project labels |
|
| `projectLabels` | array | List of project labels |
|
||||||
|
| ↳ `id` | string | Project label ID |
|
||||||
|
| ↳ `name` | string | Label name |
|
||||||
|
| ↳ `description` | string | Label description |
|
||||||
|
| ↳ `color` | string | Label color \(hex\) |
|
||||||
|
| ↳ `isGroup` | boolean | Whether this label is a group |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last update timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_add_label_to_project`
|
### `linear_add_label_to_project`
|
||||||
|
|
||||||
@@ -1867,6 +1974,16 @@ Create a new project milestone in Linear
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `projectMilestone` | object | The created project milestone |
|
| `projectMilestone` | object | The created project milestone |
|
||||||
|
| ↳ `id` | string | Project milestone ID |
|
||||||
|
| ↳ `name` | string | Milestone name |
|
||||||
|
| ↳ `description` | string | Milestone description |
|
||||||
|
| ↳ `projectId` | string | Project ID |
|
||||||
|
| ↳ `targetDate` | string | Target date \(YYYY-MM-DD\) |
|
||||||
|
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
||||||
|
| ↳ `sortOrder` | number | Sort order within the project |
|
||||||
|
| ↳ `status` | string | Milestone status \(done, next, overdue, unstarted\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_update_project_milestone`
|
### `linear_update_project_milestone`
|
||||||
|
|
||||||
@@ -1886,6 +2003,16 @@ Update a project milestone in Linear
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `projectMilestone` | object | The updated project milestone |
|
| `projectMilestone` | object | The updated project milestone |
|
||||||
|
| ↳ `id` | string | Project milestone ID |
|
||||||
|
| ↳ `name` | string | Milestone name |
|
||||||
|
| ↳ `description` | string | Milestone description |
|
||||||
|
| ↳ `projectId` | string | Project ID |
|
||||||
|
| ↳ `targetDate` | string | Target date \(YYYY-MM-DD\) |
|
||||||
|
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
||||||
|
| ↳ `sortOrder` | number | Sort order within the project |
|
||||||
|
| ↳ `status` | string | Milestone status \(done, next, overdue, unstarted\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_delete_project_milestone`
|
### `linear_delete_project_milestone`
|
||||||
|
|
||||||
@@ -1912,12 +2039,27 @@ List all milestones for a project in Linear
|
|||||||
| Parameter | Type | Required | Description |
|
| Parameter | Type | Required | Description |
|
||||||
| --------- | ---- | -------- | ----------- |
|
| --------- | ---- | -------- | ----------- |
|
||||||
| `projectId` | string | Yes | Project ID to list milestones for |
|
| `projectId` | string | Yes | Project ID to list milestones for |
|
||||||
|
| `first` | number | No | Number of milestones to return \(default: 50\) |
|
||||||
|
| `after` | string | No | Cursor for pagination |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
|
| `pageInfo` | object | Pagination information |
|
||||||
|
| ↳ `hasNextPage` | boolean | Whether there are more results |
|
||||||
|
| ↳ `endCursor` | string | Cursor for the next page |
|
||||||
| `projectMilestones` | array | List of project milestones |
|
| `projectMilestones` | array | List of project milestones |
|
||||||
|
| ↳ `id` | string | Project milestone ID |
|
||||||
|
| ↳ `name` | string | Milestone name |
|
||||||
|
| ↳ `description` | string | Milestone description |
|
||||||
|
| ↳ `projectId` | string | Project ID |
|
||||||
|
| ↳ `targetDate` | string | Target date \(YYYY-MM-DD\) |
|
||||||
|
| ↳ `progress` | number | Progress percentage \(0-1\) |
|
||||||
|
| ↳ `sortOrder` | number | Sort order within the project |
|
||||||
|
| ↳ `status` | string | Milestone status \(done, next, overdue, unstarted\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_create_project_status`
|
### `linear_create_project_status`
|
||||||
|
|
||||||
@@ -1939,6 +2081,16 @@ Create a new project status in Linear
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `projectStatus` | object | The created project status |
|
| `projectStatus` | object | The created project status |
|
||||||
|
| ↳ `id` | string | Project status ID |
|
||||||
|
| ↳ `name` | string | Status name |
|
||||||
|
| ↳ `description` | string | Status description |
|
||||||
|
| ↳ `color` | string | Status color \(hex\) |
|
||||||
|
| ↳ `indefinite` | boolean | Whether this status is indefinite |
|
||||||
|
| ↳ `position` | number | Position in list |
|
||||||
|
| ↳ `type` | string | Status type \(backlog, planned, started, paused, completed, canceled\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last updated timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_update_project_status`
|
### `linear_update_project_status`
|
||||||
|
|
||||||
@@ -1960,6 +2112,16 @@ Update a project status in Linear
|
|||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
| `projectStatus` | object | The updated project status |
|
| `projectStatus` | object | The updated project status |
|
||||||
|
| ↳ `id` | string | Project status ID |
|
||||||
|
| ↳ `name` | string | Status name |
|
||||||
|
| ↳ `description` | string | Status description |
|
||||||
|
| ↳ `color` | string | Status color \(hex\) |
|
||||||
|
| ↳ `indefinite` | boolean | Whether this status is indefinite |
|
||||||
|
| ↳ `position` | number | Position in list |
|
||||||
|
| ↳ `type` | string | Status type \(backlog, planned, started, paused, completed, canceled\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last updated timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
### `linear_delete_project_status`
|
### `linear_delete_project_status`
|
||||||
|
|
||||||
@@ -1985,11 +2147,26 @@ List all project statuses in Linear
|
|||||||
|
|
||||||
| Parameter | Type | Required | Description |
|
| Parameter | Type | Required | Description |
|
||||||
| --------- | ---- | -------- | ----------- |
|
| --------- | ---- | -------- | ----------- |
|
||||||
|
| `first` | number | No | Number of statuses to return \(default: 50\) |
|
||||||
|
| `after` | string | No | Cursor for pagination |
|
||||||
|
|
||||||
#### Output
|
#### Output
|
||||||
|
|
||||||
| Parameter | Type | Description |
|
| Parameter | Type | Description |
|
||||||
| --------- | ---- | ----------- |
|
| --------- | ---- | ----------- |
|
||||||
|
| `pageInfo` | object | Pagination information |
|
||||||
|
| ↳ `hasNextPage` | boolean | Whether there are more results |
|
||||||
|
| ↳ `endCursor` | string | Cursor for the next page |
|
||||||
| `projectStatuses` | array | List of project statuses |
|
| `projectStatuses` | array | List of project statuses |
|
||||||
|
| ↳ `id` | string | Project status ID |
|
||||||
|
| ↳ `name` | string | Status name |
|
||||||
|
| ↳ `description` | string | Status description |
|
||||||
|
| ↳ `color` | string | Status color \(hex\) |
|
||||||
|
| ↳ `indefinite` | boolean | Whether this status is indefinite |
|
||||||
|
| ↳ `position` | number | Position in list |
|
||||||
|
| ↳ `type` | string | Status type \(backlog, planned, started, paused, completed, canceled\) |
|
||||||
|
| ↳ `createdAt` | string | Creation timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `updatedAt` | string | Last updated timestamp \(ISO 8601\) |
|
||||||
|
| ↳ `archivedAt` | string | Archive timestamp \(ISO 8601\) |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ interface CredentialSelectorProps {
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
isPreview?: boolean
|
isPreview?: boolean
|
||||||
previewValue?: any | null
|
previewValue?: any | null
|
||||||
|
previewContextValues?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function CredentialSelector({
|
export function CredentialSelector({
|
||||||
@@ -43,6 +44,7 @@ export function CredentialSelector({
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
isPreview = false,
|
isPreview = false,
|
||||||
previewValue,
|
previewValue,
|
||||||
|
previewContextValues,
|
||||||
}: CredentialSelectorProps) {
|
}: CredentialSelectorProps) {
|
||||||
const [showOAuthModal, setShowOAuthModal] = useState(false)
|
const [showOAuthModal, setShowOAuthModal] = useState(false)
|
||||||
const [editingValue, setEditingValue] = useState('')
|
const [editingValue, setEditingValue] = useState('')
|
||||||
@@ -67,7 +69,11 @@ export function CredentialSelector({
|
|||||||
canUseCredentialSets
|
canUseCredentialSets
|
||||||
)
|
)
|
||||||
|
|
||||||
const { depsSatisfied, dependsOn } = useDependsOnGate(blockId, subBlock, { disabled, isPreview })
|
const { depsSatisfied, dependsOn } = useDependsOnGate(blockId, subBlock, {
|
||||||
|
disabled,
|
||||||
|
isPreview,
|
||||||
|
previewContextValues,
|
||||||
|
})
|
||||||
const hasDependencies = dependsOn.length > 0
|
const hasDependencies = dependsOn.length > 0
|
||||||
|
|
||||||
const effectiveDisabled = disabled || (hasDependencies && !depsSatisfied)
|
const effectiveDisabled = disabled || (hasDependencies && !depsSatisfied)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { Tooltip } from '@/components/emcn'
|
|||||||
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
||||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import type { SelectorContext } from '@/hooks/selectors/types'
|
import type { SelectorContext } from '@/hooks/selectors/types'
|
||||||
|
|
||||||
@@ -33,7 +34,9 @@ export function DocumentSelector({
|
|||||||
previewContextValues,
|
previewContextValues,
|
||||||
})
|
})
|
||||||
const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId')
|
const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId')
|
||||||
const knowledgeBaseIdValue = previewContextValues?.knowledgeBaseId ?? knowledgeBaseIdFromStore
|
const knowledgeBaseIdValue = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.knowledgeBaseId)
|
||||||
|
: knowledgeBaseIdFromStore
|
||||||
const normalizedKnowledgeBaseId =
|
const normalizedKnowledgeBaseId =
|
||||||
typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0
|
typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0
|
||||||
? knowledgeBaseIdValue
|
? knowledgeBaseIdValue
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/
|
|||||||
import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
|
import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
|
||||||
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
|
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
|
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions'
|
import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions'
|
||||||
@@ -77,7 +78,9 @@ export function DocumentTagEntry({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId')
|
const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId')
|
||||||
const knowledgeBaseIdValue = previewContextValues?.knowledgeBaseId ?? knowledgeBaseIdFromStore
|
const knowledgeBaseIdValue = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.knowledgeBaseId)
|
||||||
|
: knowledgeBaseIdFromStore
|
||||||
const knowledgeBaseId =
|
const knowledgeBaseId =
|
||||||
typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0
|
typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0
|
||||||
? knowledgeBaseIdValue
|
? knowledgeBaseIdValue
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c
|
|||||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import { getBlock } from '@/blocks/registry'
|
import { getBlock } from '@/blocks/registry'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { isDependency } from '@/blocks/utils'
|
import { isDependency } from '@/blocks/utils'
|
||||||
@@ -62,42 +63,56 @@ export function FileSelectorInput({
|
|||||||
|
|
||||||
const [domainValueFromStore] = useSubBlockValue(blockId, 'domain')
|
const [domainValueFromStore] = useSubBlockValue(blockId, 'domain')
|
||||||
|
|
||||||
const connectedCredential = previewContextValues?.credential ?? blockValues.credential
|
const connectedCredential = previewContextValues
|
||||||
const domainValue = previewContextValues?.domain ?? domainValueFromStore
|
? resolvePreviewContextValue(previewContextValues.credential)
|
||||||
|
: blockValues.credential
|
||||||
|
const domainValue = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.domain)
|
||||||
|
: domainValueFromStore
|
||||||
|
|
||||||
const teamIdValue = useMemo(
|
const teamIdValue = useMemo(
|
||||||
() =>
|
() =>
|
||||||
previewContextValues?.teamId ??
|
previewContextValues
|
||||||
resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides),
|
? resolvePreviewContextValue(previewContextValues.teamId)
|
||||||
[previewContextValues?.teamId, blockValues, canonicalIndex, canonicalModeOverrides]
|
: resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides),
|
||||||
|
[previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides]
|
||||||
)
|
)
|
||||||
|
|
||||||
const siteIdValue = useMemo(
|
const siteIdValue = useMemo(
|
||||||
() =>
|
() =>
|
||||||
previewContextValues?.siteId ??
|
previewContextValues
|
||||||
resolveDependencyValue('siteId', blockValues, canonicalIndex, canonicalModeOverrides),
|
? resolvePreviewContextValue(previewContextValues.siteId)
|
||||||
[previewContextValues?.siteId, blockValues, canonicalIndex, canonicalModeOverrides]
|
: resolveDependencyValue('siteId', blockValues, canonicalIndex, canonicalModeOverrides),
|
||||||
|
[previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides]
|
||||||
)
|
)
|
||||||
|
|
||||||
const collectionIdValue = useMemo(
|
const collectionIdValue = useMemo(
|
||||||
() =>
|
() =>
|
||||||
previewContextValues?.collectionId ??
|
previewContextValues
|
||||||
resolveDependencyValue('collectionId', blockValues, canonicalIndex, canonicalModeOverrides),
|
? resolvePreviewContextValue(previewContextValues.collectionId)
|
||||||
[previewContextValues?.collectionId, blockValues, canonicalIndex, canonicalModeOverrides]
|
: resolveDependencyValue(
|
||||||
|
'collectionId',
|
||||||
|
blockValues,
|
||||||
|
canonicalIndex,
|
||||||
|
canonicalModeOverrides
|
||||||
|
),
|
||||||
|
[previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides]
|
||||||
)
|
)
|
||||||
|
|
||||||
const projectIdValue = useMemo(
|
const projectIdValue = useMemo(
|
||||||
() =>
|
() =>
|
||||||
previewContextValues?.projectId ??
|
previewContextValues
|
||||||
resolveDependencyValue('projectId', blockValues, canonicalIndex, canonicalModeOverrides),
|
? resolvePreviewContextValue(previewContextValues.projectId)
|
||||||
[previewContextValues?.projectId, blockValues, canonicalIndex, canonicalModeOverrides]
|
: resolveDependencyValue('projectId', blockValues, canonicalIndex, canonicalModeOverrides),
|
||||||
|
[previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides]
|
||||||
)
|
)
|
||||||
|
|
||||||
const planIdValue = useMemo(
|
const planIdValue = useMemo(
|
||||||
() =>
|
() =>
|
||||||
previewContextValues?.planId ??
|
previewContextValues
|
||||||
resolveDependencyValue('planId', blockValues, canonicalIndex, canonicalModeOverrides),
|
? resolvePreviewContextValue(previewContextValues.planId)
|
||||||
[previewContextValues?.planId, blockValues, canonicalIndex, canonicalModeOverrides]
|
: resolveDependencyValue('planId', blockValues, canonicalIndex, canonicalModeOverrides),
|
||||||
|
[previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides]
|
||||||
)
|
)
|
||||||
|
|
||||||
const normalizedCredentialId =
|
const normalizedCredentialId =
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c
|
|||||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution'
|
import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution'
|
||||||
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
|
import { useCollaborativeWorkflow } from '@/hooks/use-collaborative-workflow'
|
||||||
@@ -17,6 +18,7 @@ interface FolderSelectorInputProps {
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
isPreview?: boolean
|
isPreview?: boolean
|
||||||
previewValue?: any | null
|
previewValue?: any | null
|
||||||
|
previewContextValues?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FolderSelectorInput({
|
export function FolderSelectorInput({
|
||||||
@@ -25,9 +27,13 @@ export function FolderSelectorInput({
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
isPreview = false,
|
isPreview = false,
|
||||||
previewValue,
|
previewValue,
|
||||||
|
previewContextValues,
|
||||||
}: FolderSelectorInputProps) {
|
}: FolderSelectorInputProps) {
|
||||||
const [storeValue] = useSubBlockValue(blockId, subBlock.id)
|
const [storeValue] = useSubBlockValue(blockId, subBlock.id)
|
||||||
const [connectedCredential] = useSubBlockValue(blockId, 'credential')
|
const [credentialFromStore] = useSubBlockValue(blockId, 'credential')
|
||||||
|
const connectedCredential = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.credential)
|
||||||
|
: credentialFromStore
|
||||||
const { collaborativeSetSubblockValue } = useCollaborativeWorkflow()
|
const { collaborativeSetSubblockValue } = useCollaborativeWorkflow()
|
||||||
const { activeWorkflowId } = useWorkflowRegistry()
|
const { activeWorkflowId } = useWorkflowRegistry()
|
||||||
const [selectedFolderId, setSelectedFolderId] = useState<string>('')
|
const [selectedFolderId, setSelectedFolderId] = useState<string>('')
|
||||||
@@ -47,7 +53,11 @@ export function FolderSelectorInput({
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Central dependsOn gating
|
// Central dependsOn gating
|
||||||
const { finalDisabled } = useDependsOnGate(blockId, subBlock, { disabled, isPreview })
|
const { finalDisabled } = useDependsOnGate(blockId, subBlock, {
|
||||||
|
disabled,
|
||||||
|
isPreview,
|
||||||
|
previewContextValues,
|
||||||
|
})
|
||||||
|
|
||||||
// Get the current value from the store or prop value if in preview mode
|
// Get the current value from the store or prop value if in preview mode
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/
|
|||||||
import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
|
import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
|
||||||
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
|
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
|
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
|
||||||
import { useWorkflowState } from '@/hooks/queries/workflows'
|
import { useWorkflowState } from '@/hooks/queries/workflows'
|
||||||
|
|
||||||
@@ -37,6 +38,8 @@ interface InputMappingProps {
|
|||||||
isPreview?: boolean
|
isPreview?: boolean
|
||||||
previewValue?: Record<string, unknown>
|
previewValue?: Record<string, unknown>
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
|
/** Sub-block values from the preview context for resolving sibling sub-block values */
|
||||||
|
previewContextValues?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,9 +53,13 @@ export function InputMapping({
|
|||||||
isPreview = false,
|
isPreview = false,
|
||||||
previewValue,
|
previewValue,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
|
previewContextValues,
|
||||||
}: InputMappingProps) {
|
}: InputMappingProps) {
|
||||||
const [mapping, setMapping] = useSubBlockValue(blockId, subBlockId)
|
const [mapping, setMapping] = useSubBlockValue(blockId, subBlockId)
|
||||||
const [selectedWorkflowId] = useSubBlockValue(blockId, 'workflowId')
|
const [storeWorkflowId] = useSubBlockValue(blockId, 'workflowId')
|
||||||
|
const selectedWorkflowId = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.workflowId)
|
||||||
|
: storeWorkflowId
|
||||||
|
|
||||||
const inputController = useSubBlockInput({
|
const inputController = useSubBlockInput({
|
||||||
blockId,
|
blockId,
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { type FilterFieldType, getOperatorsForFieldType } from '@/lib/knowledge/
|
|||||||
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
|
import { formatDisplayText } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/formatted-text'
|
||||||
import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
|
import { TagDropdown } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/tag-dropdown/tag-dropdown'
|
||||||
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
|
import { useSubBlockInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-input'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
|
import { useAccessibleReferencePrefixes } from '@/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-accessible-reference-prefixes'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions'
|
import { useKnowledgeBaseTagDefinitions } from '@/hooks/kb/use-knowledge-base-tag-definitions'
|
||||||
@@ -69,7 +70,9 @@ export function KnowledgeTagFilters({
|
|||||||
const overlayRefs = useRef<Record<string, HTMLDivElement>>({})
|
const overlayRefs = useRef<Record<string, HTMLDivElement>>({})
|
||||||
|
|
||||||
const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId')
|
const [knowledgeBaseIdFromStore] = useSubBlockValue(blockId, 'knowledgeBaseId')
|
||||||
const knowledgeBaseIdValue = previewContextValues?.knowledgeBaseId ?? knowledgeBaseIdFromStore
|
const knowledgeBaseIdValue = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.knowledgeBaseId)
|
||||||
|
: knowledgeBaseIdFromStore
|
||||||
const knowledgeBaseId =
|
const knowledgeBaseId =
|
||||||
typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0
|
typeof knowledgeBaseIdValue === 'string' && knowledgeBaseIdValue.trim().length > 0
|
||||||
? knowledgeBaseIdValue
|
? knowledgeBaseIdValue
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { cn } from '@/lib/core/utils/cn'
|
|||||||
import { LongInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/long-input/long-input'
|
import { LongInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/long-input/long-input'
|
||||||
import { ShortInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/short-input/short-input'
|
import { ShortInput } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/short-input/short-input'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { useMcpTools } from '@/hooks/mcp/use-mcp-tools'
|
import { useMcpTools } from '@/hooks/mcp/use-mcp-tools'
|
||||||
import { formatParameterLabel } from '@/tools/params'
|
import { formatParameterLabel } from '@/tools/params'
|
||||||
@@ -18,6 +19,7 @@ interface McpDynamicArgsProps {
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
isPreview?: boolean
|
isPreview?: boolean
|
||||||
previewValue?: any
|
previewValue?: any
|
||||||
|
previewContextValues?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,12 +49,19 @@ export function McpDynamicArgs({
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
isPreview = false,
|
isPreview = false,
|
||||||
previewValue,
|
previewValue,
|
||||||
|
previewContextValues,
|
||||||
}: McpDynamicArgsProps) {
|
}: McpDynamicArgsProps) {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const workspaceId = params.workspaceId as string
|
const workspaceId = params.workspaceId as string
|
||||||
const { mcpTools, isLoading } = useMcpTools(workspaceId)
|
const { mcpTools, isLoading } = useMcpTools(workspaceId)
|
||||||
const [selectedTool] = useSubBlockValue(blockId, 'tool')
|
const [toolFromStore] = useSubBlockValue(blockId, 'tool')
|
||||||
const [cachedSchema] = useSubBlockValue(blockId, '_toolSchema')
|
const selectedTool = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.tool)
|
||||||
|
: toolFromStore
|
||||||
|
const [schemaFromStore] = useSubBlockValue(blockId, '_toolSchema')
|
||||||
|
const cachedSchema = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues._toolSchema)
|
||||||
|
: schemaFromStore
|
||||||
const [toolArgs, setToolArgs] = useSubBlockValue(blockId, subBlockId)
|
const [toolArgs, setToolArgs] = useSubBlockValue(blockId, subBlockId)
|
||||||
|
|
||||||
const selectedToolConfig = mcpTools.find((tool) => tool.id === selectedTool)
|
const selectedToolConfig = mcpTools.find((tool) => tool.id === selectedTool)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useEffect, useMemo, useState } from 'react'
|
|||||||
import { useParams } from 'next/navigation'
|
import { useParams } from 'next/navigation'
|
||||||
import { Combobox } from '@/components/emcn/components'
|
import { Combobox } from '@/components/emcn/components'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { useMcpTools } from '@/hooks/mcp/use-mcp-tools'
|
import { useMcpTools } from '@/hooks/mcp/use-mcp-tools'
|
||||||
|
|
||||||
@@ -13,6 +14,7 @@ interface McpToolSelectorProps {
|
|||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
isPreview?: boolean
|
isPreview?: boolean
|
||||||
previewValue?: string | null
|
previewValue?: string | null
|
||||||
|
previewContextValues?: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function McpToolSelector({
|
export function McpToolSelector({
|
||||||
@@ -21,6 +23,7 @@ export function McpToolSelector({
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
isPreview = false,
|
isPreview = false,
|
||||||
previewValue,
|
previewValue,
|
||||||
|
previewContextValues,
|
||||||
}: McpToolSelectorProps) {
|
}: McpToolSelectorProps) {
|
||||||
const params = useParams()
|
const params = useParams()
|
||||||
const workspaceId = params.workspaceId as string
|
const workspaceId = params.workspaceId as string
|
||||||
@@ -31,7 +34,10 @@ export function McpToolSelector({
|
|||||||
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id)
|
const [storeValue, setStoreValue] = useSubBlockValue(blockId, subBlock.id)
|
||||||
const [, setSchemaCache] = useSubBlockValue(blockId, '_toolSchema')
|
const [, setSchemaCache] = useSubBlockValue(blockId, '_toolSchema')
|
||||||
|
|
||||||
const [serverValue] = useSubBlockValue(blockId, 'server')
|
const [serverFromStore] = useSubBlockValue(blockId, 'server')
|
||||||
|
const serverValue = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.server)
|
||||||
|
: serverFromStore
|
||||||
|
|
||||||
const label = subBlock.placeholder || 'Select tool'
|
const label = subBlock.placeholder || 'Select tool'
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c
|
|||||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import { getBlock } from '@/blocks/registry'
|
import { getBlock } from '@/blocks/registry'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution'
|
import { resolveSelectorForSubBlock } from '@/hooks/selectors/resolution'
|
||||||
@@ -55,14 +56,19 @@ export function ProjectSelectorInput({
|
|||||||
return (workflowValues as Record<string, Record<string, unknown>>)[blockId] || {}
|
return (workflowValues as Record<string, Record<string, unknown>>)[blockId] || {}
|
||||||
})
|
})
|
||||||
|
|
||||||
const connectedCredential = previewContextValues?.credential ?? blockValues.credential
|
const connectedCredential = previewContextValues
|
||||||
const jiraDomain = previewContextValues?.domain ?? jiraDomainFromStore
|
? resolvePreviewContextValue(previewContextValues.credential)
|
||||||
|
: blockValues.credential
|
||||||
|
const jiraDomain = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.domain)
|
||||||
|
: jiraDomainFromStore
|
||||||
|
|
||||||
const linearTeamId = useMemo(
|
const linearTeamId = useMemo(
|
||||||
() =>
|
() =>
|
||||||
previewContextValues?.teamId ??
|
previewContextValues
|
||||||
resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides),
|
? resolvePreviewContextValue(previewContextValues.teamId)
|
||||||
[previewContextValues?.teamId, blockValues, canonicalIndex, canonicalModeOverrides]
|
: resolveDependencyValue('teamId', blockValues, canonicalIndex, canonicalModeOverrides),
|
||||||
|
[previewContextValues, blockValues, canonicalIndex, canonicalModeOverrides]
|
||||||
)
|
)
|
||||||
|
|
||||||
const serviceId = subBlock.serviceId || ''
|
const serviceId = subBlock.serviceId || ''
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { buildCanonicalIndex, resolveDependencyValue } from '@/lib/workflows/sub
|
|||||||
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/components/selector-combobox/selector-combobox'
|
||||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import { getBlock } from '@/blocks/registry'
|
import { getBlock } from '@/blocks/registry'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import { resolveSelectorForSubBlock, type SelectorResolution } from '@/hooks/selectors/resolution'
|
import { resolveSelectorForSubBlock, type SelectorResolution } from '@/hooks/selectors/resolution'
|
||||||
@@ -66,9 +67,12 @@ export function SheetSelectorInput({
|
|||||||
[blockValues, canonicalIndex, canonicalModeOverrides]
|
[blockValues, canonicalIndex, canonicalModeOverrides]
|
||||||
)
|
)
|
||||||
|
|
||||||
const connectedCredential = previewContextValues?.credential ?? connectedCredentialFromStore
|
const connectedCredential = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.credential)
|
||||||
|
: connectedCredentialFromStore
|
||||||
const spreadsheetId = previewContextValues
|
const spreadsheetId = previewContextValues
|
||||||
? (previewContextValues.spreadsheetId ?? previewContextValues.manualSpreadsheetId)
|
? (resolvePreviewContextValue(previewContextValues.spreadsheetId) ??
|
||||||
|
resolvePreviewContextValue(previewContextValues.manualSpreadsheetId))
|
||||||
: spreadsheetIdFromStore
|
: spreadsheetIdFromStore
|
||||||
|
|
||||||
const normalizedCredentialId =
|
const normalizedCredentialId =
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { SelectorCombobox } from '@/app/workspace/[workspaceId]/w/[workflowId]/c
|
|||||||
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
import { useDependsOnGate } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-depends-on-gate'
|
||||||
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
import { useForeignCredential } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-foreign-credential'
|
||||||
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
import { useSubBlockValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/hooks/use-sub-block-value'
|
||||||
|
import { resolvePreviewContextValue } from '@/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/components/sub-block/utils'
|
||||||
import type { SubBlockConfig } from '@/blocks/types'
|
import type { SubBlockConfig } from '@/blocks/types'
|
||||||
import type { SelectorContext, SelectorKey } from '@/hooks/selectors/types'
|
import type { SelectorContext, SelectorKey } from '@/hooks/selectors/types'
|
||||||
|
|
||||||
@@ -58,9 +59,15 @@ export function SlackSelectorInput({
|
|||||||
const [botToken] = useSubBlockValue(blockId, 'botToken')
|
const [botToken] = useSubBlockValue(blockId, 'botToken')
|
||||||
const [connectedCredential] = useSubBlockValue(blockId, 'credential')
|
const [connectedCredential] = useSubBlockValue(blockId, 'credential')
|
||||||
|
|
||||||
const effectiveAuthMethod = previewContextValues?.authMethod ?? authMethod
|
const effectiveAuthMethod = previewContextValues
|
||||||
const effectiveBotToken = previewContextValues?.botToken ?? botToken
|
? resolvePreviewContextValue(previewContextValues.authMethod)
|
||||||
const effectiveCredential = previewContextValues?.credential ?? connectedCredential
|
: authMethod
|
||||||
|
const effectiveBotToken = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.botToken)
|
||||||
|
: botToken
|
||||||
|
const effectiveCredential = previewContextValues
|
||||||
|
? resolvePreviewContextValue(previewContextValues.credential)
|
||||||
|
: connectedCredential
|
||||||
const [_selectedValue, setSelectedValue] = useState<string | null>(null)
|
const [_selectedValue, setSelectedValue] = useState<string | null>(null)
|
||||||
|
|
||||||
const serviceId = subBlock.serviceId || ''
|
const serviceId = subBlock.serviceId || ''
|
||||||
|
|||||||
@@ -332,6 +332,7 @@ function FolderSelectorSyncWrapper({
|
|||||||
dependsOn: uiComponent.dependsOn,
|
dependsOn: uiComponent.dependsOn,
|
||||||
}}
|
}}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
previewContextValues={previewContextValues}
|
||||||
/>
|
/>
|
||||||
</GenericSyncWrapper>
|
</GenericSyncWrapper>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -785,6 +785,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue}
|
previewValue={previewValue}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -820,6 +821,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue}
|
previewValue={previewValue}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -831,6 +833,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue}
|
previewValue={previewValue}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -853,6 +856,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue as any}
|
previewValue={previewValue as any}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -864,6 +868,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue as any}
|
previewValue={previewValue as any}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -875,6 +880,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue as any}
|
previewValue={previewValue as any}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -899,6 +905,7 @@ function SubBlockComponent({
|
|||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue as any}
|
previewValue={previewValue as any}
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -934,6 +941,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue}
|
previewValue={previewValue}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -967,6 +975,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue as any}
|
previewValue={previewValue as any}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -978,6 +987,7 @@ function SubBlockComponent({
|
|||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
isPreview={isPreview}
|
isPreview={isPreview}
|
||||||
previewValue={previewValue}
|
previewValue={previewValue}
|
||||||
|
previewContextValues={isPreview ? subBlockValues : undefined}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Extracts the raw value from a preview context entry.
|
||||||
|
*
|
||||||
|
* @remarks
|
||||||
|
* In the sub-block preview context, values are wrapped as `{ value: T }` objects
|
||||||
|
* (the full sub-block state). In the tool-input preview context, values are already
|
||||||
|
* raw. This function normalizes both cases to return the underlying value.
|
||||||
|
*
|
||||||
|
* @param raw - The preview context entry, which may be a raw value or a `{ value: T }` wrapper
|
||||||
|
* @returns The unwrapped value, or `null` if the input is nullish
|
||||||
|
*/
|
||||||
|
export function resolvePreviewContextValue(raw: unknown): unknown {
|
||||||
|
if (raw === null || raw === undefined) return null
|
||||||
|
if (typeof raw === 'object' && !Array.isArray(raw) && 'value' in raw) {
|
||||||
|
return (raw as Record<string, unknown>).value ?? null
|
||||||
|
}
|
||||||
|
return raw
|
||||||
|
}
|
||||||
@@ -491,6 +491,13 @@ export function useWorkflowExecution() {
|
|||||||
updateActiveBlocks(data.blockId, false)
|
updateActiveBlocks(data.blockId, false)
|
||||||
setBlockRunStatus(data.blockId, 'error')
|
setBlockRunStatus(data.blockId, 'error')
|
||||||
|
|
||||||
|
executedBlockIds.add(data.blockId)
|
||||||
|
accumulatedBlockStates.set(data.blockId, {
|
||||||
|
output: { error: data.error },
|
||||||
|
executed: true,
|
||||||
|
executionTime: data.durationMs || 0,
|
||||||
|
})
|
||||||
|
|
||||||
accumulatedBlockLogs.push(
|
accumulatedBlockLogs.push(
|
||||||
createBlockLogEntry(data, { success: false, output: {}, error: data.error })
|
createBlockLogEntry(data, { success: false, output: {}, error: data.error })
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -784,8 +784,12 @@ function PreviewEditorContent({
|
|||||||
? childWorkflowSnapshotState
|
? childWorkflowSnapshotState
|
||||||
: childWorkflowState
|
: childWorkflowState
|
||||||
const resolvedIsLoadingChildWorkflow = isExecutionMode ? false : isLoadingChildWorkflow
|
const resolvedIsLoadingChildWorkflow = isExecutionMode ? false : isLoadingChildWorkflow
|
||||||
|
const isBlockNotExecuted = isExecutionMode && !executionData
|
||||||
const isMissingChildWorkflow =
|
const isMissingChildWorkflow =
|
||||||
Boolean(childWorkflowId) && !resolvedIsLoadingChildWorkflow && !resolvedChildWorkflowState
|
Boolean(childWorkflowId) &&
|
||||||
|
!isBlockNotExecuted &&
|
||||||
|
!resolvedIsLoadingChildWorkflow &&
|
||||||
|
!resolvedChildWorkflowState
|
||||||
|
|
||||||
/** Drills down into the child workflow or opens it in a new tab */
|
/** Drills down into the child workflow or opens it in a new tab */
|
||||||
const handleExpandChildWorkflow = useCallback(() => {
|
const handleExpandChildWorkflow = useCallback(() => {
|
||||||
@@ -1192,7 +1196,7 @@ function PreviewEditorContent({
|
|||||||
<div ref={subBlocksRef} className='subblocks-section flex flex-1 flex-col overflow-hidden'>
|
<div ref={subBlocksRef} className='subblocks-section flex flex-1 flex-col overflow-hidden'>
|
||||||
<div className='flex-1 overflow-y-auto overflow-x-hidden'>
|
<div className='flex-1 overflow-y-auto overflow-x-hidden'>
|
||||||
{/* Not Executed Banner - shown when in execution mode but block wasn't executed */}
|
{/* Not Executed Banner - shown when in execution mode but block wasn't executed */}
|
||||||
{isExecutionMode && !executionData && (
|
{isBlockNotExecuted && (
|
||||||
<div className='flex min-w-0 flex-col gap-[8px] overflow-hidden border-[var(--border)] border-b px-[12px] py-[10px]'>
|
<div className='flex min-w-0 flex-col gap-[8px] overflow-hidden border-[var(--border)] border-b px-[12px] py-[10px]'>
|
||||||
<div className='flex items-center justify-between'>
|
<div className='flex items-center justify-between'>
|
||||||
<Badge variant='gray-secondary' size='sm' dot>
|
<Badge variant='gray-secondary' size='sm' dot>
|
||||||
@@ -1419,9 +1423,11 @@ function PreviewEditorContent({
|
|||||||
) : (
|
) : (
|
||||||
<div className='flex h-full items-center justify-center bg-[var(--surface-3)]'>
|
<div className='flex h-full items-center justify-center bg-[var(--surface-3)]'>
|
||||||
<span className='text-[13px] text-[var(--text-tertiary)]'>
|
<span className='text-[13px] text-[var(--text-tertiary)]'>
|
||||||
{isMissingChildWorkflow
|
{isBlockNotExecuted
|
||||||
? DELETED_WORKFLOW_LABEL
|
? 'Not Executed'
|
||||||
: 'Unable to load preview'}
|
: isMissingChildWorkflow
|
||||||
|
? DELETED_WORKFLOW_LABEL
|
||||||
|
: 'Unable to load preview'}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -349,7 +349,15 @@ export function PreviewWorkflow({
|
|||||||
if (block.type === 'loop' || block.type === 'parallel') {
|
if (block.type === 'loop' || block.type === 'parallel') {
|
||||||
const isSelected = selectedBlockId === blockId
|
const isSelected = selectedBlockId === blockId
|
||||||
const dimensions = calculateContainerDimensions(blockId, workflowState.blocks)
|
const dimensions = calculateContainerDimensions(blockId, workflowState.blocks)
|
||||||
const subflowExecutionStatus = getSubflowExecutionStatus(blockId)
|
|
||||||
|
// Check for direct error on the subflow block itself (e.g., loop resolution errors)
|
||||||
|
// before falling back to children-derived status
|
||||||
|
const directExecution = blockExecutionMap.get(blockId)
|
||||||
|
const subflowExecutionStatus: ExecutionStatus | undefined =
|
||||||
|
directExecution?.status === 'error'
|
||||||
|
? 'error'
|
||||||
|
: (getSubflowExecutionStatus(blockId) ??
|
||||||
|
(directExecution ? (directExecution.status as ExecutionStatus) : undefined))
|
||||||
|
|
||||||
nodeArray.push({
|
nodeArray.push({
|
||||||
id: blockId,
|
id: blockId,
|
||||||
|
|||||||
@@ -79,9 +79,7 @@ export function SearchModal({
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const workspaceId = params.workspaceId as string
|
const workspaceId = params.workspaceId as string
|
||||||
const inputRef = useRef<HTMLInputElement>(null)
|
const inputRef = useRef<HTMLInputElement>(null)
|
||||||
const listRef = useRef<HTMLDivElement>(null)
|
|
||||||
const [mounted, setMounted] = useState(false)
|
const [mounted, setMounted] = useState(false)
|
||||||
const [search, setSearch] = useState('')
|
|
||||||
const openSettingsModal = useSettingsModalStore((state) => state.openModal)
|
const openSettingsModal = useSettingsModalStore((state) => state.openModal)
|
||||||
const { config: permissionConfig } = usePermissionConfig()
|
const { config: permissionConfig } = usePermissionConfig()
|
||||||
|
|
||||||
@@ -144,19 +142,42 @@ export function SearchModal({
|
|||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open && inputRef.current) {
|
||||||
setSearch('')
|
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
|
||||||
inputRef.current?.focus()
|
window.HTMLInputElement.prototype,
|
||||||
|
'value'
|
||||||
|
)?.set
|
||||||
|
if (nativeInputValueSetter) {
|
||||||
|
nativeInputValueSetter.call(inputRef.current, '')
|
||||||
|
inputRef.current.dispatchEvent(new Event('input', { bubbles: true }))
|
||||||
|
}
|
||||||
|
inputRef.current.focus()
|
||||||
}
|
}
|
||||||
}, [open])
|
}, [open])
|
||||||
|
|
||||||
const handleSearchChange = useCallback((value: string) => {
|
const handleSearchChange = useCallback(() => {
|
||||||
setSearch(value)
|
requestAnimationFrame(() => {
|
||||||
if (listRef.current) {
|
const list = document.querySelector('[cmdk-list]')
|
||||||
listRef.current.scrollTop = 0
|
if (list) {
|
||||||
}
|
list.scrollTop = 0
|
||||||
|
}
|
||||||
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) return
|
||||||
|
|
||||||
|
const handleKeyDown = (e: KeyboardEvent) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
e.preventDefault()
|
||||||
|
onOpenChange(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('keydown', handleKeyDown)
|
||||||
|
return () => document.removeEventListener('keydown', handleKeyDown)
|
||||||
|
}, [open, onOpenChange])
|
||||||
|
|
||||||
const handleBlockSelect = useCallback(
|
const handleBlockSelect = useCallback(
|
||||||
(block: SearchBlockItem, type: 'block' | 'trigger' | 'tool') => {
|
(block: SearchBlockItem, type: 'block' | 'trigger' | 'tool') => {
|
||||||
const enableTriggerMode =
|
const enableTriggerMode =
|
||||||
@@ -243,7 +264,7 @@ export function SearchModal({
|
|||||||
{/* Overlay */}
|
{/* Overlay */}
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
'fixed inset-0 z-40 bg-[#E4E4E4]/50 transition-opacity duration-100 dark:bg-[#0D0D0D]/50',
|
'fixed inset-0 z-40 bg-[#E4E4E4]/50 backdrop-blur-[0.75px] transition-opacity duration-100 dark:bg-[#0D0D0D]/50',
|
||||||
open ? 'opacity-100' : 'pointer-events-none opacity-0'
|
open ? 'opacity-100' : 'pointer-events-none opacity-0'
|
||||||
)}
|
)}
|
||||||
onClick={() => onOpenChange(false)}
|
onClick={() => onOpenChange(false)}
|
||||||
@@ -260,31 +281,16 @@ export function SearchModal({
|
|||||||
'-translate-x-1/2 fixed top-[15%] left-1/2 z-50 w-[500px] overflow-hidden rounded-[12px] border border-[var(--border)] bg-[var(--surface-4)] shadow-lg',
|
'-translate-x-1/2 fixed top-[15%] left-1/2 z-50 w-[500px] overflow-hidden rounded-[12px] border border-[var(--border)] bg-[var(--surface-4)] shadow-lg',
|
||||||
open ? 'visible opacity-100' : 'invisible opacity-0'
|
open ? 'visible opacity-100' : 'invisible opacity-0'
|
||||||
)}
|
)}
|
||||||
onKeyDown={(e) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
e.preventDefault()
|
|
||||||
onOpenChange(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Command label='Search' filter={customFilter}>
|
<Command label='Search' filter={customFilter}>
|
||||||
<Command.Input
|
<Command.Input
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
value={search}
|
autoFocus
|
||||||
onValueChange={handleSearchChange}
|
onValueChange={handleSearchChange}
|
||||||
onKeyDown={(e) => {
|
|
||||||
if (e.key === 'Escape') {
|
|
||||||
e.preventDefault()
|
|
||||||
onOpenChange(false)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
placeholder='Search anything...'
|
placeholder='Search anything...'
|
||||||
className='w-full border-0 border-[var(--border)] border-b bg-transparent px-[12px] py-[10px] font-base text-[15px] text-[var(--text-primary)] placeholder:text-[var(--text-secondary)] focus:outline-none'
|
className='w-full border-0 border-[var(--border)] border-b bg-transparent px-[12px] py-[10px] font-base text-[15px] text-[var(--text-primary)] placeholder:text-[var(--text-secondary)] focus:outline-none'
|
||||||
/>
|
/>
|
||||||
<Command.List
|
<Command.List className='scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent max-h-[400px] overflow-y-auto p-[8px]'>
|
||||||
ref={listRef}
|
|
||||||
className='scrollbar-thin scrollbar-thumb-border scrollbar-track-transparent max-h-[400px] overflow-y-auto p-[8px]'
|
|
||||||
>
|
|
||||||
<Command.Empty className='flex items-center justify-center px-[16px] py-[24px] text-[15px] text-[var(--text-subtle)]'>
|
<Command.Empty className='flex items-center justify-center px-[16px] py-[24px] text-[15px] text-[var(--text-subtle)]'>
|
||||||
No results found.
|
No results found.
|
||||||
</Command.Empty>
|
</Command.Empty>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { executeWorkflowCore } from '@/lib/workflows/executor/execution-core'
|
|||||||
import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-manager'
|
import { PauseResumeManager } from '@/lib/workflows/executor/human-in-the-loop-manager'
|
||||||
import { loadDeployedWorkflowState } from '@/lib/workflows/persistence/utils'
|
import { loadDeployedWorkflowState } from '@/lib/workflows/persistence/utils'
|
||||||
import { getWorkflowById } from '@/lib/workflows/utils'
|
import { getWorkflowById } from '@/lib/workflows/utils'
|
||||||
|
import { getBlock } from '@/blocks'
|
||||||
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
import { ExecutionSnapshot } from '@/executor/execution/snapshot'
|
||||||
import type { ExecutionMetadata } from '@/executor/execution/types'
|
import type { ExecutionMetadata } from '@/executor/execution/types'
|
||||||
import { hasExecutionResult } from '@/executor/utils/errors'
|
import { hasExecutionResult } from '@/executor/utils/errors'
|
||||||
@@ -74,8 +75,21 @@ async function processTriggerFileOutputs(
|
|||||||
logger.error(`[${context.requestId}] Error processing ${currentPath}:`, error)
|
logger.error(`[${context.requestId}] Error processing ${currentPath}:`, error)
|
||||||
processed[key] = val
|
processed[key] = val
|
||||||
}
|
}
|
||||||
|
} else if (
|
||||||
|
outputDef &&
|
||||||
|
typeof outputDef === 'object' &&
|
||||||
|
(outputDef.type === 'object' || outputDef.type === 'json') &&
|
||||||
|
outputDef.properties
|
||||||
|
) {
|
||||||
|
// Explicit object schema with properties - recurse into properties
|
||||||
|
processed[key] = await processTriggerFileOutputs(
|
||||||
|
val,
|
||||||
|
outputDef.properties,
|
||||||
|
context,
|
||||||
|
currentPath
|
||||||
|
)
|
||||||
} else if (outputDef && typeof outputDef === 'object' && !outputDef.type) {
|
} else if (outputDef && typeof outputDef === 'object' && !outputDef.type) {
|
||||||
// Nested object in schema - recurse with the nested schema
|
// Nested object in schema (flat pattern) - recurse with the nested schema
|
||||||
processed[key] = await processTriggerFileOutputs(val, outputDef, context, currentPath)
|
processed[key] = await processTriggerFileOutputs(val, outputDef, context, currentPath)
|
||||||
} else {
|
} else {
|
||||||
// Not a file output - keep as is
|
// Not a file output - keep as is
|
||||||
@@ -405,11 +419,23 @@ async function executeWebhookJobInternal(
|
|||||||
const rawSelectedTriggerId = triggerBlock?.subBlocks?.selectedTriggerId?.value
|
const rawSelectedTriggerId = triggerBlock?.subBlocks?.selectedTriggerId?.value
|
||||||
const rawTriggerId = triggerBlock?.subBlocks?.triggerId?.value
|
const rawTriggerId = triggerBlock?.subBlocks?.triggerId?.value
|
||||||
|
|
||||||
const resolvedTriggerId = [rawSelectedTriggerId, rawTriggerId].find(
|
let resolvedTriggerId = [rawSelectedTriggerId, rawTriggerId].find(
|
||||||
(candidate): candidate is string =>
|
(candidate): candidate is string =>
|
||||||
typeof candidate === 'string' && isTriggerValid(candidate)
|
typeof candidate === 'string' && isTriggerValid(candidate)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!resolvedTriggerId) {
|
||||||
|
const blockConfig = getBlock(triggerBlock.type)
|
||||||
|
if (blockConfig?.category === 'triggers' && isTriggerValid(triggerBlock.type)) {
|
||||||
|
resolvedTriggerId = triggerBlock.type
|
||||||
|
} else if (triggerBlock.triggerMode && blockConfig?.triggers?.enabled) {
|
||||||
|
const available = blockConfig.triggers?.available?.[0]
|
||||||
|
if (available && isTriggerValid(available)) {
|
||||||
|
resolvedTriggerId = available
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (resolvedTriggerId) {
|
if (resolvedTriggerId) {
|
||||||
const triggerConfig = getTrigger(resolvedTriggerId)
|
const triggerConfig = getTrigger(resolvedTriggerId)
|
||||||
|
|
||||||
|
|||||||
@@ -810,7 +810,29 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
placeholder: 'Number of items to return (default: 50)',
|
placeholder: 'Number of items to return (default: 50)',
|
||||||
condition: {
|
condition: {
|
||||||
field: 'operation',
|
field: 'operation',
|
||||||
value: ['linear_list_favorites'],
|
value: [
|
||||||
|
'linear_read_issues',
|
||||||
|
'linear_search_issues',
|
||||||
|
'linear_list_comments',
|
||||||
|
'linear_list_projects',
|
||||||
|
'linear_list_users',
|
||||||
|
'linear_list_teams',
|
||||||
|
'linear_list_labels',
|
||||||
|
'linear_list_workflow_states',
|
||||||
|
'linear_list_cycles',
|
||||||
|
'linear_list_attachments',
|
||||||
|
'linear_list_issue_relations',
|
||||||
|
'linear_list_favorites',
|
||||||
|
'linear_list_project_updates',
|
||||||
|
'linear_list_notifications',
|
||||||
|
'linear_list_customer_statuses',
|
||||||
|
'linear_list_customer_tiers',
|
||||||
|
'linear_list_customers',
|
||||||
|
'linear_list_customer_requests',
|
||||||
|
'linear_list_project_labels',
|
||||||
|
'linear_list_project_milestones',
|
||||||
|
'linear_list_project_statuses',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Pagination - After (for list operations)
|
// Pagination - After (for list operations)
|
||||||
@@ -821,7 +843,29 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
placeholder: 'Cursor for pagination',
|
placeholder: 'Cursor for pagination',
|
||||||
condition: {
|
condition: {
|
||||||
field: 'operation',
|
field: 'operation',
|
||||||
value: ['linear_list_favorites'],
|
value: [
|
||||||
|
'linear_read_issues',
|
||||||
|
'linear_search_issues',
|
||||||
|
'linear_list_comments',
|
||||||
|
'linear_list_projects',
|
||||||
|
'linear_list_users',
|
||||||
|
'linear_list_teams',
|
||||||
|
'linear_list_labels',
|
||||||
|
'linear_list_workflow_states',
|
||||||
|
'linear_list_cycles',
|
||||||
|
'linear_list_attachments',
|
||||||
|
'linear_list_issue_relations',
|
||||||
|
'linear_list_favorites',
|
||||||
|
'linear_list_project_updates',
|
||||||
|
'linear_list_notifications',
|
||||||
|
'linear_list_customers',
|
||||||
|
'linear_list_customer_requests',
|
||||||
|
'linear_list_customer_statuses',
|
||||||
|
'linear_list_customer_tiers',
|
||||||
|
'linear_list_project_labels',
|
||||||
|
'linear_list_project_milestones',
|
||||||
|
'linear_list_project_statuses',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Project health (for project updates)
|
// Project health (for project updates)
|
||||||
@@ -1053,28 +1097,6 @@ Return ONLY the description text - no explanations.`,
|
|||||||
value: ['linear_create_customer_request', 'linear_update_customer_request'],
|
value: ['linear_create_customer_request', 'linear_update_customer_request'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Pagination - first
|
|
||||||
{
|
|
||||||
id: 'first',
|
|
||||||
title: 'Limit',
|
|
||||||
type: 'short-input',
|
|
||||||
placeholder: 'Number of items (default: 50)',
|
|
||||||
condition: {
|
|
||||||
field: 'operation',
|
|
||||||
value: ['linear_list_customers', 'linear_list_customer_requests'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Pagination - after
|
|
||||||
{
|
|
||||||
id: 'after',
|
|
||||||
title: 'After Cursor',
|
|
||||||
type: 'short-input',
|
|
||||||
placeholder: 'Cursor for pagination',
|
|
||||||
condition: {
|
|
||||||
field: 'operation',
|
|
||||||
value: ['linear_list_customers', 'linear_list_customer_requests'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
// Customer ID for get/update/delete/merge operations
|
// Customer ID for get/update/delete/merge operations
|
||||||
{
|
{
|
||||||
id: 'customerIdTarget',
|
id: 'customerIdTarget',
|
||||||
@@ -1493,6 +1515,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
teamId: effectiveTeamId || undefined,
|
teamId: effectiveTeamId || undefined,
|
||||||
projectId: effectiveProjectId || undefined,
|
projectId: effectiveProjectId || undefined,
|
||||||
includeArchived: params.includeArchived,
|
includeArchived: params.includeArchived,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_get_issue':
|
case 'linear_get_issue':
|
||||||
@@ -1558,6 +1582,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
query: params.query.trim(),
|
query: params.query.trim(),
|
||||||
teamId: effectiveTeamId,
|
teamId: effectiveTeamId,
|
||||||
includeArchived: params.includeArchived,
|
includeArchived: params.includeArchived,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_add_label_to_issue':
|
case 'linear_add_label_to_issue':
|
||||||
@@ -1607,6 +1633,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
issueId: params.issueId.trim(),
|
issueId: params.issueId.trim(),
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_list_projects':
|
case 'linear_list_projects':
|
||||||
@@ -1614,6 +1642,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
...baseParams,
|
...baseParams,
|
||||||
teamId: effectiveTeamId,
|
teamId: effectiveTeamId,
|
||||||
includeArchived: params.includeArchived,
|
includeArchived: params.includeArchived,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_get_project':
|
case 'linear_get_project':
|
||||||
@@ -1665,6 +1695,12 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
|
|
||||||
case 'linear_list_users':
|
case 'linear_list_users':
|
||||||
case 'linear_list_teams':
|
case 'linear_list_teams':
|
||||||
|
return {
|
||||||
|
...baseParams,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
|
}
|
||||||
|
|
||||||
case 'linear_get_viewer':
|
case 'linear_get_viewer':
|
||||||
return baseParams
|
return baseParams
|
||||||
|
|
||||||
@@ -1672,6 +1708,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
teamId: effectiveTeamId,
|
teamId: effectiveTeamId,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_create_label':
|
case 'linear_create_label':
|
||||||
@@ -1709,6 +1747,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
teamId: effectiveTeamId,
|
teamId: effectiveTeamId,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_create_workflow_state':
|
case 'linear_create_workflow_state':
|
||||||
@@ -1738,6 +1778,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
teamId: effectiveTeamId,
|
teamId: effectiveTeamId,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_get_cycle':
|
case 'linear_get_cycle':
|
||||||
@@ -1801,6 +1843,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
issueId: params.issueId.trim(),
|
issueId: params.issueId.trim(),
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_update_attachment':
|
case 'linear_update_attachment':
|
||||||
@@ -1840,6 +1884,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
issueId: params.issueId.trim(),
|
issueId: params.issueId.trim(),
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_delete_issue_relation':
|
case 'linear_delete_issue_relation':
|
||||||
@@ -1886,10 +1932,16 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
projectId: effectiveProjectId,
|
projectId: effectiveProjectId,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_list_notifications':
|
case 'linear_list_notifications':
|
||||||
return baseParams
|
return {
|
||||||
|
...baseParams,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
|
}
|
||||||
|
|
||||||
case 'linear_update_notification':
|
case 'linear_update_notification':
|
||||||
if (!params.notificationId?.trim()) {
|
if (!params.notificationId?.trim()) {
|
||||||
@@ -2018,9 +2070,9 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
name: params.statusName.trim(),
|
name: params.statusName.trim(),
|
||||||
displayName: params.statusDisplayName?.trim() || params.statusName.trim(),
|
|
||||||
color: params.statusColor.trim(),
|
color: params.statusColor.trim(),
|
||||||
description: params.statusDescription?.trim() || undefined,
|
description: params.statusDescription?.trim() || undefined,
|
||||||
|
displayName: params.statusDisplayName?.trim() || undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_update_customer_status':
|
case 'linear_update_customer_status':
|
||||||
@@ -2031,9 +2083,9 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
...baseParams,
|
...baseParams,
|
||||||
statusId: params.statusId.trim(),
|
statusId: params.statusId.trim(),
|
||||||
name: params.statusName?.trim() || undefined,
|
name: params.statusName?.trim() || undefined,
|
||||||
displayName: params.statusDisplayName?.trim() || undefined,
|
|
||||||
color: params.statusColor?.trim() || undefined,
|
color: params.statusColor?.trim() || undefined,
|
||||||
description: params.statusDescription?.trim() || undefined,
|
description: params.statusDescription?.trim() || undefined,
|
||||||
|
displayName: params.statusDisplayName?.trim() || undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_delete_customer_status':
|
case 'linear_delete_customer_status':
|
||||||
@@ -2046,7 +2098,11 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_list_customer_statuses':
|
case 'linear_list_customer_statuses':
|
||||||
return baseParams
|
return {
|
||||||
|
...baseParams,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
|
}
|
||||||
|
|
||||||
// Customer Tier Operations
|
// Customer Tier Operations
|
||||||
case 'linear_create_customer_tier':
|
case 'linear_create_customer_tier':
|
||||||
@@ -2084,7 +2140,11 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_list_customer_tiers':
|
case 'linear_list_customer_tiers':
|
||||||
return baseParams
|
return {
|
||||||
|
...baseParams,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
|
}
|
||||||
|
|
||||||
// Project Management Operations
|
// Project Management Operations
|
||||||
case 'linear_delete_project':
|
case 'linear_delete_project':
|
||||||
@@ -2135,6 +2195,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
projectId: effectiveProjectId || undefined,
|
projectId: effectiveProjectId || undefined,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_add_label_to_project':
|
case 'linear_add_label_to_project':
|
||||||
@@ -2198,6 +2260,8 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
return {
|
return {
|
||||||
...baseParams,
|
...baseParams,
|
||||||
projectId: params.projectIdForMilestone.trim(),
|
projectId: params.projectIdForMilestone.trim(),
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Project Status Operations
|
// Project Status Operations
|
||||||
@@ -2245,7 +2309,11 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'linear_list_project_statuses':
|
case 'linear_list_project_statuses':
|
||||||
return baseParams
|
return {
|
||||||
|
...baseParams,
|
||||||
|
first: params.first ? Number(params.first) : undefined,
|
||||||
|
after: params.after,
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return baseParams
|
return baseParams
|
||||||
@@ -2321,9 +2389,9 @@ Return ONLY the date string in YYYY-MM-DD format - no explanations, no quotes, n
|
|||||||
// Customer status and tier inputs
|
// Customer status and tier inputs
|
||||||
statusId: { type: 'string', description: 'Status identifier' },
|
statusId: { type: 'string', description: 'Status identifier' },
|
||||||
statusName: { type: 'string', description: 'Status name' },
|
statusName: { type: 'string', description: 'Status name' },
|
||||||
statusDisplayName: { type: 'string', description: 'Status display name' },
|
|
||||||
statusColor: { type: 'string', description: 'Status color in hex format' },
|
statusColor: { type: 'string', description: 'Status color in hex format' },
|
||||||
statusDescription: { type: 'string', description: 'Status description' },
|
statusDescription: { type: 'string', description: 'Status description' },
|
||||||
|
statusDisplayName: { type: 'string', description: 'Status display name' },
|
||||||
tierId: { type: 'string', description: 'Tier identifier' },
|
tierId: { type: 'string', description: 'Tier identifier' },
|
||||||
tierName: { type: 'string', description: 'Tier name' },
|
tierName: { type: 'string', description: 'Tier name' },
|
||||||
tierDisplayName: { type: 'string', description: 'Tier display name' },
|
tierDisplayName: { type: 'string', description: 'Tier display name' },
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ export const WorkflowBlock: BlockConfig = {
|
|||||||
outputs: {
|
outputs: {
|
||||||
success: { type: 'boolean', description: 'Execution success status' },
|
success: { type: 'boolean', description: 'Execution success status' },
|
||||||
childWorkflowName: { type: 'string', description: 'Child workflow name' },
|
childWorkflowName: { type: 'string', description: 'Child workflow name' },
|
||||||
|
childWorkflowId: { type: 'string', description: 'Child workflow ID' },
|
||||||
result: { type: 'json', description: 'Workflow execution result' },
|
result: { type: 'json', description: 'Workflow execution result' },
|
||||||
error: { type: 'string', description: 'Error message' },
|
error: { type: 'string', description: 'Error message' },
|
||||||
childTraceSpans: {
|
childTraceSpans: {
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ export const WorkflowInputBlock: BlockConfig = {
|
|||||||
outputs: {
|
outputs: {
|
||||||
success: { type: 'boolean', description: 'Execution success status' },
|
success: { type: 'boolean', description: 'Execution success status' },
|
||||||
childWorkflowName: { type: 'string', description: 'Child workflow name' },
|
childWorkflowName: { type: 'string', description: 'Child workflow name' },
|
||||||
|
childWorkflowId: { type: 'string', description: 'Child workflow ID' },
|
||||||
result: { type: 'json', description: 'Workflow execution result' },
|
result: { type: 'json', description: 'Workflow execution result' },
|
||||||
error: { type: 'string', description: 'Error message' },
|
error: { type: 'string', description: 'Error message' },
|
||||||
childTraceSpans: {
|
childTraceSpans: {
|
||||||
|
|||||||
@@ -2478,6 +2478,9 @@ describe('EdgeManager', () => {
|
|||||||
expect(readyNodes).toContain(otherBranchId)
|
expect(readyNodes).toContain(otherBranchId)
|
||||||
expect(readyNodes).not.toContain(sentinelStartId)
|
expect(readyNodes).not.toContain(sentinelStartId)
|
||||||
|
|
||||||
|
// sentinel_end should NOT be ready - it's on a fully deactivated path
|
||||||
|
expect(readyNodes).not.toContain(sentinelEndId)
|
||||||
|
|
||||||
// afterLoop should NOT be ready - its incoming edge from sentinel_end should be deactivated
|
// afterLoop should NOT be ready - its incoming edge from sentinel_end should be deactivated
|
||||||
expect(readyNodes).not.toContain(afterLoopId)
|
expect(readyNodes).not.toContain(afterLoopId)
|
||||||
|
|
||||||
@@ -2545,6 +2548,84 @@ describe('EdgeManager', () => {
|
|||||||
expect(edgeManager.isNodeReady(afterParallelNode)).toBe(true)
|
expect(edgeManager.isNodeReady(afterParallelNode)).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not queue loop sentinel-end when upstream condition deactivates entire loop branch', () => {
|
||||||
|
// Regression test for: upstream condition → (if) → ... many blocks ... → sentinel_start → body → sentinel_end
|
||||||
|
// → (else) → exit_block
|
||||||
|
// When condition takes "else", the deep cascade deactivation should NOT queue sentinel_end.
|
||||||
|
// Previously, sentinel_end was flagged as a cascadeTarget (terminal control node) and
|
||||||
|
// spuriously queued, causing it to attempt loop scope initialization and fail.
|
||||||
|
|
||||||
|
const conditionId = 'condition'
|
||||||
|
const intermediateId = 'intermediate'
|
||||||
|
const sentinelStartId = 'sentinel-start'
|
||||||
|
const loopBodyId = 'loop-body'
|
||||||
|
const sentinelEndId = 'sentinel-end'
|
||||||
|
const afterLoopId = 'after-loop'
|
||||||
|
const exitBlockId = 'exit-block'
|
||||||
|
|
||||||
|
const conditionNode = createMockNode(conditionId, [
|
||||||
|
{ target: intermediateId, sourceHandle: 'condition-if' },
|
||||||
|
{ target: exitBlockId, sourceHandle: 'condition-else' },
|
||||||
|
])
|
||||||
|
|
||||||
|
const intermediateNode = createMockNode(
|
||||||
|
intermediateId,
|
||||||
|
[{ target: sentinelStartId }],
|
||||||
|
[conditionId]
|
||||||
|
)
|
||||||
|
|
||||||
|
const sentinelStartNode = createMockNode(
|
||||||
|
sentinelStartId,
|
||||||
|
[{ target: loopBodyId }],
|
||||||
|
[intermediateId]
|
||||||
|
)
|
||||||
|
|
||||||
|
const loopBodyNode = createMockNode(
|
||||||
|
loopBodyId,
|
||||||
|
[{ target: sentinelEndId }],
|
||||||
|
[sentinelStartId]
|
||||||
|
)
|
||||||
|
|
||||||
|
const sentinelEndNode = createMockNode(
|
||||||
|
sentinelEndId,
|
||||||
|
[
|
||||||
|
{ target: sentinelStartId, sourceHandle: 'loop_continue' },
|
||||||
|
{ target: afterLoopId, sourceHandle: 'loop_exit' },
|
||||||
|
],
|
||||||
|
[loopBodyId]
|
||||||
|
)
|
||||||
|
|
||||||
|
const afterLoopNode = createMockNode(afterLoopId, [], [sentinelEndId])
|
||||||
|
const exitBlockNode = createMockNode(exitBlockId, [], [conditionId])
|
||||||
|
|
||||||
|
const nodes = new Map<string, DAGNode>([
|
||||||
|
[conditionId, conditionNode],
|
||||||
|
[intermediateId, intermediateNode],
|
||||||
|
[sentinelStartId, sentinelStartNode],
|
||||||
|
[loopBodyId, loopBodyNode],
|
||||||
|
[sentinelEndId, sentinelEndNode],
|
||||||
|
[afterLoopId, afterLoopNode],
|
||||||
|
[exitBlockId, exitBlockNode],
|
||||||
|
])
|
||||||
|
|
||||||
|
const dag = createMockDAG(nodes)
|
||||||
|
const edgeManager = new EdgeManager(dag)
|
||||||
|
|
||||||
|
const readyNodes = edgeManager.processOutgoingEdges(conditionNode, {
|
||||||
|
selectedOption: 'else',
|
||||||
|
})
|
||||||
|
|
||||||
|
// Only exitBlock should be ready
|
||||||
|
expect(readyNodes).toContain(exitBlockId)
|
||||||
|
|
||||||
|
// Nothing on the deactivated path should be queued
|
||||||
|
expect(readyNodes).not.toContain(intermediateId)
|
||||||
|
expect(readyNodes).not.toContain(sentinelStartId)
|
||||||
|
expect(readyNodes).not.toContain(loopBodyId)
|
||||||
|
expect(readyNodes).not.toContain(sentinelEndId)
|
||||||
|
expect(readyNodes).not.toContain(afterLoopId)
|
||||||
|
})
|
||||||
|
|
||||||
it('should still correctly handle normal loop exit (not deactivate when loop runs)', () => {
|
it('should still correctly handle normal loop exit (not deactivate when loop runs)', () => {
|
||||||
// When a loop actually executes and exits normally, after_loop should become ready
|
// When a loop actually executes and exits normally, after_loop should become ready
|
||||||
const sentinelStartId = 'sentinel-start'
|
const sentinelStartId = 'sentinel-start'
|
||||||
|
|||||||
@@ -71,7 +71,13 @@ export class EdgeManager {
|
|||||||
|
|
||||||
for (const targetId of cascadeTargets) {
|
for (const targetId of cascadeTargets) {
|
||||||
if (!readyNodes.includes(targetId) && !activatedTargets.includes(targetId)) {
|
if (!readyNodes.includes(targetId) && !activatedTargets.includes(targetId)) {
|
||||||
if (this.isTargetReady(targetId)) {
|
// Only queue cascade terminal control nodes when ALL outgoing edges from the
|
||||||
|
// current node were deactivated (dead-end scenario). When some edges are
|
||||||
|
// activated, terminal control nodes on deactivated branches should NOT be
|
||||||
|
// queued - they will be reached through the normal activated path's completion.
|
||||||
|
// This prevents loop/parallel sentinels on fully deactivated paths (e.g., an
|
||||||
|
// upstream condition took a different branch) from being spuriously executed.
|
||||||
|
if (activatedTargets.length === 0 && this.isTargetReady(targetId)) {
|
||||||
readyNodes.push(targetId)
|
readyNodes.push(targetId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import {
|
||||||
|
extractFieldsFromSchema,
|
||||||
|
parseResponseFormatSafely,
|
||||||
|
} from '@/lib/core/utils/response-format'
|
||||||
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
|
import { normalizeInputFormatValue } from '@/lib/workflows/input-format'
|
||||||
import { isTriggerBehavior, normalizeName } from '@/executor/constants'
|
import { isTriggerBehavior, normalizeName } from '@/executor/constants'
|
||||||
import type { ExecutionContext } from '@/executor/types'
|
import type { ExecutionContext } from '@/executor/types'
|
||||||
@@ -43,23 +47,53 @@ function getInputFormatFields(block: SerializedBlock): OutputSchema {
|
|||||||
const schema: OutputSchema = {}
|
const schema: OutputSchema = {}
|
||||||
for (const field of inputFormat) {
|
for (const field of inputFormat) {
|
||||||
if (!field.name) continue
|
if (!field.name) continue
|
||||||
schema[field.name] = {
|
schema[field.name] = { type: field.type || 'any' }
|
||||||
type: (field.type || 'any') as 'string' | 'number' | 'boolean' | 'object' | 'array' | 'any',
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return schema
|
return schema
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getEvaluatorMetricsSchema(block: SerializedBlock): OutputSchema | undefined {
|
||||||
|
if (block.metadata?.id !== 'evaluator') return undefined
|
||||||
|
|
||||||
|
const metrics = block.config?.params?.metrics
|
||||||
|
if (!Array.isArray(metrics) || metrics.length === 0) return undefined
|
||||||
|
|
||||||
|
const validMetrics = metrics.filter(
|
||||||
|
(m: { name?: string }) => m?.name && typeof m.name === 'string'
|
||||||
|
)
|
||||||
|
if (validMetrics.length === 0) return undefined
|
||||||
|
|
||||||
|
const schema: OutputSchema = { ...(block.outputs as OutputSchema) }
|
||||||
|
for (const metric of validMetrics) {
|
||||||
|
schema[metric.name.toLowerCase()] = { type: 'number' }
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
|
function getResponseFormatSchema(block: SerializedBlock): OutputSchema | undefined {
|
||||||
|
const responseFormatValue = block.config?.params?.responseFormat
|
||||||
|
if (!responseFormatValue) return undefined
|
||||||
|
|
||||||
|
const parsed = parseResponseFormatSafely(responseFormatValue, block.id)
|
||||||
|
if (!parsed) return undefined
|
||||||
|
|
||||||
|
const fields = extractFieldsFromSchema(parsed)
|
||||||
|
if (fields.length === 0) return undefined
|
||||||
|
|
||||||
|
const schema: OutputSchema = {}
|
||||||
|
for (const field of fields) {
|
||||||
|
schema[field.name] = { type: field.type || 'any' }
|
||||||
|
}
|
||||||
|
return schema
|
||||||
|
}
|
||||||
|
|
||||||
export function getBlockSchema(
|
export function getBlockSchema(
|
||||||
block: SerializedBlock,
|
block: SerializedBlock,
|
||||||
toolConfig?: ToolConfig
|
toolConfig?: ToolConfig
|
||||||
): OutputSchema | undefined {
|
): OutputSchema | undefined {
|
||||||
const blockType = block.metadata?.id
|
const blockType = block.metadata?.id
|
||||||
|
|
||||||
// For blocks that expose inputFormat as outputs, always merge them
|
|
||||||
// This includes both triggers (start_trigger, generic_webhook) and
|
|
||||||
// non-triggers (starter, human_in_the_loop) that have inputFormat
|
|
||||||
if (
|
if (
|
||||||
blockType &&
|
blockType &&
|
||||||
BLOCKS_WITH_INPUT_FORMAT_OUTPUTS.includes(
|
BLOCKS_WITH_INPUT_FORMAT_OUTPUTS.includes(
|
||||||
@@ -74,6 +108,16 @@ export function getBlockSchema(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const evaluatorSchema = getEvaluatorMetricsSchema(block)
|
||||||
|
if (evaluatorSchema) {
|
||||||
|
return evaluatorSchema
|
||||||
|
}
|
||||||
|
|
||||||
|
const responseFormatSchema = getResponseFormatSchema(block)
|
||||||
|
if (responseFormatSchema) {
|
||||||
|
return responseFormatSchema
|
||||||
|
}
|
||||||
|
|
||||||
const isTrigger = isTriggerBehavior(block)
|
const isTrigger = isTriggerBehavior(block)
|
||||||
|
|
||||||
if (isTrigger && block.outputs && Object.keys(block.outputs).length > 0) {
|
if (isTrigger && block.outputs && Object.keys(block.outputs).length > 0) {
|
||||||
|
|||||||
@@ -33,11 +33,25 @@ export class SnapshotService implements ISnapshotService {
|
|||||||
|
|
||||||
const existingSnapshot = await this.getSnapshotByHash(workflowId, stateHash)
|
const existingSnapshot = await this.getSnapshotByHash(workflowId, stateHash)
|
||||||
if (existingSnapshot) {
|
if (existingSnapshot) {
|
||||||
|
let refreshedState: WorkflowState = existingSnapshot.stateData
|
||||||
|
try {
|
||||||
|
await db
|
||||||
|
.update(workflowExecutionSnapshots)
|
||||||
|
.set({ stateData: state })
|
||||||
|
.where(eq(workflowExecutionSnapshots.id, existingSnapshot.id))
|
||||||
|
refreshedState = state
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn(
|
||||||
|
`Failed to refresh snapshot stateData for ${existingSnapshot.id}, continuing with existing data`,
|
||||||
|
error
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
`Reusing existing snapshot for workflow ${workflowId} (hash: ${stateHash.slice(0, 12)}...)`
|
`Reusing existing snapshot for workflow ${workflowId} (hash: ${stateHash.slice(0, 12)}...)`
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
snapshot: existingSnapshot,
|
snapshot: { ...existingSnapshot, stateData: refreshedState },
|
||||||
isNew: false,
|
isNew: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -527,6 +527,113 @@ export async function validateTwilioSignature(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SLACK_FILE_HOSTS = new Set(['files.slack.com', 'files-pri.slack.com'])
|
||||||
|
const SLACK_MAX_FILE_SIZE = 50 * 1024 * 1024 // 50 MB
|
||||||
|
const SLACK_MAX_FILES = 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads file attachments from Slack using the bot token.
|
||||||
|
* Returns files in the format expected by WebhookAttachmentProcessor:
|
||||||
|
* { name, data (base64 string), mimeType, size }
|
||||||
|
*
|
||||||
|
* Security:
|
||||||
|
* - Validates each url_private against allowlisted Slack file hosts
|
||||||
|
* - Uses validateUrlWithDNS + secureFetchWithPinnedIP to prevent SSRF
|
||||||
|
* - Enforces per-file size limit and max file count
|
||||||
|
*/
|
||||||
|
async function downloadSlackFiles(
|
||||||
|
rawFiles: any[],
|
||||||
|
botToken: string
|
||||||
|
): Promise<Array<{ name: string; data: string; mimeType: string; size: number }>> {
|
||||||
|
const filesToProcess = rawFiles.slice(0, SLACK_MAX_FILES)
|
||||||
|
const downloaded: Array<{ name: string; data: string; mimeType: string; size: number }> = []
|
||||||
|
|
||||||
|
for (const file of filesToProcess) {
|
||||||
|
const urlPrivate = file.url_private as string | undefined
|
||||||
|
if (!urlPrivate) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate the URL points to a known Slack file host
|
||||||
|
let parsedUrl: URL
|
||||||
|
try {
|
||||||
|
parsedUrl = new URL(urlPrivate)
|
||||||
|
} catch {
|
||||||
|
logger.warn('Slack file has invalid url_private, skipping', { fileId: file.id })
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SLACK_FILE_HOSTS.has(parsedUrl.hostname)) {
|
||||||
|
logger.warn('Slack file url_private points to unexpected host, skipping', {
|
||||||
|
fileId: file.id,
|
||||||
|
hostname: sanitizeUrlForLog(urlPrivate),
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip files that exceed the size limit
|
||||||
|
const reportedSize = Number(file.size) || 0
|
||||||
|
if (reportedSize > SLACK_MAX_FILE_SIZE) {
|
||||||
|
logger.warn('Slack file exceeds size limit, skipping', {
|
||||||
|
fileId: file.id,
|
||||||
|
size: reportedSize,
|
||||||
|
limit: SLACK_MAX_FILE_SIZE,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const urlValidation = await validateUrlWithDNS(urlPrivate, 'url_private')
|
||||||
|
if (!urlValidation.isValid) {
|
||||||
|
logger.warn('Slack file url_private failed DNS validation, skipping', {
|
||||||
|
fileId: file.id,
|
||||||
|
error: urlValidation.error,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await secureFetchWithPinnedIP(urlPrivate, urlValidation.resolvedIP!, {
|
||||||
|
headers: { Authorization: `Bearer ${botToken}` },
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
logger.warn('Failed to download Slack file, skipping', {
|
||||||
|
fileId: file.id,
|
||||||
|
status: response.status,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const arrayBuffer = await response.arrayBuffer()
|
||||||
|
const buffer = Buffer.from(arrayBuffer)
|
||||||
|
|
||||||
|
// Verify the actual downloaded size doesn't exceed our limit
|
||||||
|
if (buffer.length > SLACK_MAX_FILE_SIZE) {
|
||||||
|
logger.warn('Downloaded Slack file exceeds size limit, skipping', {
|
||||||
|
fileId: file.id,
|
||||||
|
actualSize: buffer.length,
|
||||||
|
limit: SLACK_MAX_FILE_SIZE,
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
downloaded.push({
|
||||||
|
name: file.name || 'download',
|
||||||
|
data: buffer.toString('base64'),
|
||||||
|
mimeType: file.mimetype || 'application/octet-stream',
|
||||||
|
size: buffer.length,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('Error downloading Slack file, skipping', {
|
||||||
|
fileId: file.id,
|
||||||
|
error: error instanceof Error ? error.message : String(error),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return downloaded
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format webhook input based on provider
|
* Format webhook input based on provider
|
||||||
*/
|
*/
|
||||||
@@ -787,43 +894,44 @@ export async function formatWebhookInput(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (foundWebhook.provider === 'slack') {
|
if (foundWebhook.provider === 'slack') {
|
||||||
const event = body?.event
|
const providerConfig = (foundWebhook.providerConfig as Record<string, any>) || {}
|
||||||
|
const botToken = providerConfig.botToken as string | undefined
|
||||||
|
const includeFiles = Boolean(providerConfig.includeFiles)
|
||||||
|
|
||||||
if (event && body?.type === 'event_callback') {
|
const rawEvent = body?.event
|
||||||
return {
|
|
||||||
event: {
|
if (!rawEvent) {
|
||||||
event_type: event.type || '',
|
logger.warn('Unknown Slack event type', {
|
||||||
channel: event.channel || '',
|
type: body?.type,
|
||||||
channel_name: '',
|
hasEvent: false,
|
||||||
user: event.user || '',
|
bodyKeys: Object.keys(body || {}),
|
||||||
user_name: '',
|
})
|
||||||
text: event.text || '',
|
|
||||||
timestamp: event.ts || event.event_ts || '',
|
|
||||||
thread_ts: event.thread_ts || '',
|
|
||||||
team_id: body.team_id || event.team || '',
|
|
||||||
event_id: body.event_id || '',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.warn('Unknown Slack event type', {
|
const rawFiles: any[] = rawEvent?.files ?? []
|
||||||
type: body?.type,
|
const hasFiles = rawFiles.length > 0
|
||||||
hasEvent: !!body?.event,
|
|
||||||
bodyKeys: Object.keys(body || {}),
|
let files: any[] = []
|
||||||
})
|
if (hasFiles && includeFiles && botToken) {
|
||||||
|
files = await downloadSlackFiles(rawFiles, botToken)
|
||||||
|
} else if (hasFiles && includeFiles && !botToken) {
|
||||||
|
logger.warn('Slack message has files and includeFiles is enabled, but no bot token provided')
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
event: {
|
event: {
|
||||||
event_type: body?.event?.type || body?.type || 'unknown',
|
event_type: rawEvent?.type || body?.type || 'unknown',
|
||||||
channel: body?.event?.channel || '',
|
channel: rawEvent?.channel || '',
|
||||||
channel_name: '',
|
channel_name: '',
|
||||||
user: body?.event?.user || '',
|
user: rawEvent?.user || '',
|
||||||
user_name: '',
|
user_name: '',
|
||||||
text: body?.event?.text || '',
|
text: rawEvent?.text || '',
|
||||||
timestamp: body?.event?.ts || '',
|
timestamp: rawEvent?.ts || rawEvent?.event_ts || '',
|
||||||
thread_ts: body?.event?.thread_ts || '',
|
thread_ts: rawEvent?.thread_ts || '',
|
||||||
team_id: body?.team_id || '',
|
team_id: body?.team_id || rawEvent?.team || '',
|
||||||
event_id: body?.event_id || '',
|
event_id: body?.event_id || '',
|
||||||
|
hasFiles,
|
||||||
|
files,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -131,8 +131,12 @@ export const linearCreateCustomerTool: ToolConfig<
|
|||||||
domains
|
domains
|
||||||
externalIds
|
externalIds
|
||||||
logoUrl
|
logoUrl
|
||||||
|
slugId
|
||||||
approximateNeedCount
|
approximateNeedCount
|
||||||
|
revenue
|
||||||
|
size
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,18 +32,18 @@ export const linearCreateCustomerStatusTool: ToolConfig<
|
|||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Status color (hex code)',
|
description: 'Status color (hex code)',
|
||||||
},
|
},
|
||||||
displayName: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
visibility: 'user-or-llm',
|
|
||||||
description: 'Display name for the status',
|
|
||||||
},
|
|
||||||
description: {
|
description: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: false,
|
required: false,
|
||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Status description',
|
description: 'Status description',
|
||||||
},
|
},
|
||||||
|
displayName: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Display name for the status',
|
||||||
|
},
|
||||||
position: {
|
position: {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
required: false,
|
required: false,
|
||||||
@@ -70,12 +70,12 @@ export const linearCreateCustomerStatusTool: ToolConfig<
|
|||||||
color: params.color,
|
color: params.color,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.displayName != null && params.displayName !== '') {
|
|
||||||
input.displayName = params.displayName
|
|
||||||
}
|
|
||||||
if (params.description != null && params.description !== '') {
|
if (params.description != null && params.description !== '') {
|
||||||
input.description = params.description
|
input.description = params.description
|
||||||
}
|
}
|
||||||
|
if (params.displayName != null && params.displayName !== '') {
|
||||||
|
input.displayName = params.displayName
|
||||||
|
}
|
||||||
if (params.position != null) {
|
if (params.position != null) {
|
||||||
input.position = params.position
|
input.position = params.position
|
||||||
}
|
}
|
||||||
@@ -88,11 +88,12 @@ export const linearCreateCustomerStatusTool: ToolConfig<
|
|||||||
status {
|
status {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
displayName
|
|
||||||
description
|
description
|
||||||
color
|
color
|
||||||
position
|
position
|
||||||
|
type
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { LinearCreateCycleParams, LinearCreateCycleResponse } from '@/tools/linear/types'
|
import type { LinearCreateCycleParams, LinearCreateCycleResponse } from '@/tools/linear/types'
|
||||||
|
import { CYCLE_FULL_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearCreateCycleTool: ToolConfig<LinearCreateCycleParams, LinearCreateCycleResponse> =
|
export const linearCreateCycleTool: ToolConfig<LinearCreateCycleParams, LinearCreateCycleResponse> =
|
||||||
@@ -72,7 +73,9 @@ export const linearCreateCycleTool: ToolConfig<LinearCreateCycleParams, LinearCr
|
|||||||
name
|
name
|
||||||
startsAt
|
startsAt
|
||||||
endsAt
|
endsAt
|
||||||
|
completedAt
|
||||||
progress
|
progress
|
||||||
|
createdAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -120,14 +123,7 @@ export const linearCreateCycleTool: ToolConfig<LinearCreateCycleParams, LinearCr
|
|||||||
cycle: {
|
cycle: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The created cycle',
|
description: 'The created cycle',
|
||||||
properties: {
|
properties: CYCLE_FULL_OUTPUT_PROPERTIES,
|
||||||
id: { type: 'string', description: 'Cycle ID' },
|
|
||||||
number: { type: 'number', description: 'Cycle number' },
|
|
||||||
name: { type: 'string', description: 'Cycle name' },
|
|
||||||
startsAt: { type: 'string', description: 'Start date' },
|
|
||||||
endsAt: { type: 'string', description: 'End date' },
|
|
||||||
team: { type: 'object', description: 'Team this cycle belongs to' },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ export const linearCreateLabelTool: ToolConfig<LinearCreateLabelParams, LinearCr
|
|||||||
name
|
name
|
||||||
color
|
color
|
||||||
description
|
description
|
||||||
|
isGroup
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
archivedAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearCreateProjectLabelParams,
|
LinearCreateProjectLabelParams,
|
||||||
LinearCreateProjectLabelResponse,
|
LinearCreateProjectLabelResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PROJECT_LABEL_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearCreateProjectLabelTool: ToolConfig<
|
export const linearCreateProjectLabelTool: ToolConfig<
|
||||||
@@ -93,6 +94,7 @@ export const linearCreateProjectLabelTool: ToolConfig<
|
|||||||
color
|
color
|
||||||
isGroup
|
isGroup
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -137,6 +139,7 @@ export const linearCreateProjectLabelTool: ToolConfig<
|
|||||||
projectLabel: {
|
projectLabel: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The created project label',
|
description: 'The created project label',
|
||||||
|
properties: PROJECT_LABEL_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearCreateProjectMilestoneParams,
|
LinearCreateProjectMilestoneParams,
|
||||||
LinearCreateProjectMilestoneResponse,
|
LinearCreateProjectMilestoneResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PROJECT_MILESTONE_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearCreateProjectMilestoneTool: ToolConfig<
|
export const linearCreateProjectMilestoneTool: ToolConfig<
|
||||||
@@ -79,10 +80,15 @@ export const linearCreateProjectMilestoneTool: ToolConfig<
|
|||||||
id
|
id
|
||||||
name
|
name
|
||||||
description
|
description
|
||||||
projectId
|
|
||||||
targetDate
|
targetDate
|
||||||
|
progress
|
||||||
|
sortOrder
|
||||||
|
status
|
||||||
createdAt
|
createdAt
|
||||||
archivedAt
|
archivedAt
|
||||||
|
project {
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,10 +120,15 @@ export const linearCreateProjectMilestoneTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const milestone = result.projectMilestone
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
projectMilestone: result.projectMilestone,
|
projectMilestone: {
|
||||||
|
...milestone,
|
||||||
|
projectId: milestone.project?.id ?? null,
|
||||||
|
project: undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -126,6 +137,7 @@ export const linearCreateProjectMilestoneTool: ToolConfig<
|
|||||||
projectMilestone: {
|
projectMilestone: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The created project milestone',
|
description: 'The created project milestone',
|
||||||
|
properties: PROJECT_MILESTONE_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearCreateProjectStatusParams,
|
LinearCreateProjectStatusParams,
|
||||||
LinearCreateProjectStatusResponse,
|
LinearCreateProjectStatusResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PROJECT_STATUS_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearCreateProjectStatusTool: ToolConfig<
|
export const linearCreateProjectStatusTool: ToolConfig<
|
||||||
@@ -97,7 +98,9 @@ export const linearCreateProjectStatusTool: ToolConfig<
|
|||||||
color
|
color
|
||||||
indefinite
|
indefinite
|
||||||
position
|
position
|
||||||
|
type
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -142,6 +145,7 @@ export const linearCreateProjectStatusTool: ToolConfig<
|
|||||||
projectStatus: {
|
projectStatus: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The created project status',
|
description: 'The created project status',
|
||||||
|
properties: PROJECT_STATUS_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearCreateWorkflowStateParams,
|
LinearCreateWorkflowStateParams,
|
||||||
LinearCreateWorkflowStateResponse,
|
LinearCreateWorkflowStateResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { WORKFLOW_STATE_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearCreateWorkflowStateTool: ToolConfig<
|
export const linearCreateWorkflowStateTool: ToolConfig<
|
||||||
@@ -94,9 +95,13 @@ export const linearCreateWorkflowStateTool: ToolConfig<
|
|||||||
workflowState {
|
workflowState {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
description
|
||||||
type
|
type
|
||||||
color
|
color
|
||||||
position
|
position
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
archivedAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -144,14 +149,7 @@ export const linearCreateWorkflowStateTool: ToolConfig<
|
|||||||
state: {
|
state: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The created workflow state',
|
description: 'The created workflow state',
|
||||||
properties: {
|
properties: WORKFLOW_STATE_OUTPUT_PROPERTIES,
|
||||||
id: { type: 'string', description: 'State ID' },
|
|
||||||
name: { type: 'string', description: 'State name' },
|
|
||||||
type: { type: 'string', description: 'State type' },
|
|
||||||
color: { type: 'string', description: 'State color' },
|
|
||||||
position: { type: 'number', description: 'State position' },
|
|
||||||
team: { type: 'object', description: 'Team this state belongs to' },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { LinearGetActiveCycleParams, LinearGetActiveCycleResponse } from '@/tools/linear/types'
|
import type { LinearGetActiveCycleParams, LinearGetActiveCycleResponse } from '@/tools/linear/types'
|
||||||
|
import { CYCLE_FULL_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearGetActiveCycleTool: ToolConfig<
|
export const linearGetActiveCycleTool: ToolConfig<
|
||||||
@@ -48,6 +49,7 @@ export const linearGetActiveCycleTool: ToolConfig<
|
|||||||
endsAt
|
endsAt
|
||||||
completedAt
|
completedAt
|
||||||
progress
|
progress
|
||||||
|
createdAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -93,15 +95,7 @@ export const linearGetActiveCycleTool: ToolConfig<
|
|||||||
cycle: {
|
cycle: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The active cycle (null if no active cycle)',
|
description: 'The active cycle (null if no active cycle)',
|
||||||
properties: {
|
properties: CYCLE_FULL_OUTPUT_PROPERTIES,
|
||||||
id: { type: 'string', description: 'Cycle ID' },
|
|
||||||
number: { type: 'number', description: 'Cycle number' },
|
|
||||||
name: { type: 'string', description: 'Cycle name' },
|
|
||||||
startsAt: { type: 'string', description: 'Start date' },
|
|
||||||
endsAt: { type: 'string', description: 'End date' },
|
|
||||||
progress: { type: 'number', description: 'Progress percentage' },
|
|
||||||
team: { type: 'object', description: 'Team this cycle belongs to' },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,12 @@ export const linearGetCustomerTool: ToolConfig<LinearGetCustomerParams, LinearGe
|
|||||||
domains
|
domains
|
||||||
externalIds
|
externalIds
|
||||||
logoUrl
|
logoUrl
|
||||||
|
slugId
|
||||||
approximateNeedCount
|
approximateNeedCount
|
||||||
|
revenue
|
||||||
|
size
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export const linearGetCycleTool: ToolConfig<LinearGetCycleParams, LinearGetCycle
|
|||||||
endsAt
|
endsAt
|
||||||
completedAt
|
completedAt
|
||||||
progress
|
progress
|
||||||
|
createdAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export const linearListCustomerRequestsTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: {
|
variables: {
|
||||||
first: params.first || 50,
|
first: params.first ? Number(params.first) : 50,
|
||||||
after: params.after,
|
after: params.after,
|
||||||
includeArchived: params.includeArchived || false,
|
includeArchived: params.includeArchived || false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type {
|
|||||||
LinearListCustomerStatusesParams,
|
LinearListCustomerStatusesParams,
|
||||||
LinearListCustomerStatusesResponse,
|
LinearListCustomerStatusesResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
import { CUSTOMER_STATUS_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
import { CUSTOMER_STATUS_OUTPUT_PROPERTIES, PAGE_INFO_OUTPUT } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearListCustomerStatusesTool: ToolConfig<
|
export const linearListCustomerStatusesTool: ToolConfig<
|
||||||
@@ -19,7 +19,20 @@ export const linearListCustomerStatusesTool: ToolConfig<
|
|||||||
provider: 'linear',
|
provider: 'linear',
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {},
|
params: {
|
||||||
|
first: {
|
||||||
|
type: 'number',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Number of statuses to return (default: 50)',
|
||||||
|
},
|
||||||
|
after: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Cursor for pagination',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
request: {
|
request: {
|
||||||
url: 'https://api.linear.app/graphql',
|
url: 'https://api.linear.app/graphql',
|
||||||
@@ -33,23 +46,32 @@ export const linearListCustomerStatusesTool: ToolConfig<
|
|||||||
Authorization: `Bearer ${params.accessToken}`,
|
Authorization: `Bearer ${params.accessToken}`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
body: () => ({
|
body: (params) => ({
|
||||||
query: `
|
query: `
|
||||||
query CustomerStatuses {
|
query CustomerStatuses($first: Int, $after: String) {
|
||||||
customerStatuses {
|
customerStatuses(first: $first, after: $after) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
displayName
|
|
||||||
description
|
description
|
||||||
color
|
color
|
||||||
position
|
position
|
||||||
|
type
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
variables: {
|
||||||
|
first: params.first ? Number(params.first) : 50,
|
||||||
|
after: params.after,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -64,10 +86,15 @@ export const linearListCustomerStatusesTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = data.data.customerStatuses
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
customerStatuses: data.data.customerStatuses.nodes,
|
customerStatuses: result.nodes,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: result.pageInfo.hasNextPage,
|
||||||
|
endCursor: result.pageInfo.endCursor,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -81,5 +108,6 @@ export const linearListCustomerStatusesTool: ToolConfig<
|
|||||||
properties: CUSTOMER_STATUS_OUTPUT_PROPERTIES,
|
properties: CUSTOMER_STATUS_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
pageInfo: PAGE_INFO_OUTPUT,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import type {
|
|||||||
LinearListCustomerTiersParams,
|
LinearListCustomerTiersParams,
|
||||||
LinearListCustomerTiersResponse,
|
LinearListCustomerTiersResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
import { CUSTOMER_TIER_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
import { CUSTOMER_TIER_OUTPUT_PROPERTIES, PAGE_INFO_OUTPUT } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearListCustomerTiersTool: ToolConfig<
|
export const linearListCustomerTiersTool: ToolConfig<
|
||||||
@@ -19,7 +19,20 @@ export const linearListCustomerTiersTool: ToolConfig<
|
|||||||
provider: 'linear',
|
provider: 'linear',
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {},
|
params: {
|
||||||
|
first: {
|
||||||
|
type: 'number',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Number of tiers to return (default: 50)',
|
||||||
|
},
|
||||||
|
after: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Cursor for pagination',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
request: {
|
request: {
|
||||||
url: 'https://api.linear.app/graphql',
|
url: 'https://api.linear.app/graphql',
|
||||||
@@ -33,10 +46,10 @@ export const linearListCustomerTiersTool: ToolConfig<
|
|||||||
Authorization: `Bearer ${params.accessToken}`,
|
Authorization: `Bearer ${params.accessToken}`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
body: () => ({
|
body: (params) => ({
|
||||||
query: `
|
query: `
|
||||||
query CustomerTiers {
|
query CustomerTiers($first: Int, $after: String) {
|
||||||
customerTiers {
|
customerTiers(first: $first, after: $after) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -47,9 +60,17 @@ export const linearListCustomerTiersTool: ToolConfig<
|
|||||||
createdAt
|
createdAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
variables: {
|
||||||
|
first: params.first ? Number(params.first) : 50,
|
||||||
|
after: params.after,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -64,10 +85,15 @@ export const linearListCustomerTiersTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = data.data.customerTiers
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
customerTiers: data.data.customerTiers.nodes,
|
customerTiers: result.nodes,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: result.pageInfo.hasNextPage,
|
||||||
|
endCursor: result.pageInfo.endCursor,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -81,5 +107,6 @@ export const linearListCustomerTiersTool: ToolConfig<
|
|||||||
properties: CUSTOMER_TIER_OUTPUT_PROPERTIES,
|
properties: CUSTOMER_TIER_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
pageInfo: PAGE_INFO_OUTPUT,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,8 +59,12 @@ export const linearListCustomersTool: ToolConfig<
|
|||||||
domains
|
domains
|
||||||
externalIds
|
externalIds
|
||||||
logoUrl
|
logoUrl
|
||||||
|
slugId
|
||||||
approximateNeedCount
|
approximateNeedCount
|
||||||
|
revenue
|
||||||
|
size
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
pageInfo {
|
pageInfo {
|
||||||
@@ -71,7 +75,7 @@ export const linearListCustomersTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: {
|
variables: {
|
||||||
first: params.first || 50,
|
first: params.first ? Number(params.first) : 50,
|
||||||
after: params.after,
|
after: params.after,
|
||||||
includeArchived: params.includeArchived || false,
|
includeArchived: params.includeArchived || false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ export const linearListCyclesTool: ToolConfig<LinearListCyclesParams, LinearList
|
|||||||
endsAt
|
endsAt
|
||||||
completedAt
|
completedAt
|
||||||
progress
|
progress
|
||||||
|
createdAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -61,6 +61,10 @@ export const linearListLabelsTool: ToolConfig<LinearListLabelsParams, LinearList
|
|||||||
name
|
name
|
||||||
color
|
color
|
||||||
description
|
description
|
||||||
|
isGroup
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
archivedAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearListProjectLabelsParams,
|
LinearListProjectLabelsParams,
|
||||||
LinearListProjectLabelsResponse,
|
LinearListProjectLabelsResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PAGE_INFO_OUTPUT, PROJECT_LABEL_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearListProjectLabelsTool: ToolConfig<
|
export const linearListProjectLabelsTool: ToolConfig<
|
||||||
@@ -25,6 +26,18 @@ export const linearListProjectLabelsTool: ToolConfig<
|
|||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Optional project ID to filter labels for a specific project',
|
description: 'Optional project ID to filter labels for a specific project',
|
||||||
},
|
},
|
||||||
|
first: {
|
||||||
|
type: 'number',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Number of labels to return (default: 50)',
|
||||||
|
},
|
||||||
|
after: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Cursor for pagination',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
request: {
|
request: {
|
||||||
@@ -40,15 +53,14 @@ export const linearListProjectLabelsTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
body: (params) => {
|
body: (params) => {
|
||||||
// If projectId is provided, query the specific project's labels
|
|
||||||
if (params.projectId?.trim()) {
|
if (params.projectId?.trim()) {
|
||||||
return {
|
return {
|
||||||
query: `
|
query: `
|
||||||
query ProjectWithLabels($id: String!) {
|
query ProjectWithLabels($id: String!, $first: Int, $after: String) {
|
||||||
project(id: $id) {
|
project(id: $id) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
labels {
|
labels(first: $first, after: $after) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -56,23 +68,29 @@ export const linearListProjectLabelsTool: ToolConfig<
|
|||||||
color
|
color
|
||||||
isGroup
|
isGroup
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: {
|
variables: {
|
||||||
id: params.projectId.trim(),
|
id: params.projectId.trim(),
|
||||||
|
first: params.first ? Number(params.first) : 50,
|
||||||
|
after: params.after,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, list all project labels
|
|
||||||
return {
|
return {
|
||||||
query: `
|
query: `
|
||||||
query ProjectLabels {
|
query ProjectLabels($first: Int, $after: String) {
|
||||||
projectLabels {
|
projectLabels(first: $first, after: $after) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -80,11 +98,20 @@ export const linearListProjectLabelsTool: ToolConfig<
|
|||||||
color
|
color
|
||||||
isGroup
|
isGroup
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
variables: {
|
||||||
|
first: params.first ? Number(params.first) : 50,
|
||||||
|
after: params.after,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -100,21 +127,29 @@ export const linearListProjectLabelsTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle project-specific query response
|
|
||||||
if (data.data.project) {
|
if (data.data.project) {
|
||||||
|
const result = data.data.project.labels
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
projectLabels: data.data.project.labels.nodes,
|
projectLabels: result.nodes,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: result.pageInfo.hasNextPage,
|
||||||
|
endCursor: result.pageInfo.endCursor,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle global projectLabels query response
|
const result = data.data.projectLabels
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
projectLabels: data.data.projectLabels.nodes,
|
projectLabels: result.nodes,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: result.pageInfo.hasNextPage,
|
||||||
|
endCursor: result.pageInfo.endCursor,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -123,6 +158,11 @@ export const linearListProjectLabelsTool: ToolConfig<
|
|||||||
projectLabels: {
|
projectLabels: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
description: 'List of project labels',
|
description: 'List of project labels',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
properties: PROJECT_LABEL_OUTPUT_PROPERTIES,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
pageInfo: PAGE_INFO_OUTPUT,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearListProjectMilestonesParams,
|
LinearListProjectMilestonesParams,
|
||||||
LinearListProjectMilestonesResponse,
|
LinearListProjectMilestonesResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PAGE_INFO_OUTPUT, PROJECT_MILESTONE_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearListProjectMilestonesTool: ToolConfig<
|
export const linearListProjectMilestonesTool: ToolConfig<
|
||||||
@@ -25,6 +26,18 @@ export const linearListProjectMilestonesTool: ToolConfig<
|
|||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Project ID to list milestones for',
|
description: 'Project ID to list milestones for',
|
||||||
},
|
},
|
||||||
|
first: {
|
||||||
|
type: 'number',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Number of milestones to return (default: 50)',
|
||||||
|
},
|
||||||
|
after: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Cursor for pagination',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
request: {
|
request: {
|
||||||
@@ -41,17 +54,26 @@ export const linearListProjectMilestonesTool: ToolConfig<
|
|||||||
},
|
},
|
||||||
body: (params) => ({
|
body: (params) => ({
|
||||||
query: `
|
query: `
|
||||||
query Project($id: String!) {
|
query Project($id: String!, $first: Int, $after: String) {
|
||||||
project(id: $id) {
|
project(id: $id) {
|
||||||
projectMilestones {
|
projectMilestones(first: $first, after: $after) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
description
|
description
|
||||||
projectId
|
|
||||||
targetDate
|
targetDate
|
||||||
|
progress
|
||||||
|
sortOrder
|
||||||
|
status
|
||||||
createdAt
|
createdAt
|
||||||
archivedAt
|
archivedAt
|
||||||
|
project {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,6 +81,8 @@ export const linearListProjectMilestonesTool: ToolConfig<
|
|||||||
`,
|
`,
|
||||||
variables: {
|
variables: {
|
||||||
id: params.projectId,
|
id: params.projectId,
|
||||||
|
first: params.first ? Number(params.first) : 50,
|
||||||
|
after: params.after,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
@@ -74,10 +98,20 @@ export const linearListProjectMilestonesTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = data.data.project?.projectMilestones
|
||||||
|
const milestones = (result?.nodes || []).map((node: Record<string, unknown>) => ({
|
||||||
|
...node,
|
||||||
|
projectId: (node.project as Record<string, string>)?.id ?? null,
|
||||||
|
project: undefined,
|
||||||
|
}))
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
projectMilestones: data.data.project?.projectMilestones?.nodes || [],
|
projectMilestones: milestones,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: result?.pageInfo?.hasNextPage ?? false,
|
||||||
|
endCursor: result?.pageInfo?.endCursor,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -86,6 +120,11 @@ export const linearListProjectMilestonesTool: ToolConfig<
|
|||||||
projectMilestones: {
|
projectMilestones: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
description: 'List of project milestones',
|
description: 'List of project milestones',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
properties: PROJECT_MILESTONE_OUTPUT_PROPERTIES,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
pageInfo: PAGE_INFO_OUTPUT,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearListProjectStatusesParams,
|
LinearListProjectStatusesParams,
|
||||||
LinearListProjectStatusesResponse,
|
LinearListProjectStatusesResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PAGE_INFO_OUTPUT, PROJECT_STATUS_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearListProjectStatusesTool: ToolConfig<
|
export const linearListProjectStatusesTool: ToolConfig<
|
||||||
@@ -18,7 +19,20 @@ export const linearListProjectStatusesTool: ToolConfig<
|
|||||||
provider: 'linear',
|
provider: 'linear',
|
||||||
},
|
},
|
||||||
|
|
||||||
params: {},
|
params: {
|
||||||
|
first: {
|
||||||
|
type: 'number',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Number of statuses to return (default: 50)',
|
||||||
|
},
|
||||||
|
after: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Cursor for pagination',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
request: {
|
request: {
|
||||||
url: 'https://api.linear.app/graphql',
|
url: 'https://api.linear.app/graphql',
|
||||||
@@ -32,10 +46,10 @@ export const linearListProjectStatusesTool: ToolConfig<
|
|||||||
Authorization: `Bearer ${params.accessToken}`,
|
Authorization: `Bearer ${params.accessToken}`,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
body: () => ({
|
body: (params) => ({
|
||||||
query: `
|
query: `
|
||||||
query ProjectStatuses {
|
query ProjectStatuses($first: Int, $after: String) {
|
||||||
projectStatuses {
|
projectStatuses(first: $first, after: $after) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -43,12 +57,22 @@ export const linearListProjectStatusesTool: ToolConfig<
|
|||||||
color
|
color
|
||||||
indefinite
|
indefinite
|
||||||
position
|
position
|
||||||
|
type
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
|
variables: {
|
||||||
|
first: params.first ? Number(params.first) : 50,
|
||||||
|
after: params.after,
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -63,10 +87,15 @@ export const linearListProjectStatusesTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const result = data.data.projectStatuses
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
projectStatuses: data.data.projectStatuses.nodes,
|
projectStatuses: result.nodes,
|
||||||
|
pageInfo: {
|
||||||
|
hasNextPage: result.pageInfo.hasNextPage,
|
||||||
|
endCursor: result.pageInfo.endCursor,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -75,6 +104,11 @@ export const linearListProjectStatusesTool: ToolConfig<
|
|||||||
projectStatuses: {
|
projectStatuses: {
|
||||||
type: 'array',
|
type: 'array',
|
||||||
description: 'List of project statuses',
|
description: 'List of project statuses',
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
properties: PROJECT_STATUS_OUTPUT_PROPERTIES,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
pageInfo: PAGE_INFO_OUTPUT,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export const linearListProjectsTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: {
|
variables: {
|
||||||
first: params.first || 50,
|
first: params.first ? Number(params.first) : 50,
|
||||||
after: params.after,
|
after: params.after,
|
||||||
includeArchived: params.includeArchived || false,
|
includeArchived: params.includeArchived || false,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -65,9 +65,13 @@ export const linearListWorkflowStatesTool: ToolConfig<
|
|||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
description
|
||||||
type
|
type
|
||||||
color
|
color
|
||||||
position
|
position
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
archivedAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ export const linearSearchIssuesTool: ToolConfig<
|
|||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Number of results to return (default: 50)',
|
description: 'Number of results to return (default: 50)',
|
||||||
},
|
},
|
||||||
|
after: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Cursor for pagination',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
request: {
|
request: {
|
||||||
@@ -63,8 +69,8 @@ export const linearSearchIssuesTool: ToolConfig<
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
query: `
|
query: `
|
||||||
query SearchIssues($term: String!, $filter: IssueFilter, $first: Int, $includeArchived: Boolean) {
|
query SearchIssues($term: String!, $filter: IssueFilter, $first: Int, $after: String, $includeArchived: Boolean) {
|
||||||
searchIssues(term: $term, filter: $filter, first: $first, includeArchived: $includeArchived) {
|
searchIssues(term: $term, filter: $filter, first: $first, after: $after, includeArchived: $includeArchived) {
|
||||||
nodes {
|
nodes {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
@@ -111,7 +117,8 @@ export const linearSearchIssuesTool: ToolConfig<
|
|||||||
variables: {
|
variables: {
|
||||||
term: params.query,
|
term: params.query,
|
||||||
filter: Object.keys(filter).length > 0 ? filter : undefined,
|
filter: Object.keys(filter).length > 0 ? filter : undefined,
|
||||||
first: params.first || 50,
|
first: params.first ? Number(params.first) : 50,
|
||||||
|
after: params.after,
|
||||||
includeArchived: params.includeArchived || false,
|
includeArchived: params.includeArchived || false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,6 +112,10 @@ export const LABEL_FULL_OUTPUT_PROPERTIES = {
|
|||||||
name: { type: 'string', description: 'Label name' },
|
name: { type: 'string', description: 'Label name' },
|
||||||
color: { type: 'string', description: 'Label color (hex)' },
|
color: { type: 'string', description: 'Label color (hex)' },
|
||||||
description: { type: 'string', description: 'Label description' },
|
description: { type: 'string', description: 'Label description' },
|
||||||
|
isGroup: { type: 'boolean', description: 'Whether this label is a group' },
|
||||||
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
|
updatedAt: { type: 'string', description: 'Last update timestamp (ISO 8601)' },
|
||||||
|
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
||||||
team: TEAM_OUTPUT,
|
team: TEAM_OUTPUT,
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
|
|
||||||
@@ -144,6 +148,7 @@ export const CYCLE_FULL_OUTPUT_PROPERTIES = {
|
|||||||
endsAt: { type: 'string', description: 'End date (ISO 8601)' },
|
endsAt: { type: 'string', description: 'End date (ISO 8601)' },
|
||||||
completedAt: { type: 'string', description: 'Completion date (ISO 8601)' },
|
completedAt: { type: 'string', description: 'Completion date (ISO 8601)' },
|
||||||
progress: { type: 'number', description: 'Progress percentage (0-1)' },
|
progress: { type: 'number', description: 'Progress percentage (0-1)' },
|
||||||
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
team: TEAM_OUTPUT,
|
team: TEAM_OUTPUT,
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
|
|
||||||
@@ -277,9 +282,16 @@ export const ATTACHMENT_OUTPUT_PROPERTIES = {
|
|||||||
export const WORKFLOW_STATE_OUTPUT_PROPERTIES = {
|
export const WORKFLOW_STATE_OUTPUT_PROPERTIES = {
|
||||||
id: { type: 'string', description: 'State ID' },
|
id: { type: 'string', description: 'State ID' },
|
||||||
name: { type: 'string', description: 'State name (e.g., "Todo", "In Progress")' },
|
name: { type: 'string', description: 'State name (e.g., "Todo", "In Progress")' },
|
||||||
type: { type: 'string', description: 'State type (unstarted, started, completed, canceled)' },
|
description: { type: 'string', description: 'State description' },
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'State type (triage, backlog, unstarted, started, completed, canceled)',
|
||||||
|
},
|
||||||
color: { type: 'string', description: 'State color (hex)' },
|
color: { type: 'string', description: 'State color (hex)' },
|
||||||
position: { type: 'number', description: 'State position in workflow' },
|
position: { type: 'number', description: 'State position in workflow' },
|
||||||
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
|
updatedAt: { type: 'string', description: 'Last update timestamp (ISO 8601)' },
|
||||||
|
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
||||||
team: TEAM_OUTPUT,
|
team: TEAM_OUTPUT,
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
|
|
||||||
@@ -343,8 +355,12 @@ export const CUSTOMER_OUTPUT_PROPERTIES = {
|
|||||||
items: { type: 'string', description: 'External ID' },
|
items: { type: 'string', description: 'External ID' },
|
||||||
},
|
},
|
||||||
logoUrl: { type: 'string', description: 'Logo URL' },
|
logoUrl: { type: 'string', description: 'Logo URL' },
|
||||||
|
slugId: { type: 'string', description: 'Unique URL slug' },
|
||||||
approximateNeedCount: { type: 'number', description: 'Number of customer needs' },
|
approximateNeedCount: { type: 'number', description: 'Number of customer needs' },
|
||||||
|
revenue: { type: 'number', description: 'Annual revenue' },
|
||||||
|
size: { type: 'number', description: 'Organization size' },
|
||||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
|
updatedAt: { type: 'string', description: 'Last update timestamp (ISO 8601)' },
|
||||||
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
|
|
||||||
@@ -378,11 +394,12 @@ export const CUSTOMER_NEED_OUTPUT_PROPERTIES = {
|
|||||||
export const CUSTOMER_STATUS_OUTPUT_PROPERTIES = {
|
export const CUSTOMER_STATUS_OUTPUT_PROPERTIES = {
|
||||||
id: { type: 'string', description: 'Customer status ID' },
|
id: { type: 'string', description: 'Customer status ID' },
|
||||||
name: { type: 'string', description: 'Status name' },
|
name: { type: 'string', description: 'Status name' },
|
||||||
displayName: { type: 'string', description: 'Display name' },
|
|
||||||
description: { type: 'string', description: 'Status description' },
|
description: { type: 'string', description: 'Status description' },
|
||||||
color: { type: 'string', description: 'Status color (hex)' },
|
color: { type: 'string', description: 'Status color (hex)' },
|
||||||
position: { type: 'number', description: 'Position in list' },
|
position: { type: 'number', description: 'Position in list' },
|
||||||
|
type: { type: 'string', description: 'Status type (active, inactive)' },
|
||||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
|
updatedAt: { type: 'string', description: 'Last updated timestamp (ISO 8601)' },
|
||||||
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
|
|
||||||
@@ -410,6 +427,7 @@ export const PROJECT_LABEL_OUTPUT_PROPERTIES = {
|
|||||||
color: { type: 'string', description: 'Label color (hex)' },
|
color: { type: 'string', description: 'Label color (hex)' },
|
||||||
isGroup: { type: 'boolean', description: 'Whether this label is a group' },
|
isGroup: { type: 'boolean', description: 'Whether this label is a group' },
|
||||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
|
updatedAt: { type: 'string', description: 'Last update timestamp (ISO 8601)' },
|
||||||
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
|
|
||||||
@@ -422,6 +440,9 @@ export const PROJECT_MILESTONE_OUTPUT_PROPERTIES = {
|
|||||||
description: { type: 'string', description: 'Milestone description' },
|
description: { type: 'string', description: 'Milestone description' },
|
||||||
projectId: { type: 'string', description: 'Project ID' },
|
projectId: { type: 'string', description: 'Project ID' },
|
||||||
targetDate: { type: 'string', description: 'Target date (YYYY-MM-DD)' },
|
targetDate: { type: 'string', description: 'Target date (YYYY-MM-DD)' },
|
||||||
|
progress: { type: 'number', description: 'Progress percentage (0-1)' },
|
||||||
|
sortOrder: { type: 'number', description: 'Sort order within the project' },
|
||||||
|
status: { type: 'string', description: 'Milestone status (done, next, overdue, unstarted)' },
|
||||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
@@ -444,7 +465,12 @@ export const PROJECT_STATUS_OUTPUT_PROPERTIES = {
|
|||||||
color: { type: 'string', description: 'Status color (hex)' },
|
color: { type: 'string', description: 'Status color (hex)' },
|
||||||
indefinite: { type: 'boolean', description: 'Whether this status is indefinite' },
|
indefinite: { type: 'boolean', description: 'Whether this status is indefinite' },
|
||||||
position: { type: 'number', description: 'Position in list' },
|
position: { type: 'number', description: 'Position in list' },
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Status type (backlog, planned, started, paused, completed, canceled)',
|
||||||
|
},
|
||||||
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
createdAt: { type: 'string', description: 'Creation timestamp (ISO 8601)' },
|
||||||
|
updatedAt: { type: 'string', description: 'Last updated timestamp (ISO 8601)' },
|
||||||
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
archivedAt: { type: 'string', description: 'Archive timestamp (ISO 8601)' },
|
||||||
} as const satisfies Record<string, OutputProperty>
|
} as const satisfies Record<string, OutputProperty>
|
||||||
|
|
||||||
@@ -587,6 +613,10 @@ export interface LinearLabel {
|
|||||||
name: string
|
name: string
|
||||||
color: string
|
color: string
|
||||||
description?: string
|
description?: string
|
||||||
|
isGroup: boolean
|
||||||
|
createdAt: string
|
||||||
|
updatedAt: string
|
||||||
|
archivedAt?: string
|
||||||
team?: {
|
team?: {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
@@ -596,9 +626,13 @@ export interface LinearLabel {
|
|||||||
export interface LinearWorkflowState {
|
export interface LinearWorkflowState {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
|
description?: string
|
||||||
type: string
|
type: string
|
||||||
color: string
|
color: string
|
||||||
position: number
|
position: number
|
||||||
|
createdAt: string
|
||||||
|
updatedAt: string
|
||||||
|
archivedAt?: string
|
||||||
team: {
|
team: {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
@@ -613,6 +647,7 @@ export interface LinearCycle {
|
|||||||
endsAt: string
|
endsAt: string
|
||||||
completedAt?: string
|
completedAt?: string
|
||||||
progress: number
|
progress: number
|
||||||
|
createdAt: string
|
||||||
team: {
|
team: {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
@@ -710,6 +745,7 @@ export interface LinearSearchIssuesParams {
|
|||||||
teamId?: string
|
teamId?: string
|
||||||
includeArchived?: boolean
|
includeArchived?: boolean
|
||||||
first?: number
|
first?: number
|
||||||
|
after?: string
|
||||||
accessToken?: string
|
accessToken?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1205,7 +1241,7 @@ export interface LinearAttachment {
|
|||||||
subtitle?: string
|
subtitle?: string
|
||||||
url: string
|
url: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
updatedAt?: string
|
updatedAt: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearCreateAttachmentResponse extends ToolResponse {
|
export interface LinearCreateAttachmentResponse extends ToolResponse {
|
||||||
@@ -1366,8 +1402,12 @@ export interface LinearCustomer {
|
|||||||
domains: string[]
|
domains: string[]
|
||||||
externalIds: string[]
|
externalIds: string[]
|
||||||
logoUrl?: string
|
logoUrl?: string
|
||||||
|
slugId: string
|
||||||
approximateNeedCount: number
|
approximateNeedCount: number
|
||||||
|
revenue?: number
|
||||||
|
size?: number
|
||||||
createdAt: string
|
createdAt: string
|
||||||
|
updatedAt: string
|
||||||
archivedAt?: string
|
archivedAt?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1542,11 +1582,12 @@ export interface LinearMergeCustomersResponse extends ToolResponse {
|
|||||||
export interface LinearCustomerStatus {
|
export interface LinearCustomerStatus {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
displayName: string
|
|
||||||
description?: string
|
description?: string
|
||||||
color: string
|
color: string
|
||||||
position: number
|
position: number
|
||||||
|
type: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
|
updatedAt: string
|
||||||
archivedAt?: string
|
archivedAt?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1593,12 +1634,18 @@ export interface LinearDeleteCustomerStatusResponse extends ToolResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListCustomerStatusesParams {
|
export interface LinearListCustomerStatusesParams {
|
||||||
|
first?: number
|
||||||
|
after?: string
|
||||||
accessToken?: string
|
accessToken?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListCustomerStatusesResponse extends ToolResponse {
|
export interface LinearListCustomerStatusesResponse extends ToolResponse {
|
||||||
output: {
|
output: {
|
||||||
customerStatuses?: LinearCustomerStatus[]
|
customerStatuses?: LinearCustomerStatus[]
|
||||||
|
pageInfo?: {
|
||||||
|
hasNextPage: boolean
|
||||||
|
endCursor?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1658,12 +1705,18 @@ export interface LinearDeleteCustomerTierResponse extends ToolResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListCustomerTiersParams {
|
export interface LinearListCustomerTiersParams {
|
||||||
|
first?: number
|
||||||
|
after?: string
|
||||||
accessToken?: string
|
accessToken?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListCustomerTiersResponse extends ToolResponse {
|
export interface LinearListCustomerTiersResponse extends ToolResponse {
|
||||||
output: {
|
output: {
|
||||||
customerTiers?: LinearCustomerTier[]
|
customerTiers?: LinearCustomerTier[]
|
||||||
|
pageInfo?: {
|
||||||
|
hasNextPage: boolean
|
||||||
|
endCursor?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1676,6 +1729,7 @@ export interface LinearProjectLabel {
|
|||||||
color?: string
|
color?: string
|
||||||
isGroup: boolean
|
isGroup: boolean
|
||||||
createdAt: string
|
createdAt: string
|
||||||
|
updatedAt: string
|
||||||
archivedAt?: string
|
archivedAt?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1720,13 +1774,19 @@ export interface LinearDeleteProjectLabelResponse extends ToolResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListProjectLabelsParams {
|
export interface LinearListProjectLabelsParams {
|
||||||
accessToken?: string
|
|
||||||
projectId?: string
|
projectId?: string
|
||||||
|
first?: number
|
||||||
|
after?: string
|
||||||
|
accessToken?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListProjectLabelsResponse extends ToolResponse {
|
export interface LinearListProjectLabelsResponse extends ToolResponse {
|
||||||
output: {
|
output: {
|
||||||
projectLabels?: LinearProjectLabel[]
|
projectLabels?: LinearProjectLabel[]
|
||||||
|
pageInfo?: {
|
||||||
|
hasNextPage: boolean
|
||||||
|
endCursor?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1764,6 +1824,9 @@ export interface LinearProjectMilestone {
|
|||||||
description?: string
|
description?: string
|
||||||
projectId: string
|
projectId: string
|
||||||
targetDate?: string
|
targetDate?: string
|
||||||
|
progress: number
|
||||||
|
sortOrder: number
|
||||||
|
status: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
archivedAt?: string
|
archivedAt?: string
|
||||||
}
|
}
|
||||||
@@ -1809,12 +1872,18 @@ export interface LinearDeleteProjectMilestoneResponse extends ToolResponse {
|
|||||||
|
|
||||||
export interface LinearListProjectMilestonesParams {
|
export interface LinearListProjectMilestonesParams {
|
||||||
projectId: string
|
projectId: string
|
||||||
|
first?: number
|
||||||
|
after?: string
|
||||||
accessToken?: string
|
accessToken?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListProjectMilestonesResponse extends ToolResponse {
|
export interface LinearListProjectMilestonesResponse extends ToolResponse {
|
||||||
output: {
|
output: {
|
||||||
projectMilestones?: LinearProjectMilestone[]
|
projectMilestones?: LinearProjectMilestone[]
|
||||||
|
pageInfo?: {
|
||||||
|
hasNextPage: boolean
|
||||||
|
endCursor?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1827,7 +1896,9 @@ export interface LinearProjectStatus {
|
|||||||
color: string
|
color: string
|
||||||
indefinite: boolean
|
indefinite: boolean
|
||||||
position: number
|
position: number
|
||||||
|
type: string
|
||||||
createdAt: string
|
createdAt: string
|
||||||
|
updatedAt: string
|
||||||
archivedAt?: string
|
archivedAt?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1875,12 +1946,18 @@ export interface LinearDeleteProjectStatusResponse extends ToolResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListProjectStatusesParams {
|
export interface LinearListProjectStatusesParams {
|
||||||
|
first?: number
|
||||||
|
after?: string
|
||||||
accessToken?: string
|
accessToken?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LinearListProjectStatusesResponse extends ToolResponse {
|
export interface LinearListProjectStatusesResponse extends ToolResponse {
|
||||||
output: {
|
output: {
|
||||||
projectStatuses?: LinearProjectStatus[]
|
projectStatuses?: LinearProjectStatus[]
|
||||||
|
pageInfo?: {
|
||||||
|
hasNextPage: boolean
|
||||||
|
endCursor?: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ export const linearUpdateAttachmentTool: ToolConfig<
|
|||||||
title
|
title
|
||||||
subtitle
|
subtitle
|
||||||
url
|
url
|
||||||
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,8 +137,12 @@ export const linearUpdateCustomerTool: ToolConfig<
|
|||||||
domains
|
domains
|
||||||
externalIds
|
externalIds
|
||||||
logoUrl
|
logoUrl
|
||||||
|
slugId
|
||||||
approximateNeedCount
|
approximateNeedCount
|
||||||
|
revenue
|
||||||
|
size
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearUpdateCustomerStatusParams,
|
LinearUpdateCustomerStatusParams,
|
||||||
LinearUpdateCustomerStatusResponse,
|
LinearUpdateCustomerStatusResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { CUSTOMER_STATUS_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearUpdateCustomerStatusTool: ToolConfig<
|
export const linearUpdateCustomerStatusTool: ToolConfig<
|
||||||
@@ -37,18 +38,18 @@ export const linearUpdateCustomerStatusTool: ToolConfig<
|
|||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Updated status color',
|
description: 'Updated status color',
|
||||||
},
|
},
|
||||||
displayName: {
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
visibility: 'user-or-llm',
|
|
||||||
description: 'Updated display name',
|
|
||||||
},
|
|
||||||
description: {
|
description: {
|
||||||
type: 'string',
|
type: 'string',
|
||||||
required: false,
|
required: false,
|
||||||
visibility: 'user-or-llm',
|
visibility: 'user-or-llm',
|
||||||
description: 'Updated description',
|
description: 'Updated description',
|
||||||
},
|
},
|
||||||
|
displayName: {
|
||||||
|
type: 'string',
|
||||||
|
required: false,
|
||||||
|
visibility: 'user-or-llm',
|
||||||
|
description: 'Updated display name',
|
||||||
|
},
|
||||||
position: {
|
position: {
|
||||||
type: 'number',
|
type: 'number',
|
||||||
required: false,
|
required: false,
|
||||||
@@ -78,12 +79,12 @@ export const linearUpdateCustomerStatusTool: ToolConfig<
|
|||||||
if (params.color != null && params.color !== '') {
|
if (params.color != null && params.color !== '') {
|
||||||
input.color = params.color
|
input.color = params.color
|
||||||
}
|
}
|
||||||
if (params.displayName != null && params.displayName !== '') {
|
|
||||||
input.displayName = params.displayName
|
|
||||||
}
|
|
||||||
if (params.description != null && params.description !== '') {
|
if (params.description != null && params.description !== '') {
|
||||||
input.description = params.description
|
input.description = params.description
|
||||||
}
|
}
|
||||||
|
if (params.displayName != null && params.displayName !== '') {
|
||||||
|
input.displayName = params.displayName
|
||||||
|
}
|
||||||
if (params.position != null) {
|
if (params.position != null) {
|
||||||
input.position = params.position
|
input.position = params.position
|
||||||
}
|
}
|
||||||
@@ -96,11 +97,12 @@ export const linearUpdateCustomerStatusTool: ToolConfig<
|
|||||||
customerStatus {
|
customerStatus {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
displayName
|
|
||||||
description
|
description
|
||||||
color
|
color
|
||||||
position
|
position
|
||||||
|
type
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,6 +140,7 @@ export const linearUpdateCustomerStatusTool: ToolConfig<
|
|||||||
customerStatus: {
|
customerStatus: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The updated customer status',
|
description: 'The updated customer status',
|
||||||
|
properties: CUSTOMER_STATUS_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,10 @@ export const linearUpdateLabelTool: ToolConfig<LinearUpdateLabelParams, LinearUp
|
|||||||
name
|
name
|
||||||
color
|
color
|
||||||
description
|
description
|
||||||
|
isGroup
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
archivedAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearUpdateProjectLabelParams,
|
LinearUpdateProjectLabelParams,
|
||||||
LinearUpdateProjectLabelResponse,
|
LinearUpdateProjectLabelResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PROJECT_LABEL_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearUpdateProjectLabelTool: ToolConfig<
|
export const linearUpdateProjectLabelTool: ToolConfig<
|
||||||
@@ -82,6 +83,7 @@ export const linearUpdateProjectLabelTool: ToolConfig<
|
|||||||
color
|
color
|
||||||
isGroup
|
isGroup
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,6 +121,7 @@ export const linearUpdateProjectLabelTool: ToolConfig<
|
|||||||
projectLabel: {
|
projectLabel: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The updated project label',
|
description: 'The updated project label',
|
||||||
|
properties: PROJECT_LABEL_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearUpdateProjectMilestoneParams,
|
LinearUpdateProjectMilestoneParams,
|
||||||
LinearUpdateProjectMilestoneResponse,
|
LinearUpdateProjectMilestoneResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PROJECT_MILESTONE_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearUpdateProjectMilestoneTool: ToolConfig<
|
export const linearUpdateProjectMilestoneTool: ToolConfig<
|
||||||
@@ -79,10 +80,15 @@ export const linearUpdateProjectMilestoneTool: ToolConfig<
|
|||||||
id
|
id
|
||||||
name
|
name
|
||||||
description
|
description
|
||||||
projectId
|
|
||||||
targetDate
|
targetDate
|
||||||
|
progress
|
||||||
|
sortOrder
|
||||||
|
status
|
||||||
createdAt
|
createdAt
|
||||||
archivedAt
|
archivedAt
|
||||||
|
project {
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,10 +113,23 @@ export const linearUpdateProjectMilestoneTool: ToolConfig<
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = data.data.projectMilestoneUpdate
|
const result = data.data.projectMilestoneUpdate
|
||||||
|
if (!result.success) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: 'Project milestone update was not successful',
|
||||||
|
output: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const milestone = result.projectMilestone
|
||||||
return {
|
return {
|
||||||
success: result.success,
|
success: true,
|
||||||
output: {
|
output: {
|
||||||
projectMilestone: result.projectMilestone,
|
projectMilestone: {
|
||||||
|
...milestone,
|
||||||
|
projectId: milestone.project?.id ?? null,
|
||||||
|
project: undefined,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -119,6 +138,7 @@ export const linearUpdateProjectMilestoneTool: ToolConfig<
|
|||||||
projectMilestone: {
|
projectMilestone: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The updated project milestone',
|
description: 'The updated project milestone',
|
||||||
|
properties: PROJECT_MILESTONE_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearUpdateProjectStatusParams,
|
LinearUpdateProjectStatusParams,
|
||||||
LinearUpdateProjectStatusResponse,
|
LinearUpdateProjectStatusResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { PROJECT_STATUS_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearUpdateProjectStatusTool: ToolConfig<
|
export const linearUpdateProjectStatusTool: ToolConfig<
|
||||||
@@ -100,7 +101,9 @@ export const linearUpdateProjectStatusTool: ToolConfig<
|
|||||||
color
|
color
|
||||||
indefinite
|
indefinite
|
||||||
position
|
position
|
||||||
|
type
|
||||||
createdAt
|
createdAt
|
||||||
|
updatedAt
|
||||||
archivedAt
|
archivedAt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -138,6 +141,7 @@ export const linearUpdateProjectStatusTool: ToolConfig<
|
|||||||
projectStatus: {
|
projectStatus: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The updated project status',
|
description: 'The updated project status',
|
||||||
|
properties: PROJECT_STATUS_OUTPUT_PROPERTIES,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type {
|
|||||||
LinearUpdateWorkflowStateParams,
|
LinearUpdateWorkflowStateParams,
|
||||||
LinearUpdateWorkflowStateResponse,
|
LinearUpdateWorkflowStateResponse,
|
||||||
} from '@/tools/linear/types'
|
} from '@/tools/linear/types'
|
||||||
|
import { WORKFLOW_STATE_OUTPUT_PROPERTIES } from '@/tools/linear/types'
|
||||||
import type { ToolConfig } from '@/tools/types'
|
import type { ToolConfig } from '@/tools/types'
|
||||||
|
|
||||||
export const linearUpdateWorkflowStateTool: ToolConfig<
|
export const linearUpdateWorkflowStateTool: ToolConfig<
|
||||||
@@ -87,9 +88,13 @@ export const linearUpdateWorkflowStateTool: ToolConfig<
|
|||||||
workflowState {
|
workflowState {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
description
|
||||||
type
|
type
|
||||||
color
|
color
|
||||||
position
|
position
|
||||||
|
createdAt
|
||||||
|
updatedAt
|
||||||
|
archivedAt
|
||||||
team {
|
team {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -138,13 +143,7 @@ export const linearUpdateWorkflowStateTool: ToolConfig<
|
|||||||
state: {
|
state: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
description: 'The updated workflow state',
|
description: 'The updated workflow state',
|
||||||
properties: {
|
properties: WORKFLOW_STATE_OUTPUT_PROPERTIES,
|
||||||
id: { type: 'string', description: 'State ID' },
|
|
||||||
name: { type: 'string', description: 'State name' },
|
|
||||||
type: { type: 'string', description: 'State type' },
|
|
||||||
color: { type: 'string', description: 'State color' },
|
|
||||||
position: { type: 'number', description: 'State position' },
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,27 @@ export const slackWebhookTrigger: TriggerConfig = {
|
|||||||
required: true,
|
required: true,
|
||||||
mode: 'trigger',
|
mode: 'trigger',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: 'botToken',
|
||||||
|
title: 'Bot Token',
|
||||||
|
type: 'short-input',
|
||||||
|
placeholder: 'xoxb-...',
|
||||||
|
description:
|
||||||
|
'The bot token from your Slack app. Required for downloading files attached to messages.',
|
||||||
|
password: true,
|
||||||
|
required: false,
|
||||||
|
mode: 'trigger',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'includeFiles',
|
||||||
|
title: 'Include File Attachments',
|
||||||
|
type: 'switch',
|
||||||
|
defaultValue: false,
|
||||||
|
description:
|
||||||
|
'Download and include file attachments from messages. Requires a bot token with files:read scope.',
|
||||||
|
required: false,
|
||||||
|
mode: 'trigger',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: 'triggerSave',
|
id: 'triggerSave',
|
||||||
title: '',
|
title: '',
|
||||||
@@ -46,9 +67,10 @@ export const slackWebhookTrigger: TriggerConfig = {
|
|||||||
'Go to <a href="https://api.slack.com/apps" target="_blank" rel="noopener noreferrer" class="text-muted-foreground underline transition-colors hover:text-muted-foreground/80">Slack Apps page</a>',
|
'Go to <a href="https://api.slack.com/apps" target="_blank" rel="noopener noreferrer" class="text-muted-foreground underline transition-colors hover:text-muted-foreground/80">Slack Apps page</a>',
|
||||||
'If you don\'t have an app:<br><ul class="mt-1 ml-5 list-disc"><li>Create an app from scratch</li><li>Give it a name and select your workspace</li></ul>',
|
'If you don\'t have an app:<br><ul class="mt-1 ml-5 list-disc"><li>Create an app from scratch</li><li>Give it a name and select your workspace</li></ul>',
|
||||||
'Go to "Basic Information", find the "Signing Secret", and paste it in the field above.',
|
'Go to "Basic Information", find the "Signing Secret", and paste it in the field above.',
|
||||||
'Go to "OAuth & Permissions" and add bot token scopes:<br><ul class="mt-1 ml-5 list-disc"><li><code>app_mentions:read</code> - For viewing messages that tag your bot with an @</li><li><code>chat:write</code> - To send messages to channels your bot is a part of</li></ul>',
|
'Go to "OAuth & Permissions" and add bot token scopes:<br><ul class="mt-1 ml-5 list-disc"><li><code>app_mentions:read</code> - For viewing messages that tag your bot with an @</li><li><code>chat:write</code> - To send messages to channels your bot is a part of</li><li><code>files:read</code> - To access files and images shared in messages</li></ul>',
|
||||||
'Go to "Event Subscriptions":<br><ul class="mt-1 ml-5 list-disc"><li>Enable events</li><li>Under "Subscribe to Bot Events", add <code>app_mention</code> to listen to messages that mention your bot</li><li>Paste the Webhook URL above into the "Request URL" field</li></ul>',
|
'Go to "Event Subscriptions":<br><ul class="mt-1 ml-5 list-disc"><li>Enable events</li><li>Under "Subscribe to Bot Events", add <code>app_mention</code> to listen to messages that mention your bot</li><li>Paste the Webhook URL above into the "Request URL" field</li></ul>',
|
||||||
'Go to "Install App" in the left sidebar and install the app into your desired Slack workspace and channel.',
|
'Go to "Install App" in the left sidebar and install the app into your desired Slack workspace and channel.',
|
||||||
|
'Copy the "Bot User OAuth Token" (starts with <code>xoxb-</code>) and paste it in the Bot Token field above to enable file downloads.',
|
||||||
'Save changes in both Slack and here.',
|
'Save changes in both Slack and here.',
|
||||||
]
|
]
|
||||||
.map(
|
.map(
|
||||||
@@ -106,6 +128,15 @@ export const slackWebhookTrigger: TriggerConfig = {
|
|||||||
type: 'string',
|
type: 'string',
|
||||||
description: 'Unique event identifier',
|
description: 'Unique event identifier',
|
||||||
},
|
},
|
||||||
|
hasFiles: {
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Whether the message has file attachments',
|
||||||
|
},
|
||||||
|
files: {
|
||||||
|
type: 'file[]',
|
||||||
|
description:
|
||||||
|
'File attachments downloaded from the message (if includeFiles is enabled and bot token is provided)',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user