@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.
- package/dist/index.js +1842 -25
- package/dist/sdk/{check-provider-registry-GJ4EZAIO.mjs → check-provider-registry-3O2PAJPF.mjs} +2 -2
- package/dist/sdk/{check-provider-registry-PK3OTEX6.mjs → check-provider-registry-OBUYAPPC.mjs} +2 -2
- package/dist/sdk/{chunk-D7STLGAD.mjs → chunk-2XSKH755.mjs} +9 -9
- package/dist/sdk/{chunk-D7STLGAD.mjs.map → chunk-2XSKH755.mjs.map} +1 -1
- package/dist/sdk/{chunk-WPF7PJ64.mjs → chunk-PLMM6W3K.mjs} +8 -8
- package/dist/sdk/{host-6DJCOUJE.mjs → host-MIHKJ63G.mjs} +2 -2
- package/dist/sdk/knex-store-CRORFJE6.mjs +527 -0
- package/dist/sdk/knex-store-CRORFJE6.mjs.map +1 -0
- package/dist/sdk/loader-NJCF7DUS.mjs +89 -0
- package/dist/sdk/loader-NJCF7DUS.mjs.map +1 -0
- package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs +655 -0
- package/dist/sdk/opa-policy-engine-S2S2ULEI.mjs.map +1 -0
- package/dist/sdk/{schedule-tool-SLR7ZHBZ.mjs → schedule-tool-EZVQOF55.mjs} +2 -2
- package/dist/sdk/{schedule-tool-HRFONU5J.mjs → schedule-tool-M2H7O5WL.mjs} +2 -2
- package/dist/sdk/{schedule-tool-handler-KXZC4ZOR.mjs → schedule-tool-handler-J3CJWB6A.mjs} +2 -2
- package/dist/sdk/{schedule-tool-handler-XVHYK4KT.mjs → schedule-tool-handler-O7T66M3I.mjs} +2 -2
- package/dist/sdk/sdk.js +1633 -259
- package/dist/sdk/sdk.js.map +1 -1
- package/dist/sdk/sdk.mjs +4 -4
- package/dist/sdk/validator-XTZJZZJH.mjs +134 -0
- package/dist/sdk/validator-XTZJZZJH.mjs.map +1 -0
- package/dist/sdk/{workflow-check-provider-NYBQAYVH.mjs → workflow-check-provider-4DC4KOHI.mjs} +2 -2
- package/dist/sdk/{workflow-check-provider-HGFTX64I.mjs → workflow-check-provider-7RLM3T2I.mjs} +2 -2
- package/package.json +1 -1
- package/dist/output/traces/run-2026-03-04T18-12-39-729Z.ndjson +0 -138
- package/dist/output/traces/run-2026-03-04T18-13-23-673Z.ndjson +0 -2197
- package/dist/sdk/check-provider-registry-7ZHNM7YO.mjs +0 -29
- package/dist/sdk/chunk-E7QWTDTC.mjs +0 -43774
- package/dist/sdk/chunk-E7QWTDTC.mjs.map +0 -1
- package/dist/sdk/chunk-JBLYMLQJ.mjs +0 -1502
- package/dist/sdk/chunk-JBLYMLQJ.mjs.map +0 -1
- package/dist/sdk/chunk-MLMI3N35.mjs +0 -739
- package/dist/sdk/chunk-MLMI3N35.mjs.map +0 -1
- package/dist/sdk/chunk-POPHHNHJ.mjs +0 -443
- package/dist/sdk/chunk-POPHHNHJ.mjs.map +0 -1
- package/dist/sdk/failure-condition-evaluator-NZGTI5SZ.mjs +0 -17
- package/dist/sdk/github-frontend-6U46M2ZI.mjs +0 -1368
- package/dist/sdk/github-frontend-6U46M2ZI.mjs.map +0 -1
- package/dist/sdk/host-OXBUPRSC.mjs +0 -63
- package/dist/sdk/host-OXBUPRSC.mjs.map +0 -1
- package/dist/sdk/routing-PTYHW3IU.mjs +0 -25
- package/dist/sdk/schedule-tool-K5LTUYHP.mjs +0 -35
- package/dist/sdk/schedule-tool-handler-5HKGK5IL.mjs +0 -39
- package/dist/sdk/schedule-tool-handler-5HKGK5IL.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-KXZC4ZOR.mjs.map +0 -1
- package/dist/sdk/schedule-tool-handler-XVHYK4KT.mjs.map +0 -1
- package/dist/sdk/slack-frontend-TZU2HIK7.mjs +0 -875
- package/dist/sdk/slack-frontend-TZU2HIK7.mjs.map +0 -1
- package/dist/sdk/trace-helpers-NSPBKLBU.mjs +0 -25
- package/dist/sdk/trace-helpers-NSPBKLBU.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-HGFTX64I.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-KWXTBIV2.mjs +0 -29
- package/dist/sdk/workflow-check-provider-KWXTBIV2.mjs.map +0 -1
- package/dist/sdk/workflow-check-provider-NYBQAYVH.mjs.map +0 -1
- package/dist/traces/run-2026-03-04T18-12-39-729Z.ndjson +0 -138
- package/dist/traces/run-2026-03-04T18-13-23-673Z.ndjson +0 -2197
- /package/dist/sdk/{check-provider-registry-7ZHNM7YO.mjs.map → check-provider-registry-3O2PAJPF.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-GJ4EZAIO.mjs.map → check-provider-registry-OBUYAPPC.mjs.map} +0 -0
- /package/dist/sdk/{chunk-WPF7PJ64.mjs.map → chunk-PLMM6W3K.mjs.map} +0 -0
- /package/dist/sdk/{host-6DJCOUJE.mjs.map → host-MIHKJ63G.mjs.map} +0 -0
- /package/dist/sdk/{check-provider-registry-PK3OTEX6.mjs.map → schedule-tool-EZVQOF55.mjs.map} +0 -0
- /package/dist/sdk/{failure-condition-evaluator-NZGTI5SZ.mjs.map → schedule-tool-M2H7O5WL.mjs.map} +0 -0
- /package/dist/sdk/{routing-PTYHW3IU.mjs.map → schedule-tool-handler-J3CJWB6A.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-HRFONU5J.mjs.map → schedule-tool-handler-O7T66M3I.mjs.map} +0 -0
- /package/dist/sdk/{schedule-tool-K5LTUYHP.mjs.map → workflow-check-provider-4DC4KOHI.mjs.map} +0 -0
- /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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
40726
|
-
const { extractSlackContext: extractSlackContext2 } = await import("./schedule-tool-handler-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|