@probelabs/visor 0.1.165 → 0.1.166-ee

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 (88) hide show
  1. package/dist/index.js +2363 -141
  2. package/dist/pr-analyzer.d.ts +2 -1
  3. package/dist/pr-analyzer.d.ts.map +1 -1
  4. package/dist/providers/http-client-provider.d.ts.map +1 -1
  5. package/dist/sdk/{check-provider-registry-6P2KJ423.mjs → check-provider-registry-PU67PWTU.mjs} +5 -5
  6. package/dist/sdk/{check-provider-registry-TTVN3V2O.mjs → check-provider-registry-TGPICTHD.mjs} +5 -5
  7. package/dist/sdk/{chunk-EO4IJNM7.mjs → chunk-E7NRUDWL.mjs} +2 -2
  8. package/dist/sdk/{chunk-G5JBWW3O.mjs → chunk-P5P6BOO7.mjs} +161 -21
  9. package/dist/sdk/chunk-P5P6BOO7.mjs.map +1 -0
  10. package/dist/sdk/{chunk-GMHSXC5K.mjs → chunk-RV5SK4FZ.mjs} +3 -3
  11. package/dist/sdk/{chunk-S47KBQQK.mjs → chunk-T5USZCCM.mjs} +2 -2
  12. package/dist/sdk/{chunk-S47KBQQK.mjs.map → chunk-T5USZCCM.mjs.map} +1 -1
  13. package/dist/sdk/{chunk-GOJRNYTV.mjs → chunk-WSYVK6ML.mjs} +188 -22
  14. package/dist/sdk/chunk-WSYVK6ML.mjs.map +1 -0
  15. package/dist/sdk/{failure-condition-evaluator-N3VNLWZD.mjs → failure-condition-evaluator-GPANOHP2.mjs} +3 -3
  16. package/dist/sdk/{github-frontend-ATORHHF6.mjs → github-frontend-P274ISBJ.mjs} +3 -3
  17. package/dist/sdk/{host-JROON6IT.mjs → host-AIMRV5YL.mjs} +2 -2
  18. package/dist/sdk/{host-OBXKDFT7.mjs → host-QYPOS4R6.mjs} +2 -2
  19. package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
  20. package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
  21. package/dist/sdk/loader-NJCF7DUS.mjs +89 -0
  22. package/dist/sdk/loader-NJCF7DUS.mjs.map +1 -0
  23. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
  24. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  25. package/dist/sdk/{routing-QCDX43XD.mjs → routing-BXHP2E62.mjs} +4 -4
  26. package/dist/sdk/{schedule-tool-D5TSTGP2.mjs → schedule-tool-5FVFYH2A.mjs} +5 -5
  27. package/dist/sdk/{schedule-tool-XCGJI2VB.mjs → schedule-tool-MQHISNJ6.mjs} +5 -5
  28. package/dist/sdk/{schedule-tool-handler-DKHHPZAG.mjs → schedule-tool-handler-4TCT2P7A.mjs} +5 -5
  29. package/dist/sdk/{schedule-tool-handler-OKZ53WMC.mjs → schedule-tool-handler-TZYXM664.mjs} +5 -5
  30. package/dist/sdk/sdk.js +1779 -265
  31. package/dist/sdk/sdk.js.map +1 -1
  32. package/dist/sdk/sdk.mjs +4 -4
  33. package/dist/sdk/{trace-helpers-J5CJ4PUN.mjs → trace-helpers-UG6FOWVV.mjs} +2 -2
  34. package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
  35. package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
  36. package/dist/sdk/{workflow-check-provider-T6WFK4RB.mjs → workflow-check-provider-BE2SVYWW.mjs} +5 -5
  37. package/dist/sdk/{workflow-check-provider-WLUAJPAS.mjs → workflow-check-provider-QKHL6AFT.mjs} +5 -5
  38. package/dist/slack/socket-runner.d.ts +14 -0
  39. package/dist/slack/socket-runner.d.ts.map +1 -1
  40. package/dist/utils/oauth2-token-cache.d.ts +44 -0
  41. package/dist/utils/oauth2-token-cache.d.ts.map +1 -0
  42. package/package.json +2 -2
  43. package/dist/output/traces/run-2026-03-06T06-08-10-897Z.ndjson +0 -138
  44. package/dist/output/traces/run-2026-03-06T06-08-55-016Z.ndjson +0 -2235
  45. package/dist/sdk/check-provider-registry-4SHN3GSH.mjs +0 -29
  46. package/dist/sdk/chunk-G5JBWW3O.mjs.map +0 -1
  47. package/dist/sdk/chunk-GOJRNYTV.mjs.map +0 -1
  48. package/dist/sdk/chunk-J236ZVYX.mjs +0 -1502
  49. package/dist/sdk/chunk-J236ZVYX.mjs.map +0 -1
  50. package/dist/sdk/chunk-LDE33FGE.mjs +0 -443
  51. package/dist/sdk/chunk-LDE33FGE.mjs.map +0 -1
  52. package/dist/sdk/chunk-MYROK4LB.mjs +0 -43917
  53. package/dist/sdk/chunk-MYROK4LB.mjs.map +0 -1
  54. package/dist/sdk/chunk-XDIBL7QB.mjs +0 -739
  55. package/dist/sdk/chunk-XDIBL7QB.mjs.map +0 -1
  56. package/dist/sdk/failure-condition-evaluator-M6SIUQF4.mjs +0 -17
  57. package/dist/sdk/github-frontend-MHXL2Q2V.mjs +0 -1368
  58. package/dist/sdk/github-frontend-MHXL2Q2V.mjs.map +0 -1
  59. package/dist/sdk/routing-TGJD66Q5.mjs +0 -25
  60. package/dist/sdk/schedule-tool-C5QN5OQU.mjs +0 -35
  61. package/dist/sdk/schedule-tool-handler-OKZ53WMC.mjs.map +0 -1
  62. package/dist/sdk/schedule-tool-handler-ZUMPNAVY.mjs +0 -39
  63. package/dist/sdk/schedule-tool-handler-ZUMPNAVY.mjs.map +0 -1
  64. package/dist/sdk/trace-helpers-J5CJ4PUN.mjs.map +0 -1
  65. package/dist/sdk/trace-helpers-KFQJ7IAG.mjs +0 -25
  66. package/dist/sdk/trace-helpers-KFQJ7IAG.mjs.map +0 -1
  67. package/dist/sdk/workflow-check-provider-RBYA6ZGU.mjs +0 -29
  68. package/dist/sdk/workflow-check-provider-RBYA6ZGU.mjs.map +0 -1
  69. package/dist/sdk/workflow-check-provider-T6WFK4RB.mjs.map +0 -1
  70. package/dist/sdk/workflow-check-provider-WLUAJPAS.mjs.map +0 -1
  71. package/dist/traces/run-2026-03-06T06-08-10-897Z.ndjson +0 -138
  72. package/dist/traces/run-2026-03-06T06-08-55-016Z.ndjson +0 -2235
  73. /package/dist/sdk/{check-provider-registry-4SHN3GSH.mjs.map → check-provider-registry-PU67PWTU.mjs.map} +0 -0
  74. /package/dist/sdk/{check-provider-registry-6P2KJ423.mjs.map → check-provider-registry-TGPICTHD.mjs.map} +0 -0
  75. /package/dist/sdk/{chunk-EO4IJNM7.mjs.map → chunk-E7NRUDWL.mjs.map} +0 -0
  76. /package/dist/sdk/{chunk-GMHSXC5K.mjs.map → chunk-RV5SK4FZ.mjs.map} +0 -0
  77. /package/dist/sdk/{check-provider-registry-TTVN3V2O.mjs.map → failure-condition-evaluator-GPANOHP2.mjs.map} +0 -0
  78. /package/dist/sdk/{github-frontend-ATORHHF6.mjs.map → github-frontend-P274ISBJ.mjs.map} +0 -0
  79. /package/dist/sdk/{host-JROON6IT.mjs.map → host-AIMRV5YL.mjs.map} +0 -0
  80. /package/dist/sdk/{host-OBXKDFT7.mjs.map → host-QYPOS4R6.mjs.map} +0 -0
  81. /package/dist/sdk/{failure-condition-evaluator-M6SIUQF4.mjs.map → routing-BXHP2E62.mjs.map} +0 -0
  82. /package/dist/sdk/{failure-condition-evaluator-N3VNLWZD.mjs.map → schedule-tool-5FVFYH2A.mjs.map} +0 -0
  83. /package/dist/sdk/{routing-QCDX43XD.mjs.map → schedule-tool-MQHISNJ6.mjs.map} +0 -0
  84. /package/dist/sdk/{routing-TGJD66Q5.mjs.map → schedule-tool-handler-4TCT2P7A.mjs.map} +0 -0
  85. /package/dist/sdk/{schedule-tool-C5QN5OQU.mjs.map → schedule-tool-handler-TZYXM664.mjs.map} +0 -0
  86. /package/dist/sdk/{schedule-tool-D5TSTGP2.mjs.map → trace-helpers-UG6FOWVV.mjs.map} +0 -0
  87. /package/dist/sdk/{schedule-tool-XCGJI2VB.mjs.map → workflow-check-provider-BE2SVYWW.mjs.map} +0 -0
  88. /package/dist/sdk/{schedule-tool-handler-DKHHPZAG.mjs.map → workflow-check-provider-QKHL6AFT.mjs.map} +0 -0
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  FailureConditionEvaluator,
3
3
  init_failure_condition_evaluator
