devchain-cli 0.2.1 → 0.3.1

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 (152) hide show
  1. package/README.md +2 -0
  2. package/dist/cli.js +199 -42
  3. package/dist/drizzle/0018_whole_zodiak.sql +43 -0
  4. package/dist/drizzle/0019_flat_avengers.sql +3 -0
  5. package/dist/drizzle/0020_statuses_mcp_hidden.sql +1 -0
  6. package/dist/drizzle/meta/0018_snapshot.json +2920 -0
  7. package/dist/drizzle/meta/0019_snapshot.json +2943 -0
  8. package/dist/drizzle/meta/0020_snapshot.json +2951 -0
  9. package/dist/drizzle/meta/_journal.json +21 -0
  10. package/dist/server/app.module.js +11 -1
  11. package/dist/server/app.module.js.map +1 -1
  12. package/dist/server/common/config/env.config.d.ts +1 -0
  13. package/dist/server/common/config/env.config.js +4 -0
  14. package/dist/server/common/config/env.config.js.map +1 -1
  15. package/dist/server/common/filters/http-exception.filter.js +24 -1
  16. package/dist/server/common/filters/http-exception.filter.js.map +1 -1
  17. package/dist/server/common/logging/logger.js +4 -3
  18. package/dist/server/common/logging/logger.js.map +1 -1
  19. package/dist/server/main.js +0 -3
  20. package/dist/server/main.js.map +1 -1
  21. package/dist/server/modules/agents/agents.module.js +2 -1
  22. package/dist/server/modules/agents/agents.module.js.map +1 -1
  23. package/dist/server/modules/agents/controllers/agents.controller.d.ts +17 -2
  24. package/dist/server/modules/agents/controllers/agents.controller.js +84 -3
  25. package/dist/server/modules/agents/controllers/agents.controller.js.map +1 -1
  26. package/dist/server/modules/chat/dtos/chat.dto.d.ts +18 -18
  27. package/dist/server/modules/chat/services/invite-template.util.js +1 -1
  28. package/dist/server/modules/chat/services/invite-template.util.js.map +1 -1
  29. package/dist/server/modules/core/controllers/health.controller.d.ts +1 -0
  30. package/dist/server/modules/core/controllers/health.controller.js +23 -0
  31. package/dist/server/modules/core/controllers/health.controller.js.map +1 -1
  32. package/dist/server/modules/events/catalog/index.d.ts +40 -0
  33. package/dist/server/modules/events/catalog/index.js +2 -0
  34. package/dist/server/modules/events/catalog/index.js.map +1 -1
  35. package/dist/server/modules/events/catalog/terminal.watcher.triggered.d.ts +45 -0
  36. package/dist/server/modules/events/catalog/terminal.watcher.triggered.js +22 -0
  37. package/dist/server/modules/events/catalog/terminal.watcher.triggered.js.map +1 -0
  38. package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.d.ts +1 -0
  39. package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.js +30 -12
  40. package/dist/server/modules/events/subscribers/chat-message-delivery.subscriber.js.map +1 -1
  41. package/dist/server/modules/mcp/constants.js +5 -1
  42. package/dist/server/modules/mcp/constants.js.map +1 -1
  43. package/dist/server/modules/mcp/controllers/mcp-http.controller.js +78 -77
  44. package/dist/server/modules/mcp/controllers/mcp-http.controller.js.map +1 -1
  45. package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js +78 -77
  46. package/dist/server/modules/mcp/controllers/mcp-sdk.controller.js.map +1 -1
  47. package/dist/server/modules/mcp/dtos/mcp.dto.d.ts +125 -97
  48. package/dist/server/modules/mcp/dtos/mcp.dto.js +23 -26
  49. package/dist/server/modules/mcp/dtos/mcp.dto.js.map +1 -1
  50. package/dist/server/modules/mcp/services/instructions-resolver.d.ts +3 -0
  51. package/dist/server/modules/mcp/services/instructions-resolver.js +83 -2
  52. package/dist/server/modules/mcp/services/instructions-resolver.js.map +1 -1
  53. package/dist/server/modules/mcp/services/mcp.service.d.ts +3 -2
  54. package/dist/server/modules/mcp/services/mcp.service.js +549 -263
  55. package/dist/server/modules/mcp/services/mcp.service.js.map +1 -1
  56. package/dist/server/modules/projects/controllers/projects.controller.d.ts +42 -0
  57. package/dist/server/modules/projects/controllers/projects.controller.js +11 -0
  58. package/dist/server/modules/projects/controllers/projects.controller.js.map +1 -1
  59. package/dist/server/modules/projects/projects.module.js +2 -1
  60. package/dist/server/modules/projects/projects.module.js.map +1 -1
  61. package/dist/server/modules/projects/services/projects.service.d.ts +47 -1
  62. package/dist/server/modules/projects/services/projects.service.js +278 -22
  63. package/dist/server/modules/projects/services/projects.service.js.map +1 -1
  64. package/dist/server/modules/prompts/controllers/prompts.controller.d.ts +1 -1
  65. package/dist/server/modules/prompts/controllers/prompts.controller.js +26 -4
  66. package/dist/server/modules/prompts/controllers/prompts.controller.js.map +1 -1
  67. package/dist/server/modules/sessions/utils/template-renderer.js +1 -0
  68. package/dist/server/modules/sessions/utils/template-renderer.js.map +1 -1
  69. package/dist/server/modules/statuses/controllers/statuses.controller.js +2 -0
  70. package/dist/server/modules/statuses/controllers/statuses.controller.js.map +1 -1
  71. package/dist/server/modules/storage/db/schema.d.ts +613 -0
  72. package/dist/server/modules/storage/db/schema.js +50 -1
  73. package/dist/server/modules/storage/db/schema.js.map +1 -1
  74. package/dist/server/modules/storage/interfaces/storage.interface.d.ts +40 -2
  75. package/dist/server/modules/storage/interfaces/storage.interface.js.map +1 -1
  76. package/dist/server/modules/storage/local/local-storage.service.d.ts +18 -3
  77. package/dist/server/modules/storage/local/local-storage.service.js +407 -11
  78. package/dist/server/modules/storage/local/local-storage.service.js.map +1 -1
  79. package/dist/server/modules/storage/models/domain.models.d.ts +59 -1
  80. package/dist/server/modules/subscribers/actions/action.interface.d.ts +67 -0
  81. package/dist/server/modules/subscribers/actions/action.interface.js +3 -0
  82. package/dist/server/modules/subscribers/actions/action.interface.js.map +1 -0
  83. package/dist/server/modules/subscribers/actions/actions.registry.d.ts +7 -0
  84. package/dist/server/modules/subscribers/actions/actions.registry.js +37 -0
  85. package/dist/server/modules/subscribers/actions/actions.registry.js.map +1 -0
  86. package/dist/server/modules/subscribers/actions/restart-agent.action.d.ts +8 -0
  87. package/dist/server/modules/subscribers/actions/restart-agent.action.js +119 -0
  88. package/dist/server/modules/subscribers/actions/restart-agent.action.js.map +1 -0
  89. package/dist/server/modules/subscribers/actions/send-message.action.d.ts +2 -0
  90. package/dist/server/modules/subscribers/actions/send-message.action.js +83 -0
  91. package/dist/server/modules/subscribers/actions/send-message.action.js.map +1 -0
  92. package/dist/server/modules/subscribers/controllers/actions.controller.d.ts +6 -0
  93. package/dist/server/modules/subscribers/controllers/actions.controller.js +51 -0
  94. package/dist/server/modules/subscribers/controllers/actions.controller.js.map +1 -0
  95. package/dist/server/modules/subscribers/controllers/subscribers.controller.d.ts +17 -0
  96. package/dist/server/modules/subscribers/controllers/subscribers.controller.js +178 -0
  97. package/dist/server/modules/subscribers/controllers/subscribers.controller.js.map +1 -0
  98. package/dist/server/modules/subscribers/dtos/subscriber.dto.d.ts +251 -0
  99. package/dist/server/modules/subscribers/dtos/subscriber.dto.js +68 -0
  100. package/dist/server/modules/subscribers/dtos/subscriber.dto.js.map +1 -0
  101. package/dist/server/modules/subscribers/events/event-fields-catalog.d.ts +19 -0
  102. package/dist/server/modules/subscribers/events/event-fields-catalog.js +98 -0
  103. package/dist/server/modules/subscribers/events/event-fields-catalog.js.map +1 -0
  104. package/dist/server/modules/subscribers/services/automation-scheduler.service.d.ts +49 -0
  105. package/dist/server/modules/subscribers/services/automation-scheduler.service.js +300 -0
  106. package/dist/server/modules/subscribers/services/automation-scheduler.service.js.map +1 -0
  107. package/dist/server/modules/subscribers/services/subscriber-executor.service.d.ts +77 -0
  108. package/dist/server/modules/subscribers/services/subscriber-executor.service.js +576 -0
  109. package/dist/server/modules/subscribers/services/subscriber-executor.service.js.map +1 -0
  110. package/dist/server/modules/subscribers/services/subscribers.service.d.ts +14 -0
  111. package/dist/server/modules/subscribers/services/subscribers.service.js +70 -0
  112. package/dist/server/modules/subscribers/services/subscribers.service.js.map +1 -0
  113. package/dist/server/modules/subscribers/subscribers.module.d.ts +2 -0
  114. package/dist/server/modules/subscribers/subscribers.module.js +36 -0
  115. package/dist/server/modules/subscribers/subscribers.module.js.map +1 -0
  116. package/dist/server/modules/terminal/services/tmux.service.js +9 -6
  117. package/dist/server/modules/terminal/services/tmux.service.js.map +1 -1
  118. package/dist/server/modules/watchers/controllers/watchers.controller.d.ts +16 -0
  119. package/dist/server/modules/watchers/controllers/watchers.controller.js +180 -0
  120. package/dist/server/modules/watchers/controllers/watchers.controller.js.map +1 -0
  121. package/dist/server/modules/watchers/dtos/watcher.dto.d.ts +206 -0
  122. package/dist/server/modules/watchers/dtos/watcher.dto.js +54 -0
  123. package/dist/server/modules/watchers/dtos/watcher.dto.js.map +1 -0
  124. package/dist/server/modules/watchers/services/watcher-runner.service.d.ts +68 -0
  125. package/dist/server/modules/watchers/services/watcher-runner.service.js +477 -0
  126. package/dist/server/modules/watchers/services/watcher-runner.service.js.map +1 -0
  127. package/dist/server/modules/watchers/services/watchers.service.d.ts +29 -0
  128. package/dist/server/modules/watchers/services/watchers.service.js +98 -0
  129. package/dist/server/modules/watchers/services/watchers.service.js.map +1 -0
  130. package/dist/server/modules/watchers/watchers.module.d.ts +2 -0
  131. package/dist/server/modules/watchers/watchers.module.js +34 -0
  132. package/dist/server/modules/watchers/watchers.module.js.map +1 -0
  133. package/dist/server/templates/claude-codex-advanced.json +377 -0
  134. package/dist/server/templates/claude-opus.json +29 -25
  135. package/dist/server/templates/simple-codex.json +29 -25
  136. package/dist/server/test-setup-node.d.ts +1 -0
  137. package/dist/server/test-setup-node.js +8 -0
  138. package/dist/server/test-setup-node.js.map +1 -0
  139. package/dist/server/test-setup.js +2 -0
  140. package/dist/server/test-setup.js.map +1 -1
  141. package/dist/server/tsconfig.tsbuildinfo +1 -1
  142. package/dist/server/ui/assets/index-C9GXCjnF.js +700 -0
  143. package/dist/server/ui/assets/index-o0FbZg-1.css +32 -0
  144. package/dist/server/ui/index.html +2 -2
  145. package/dist/templates/claude-codex-advanced.json +377 -0
  146. package/dist/templates/claude-opus.json +29 -25
  147. package/dist/templates/simple-codex.json +29 -25
  148. package/package.json +58 -27
  149. package/dist/server/templates/codex-claude.json +0 -178
  150. package/dist/server/ui/assets/index-5Xb7jFMJ.js +0 -641
  151. package/dist/server/ui/assets/index-CbYIbCQV.css +0 -32
  152. package/dist/templates/codex-claude.json +0 -178
