mirror of
https://github.com/n8n-io/n8n.git
synced 2026-10-17 05:29:44 +02:00
Merge cf4de22c92 into d678c597e8
This commit is contained in:
commit
026ed3855c
10
docs/generated/postgres-schema/README.md
generated
10
docs/generated/postgres-schema/README.md
generated
|
|
@ -9,7 +9,7 @@ Auto-generated from the PostgreSQL migrations in @n8n/db. Do not edit by hand.
|
|||
| Name | Columns | Comment | Type |
|
||||
| ---- | ------- | ------- | ---- |
|
||||
| [public.activity_event](public.activity_event.md) | 11 | | BASE TABLE |
|
||||
| [public.agent_background_job](public.agent_background_job.md) | 20 | | BASE TABLE |
|
||||
| [public.agent_background_job](public.agent_background_job.md) | 23 | | BASE TABLE |
|
||||
| [public.agent_budget_applied_call](public.agent_budget_applied_call.md) | 2 | | BASE TABLE |
|
||||
| [public.agent_budget_spend](public.agent_budget_spend.md) | 4 | | BASE TABLE |
|
||||
| [public.agent_channel_status](public.agent_channel_status.md) | 11 | | BASE TABLE |
|
||||
|
|
@ -23,7 +23,7 @@ Auto-generated from the PostgreSQL migrations in @n8n/db. Do not edit by hand.
|
|||
| [public.agent_eval_run](public.agent_eval_run.md) | 14 | | BASE TABLE |
|
||||
| [public.agent_execution](public.agent_execution.md) | 23 | | BASE TABLE |
|
||||
| [public.agent_execution_message_links](public.agent_execution_message_links.md) | 5 | | BASE TABLE |
|
||||
| [public.agent_execution_threads](public.agent_execution_threads.md) | 19 | | BASE TABLE |
|
||||
| [public.agent_execution_threads](public.agent_execution_threads.md) | 20 | | BASE TABLE |
|
||||
| [public.agent_files](public.agent_files.md) | 10 | | BASE TABLE |
|
||||
| [public.agent_history](public.agent_history.md) | 9 | | BASE TABLE |
|
||||
| [public.agent_message_queue](public.agent_message_queue.md) | 10 | | BASE TABLE |
|
||||
|
|
@ -200,6 +200,8 @@ erDiagram
|
|||
"public.activity_event" }o--o| "public.user" : "FOREIGN KEY (#quot;userId#quot;) REFERENCES #quot;user#quot;(id) ON DELETE SET NULL"
|
||||
"public.activity_event" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE"
|
||||
"public.agent_background_job" }o--|| "public.agents" : "FOREIGN KEY (#quot;parentAgentId#quot;) REFERENCES agents(id) ON DELETE CASCADE"
|
||||
"public.agent_background_job" }o--o| "public.agent_execution" : "FOREIGN KEY (#quot;sourceExecutionId#quot;) REFERENCES agent_execution(id) ON DELETE SET NULL"
|
||||
"public.agent_background_job" }o--o| "public.agent_plan" : "FOREIGN KEY (#quot;planId#quot;) REFERENCES agent_plan(id) ON DELETE SET NULL"
|
||||
"public.agent_channel_status" }o--|| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE"
|
||||
"public.agent_chat_attachments" }o--|| "public.project" : "FOREIGN KEY (#quot;projectId#quot;) REFERENCES project(id) ON DELETE CASCADE"
|
||||
"public.agent_chat_attachments" }o--o| "public.agents" : "FOREIGN KEY (#quot;agentId#quot;) REFERENCES agents(id) ON DELETE CASCADE"
|
||||
|
|
@ -474,8 +476,11 @@ erDiagram
|
|||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
uuid pauseRequestId
|
||||
uuid planId FK
|
||||
uuid planTaskId
|
||||
text result
|
||||
timestamp_3__with_time_zone settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
timestamp_3__with_time_zone timeoutAt
|
||||
|
|
@ -643,6 +648,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -16,8 +16,11 @@
|
|||
| parentResourceId | varchar(255) | | false | | | Memory resource of the parent agent run |
|
||||
| parentThreadId | varchar(128) | | false | | | |
|
||||
| pauseRequestId | uuid | | true | | | Groups jobs stopped by one user request |
|
||||
| planId | uuid | | true | | [public.agent_plan](public.agent_plan.md) | Plan that owns this work |
|
||||
| planTaskId | uuid | | true | | | Task ID in the saved plan document |
|
||||
| result | text | | true | | | Final answer of a settled sub-agent job |
|
||||
| settledAt | timestamp(3) with time zone | | true | | | |
|
||||
| sourceExecutionId | varchar(36) | | true | | [public.agent_execution](public.agent_execution.md) | Execution that dispatched this job |
|
||||
| status | varchar(16) | | false | | | running: child works; suspended: child awaits approval; paused: user stopped the child; completed, failed, cancelled: terminal |
|
||||
| subAgentId | varchar(36) | | true | | | Sub-agent jobs only |
|
||||
| timeoutAt | timestamp(3) with time zone | | true | | | When reconciliation fails the job as timed out; NULL means no timeout |
|
||||
|
|
@ -31,6 +34,8 @@
|
|||
| ---- | ---- | ---------- |
|
||||
| CHK_agent_background_job_kind | CHECK | CHECK (((kind)::text = ANY ((ARRAY['subagent'::character varying, 'workflow'::character varying])::text[]))) |
|
||||
| CHK_agent_background_job_status | CHECK | CHECK (((status)::text = ANY ((ARRAY['running'::character varying, 'suspended'::character varying, 'paused'::character varying, 'completed'::character varying, 'failed'::character varying, 'cancelled'::character varying])::text[]))) |
|
||||
| FK_4db3b7ebea4ed4f69649982018c | FOREIGN KEY | FOREIGN KEY ("sourceExecutionId") REFERENCES agent_execution(id) ON DELETE SET NULL |
|
||||
| FK_ce131bff629d89015893e350e9c | FOREIGN KEY | FOREIGN KEY ("planId") REFERENCES agent_plan(id) ON DELETE SET NULL |
|
||||
| FK_d46c6f00730c2ef8bcb6ee24b67 | FOREIGN KEY | FOREIGN KEY ("parentAgentId") REFERENCES agents(id) ON DELETE CASCADE |
|
||||
| PK_6e0db58281aa2b4c956dc0d58e9 | PRIMARY KEY | PRIMARY KEY (id) |
|
||||
| agent_background_job_createdAt_not_null | n | NOT NULL "createdAt" |
|
||||
|
|
@ -51,6 +56,8 @@
|
|||
| IDX_93d62baabe9858816b5adafb44 | CREATE INDEX "IDX_93d62baabe9858816b5adafb44" ON public.agent_background_job USING btree ("parentThreadId", status) |
|
||||
| IDX_agent_background_job_childExecutionId | CREATE UNIQUE INDEX "IDX_agent_background_job_childExecutionId" ON public.agent_background_job USING btree ("childExecutionId") WHERE ("childExecutionId" IS NOT NULL) |
|
||||
| IDX_agent_background_job_parentThreadId | CREATE INDEX "IDX_agent_background_job_parentThreadId" ON public.agent_background_job USING btree ("parentThreadId") WHERE (((status)::text <> 'running'::text) AND ("notifiedAt" IS NULL)) |
|
||||
| IDX_agent_background_job_planId_planTaskId | CREATE INDEX "IDX_agent_background_job_planId_planTaskId" ON public.agent_background_job USING btree ("planId", "planTaskId") |
|
||||
| IDX_agent_background_job_sourceExecutionId | CREATE INDEX "IDX_agent_background_job_sourceExecutionId" ON public.agent_background_job USING btree ("sourceExecutionId") |
|
||||
| IDX_agent_background_job_timeoutAt | CREATE INDEX "IDX_agent_background_job_timeoutAt" ON public.agent_background_job USING btree ("timeoutAt") WHERE ((status)::text = ANY ((ARRAY['running'::character varying, 'suspended'::character varying])::text[])) |
|
||||
| IDX_d46c6f00730c2ef8bcb6ee24b6 | CREATE INDEX "IDX_d46c6f00730c2ef8bcb6ee24b6" ON public.agent_background_job USING btree ("parentAgentId") |
|
||||
| IDX_e43e630272995a93dfeb94ab3e | CREATE INDEX "IDX_e43e630272995a93dfeb94ab3e" ON public.agent_background_job USING btree ("settledAt") |
|
||||
|
|
@ -62,6 +69,8 @@
|
|||
erDiagram
|
||||
|
||||
"public.agent_background_job" }o--|| "public.agents" : "FOREIGN KEY (#quot;parentAgentId#quot;) REFERENCES agents(id) ON DELETE CASCADE"
|
||||
"public.agent_background_job" }o--o| "public.agent_plan" : "FOREIGN KEY (#quot;planId#quot;) REFERENCES agent_plan(id) ON DELETE SET NULL"
|
||||
"public.agent_background_job" }o--o| "public.agent_execution" : "FOREIGN KEY (#quot;sourceExecutionId#quot;) REFERENCES agent_execution(id) ON DELETE SET NULL"
|
||||
|
||||
"public.agent_background_job" {
|
||||
varchar_36_ childExecutionId
|
||||
|
|
@ -76,8 +85,11 @@ erDiagram
|
|||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
uuid pauseRequestId
|
||||
uuid planId FK
|
||||
uuid planTaskId
|
||||
text result
|
||||
timestamp_3__with_time_zone settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
timestamp_3__with_time_zone timeoutAt
|
||||
|
|
@ -102,6 +114,41 @@ erDiagram
|
|||
timestamp_3__with_time_zone updatedAt
|
||||
varchar_36_ versionId
|
||||
}
|
||||
"public.agent_plan" {
|
||||
timestamp_3__with_time_zone closedAt
|
||||
timestamp_3__with_time_zone createdAt
|
||||
json data
|
||||
integer formatVersion
|
||||
uuid id
|
||||
integer revision
|
||||
varchar_128_ threadId FK
|
||||
timestamp_3__with_time_zone updatedAt
|
||||
}
|
||||
"public.agent_execution" {
|
||||
boolean acceptsSteering
|
||||
json attachments
|
||||
json author
|
||||
integer completionTokens
|
||||
double_precision cost
|
||||
timestamp_3__with_time_zone createdAt
|
||||
integer duration
|
||||
text error
|
||||
json failureSummary
|
||||
varchar_16_ hitlStatus
|
||||
varchar_36_ id
|
||||
varchar_255_ model
|
||||
integer promptTokens
|
||||
varchar_32_ source
|
||||
timestamp_3__with_time_zone startedAt
|
||||
varchar_16_ status
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
varchar_128_ threadId FK
|
||||
json timeline
|
||||
integer totalTokens
|
||||
timestamp_3__with_time_zone updatedAt
|
||||
text userMessage
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
| error | text | | true | | | |
|
||||
| failureSummary | json | | true | | | Execution failure projection as {count, latest} for session list queries |
|
||||
| hitlStatus | varchar(16) | | true | | | |
|
||||
| id | varchar(36) | | false | [public.agent_execution_message_links](public.agent_execution_message_links.md) [public.agent_message_queue](public.agent_message_queue.md) | | |
|
||||
| id | varchar(36) | | false | [public.agent_background_job](public.agent_background_job.md) [public.agent_execution_message_links](public.agent_execution_message_links.md) [public.agent_message_queue](public.agent_message_queue.md) | | |
|
||||
| model | varchar(255) | | true | | | |
|
||||
| promptTokens | integer | | true | | | |
|
||||
| source | varchar(32) | | true | | | |
|
||||
|
|
@ -59,6 +59,7 @@
|
|||
```mermaid
|
||||
erDiagram
|
||||
|
||||
"public.agent_background_job" }o--o| "public.agent_execution" : "FOREIGN KEY (#quot;sourceExecutionId#quot;) REFERENCES agent_execution(id) ON DELETE SET NULL"
|
||||
"public.agent_execution_message_links" }o--|| "public.agent_execution" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES agent_execution(id) ON DELETE CASCADE"
|
||||
"public.agent_message_queue" }o--o| "public.agent_execution" : "FOREIGN KEY (#quot;executionId#quot;) REFERENCES agent_execution(id)"
|
||||
"public.agent_message_queue" }o--o| "public.agent_execution" : "FOREIGN KEY (#quot;steeringExecutionId#quot;) REFERENCES agent_execution(id)"
|
||||
|
|
@ -89,6 +90,31 @@ erDiagram
|
|||
timestamp_3__with_time_zone updatedAt
|
||||
text userMessage
|
||||
}
|
||||
"public.agent_background_job" {
|
||||
varchar_36_ childExecutionId
|
||||
varchar_128_ childThreadId
|
||||
timestamp_3__with_time_zone createdAt
|
||||
text error
|
||||
varchar_36_ id
|
||||
varchar_16_ kind
|
||||
timestamp_3__with_time_zone notifiedAt
|
||||
varchar_36_ parentAgentId FK
|
||||
varchar_64_ parentPrincipalHash
|
||||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
uuid pauseRequestId
|
||||
uuid planId FK
|
||||
uuid planTaskId
|
||||
text result
|
||||
timestamp_3__with_time_zone settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
timestamp_3__with_time_zone timeoutAt
|
||||
varchar_255_ title
|
||||
timestamp_3__with_time_zone updatedAt
|
||||
varchar_36_ workflowId
|
||||
}
|
||||
"public.agent_execution_message_links" {
|
||||
timestamp_3__with_time_zone createdAt
|
||||
varchar_6_ direction
|
||||
|
|
@ -121,6 +147,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
| projectId | varchar(255) | | false | | [public.project](public.project.md) | |
|
||||
| sessionNumber | integer | 0 | false | | | |
|
||||
| taskId | varchar(32) | | true | | | Published task ID that triggered this session; not an FK because published runs can outlive draft task definition rows |
|
||||
| taskStop | json | | true | | | Latest task stop boundary and unresolved stop errors |
|
||||
| taskVersionId | varchar(36) | | true | | [public.agent_history](public.agent_history.md) | Published agent_history version that supplied the task snapshot |
|
||||
| title | varchar(255) | | true | | | |
|
||||
| totalCompletionTokens | integer | 0 | false | | | |
|
||||
|
|
@ -84,6 +85,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
29
docs/generated/postgres-schema/public.agent_plan.md
generated
29
docs/generated/postgres-schema/public.agent_plan.md
generated
|
|
@ -8,7 +8,7 @@
|
|||
| createdAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | |
|
||||
| data | json | | false | | | Opaque plan document |
|
||||
| formatVersion | integer | | false | | | Version of the plan JSON format |
|
||||
| id | uuid | | false | [public.agent_plan_history](public.agent_plan_history.md) | | Plan ID generated by the caller |
|
||||
| id | uuid | | false | [public.agent_background_job](public.agent_background_job.md) [public.agent_plan_history](public.agent_plan_history.md) | | Plan ID generated by the caller |
|
||||
| revision | integer | 1 | false | | | Current document revision |
|
||||
| threadId | varchar(128) | | false | | [public.agent_execution_threads](public.agent_execution_threads.md) | Session that owns the plan |
|
||||
| updatedAt | timestamp(3) with time zone | CURRENT_TIMESTAMP(3) | false | | | |
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
```mermaid
|
||||
erDiagram
|
||||
|
||||
"public.agent_background_job" }o--o| "public.agent_plan" : "FOREIGN KEY (#quot;planId#quot;) REFERENCES agent_plan(id) ON DELETE SET NULL"
|
||||
"public.agent_plan_history" }o--|| "public.agent_plan" : "FOREIGN KEY (#quot;planId#quot;) REFERENCES agent_plan(id) ON DELETE CASCADE"
|
||||
"public.agent_plan" }o--|| "public.agent_execution_threads" : "FOREIGN KEY (#quot;threadId#quot;) REFERENCES agent_execution_threads(id) ON DELETE CASCADE"
|
||||
|
||||
|
|
@ -55,6 +56,31 @@ erDiagram
|
|||
varchar_128_ threadId FK
|
||||
timestamp_3__with_time_zone updatedAt
|
||||
}
|
||||
"public.agent_background_job" {
|
||||
varchar_36_ childExecutionId
|
||||
varchar_128_ childThreadId
|
||||
timestamp_3__with_time_zone createdAt
|
||||
text error
|
||||
varchar_36_ id
|
||||
varchar_16_ kind
|
||||
timestamp_3__with_time_zone notifiedAt
|
||||
varchar_36_ parentAgentId FK
|
||||
varchar_64_ parentPrincipalHash
|
||||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
uuid pauseRequestId
|
||||
uuid planId FK
|
||||
uuid planTaskId
|
||||
text result
|
||||
timestamp_3__with_time_zone settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
timestamp_3__with_time_zone timeoutAt
|
||||
varchar_255_ title
|
||||
timestamp_3__with_time_zone updatedAt
|
||||
varchar_36_ workflowId
|
||||
}
|
||||
"public.agent_plan_history" {
|
||||
timestamp_3__with_time_zone closedAt
|
||||
timestamp_3__with_time_zone createdAt
|
||||
|
|
@ -76,6 +102,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
4
docs/generated/postgres-schema/public.agents.md
generated
4
docs/generated/postgres-schema/public.agents.md
generated
|
|
@ -119,8 +119,11 @@ erDiagram
|
|||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
uuid pauseRequestId
|
||||
uuid planId FK
|
||||
uuid planTaskId
|
||||
text result
|
||||
timestamp_3__with_time_zone settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
timestamp_3__with_time_zone timeoutAt
|
||||
|
|
@ -202,6 +205,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
1
docs/generated/postgres-schema/public.project.md
generated
1
docs/generated/postgres-schema/public.project.md
generated
|
|
@ -130,6 +130,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
1
docs/generated/postgres-schema/public.user.md
generated
1
docs/generated/postgres-schema/public.user.md
generated
|
|
@ -178,6 +178,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
integer sessionNumber
|
||||
varchar_32_ taskId
|
||||
json taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
integer totalCompletionTokens
|
||||
|
|
|
|||
10
docs/generated/sqlite-schema/README.md
generated
10
docs/generated/sqlite-schema/README.md
generated
|
|
@ -9,7 +9,7 @@ Auto-generated from the SQLite migrations in @n8n/db. Do not edit by hand.
|
|||
| Name | Columns | Comment | Type |
|
||||
| ---- | ------- | ------- | ---- |
|
||||
| [activity_event](activity_event.md) | 11 | | table |
|
||||
| [agent_background_job](agent_background_job.md) | 20 | | table |
|
||||
| [agent_background_job](agent_background_job.md) | 23 | | table |
|
||||
| [agent_budget_applied_call](agent_budget_applied_call.md) | 2 | | table |
|
||||
| [agent_budget_spend](agent_budget_spend.md) | 4 | | table |
|
||||
| [agent_channel_status](agent_channel_status.md) | 11 | | table |
|
||||
|
|
@ -23,7 +23,7 @@ Auto-generated from the SQLite migrations in @n8n/db. Do not edit by hand.
|
|||
| [agent_eval_run](agent_eval_run.md) | 14 | | table |
|
||||
| [agent_execution](agent_execution.md) | 23 | | table |
|
||||
| [agent_execution_message_links](agent_execution_message_links.md) | 5 | | table |
|
||||
| [agent_execution_threads](agent_execution_threads.md) | 19 | | table |
|
||||
| [agent_execution_threads](agent_execution_threads.md) | 20 | | table |
|
||||
| [agent_files](agent_files.md) | 10 | | table |
|
||||
| [agent_history](agent_history.md) | 9 | | table |
|
||||
| [agent_message_queue](agent_message_queue.md) | 10 | | table |
|
||||
|
|
@ -181,6 +181,8 @@ erDiagram
|
|||
|
||||
"activity_event" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
"activity_event" }o--o| "user" : "FOREIGN KEY (userId) REFERENCES user (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE"
|
||||
"agent_background_job" }o--o| "agent_plan" : "FOREIGN KEY (planId) REFERENCES agent_plan (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE"
|
||||
"agent_background_job" }o--o| "agent_execution" : "FOREIGN KEY (sourceExecutionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE"
|
||||
"agent_background_job" }o--|| "agents" : "FOREIGN KEY (parentAgentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
"agent_channel_status" |o--|| "agents" : "FOREIGN KEY (agentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
"agent_chat_attachments" }o--|| "project" : "FOREIGN KEY (projectId) REFERENCES project (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
|
|
@ -460,8 +462,11 @@ erDiagram
|
|||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
varchar pauseRequestId
|
||||
varchar planId FK
|
||||
varchar planTaskId
|
||||
TEXT result
|
||||
datetime_3_ settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
datetime_3_ timeoutAt
|
||||
|
|
@ -629,6 +634,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
51
docs/generated/sqlite-schema/agent_background_job.md
generated
51
docs/generated/sqlite-schema/agent_background_job.md
generated
|
|
@ -6,7 +6,7 @@
|
|||
<summary><strong>Table Definition</strong></summary>
|
||||
|
||||
```sql
|
||||
CREATE TABLE "agent_background_job" ("id" varchar(36) PRIMARY KEY NOT NULL, "kind" varchar(16) NOT NULL, "status" varchar(16) NOT NULL, "parentAgentId" varchar(36) NOT NULL, "parentThreadId" varchar(128) NOT NULL, "title" varchar(255) NOT NULL, "subAgentId" varchar(36), "childThreadId" varchar(128), "childExecutionId" varchar(36), "workflowId" varchar(36), "timeoutAt" datetime(3), "result" text, "error" text, "settledAt" datetime(3), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "notifiedAt" datetime(3), "parentResourceId" varchar(255) NOT NULL, "parentPrincipalHash" varchar(64) NOT NULL, "pauseRequestId" varchar, CONSTRAINT "CHK_agent_background_job_kind" CHECK (((("kind" IN ('subagent', 'workflow'))))), CONSTRAINT "CHK_agent_background_job_status" CHECK ("status" IN ('running', 'suspended', 'paused', 'completed', 'failed', 'cancelled')), CONSTRAINT "FK_d46c6f00730c2ef8bcb6ee24b67" FOREIGN KEY ("parentAgentId") REFERENCES "agents" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)
|
||||
CREATE TABLE "agent_background_job" ("id" varchar(36) PRIMARY KEY NOT NULL, "kind" varchar(16) NOT NULL, "status" varchar(16) NOT NULL, "parentAgentId" varchar(36) NOT NULL, "parentThreadId" varchar(128) NOT NULL, "title" varchar(255) NOT NULL, "subAgentId" varchar(36), "childThreadId" varchar(128), "childExecutionId" varchar(36), "workflowId" varchar(36), "timeoutAt" datetime(3), "result" text, "error" text, "settledAt" datetime(3), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "notifiedAt" datetime(3), "parentResourceId" varchar(255) NOT NULL, "parentPrincipalHash" varchar(64) NOT NULL, "pauseRequestId" varchar, "sourceExecutionId" varchar(36), "planId" varchar, "planTaskId" varchar, CONSTRAINT "CHK_agent_background_job_kind" CHECK (((("kind" IN ('subagent', 'workflow'))))), CONSTRAINT "CHK_agent_background_job_status" CHECK ("status" IN ('running', 'suspended', 'paused', 'completed', 'failed', 'cancelled')), CONSTRAINT "FK_d46c6f00730c2ef8bcb6ee24b67" FOREIGN KEY ("parentAgentId") REFERENCES "agents" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_4db3b7ebea4ed4f69649982018c" FOREIGN KEY ("sourceExecutionId") REFERENCES "agent_execution" ("id") ON DELETE SET NULL, CONSTRAINT "FK_ce131bff629d89015893e350e9c" FOREIGN KEY ("planId") REFERENCES "agent_plan" ("id") ON DELETE SET NULL)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
|
@ -27,8 +27,11 @@ CREATE TABLE "agent_background_job" ("id" varchar(36) PRIMARY KEY NOT NULL, "kin
|
|||
| parentResourceId | varchar(255) | | false | | | |
|
||||
| parentThreadId | varchar(128) | | false | | | |
|
||||
| pauseRequestId | varchar | | true | | | |
|
||||
| planId | varchar | | true | | [agent_plan](agent_plan.md) | |
|
||||
| planTaskId | varchar | | true | | | |
|
||||
| result | TEXT | | true | | | |
|
||||
| settledAt | datetime(3) | | true | | | |
|
||||
| sourceExecutionId | varchar(36) | | true | | [agent_execution](agent_execution.md) | |
|
||||
| status | varchar(16) | | false | | | |
|
||||
| subAgentId | varchar(36) | | true | | | |
|
||||
| timeoutAt | datetime(3) | | true | | | |
|
||||
|
|
@ -42,7 +45,9 @@ CREATE TABLE "agent_background_job" ("id" varchar(36) PRIMARY KEY NOT NULL, "kin
|
|||
| ---- | ---- | ---------- |
|
||||
| - | CHECK | CHECK (((("kind" IN ('subagent', 'workflow'))))) |
|
||||
| - | CHECK | CHECK ("status" IN ('running', 'suspended', 'paused', 'completed', 'failed', 'cancelled')) |
|
||||
| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (parentAgentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE |
|
||||
| - (Foreign key ID: 0) | FOREIGN KEY | FOREIGN KEY (planId) REFERENCES agent_plan (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE |
|
||||
| - (Foreign key ID: 1) | FOREIGN KEY | FOREIGN KEY (sourceExecutionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE |
|
||||
| - (Foreign key ID: 2) | FOREIGN KEY | FOREIGN KEY (parentAgentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE |
|
||||
| id | PRIMARY KEY | PRIMARY KEY (id) |
|
||||
| sqlite_autoindex_agent_background_job_1 | PRIMARY KEY | PRIMARY KEY (id) |
|
||||
|
||||
|
|
@ -53,6 +58,8 @@ CREATE TABLE "agent_background_job" ("id" varchar(36) PRIMARY KEY NOT NULL, "kin
|
|||
| IDX_93d62baabe9858816b5adafb44 | CREATE INDEX "IDX_93d62baabe9858816b5adafb44" ON "agent_background_job" ("parentThreadId", "status") |
|
||||
| IDX_agent_background_job_childExecutionId | CREATE UNIQUE INDEX "IDX_agent_background_job_childExecutionId" ON "agent_background_job" ("childExecutionId") WHERE "childExecutionId" IS NOT NULL |
|
||||
| IDX_agent_background_job_parentThreadId | CREATE INDEX "IDX_agent_background_job_parentThreadId" ON "agent_background_job" ("parentThreadId") WHERE "status" <> 'running' AND "notifiedAt" IS NULL |
|
||||
| IDX_agent_background_job_planId_planTaskId | CREATE INDEX "IDX_agent_background_job_planId_planTaskId" ON "agent_background_job" ("planId", "planTaskId") |
|
||||
| IDX_agent_background_job_sourceExecutionId | CREATE INDEX "IDX_agent_background_job_sourceExecutionId" ON "agent_background_job" ("sourceExecutionId") |
|
||||
| IDX_agent_background_job_timeoutAt | CREATE INDEX "IDX_agent_background_job_timeoutAt" ON "agent_background_job" ("timeoutAt") WHERE "status" IN ('running', 'suspended') |
|
||||
| IDX_d46c6f00730c2ef8bcb6ee24b6 | CREATE INDEX "IDX_d46c6f00730c2ef8bcb6ee24b6" ON "agent_background_job" ("parentAgentId") |
|
||||
| IDX_e43e630272995a93dfeb94ab3e | CREATE INDEX "IDX_e43e630272995a93dfeb94ab3e" ON "agent_background_job" ("settledAt") |
|
||||
|
|
@ -64,6 +71,8 @@ CREATE TABLE "agent_background_job" ("id" varchar(36) PRIMARY KEY NOT NULL, "kin
|
|||
erDiagram
|
||||
|
||||
"agent_background_job" }o--|| "agents" : "FOREIGN KEY (parentAgentId) REFERENCES agents (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
"agent_background_job" }o--o| "agent_plan" : "FOREIGN KEY (planId) REFERENCES agent_plan (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE"
|
||||
"agent_background_job" }o--o| "agent_execution" : "FOREIGN KEY (sourceExecutionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE"
|
||||
|
||||
"agent_background_job" {
|
||||
varchar_36_ childExecutionId
|
||||
|
|
@ -78,8 +87,11 @@ erDiagram
|
|||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
varchar pauseRequestId
|
||||
varchar planId FK
|
||||
varchar planTaskId
|
||||
TEXT result
|
||||
datetime_3_ settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
datetime_3_ timeoutAt
|
||||
|
|
@ -104,6 +116,41 @@ erDiagram
|
|||
datetime_3_ updatedAt
|
||||
varchar_36_ versionId
|
||||
}
|
||||
"agent_plan" {
|
||||
datetime_3_ closedAt
|
||||
datetime_3_ createdAt
|
||||
TEXT data
|
||||
INTEGER formatVersion
|
||||
varchar id PK
|
||||
INTEGER revision
|
||||
varchar_128_ threadId FK
|
||||
datetime_3_ updatedAt
|
||||
}
|
||||
"agent_execution" {
|
||||
BOOLEAN acceptsSteering
|
||||
TEXT attachments
|
||||
TEXT author
|
||||
INTEGER completionTokens
|
||||
REAL cost
|
||||
datetime_3_ createdAt
|
||||
INTEGER duration
|
||||
TEXT error
|
||||
TEXT failureSummary
|
||||
varchar_16_ hitlStatus
|
||||
varchar_36_ id PK
|
||||
varchar_255_ model
|
||||
INTEGER promptTokens
|
||||
varchar_32_ source
|
||||
datetime_3_ startedAt
|
||||
varchar_16_ status
|
||||
datetime_3_ stoppedAt
|
||||
varchar_2_ storedAt
|
||||
varchar_128_ threadId FK
|
||||
TEXT timeline
|
||||
INTEGER totalTokens
|
||||
datetime_3_ updatedAt
|
||||
TEXT userMessage
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
|
|
|||
29
docs/generated/sqlite-schema/agent_execution.md
generated
29
docs/generated/sqlite-schema/agent_execution.md
generated
|
|
@ -25,7 +25,7 @@ CREATE TABLE "agent_execution" ("id" varchar(36) PRIMARY KEY NOT NULL, "threadId
|
|||
| error | TEXT | | true | | | |
|
||||
| failureSummary | TEXT | | true | | | |
|
||||
| hitlStatus | varchar(16) | | true | | | |
|
||||
| id | varchar(36) | | false | [agent_execution_message_links](agent_execution_message_links.md) [agent_message_queue](agent_message_queue.md) | | |
|
||||
| id | varchar(36) | | false | [agent_background_job](agent_background_job.md) [agent_execution_message_links](agent_execution_message_links.md) [agent_message_queue](agent_message_queue.md) | | |
|
||||
| model | varchar(255) | | true | | | |
|
||||
| promptTokens | INTEGER | | true | | | |
|
||||
| source | varchar(32) | | true | | | |
|
||||
|
|
@ -63,6 +63,7 @@ CREATE TABLE "agent_execution" ("id" varchar(36) PRIMARY KEY NOT NULL, "threadId
|
|||
```mermaid
|
||||
erDiagram
|
||||
|
||||
"agent_background_job" }o--o| "agent_execution" : "FOREIGN KEY (sourceExecutionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE"
|
||||
"agent_execution_message_links" |o--|| "agent_execution" : "FOREIGN KEY (executionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
"agent_message_queue" }o--o| "agent_execution" : "FOREIGN KEY (executionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE"
|
||||
"agent_message_queue" }o--o| "agent_execution" : "FOREIGN KEY (steeringExecutionId) REFERENCES agent_execution (id) ON UPDATE NO ACTION ON DELETE NO ACTION MATCH NONE"
|
||||
|
|
@ -93,6 +94,31 @@ erDiagram
|
|||
datetime_3_ updatedAt
|
||||
TEXT userMessage
|
||||
}
|
||||
"agent_background_job" {
|
||||
varchar_36_ childExecutionId
|
||||
varchar_128_ childThreadId
|
||||
datetime_3_ createdAt
|
||||
TEXT error
|
||||
varchar_36_ id PK
|
||||
varchar_16_ kind
|
||||
datetime_3_ notifiedAt
|
||||
varchar_36_ parentAgentId FK
|
||||
varchar_64_ parentPrincipalHash
|
||||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
varchar pauseRequestId
|
||||
varchar planId FK
|
||||
varchar planTaskId
|
||||
TEXT result
|
||||
datetime_3_ settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
datetime_3_ timeoutAt
|
||||
varchar_255_ title
|
||||
datetime_3_ updatedAt
|
||||
varchar_36_ workflowId
|
||||
}
|
||||
"agent_execution_message_links" {
|
||||
datetime_3_ createdAt
|
||||
varchar_6_ direction
|
||||
|
|
@ -125,6 +151,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<summary><strong>Table Definition</strong></summary>
|
||||
|
||||
```sql
|
||||
CREATE TABLE "agent_execution_threads" ("id" varchar(128) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "agentName" varchar(255) NOT NULL, "projectId" varchar(255) NOT NULL, "sessionNumber" integer NOT NULL DEFAULT (0), "totalPromptTokens" integer NOT NULL DEFAULT (0), "totalCompletionTokens" integer NOT NULL DEFAULT (0), "totalCost" real NOT NULL DEFAULT (0), "totalDuration" integer NOT NULL DEFAULT (0), "title" varchar(255), "emoji" varchar(8), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "taskId" varchar(32), "taskVersionId" varchar(36), "parentThreadId" varchar(128), "parentAgentId" varchar(36), "ownerId" varchar, "accessScope" varchar(16) NOT NULL DEFAULT ('user'), CONSTRAINT "CHK_agent_execution_threads_accessScope" CHECK ("accessScope" IN ('user', 'project')), CONSTRAINT "FK_f00b52d74fe11838e1fe086deea" FOREIGN KEY ("taskVersionId") REFERENCES "agent_history" ("versionId") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_0468a9dc35597314e641d4722aa" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_0e2f8bf92a7a9c88b89670f701c" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_agent_execution_threads_owner" FOREIGN KEY ("ownerId") REFERENCES "user" ("id") ON DELETE SET NULL)
|
||||
CREATE TABLE "agent_execution_threads" ("id" varchar(128) PRIMARY KEY NOT NULL, "agentId" varchar(36) NOT NULL, "agentName" varchar(255) NOT NULL, "projectId" varchar(255) NOT NULL, "sessionNumber" integer NOT NULL DEFAULT (0), "totalPromptTokens" integer NOT NULL DEFAULT (0), "totalCompletionTokens" integer NOT NULL DEFAULT (0), "totalCost" real NOT NULL DEFAULT (0), "totalDuration" integer NOT NULL DEFAULT (0), "title" varchar(255), "emoji" varchar(8), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "updatedAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "taskId" varchar(32), "taskVersionId" varchar(36), "parentThreadId" varchar(128), "parentAgentId" varchar(36), "ownerId" varchar, "accessScope" varchar(16) NOT NULL DEFAULT ('user'), "taskStop" TEXT, CONSTRAINT "CHK_agent_execution_threads_accessScope" CHECK ("accessScope" IN ('user', 'project')), CONSTRAINT "FK_f00b52d74fe11838e1fe086deea" FOREIGN KEY ("taskVersionId") REFERENCES "agent_history" ("versionId") ON DELETE SET NULL ON UPDATE NO ACTION, CONSTRAINT "FK_0468a9dc35597314e641d4722aa" FOREIGN KEY ("agentId") REFERENCES "agents" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_0e2f8bf92a7a9c88b89670f701c" FOREIGN KEY ("projectId") REFERENCES "project" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_agent_execution_threads_owner" FOREIGN KEY ("ownerId") REFERENCES "user" ("id") ON DELETE SET NULL)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
|
@ -27,6 +27,7 @@ CREATE TABLE "agent_execution_threads" ("id" varchar(128) PRIMARY KEY NOT NULL,
|
|||
| projectId | varchar(255) | | false | | [project](project.md) | |
|
||||
| sessionNumber | INTEGER | 0 | false | | | |
|
||||
| taskId | varchar(32) | | true | | | |
|
||||
| taskStop | TEXT | | true | | | |
|
||||
| taskVersionId | varchar(36) | | true | | [agent_history](agent_history.md) | |
|
||||
| title | varchar(255) | | true | | | |
|
||||
| totalCompletionTokens | INTEGER | 0 | false | | | |
|
||||
|
|
@ -84,6 +85,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
1
docs/generated/sqlite-schema/agent_history.md
generated
1
docs/generated/sqlite-schema/agent_history.md
generated
|
|
@ -111,6 +111,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
29
docs/generated/sqlite-schema/agent_plan.md
generated
29
docs/generated/sqlite-schema/agent_plan.md
generated
|
|
@ -19,7 +19,7 @@ CREATE TABLE "agent_plan" ("id" varchar PRIMARY KEY NOT NULL, "threadId" varchar
|
|||
| createdAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | |
|
||||
| data | TEXT | | false | | | |
|
||||
| formatVersion | INTEGER | | false | | | |
|
||||
| id | varchar | | false | [agent_plan_history](agent_plan_history.md) | | |
|
||||
| id | varchar | | false | [agent_background_job](agent_background_job.md) [agent_plan_history](agent_plan_history.md) | | |
|
||||
| revision | INTEGER | 1 | false | | | |
|
||||
| threadId | varchar(128) | | false | | [agent_execution_threads](agent_execution_threads.md) | |
|
||||
| updatedAt | datetime(3) | STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW') | false | | | |
|
||||
|
|
@ -47,6 +47,7 @@ CREATE TABLE "agent_plan" ("id" varchar PRIMARY KEY NOT NULL, "threadId" varchar
|
|||
```mermaid
|
||||
erDiagram
|
||||
|
||||
"agent_background_job" }o--o| "agent_plan" : "FOREIGN KEY (planId) REFERENCES agent_plan (id) ON UPDATE NO ACTION ON DELETE SET NULL MATCH NONE"
|
||||
"agent_plan_history" |o--|| "agent_plan" : "FOREIGN KEY (planId) REFERENCES agent_plan (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
"agent_plan" }o--|| "agent_execution_threads" : "FOREIGN KEY (threadId) REFERENCES agent_execution_threads (id) ON UPDATE NO ACTION ON DELETE CASCADE MATCH NONE"
|
||||
|
||||
|
|
@ -60,6 +61,31 @@ erDiagram
|
|||
varchar_128_ threadId FK
|
||||
datetime_3_ updatedAt
|
||||
}
|
||||
"agent_background_job" {
|
||||
varchar_36_ childExecutionId
|
||||
varchar_128_ childThreadId
|
||||
datetime_3_ createdAt
|
||||
TEXT error
|
||||
varchar_36_ id PK
|
||||
varchar_16_ kind
|
||||
datetime_3_ notifiedAt
|
||||
varchar_36_ parentAgentId FK
|
||||
varchar_64_ parentPrincipalHash
|
||||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
varchar pauseRequestId
|
||||
varchar planId FK
|
||||
varchar planTaskId
|
||||
TEXT result
|
||||
datetime_3_ settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
datetime_3_ timeoutAt
|
||||
varchar_255_ title
|
||||
datetime_3_ updatedAt
|
||||
varchar_36_ workflowId
|
||||
}
|
||||
"agent_plan_history" {
|
||||
datetime_3_ closedAt
|
||||
datetime_3_ createdAt
|
||||
|
|
@ -81,6 +107,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
4
docs/generated/sqlite-schema/agents.md
generated
4
docs/generated/sqlite-schema/agents.md
generated
|
|
@ -121,8 +121,11 @@ erDiagram
|
|||
varchar_255_ parentResourceId
|
||||
varchar_128_ parentThreadId
|
||||
varchar pauseRequestId
|
||||
varchar planId FK
|
||||
varchar planTaskId
|
||||
TEXT result
|
||||
datetime_3_ settledAt
|
||||
varchar_36_ sourceExecutionId FK
|
||||
varchar_16_ status
|
||||
varchar_36_ subAgentId
|
||||
datetime_3_ timeoutAt
|
||||
|
|
@ -204,6 +207,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
1
docs/generated/sqlite-schema/project.md
generated
1
docs/generated/sqlite-schema/project.md
generated
|
|
@ -136,6 +136,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
1
docs/generated/sqlite-schema/user.md
generated
1
docs/generated/sqlite-schema/user.md
generated
|
|
@ -184,6 +184,7 @@ erDiagram
|
|||
varchar_255_ projectId FK
|
||||
INTEGER sessionNumber
|
||||
varchar_32_ taskId
|
||||
TEXT taskStop
|
||||
varchar_36_ taskVersionId FK
|
||||
varchar_255_ title
|
||||
INTEGER totalCompletionTokens
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
import type { AgentPlanTaskRef } from './task-cancellation';
|
||||
|
||||
import type { AgentBuilderOpenSuspension } from './types';
|
||||
|
||||
export interface AgentBackgroundJobDto {
|
||||
planTask?: AgentPlanTaskRef;
|
||||
id: string;
|
||||
title: string;
|
||||
/** Source of the background job. */
|
||||
|
|
|
|||
|
|
@ -457,3 +457,7 @@ export interface VectorStoreTestResult {
|
|||
export class AgentChatCancelDto extends Z.class({
|
||||
scope: z.enum(['foreground', 'all']).optional(),
|
||||
}) {}
|
||||
|
||||
export class AgentTaskCancellationDto extends Z.class({
|
||||
planId: z.string().uuid().toLowerCase().nullable(),
|
||||
}) {}
|
||||
|
|
|
|||
|
|
@ -48,3 +48,5 @@ export {
|
|||
type CancellationResumeData,
|
||||
} from '../agent-builder-interactive';
|
||||
export * from './agent-interaction.schema';
|
||||
|
||||
export type * from './task-cancellation';
|
||||
|
|
|
|||
59
packages/@n8n/api-types/src/agents/task-cancellation.ts
Normal file
59
packages/@n8n/api-types/src/agents/task-cancellation.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
export interface AgentPlanTaskRef {
|
||||
planId: string;
|
||||
planTaskId: string;
|
||||
}
|
||||
|
||||
/** Runtime state does not change the saved task statuses. */
|
||||
export interface AgentPlanWorkState {
|
||||
stoppedTaskIds: string[];
|
||||
stoppingTaskIds: string[];
|
||||
fullyStopped: boolean;
|
||||
stoppedAt: string | null;
|
||||
taskStateAvailable: boolean;
|
||||
}
|
||||
|
||||
export interface AgentPlanItemDto {
|
||||
id: string;
|
||||
title: string;
|
||||
description?: string;
|
||||
resultSummary?: string;
|
||||
status: 'pending' | 'in_progress' | 'done' | 'failed' | 'cancelled';
|
||||
dependsOn: string[];
|
||||
}
|
||||
|
||||
export interface AgentPlanSnapshotDto {
|
||||
workState?: AgentPlanWorkState;
|
||||
readiness: { ready: string[]; blocked: Array<{ id: string; blockedBy: string[] }> };
|
||||
planId: string;
|
||||
revision: number;
|
||||
closed: boolean;
|
||||
startedAt: string | null;
|
||||
finishedAt?: string | null;
|
||||
closedAt: string | null;
|
||||
document: {
|
||||
title: string;
|
||||
description?: string;
|
||||
presentation?: { label: string; detail?: string };
|
||||
items: Array<
|
||||
| (AgentPlanItemDto & { kind: 'task'; fallbackFor?: string })
|
||||
| (AgentPlanItemDto & {
|
||||
kind: 'group';
|
||||
tasks: Array<AgentPlanItemDto & { kind: 'task'; fallbackFor?: string }>;
|
||||
})
|
||||
>;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AgentTaskStopFailure {
|
||||
jobId: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface AgentTaskCancellationState {
|
||||
planId: string | null;
|
||||
status: 'stopping' | 'failed' | 'stopped' | 'resumed';
|
||||
reportFailed?: boolean;
|
||||
requestedAt: string;
|
||||
failures: AgentTaskStopFailure[];
|
||||
plan: AgentPlanSnapshotDto | null;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import type { MigrationContext, ReversibleMigration } from '../migration-types';
|
||||
|
||||
export class AddSourceExecutionToAgentBackgroundJob1792083059203 implements ReversibleMigration {
|
||||
async up({
|
||||
schemaBuilder: { addColumns, addForeignKey, column, createIndex },
|
||||
}: MigrationContext) {
|
||||
await addColumns(
|
||||
'agent_background_job',
|
||||
[column('sourceExecutionId').varchar(36).comment('Execution that dispatched this job')],
|
||||
{ recreatesOnSqlite: true },
|
||||
);
|
||||
await addForeignKey(
|
||||
'agent_background_job',
|
||||
'sourceExecutionId',
|
||||
['agent_execution', 'id'],
|
||||
undefined,
|
||||
'SET NULL',
|
||||
);
|
||||
await createIndex('agent_background_job', ['sourceExecutionId']);
|
||||
}
|
||||
|
||||
async down({ schemaBuilder: { dropColumns, dropIndex } }: MigrationContext) {
|
||||
await dropIndex('agent_background_job', ['sourceExecutionId']);
|
||||
await dropColumns('agent_background_job', ['sourceExecutionId'], {
|
||||
recreatesOnSqlite: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
import type { MigrationContext, ReversibleMigration } from '../migration-types';
|
||||
|
||||
export class AddTaskStopToAgentExecutionThreads1792083059437 implements ReversibleMigration {
|
||||
async up({
|
||||
schemaBuilder: { addColumns, column },
|
||||
isSqlite,
|
||||
escape,
|
||||
runQuery,
|
||||
}: MigrationContext) {
|
||||
if (isSqlite) {
|
||||
await runQuery(
|
||||
`ALTER TABLE ${escape.tableName('agent_execution_threads')} ADD COLUMN ${escape.columnName('taskStop')} TEXT`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
await addColumns(
|
||||
'agent_execution_threads',
|
||||
[column('taskStop').json.comment('Latest task stop boundary and unresolved stop errors')],
|
||||
{ recreatesOnSqlite: true },
|
||||
);
|
||||
}
|
||||
|
||||
async down({ escape, runQuery }: MigrationContext) {
|
||||
await runQuery(
|
||||
`ALTER TABLE ${escape.tableName('agent_execution_threads')} DROP COLUMN ${escape.columnName('taskStop')}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
import type { MigrationContext, ReversibleMigration } from '../migration-types';
|
||||
|
||||
export class AddPlanTaskToAgentBackgroundJob1792083059654 implements ReversibleMigration {
|
||||
async up({
|
||||
schemaBuilder: { addColumns, column, addForeignKey, createIndex },
|
||||
}: MigrationContext) {
|
||||
await addColumns(
|
||||
'agent_background_job',
|
||||
[
|
||||
column('planId').uuid.comment('Plan that owns this work'),
|
||||
column('planTaskId').uuid.comment('Task ID in the saved plan document'),
|
||||
],
|
||||
{ recreatesOnSqlite: true },
|
||||
);
|
||||
await addForeignKey(
|
||||
'agent_background_job',
|
||||
'planId',
|
||||
['agent_plan', 'id'],
|
||||
undefined,
|
||||
'SET NULL',
|
||||
);
|
||||
await createIndex('agent_background_job', ['planId', 'planTaskId']);
|
||||
}
|
||||
|
||||
async down({ schemaBuilder: { dropIndex, dropColumns } }: MigrationContext) {
|
||||
await dropIndex('agent_background_job', ['planId', 'planTaskId']);
|
||||
await dropColumns('agent_background_job', ['planId', 'planTaskId'], {
|
||||
recreatesOnSqlite: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import type { AgentPlan } from './agent-plan.entity';
|
||||
import type { AgentExecution } from './agent-execution.entity';
|
||||
import type { AgentBackgroundJobDto } from '@n8n/api-types';
|
||||
import { DateTimeColumn, WithTimestampsAndStringId } from '@n8n/db';
|
||||
import { Column, Entity, Index } from '@n8n/typeorm';
|
||||
import { Column, Entity, Index, ManyToOne, JoinColumn, type Relation } from '@n8n/typeorm';
|
||||
|
||||
export type AgentBackgroundJobKind = AgentBackgroundJobDto['kind'];
|
||||
export type AgentBackgroundJobStatus = AgentBackgroundJobDto['status'];
|
||||
|
|
@ -15,11 +17,35 @@ export type AgentBackgroundJobStatus = AgentBackgroundJobDto['status'];
|
|||
@Entity({ name: 'agent_background_job' })
|
||||
@Index(['parentThreadId', 'status'])
|
||||
@Index(['parentAgentId'])
|
||||
@Index(['sourceExecutionId'])
|
||||
@Index(['planId', 'planTaskId'])
|
||||
@Index(['settledAt'])
|
||||
@Index(['childExecutionId'], { unique: true, where: '"childExecutionId" IS NOT NULL' })
|
||||
@Index(['timeoutAt'], { where: "\"status\" IN ('running', 'suspended')" })
|
||||
@Index(['parentThreadId'], { where: '"status" <> \'running\' AND "notifiedAt" IS NULL' })
|
||||
export class AgentBackgroundJob extends WithTimestampsAndStringId {
|
||||
@Column({
|
||||
type: 'varchar',
|
||||
length: 36,
|
||||
nullable: true,
|
||||
comment: 'Execution that dispatched this job',
|
||||
})
|
||||
sourceExecutionId: string | null;
|
||||
|
||||
@ManyToOne('AgentExecution', { nullable: true, onDelete: 'SET NULL' })
|
||||
@JoinColumn({ name: 'sourceExecutionId' })
|
||||
sourceExecution: Relation<AgentExecution> | null;
|
||||
|
||||
@Column({ type: 'uuid', nullable: true, comment: 'Plan that owns this work' })
|
||||
planId: string | null;
|
||||
|
||||
@Column({ type: 'uuid', nullable: true, comment: 'Task ID in the saved plan document' })
|
||||
planTaskId: string | null;
|
||||
|
||||
@ManyToOne('AgentPlan', { nullable: true, onDelete: 'SET NULL' })
|
||||
@JoinColumn({ name: 'planId' })
|
||||
plan: Relation<AgentPlan> | null;
|
||||
|
||||
@Column({ type: 'varchar', length: 16 })
|
||||
kind: AgentBackgroundJobKind;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { AGENT_TASK_ID_MAX_LENGTH } from '@n8n/api-types';
|
||||
import { Project, User, WithTimestampsAndStringId } from '@n8n/db';
|
||||
import { JsonColumn, Project, User, WithTimestampsAndStringId } from '@n8n/db';
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne, type Relation } from '@n8n/typeorm';
|
||||
|
||||
import { AgentHistory } from './agent-history.entity';
|
||||
import { Agent } from './agent.entity';
|
||||
import type { StoredAgentTaskStop } from '../types/agent-task-stop';
|
||||
|
||||
/**
|
||||
* One conversation between a user and an agent. Aggregates per-session
|
||||
|
|
@ -20,6 +21,9 @@ import { Agent } from './agent.entity';
|
|||
*/
|
||||
@Entity({ name: 'agent_execution_threads' })
|
||||
export class AgentExecutionThread extends WithTimestampsAndStringId {
|
||||
@JsonColumn({ nullable: true, comment: 'Latest task stop boundary and unresolved stop errors' })
|
||||
taskStop: StoredAgentTaskStop | null;
|
||||
|
||||
@ManyToOne(() => User, { nullable: true, onDelete: 'SET NULL' })
|
||||
@JoinColumn({ name: 'ownerId', foreignKeyConstraintName: 'FK_agent_execution_threads_owner' })
|
||||
owner: Relation<User> | null;
|
||||
|
|
|
|||
28
packages/cli/src/modules/agents/types/agent-task-stop.ts
Normal file
28
packages/cli/src/modules/agents/types/agent-task-stop.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
import type { AgentTaskStopFailure } from '@n8n/api-types';
|
||||
|
||||
/** Keep the stop and its acknowledgement available between jobs and across restarts. */
|
||||
export interface AgentTaskStop {
|
||||
planId: string | null;
|
||||
requestedAt: string;
|
||||
/** Unfinished leaf tasks and empty groups captured when Stop was requested. */
|
||||
stoppedTaskIds?: string[];
|
||||
/** Explicitly selected workflow tasks that still need a replacement job. */
|
||||
restartTaskIds?: string[];
|
||||
planRevision?: number;
|
||||
generation: { executionIds: string[]; jobIds: string[]; threadIds: string[] };
|
||||
failures: AgentTaskStopFailure[];
|
||||
/** Reuse background checkpoints and deliver one report for this stop. */
|
||||
pause: {
|
||||
id: string;
|
||||
reportExecutionId?: string;
|
||||
reportedAt?: string;
|
||||
reportFailed?: boolean;
|
||||
/** Chat admission only. This does not resume stopped tasks. */
|
||||
resumedAt?: string;
|
||||
};
|
||||
}
|
||||
|
||||
/** Earlier stop records have no pause coordination. */
|
||||
export type StoredAgentTaskStop = Omit<AgentTaskStop, 'pause'> & {
|
||||
pause?: AgentTaskStop['pause'];
|
||||
};
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
import {
|
||||
createTestMigrationContext,
|
||||
initDbUpToMigration,
|
||||
runSingleMigration,
|
||||
undoLastSingleMigration,
|
||||
type TestMigrationContext,
|
||||
} from '@n8n/backend-test-utils';
|
||||
import { DbConnection } from '@n8n/db';
|
||||
import { Container } from '@n8n/di';
|
||||
import { DataSource } from '@n8n/typeorm';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
const migrationName = 'AddSourceExecutionToAgentBackgroundJob1792083059203';
|
||||
|
||||
describe('Agent background job source migration', () => {
|
||||
const threadId = randomUUID();
|
||||
const executionId = randomUUID();
|
||||
const jobId = randomUUID();
|
||||
|
||||
async function withContext<T>(fn: (context: TestMigrationContext) => Promise<T>): Promise<T> {
|
||||
const context = createTestMigrationContext(Container.get(DataSource));
|
||||
try {
|
||||
return await fn(context);
|
||||
} finally {
|
||||
await context.queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
async function insert(
|
||||
context: TestMigrationContext,
|
||||
table: string,
|
||||
values: Record<string, string>,
|
||||
) {
|
||||
const columns = Object.keys(values);
|
||||
await context.runQuery(
|
||||
`INSERT INTO ${context.escape.tableName(table)}
|
||||
(${columns.map(context.escape.columnName).join(', ')})
|
||||
VALUES (${columns.map((name) => `:${name}`).join(', ')})`,
|
||||
values,
|
||||
);
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
await Container.get(DbConnection).init();
|
||||
await withContext(async (context) => await context.queryRunner.clearDatabase());
|
||||
await initDbUpToMigration(migrationName);
|
||||
await withContext(async (context) => {
|
||||
const projectId = randomUUID();
|
||||
const agentId = randomUUID();
|
||||
await insert(context, 'project', { id: projectId, name: 'Stop test project', type: 'team' });
|
||||
await insert(context, 'agents', {
|
||||
id: agentId,
|
||||
projectId,
|
||||
name: 'Stop test agent',
|
||||
integrations: '[]',
|
||||
tools: '{}',
|
||||
skills: '{}',
|
||||
});
|
||||
await insert(context, 'agent_execution_threads', {
|
||||
id: threadId,
|
||||
projectId,
|
||||
agentId,
|
||||
agentName: 'Stop test agent',
|
||||
});
|
||||
await insert(context, 'agent_execution', { id: executionId, threadId, status: 'success' });
|
||||
await insert(context, 'agent_background_job', {
|
||||
id: jobId,
|
||||
parentAgentId: agentId,
|
||||
parentThreadId: threadId,
|
||||
parentResourceId: 'draft-chat:test',
|
||||
parentPrincipalHash: 'principal',
|
||||
title: 'Saved result',
|
||||
kind: 'workflow',
|
||||
status: 'completed',
|
||||
result: '{"completed":true}',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => await Container.get(DbConnection).close());
|
||||
|
||||
it('preserves jobs and supports source deletion, rollback, and reapplication', async () => {
|
||||
await runSingleMigration(migrationName);
|
||||
await withContext(async ({ escape, runQuery, queryRunner, tablePrefix }) => {
|
||||
const table = await queryRunner.getTable(`${tablePrefix}agent_background_job`);
|
||||
expect(table?.findColumnByName('sourceExecutionId')).toMatchObject({ isNullable: true });
|
||||
expect(
|
||||
table?.foreignKeys.filter((key) => key.columnNames.includes('sourceExecutionId')),
|
||||
).toHaveLength(1);
|
||||
expect(
|
||||
table?.indices.some((index) => index.columnNames.join(',') === 'sourceExecutionId'),
|
||||
).toBe(true);
|
||||
await runQuery(
|
||||
`UPDATE ${escape.tableName('agent_background_job')} SET ${escape.columnName('sourceExecutionId')} = :executionId WHERE ${escape.columnName('id')} = :jobId`,
|
||||
{ executionId, jobId },
|
||||
);
|
||||
await runQuery(
|
||||
`DELETE FROM ${escape.tableName('agent_execution')} WHERE ${escape.columnName('id')} = :executionId`,
|
||||
{ executionId },
|
||||
);
|
||||
expect(
|
||||
await runQuery(
|
||||
`SELECT ${escape.columnName('sourceExecutionId')}, ${escape.columnName('result')} FROM ${escape.tableName('agent_background_job')}`,
|
||||
),
|
||||
).toEqual([{ sourceExecutionId: null, result: '{"completed":true}' }]);
|
||||
});
|
||||
await undoLastSingleMigration();
|
||||
await withContext(async ({ escape, runQuery, queryRunner, tablePrefix }) => {
|
||||
expect(
|
||||
(await queryRunner.getTable(`${tablePrefix}agent_background_job`))?.findColumnByName(
|
||||
'sourceExecutionId',
|
||||
),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
await runQuery(
|
||||
`SELECT ${escape.columnName('result')} FROM ${escape.tableName('agent_background_job')}`,
|
||||
),
|
||||
).toEqual([{ result: '{"completed":true}' }]);
|
||||
});
|
||||
await runSingleMigration(migrationName);
|
||||
await withContext(async ({ queryRunner, tablePrefix }) => {
|
||||
const table = await queryRunner.getTable(`${tablePrefix}agent_background_job`);
|
||||
expect(
|
||||
table?.foreignKeys.filter((key) => key.columnNames.includes('sourceExecutionId')),
|
||||
).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
import {
|
||||
createTestMigrationContext,
|
||||
initDbUpToMigration,
|
||||
runSingleMigration,
|
||||
undoLastSingleMigration,
|
||||
type TestMigrationContext,
|
||||
} from '@n8n/backend-test-utils';
|
||||
import { DbConnection } from '@n8n/db';
|
||||
import { Container } from '@n8n/di';
|
||||
import { DataSource } from '@n8n/typeorm';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
const migrationName = 'AddTaskStopToAgentExecutionThreads1792083059437';
|
||||
|
||||
describe('AddTaskStopToAgentExecutionThreads migration', () => {
|
||||
const threadId = randomUUID();
|
||||
const executionId = randomUUID();
|
||||
|
||||
async function withContext<T>(fn: (context: TestMigrationContext) => Promise<T>): Promise<T> {
|
||||
const context = createTestMigrationContext(Container.get(DataSource));
|
||||
try {
|
||||
return await fn(context);
|
||||
} finally {
|
||||
await context.queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
async function insert(
|
||||
context: TestMigrationContext,
|
||||
table: string,
|
||||
values: Record<string, string>,
|
||||
) {
|
||||
const columns = Object.keys(values);
|
||||
await context.runQuery(
|
||||
`INSERT INTO ${context.escape.tableName(table)}
|
||||
(${columns.map(context.escape.columnName).join(', ')})
|
||||
VALUES (${columns.map((name) => `:${name}`).join(', ')})`,
|
||||
values,
|
||||
);
|
||||
}
|
||||
|
||||
async function readThreads() {
|
||||
return await withContext(
|
||||
async ({ escape, runQuery }) =>
|
||||
await runQuery(`SELECT * FROM ${escape.tableName('agent_execution_threads')}`),
|
||||
);
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
await Container.get(DbConnection).init();
|
||||
await withContext(async (context) => await context.queryRunner.clearDatabase());
|
||||
await initDbUpToMigration(migrationName);
|
||||
await withContext(async (context) => {
|
||||
const projectId = randomUUID();
|
||||
const agentId = randomUUID();
|
||||
await insert(context, 'project', { id: projectId, name: 'Stop test project', type: 'team' });
|
||||
await insert(context, 'agents', {
|
||||
id: agentId,
|
||||
projectId,
|
||||
name: 'Stop test agent',
|
||||
integrations: '[]',
|
||||
tools: '{}',
|
||||
skills: '{}',
|
||||
});
|
||||
await insert(context, 'agent_execution_threads', {
|
||||
id: threadId,
|
||||
projectId,
|
||||
agentId,
|
||||
agentName: 'Stop test agent',
|
||||
});
|
||||
await insert(context, 'agent_execution', { id: executionId, threadId, status: 'success' });
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => await Container.get(DbConnection).close());
|
||||
|
||||
it('preserves chats and their execution records through upgrade, rollback, and reapplication', async () => {
|
||||
const original = await readThreads();
|
||||
await runSingleMigration(migrationName);
|
||||
await withContext(async ({ escape, runQuery, queryRunner, tablePrefix, isSqlite }) => {
|
||||
expect(
|
||||
(await queryRunner.getTable(`${tablePrefix}agent_execution_threads`))?.findColumnByName(
|
||||
'taskStop',
|
||||
),
|
||||
).toMatchObject({
|
||||
isNullable: true,
|
||||
type: isSqlite ? 'text' : 'json',
|
||||
});
|
||||
expect(
|
||||
await runQuery(
|
||||
`SELECT ${escape.columnName('taskStop')} FROM ${escape.tableName('agent_execution_threads')}`,
|
||||
),
|
||||
).toEqual([{ taskStop: null }]);
|
||||
await runQuery(
|
||||
`UPDATE ${escape.tableName('agent_execution_threads')} SET ${escape.columnName('taskStop')} = :stop WHERE ${escape.columnName('id')} = :threadId`,
|
||||
{ threadId, stop: JSON.stringify({ requestedAt: '2026-10-08T10:00:00.000Z' }) },
|
||||
);
|
||||
});
|
||||
await undoLastSingleMigration();
|
||||
expect(await readThreads()).toEqual(original);
|
||||
await withContext(async ({ queryRunner, tablePrefix }) => {
|
||||
expect(
|
||||
(await queryRunner.getTable(`${tablePrefix}agent_execution_threads`))?.findColumnByName(
|
||||
'taskStop',
|
||||
),
|
||||
).toBeUndefined();
|
||||
});
|
||||
await runSingleMigration(migrationName);
|
||||
await withContext(async ({ escape, runQuery, queryRunner, tablePrefix }) => {
|
||||
expect(
|
||||
await runQuery(
|
||||
`SELECT ${escape.columnName('id')} FROM ${escape.tableName('agent_execution')}`,
|
||||
),
|
||||
).toEqual([{ id: executionId }]);
|
||||
expect(
|
||||
(await queryRunner.getTable(`${tablePrefix}agent_execution_threads`))?.findColumnByName(
|
||||
'taskStop',
|
||||
),
|
||||
).toMatchObject({ isNullable: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
import {
|
||||
createTestMigrationContext,
|
||||
initDbUpToMigration,
|
||||
runSingleMigration,
|
||||
undoLastSingleMigration,
|
||||
type TestMigrationContext,
|
||||
} from '@n8n/backend-test-utils';
|
||||
import { DbConnection } from '@n8n/db';
|
||||
import { Container } from '@n8n/di';
|
||||
import { DataSource } from '@n8n/typeorm';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
const migrationName = 'AddPlanTaskToAgentBackgroundJob1792083059654';
|
||||
|
||||
describe('Agent background job plan task migration', () => {
|
||||
const threadId = randomUUID();
|
||||
const planId = randomUUID();
|
||||
const planTaskId = randomUUID();
|
||||
const jobId = randomUUID();
|
||||
|
||||
async function withContext<T>(fn: (context: TestMigrationContext) => Promise<T>): Promise<T> {
|
||||
const context = createTestMigrationContext(Container.get(DataSource));
|
||||
try {
|
||||
return await fn(context);
|
||||
} finally {
|
||||
await context.queryRunner.release();
|
||||
}
|
||||
}
|
||||
|
||||
async function insert(
|
||||
context: TestMigrationContext,
|
||||
table: string,
|
||||
values: Record<string, string>,
|
||||
) {
|
||||
const columns = Object.keys(values);
|
||||
await context.runQuery(
|
||||
`INSERT INTO ${context.escape.tableName(table)}
|
||||
(${columns.map(context.escape.columnName).join(', ')})
|
||||
VALUES (${columns.map((name) => `:${name}`).join(', ')})`,
|
||||
values,
|
||||
);
|
||||
}
|
||||
|
||||
beforeAll(async () => {
|
||||
await Container.get(DbConnection).init();
|
||||
await withContext(async (context) => await context.queryRunner.clearDatabase());
|
||||
await initDbUpToMigration(migrationName);
|
||||
await withContext(async (context) => {
|
||||
const projectId = randomUUID();
|
||||
const agentId = randomUUID();
|
||||
await insert(context, 'project', { id: projectId, name: 'Stop test project', type: 'team' });
|
||||
await insert(context, 'agents', {
|
||||
id: agentId,
|
||||
projectId,
|
||||
name: 'Stop test agent',
|
||||
integrations: '[]',
|
||||
tools: '{}',
|
||||
skills: '{}',
|
||||
});
|
||||
await insert(context, 'agent_execution_threads', {
|
||||
id: threadId,
|
||||
projectId,
|
||||
agentId,
|
||||
agentName: 'Stop test agent',
|
||||
});
|
||||
await insert(context, 'agent_plan', { id: planId, threadId, formatVersion: '1', data: '{}' });
|
||||
await insert(context, 'agent_background_job', {
|
||||
id: jobId,
|
||||
parentAgentId: agentId,
|
||||
parentThreadId: threadId,
|
||||
parentResourceId: 'draft-chat:test',
|
||||
parentPrincipalHash: 'principal',
|
||||
title: 'Saved result',
|
||||
kind: 'workflow',
|
||||
status: 'completed',
|
||||
result: '{"completed":true}',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => await Container.get(DbConnection).close());
|
||||
|
||||
it('preserves jobs and supports plan deletion, rollback, and reapplication', async () => {
|
||||
await runSingleMigration(migrationName);
|
||||
await withContext(async ({ escape, runQuery, queryRunner, tablePrefix }) => {
|
||||
const table = await queryRunner.getTable(`${tablePrefix}agent_background_job`);
|
||||
expect(table?.findColumnByName('planId')).toMatchObject({ isNullable: true });
|
||||
expect(table?.findColumnByName('planTaskId')).toMatchObject({ isNullable: true });
|
||||
expect(
|
||||
table?.indices.some((index) => index.columnNames.join(',') === 'planId,planTaskId'),
|
||||
).toBe(true);
|
||||
expect(table?.foreignKeys.filter((key) => key.columnNames.includes('planId'))).toHaveLength(
|
||||
1,
|
||||
);
|
||||
expect(table?.findColumnByName('detached')).toBeUndefined();
|
||||
expect(
|
||||
(await queryRunner.getTable(`${tablePrefix}agent_message_queue`))?.findColumnByName('held'),
|
||||
).toBeUndefined();
|
||||
await runQuery(
|
||||
`UPDATE ${escape.tableName('agent_background_job')} SET ${escape.columnName('planId')} = :planId, ${escape.columnName('planTaskId')} = :planTaskId WHERE ${escape.columnName('id')} = :jobId`,
|
||||
{ planId, planTaskId, jobId },
|
||||
);
|
||||
await runQuery(
|
||||
`DELETE FROM ${escape.tableName('agent_plan')} WHERE ${escape.columnName('id')} = :planId`,
|
||||
{ planId },
|
||||
);
|
||||
expect(
|
||||
await runQuery(
|
||||
`SELECT ${escape.columnName('planId')}, ${escape.columnName('result')} FROM ${escape.tableName('agent_background_job')}`,
|
||||
),
|
||||
).toEqual([{ planId: null, result: '{"completed":true}' }]);
|
||||
});
|
||||
await undoLastSingleMigration();
|
||||
await withContext(async ({ escape, runQuery, queryRunner, tablePrefix }) => {
|
||||
expect(
|
||||
(await queryRunner.getTable(`${tablePrefix}agent_background_job`))?.findColumnByName(
|
||||
'planId',
|
||||
),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
await runQuery(
|
||||
`SELECT ${escape.columnName('result')} FROM ${escape.tableName('agent_background_job')}`,
|
||||
),
|
||||
).toEqual([{ result: '{"completed":true}' }]);
|
||||
});
|
||||
await runSingleMigration(migrationName);
|
||||
await withContext(async ({ queryRunner, tablePrefix }) => {
|
||||
const table = await queryRunner.getTable(`${tablePrefix}agent_background_job`);
|
||||
expect(table?.foreignKeys.filter((key) => key.columnNames.includes('planId'))).toHaveLength(
|
||||
1,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user