4
- } from "./chunk-XDIBL7QB.mjs";
5
- import "./chunk-S47KBQQK.mjs";
4
+ } from "./chunk-E7NRUDWL.mjs";
5
+ import "./chunk-T5USZCCM.mjs";
6
6
  import "./chunk-JL7JXCET.mjs";
7
7
  import "./chunk-25IC7KXZ.mjs";
8
8
  import "./chunk-LW3INISN.mjs";
@@ -14,4 +14,4 @@ init_failure_condition_evaluator();
14
14
  export {
15
15
  FailureConditionEvaluator
16
16
  };
17
- //# sourceMappingURL=failure-condition-evaluator-N3VNLWZD.mjs.map
17
+ //# sourceMappingURL=failure-condition-evaluator-GPANOHP2.mjs.map
@@ -9,8 +9,8 @@ import {
9
9
  import {
10
10
  failure_condition_evaluator_exports,
11
11
  init_failure_condition_evaluator
12
- } from "./chunk-XDIBL7QB.mjs";
13
- import "./chunk-S47KBQQK.mjs";
12
+ } from "./chunk-E7NRUDWL.mjs";
13
+ import "./chunk-T5USZCCM.mjs";
14
14
  import "./chunk-JL7JXCET.mjs";
15
15
  import "./chunk-25IC7KXZ.mjs";
