@probelabs/visor 0.1.155 → 0.1.156-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 (67) hide show
  1. package/dist/index.js +1842 -25
  2. package/dist/sdk/{check-provider-registry-GJ4EZAIO.mjs → check-provider-registry-3O2PAJPF.mjs} +2 -2
  3. package/dist/sdk/{check-provider-registry-PK3OTEX6.mjs → check-provider-registry-OBUYAPPC.mjs} +2 -2
  4. package/dist/sdk/{chunk-D7STLGAD.mjs → chunk-2XSKH755.mjs} +9 -9
  5. package/dist/sdk/{chunk-D7STLGAD.mjs.map → chunk-2XSKH755.mjs.map} +1 -1
  6. package/dist/sdk/{chunk-WPF7PJ64.mjs → chunk-PLMM6W3K.mjs} +8 -8
  7. package/dist/sdk/{host-6DJCOUJE.mjs → host-MIHKJ63G.mjs} +2 -2
  8. package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
  9. package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
  10. package/dist/sdk/loader-NJCF7DUS.mjs +89 -0
  11. package/dist/sdk/loader-NJCF7DUS.mjs.map +1 -0
  12. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
  13. package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
  14. package/dist/sdk/{schedule-tool-SLR7ZHBZ.mjs → schedule-tool-EZVQOF55.mjs} +2 -2
  15. package/dist/sdk/{schedule-tool-HRFONU5J.mjs → schedule-tool-M2H7O5WL.mjs} +2 -2
  16. package/dist/sdk/{schedule-tool-handler-KXZC4ZOR.mjs → schedule-tool-handler-J3CJWB6A.mjs} +2 -2
  17. package/dist/sdk/{schedule-tool-handler-XVHYK4KT.mjs → schedule-tool-handler-O7T66M3I.mjs} +2 -2
  18. package/dist/sdk/sdk.js +1633 -259
  19. package/dist/sdk/sdk.js.map +1 -1
  20. package/dist/sdk/sdk.mjs +4 -4
  21. package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
  22. package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
  23. package/dist/sdk/{workflow-check-provider-NYBQAYVH.mjs → workflow-check-provider-4DC4KOHI.mjs} +2 -2
  24. package/dist/sdk/{workflow-check-provider-HGFTX64I.mjs → workflow-check-provider-7RLM3T2I.mjs} +2 -2
  25. package/package.json +1 -1
  26. package/dist/output/traces/run-2026-03-04T18-12-39-729Z.ndjson +0 -138
  27. package/dist/output/traces/run-2026-03-04T18-13-23-673Z.ndjson +0 -2197
  28. package/dist/sdk/check-provider-registry-7ZHNM7YO.mjs +0 -29
  29. package/dist/sdk/chunk-E7QWTDTC.mjs +0 -43774
  30. package/dist/sdk/chunk-E7QWTDTC.mjs.map +0 -1
  31. package/dist/sdk/chunk-JBLYMLQJ.mjs +0 -1502
  32. package/dist/sdk/chunk-JBLYMLQJ.mjs.map +0 -1
  33. package/dist/sdk/chunk-MLMI3N35.mjs +0 -739
  34. package/dist/sdk/chunk-MLMI3N35.mjs.map +0 -1
  35. package/dist/sdk/chunk-POPHHNHJ.mjs +0 -443
  36. package/dist/sdk/chunk-POPHHNHJ.mjs.map +0 -1
  37. package/dist/sdk/failure-condition-evaluator-NZGTI5SZ.mjs +0 -17
  38. package/dist/sdk/github-frontend-6U46M2ZI.mjs +0 -1368
  39. package/dist/sdk/github-frontend-6U46M2ZI.mjs.map +0 -1
  40. package/dist/sdk/host-OXBUPRSC.mjs +0 -63
  41. package/dist/sdk/host-OXBUPRSC.mjs.map +0 -1
  42. package/dist/sdk/routing-PTYHW3IU.mjs +0 -25
  43. package/dist/sdk/schedule-tool-K5LTUYHP.mjs +0 -35
  44. package/dist/sdk/schedule-tool-handler-5HKGK5IL.mjs +0 -39
  45. package/dist/sdk/schedule-tool-handler-5HKGK5IL.mjs.map +0 -1
  46. package/dist/sdk/schedule-tool-handler-KXZC4ZOR.mjs.map +0 -1
  47. package/dist/sdk/schedule-tool-handler-XVHYK4KT.mjs.map +0 -1
  48. package/dist/sdk/slack-frontend-TZU2HIK7.mjs +0 -875
  49. package/dist/sdk/slack-frontend-TZU2HIK7.mjs.map +0 -1
  50. package/dist/sdk/trace-helpers-NSPBKLBU.mjs +0 -25
  51. package/dist/sdk/trace-helpers-NSPBKLBU.mjs.map +0 -1
  52. package/dist/sdk/workflow-check-provider-HGFTX64I.mjs.map +0 -1
  53. package/dist/sdk/workflow-check-provider-KWXTBIV2.mjs +0 -29
  54. package/dist/sdk/workflow-check-provider-KWXTBIV2.mjs.map +0 -1
  55. package/dist/sdk/workflow-check-provider-NYBQAYVH.mjs.map +0 -1
  56. package/dist/traces/run-2026-03-04T18-12-39-729Z.ndjson +0 -138
  57. package/dist/traces/run-2026-03-04T18-13-23-673Z.ndjson +0 -2197
  58. /package/dist/sdk/{check-provider-registry-7ZHNM7YO.mjs.map → check-provider-registry-3O2PAJPF.mjs.map} +0 -0
  59. /package/dist/sdk/{check-provider-registry-GJ4EZAIO.mjs.map → check-provider-registry-OBUYAPPC.mjs.map} +0 -0
  60. /package/dist/sdk/{chunk-WPF7PJ64.mjs.map → chunk-PLMM6W3K.mjs.map} +0 -0
  61. /package/dist/sdk/{host-6DJCOUJE.mjs.map → host-MIHKJ63G.mjs.map} +0 -0
  62. /package/dist/sdk/{check-provider-registry-PK3OTEX6.mjs.map → schedule-tool-EZVQOF55.mjs.map} +0 -0
  63. /package/dist/sdk/{failure-condition-evaluator-NZGTI5SZ.mjs.map → schedule-tool-M2H7O5WL.mjs.map} +0 -0
  64. /package/dist/sdk/{routing-PTYHW3IU.mjs.map → schedule-tool-handler-J3CJWB6A.mjs.map} +0 -0
  65. /package/dist/sdk/{schedule-tool-HRFONU5J.mjs.map → schedule-tool-handler-O7T66M3I.mjs.map} +0 -0
  66. /package/dist/sdk/{schedule-tool-K5LTUYHP.mjs.map → workflow-check-provider-4DC4KOHI.mjs.map} +0 -0
  67. /package/dist/sdk/{schedule-tool-SLR7ZHBZ.mjs.map → workflow-check-provider-7RLM3T2I.mjs.map} +0 -0
