@polpo-ai/drizzle 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/LICENSE +21 -0
  2. package/dist/__tests__/stores.test.d.ts +2 -0
  3. package/dist/__tests__/stores.test.d.ts.map +1 -0
  4. package/dist/__tests__/stores.test.js +922 -0
  5. package/dist/__tests__/stores.test.js.map +1 -0
  6. package/dist/index.d.ts +4811 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +129 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/migrate.d.ts +8 -0
  11. package/dist/migrate.d.ts.map +1 -0
  12. package/dist/migrate.js +214 -0
  13. package/dist/migrate.js.map +1 -0
  14. package/dist/schema/approvals.d.ts +413 -0
  15. package/dist/schema/approvals.d.ts.map +1 -0
  16. package/dist/schema/approvals.js +37 -0
  17. package/dist/schema/approvals.js.map +1 -0
  18. package/dist/schema/index.d.ts +17 -0
  19. package/dist/schema/index.d.ts.map +1 -0
  20. package/dist/schema/index.js +19 -0
  21. package/dist/schema/index.js.map +1 -0
  22. package/dist/schema/logs.d.ts +281 -0
  23. package/dist/schema/logs.d.ts.map +1 -0
  24. package/dist/schema/logs.js +33 -0
  25. package/dist/schema/logs.js.map +1 -0
  26. package/dist/schema/memory.d.ts +87 -0
  27. package/dist/schema/memory.d.ts.map +1 -0
  28. package/dist/schema/memory.js +13 -0
  29. package/dist/schema/memory.js.map +1 -0
  30. package/dist/schema/notifications.d.ts +521 -0
  31. package/dist/schema/notifications.d.ts.map +1 -0
  32. package/dist/schema/notifications.js +47 -0
  33. package/dist/schema/notifications.js.map +1 -0
  34. package/dist/schema/peers.d.ts +743 -0
  35. package/dist/schema/peers.d.ts.map +1 -0
  36. package/dist/schema/peers.js +71 -0
  37. package/dist/schema/peers.js.map +1 -0
  38. package/dist/schema/runs.d.ts +483 -0
  39. package/dist/schema/runs.d.ts.map +1 -0
  40. package/dist/schema/runs.js +41 -0
  41. package/dist/schema/runs.js.map +1 -0
  42. package/dist/schema/sessions.d.ts +389 -0
  43. package/dist/schema/sessions.d.ts.map +1 -0
  44. package/dist/schema/sessions.js +37 -0
  45. package/dist/schema/sessions.js.map +1 -0
  46. package/dist/schema/tasks.d.ts +1843 -0
  47. package/dist/schema/tasks.d.ts.map +1 -0
  48. package/dist/schema/tasks.js +135 -0
  49. package/dist/schema/tasks.js.map +1 -0
  50. package/dist/stores/approval-store.d.ts +19 -0
  51. package/dist/stores/approval-store.d.ts.map +1 -0
  52. package/dist/stores/approval-store.js +77 -0
  53. package/dist/stores/approval-store.js.map +1 -0
  54. package/dist/stores/checkpoint-store.d.ts +14 -0
  55. package/dist/stores/checkpoint-store.d.ts.map +1 -0
  56. package/dist/stores/checkpoint-store.js +44 -0
  57. package/dist/stores/checkpoint-store.js.map +1 -0
  58. package/dist/stores/config-store.d.ts +15 -0
  59. package/dist/stores/config-store.d.ts.map +1 -0
  60. package/dist/stores/config-store.js +31 -0
  61. package/dist/stores/config-store.js.map +1 -0
  62. package/dist/stores/delay-store.d.ts +14 -0
  63. package/dist/stores/delay-store.d.ts.map +1 -0
  64. package/dist/stores/delay-store.js +42 -0
  65. package/dist/stores/delay-store.js.map +1 -0
  66. package/dist/stores/index.d.ts +13 -0
  67. package/dist/stores/index.d.ts.map +1 -0
  68. package/dist/stores/index.js +12 -0
  69. package/dist/stores/index.js.map +1 -0
  70. package/dist/stores/log-store.d.ts +20 -0
  71. package/dist/stores/log-store.d.ts.map +1 -0
  72. package/dist/stores/log-store.js +87 -0
  73. package/dist/stores/log-store.js.map +1 -0
  74. package/dist/stores/memory-store.d.ts +14 -0
  75. package/dist/stores/memory-store.d.ts.map +1 -0
  76. package/dist/stores/memory-store.js +39 -0
  77. package/dist/stores/memory-store.js.map +1 -0
  78. package/dist/stores/notification-store.d.ts +20 -0
  79. package/dist/stores/notification-store.d.ts.map +1 -0
  80. package/dist/stores/notification-store.js +111 -0
  81. package/dist/stores/notification-store.js.map +1 -0
  82. package/dist/stores/peer-store.d.ts +40 -0
  83. package/dist/stores/peer-store.d.ts.map +1 -0
  84. package/dist/stores/peer-store.js +203 -0
  85. package/dist/stores/peer-store.js.map +1 -0
  86. package/dist/stores/run-store.d.ts +23 -0
  87. package/dist/stores/run-store.d.ts.map +1 -0
  88. package/dist/stores/run-store.js +120 -0
  89. package/dist/stores/run-store.js.map +1 -0
  90. package/dist/stores/session-store.d.ts +26 -0
  91. package/dist/stores/session-store.d.ts.map +1 -0
  92. package/dist/stores/session-store.js +166 -0
  93. package/dist/stores/session-store.js.map +1 -0
  94. package/dist/stores/task-store.d.ts +42 -0
  95. package/dist/stores/task-store.d.ts.map +1 -0
  96. package/dist/stores/task-store.js +387 -0
  97. package/dist/stores/task-store.js.map +1 -0
  98. package/dist/utils.d.ts +11 -0
  99. package/dist/utils.d.ts.map +1 -0
  100. package/dist/utils.js +24 -0
  101. package/dist/utils.js.map +1 -0
  102. package/package.json +74 -0