16
16
  import "./chunk-LW3INISN.mjs";
@@ -1365,4 +1365,4 @@ init_github_frontend();
1365
1365
  export {
1366
1366
  GitHubFrontend
1367
1367
  };
1368
- //# sourceMappingURL=github-frontend-ATORHHF6.mjs.map
1368
+ //# sourceMappingURL=github-frontend-P274ISBJ.mjs.map
@@ -21,7 +21,7 @@ var init_host = __esm({
21
21
  const { NdjsonSink } = await import("./ndjson-sink-FD2PSXGD.mjs");
22
22
  this.frontends.push(new NdjsonSink(spec.config));
23
23
  } else if (spec.name === "github") {
24
- const { GitHubFrontend } = await import("./github-frontend-MHXL2Q2V.mjs");
24
+ const { GitHubFrontend } = await import("./github-frontend-P274ISBJ.mjs");
25
25
  this.frontends.push(new GitHubFrontend());
26
26
  } else if (spec.name === "slack") {
27
27
  const { SlackFrontend } = await import("./slack-frontend-QO7LW5BH.mjs");
@@ -60,4 +60,4 @@ init_host();
60
60
  export {
61
61
  FrontendsHost
62
62
  };
63
- //# sourceMappingURL=host-JROON6IT.mjs.map
63
+ //# sourceMappingURL=host-AIMRV5YL.mjs.map
@@ -21,7 +21,7 @@ var init_host = __esm({
21
21
  const { NdjsonSink } = await import("./ndjson-sink-FD2PSXGD.mjs");
22
22
  this.frontends.push(new NdjsonSink(spec.config));
23
23
  } else if (spec.name === "github") {
24
- const { GitHubFrontend } = await import("./github-frontend-ATORHHF6.mjs");
24
+ const { GitHubFrontend } = await import("./github-frontend-P274ISBJ.mjs");
25
25
  this.frontends.push(new GitHubFrontend());
26
26
  } else if (spec.name === "slack") {
27
27
  const { SlackFrontend } = await import("./slack-frontend-QO7LW5BH.mjs");
@@ -60,4 +60,4 @@ init_host();
60
60
  export {
61
61
  FrontendsHost
62
62
  };
63
- //# sourceMappingURL=host-OBXKDFT7.mjs.map
63
+ //# sourceMappingURL=host-QYPOS4R6.mjs.map
@@ -0,0 +1,527 @@
1
+ import {
2
+ init_logger,
3
+ logger
4
+ } from "./chunk-SZXICFQ3.mjs";
5
+ import "./chunk-UCMJJ3IM.mjs";
6
+ import {
7
+ __esm,
8
+ __require
9
+ } from "./chunk-J7LXIPZS.mjs";
10
+
11
+ // src/enterprise/scheduler/knex-store.ts
12
+ import * as fs from "fs";
13
+ import * as path from "path";
14
+ import { v4 as uuidv4 } from "uuid";
15
+ function toNum(val) {
16
+ if (val === null || val === void 0) return void 0;
17
+ return typeof val === "string" ? parseInt(val, 10) : val;
18
+ }
19
+ function safeJsonParse(value) {
20
+ if (!value) return void 0;
21
+ try {
22
+ return JSON.parse(value);
23
+ } catch {
24
+ return void 0;
25
+ }
26
+ }
27
+ function fromTriggerRow(row) {
28
+ return {
29
+ id: row.id,
30
+ creatorId: row.creator_id,
31
+ creatorContext: row.creator_context ?? void 0,
32
+ creatorName: row.creator_name ?? void 0,
33
+ description: row.description ?? void 0,
34
+ channels: safeJsonParse(row.channels),
35
+ fromUsers: safeJsonParse(row.from_users),
36
+ fromBots: row.from_bots === true || row.from_bots === 1,
37
+ contains: safeJsonParse(row.contains),
38
+ matchPattern: row.match_pattern ?? void 0,
39
+ threads: row.threads,
40
+ workflow: row.workflow,
41
+ inputs: safeJsonParse(row.inputs),
42
+ outputContext: safeJsonParse(row.output_context),
43
+ status: row.status,
44
+ enabled: row.enabled === true || row.enabled === 1,
45
+ createdAt: toNum(row.created_at)
46
+ };
47
+ }
48
+ function toTriggerInsertRow(trigger) {
49
+ return {
50
+ id: trigger.id,
51
+ creator_id: trigger.creatorId,
52
+ creator_context: trigger.creatorContext ?? null,
53
+ creator_name: trigger.creatorName ?? null,
54
+ description: trigger.description ?? null,
55
+ channels: trigger.channels ? JSON.stringify(trigger.channels) : null,
56
+ from_users: trigger.fromUsers ? JSON.stringify(trigger.fromUsers) : null,
57
+ from_bots: trigger.fromBots,
58
+ contains: trigger.contains ? JSON.stringify(trigger.contains) : null,
59
+ match_pattern: trigger.matchPattern ?? null,
60
+ threads: trigger.threads,
61
+ workflow: trigger.workflow,
62
+ inputs: trigger.inputs ? JSON.stringify(trigger.inputs) : null,
63
+ output_context: trigger.outputContext ? JSON.stringify(trigger.outputContext) : null,
64
+ status: trigger.status,
65
+ enabled: trigger.enabled,
66
+ created_at: trigger.createdAt
67
+ };
68
+ }
69
+ function fromDbRow(row) {
70
+ return {
71
+ id: row.id,
72
+ creatorId: row.creator_id,
73
+ creatorContext: row.creator_context ?? void 0,
74
+ creatorName: row.creator_name ?? void 0,
75
+ timezone: row.timezone,
76
+ schedule: row.schedule_expr,
77
+ runAt: toNum(row.run_at),
78
+ isRecurring: row.is_recurring === true || row.is_recurring === 1,
79
+ originalExpression: row.original_expression,
80
+ workflow: row.workflow ?? void 0,
81
+ workflowInputs: safeJsonParse(row.workflow_inputs),
82
+ outputContext: safeJsonParse(row.output_context),
83
+ status: row.status,
84
+ createdAt: toNum(row.created_at),
85
+ lastRunAt: toNum(row.last_run_at),
86
+ nextRunAt: toNum(row.next_run_at),
87
+ runCount: row.run_count,
88
+ failureCount: row.failure_count,
89
+ lastError: row.last_error ?? void 0,
90
+ previousResponse: row.previous_response ?? void 0
91
+ };
92
+ }
93
+ function toInsertRow(schedule) {
94
+ return {
95
+ id: schedule.id,
96
+ creator_id: schedule.creatorId,
97
+ creator_context: schedule.creatorContext ?? null,
98
+ creator_name: schedule.creatorName ?? null,
99
+ timezone: schedule.timezone,
100
+ schedule_expr: schedule.schedule,
101
+ run_at: schedule.runAt ?? null,
102
+ is_recurring: schedule.isRecurring,
103
+ original_expression: schedule.originalExpression,
104
+ workflow: schedule.workflow ?? null,
105
+ workflow_inputs: schedule.workflowInputs ? JSON.stringify(schedule.workflowInputs) : null,
106
+ output_context: schedule.outputContext ? JSON.stringify(schedule.outputContext) : null,
107
+ status: schedule.status,
108
+ created_at: schedule.createdAt,
109
+ last_run_at: schedule.lastRunAt ?? null,
110
+ next_run_at: schedule.nextRunAt ?? null,
111
+ run_count: schedule.runCount,
112
+ failure_count: schedule.failureCount,
113
+ last_error: schedule.lastError ?? null,
114
+ previous_response: schedule.previousResponse ?? null
115
+ };
116
+ }
117
+ var KnexStoreBackend;
118
+ var init_knex_store = __esm({
119
+ "src/enterprise/scheduler/knex-store.ts"() {
120
+ init_logger();
121
+ KnexStoreBackend = class {
122
+ knex = null;
123
+ driver;
124
+ connection;
125
+ constructor(driver, storageConfig, _haConfig) {
126
+ this.driver = driver;
127
+ this.connection = storageConfig.connection || {};
128
+ }
129
+ async initialize() {
130
+ const { createRequire } = __require("module");
131
+ const runtimeRequire = createRequire(__filename);
132
+ let knexFactory;
133
+ try {
134
+ knexFactory = runtimeRequire("knex");
135
+ } catch (err) {
136
+ const code = err?.code;
137
+ if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
138
+ throw new Error(
139
+ "knex is required for PostgreSQL/MySQL/MSSQL schedule storage. Install it with: npm install knex"
140
+ );
141
+ }
142
+ throw err;
143
+ }
144
+ const clientMap = {
145
+ postgresql: "pg",
146
+ mysql: "mysql2",
147
+ mssql: "tedious"
148
+ };
149
+ const client = clientMap[this.driver];
150
+ let connection;
151
+ if (this.connection.connection_string) {
152
+ connection = this.connection.connection_string;
153
+ } else if (this.driver === "mssql") {
154
+ connection = this.buildMssqlConnection();
155
+ } else {
156
+ connection = this.buildStandardConnection();
157
+ }
158
+ this.knex = knexFactory({
159
+ client,
160
+ connection,
161
+ pool: {
162
+ min: this.connection.pool?.min ?? 0,
163
+ max: this.connection.pool?.max ?? 10
164
+ }
165
+ });
166
+ await this.migrateSchema();
167
+ logger.info(`[KnexStore] Initialized (${this.driver})`);
168
+ }
169
+ buildStandardConnection() {
170
+ return {
171
+ host: this.connection.host || "localhost",
172
+ port: this.connection.port,
173
+ database: this.connection.database || "visor",
174
+ user: this.connection.user,
175
+ password: this.connection.password,
176
+ ssl: this.resolveSslConfig()
177
+ };
178
+ }
179
+ buildMssqlConnection() {
180
+ const ssl = this.connection.ssl;
181
+ const sslEnabled = ssl === true || typeof ssl === "object" && ssl.enabled !== false;
182
+ return {
183
+ server: this.connection.host || "localhost",
184
+ port: this.connection.port,
185
+ database: this.connection.database || "visor",
186
+ user: this.connection.user,
187
+ password: this.connection.password,
188
+ options: {
189
+ encrypt: sslEnabled,
190
+ trustServerCertificate: typeof ssl === "object" ? ssl.reject_unauthorized === false : !sslEnabled
191
+ }
192
+ };
193
+ }
194
+ resolveSslConfig() {
195
+ const ssl = this.connection.ssl;
196
+ if (ssl === false || ssl === void 0) return false;
197
+ if (ssl === true) return { rejectUnauthorized: true };
198
+ if (ssl.enabled === false) return false;
199
+ const result = {
200
+ rejectUnauthorized: ssl.reject_unauthorized !== false
201
+ };
202
+ if (ssl.ca) {
203
+ const caPath = this.validateSslPath(ssl.ca, "CA certificate");
204
+ result.ca = fs.readFileSync(caPath, "utf8");
205
+ }
206
+ if (ssl.cert) {
207
+ const certPath = this.validateSslPath(ssl.cert, "client certificate");
208
+ result.cert = fs.readFileSync(certPath, "utf8");
209
+ }
210
+ if (ssl.key) {
211
+ const keyPath = this.validateSslPath(ssl.key, "client key");
212
+ result.key = fs.readFileSync(keyPath, "utf8");
213
+ }
214
+ return result;
215
+ }
216
+ validateSslPath(filePath, label) {
217
+ const resolved = path.resolve(filePath);
218
+ if (resolved !== path.normalize(resolved)) {
219
+ throw new Error(`SSL ${label} path contains invalid sequences: ${filePath}`);
220
+ }
221
+ if (!fs.existsSync(resolved)) {
222
+ throw new Error(`SSL ${label} not found: ${filePath}`);
223
+ }
224
+ return resolved;
225
+ }
226
+ async shutdown() {
227
+ if (this.knex) {
228
+ await this.knex.destroy();
229
+ this.knex = null;
230
+ }
231
+ }
232
+ async migrateSchema() {
233
+ const knex = this.getKnex();
234
+ const exists = await knex.schema.hasTable("schedules");
235
+ if (!exists) {
236
+ await knex.schema.createTable("schedules", (table) => {
237
+ table.string("id", 36).primary();
238
+ table.string("creator_id", 255).notNullable().index();
239
+ table.string("creator_context", 255);
240
+ table.string("creator_name", 255);
241
+ table.string("timezone", 64).notNullable().defaultTo("UTC");
242
+ table.string("schedule_expr", 255);
243
+ table.bigInteger("run_at");
244
+ table.boolean("is_recurring").notNullable();
245
+ table.text("original_expression");
246
+ table.string("workflow", 255);
247
+ table.text("workflow_inputs");
248
+ table.text("output_context");
249
+ table.string("status", 20).notNullable().index();
250
+ table.bigInteger("created_at").notNullable();
251
+ table.bigInteger("last_run_at");
252
+ table.bigInteger("next_run_at");
253
+ table.integer("run_count").notNullable().defaultTo(0);
254
+ table.integer("failure_count").notNullable().defaultTo(0);
255
+ table.text("last_error");
256
+ table.text("previous_response");
257
+ table.index(["status", "next_run_at"]);
258
+ });
259
+ }
260
+ const triggersExist = await knex.schema.hasTable("message_triggers");
261
+ if (!triggersExist) {
262
+ await knex.schema.createTable("message_triggers", (table) => {
263
+ table.string("id", 36).primary();
264
+ table.string("creator_id", 255).notNullable().index();
265
+ table.string("creator_context", 255);
266
+ table.string("creator_name", 255);
267
+ table.text("description");
268
+ table.text("channels");
269
+ table.text("from_users");
270
+ table.boolean("from_bots").notNullable().defaultTo(false);
271
+ table.text("contains");
272
+ table.text("match_pattern");
273
+ table.string("threads", 20).notNullable().defaultTo("any");
274
+ table.string("workflow", 255).notNullable();
275
+ table.text("inputs");
276
+ table.text("output_context");
277
+ table.string("status", 20).notNullable().defaultTo("active").index();
278
+ table.boolean("enabled").notNullable().defaultTo(true);
279
+ table.bigInteger("created_at").notNullable();
280
+ });
281
+ }
282
+ const locksExist = await knex.schema.hasTable("scheduler_locks");
283
+ if (!locksExist) {
284
+ await knex.schema.createTable("scheduler_locks", (table) => {
285
+ table.string("lock_id", 255).primary();
286
+ table.string("node_id", 255).notNullable();
287
+ table.string("lock_token", 36).notNullable();
288
+ table.bigInteger("acquired_at").notNullable();
289
+ table.bigInteger("expires_at").notNullable();
290
+ });
291
+ }
292
+ }
293
+ getKnex() {
294
+ if (!this.knex) {
295
+ throw new Error("[KnexStore] Not initialized. Call initialize() first.");
296
+ }
297
+ return this.knex;
298
+ }
299
+ // --- CRUD ---
300
+ async create(schedule) {
301
+ const knex = this.getKnex();
302
+ const newSchedule = {
303
+ ...schedule,
304
+ id: uuidv4(),
305
+ createdAt: Date.now(),
306
+ runCount: 0,
307
+ failureCount: 0,
308
+ status: "active"
309
+ };
310
+ await knex("schedules").insert(toInsertRow(newSchedule));
311
+ logger.info(`[KnexStore] Created schedule ${newSchedule.id} for user ${newSchedule.creatorId}`);
312
+ return newSchedule;
313
+ }
314
+ async importSchedule(schedule) {
315
+ const knex = this.getKnex();
316
+ const existing = await knex("schedules").where("id", schedule.id).first();
317
+ if (existing) return;
318
+ await knex("schedules").insert(toInsertRow(schedule));
319
+ }
320
+ async get(id) {
321
+ const knex = this.getKnex();
322
+ const row = await knex("schedules").where("id", id).first();
323
+ return row ? fromDbRow(row) : void 0;
324
+ }
325
+ async update(id, patch) {
326
+ const knex = this.getKnex();
327
+ const existing = await knex("schedules").where("id", id).first();
328
+ if (!existing) return void 0;
329
+ const current = fromDbRow(existing);
330
+ const updated = { ...current, ...patch, id: current.id };
331
+ const row = toInsertRow(updated);
332
+ delete row.id;
333
+ await knex("schedules").where("id", id).update(row);
334
+ return updated;
335
+ }
336
+ async delete(id) {
337
+ const knex = this.getKnex();
338
+ const deleted = await knex("schedules").where("id", id).del();
339
+ if (deleted > 0) {
340
+ logger.info(`[KnexStore] Deleted schedule ${id}`);
341
+ return true;
342
+ }
343
+ return false;
344
+ }
345
+ // --- Queries ---
346
+ async getByCreator(creatorId) {
347
+ const knex = this.getKnex();
348
+ const rows = await knex("schedules").where("creator_id", creatorId);
349
+ return rows.map((r) => fromDbRow(r));
350
+ }
351
+ async getActiveSchedules() {
352
+ const knex = this.getKnex();
353
+ const rows = await knex("schedules").where("status", "active");
354
+ return rows.map((r) => fromDbRow(r));
355
+ }
356
+ async getDueSchedules(now) {
357
+ const ts = now ?? Date.now();
358
+ const knex = this.getKnex();
359
+ const bFalse = this.driver === "mssql" ? 0 : false;
360
+ const bTrue = this.driver === "mssql" ? 1 : true;
361
+ const rows = await knex("schedules").where("status", "active").andWhere(function() {
362
+ this.where(function() {
363
+ this.where("is_recurring", bFalse).whereNotNull("run_at").where("run_at", "<=", ts);
364
+ }).orWhere(function() {
365
+ this.where("is_recurring", bTrue).whereNotNull("next_run_at").where("next_run_at", "<=", ts);
366
+ });
367
+ });
368
+ return rows.map((r) => fromDbRow(r));
369
+ }
370
+ async findByWorkflow(creatorId, workflowName) {
371
+ const knex = this.getKnex();
372
+ const escaped = workflowName.toLowerCase().replace(/[%_\\]/g, "\\$&");
373
+ const pattern = `%${escaped}%`;
374
+ const rows = await knex("schedules").where("creator_id", creatorId).where("status", "active").whereRaw("LOWER(workflow) LIKE ? ESCAPE '\\'", [pattern]);
375
+ return rows.map((r) => fromDbRow(r));
376
+ }
377
+ async getAll() {
378
+ const knex = this.getKnex();
379
+ const rows = await knex("schedules");
380
+ return rows.map((r) => fromDbRow(r));
381
+ }
382
+ async getStats() {
383
+ const knex = this.getKnex();
384
+ const boolTrue = this.driver === "mssql" ? "1" : "true";
385
+ const boolFalse = this.driver === "mssql" ? "0" : "false";
386
+ const result = await knex("schedules").select(
387
+ knex.raw("COUNT(*) as total"),
388
+ knex.raw("SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as active"),
389
+ knex.raw("SUM(CASE WHEN status = 'paused' THEN 1 ELSE 0 END) as paused"),
390
+ knex.raw("SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed"),
391
+ knex.raw("SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) as failed"),
392
+ knex.raw(`SUM(CASE WHEN is_recurring = ${boolTrue} THEN 1 ELSE 0 END) as recurring`),
393
+ knex.raw(`SUM(CASE WHEN is_recurring = ${boolFalse} THEN 1 ELSE 0 END) as one_time`)
394
+ ).first();
395
+ return {
396
+ total: Number(result.total) || 0,
397
+ active: Number(result.active) || 0,
398
+ paused: Number(result.paused) || 0,
399
+ completed: Number(result.completed) || 0,
400
+ failed: Number(result.failed) || 0,
401
+ recurring: Number(result.recurring) || 0,
402
+ oneTime: Number(result.one_time) || 0
403
+ };
404
+ }
405
+ async validateLimits(creatorId, isRecurring, limits) {
406
+ const knex = this.getKnex();
407
+ if (limits.maxGlobal) {
408
+ const result = await knex("schedules").count("* as cnt").first();
409
+ if (Number(result?.cnt) >= limits.maxGlobal) {
410
+ throw new Error(`Global schedule limit reached (${limits.maxGlobal})`);
411
+ }
412
+ }
413
+ if (limits.maxPerUser) {
414
+ const result = await knex("schedules").where("creator_id", creatorId).count("* as cnt").first();
415
+ if (Number(result?.cnt) >= limits.maxPerUser) {
416
+ throw new Error(`You have reached the maximum number of schedules (${limits.maxPerUser})`);
417
+ }
418
+ }
419
+ if (isRecurring && limits.maxRecurringPerUser) {
420
+ const bTrue = this.driver === "mssql" ? 1 : true;
421
+ const result = await knex("schedules").where("creator_id", creatorId).where("is_recurring", bTrue).count("* as cnt").first();
422
+ if (Number(result?.cnt) >= limits.maxRecurringPerUser) {
423
+ throw new Error(
424
+ `You have reached the maximum number of recurring schedules (${limits.maxRecurringPerUser})`
425
+ );
426
+ }
427
+ }
428
+ }
429
+ // --- HA Distributed Locking (via scheduler_locks table) ---
430
+ async tryAcquireLock(lockId, nodeId, ttlSeconds) {
431
+ const knex = this.getKnex();
432
+ const now = Date.now();
433
+ const expiresAt = now + ttlSeconds * 1e3;
434
+ const token = uuidv4();
435
+ const updated = await knex("scheduler_locks").where("lock_id", lockId).where("expires_at", "<", now).update({
436
+ node_id: nodeId,
437
+ lock_token: token,
438
+ acquired_at: now,
439
+ expires_at: expiresAt
440
+ });
441
+ if (updated > 0) return token;
442
+ try {
443
+ await knex("scheduler_locks").insert({
444
+ lock_id: lockId,
445
+ node_id: nodeId,
446
+ lock_token: token,
447
+ acquired_at: now,
448
+ expires_at: expiresAt
449
+ });
450
+ return token;
451
+ } catch {
452
+ return null;
453
+ }
454
+ }
455
+ async releaseLock(lockId, lockToken) {
456
+ const knex = this.getKnex();
457
+ await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).del();
458
+ }
459
+ async renewLock(lockId, lockToken, ttlSeconds) {
460
+ const knex = this.getKnex();
461
+ const now = Date.now();
462
+ const expiresAt = now + ttlSeconds * 1e3;
463
+ const updated = await knex("scheduler_locks").where("lock_id", lockId).where("lock_token", lockToken).update({ acquired_at: now, expires_at: expiresAt });
464
+ return updated > 0;
465
+ }
466
+ async flush() {
467
+ }
468
+ // --- Message Trigger CRUD ---
469
+ async createTrigger(trigger) {
470
+ const knex = this.getKnex();
471
+ const newTrigger = {
472
+ ...trigger,
473
+ id: uuidv4(),
474
+ createdAt: Date.now()
475
+ };
476
+ await knex("message_triggers").insert(toTriggerInsertRow(newTrigger));
477
+ logger.info(`[KnexStore] Created trigger ${newTrigger.id} for user ${newTrigger.creatorId}`);
478
+ return newTrigger;
479
+ }
480
+ async getTrigger(id) {
481
+ const knex = this.getKnex();
482
+ const row = await knex("message_triggers").where("id", id).first();
483
+ return row ? fromTriggerRow(row) : void 0;
484
+ }
485
+ async updateTrigger(id, patch) {
486
+ const knex = this.getKnex();
487
+ const existing = await knex("message_triggers").where("id", id).first();
488
+ if (!existing) return void 0;
489
+ const current = fromTriggerRow(existing);
490
+ const updated = {
491
+ ...current,
492
+ ...patch,
493
+ id: current.id,
494
+ createdAt: current.createdAt
495
+ };
496
+ const row = toTriggerInsertRow(updated);
497
+ delete row.id;
498
+ await knex("message_triggers").where("id", id).update(row);
499
+ return updated;
500
+ }
501
+ async deleteTrigger(id) {
502
+ const knex = this.getKnex();
503
+ const deleted = await knex("message_triggers").where("id", id).del();
504
+ if (deleted > 0) {
505
+ logger.info(`[KnexStore] Deleted trigger ${id}`);
506
+ return true;
507
+ }
508
+ return false;
509
+ }
510
+ async getTriggersByCreator(creatorId) {
511
+ const knex = this.getKnex();
512
+ const rows = await knex("message_triggers").where("creator_id", creatorId);
513
+ return rows.map((r) => fromTriggerRow(r));
514
+ }
515
+ async getActiveTriggers() {
516
+ const knex = this.getKnex();
517
+ const rows = await knex("message_triggers").where("status", "active").where("enabled", this.driver === "mssql" ? 1 : true);
518
+ return rows.map((r) => fromTriggerRow(r));
519
+ }
520
+ };
521
+ }
522
+ });
523
+ init_knex_store();
524
+ export {
525
+ KnexStoreBackend
526
+ };
527
+ //# sourceMappingURL=knex-store-CRORFJE6.mjs.map