@@ -3959,7 +3959,7 @@ async function executeWorkflowAsTool(workflowId, args, context2, argsOverrides)
3959
3959
  ...args,
3960
3960
  ...argsOverrides
3961
3961
  };
3962
- const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-HGFTX64I.mjs");
3962
+ const { WorkflowCheckProvider: WorkflowCheckProvider2 } = await import("./workflow-check-provider-4DC4KOHI.mjs");
3963
3963
  const provider = new WorkflowCheckProvider2();
3964
3964
  const checkConfig = {
3965
3965
  type: "workflow",
@@ -13027,7 +13027,7 @@ var init_state_machine_execution_engine = __esm({
13027
13027
  try {
13028
13028
  const map = options?.webhookContext?.webhookData;
13029
13029
  if (map) {
13030
- const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-PK3OTEX6.mjs");
13030
+ const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-3O2PAJPF.mjs");
13031
13031
  const reg = CheckProviderRegistry2.getInstance();
13032
13032
  const p = reg.getProvider("http_input");
13033
13033
  if (p && typeof p.setWebhookContext === "function") p.setWebhookContext(map);
@@ -13150,7 +13150,7 @@ var init_state_machine_execution_engine = __esm({
13150
13150
  tag_filter: tagFilter
13151
13151
  } : config;
13152
13152
  try {
13153
- const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-PK3OTEX6.mjs");
13153
+ const { CheckProviderRegistry: CheckProviderRegistry2 } = await import("./check-provider-registry-3O2PAJPF.mjs");
13154
13154
  const registry = CheckProviderRegistry2.getInstance();
13155
13155
  registry.setCustomTools(configWithTagFilter.tools || {});
13156
13156
  } catch (error) {
@@ -13214,7 +13214,7 @@ var init_state_machine_execution_engine = __esm({
13214
13214
  try {
13215
13215
  const webhookData = this.executionContext?.webhookContext?.webhookData;
13216
13216
  if (webhookData instanceof Map) {
13217
- const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-KXZC4ZOR.mjs");
13217
+ const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-O7T66M3I.mjs");
13218
13218
  const slackCtx = extractSlackContext2(webhookData);
13219
13219
  if (slackCtx) {
13220
13220
  const payload = Array.from(webhookData.values())[0];
@@ -13243,7 +13243,7 @@ var init_state_machine_execution_engine = __esm({
13243
13243
  if (Array.isArray(configWithTagFilter.frontends) && configWithTagFilter.frontends.length > 0) {
13244
13244
  try {
13245
13245
  const { EventBus } = await import("./event-bus-5K3Y2FCS.mjs");
13246
- const { FrontendsHost } = await import("./host-6DJCOUJE.mjs");
13246
+ const { FrontendsHost } = await import("./host-4ONWAJ6Q.mjs");
13247
13247
  const bus = new EventBus();
13248
13248
  context2.eventBus = bus;
13249
13249
  frontendsHost = new FrontendsHost(bus, logger);
@@ -40722,8 +40722,8 @@ function buildBuiltinGlobals(opts) {
40722
40722
  const asyncFunctionNames = /* @__PURE__ */ new Set();
40723
40723
  const scheduleFn = async (args = {}) => {
40724
40724
  try {
40725
- const { handleScheduleAction: handleScheduleAction2, buildScheduleToolContext: buildScheduleToolContext2 } = await import("./schedule-tool-HRFONU5J.mjs");
40726
- const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-KXZC4ZOR.mjs");
40725
+ const { handleScheduleAction: handleScheduleAction2, buildScheduleToolContext: buildScheduleToolContext2 } = await import("./schedule-tool-EZVQOF55.mjs");
40726
+ const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-O7T66M3I.mjs");
40727
40727
  const parentCtx = opts.sessionInfo?._parentContext;
40728
40728
  const webhookData = parentCtx?.prInfo?.eventContext?.webhookData;
40729
40729
  const visorCfg = parentCtx?.config;
@@ -43771,4 +43771,4 @@ undici/lib/fetch/body.js:
43771
43771
  undici/lib/websocket/frame.js:
43772
43772
  (*! ws. MIT License. Einar Otto Stangvik <einaros@gmail.com> *)
43773
43773
  */
43774
- //# sourceMappingURL=chunk-WPF7PJ64.mjs.map
43774
+ //# sourceMappingURL=chunk-PLMM6W3K.mjs.map
@@ -24,7 +24,7 @@ var init_host = __esm({
24
24
  const { GitHubFrontend } = await import("./github-frontend-XKPAYXOT.mjs");
25
25
  this.frontends.push(new GitHubFrontend());
26
26
  } else if (spec.name === "slack") {
27
- const { SlackFrontend } = await import("./slack-frontend-TZU2HIK7.mjs");
27
+ const { SlackFrontend } = await import("./slack-frontend-6KDUMDDI.mjs");
28
28
  this.frontends.push(new SlackFrontend(spec.config));
29
29
  } else if (spec.name === "tui") {
30
30
  const { TuiFrontend } = await import("./tui-frontend-T56PZB67.mjs");
@@ -60,4 +60,4 @@ init_host();
60
60
  export {
61
61
  FrontendsHost
62
62
  };
63
- //# sourceMappingURL=host-6DJCOUJE.mjs.map
63
+ //# sourceMappingURL=host-MIHKJ63G.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