@@ -0,0 +1,26 @@
1
+ import type { SessionStore, Session, Message, MessageRole, ToolCallInfo } from "@polpo-ai/core/session-store";
2
+ import { type Dialect } from "../utils.js";
3
+ type AnyTable = any;
4
+ export declare class DrizzleSessionStore implements SessionStore {
5
+ private db;
6
+ private sessions;
7
+ private messages;
8
+ private dialect;
9
+ constructor(db: any, sessions: AnyTable, messages: AnyTable, dialect: Dialect);
10
+ private rowToSession;
11
+ private rowToMessage;
12
+ create(title?: string): Promise<string>;
13
+ addMessage(sessionId: string, role: MessageRole, content: string): Promise<Message>;
14
+ updateMessage(sessionId: string, messageId: string, content: string, toolCalls?: ToolCallInfo[]): Promise<boolean>;
15
+ getMessages(sessionId: string): Promise<Message[]>;
16
+ getRecentMessages(sessionId: string, limit: number): Promise<Message[]>;
17
+ listSessions(): Promise<Session[]>;
18
+ getSession(sessionId: string): Promise<Session | undefined>;
19
+ getLatestSession(): Promise<Session | undefined>;
20
+ renameSession(sessionId: string, title: string): Promise<boolean>;
21
+ deleteSession(sessionId: string): Promise<boolean>;
22
+ prune(keepSessions: number): Promise<number>;
23
+ close(): Promise<void>;
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=session-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/stores/session-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC9G,OAAO,EAAE,KAAK,OAAO,EAAmB,MAAM,aAAa,CAAC;AAE5D,KAAK,QAAQ,GAAG,GAAG,CAAC;AAEpB,qBAAa,mBAAoB,YAAW,YAAY;IAEpD,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;gBAHP,EAAE,EAAE,GAAG,EACP,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO;IAG1B,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,YAAY;IAUd,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAYvC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBnF,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAmBlH,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAOlD,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAQvE,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAiBlC,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAiB3D,gBAAgB,IAAI,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAkBhD,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAQjE,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOlD,KAAK,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgB5C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -0,0 +1,166 @@
1
+ import { eq, desc, asc, count as drizzleCount } from "drizzle-orm";
2
+ import { nanoid } from "nanoid";
3
+ import { deserializeJson } from "../utils.js";
4
+ export class DrizzleSessionStore {
5
+ db;
6
+ sessions;
7
+ messages;
8
+ dialect;
9
+ constructor(db, sessions, messages, dialect) {
10
+ this.db = db;
11
+ this.sessions = sessions;
12
+ this.messages = messages;
13
+ this.dialect = dialect;
14
+ }
15
+ rowToSession(row, messageCount) {
16
+ return {
17
+ id: row.id,
18
+ title: row.title ?? undefined,
19
+ createdAt: row.createdAt,
20
+ updatedAt: row.updatedAt,
21
+ messageCount,
22
+ };
23
+ }
24
+ rowToMessage(row) {
25
+ return {
26
+ id: row.id,
27
+ role: row.role,
28
+ content: row.content,
29
+ ts: row.ts,
30
+ toolCalls: deserializeJson(row.toolCalls, undefined, this.dialect),
31
+ };
32
+ }
33
+ async create(title) {
34
+ const id = nanoid(10);
35
+ const now = new Date().toISOString();
36
+ await this.db.insert(this.sessions).values({
37
+ id,
38
+ title: title ?? null,
39
+ createdAt: now,
40
+ updatedAt: now,
41
+ });
42
+ return id;
43
+ }
44
+ async addMessage(sessionId, role, content) {
45
+ const id = nanoid();
46
+ const ts = new Date().toISOString();
47
+ await this.db.insert(this.messages).values({
48
+ id,
49
+ sessionId,
50
+ role,
51
+ content,
52
+ ts,
53
+ toolCalls: null,
54
+ });
55
+ await this.db.update(this.sessions)
56
+ .set({ updatedAt: ts })
57
+ .where(eq(this.sessions.id, sessionId));
58
+ return { id, role, content, ts };
59
+ }
60
+ async updateMessage(sessionId, messageId, content, toolCalls) {
61
+ const now = new Date().toISOString();
62
+ const tcValue = toolCalls
63
+ ? (this.dialect === "sqlite" ? JSON.stringify(toolCalls) : toolCalls)
64
+ : null;
65
+ const result = await this.db.update(this.messages)
66
+ .set({ content, toolCalls: tcValue })
67
+ .where(eq(this.messages.id, messageId));
68
+ const changed = (result?.rowCount ?? result?.changes ?? 0) > 0;
69
+ if (changed) {
70
+ await this.db.update(this.sessions)
71
+ .set({ updatedAt: now })
72
+ .where(eq(this.sessions.id, sessionId));
73
+ }
74
+ return changed;
75
+ }
76
+ async getMessages(sessionId) {
77
+ const rows = await this.db.select().from(this.messages)
78
+ .where(eq(this.messages.sessionId, sessionId))
79
+ .orderBy(asc(this.messages.ts));
80
+ return rows.map((r) => this.rowToMessage(r));
81
+ }
82
+ async getRecentMessages(sessionId, limit) {
83
+ const rows = await this.db.select().from(this.messages)
84
+ .where(eq(this.messages.sessionId, sessionId))
85
+ .orderBy(desc(this.messages.ts))
86
+ .limit(limit);
87
+ return rows.reverse().map((r) => this.rowToMessage(r));
88
+ }
89
+ async listSessions() {
90
+ const rows = await this.db
91
+ .select({
92
+ id: this.sessions.id,
93
+ title: this.sessions.title,
94
+ createdAt: this.sessions.createdAt,
95
+ updatedAt: this.sessions.updatedAt,
96
+ messageCount: drizzleCount(this.messages.id),
97
+ })
98
+ .from(this.sessions)
99
+ .leftJoin(this.messages, eq(this.sessions.id, this.messages.sessionId))
100
+ .groupBy(this.sessions.id)
101
+ .orderBy(desc(this.sessions.updatedAt));
102
+ return rows.map((r) => this.rowToSession(r, Number(r.messageCount)));
103
+ }
104
+ async getSession(sessionId) {
105
+ const rows = await this.db
106
+ .select({
107
+ id: this.sessions.id,
108
+ title: this.sessions.title,
109
+ createdAt: this.sessions.createdAt,
110
+ updatedAt: this.sessions.updatedAt,
111
+ messageCount: drizzleCount(this.messages.id),
112
+ })
113
+ .from(this.sessions)
114
+ .leftJoin(this.messages, eq(this.sessions.id, this.messages.sessionId))
115
+ .where(eq(this.sessions.id, sessionId))
116
+ .groupBy(this.sessions.id);
117
+ return rows.length > 0 ? this.rowToSession(rows[0], Number(rows[0].messageCount)) : undefined;
118
+ }
119
+ async getLatestSession() {
120
+ const rows = await this.db
121
+ .select({
122
+ id: this.sessions.id,
123
+ title: this.sessions.title,
124
+ createdAt: this.sessions.createdAt,
125
+ updatedAt: this.sessions.updatedAt,
126
+ messageCount: drizzleCount(this.messages.id),
127
+ })
128
+ .from(this.sessions)
129
+ .leftJoin(this.messages, eq(this.sessions.id, this.messages.sessionId))
130
+ .groupBy(this.sessions.id)
131
+ .orderBy(desc(this.sessions.updatedAt))
132
+ .limit(1);
133
+ return rows.length > 0 ? this.rowToSession(rows[0], Number(rows[0].messageCount)) : undefined;
134
+ }
135
+ async renameSession(sessionId, title) {
136
+ const now = new Date().toISOString();
137
+ const result = await this.db.update(this.sessions)
138
+ .set({ title, updatedAt: now })
139
+ .where(eq(this.sessions.id, sessionId));
140
+ return (result?.rowCount ?? result?.changes ?? 0) > 0;
141
+ }
142
+ async deleteSession(sessionId) {
143
+ // Messages are cascade-deleted via FK
144
+ const result = await this.db.delete(this.sessions)
145
+ .where(eq(this.sessions.id, sessionId));
146
+ return (result?.rowCount ?? result?.changes ?? 0) > 0;
147
+ }
148
+ async prune(keepSessions) {
149
+ const all = await this.db.select({ id: this.sessions.id })
150
+ .from(this.sessions)
151
+ .orderBy(desc(this.sessions.updatedAt));
152
+ if (all.length <= keepSessions)
153
+ return 0;
154
+ const toDelete = all.slice(keepSessions).map((r) => r.id);
155
+ let deleted = 0;
156
+ for (const id of toDelete) {
157
+ await this.db.delete(this.sessions).where(eq(this.sessions.id, id));
158
+ deleted++;
159
+ }
160
+ return deleted;
161
+ }
162
+ async close() {
163
+ // Connection lifecycle managed externally
164
+ }
165
+ }
166
+ //# sourceMappingURL=session-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/stores/session-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import type { TaskStore } from "@polpo-ai/core/task-store";
2
+ import type { Task, TaskStatus, Mission, PolpoState } from "@polpo-ai/core/types";
3
+ import { type Dialect } from "../utils.js";
4
+ type AnyTable = any;
5
+ export interface TaskStoreSchema {
6
+ tasks: AnyTable;
7
+ missions: AnyTable;
8
+ metadata: AnyTable;
9
+ processes: AnyTable;
10
+ }
11
+ export declare class DrizzleTaskStore implements TaskStore {
12
+ private db;
13
+ private schema;
14
+ private dialect;
15
+ constructor(db: any, schema: TaskStoreSchema, dialect: Dialect);
16
+ private rowToTask;
17
+ private taskToValues;
18
+ private rowToMission;
19
+ private rowToProcess;
20
+ getState(): Promise<PolpoState>;
21
+ setState(partial: Partial<PolpoState>): Promise<void>;
22
+ addTask(input: Omit<Task, "id" | "status" | "retries" | "createdAt" | "updatedAt"> & {
23
+ status?: TaskStatus;
24
+ }): Promise<Task>;
25
+ getTask(taskId: string): Promise<Task | undefined>;
26
+ getAllTasks(): Promise<Task[]>;
27
+ updateTask(taskId: string, updates: Partial<Omit<Task, "id" | "status">>): Promise<Task>;
28
+ removeTask(taskId: string): Promise<boolean>;
29
+ removeTasks(filter: (task: Task) => boolean): Promise<number>;
30
+ transition(taskId: string, newStatus: TaskStatus): Promise<Task>;
31
+ unsafeSetStatus(taskId: string, newStatus: TaskStatus, _reason: string): Promise<Task>;
32
+ saveMission(input: Omit<Mission, "id" | "createdAt" | "updatedAt">): Promise<Mission>;
33
+ getMission(missionId: string): Promise<Mission | undefined>;
34
+ getMissionByName(name: string): Promise<Mission | undefined>;
35
+ getAllMissions(): Promise<Mission[]>;
36
+ updateMission(missionId: string, updates: Partial<Omit<Mission, "id">>): Promise<Mission>;
37
+ deleteMission(missionId: string): Promise<boolean>;
38
+ nextMissionName(): Promise<string>;
39
+ close(): Promise<void>;
40
+ }
41
+ export {};
42
+ //# sourceMappingURL=task-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/stores/task-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EACV,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EACtC,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,KAAK,OAAO,EAAkC,MAAM,aAAa,CAAC;AAG3E,KAAK,QAAQ,GAAG,GAAG,CAAC;AAEpB,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,QAAQ,CAAC;CACrB;AAED,qBAAa,gBAAiB,YAAW,SAAS;IAE9C,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,OAAO;gBAFP,EAAE,EAAE,GAAG,EACP,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,OAAO;IAK1B,OAAO,CAAC,SAAS;IAmCjB,OAAO,CAAC,YAAY;IAmCpB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,YAAY;IAed,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IA2B/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAuDrD,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG;QAAE,MAAM,CAAC,EAAE,UAAU,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAc5H,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAMlD,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAM9B,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAaxF,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAM5C,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAa7D,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBhE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IActF,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BrF,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAM3D,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;IAM5D,cAAc,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAMpC,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC;IAyBzF,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMlD,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAWlC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
@@ -0,0 +1,387 @@
1
+ import { eq, desc, asc } from "drizzle-orm";
2
+ import { nanoid } from "nanoid";
3
+ import { assertValidTransition } from "@polpo-ai/core/state-machine";
4
+ import { serializeJson, deserializeJson } from "../utils.js";
5
+ export class DrizzleTaskStore {
6
+ db;
7
+ schema;
8
+ dialect;
9
+ constructor(db, schema, dialect) {
10
+ this.db = db;
11
+ this.schema = schema;
12
+ this.dialect = dialect;
13
+ }
14
+ // ── Helpers ──────────────────────────────────────────────────────────
15
+ rowToTask(row) {
16
+ const d = this.dialect;
17
+ return {
18
+ id: row.id,
19
+ title: row.title,
20
+ description: row.description,
21
+ assignTo: row.assignTo,
22
+ group: row.group ?? undefined,
23
+ missionId: row.missionId ?? undefined,
24
+ dependsOn: deserializeJson(row.dependsOn, [], d),
25
+ status: row.status,
26
+ retries: row.retries,
27
+ maxRetries: row.maxRetries,
28
+ maxDuration: row.maxDuration ?? undefined,
29
+ retryPolicy: deserializeJson(row.retryPolicy, undefined, d),
30
+ expectations: deserializeJson(row.expectations, [], d),
31
+ metrics: deserializeJson(row.metrics, [], d),
32
+ result: deserializeJson(row.result, undefined, d),
33
+ phase: row.phase ?? undefined,
34
+ fixAttempts: row.fixAttempts ?? 0,
35
+ resolutionAttempts: row.resolutionAttempts ?? 0,
36
+ originalDescription: row.originalDescription ?? undefined,
37
+ sessionId: row.sessionId ?? undefined,
38
+ notifications: deserializeJson(row.notifications, undefined, d),
39
+ outcomes: deserializeJson(row.outcomes, undefined, d),
40
+ expectedOutcomes: deserializeJson(row.expectedOutcomes, undefined, d),
41
+ deadline: row.deadline ?? undefined,
42
+ priority: row.priority ? Number(row.priority) : undefined,
43
+ sideEffects: row.sideEffects ? Boolean(row.sideEffects) : undefined,
44
+ revisionCount: row.revisionCount ?? undefined,
45
+ createdAt: row.createdAt,
46
+ updatedAt: row.updatedAt,
47
+ };
48
+ }
49
+ taskToValues(task) {
50
+ const d = this.dialect;
51
+ const v = {};
52
+ if (task.id !== undefined)
53
+ v.id = task.id;
54
+ if (task.title !== undefined)
55
+ v.title = task.title;
56
+ if (task.description !== undefined)
57
+ v.description = task.description;
58
+ if (task.assignTo !== undefined)
59
+ v.assignTo = task.assignTo;
60
+ if (task.group !== undefined)
61
+ v.group = task.group;
62
+ if (task.missionId !== undefined)
63
+ v.missionId = task.missionId;
64
+ if (task.dependsOn !== undefined)
65
+ v.dependsOn = serializeJson(task.dependsOn, d);
66
+ if (task.status !== undefined)
67
+ v.status = task.status;
68
+ if (task.retries !== undefined)
69
+ v.retries = task.retries;
70
+ if (task.maxRetries !== undefined)
71
+ v.maxRetries = task.maxRetries;
72
+ if (task.maxDuration !== undefined)
73
+ v.maxDuration = task.maxDuration;
74
+ if (task.retryPolicy !== undefined)
75
+ v.retryPolicy = serializeJson(task.retryPolicy, d);
76
+ if (task.expectations !== undefined)
77
+ v.expectations = serializeJson(task.expectations, d);
78
+ if (task.metrics !== undefined)
79
+ v.metrics = serializeJson(task.metrics, d);
80
+ if (task.result !== undefined)
81
+ v.result = serializeJson(task.result, d);
82
+ if (task.phase !== undefined)
83
+ v.phase = task.phase;
84
+ if (task.fixAttempts !== undefined)
85
+ v.fixAttempts = task.fixAttempts;
86
+ if (task.resolutionAttempts !== undefined)
87
+ v.resolutionAttempts = task.resolutionAttempts;
88
+ if (task.originalDescription !== undefined)
89
+ v.originalDescription = task.originalDescription;
90
+ if (task.sessionId !== undefined)
91
+ v.sessionId = task.sessionId;
92
+ if (task.notifications !== undefined)
93
+ v.notifications = serializeJson(task.notifications, d);
94
+ if (task.outcomes !== undefined)
95
+ v.outcomes = serializeJson(task.outcomes, d);
96
+ if (task.expectedOutcomes !== undefined)
97
+ v.expectedOutcomes = serializeJson(task.expectedOutcomes, d);
98
+ if (task.deadline !== undefined)
99
+ v.deadline = task.deadline;
100
+ if (task.priority !== undefined)
101
+ v.priority = String(task.priority);
102
+ if (task.sideEffects !== undefined)
103
+ v.sideEffects = task.sideEffects ? 1 : 0;
104
+ if (task.revisionCount !== undefined)
105
+ v.revisionCount = task.revisionCount;
106
+ if (task.createdAt !== undefined)
107
+ v.createdAt = task.createdAt;
108
+ if (task.updatedAt !== undefined)
109
+ v.updatedAt = task.updatedAt;
110
+ return v;
111
+ }
112
+ rowToMission(row) {
113
+ const d = this.dialect;
114
+ return {
115
+ id: row.id,
116
+ name: row.name,
117
+ data: row.data,
118
+ prompt: row.prompt ?? undefined,
119
+ status: row.status,
120
+ schedule: row.schedule ?? undefined,
121
+ endDate: row.endDate ?? undefined,
122
+ qualityThreshold: row.qualityThreshold ? Number(row.qualityThreshold) : undefined,
123
+ deadline: row.deadline ?? undefined,
124
+ notifications: deserializeJson(row.notifications, undefined, d),
125
+ executionCount: row.executionCount ?? 0,
126
+ createdAt: row.createdAt,
127
+ updatedAt: row.updatedAt,
128
+ };
129
+ }
130
+ rowToProcess(row) {
131
+ return {
132
+ agentName: row.agentName,
133
+ pid: row.pid,
134
+ taskId: row.taskId,
135
+ startedAt: row.startedAt,
136
+ alive: Boolean(row.alive),
137
+ activity: deserializeJson(row.activity, {
138
+ filesCreated: [], filesEdited: [], toolCalls: 0, totalTokens: 0, lastUpdate: "",
139
+ }, this.dialect),
140
+ };
141
+ }
142
+ // ── State ────────────────────────────────────────────────────────────
143
+ async getState() {
144
+ const { metadata, tasks, processes } = this.schema;
145
+ const metaRows = await this.db.select().from(metadata);
146
+ const meta = {};
147
+ for (const r of metaRows)
148
+ meta[r.key] = r.value;
149
+ let teams = [];
150
+ if (meta.teams) {
151
+ teams = deserializeJson(meta.teams, [], this.dialect);
152
+ }
153
+ else if (meta.team) {
154
+ teams = [deserializeJson(meta.team, { name: "default", agents: [] }, this.dialect)];
155
+ }
156
+ const taskRows = await this.db.select().from(tasks).orderBy(asc(tasks.createdAt));
157
+ const procRows = await this.db.select().from(processes);
158
+ return {
159
+ project: meta.project ?? "",
160
+ teams,
161
+ tasks: taskRows.map((r) => this.rowToTask(r)),
162
+ processes: procRows.map((r) => this.rowToProcess(r)),
163
+ startedAt: meta.startedAt,
164
+ completedAt: meta.completedAt,
165
+ };
166
+ }
167
+ async setState(partial) {
168
+ const { metadata, tasks, processes } = this.schema;
169
+ const d = this.dialect;
170
+ // SQLite transactions require synchronous callbacks — execute directly.
171
+ const upsertMeta = (db, key, value) => db.insert(metadata).values({ key, value })
172
+ .onConflictDoUpdate({ target: metadata.key, set: { value } });
173
+ const exec = async (db) => {
174
+ if (partial.project !== undefined) {
175
+ await upsertMeta(db, "project", partial.project);
176
+ }
177
+ if (partial.teams !== undefined) {
178
+ const val = JSON.stringify(partial.teams);
179
+ await upsertMeta(db, "teams", val);
180
+ }
181
+ if (partial.startedAt !== undefined) {
182
+ await upsertMeta(db, "startedAt", partial.startedAt);
183
+ }
184
+ if (partial.completedAt !== undefined) {
185
+ await upsertMeta(db, "completedAt", partial.completedAt);
186
+ }
187
+ if (partial.processes !== undefined) {
188
+ await db.delete(processes);
189
+ for (const p of partial.processes) {
190
+ await db.insert(processes).values({
191
+ agentName: p.agentName,
192
+ pid: p.pid,
193
+ taskId: p.taskId,
194
+ startedAt: p.startedAt,
195
+ alive: p.alive ? 1 : 0,
196
+ activity: serializeJson(p.activity, d),
197
+ });
198
+ }
199
+ }
200
+ if (partial.tasks !== undefined) {
201
+ await db.delete(tasks);
202
+ for (const t of partial.tasks) {
203
+ await db.insert(tasks).values(this.taskToValues(t));
204
+ }
205
+ }
206
+ };
207
+ if (this.dialect === "pg") {
208
+ await this.db.transaction(async (tx) => exec(tx));
209
+ }
210
+ else {
211
+ // SQLite: better-sqlite3 transactions don't support async callbacks.
212
+ // Individual upserts are idempotent — no transaction needed for correctness.
213
+ await exec(this.db);
214
+ }
215
+ }
216
+ // ── Task CRUD ────────────────────────────────────────────────────────
217
+ async addTask(input) {
218
+ const now = new Date().toISOString();
219
+ const task = {
220
+ ...input,
221
+ id: nanoid(),
222
+ status: input.status ?? "pending",
223
+ retries: 0,
224
+ createdAt: now,
225
+ updatedAt: now,
226
+ };
227
+ await this.db.insert(this.schema.tasks).values(this.taskToValues(task));
228
+ return task;
229
+ }
230
+ async getTask(taskId) {
231
+ const rows = await this.db.select().from(this.schema.tasks)
232
+ .where(eq(this.schema.tasks.id, taskId));
233
+ return rows.length > 0 ? this.rowToTask(rows[0]) : undefined;
234
+ }
235
+ async getAllTasks() {
236
+ const rows = await this.db.select().from(this.schema.tasks)
237
+ .orderBy(asc(this.schema.tasks.createdAt));
238
+ return rows.map((r) => this.rowToTask(r));
239
+ }
240
+ async updateTask(taskId, updates) {
241
+ const existing = await this.getTask(taskId);
242
+ if (!existing)
243
+ throw new Error(`Task "${taskId}" not found`);
244
+ const now = new Date().toISOString();
245
+ const merged = { ...existing, ...updates, updatedAt: now };
246
+ const values = this.taskToValues(merged);
247
+ delete values.id;
248
+ await this.db.update(this.schema.tasks).set(values)
249
+ .where(eq(this.schema.tasks.id, taskId));
250
+ return merged;
251
+ }
252
+ async removeTask(taskId) {
253
+ const result = await this.db.delete(this.schema.tasks)
254
+ .where(eq(this.schema.tasks.id, taskId));
255
+ return (result?.rowCount ?? result?.changes ?? 0) > 0;
256
+ }
257
+ async removeTasks(filter) {
258
+ const all = await this.getAllTasks();
259
+ const toRemove = all.filter(filter);
260
+ if (toRemove.length === 0)
261
+ return 0;
262
+ for (const t of toRemove) {
263
+ await this.db.delete(this.schema.tasks)
264
+ .where(eq(this.schema.tasks.id, t.id));
265
+ }
266
+ return toRemove.length;
267
+ }
268
+ // ── State machine ───────────────────────────────────────────────────
269
+ async transition(taskId, newStatus) {
270
+ const task = await this.getTask(taskId);
271
+ if (!task)
272
+ throw new Error(`Task "${taskId}" not found`);
273
+ assertValidTransition(task.status, newStatus);
274
+ const now = new Date().toISOString();
275
+ const updates = { status: newStatus, updatedAt: now };
276
+ // Increment retries on failed → pending
277
+ if (task.status === "failed" && newStatus === "pending") {
278
+ updates.retries = task.retries + 1;
279
+ }
280
+ await this.db.update(this.schema.tasks).set(updates)
281
+ .where(eq(this.schema.tasks.id, taskId));
282
+ return { ...task, status: newStatus, updatedAt: now, retries: updates.retries ?? task.retries };
283
+ }
284
+ async unsafeSetStatus(taskId, newStatus, _reason) {
285
+ const task = await this.getTask(taskId);
286
+ if (!task)
287
+ throw new Error(`Task "${taskId}" not found`);
288
+ const now = new Date().toISOString();
289
+ await this.db.update(this.schema.tasks)
290
+ .set({ status: newStatus, updatedAt: now })
291
+ .where(eq(this.schema.tasks.id, taskId));
292
+ return { ...task, status: newStatus, updatedAt: now };
293
+ }
294
+ // ── Missions ─────────────────────────────────────────────────────────
295
+ async saveMission(input) {
296
+ const now = new Date().toISOString();
297
+ const mission = {
298
+ ...input,
299
+ id: nanoid(),
300
+ createdAt: now,
301
+ updatedAt: now,
302
+ };
303
+ const d = this.dialect;
304
+ await this.db.insert(this.schema.missions).values({
305
+ id: mission.id,
306
+ name: mission.name,
307
+ data: mission.data,
308
+ prompt: mission.prompt ?? null,
309
+ status: mission.status,
310
+ schedule: mission.schedule ?? null,
311
+ endDate: mission.endDate ?? null,
312
+ qualityThreshold: mission.qualityThreshold != null ? String(mission.qualityThreshold) : null,
313
+ deadline: mission.deadline ?? null,
314
+ notifications: serializeJson(mission.notifications, d),
315
+ executionCount: mission.executionCount ?? 0,
316
+ createdAt: mission.createdAt,
317
+ updatedAt: mission.updatedAt,
318
+ });
319
+ return mission;
320
+ }
321
+ async getMission(missionId) {
322
+ const rows = await this.db.select().from(this.schema.missions)
323
+ .where(eq(this.schema.missions.id, missionId));
324
+ return rows.length > 0 ? this.rowToMission(rows[0]) : undefined;
325
+ }
326
+ async getMissionByName(name) {
327
+ const rows = await this.db.select().from(this.schema.missions)
328
+ .where(eq(this.schema.missions.name, name));
329
+ return rows.length > 0 ? this.rowToMission(rows[0]) : undefined;
330
+ }
331
+ async getAllMissions() {
332
+ const rows = await this.db.select().from(this.schema.missions)
333
+ .orderBy(desc(this.schema.missions.createdAt));
334
+ return rows.map((r) => this.rowToMission(r));
335
+ }
336
+ async updateMission(missionId, updates) {
337
+ const existing = await this.getMission(missionId);
338
+ if (!existing)
339
+ throw new Error(`Mission "${missionId}" not found`);
340
+ const now = new Date().toISOString();
341
+ const d = this.dialect;
342
+ const values = { updatedAt: now };
343
+ if (updates.name !== undefined)
344
+ values.name = updates.name;
345
+ if (updates.data !== undefined)
346
+ values.data = updates.data;
347
+ if (updates.prompt !== undefined)
348
+ values.prompt = updates.prompt;
349
+ if (updates.status !== undefined)
350
+ values.status = updates.status;
351
+ if (updates.schedule !== undefined)
352
+ values.schedule = updates.schedule;
353
+ if (updates.endDate !== undefined)
354
+ values.endDate = updates.endDate;
355
+ if (updates.qualityThreshold !== undefined)
356
+ values.qualityThreshold = updates.qualityThreshold != null ? String(updates.qualityThreshold) : null;
357
+ if (updates.deadline !== undefined)
358
+ values.deadline = updates.deadline;
359
+ if (updates.notifications !== undefined)
360
+ values.notifications = serializeJson(updates.notifications, d);
361
+ if (updates.executionCount !== undefined)
362
+ values.executionCount = updates.executionCount;
363
+ await this.db.update(this.schema.missions).set(values)
364
+ .where(eq(this.schema.missions.id, missionId));
365
+ return { ...existing, ...updates, updatedAt: now };
366
+ }
367
+ async deleteMission(missionId) {
368
+ const result = await this.db.delete(this.schema.missions)
369
+ .where(eq(this.schema.missions.id, missionId));
370
+ return (result?.rowCount ?? result?.changes ?? 0) > 0;
371
+ }
372
+ async nextMissionName() {
373
+ const rows = await this.db.select().from(this.schema.missions)
374
+ .orderBy(desc(this.schema.missions.createdAt));
375
+ let maxNum = 0;
376
+ for (const r of rows) {
377
+ const match = r.name.match(/^mission-(\d+)$/);
378
+ if (match)
379
+ maxNum = Math.max(maxNum, Number(match[1]));
380
+ }
381
+ return `mission-${maxNum + 1}`;
382
+ }
383
+ async close() {
384
+ // Connection lifecycle managed externally
385
+ }
386
+ }
387
+ //# sourceMappingURL=task-store.js.map