@@ -100,6 +100,21 @@ let LocalStorageService = class LocalStorageService {
100
100
  }
101
101
  }
102
102
  }
103
+ async buildMcpHiddenExclusionPredicate(projectId, epicsTable) {
104
+ const { sql } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
105
+ return sql `${epicsTable.id} NOT IN (
106
+ WITH RECURSIVE excluded_tree AS (
107
+ SELECT e.id FROM epics e
108
+ JOIN statuses s ON e.status_id = s.id
109
+ WHERE s.mcp_hidden = 1 AND e.project_id = ${projectId}
110
+ UNION ALL
111
+ SELECT e.id FROM epics e
112
+ JOIN excluded_tree et ON e.parent_id = et.id
113
+ WHERE e.project_id = ${projectId}
114
+ )
115
+ SELECT id FROM excluded_tree
116
+ )`;
117
+ }
103
118
  async ensureValidAgent(projectId, agentId) {
104
119
  if (!agentId) {
105
120
  return;
@@ -195,6 +210,7 @@ let LocalStorageService = class LocalStorageService {
195
210
  label: s.label,
196
211
  color: s.color,
197
212
  position: s.position,
213
+ mcpHidden: s.mcpHidden ?? false,
198
214
  createdAt: now,
199
215
  updatedAt: now,
200
216
  });
@@ -516,6 +532,7 @@ let LocalStorageService = class LocalStorageService {
516
532
  const status = {
517
533
  id: randomUUID(),
518
534
  ...data,
535
+ mcpHidden: data.mcpHidden ?? false,
519
536
  createdAt: now,
520
537
  updatedAt: now,
521
538
  };
@@ -525,6 +542,7 @@ let LocalStorageService = class LocalStorageService {
525
542
  label: status.label,
526
543
  color: status.color,
527
544
  position: status.position,
545
+ mcpHidden: status.mcpHidden,
528
546
  createdAt: status.createdAt,
529
547
  updatedAt: status.updatedAt,
530
548
  });
@@ -729,6 +747,12 @@ let LocalStorageService = class LocalStorageService {
729
747
  if (archivedFilter) {
730
748
  conditions.push(archivedFilter);
731
749
  }
750
+ if (options.excludeMcpHidden) {
751
+ conditions.push(await this.buildMcpHiddenExclusionPredicate(projectId, epics));
752
+ }
753
+ if (options.parentOnly) {
754
+ conditions.push(sql `${epics.parentId} IS NULL`);
755
+ }
732
756
  const whereClause = and(...conditions);
733
757
  const totalResult = await this.db
734
758
  .select({ count: sql `count(*)` })
@@ -763,7 +787,14 @@ let LocalStorageService = class LocalStorageService {
763
787
  const limit = options.limit ?? 100;
764
788
  const offset = options.offset ?? 0;
765
789
  const agent = await this.getAgentByName(projectId, options.agentName);
766
- const whereClause = and(eq(epics.projectId, projectId), eq(epics.agentId, agent.id));
790
+ const conditions = [
791
+ eq(epics.projectId, projectId),
792
+ eq(epics.agentId, agent.id),
793
+ ];
794
+ if (options.excludeMcpHidden) {
795
+ conditions.push(await this.buildMcpHiddenExclusionPredicate(projectId, epics));
796
+ }
797
+ const whereClause = and(...conditions);
767
798
  const totalResult = await this.db
768
799
  .select({ count: sql `count(*)` })
769
800
  .from(epics)
@@ -894,6 +925,120 @@ let LocalStorageService = class LocalStorageService {
894
925
  offset,
895
926
  };
896
927
  }
928
+ async listSubEpicsForParents(projectId, parentIds, options = {}) {
929
+ const result = new Map();
930
+ for (const parentId of parentIds) {
931
+ result.set(parentId, []);
932
+ }
933
+ if (parentIds.length === 0) {
934
+ return result;
935
+ }
936
+ const limitPerParent = options.limitPerParent ?? 50;
937
+ const listType = (options.type ?? 'active').toLowerCase();
938
+ let archivedCondition = '';
939
+ if (listType === 'active') {
940
+ archivedCondition = "AND lower(s.label) NOT LIKE '%archiv%'";
941
+ }
942
+ else if (listType === 'archived') {
943
+ archivedCondition = "AND lower(s.label) LIKE '%archiv%'";
944
+ }
945
+ const mcpHiddenCondition = options.excludeMcpHidden ? 'AND s.mcp_hidden != 1' : '';
946
+ const parentIdPlaceholders = parentIds.map(() => '?').join(', ');
947
+ const queryStr = `
948
+ WITH ranked AS (
949
+ SELECT
950
+ e.id,
951
+ e.project_id,
952
+ e.title,
953
+ e.description,
954
+ e.status_id,
955
+ e.parent_id,
956
+ e.agent_id,
957
+ e.version,
958
+ e.data,
959
+ e.created_at,
960
+ e.updated_at,
961
+ ROW_NUMBER() OVER (
962
+ PARTITION BY e.parent_id
963
+ ORDER BY e.updated_at DESC, e.id DESC
964
+ ) as row_num
965
+ FROM epics e
966
+ INNER JOIN statuses s ON s.id = e.status_id
967
+ WHERE e.project_id = ?
968
+ AND e.parent_id IN (${parentIdPlaceholders})
969
+ ${archivedCondition}
970
+ ${mcpHiddenCondition}
971
+ )
972
+ SELECT * FROM ranked WHERE row_num <= ?
973
+ ORDER BY parent_id, row_num
974
+ `;
975
+ const sqlite = (0, sqlite_raw_1.getRawSqliteClient)(this.db);
976
+ if (!sqlite || typeof sqlite.prepare !== 'function') {
977
+ throw new error_types_1.StorageError('Unable to access underlying SQLite client for sub-epic batching');
978
+ }
979
+ const stmt = sqlite.prepare(queryStr);
980
+ const rows = stmt.all(projectId, ...parentIds, limitPerParent);
981
+ const allEpics = [];
982
+ for (const row of rows) {
983
+ if (!row.parent_id)
984
+ continue;
985
+ const epic = {
986
+ id: row.id,
987
+ projectId: row.project_id,
988
+ title: row.title,
989
+ description: row.description,
990
+ statusId: row.status_id,
991
+ parentId: row.parent_id,
992
+ agentId: row.agent_id,
993
+ version: row.version,
994
+ data: row.data ? JSON.parse(row.data) : null,
995
+ tags: [],
996
+ createdAt: row.created_at,
997
+ updatedAt: row.updated_at,
998
+ };
999
+ allEpics.push(epic);
1000
+ const group = result.get(row.parent_id) ?? [];
1001
+ group.push(epic);
1002
+ result.set(row.parent_id, group);
1003
+ }
1004
+ if (allEpics.length > 0) {
1005
+ const epicIds = allEpics.map((e) => e.id);
1006
+ const tagsMap = await this.batchFetchTags(epicIds);
1007
+ for (const epic of allEpics) {
1008
+ epic.tags = tagsMap.get(epic.id) ?? [];
1009
+ }
1010
+ }
1011
+ return result;
1012
+ }
1013
+ async batchFetchTags(epicIds) {
1014
+ const tagsMap = new Map();
1015
+ if (epicIds.length === 0) {
1016
+ return tagsMap;
1017
+ }
1018
+ const { epicTags, tags } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
1019
+ const { eq, inArray } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
1020
+ const CHUNK_SIZE = 500;
1021
+ const chunks = [];
1022
+ for (let i = 0; i < epicIds.length; i += CHUNK_SIZE) {
1023
+ chunks.push(epicIds.slice(i, i + CHUNK_SIZE));
1024
+ }
1025
+ for (const chunk of chunks) {
1026
+ const rows = await this.db
1027
+ .select({
1028
+ epicId: epicTags.epicId,
1029
+ tagName: tags.name,
1030
+ })
1031
+ .from(epicTags)
1032
+ .innerJoin(tags, eq(epicTags.tagId, tags.id))
1033
+ .where(inArray(epicTags.epicId, chunk));
1034
+ for (const row of rows) {
1035
+ const existing = tagsMap.get(row.epicId) ?? [];
1036
+ existing.push(row.tagName);
1037
+ tagsMap.set(row.epicId, existing);
1038
+ }
1039
+ }
1040
+ return tagsMap;
1041
+ }
897
1042
  async countSubEpicsByStatus(parentId) {
898
1043
  await this.getEpic(parentId);
899
1044
  const { epics } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
@@ -1038,17 +1183,75 @@ let LocalStorageService = class LocalStorageService {
1038
1183
  tags: promptTagsResult.map((pt) => pt.tag.name),
1039
1184
  };
1040
1185
  }
1041
- async listPrompts(projectId, options = {}) {
1042
- const { prompts } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
1043
- const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
1044
- const limit = options.limit || 100;
1045
- const offset = options.offset || 0;
1046
- const query = projectId ? eq(prompts.projectId, projectId) : undefined;
1047
- const items = await this.db.select().from(prompts).where(query).limit(limit).offset(offset);
1048
- const itemsWithTags = await Promise.all(items.map((item) => this.getPrompt(item.id)));
1186
+ async listPrompts(filters = {}) {
1187
+ const { prompts, promptTags, tags } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
1188
+ const { and, eq, isNull, desc, sql } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
1189
+ const whereClauses = [];
1190
+ if (filters.projectId !== undefined) {
1191
+ whereClauses.push(filters.projectId === null
1192
+ ? isNull(prompts.projectId)
1193
+ : eq(prompts.projectId, filters.projectId));
1194
+ }
1195
+ const searchTerm = filters.q?.trim();
1196
+ if (searchTerm) {
1197
+ const pattern = `%${searchTerm.toLowerCase()}%`;
1198
+ whereClauses.push(sql `lower(${prompts.title}) LIKE ${pattern}`);
1199
+ }
1200
+ const whereCondition = whereClauses.length === 0
1201
+ ? undefined
1202
+ : whereClauses.length === 1
1203
+ ? whereClauses[0]
1204
+ : and(...whereClauses);
1205
+ const selectFields = {
1206
+ id: prompts.id,
1207
+ projectId: prompts.projectId,
1208
+ title: prompts.title,
1209
+ content: prompts.content,
1210
+ version: prompts.version,
1211
+ createdAt: prompts.createdAt,
1212
+ updatedAt: prompts.updatedAt,
1213
+ };
1214
+ const rows = await (whereCondition
1215
+ ? this.db
1216
+ .select(selectFields)
1217
+ .from(prompts)
1218
+ .where(whereCondition)
1219
+ .orderBy(desc(prompts.updatedAt))
1220
+ : this.db.select(selectFields).from(prompts).orderBy(desc(prompts.updatedAt)));
1221
+ if (!rows.length) {
1222
+ return {
1223
+ items: [],
1224
+ total: 0,
1225
+ limit: filters.limit ?? 100,
1226
+ offset: filters.offset ?? 0,
1227
+ };
1228
+ }
1229
+ const PREVIEW_LENGTH = 200;
1230
+ const promptsWithTags = await Promise.all(rows.map(async (row) => {
1231
+ const tagRows = await this.db
1232
+ .select({ tagName: tags.name })
1233
+ .from(promptTags)
1234
+ .innerJoin(tags, eq(tags.id, promptTags.tagId))
1235
+ .where(eq(promptTags.promptId, row.id));
1236
+ const content = row.content ?? '';
1237
+ const contentPreview = content.length > PREVIEW_LENGTH ? content.slice(0, PREVIEW_LENGTH) + '…' : content;
1238
+ return {
1239
+ id: row.id,
1240
+ projectId: row.projectId,
1241
+ title: row.title,
1242
+ contentPreview,
1243
+ version: row.version,
1244
+ tags: tagRows.map((t) => t.tagName),
1245
+ createdAt: row.createdAt,
1246
+ updatedAt: row.updatedAt,
1247
+ };
1248
+ }));
1249
+ const limit = filters.limit ?? 100;
1250
+ const offset = filters.offset ?? 0;
1251
+ const items = promptsWithTags.slice(offset, offset + limit);
1049
1252
  return {
1050
- items: itemsWithTags,
1051
- total: items.length,
1253
+ items,
1254
+ total: promptsWithTags.length,
1052
1255
  limit,
1053
1256
  offset,
1054
1257
  };
@@ -2094,6 +2297,199 @@ let LocalStorageService = class LocalStorageService {
2094
2297
  });
2095
2298
  }
2096
2299
  }
2300
+ async listWatchers(projectId) {
2301
+ const { terminalWatchers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2302
+ const { eq, desc } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2303
+ const rows = await this.db
2304
+ .select()
2305
+ .from(terminalWatchers)
2306
+ .where(eq(terminalWatchers.projectId, projectId))
2307
+ .orderBy(desc(terminalWatchers.createdAt));
2308
+ return rows.map((row) => ({
2309
+ ...row,
2310
+ condition: row.condition,
2311
+ }));
2312
+ }
2313
+ async getWatcher(id) {
2314
+ const { terminalWatchers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2315
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2316
+ const result = await this.db
2317
+ .select()
2318
+ .from(terminalWatchers)
2319
+ .where(eq(terminalWatchers.id, id))
2320
+ .limit(1);
2321
+ if (!result[0]) {
2322
+ return null;
2323
+ }
2324
+ return {
2325
+ ...result[0],
2326
+ condition: result[0].condition,
2327
+ };
2328
+ }
2329
+ async createWatcher(data) {
2330
+ const { randomUUID } = await Promise.resolve().then(() => __importStar(require('crypto')));
2331
+ const now = new Date().toISOString();
2332
+ const { terminalWatchers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2333
+ const watcher = {
2334
+ id: randomUUID(),
2335
+ ...data,
2336
+ createdAt: now,
2337
+ updatedAt: now,
2338
+ };
2339
+ await this.db.insert(terminalWatchers).values({
2340
+ id: watcher.id,
2341
+ projectId: watcher.projectId,
2342
+ name: watcher.name,
2343
+ description: watcher.description,
2344
+ enabled: watcher.enabled,
2345
+ scope: watcher.scope,
2346
+ scopeFilterId: watcher.scopeFilterId,
2347
+ pollIntervalMs: watcher.pollIntervalMs,
2348
+ viewportLines: watcher.viewportLines,
2349
+ condition: watcher.condition,
2350
+ cooldownMs: watcher.cooldownMs,
2351
+ cooldownMode: watcher.cooldownMode,
2352
+ eventName: watcher.eventName,
2353
+ createdAt: watcher.createdAt,
2354
+ updatedAt: watcher.updatedAt,
2355
+ });
2356
+ return watcher;
2357
+ }
2358
+ async updateWatcher(id, data) {
2359
+ const { terminalWatchers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2360
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2361
+ const now = new Date().toISOString();
2362
+ const existing = await this.getWatcher(id);
2363
+ if (!existing) {
2364
+ throw new error_types_1.NotFoundError('Watcher', id);
2365
+ }
2366
+ await this.db
2367
+ .update(terminalWatchers)
2368
+ .set({ ...data, updatedAt: now })
2369
+ .where(eq(terminalWatchers.id, id));
2370
+ const updated = await this.getWatcher(id);
2371
+ if (!updated) {
2372
+ throw new error_types_1.NotFoundError('Watcher', id);
2373
+ }
2374
+ return updated;
2375
+ }
2376
+ async deleteWatcher(id) {
2377
+ const { terminalWatchers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2378
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2379
+ await this.db.delete(terminalWatchers).where(eq(terminalWatchers.id, id));
2380
+ }
2381
+ async listEnabledWatchers() {
2382
+ const { terminalWatchers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2383
+ const { eq, desc } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2384
+ const rows = await this.db
2385
+ .select()
2386
+ .from(terminalWatchers)
2387
+ .where(eq(terminalWatchers.enabled, true))
2388
+ .orderBy(desc(terminalWatchers.createdAt));
2389
+ return rows.map((row) => ({
2390
+ ...row,
2391
+ condition: row.condition,
2392
+ }));
2393
+ }
2394
+ async listSubscribers(projectId) {
2395
+ const { automationSubscribers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2396
+ const { eq, desc } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2397
+ const rows = await this.db
2398
+ .select()
2399
+ .from(automationSubscribers)
2400
+ .where(eq(automationSubscribers.projectId, projectId))
2401
+ .orderBy(desc(automationSubscribers.createdAt));
2402
+ return rows.map((row) => ({
2403
+ ...row,
2404
+ eventFilter: row.eventFilter,
2405
+ actionInputs: row.actionInputs,
2406
+ }));
2407
+ }
2408
+ async getSubscriber(id) {
2409
+ const { automationSubscribers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2410
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2411
+ const result = await this.db
2412
+ .select()
2413
+ .from(automationSubscribers)
2414
+ .where(eq(automationSubscribers.id, id))
2415
+ .limit(1);
2416
+ if (!result[0]) {
2417
+ return null;
2418
+ }
2419
+ return {
2420
+ ...result[0],
2421
+ eventFilter: result[0].eventFilter,
2422
+ actionInputs: result[0].actionInputs,
2423
+ };
2424
+ }
2425
+ async createSubscriber(data) {
2426
+ const { randomUUID } = await Promise.resolve().then(() => __importStar(require('crypto')));
2427
+ const now = new Date().toISOString();
2428
+ const { automationSubscribers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2429
+ const subscriber = {
2430
+ id: randomUUID(),
2431
+ ...data,
2432
+ createdAt: now,
2433
+ updatedAt: now,
2434
+ };
2435
+ await this.db.insert(automationSubscribers).values({
2436
+ id: subscriber.id,
2437
+ projectId: subscriber.projectId,
2438
+ name: subscriber.name,
2439
+ description: subscriber.description,
2440
+ enabled: subscriber.enabled,
2441
+ eventName: subscriber.eventName,
2442
+ eventFilter: subscriber.eventFilter,
2443
+ actionType: subscriber.actionType,
2444
+ actionInputs: subscriber.actionInputs,
2445
+ delayMs: subscriber.delayMs,
2446
+ cooldownMs: subscriber.cooldownMs,
2447
+ retryOnError: subscriber.retryOnError,
2448
+ groupName: subscriber.groupName,
2449
+ position: subscriber.position,
2450
+ priority: subscriber.priority,
2451
+ createdAt: subscriber.createdAt,
2452
+ updatedAt: subscriber.updatedAt,
2453
+ });
2454
+ return subscriber;
2455
+ }
2456
+ async updateSubscriber(id, data) {
2457
+ const { automationSubscribers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2458
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2459
+ const now = new Date().toISOString();
2460
+ const existing = await this.getSubscriber(id);
2461
+ if (!existing) {
2462
+ throw new error_types_1.NotFoundError('Subscriber', id);
2463
+ }
2464
+ await this.db
2465
+ .update(automationSubscribers)
2466
+ .set({ ...data, updatedAt: now })
2467
+ .where(eq(automationSubscribers.id, id));
2468
+ const updated = await this.getSubscriber(id);
2469
+ if (!updated) {
2470
+ throw new error_types_1.NotFoundError('Subscriber', id);
2471
+ }
2472
+ return updated;
2473
+ }
2474
+ async deleteSubscriber(id) {
2475
+ const { automationSubscribers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2476
+ const { eq } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2477
+ await this.db.delete(automationSubscribers).where(eq(automationSubscribers.id, id));
2478
+ }
2479
+ async findSubscribersByEventName(projectId, eventName) {
2480
+ const { automationSubscribers } = await Promise.resolve().then(() => __importStar(require('../db/schema')));
2481
+ const { eq, and, desc } = await Promise.resolve().then(() => __importStar(require('drizzle-orm')));
2482
+ const rows = await this.db
2483
+ .select()
2484
+ .from(automationSubscribers)
2485
+ .where(and(eq(automationSubscribers.projectId, projectId), eq(automationSubscribers.eventName, eventName), eq(automationSubscribers.enabled, true)))
2486
+ .orderBy(desc(automationSubscribers.createdAt));
2487
+ return rows.map((row) => ({
2488
+ ...row,
2489
+ eventFilter: row.eventFilter,
2490
+ actionInputs: row.actionInputs,
2491
+ }));
2492
+ }
2097
2493
  };
2098
2494
  exports.LocalStorageService = LocalStorageService;
2099
2495
  exports.LocalStorageService = LocalStorageService = __decorate([