@xpert-ai/plugin-sdk 3.18.6 → 3.18.7
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/CHANGELOG.md +8 -0
- package/data-workbench.cjs.js +217 -66
- package/data-workbench.esm.js +217 -66
- package/index.cjs.js +40 -0
- package/index.esm.js +39 -1
- package/package.json +1 -1
- package/src/lib/core/strategy-bus.d.ts +3 -0
- package/src/lib/data/datasource/workbench-pagination.d.ts +6 -0
- package/src/lib/data/datasource/workbench-sql-lexer.d.ts +11 -0
- package/src/lib/data/datasource/workbench-sql-syntax.d.ts +3 -0
- package/src/lib/rag/analyzer/index.d.ts +3 -0
- package/src/lib/rag/analyzer/strategy.decorator.d.ts +2 -0
- package/src/lib/rag/analyzer/strategy.interface.d.ts +11 -0
- package/src/lib/rag/analyzer/strategy.registry.d.ts +8 -0
- package/src/lib/rag/index.d.ts +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @xpert-ai/plugin-sdk
|
|
2
2
|
|
|
3
|
+
## 3.18.7
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 5213185: Expose keyword analyzer strategy interfaces, discovery metadata, and a scoped registry with exact source lookup. Add optional plugin removal preflight guards so hosts can protect active analyzer dependencies.
|
|
8
|
+
|
|
9
|
+
Correct read-only SQL classification for derived tables, CTE column declarations and type modifiers, and preserve duplicate MySQL output names with direct bounded pagination.
|
|
10
|
+
|
|
3
11
|
## 3.18.6
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/data-workbench.cjs.js
CHANGED
|
@@ -8,6 +8,159 @@ const DataSourceRuntimeCapability = Object.freeze({
|
|
|
8
8
|
__type: undefined
|
|
9
9
|
});
|
|
10
10
|
|
|
11
|
+
/** Mask comments and quoted content without changing source offsets. Shared by guards and pagination. */ function lexWorkbenchSql(source) {
|
|
12
|
+
if (!source.trim() || source.length > 100000 || source.includes('\0')) throw new Error('invalid_sql');
|
|
13
|
+
const masked = source.split('');
|
|
14
|
+
const quoted = new Map();
|
|
15
|
+
const hide = (start, end, kind)=>{
|
|
16
|
+
for(let i = start; i < end; i++)if (masked[i] !== '\n') masked[i] = ' ';
|
|
17
|
+
if (kind) {
|
|
18
|
+
const marker = start + 1;
|
|
19
|
+
quoted.set(marker, kind);
|
|
20
|
+
masked[marker] = kind === 'literal' ? '?' : 'i';
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
let index = 0;
|
|
24
|
+
while(index < source.length){
|
|
25
|
+
const start = index, c = source[index], next = source[index + 1];
|
|
26
|
+
if (c === '-' && next === '-' || c === '#') {
|
|
27
|
+
while(index < source.length && source[index] !== '\n')index++;
|
|
28
|
+
hide(start, index);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (c === '/' && next === '*') {
|
|
32
|
+
if (source[index + 2] === '!') throw new Error('executable_comment_not_supported');
|
|
33
|
+
const end = source.indexOf('*/', index + 2);
|
|
34
|
+
if (end < 0) throw new Error('unterminated_comment');
|
|
35
|
+
index = end + 2;
|
|
36
|
+
hide(start, index);
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (c === "'" || c === '"' || c === '`') {
|
|
40
|
+
let closed = false;
|
|
41
|
+
index++;
|
|
42
|
+
while(index < source.length){
|
|
43
|
+
if (source[index] === '\\') throw new Error('use_parameters_for_backslash_literals');
|
|
44
|
+
if (source[index] === c) {
|
|
45
|
+
if (source[index + 1] === c) {
|
|
46
|
+
index += 2;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
index++;
|
|
50
|
+
closed = true;
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
index++;
|
|
54
|
+
}
|
|
55
|
+
if (!closed) throw new Error('unterminated_literal');
|
|
56
|
+
hide(start, index, c === "'" ? 'literal' : 'identifier');
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (c === '$') {
|
|
60
|
+
var _source_slice_match;
|
|
61
|
+
const tag = (_source_slice_match = source.slice(index).match(/^\$(?:[A-Za-z_][A-Za-z_0-9]*)?\$/)) == null ? void 0 : _source_slice_match[0];
|
|
62
|
+
if (tag) {
|
|
63
|
+
const end = source.indexOf(tag, index + tag.length);
|
|
64
|
+
if (end < 0) throw new Error('unterminated_literal');
|
|
65
|
+
index = end + tag.length;
|
|
66
|
+
hide(start, index, 'literal');
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
index++;
|
|
71
|
+
}
|
|
72
|
+
const text = masked.join('');
|
|
73
|
+
const tokens = [
|
|
74
|
+
...text.matchAll(/[A-Z_][A-Z_0-9]*|[0-9]+|[^\s]/gi)
|
|
75
|
+
].map((match)=>{
|
|
76
|
+
var _quoted_get;
|
|
77
|
+
return {
|
|
78
|
+
text: match[0].toUpperCase(),
|
|
79
|
+
start: match.index,
|
|
80
|
+
end: match.index + match[0].length,
|
|
81
|
+
kind: (_quoted_get = quoted.get(match.index)) != null ? _quoted_get : /^[A-Z_]/i.test(match[0]) ? 'word' : /^[0-9]/.test(match[0]) ? 'number' : 'symbol'
|
|
82
|
+
};
|
|
83
|
+
});
|
|
84
|
+
return {
|
|
85
|
+
masked: text,
|
|
86
|
+
tokens
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const MODIFIED_TYPES = new Set('DECIMAL NUMERIC CHAR VARCHAR NCHAR NVARCHAR BINARY VARBINARY DATETIME TIME TIMESTAMP'.split(' '));
|
|
91
|
+
/** Positions where name(...) declares columns or a built-in type, rather than invoking a function. */ function sqlDeclarationPositions(tokens) {
|
|
92
|
+
const declarations = new Set();
|
|
93
|
+
const closing = new Map(), parents = new Map();
|
|
94
|
+
const stack = [];
|
|
95
|
+
tokens.forEach((token, index)=>{
|
|
96
|
+
if (stack.length) parents.set(index, stack[stack.length - 1]);
|
|
97
|
+
if (token.text === '(') stack.push(index);
|
|
98
|
+
if (token.text === ')') {
|
|
99
|
+
const open = stack.pop();
|
|
100
|
+
if (open !== undefined) closing.set(open, index);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
const name = (index)=>{
|
|
104
|
+
var _tokens_index;
|
|
105
|
+
return [
|
|
106
|
+
'word',
|
|
107
|
+
'identifier'
|
|
108
|
+
].includes((_tokens_index = tokens[index]) == null ? void 0 : _tokens_index.kind);
|
|
109
|
+
};
|
|
110
|
+
const is = (index, word)=>{
|
|
111
|
+
var _tokens_index;
|
|
112
|
+
return ((_tokens_index = tokens[index]) == null ? void 0 : _tokens_index.text) === word;
|
|
113
|
+
};
|
|
114
|
+
for(let i = 0; i < tokens.length; i++){
|
|
115
|
+
if (tokens[i].kind !== 'word' || !is(i, 'WITH')) continue;
|
|
116
|
+
let cursor = i + 1;
|
|
117
|
+
if (is(cursor, 'RECURSIVE')) cursor++;
|
|
118
|
+
while(name(cursor)){
|
|
119
|
+
const declaration = cursor++;
|
|
120
|
+
let columns = false;
|
|
121
|
+
if (is(cursor, '(')) {
|
|
122
|
+
const end = closing.get(cursor);
|
|
123
|
+
if (end === undefined || end === cursor + 1) break;
|
|
124
|
+
const columnTokens = tokens.slice(cursor + 1, end);
|
|
125
|
+
if (columnTokens.length % 2 === 0 || !columnTokens.every((token, n)=>n % 2 === 0 ? [
|
|
126
|
+
'word',
|
|
127
|
+
'identifier'
|
|
128
|
+
].includes(token.kind) : token.text === ',')) break;
|
|
129
|
+
columns = true;
|
|
130
|
+
cursor = end + 1;
|
|
131
|
+
}
|
|
132
|
+
if (!is(cursor++, 'AS')) break;
|
|
133
|
+
if (is(cursor, 'NOT')) cursor++;
|
|
134
|
+
if (is(cursor, 'MATERIALIZED')) cursor++;
|
|
135
|
+
if (!is(cursor, '(')) break;
|
|
136
|
+
const end = closing.get(cursor);
|
|
137
|
+
if (end === undefined) break;
|
|
138
|
+
if (columns) declarations.add(tokens[declaration].start);
|
|
139
|
+
cursor = end + 1;
|
|
140
|
+
if (!is(cursor, ',')) break;
|
|
141
|
+
cursor++;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
tokens.forEach((token, i)=>{
|
|
145
|
+
var _tokens_;
|
|
146
|
+
if (token.kind !== 'word' || !MODIFIED_TYPES.has(token.text) || !is(i + 1, '(')) return;
|
|
147
|
+
const end = closing.get(i + 1);
|
|
148
|
+
if (end === undefined) return;
|
|
149
|
+
const args = tokens.slice(i + 2, end);
|
|
150
|
+
if (![
|
|
151
|
+
1,
|
|
152
|
+
3
|
|
153
|
+
].includes(args.length) || !args.every((arg, n)=>n % 2 ? arg.text === ',' : arg.kind === 'number')) return;
|
|
154
|
+
const parent = parents.get(i);
|
|
155
|
+
const owner = parent === undefined ? undefined : (_tokens_ = tokens[parent - 1]) == null ? void 0 : _tokens_.text;
|
|
156
|
+
const cast = owner === 'CAST' && is(i - 1, 'AS');
|
|
157
|
+
const convert = owner === 'CONVERT' && is(i - 1, ',');
|
|
158
|
+
const postgresCast = is(i - 1, ':') && is(i - 2, ':');
|
|
159
|
+
if (cast || convert || postgresCast) declarations.add(token.start);
|
|
160
|
+
});
|
|
161
|
+
return declarations;
|
|
162
|
+
}
|
|
163
|
+
|
|
11
164
|
const WRITE = new Set([
|
|
12
165
|
'INSERT',
|
|
13
166
|
'UPDATE',
|
|
@@ -42,15 +195,16 @@ const FORBIDDEN = new Set([
|
|
|
42
195
|
'DETACH'
|
|
43
196
|
]);
|
|
44
197
|
const SAFE_FUNCTIONS = new Set('ABS ACOS ASIN ATAN ATAN2 AVG CAST CEIL CEILING COALESCE CONCAT CONCAT_WS CONVERT COS COUNT CURDATE CURRENT_DATE CURRENT_TIMESTAMP DATE DATE_ADD DATE_SUB DATE_FORMAT DATEDIFF DAY DAYOFMONTH DAYOFWEEK EXTRACT FLOOR FORMAT GREATEST GROUP_CONCAT IF IFNULL JSON_EXTRACT JSON_LENGTH JSON_UNQUOTE LEAST LEFT LENGTH LN LOG LOWER LPAD LTRIM MAX MD5 MIN MOD MONTH NOW NULLIF POWER RAND REPLACE REVERSE RIGHT ROUND ROW_NUMBER RANK DENSE_RANK LAG LEAD FIRST_VALUE LAST_VALUE LPAD RPAD RTRIM SIGN SIN SQRT STDDEV STDDEV_POP STDDEV_SAMP SUBSTR SUBSTRING SUM TAN TO_CHAR TO_DATE TO_TIMESTAMP TRIM TRUNC UPPER VAR_POP VAR_SAMP VERSION WEEK YEAR DATABASE CURRENT_DATABASE CURRENT_SCHEMA ARRAY_AGG STRING_AGG JSON_AGG JSON_BUILD_OBJECT PG_GET_VIEWDEF'.split(' '));
|
|
45
|
-
|
|
198
|
+
// FROM/JOIN can introduce a parenthesized subquery, not a function call.
|
|
199
|
+
const SQL_PARENS = new Set('IN AS EXISTS OVER PARTITION VALUES SELECT WITH FROM JOIN AND OR NOT ON USING FILTER GROUPING ROLLUP CUBE DISTINCT EXPLAIN'.split(' '));
|
|
46
200
|
const UNSAFE_FUNCTIONS = /\b(pg_sleep|sleep|benchmark|dblink\w*|lo_\w+|pg_(?:read|write|ls|stat|terminate|cancel|reload|rotate|log|create|drop|promote|switch|backup|replication|advisory)\w*|get_lock|release_lock|load_file|nextval|setval|set_config|http\w*|s3|hdfs|jdbc|mysql|postgresql|file|url)\s*\(/i;
|
|
47
201
|
function splitWorkbenchSql(source) {
|
|
48
|
-
|
|
202
|
+
const { masked, tokens } = lexWorkbenchSql(source);
|
|
49
203
|
const statements = [];
|
|
50
|
-
let start = 0
|
|
204
|
+
let start = 0;
|
|
51
205
|
const finish = (end)=>{
|
|
52
|
-
const text =
|
|
53
|
-
if (text) {
|
|
206
|
+
const text = masked.slice(start, end);
|
|
207
|
+
if (text.trim()) {
|
|
54
208
|
var _text_toUpperCase_match;
|
|
55
209
|
const words = (_text_toUpperCase_match = text.toUpperCase().match(/[A-Z_][A-Z_0-9]*/g)) != null ? _text_toUpperCase_match : [];
|
|
56
210
|
const first = words[0];
|
|
@@ -61,10 +215,11 @@ function splitWorkbenchSql(source) {
|
|
|
61
215
|
if (words.some((word, index)=>WRITE.has(word) && !(first === 'SHOW' && index === 1 && word === 'CREATE') || FORBIDDEN.has(word)) || UNSAFE_FUNCTIONS.test(text) || /\bFOR\s+(UPDATE|SHARE)\b/i.test(text) || /:=|\bEXPLAIN\s+ANALYZE\b|@/i.test(text)) effect = 'unsupported';
|
|
62
216
|
// eslint-disable-next-line no-control-regex -- intentional: reject any non-ASCII/control input
|
|
63
217
|
if (/[^\x00-\x7f]/.test(text) || /\.\s*[A-Z_][A-Z_0-9]*\s*\(/i.test(text)) effect = 'unsupported';
|
|
218
|
+
const declarations = sqlDeclarationPositions(tokens.filter((token)=>token.start >= start && token.end <= end));
|
|
64
219
|
if ([
|
|
65
220
|
...text.matchAll(/([A-Z_][A-Z_0-9]*)\s*\(/gi)
|
|
66
|
-
].some((match)=>!SAFE_FUNCTIONS.has(match[1].toUpperCase()) && !SQL_PARENS.has(match[1].toUpperCase()))) effect = 'unsupported';
|
|
67
|
-
if (first === 'SHOW' && !/^(SHOW\s+(DATABASES|SCHEMAS|CATALOGS|TABLES|FULL\s+TABLES|COLUMNS|FULL\s+COLUMNS|INDEX|INDEXES|KEYS|CREATE\s+TABLE|CREATE\s+VIEW|PARTITIONS|VARIABLES|STATUS|GRANTS))\b/i.test(text)) effect = 'unsupported';
|
|
221
|
+
].some((match)=>!declarations.has(start + match.index) && !SAFE_FUNCTIONS.has(match[1].toUpperCase()) && !SQL_PARENS.has(match[1].toUpperCase()))) effect = 'unsupported';
|
|
222
|
+
if (first === 'SHOW' && !/^(SHOW\s+(DATABASES|SCHEMAS|CATALOGS|TABLES|FULL\s+TABLES|COLUMNS|FULL\s+COLUMNS|INDEX|INDEXES|KEYS|CREATE\s+TABLE|CREATE\s+VIEW|PARTITIONS|VARIABLES|STATUS|GRANTS))\b/i.test(text.trim())) effect = 'unsupported';
|
|
68
223
|
}
|
|
69
224
|
// CREATE/ALTER routines, external resources and privileged SQL are outside this app.
|
|
70
225
|
if (effect === 'write' && /\b(FUNCTION|PROCEDURE|TRIGGER|USER|ROLE|CATALOG|RESOURCE|SYSTEM|SERVER|EXTENSION|FILE|OUTFILE|DUMPFILE|EXECUTE)\b/i.test(text)) effect = 'unsupported';
|
|
@@ -74,63 +229,10 @@ function splitWorkbenchSql(source) {
|
|
|
74
229
|
effect
|
|
75
230
|
});
|
|
76
231
|
}
|
|
77
|
-
clean = '';
|
|
78
232
|
start = end + 1;
|
|
79
233
|
};
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (c === '-' && next === '-' || c === '#') {
|
|
83
|
-
while(index < source.length && source[index] !== '\n')index++;
|
|
84
|
-
clean += ' ';
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
if (c === '/' && next === '*') {
|
|
88
|
-
if (source[index + 2] === '!') throw new Error('executable_comment_not_supported');
|
|
89
|
-
const end = source.indexOf('*/', index + 2);
|
|
90
|
-
if (end < 0) throw new Error('unterminated_comment');
|
|
91
|
-
index = end + 2;
|
|
92
|
-
clean += ' ';
|
|
93
|
-
continue;
|
|
94
|
-
}
|
|
95
|
-
if (c === "'" || c === '"' || c === '`') {
|
|
96
|
-
const quote = c;
|
|
97
|
-
let closed = false;
|
|
98
|
-
index++;
|
|
99
|
-
while(index < source.length){
|
|
100
|
-
if (source[index] === '\\') throw new Error('use_parameters_for_backslash_literals');
|
|
101
|
-
if (source[index] === quote) {
|
|
102
|
-
if (source[index + 1] === quote) {
|
|
103
|
-
index += 2;
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
index++;
|
|
107
|
-
closed = true;
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
index++;
|
|
111
|
-
}
|
|
112
|
-
if (!closed) throw new Error('unterminated_literal');
|
|
113
|
-
clean += quote === "'" ? ' ? ' : ' identifier ';
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
if (c === '$') {
|
|
117
|
-
var _source_slice_match;
|
|
118
|
-
const tag = (_source_slice_match = source.slice(index).match(/^\$(?:[A-Za-z_][A-Za-z_0-9]*)?\$/)) == null ? void 0 : _source_slice_match[0];
|
|
119
|
-
if (tag) {
|
|
120
|
-
const end = source.indexOf(tag, index + tag.length);
|
|
121
|
-
if (end < 0) throw new Error('unterminated_literal');
|
|
122
|
-
index = end + tag.length;
|
|
123
|
-
clean += ' ? ';
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
if (c === ';') {
|
|
128
|
-
finish(index);
|
|
129
|
-
index++;
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
clean += c;
|
|
133
|
-
index++;
|
|
234
|
+
for (const token of tokens){
|
|
235
|
+
if (token.kind === 'symbol' && token.text === ';') finish(token.start);
|
|
134
236
|
}
|
|
135
237
|
finish(source.length);
|
|
136
238
|
if (!statements.length || statements.length > 50) throw new Error('statement_count_exceeded');
|
|
@@ -148,6 +250,53 @@ function quoteDatabaseIdentifier(name, engine) {
|
|
|
148
250
|
return quote + name.split(quote).join(quote + quote) + quote;
|
|
149
251
|
}
|
|
150
252
|
|
|
253
|
+
/** Apply a page to a MySQL result without turning its (possibly duplicate) output names into table columns. */ function paginateMysqlQuery(sql, parameters = [], limit, offset) {
|
|
254
|
+
const { tokens } = lexWorkbenchSql(sql);
|
|
255
|
+
const top = [];
|
|
256
|
+
let depth = 0;
|
|
257
|
+
for (const token of tokens){
|
|
258
|
+
if (token.text === '(') depth++;
|
|
259
|
+
if (!depth) top.push(token);
|
|
260
|
+
if (token.text === ')') depth--;
|
|
261
|
+
if (depth < 0) throw new Error('unsupported_pagination');
|
|
262
|
+
}
|
|
263
|
+
if (depth) throw new Error('unsupported_pagination');
|
|
264
|
+
const start = top.findIndex((token)=>token.kind === 'word' && token.text === 'LIMIT');
|
|
265
|
+
if (start < 0) return {
|
|
266
|
+
sql: `${sql}\nLIMIT ${limit + 1} OFFSET ${offset}`,
|
|
267
|
+
parameters
|
|
268
|
+
};
|
|
269
|
+
const clause = top.slice(start + 1);
|
|
270
|
+
const bindings = tokens.filter((token)=>token.text === '?' && token.kind === 'symbol');
|
|
271
|
+
const consumed = new Set();
|
|
272
|
+
const integer = (token)=>{
|
|
273
|
+
if ((token == null ? void 0 : token.kind) === 'number') return BigInt(token.text);
|
|
274
|
+
if ((token == null ? void 0 : token.kind) === 'symbol' && token.text === '?') {
|
|
275
|
+
const index = bindings.indexOf(token), value = parameters[index];
|
|
276
|
+
if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) {
|
|
277
|
+
consumed.add(index);
|
|
278
|
+
return BigInt(value);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
throw new Error('unsupported_pagination');
|
|
282
|
+
};
|
|
283
|
+
let count, skip = 0n;
|
|
284
|
+
if (clause.length === 1) count = integer(clause[0]);
|
|
285
|
+
else if (clause.length === 3 && clause[1].text === ',') {
|
|
286
|
+
skip = integer(clause[0]);
|
|
287
|
+
count = integer(clause[2]);
|
|
288
|
+
} else if (clause.length === 3 && clause[1].kind === 'word' && clause[1].text === 'OFFSET') {
|
|
289
|
+
count = integer(clause[0]);
|
|
290
|
+
skip = integer(clause[2]);
|
|
291
|
+
} else throw new Error('unsupported_pagination');
|
|
292
|
+
const remaining = count > BigInt(offset) ? count - BigInt(offset) : 0n;
|
|
293
|
+
const size = remaining < BigInt(limit + 1) ? remaining : BigInt(limit + 1);
|
|
294
|
+
return {
|
|
295
|
+
sql: `${sql.slice(0, top[start].start)}LIMIT ${size} OFFSET ${skip + BigInt(offset)}${sql.slice(clause[clause.length - 1].end)}`,
|
|
296
|
+
parameters: parameters.filter((_, index)=>!consumed.has(index))
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
151
300
|
const number = (value)=>Number(value != null ? value : 0);
|
|
152
301
|
const string = (value)=>value == null ? '' : String(value);
|
|
153
302
|
const cell = (result, row, name)=>row[result.columns.findIndex((column)=>column.name.toLowerCase() === name.toLowerCase())];
|
|
@@ -389,12 +538,14 @@ const cell = (result, row, name)=>row[result.columns.findIndex((column)=>column.
|
|
|
389
538
|
if (input.mode === 'write' && !(await this.capabilities()).writes) throw new Error('engine_version_writes_unavailable');
|
|
390
539
|
if (input.mode === 'write' && offset) throw new Error('mutation_cannot_be_paginated');
|
|
391
540
|
let sql = statements[0].sql;
|
|
392
|
-
|
|
541
|
+
let parameters = input.parameters;
|
|
393
542
|
if (input.mode === 'read' && [
|
|
394
543
|
'SELECT',
|
|
395
544
|
'WITH'
|
|
396
|
-
].includes(statements[0].words[0]))
|
|
397
|
-
|
|
545
|
+
].includes(statements[0].words[0])) {
|
|
546
|
+
if (this.engine === 'mysql') ({ sql, parameters } = paginateMysqlQuery(sql, parameters, limit, offset));
|
|
547
|
+
else sql = `SELECT * FROM (\n${sql}\n) AS ${this.quote('_db_studio_page')} LIMIT ${limit + 1} OFFSET ${offset}`;
|
|
548
|
+
} else if (offset) throw new Error('statement_cannot_be_paginated');
|
|
398
549
|
this.busy = true;
|
|
399
550
|
let readTransaction = false;
|
|
400
551
|
try {
|
|
@@ -403,7 +554,7 @@ const cell = (result, row, name)=>row[result.columns.findIndex((column)=>column.
|
|
|
403
554
|
readTransaction = true;
|
|
404
555
|
}
|
|
405
556
|
var _input_timeoutMs;
|
|
406
|
-
const result = await this.raw(sql,
|
|
557
|
+
const result = await this.raw(sql, parameters, limit + 1, signal, Math.max(1, Math.min((_input_timeoutMs = input.timeoutMs) != null ? _input_timeoutMs : 30000, 120000)));
|
|
407
558
|
const hasMore = result.rows.length > limit || result.truncated;
|
|
408
559
|
return _extends._extends({}, result, {
|
|
409
560
|
rows: result.rows.slice(0, limit),
|
package/data-workbench.esm.js
CHANGED
|
@@ -6,6 +6,159 @@ const DataSourceRuntimeCapability = Object.freeze({
|
|
|
6
6
|
__type: undefined
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
+
/** Mask comments and quoted content without changing source offsets. Shared by guards and pagination. */ function lexWorkbenchSql(source) {
|
|
10
|
+
if (!source.trim() || source.length > 100000 || source.includes('\0')) throw new Error('invalid_sql');
|
|
11
|
+
const masked = source.split('');
|
|
12
|
+
const quoted = new Map();
|
|
13
|
+
const hide = (start, end, kind)=>{
|
|
14
|
+
for(let i = start; i < end; i++)if (masked[i] !== '\n') masked[i] = ' ';
|
|
15
|
+
if (kind) {
|
|
16
|
+
const marker = start + 1;
|
|
17
|
+
quoted.set(marker, kind);
|
|
18
|
+
masked[marker] = kind === 'literal' ? '?' : 'i';
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
let index = 0;
|
|
22
|
+
while(index < source.length){
|
|
23
|
+
const start = index, c = source[index], next = source[index + 1];
|
|
24
|
+
if (c === '-' && next === '-' || c === '#') {
|
|
25
|
+
while(index < source.length && source[index] !== '\n')index++;
|
|
26
|
+
hide(start, index);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
if (c === '/' && next === '*') {
|
|
30
|
+
if (source[index + 2] === '!') throw new Error('executable_comment_not_supported');
|
|
31
|
+
const end = source.indexOf('*/', index + 2);
|
|
32
|
+
if (end < 0) throw new Error('unterminated_comment');
|
|
33
|
+
index = end + 2;
|
|
34
|
+
hide(start, index);
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (c === "'" || c === '"' || c === '`') {
|
|
38
|
+
let closed = false;
|
|
39
|
+
index++;
|
|
40
|
+
while(index < source.length){
|
|
41
|
+
if (source[index] === '\\') throw new Error('use_parameters_for_backslash_literals');
|
|
42
|
+
if (source[index] === c) {
|
|
43
|
+
if (source[index + 1] === c) {
|
|
44
|
+
index += 2;
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
index++;
|
|
48
|
+
closed = true;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
index++;
|
|
52
|
+
}
|
|
53
|
+
if (!closed) throw new Error('unterminated_literal');
|
|
54
|
+
hide(start, index, c === "'" ? 'literal' : 'identifier');
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
if (c === '$') {
|
|
58
|
+
var _source_slice_match;
|
|
59
|
+
const tag = (_source_slice_match = source.slice(index).match(/^\$(?:[A-Za-z_][A-Za-z_0-9]*)?\$/)) == null ? void 0 : _source_slice_match[0];
|
|
60
|
+
if (tag) {
|
|
61
|
+
const end = source.indexOf(tag, index + tag.length);
|
|
62
|
+
if (end < 0) throw new Error('unterminated_literal');
|
|
63
|
+
index = end + tag.length;
|
|
64
|
+
hide(start, index, 'literal');
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
index++;
|
|
69
|
+
}
|
|
70
|
+
const text = masked.join('');
|
|
71
|
+
const tokens = [
|
|
72
|
+
...text.matchAll(/[A-Z_][A-Z_0-9]*|[0-9]+|[^\s]/gi)
|
|
73
|
+
].map((match)=>{
|
|
74
|
+
var _quoted_get;
|
|
75
|
+
return {
|
|
76
|
+
text: match[0].toUpperCase(),
|
|
77
|
+
start: match.index,
|
|
78
|
+
end: match.index + match[0].length,
|
|
79
|
+
kind: (_quoted_get = quoted.get(match.index)) != null ? _quoted_get : /^[A-Z_]/i.test(match[0]) ? 'word' : /^[0-9]/.test(match[0]) ? 'number' : 'symbol'
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
masked: text,
|
|
84
|
+
tokens
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const MODIFIED_TYPES = new Set('DECIMAL NUMERIC CHAR VARCHAR NCHAR NVARCHAR BINARY VARBINARY DATETIME TIME TIMESTAMP'.split(' '));
|
|
89
|
+
/** Positions where name(...) declares columns or a built-in type, rather than invoking a function. */ function sqlDeclarationPositions(tokens) {
|
|
90
|
+
const declarations = new Set();
|
|
91
|
+
const closing = new Map(), parents = new Map();
|
|
92
|
+
const stack = [];
|
|
93
|
+
tokens.forEach((token, index)=>{
|
|
94
|
+
if (stack.length) parents.set(index, stack[stack.length - 1]);
|
|
95
|
+
if (token.text === '(') stack.push(index);
|
|
96
|
+
if (token.text === ')') {
|
|
97
|
+
const open = stack.pop();
|
|
98
|
+
if (open !== undefined) closing.set(open, index);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
const name = (index)=>{
|
|
102
|
+
var _tokens_index;
|
|
103
|
+
return [
|
|
104
|
+
'word',
|
|
105
|
+
'identifier'
|
|
106
|
+
].includes((_tokens_index = tokens[index]) == null ? void 0 : _tokens_index.kind);
|
|
107
|
+
};
|
|
108
|
+
const is = (index, word)=>{
|
|
109
|
+
var _tokens_index;
|
|
110
|
+
return ((_tokens_index = tokens[index]) == null ? void 0 : _tokens_index.text) === word;
|
|
111
|
+
};
|
|
112
|
+
for(let i = 0; i < tokens.length; i++){
|
|
113
|
+
if (tokens[i].kind !== 'word' || !is(i, 'WITH')) continue;
|
|
114
|
+
let cursor = i + 1;
|
|
115
|
+
if (is(cursor, 'RECURSIVE')) cursor++;
|
|
116
|
+
while(name(cursor)){
|
|
117
|
+
const declaration = cursor++;
|
|
118
|
+
let columns = false;
|
|
119
|
+
if (is(cursor, '(')) {
|
|
120
|
+
const end = closing.get(cursor);
|
|
121
|
+
if (end === undefined || end === cursor + 1) break;
|
|
122
|
+
const columnTokens = tokens.slice(cursor + 1, end);
|
|
123
|
+
if (columnTokens.length % 2 === 0 || !columnTokens.every((token, n)=>n % 2 === 0 ? [
|
|
124
|
+
'word',
|
|
125
|
+
'identifier'
|
|
126
|
+
].includes(token.kind) : token.text === ',')) break;
|
|
127
|
+
columns = true;
|
|
128
|
+
cursor = end + 1;
|
|
129
|
+
}
|
|
130
|
+
if (!is(cursor++, 'AS')) break;
|
|
131
|
+
if (is(cursor, 'NOT')) cursor++;
|
|
132
|
+
if (is(cursor, 'MATERIALIZED')) cursor++;
|
|
133
|
+
if (!is(cursor, '(')) break;
|
|
134
|
+
const end = closing.get(cursor);
|
|
135
|
+
if (end === undefined) break;
|
|
136
|
+
if (columns) declarations.add(tokens[declaration].start);
|
|
137
|
+
cursor = end + 1;
|
|
138
|
+
if (!is(cursor, ',')) break;
|
|
139
|
+
cursor++;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
tokens.forEach((token, i)=>{
|
|
143
|
+
var _tokens_;
|
|
144
|
+
if (token.kind !== 'word' || !MODIFIED_TYPES.has(token.text) || !is(i + 1, '(')) return;
|
|
145
|
+
const end = closing.get(i + 1);
|
|
146
|
+
if (end === undefined) return;
|
|
147
|
+
const args = tokens.slice(i + 2, end);
|
|
148
|
+
if (![
|
|
149
|
+
1,
|
|
150
|
+
3
|
|
151
|
+
].includes(args.length) || !args.every((arg, n)=>n % 2 ? arg.text === ',' : arg.kind === 'number')) return;
|
|
152
|
+
const parent = parents.get(i);
|
|
153
|
+
const owner = parent === undefined ? undefined : (_tokens_ = tokens[parent - 1]) == null ? void 0 : _tokens_.text;
|
|
154
|
+
const cast = owner === 'CAST' && is(i - 1, 'AS');
|
|
155
|
+
const convert = owner === 'CONVERT' && is(i - 1, ',');
|
|
156
|
+
const postgresCast = is(i - 1, ':') && is(i - 2, ':');
|
|
157
|
+
if (cast || convert || postgresCast) declarations.add(token.start);
|
|
158
|
+
});
|
|
159
|
+
return declarations;
|
|
160
|
+
}
|
|
161
|
+
|
|
9
162
|
const WRITE = new Set([
|
|
10
163
|
'INSERT',
|
|
11
164
|
'UPDATE',
|
|
@@ -40,15 +193,16 @@ const FORBIDDEN = new Set([
|
|
|
40
193
|
'DETACH'
|
|
41
194
|
]);
|
|
42
195
|
const SAFE_FUNCTIONS = new Set('ABS ACOS ASIN ATAN ATAN2 AVG CAST CEIL CEILING COALESCE CONCAT CONCAT_WS CONVERT COS COUNT CURDATE CURRENT_DATE CURRENT_TIMESTAMP DATE DATE_ADD DATE_SUB DATE_FORMAT DATEDIFF DAY DAYOFMONTH DAYOFWEEK EXTRACT FLOOR FORMAT GREATEST GROUP_CONCAT IF IFNULL JSON_EXTRACT JSON_LENGTH JSON_UNQUOTE LEAST LEFT LENGTH LN LOG LOWER LPAD LTRIM MAX MD5 MIN MOD MONTH NOW NULLIF POWER RAND REPLACE REVERSE RIGHT ROUND ROW_NUMBER RANK DENSE_RANK LAG LEAD FIRST_VALUE LAST_VALUE LPAD RPAD RTRIM SIGN SIN SQRT STDDEV STDDEV_POP STDDEV_SAMP SUBSTR SUBSTRING SUM TAN TO_CHAR TO_DATE TO_TIMESTAMP TRIM TRUNC UPPER VAR_POP VAR_SAMP VERSION WEEK YEAR DATABASE CURRENT_DATABASE CURRENT_SCHEMA ARRAY_AGG STRING_AGG JSON_AGG JSON_BUILD_OBJECT PG_GET_VIEWDEF'.split(' '));
|
|
43
|
-
|
|
196
|
+
// FROM/JOIN can introduce a parenthesized subquery, not a function call.
|
|
197
|
+
const SQL_PARENS = new Set('IN AS EXISTS OVER PARTITION VALUES SELECT WITH FROM JOIN AND OR NOT ON USING FILTER GROUPING ROLLUP CUBE DISTINCT EXPLAIN'.split(' '));
|
|
44
198
|
const UNSAFE_FUNCTIONS = /\b(pg_sleep|sleep|benchmark|dblink\w*|lo_\w+|pg_(?:read|write|ls|stat|terminate|cancel|reload|rotate|log|create|drop|promote|switch|backup|replication|advisory)\w*|get_lock|release_lock|load_file|nextval|setval|set_config|http\w*|s3|hdfs|jdbc|mysql|postgresql|file|url)\s*\(/i;
|
|
45
199
|
function splitWorkbenchSql(source) {
|
|
46
|
-
|
|
200
|
+
const { masked, tokens } = lexWorkbenchSql(source);
|
|
47
201
|
const statements = [];
|
|
48
|
-
let start = 0
|
|
202
|
+
let start = 0;
|
|
49
203
|
const finish = (end)=>{
|
|
50
|
-
const text =
|
|
51
|
-
if (text) {
|
|
204
|
+
const text = masked.slice(start, end);
|
|
205
|
+
if (text.trim()) {
|
|
52
206
|
var _text_toUpperCase_match;
|
|
53
207
|
const words = (_text_toUpperCase_match = text.toUpperCase().match(/[A-Z_][A-Z_0-9]*/g)) != null ? _text_toUpperCase_match : [];
|
|
54
208
|
const first = words[0];
|
|
@@ -59,10 +213,11 @@ function splitWorkbenchSql(source) {
|
|
|
59
213
|
if (words.some((word, index)=>WRITE.has(word) && !(first === 'SHOW' && index === 1 && word === 'CREATE') || FORBIDDEN.has(word)) || UNSAFE_FUNCTIONS.test(text) || /\bFOR\s+(UPDATE|SHARE)\b/i.test(text) || /:=|\bEXPLAIN\s+ANALYZE\b|@/i.test(text)) effect = 'unsupported';
|
|
60
214
|
// eslint-disable-next-line no-control-regex -- intentional: reject any non-ASCII/control input
|
|
61
215
|
if (/[^\x00-\x7f]/.test(text) || /\.\s*[A-Z_][A-Z_0-9]*\s*\(/i.test(text)) effect = 'unsupported';
|
|
216
|
+
const declarations = sqlDeclarationPositions(tokens.filter((token)=>token.start >= start && token.end <= end));
|
|
62
217
|
if ([
|
|
63
218
|
...text.matchAll(/([A-Z_][A-Z_0-9]*)\s*\(/gi)
|
|
64
|
-
].some((match)=>!SAFE_FUNCTIONS.has(match[1].toUpperCase()) && !SQL_PARENS.has(match[1].toUpperCase()))) effect = 'unsupported';
|
|
65
|
-
if (first === 'SHOW' && !/^(SHOW\s+(DATABASES|SCHEMAS|CATALOGS|TABLES|FULL\s+TABLES|COLUMNS|FULL\s+COLUMNS|INDEX|INDEXES|KEYS|CREATE\s+TABLE|CREATE\s+VIEW|PARTITIONS|VARIABLES|STATUS|GRANTS))\b/i.test(text)) effect = 'unsupported';
|
|
219
|
+
].some((match)=>!declarations.has(start + match.index) && !SAFE_FUNCTIONS.has(match[1].toUpperCase()) && !SQL_PARENS.has(match[1].toUpperCase()))) effect = 'unsupported';
|
|
220
|
+
if (first === 'SHOW' && !/^(SHOW\s+(DATABASES|SCHEMAS|CATALOGS|TABLES|FULL\s+TABLES|COLUMNS|FULL\s+COLUMNS|INDEX|INDEXES|KEYS|CREATE\s+TABLE|CREATE\s+VIEW|PARTITIONS|VARIABLES|STATUS|GRANTS))\b/i.test(text.trim())) effect = 'unsupported';
|
|
66
221
|
}
|
|
67
222
|
// CREATE/ALTER routines, external resources and privileged SQL are outside this app.
|
|
68
223
|
if (effect === 'write' && /\b(FUNCTION|PROCEDURE|TRIGGER|USER|ROLE|CATALOG|RESOURCE|SYSTEM|SERVER|EXTENSION|FILE|OUTFILE|DUMPFILE|EXECUTE)\b/i.test(text)) effect = 'unsupported';
|
|
@@ -72,63 +227,10 @@ function splitWorkbenchSql(source) {
|
|
|
72
227
|
effect
|
|
73
228
|
});
|
|
74
229
|
}
|
|
75
|
-
clean = '';
|
|
76
230
|
start = end + 1;
|
|
77
231
|
};
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
if (c === '-' && next === '-' || c === '#') {
|
|
81
|
-
while(index < source.length && source[index] !== '\n')index++;
|
|
82
|
-
clean += ' ';
|
|
83
|
-
continue;
|
|
84
|
-
}
|
|
85
|
-
if (c === '/' && next === '*') {
|
|
86
|
-
if (source[index + 2] === '!') throw new Error('executable_comment_not_supported');
|
|
87
|
-
const end = source.indexOf('*/', index + 2);
|
|
88
|
-
if (end < 0) throw new Error('unterminated_comment');
|
|
89
|
-
index = end + 2;
|
|
90
|
-
clean += ' ';
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
if (c === "'" || c === '"' || c === '`') {
|
|
94
|
-
const quote = c;
|
|
95
|
-
let closed = false;
|
|
96
|
-
index++;
|
|
97
|
-
while(index < source.length){
|
|
98
|
-
if (source[index] === '\\') throw new Error('use_parameters_for_backslash_literals');
|
|
99
|
-
if (source[index] === quote) {
|
|
100
|
-
if (source[index + 1] === quote) {
|
|
101
|
-
index += 2;
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
index++;
|
|
105
|
-
closed = true;
|
|
106
|
-
break;
|
|
107
|
-
}
|
|
108
|
-
index++;
|
|
109
|
-
}
|
|
110
|
-
if (!closed) throw new Error('unterminated_literal');
|
|
111
|
-
clean += quote === "'" ? ' ? ' : ' identifier ';
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
if (c === '$') {
|
|
115
|
-
var _source_slice_match;
|
|
116
|
-
const tag = (_source_slice_match = source.slice(index).match(/^\$(?:[A-Za-z_][A-Za-z_0-9]*)?\$/)) == null ? void 0 : _source_slice_match[0];
|
|
117
|
-
if (tag) {
|
|
118
|
-
const end = source.indexOf(tag, index + tag.length);
|
|
119
|
-
if (end < 0) throw new Error('unterminated_literal');
|
|
120
|
-
index = end + tag.length;
|
|
121
|
-
clean += ' ? ';
|
|
122
|
-
continue;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
if (c === ';') {
|
|
126
|
-
finish(index);
|
|
127
|
-
index++;
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
clean += c;
|
|
131
|
-
index++;
|
|
232
|
+
for (const token of tokens){
|
|
233
|
+
if (token.kind === 'symbol' && token.text === ';') finish(token.start);
|
|
132
234
|
}
|
|
133
235
|
finish(source.length);
|
|
134
236
|
if (!statements.length || statements.length > 50) throw new Error('statement_count_exceeded');
|
|
@@ -146,6 +248,53 @@ function quoteDatabaseIdentifier(name, engine) {
|
|
|
146
248
|
return quote + name.split(quote).join(quote + quote) + quote;
|
|
147
249
|
}
|
|
148
250
|
|
|
251
|
+
/** Apply a page to a MySQL result without turning its (possibly duplicate) output names into table columns. */ function paginateMysqlQuery(sql, parameters = [], limit, offset) {
|
|
252
|
+
const { tokens } = lexWorkbenchSql(sql);
|
|
253
|
+
const top = [];
|
|
254
|
+
let depth = 0;
|
|
255
|
+
for (const token of tokens){
|
|
256
|
+
if (token.text === '(') depth++;
|
|
257
|
+
if (!depth) top.push(token);
|
|
258
|
+
if (token.text === ')') depth--;
|
|
259
|
+
if (depth < 0) throw new Error('unsupported_pagination');
|
|
260
|
+
}
|
|
261
|
+
if (depth) throw new Error('unsupported_pagination');
|
|
262
|
+
const start = top.findIndex((token)=>token.kind === 'word' && token.text === 'LIMIT');
|
|
263
|
+
if (start < 0) return {
|
|
264
|
+
sql: `${sql}\nLIMIT ${limit + 1} OFFSET ${offset}`,
|
|
265
|
+
parameters
|
|
266
|
+
};
|
|
267
|
+
const clause = top.slice(start + 1);
|
|
268
|
+
const bindings = tokens.filter((token)=>token.text === '?' && token.kind === 'symbol');
|
|
269
|
+
const consumed = new Set();
|
|
270
|
+
const integer = (token)=>{
|
|
271
|
+
if ((token == null ? void 0 : token.kind) === 'number') return BigInt(token.text);
|
|
272
|
+
if ((token == null ? void 0 : token.kind) === 'symbol' && token.text === '?') {
|
|
273
|
+
const index = bindings.indexOf(token), value = parameters[index];
|
|
274
|
+
if (typeof value === 'number' && Number.isSafeInteger(value) && value >= 0) {
|
|
275
|
+
consumed.add(index);
|
|
276
|
+
return BigInt(value);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
throw new Error('unsupported_pagination');
|
|
280
|
+
};
|
|
281
|
+
let count, skip = 0n;
|
|
282
|
+
if (clause.length === 1) count = integer(clause[0]);
|
|
283
|
+
else if (clause.length === 3 && clause[1].text === ',') {
|
|
284
|
+
skip = integer(clause[0]);
|
|
285
|
+
count = integer(clause[2]);
|
|
286
|
+
} else if (clause.length === 3 && clause[1].kind === 'word' && clause[1].text === 'OFFSET') {
|
|
287
|
+
count = integer(clause[0]);
|
|
288
|
+
skip = integer(clause[2]);
|
|
289
|
+
} else throw new Error('unsupported_pagination');
|
|
290
|
+
const remaining = count > BigInt(offset) ? count - BigInt(offset) : 0n;
|
|
291
|
+
const size = remaining < BigInt(limit + 1) ? remaining : BigInt(limit + 1);
|
|
292
|
+
return {
|
|
293
|
+
sql: `${sql.slice(0, top[start].start)}LIMIT ${size} OFFSET ${skip + BigInt(offset)}${sql.slice(clause[clause.length - 1].end)}`,
|
|
294
|
+
parameters: parameters.filter((_, index)=>!consumed.has(index))
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
149
298
|
const number = (value)=>Number(value != null ? value : 0);
|
|
150
299
|
const string = (value)=>value == null ? '' : String(value);
|
|
151
300
|
const cell = (result, row, name)=>row[result.columns.findIndex((column)=>column.name.toLowerCase() === name.toLowerCase())];
|
|
@@ -387,12 +536,14 @@ const cell = (result, row, name)=>row[result.columns.findIndex((column)=>column.
|
|
|
387
536
|
if (input.mode === 'write' && !(await this.capabilities()).writes) throw new Error('engine_version_writes_unavailable');
|
|
388
537
|
if (input.mode === 'write' && offset) throw new Error('mutation_cannot_be_paginated');
|
|
389
538
|
let sql = statements[0].sql;
|
|
390
|
-
|
|
539
|
+
let parameters = input.parameters;
|
|
391
540
|
if (input.mode === 'read' && [
|
|
392
541
|
'SELECT',
|
|
393
542
|
'WITH'
|
|
394
|
-
].includes(statements[0].words[0]))
|
|
395
|
-
|
|
543
|
+
].includes(statements[0].words[0])) {
|
|
544
|
+
if (this.engine === 'mysql') ({ sql, parameters } = paginateMysqlQuery(sql, parameters, limit, offset));
|
|
545
|
+
else sql = `SELECT * FROM (\n${sql}\n) AS ${this.quote('_db_studio_page')} LIMIT ${limit + 1} OFFSET ${offset}`;
|
|
546
|
+
} else if (offset) throw new Error('statement_cannot_be_paginated');
|
|
396
547
|
this.busy = true;
|
|
397
548
|
let readTransaction = false;
|
|
398
549
|
try {
|
|
@@ -401,7 +552,7 @@ const cell = (result, row, name)=>row[result.columns.findIndex((column)=>column.
|
|
|
401
552
|
readTransaction = true;
|
|
402
553
|
}
|
|
403
554
|
var _input_timeoutMs;
|
|
404
|
-
const result = await this.raw(sql,
|
|
555
|
+
const result = await this.raw(sql, parameters, limit + 1, signal, Math.max(1, Math.min((_input_timeoutMs = input.timeoutMs) != null ? _input_timeoutMs : 30000, 120000)));
|
|
405
556
|
const hasMore = result.rows.length > limit || result.truncated;
|
|
406
557
|
return _extends({}, result, {
|
|
407
558
|
rows: result.rows.slice(0, limit),
|
package/index.cjs.js
CHANGED
|
@@ -515,6 +515,15 @@ function runWithRequestContext(req, res, next) {
|
|
|
515
515
|
}
|
|
516
516
|
|
|
517
517
|
exports.StrategyBus = class StrategyBus {
|
|
518
|
+
registerRemovalGuard(guard) {
|
|
519
|
+
this.removalGuards.add(guard);
|
|
520
|
+
return ()=>{
|
|
521
|
+
this.removalGuards.delete(guard);
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
async assertCanRemove(scopeKey, pluginNames) {
|
|
525
|
+
for (const guard of this.removalGuards)await guard(scopeKey, pluginNames);
|
|
526
|
+
}
|
|
518
527
|
upsert(strategyType, entry) {
|
|
519
528
|
this.subject.next({
|
|
520
529
|
type: 'UPSERT',
|
|
@@ -532,6 +541,7 @@ exports.StrategyBus = class StrategyBus {
|
|
|
532
541
|
} : {}));
|
|
533
542
|
}
|
|
534
543
|
constructor(){
|
|
544
|
+
this.removalGuards = new Set();
|
|
535
545
|
this.subject = new rxjs.Subject();
|
|
536
546
|
this.events$ = this.subject.asObservable();
|
|
537
547
|
}
|
|
@@ -1031,6 +1041,34 @@ exports.KnowledgeStrategyRegistry = __decorate([
|
|
|
1031
1041
|
])
|
|
1032
1042
|
], exports.KnowledgeStrategyRegistry);
|
|
1033
1043
|
|
|
1044
|
+
const KEYWORD_ANALYZER_STRATEGY = 'KEYWORD_ANALYZER_STRATEGY';
|
|
1045
|
+
const KeywordAnalyzerStrategy = (provider)=>common.applyDecorators(common.SetMetadata(KEYWORD_ANALYZER_STRATEGY, provider), common.SetMetadata(STRATEGY_META_KEY, KEYWORD_ANALYZER_STRATEGY));
|
|
1046
|
+
|
|
1047
|
+
exports.KeywordAnalyzerRegistry = class KeywordAnalyzerRegistry extends BaseStrategyRegistry {
|
|
1048
|
+
/** Resolve a pinned source without allowing a higher-priority scope to shadow it. */ getBySource(provider, source, organizationId) {
|
|
1049
|
+
var _this_strategies_get;
|
|
1050
|
+
if (!this.resolveStrategyScopeKeys(organizationId).includes(source.scopeKey)) return undefined;
|
|
1051
|
+
const strategy = (_this_strategies_get = this.strategies.get(source.scopeKey)) == null ? void 0 : _this_strategies_get.get(provider);
|
|
1052
|
+
if (!strategy) return undefined;
|
|
1053
|
+
const registered = this.getSource(strategy);
|
|
1054
|
+
if (registered.kind !== source.kind || registered.scopeKey !== source.scopeKey) return undefined;
|
|
1055
|
+
if (source.kind === 'plugin' && (registered.kind !== 'plugin' || registered.pluginName !== source.pluginName)) {
|
|
1056
|
+
return undefined;
|
|
1057
|
+
}
|
|
1058
|
+
return strategy;
|
|
1059
|
+
}
|
|
1060
|
+
constructor(discoveryService, reflector){
|
|
1061
|
+
super(KEYWORD_ANALYZER_STRATEGY, discoveryService, reflector);
|
|
1062
|
+
}
|
|
1063
|
+
};
|
|
1064
|
+
exports.KeywordAnalyzerRegistry = __decorate([
|
|
1065
|
+
common.Injectable(),
|
|
1066
|
+
__metadata("design:paramtypes", [
|
|
1067
|
+
core.DiscoveryService,
|
|
1068
|
+
core.Reflector
|
|
1069
|
+
])
|
|
1070
|
+
], exports.KeywordAnalyzerRegistry);
|
|
1071
|
+
|
|
1034
1072
|
const TOOLSET_STRATEGY = 'TOOLSET_STRATEGY';
|
|
1035
1073
|
/**
|
|
1036
1074
|
* Decorator to mark a provider as a Toolset Strategy
|
|
@@ -9849,7 +9887,9 @@ exports.ImageUnderstandingStrategy = ImageUnderstandingStrategy;
|
|
|
9849
9887
|
exports.IntegrationStrategyKey = IntegrationStrategyKey;
|
|
9850
9888
|
exports.JUMP_TO_TARGETS = JUMP_TO_TARGETS;
|
|
9851
9889
|
exports.JsonSchemaValidator = JsonSchemaValidator;
|
|
9890
|
+
exports.KEYWORD_ANALYZER_STRATEGY = KEYWORD_ANALYZER_STRATEGY;
|
|
9852
9891
|
exports.KNOWLEDGE_STRATEGY = KNOWLEDGE_STRATEGY;
|
|
9892
|
+
exports.KeywordAnalyzerStrategy = KeywordAnalyzerStrategy;
|
|
9853
9893
|
exports.KnowledgeStrategyKey = KnowledgeStrategyKey;
|
|
9854
9894
|
exports.LLMUsage = LLMUsage;
|
|
9855
9895
|
exports.LargeLanguageModel = LargeLanguageModel;
|
package/index.esm.js
CHANGED
|
@@ -497,6 +497,15 @@ function runWithRequestContext(req, res, next) {
|
|
|
497
497
|
}
|
|
498
498
|
|
|
499
499
|
let StrategyBus = class StrategyBus {
|
|
500
|
+
registerRemovalGuard(guard) {
|
|
501
|
+
this.removalGuards.add(guard);
|
|
502
|
+
return ()=>{
|
|
503
|
+
this.removalGuards.delete(guard);
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
async assertCanRemove(scopeKey, pluginNames) {
|
|
507
|
+
for (const guard of this.removalGuards)await guard(scopeKey, pluginNames);
|
|
508
|
+
}
|
|
500
509
|
upsert(strategyType, entry) {
|
|
501
510
|
this.subject.next({
|
|
502
511
|
type: 'UPSERT',
|
|
@@ -514,6 +523,7 @@ let StrategyBus = class StrategyBus {
|
|
|
514
523
|
} : {}));
|
|
515
524
|
}
|
|
516
525
|
constructor(){
|
|
526
|
+
this.removalGuards = new Set();
|
|
517
527
|
this.subject = new Subject();
|
|
518
528
|
this.events$ = this.subject.asObservable();
|
|
519
529
|
}
|
|
@@ -1013,6 +1023,34 @@ KnowledgeStrategyRegistry = __decorate([
|
|
|
1013
1023
|
])
|
|
1014
1024
|
], KnowledgeStrategyRegistry);
|
|
1015
1025
|
|
|
1026
|
+
const KEYWORD_ANALYZER_STRATEGY = 'KEYWORD_ANALYZER_STRATEGY';
|
|
1027
|
+
const KeywordAnalyzerStrategy = (provider)=>applyDecorators(SetMetadata(KEYWORD_ANALYZER_STRATEGY, provider), SetMetadata(STRATEGY_META_KEY, KEYWORD_ANALYZER_STRATEGY));
|
|
1028
|
+
|
|
1029
|
+
let KeywordAnalyzerRegistry = class KeywordAnalyzerRegistry extends BaseStrategyRegistry {
|
|
1030
|
+
/** Resolve a pinned source without allowing a higher-priority scope to shadow it. */ getBySource(provider, source, organizationId) {
|
|
1031
|
+
var _this_strategies_get;
|
|
1032
|
+
if (!this.resolveStrategyScopeKeys(organizationId).includes(source.scopeKey)) return undefined;
|
|
1033
|
+
const strategy = (_this_strategies_get = this.strategies.get(source.scopeKey)) == null ? void 0 : _this_strategies_get.get(provider);
|
|
1034
|
+
if (!strategy) return undefined;
|
|
1035
|
+
const registered = this.getSource(strategy);
|
|
1036
|
+
if (registered.kind !== source.kind || registered.scopeKey !== source.scopeKey) return undefined;
|
|
1037
|
+
if (source.kind === 'plugin' && (registered.kind !== 'plugin' || registered.pluginName !== source.pluginName)) {
|
|
1038
|
+
return undefined;
|
|
1039
|
+
}
|
|
1040
|
+
return strategy;
|
|
1041
|
+
}
|
|
1042
|
+
constructor(discoveryService, reflector){
|
|
1043
|
+
super(KEYWORD_ANALYZER_STRATEGY, discoveryService, reflector);
|
|
1044
|
+
}
|
|
1045
|
+
};
|
|
1046
|
+
KeywordAnalyzerRegistry = __decorate([
|
|
1047
|
+
Injectable(),
|
|
1048
|
+
__metadata("design:paramtypes", [
|
|
1049
|
+
DiscoveryService,
|
|
1050
|
+
Reflector
|
|
1051
|
+
])
|
|
1052
|
+
], KeywordAnalyzerRegistry);
|
|
1053
|
+
|
|
1016
1054
|
const TOOLSET_STRATEGY = 'TOOLSET_STRATEGY';
|
|
1017
1055
|
/**
|
|
1018
1056
|
* Decorator to mark a provider as a Toolset Strategy
|
|
@@ -9701,4 +9739,4 @@ function stableJson(value) {
|
|
|
9701
9739
|
return `{${entries.map(([key, item])=>`${JSON.stringify(key)}:${stableJson(item)}`).join(',')}}`;
|
|
9702
9740
|
}
|
|
9703
9741
|
|
|
9704
|
-
export { ACCOUNT_BINDING_PERMISSION_SERVICE_TOKEN, AGENT_CHAT_DISPATCH_ERROR_STEER_TARGET_NOT_RUNNING, AGENT_CHAT_DISPATCH_MESSAGE_TYPE, AGENT_MIDDLEWARE_STRATEGY, AIModel, AIModelProviderNotFoundException, AIModelProviderRegistry, AIModelProviderStrategy, AI_MODEL_PROVIDER, AdapterDataSourceStrategy, AgentMiddlewareRegistry, AgentMiddlewareStrategy, AiModelNotFoundException, AssistantTaskRuntimeCapability, BOUND_IDENTITY_LOGIN_PERMISSION_SERVICE_TOKEN, BUILTIN_GLOBAL_SCOPE, BaseHTTPQueryRunner, BaseQueryRunner, BaseSQLQueryRunner, BaseSandbox, BaseStrategyRegistry, BuiltinToolset, CHAT_CHANNEL, CHAT_CHANNEL_TEXT_LIMITS, COLLABORATION_DOCUMENT_PROVIDER, CONNECTION_COMMAND_ROUTER_TOKEN, CONNECTOR_STRATEGY, CancelConversationCommand, ChatChannel, ChatChannelRegistry, ChatOAICompatReasoningModel, CollaborationDocumentProvider, CollaborationDocumentProviderRegistry, CollaborationRuntimeCapability, CommonParameterRules, ConnectorRuntimeCapability, ConnectorRuntimeFactoryCapability, ConnectorStrategyKey, ConnectorStrategyRegistry, CreateModelClientCommand, CredentialsValidateFailedError, DATASOURCE_STRATEGY, DBCreateTableMode, DBProtocolEnum, DBSyntaxEnum, DBTableAction, DBTableDataAction, DEFAULT_EXECUTION_CONFIG, DEFAULT_SANDBOX_EXECUTION_MAX_OUTPUT_BYTES, DEFAULT_SANDBOX_FILE_OPERATION_EXECUTION_OPTIONS, DEFAULT_SANDBOX_FILE_OPERATION_TIMEOUT_MS, DEFAULT_SANDBOX_FILE_OPERATION_TIMEOUT_SEC, DEFAULT_SANDBOX_FILE_SEARCH_EXECUTION_OPTIONS, DEFAULT_SANDBOX_FILE_SEARCH_TIMEOUT_MS, DEFAULT_SANDBOX_FILE_SEARCH_TIMEOUT_SEC, DEFAULT_SANDBOX_SHELL_EXECUTION_OPTIONS, DEFAULT_SANDBOX_SHELL_TIMEOUT_MS, DEFAULT_SANDBOX_SHELL_TIMEOUT_SEC, DOCUMENT_SOURCE_STRATEGY, DOCUMENT_TRANSFORMER_STRATEGY, DataSourceStrategy, DataSourceStrategyRegistry, DecoratedAgentMiddlewareStrategy, DecoratedToolsetStrategy, DocumentSourceRegistry, DocumentSourceStrategy, DocumentTransformerRegistry, DocumentTransformerStrategy, EVOLUTION_RUNTIME_SERVICE_TOKEN, EVOLUTION_TARGET_PROVIDER, EvolutionChangeRuntimeCapability, EvolutionRuntimeCapability, EvolutionTargetProviderRegistry, EvolutionTargetProviderStrategy, FILE_STORAGE_PROVIDER, FILE_UPLOAD_TARGET_STRATEGY, FileRuntimeCapability, FileStorageProvider, FileStorageProviderRegistry, FileUploadTargetRegistry, FileUploadTargetStrategy, GLOBAL_ORGANIZATION_SCOPE, HANDOFF_PERMISSION_SERVICE_TOKEN, HANDOFF_PROCESSOR_STRATEGY, HANDOFF_QUEUE_SERVICE_TOKEN, HandoffProcessorRegistry, HandoffProcessorStrategy, IMAGE_UNDERSTANDING_STRATEGY, INTEGRATION_PERMISSION_SERVICE_TOKEN, INTEGRATION_STRATEGY, ImageGenerationModel, ImageUnderstandingRegistry, ImageUnderstandingStrategy, IntegrationStrategyKey, IntegrationStrategyRegistry, JUMP_TO_TARGETS, JsonSchemaValidator, KNOWLEDGE_STRATEGY, KnowledgeStrategyKey, KnowledgeStrategyRegistry, LLMUsage, LargeLanguageModel, MANAGED_CONNECTION_REGISTRY_TOKEN, MANAGED_QUEUE_HANDLER_REGISTRY_TOKEN, MANAGED_QUEUE_SERVICE_TOKEN, MCP_CAPABILITY_CHANGE_EVENT_TYPES, MODEL_OUTPUT_VALIDATION_ERROR_CODE, ModelOutputValidationError, ModelProvider, ORGANIZATION_METADATA_KEY, OpenAICompatibleReranker, PERMISSION_OPERATION_METADATA_KEY, PLUGIN_CONFIG_RESOLVER_TOKEN, PLUGIN_JOB_PROCESSOR_METADATA, PLUGIN_METADATA, PLUGIN_METADATA_KEY, PLUGIN_VERSION_METADATA_KEY, PLUGIN_WEBHOOK_AUTH_METADATA_KEY, PLUGIN_WEBHOOK_AUTH_SERVICE_TOKEN, PROVIDE_AI_MODEL_LLM, PROVIDE_AI_MODEL_MODERATION, PROVIDE_AI_MODEL_RERANK, PROVIDE_AI_MODEL_SPEECH2TEXT, PROVIDE_AI_MODEL_TEXT_EMBEDDING, PROVIDE_AI_MODEL_TTS, PluginJobProcessor, PluginWebhookAuth, PluginWebhookAuthGuard, RETRIEVER_STRATEGY, RequestContext, RequestContextMiddleware, RequirePermissionOperation, RerankModel, RetrieverRegistry, RetrieverStrategy, SANDBOX_PROVIDER, SANDBOX_RUNTIME_PROVIDER, SANDBOX_SHELL_TIMEOUT_LIMITS_SEC, SANDBOX_WORKSPACE_MAPPER, SKILL_SOURCE_PROVIDER, SPEECH_TO_TEXT_PERMISSION_SERVICE_TOKEN, SPEECH_TO_TEXT_SERVICE_TOKEN, SSOProviderRegistry, SSOProviderStrategyKey, SSO_BINDING_PERMISSION_SERVICE_TOKEN, SSO_PROVIDER, STRATEGY_META_KEY, SYSTEM_GLOBAL_SCOPE, SandboxProviderRegistry, SandboxProviderStrategy, SandboxRuntimeProviderRegistry, SandboxRuntimeProviderStrategy, SandboxWorkspaceMapperRegistry, SandboxWorkspaceMapperStrategy, SkillSourceProviderRegistry, SkillSourceProviderStrategy, Speech2TextChatModel, SpeechToTextModel, StrategyBus, TENANT_GLOBAL_SCOPE_PREFIX, TENANT_GLOBAL_SCOPE_SUFFIX, TEXT_SPLITTER_STRATEGY, TOOLSET_STRATEGY, TextEmbeddingModelManager, TextSplitterRegistry, TextSplitterStrategy, TextToSpeechModel, ToolsetRegistry, ToolsetStrategy, USER_PERMISSION_SERVICE_TOKEN, VECTOR_STORE_STRATEGY, VIDEO_GENERATION_PERMISSION_SERVICE_TOKEN, VIDEO_GENERATION_SERVICE_TOKEN, VIDEO_GENERATOR_FAMILIES, VIEW_EXTENSION_CACHE_SERVICE_TOKEN, VIEW_EXTENSION_PROVIDER, VectorStoreRegistry, VectorStoreStrategy, VideoGenerationModel, ViewExtensionProvider, ViewExtensionProviderRegistry, WORKFLOW_NODE_STRATEGY, WORKFLOW_TRIGGER_STRATEGY, WorkflowNodeRegistry, WorkflowNodeStrategy, WorkflowTriggerRegistry, WorkflowTriggerStrategy, WorkspaceFilesRuntimeCapability, WrapWorkflowNodeExecutionCommand, XPERT_AGENT_MIDDLEWARE_RUNTIME_TOKEN, XPERT_TOOL_METHOD_METADATA, XPERT_TOOL_PROVIDER, XPERT_TOOL_PROVIDER_METADATA, XPERT_TOOL_RESULT_FORMAT_VERSION, XpFileSystem, XpertPrompt, XpertResource, XpertResourceTemplate, XpertServerPlugin, XpertTool, XpertToolProvider, XpertToolProviderCoordinator, XpertToolProviderRegistry, als, appendSandboxMessage, assertConnectorDefinition, buildSandboxTimeoutMessage, calcTokenUsage, calculateLLMUsagePrice, calculateModelPrice, calculateModelUsageCharge, chunkText, countTextTokens, countTokensSafe, createI18nInstance, createPluginLogger, createRuntimeCapability, defineAgentMessageType, defineChannelMessageType, defineMcpApp, defineMcpCapabilities, defineMcpPrompt, defineMcpResource, defineMcpResourceTemplate, defineXpertTool, derivePluginArtifactNamespace, describeXpertToolProvider, downloadRemoteFile, formatSandboxTimeout, getDefaultTenantId, getErrorMessage, getModelContextSize, getPermissionOperationMetadata, getPositionList, getPositionMap, getRequestContext, getRequiredPermissionOperation, getTenantGlobalScopeKey, getXpertToolMethod, isDevelopmentSandboxRuntimeEnvironment, isModelOutputValidationError, isModelUsagePricingConfig, isRemoteFile, isSandboxBackend, isSandboxManagedServiceAdapter, isSandboxServiceProxyAdapter, isSandboxTerminalAdapter, isStrategyInstance, isStructuredMessageType, isTenantGlobalScopeKey, loadYamlFile, mergeCredentials, mergeParentChildChunks, normalizeContextSize, pluginArtifactTableName, prepareToolResult, processAsyncAIGCManagedJob, renderRemoteModuleIframeHtml, renderRemoteReactIframeHtml, renderRemoteVueIframeHtml, resolveModelUsagePricingSnapshot, resolveSandboxBackend, resolveSandboxExecutionOptions, resolveSandboxManagedServiceAdapter, resolveSandboxServiceProxyAdapter, resolveSandboxTerminalAdapter, resolveStrategyMetadataTarget, resolveTenantGlobalScopeKey, resolveTokenUsage, resolveXpertMcpExtensions, runWithRequestContext, runtimeToolProviderComponent, secondsToMilliseconds, setDefaultTenantId, sumTokenUsage, textTokenBoundaries };
|
|
9742
|
+
export { ACCOUNT_BINDING_PERMISSION_SERVICE_TOKEN, AGENT_CHAT_DISPATCH_ERROR_STEER_TARGET_NOT_RUNNING, AGENT_CHAT_DISPATCH_MESSAGE_TYPE, AGENT_MIDDLEWARE_STRATEGY, AIModel, AIModelProviderNotFoundException, AIModelProviderRegistry, AIModelProviderStrategy, AI_MODEL_PROVIDER, AdapterDataSourceStrategy, AgentMiddlewareRegistry, AgentMiddlewareStrategy, AiModelNotFoundException, AssistantTaskRuntimeCapability, BOUND_IDENTITY_LOGIN_PERMISSION_SERVICE_TOKEN, BUILTIN_GLOBAL_SCOPE, BaseHTTPQueryRunner, BaseQueryRunner, BaseSQLQueryRunner, BaseSandbox, BaseStrategyRegistry, BuiltinToolset, CHAT_CHANNEL, CHAT_CHANNEL_TEXT_LIMITS, COLLABORATION_DOCUMENT_PROVIDER, CONNECTION_COMMAND_ROUTER_TOKEN, CONNECTOR_STRATEGY, CancelConversationCommand, ChatChannel, ChatChannelRegistry, ChatOAICompatReasoningModel, CollaborationDocumentProvider, CollaborationDocumentProviderRegistry, CollaborationRuntimeCapability, CommonParameterRules, ConnectorRuntimeCapability, ConnectorRuntimeFactoryCapability, ConnectorStrategyKey, ConnectorStrategyRegistry, CreateModelClientCommand, CredentialsValidateFailedError, DATASOURCE_STRATEGY, DBCreateTableMode, DBProtocolEnum, DBSyntaxEnum, DBTableAction, DBTableDataAction, DEFAULT_EXECUTION_CONFIG, DEFAULT_SANDBOX_EXECUTION_MAX_OUTPUT_BYTES, DEFAULT_SANDBOX_FILE_OPERATION_EXECUTION_OPTIONS, DEFAULT_SANDBOX_FILE_OPERATION_TIMEOUT_MS, DEFAULT_SANDBOX_FILE_OPERATION_TIMEOUT_SEC, DEFAULT_SANDBOX_FILE_SEARCH_EXECUTION_OPTIONS, DEFAULT_SANDBOX_FILE_SEARCH_TIMEOUT_MS, DEFAULT_SANDBOX_FILE_SEARCH_TIMEOUT_SEC, DEFAULT_SANDBOX_SHELL_EXECUTION_OPTIONS, DEFAULT_SANDBOX_SHELL_TIMEOUT_MS, DEFAULT_SANDBOX_SHELL_TIMEOUT_SEC, DOCUMENT_SOURCE_STRATEGY, DOCUMENT_TRANSFORMER_STRATEGY, DataSourceStrategy, DataSourceStrategyRegistry, DecoratedAgentMiddlewareStrategy, DecoratedToolsetStrategy, DocumentSourceRegistry, DocumentSourceStrategy, DocumentTransformerRegistry, DocumentTransformerStrategy, EVOLUTION_RUNTIME_SERVICE_TOKEN, EVOLUTION_TARGET_PROVIDER, EvolutionChangeRuntimeCapability, EvolutionRuntimeCapability, EvolutionTargetProviderRegistry, EvolutionTargetProviderStrategy, FILE_STORAGE_PROVIDER, FILE_UPLOAD_TARGET_STRATEGY, FileRuntimeCapability, FileStorageProvider, FileStorageProviderRegistry, FileUploadTargetRegistry, FileUploadTargetStrategy, GLOBAL_ORGANIZATION_SCOPE, HANDOFF_PERMISSION_SERVICE_TOKEN, HANDOFF_PROCESSOR_STRATEGY, HANDOFF_QUEUE_SERVICE_TOKEN, HandoffProcessorRegistry, HandoffProcessorStrategy, IMAGE_UNDERSTANDING_STRATEGY, INTEGRATION_PERMISSION_SERVICE_TOKEN, INTEGRATION_STRATEGY, ImageGenerationModel, ImageUnderstandingRegistry, ImageUnderstandingStrategy, IntegrationStrategyKey, IntegrationStrategyRegistry, JUMP_TO_TARGETS, JsonSchemaValidator, KEYWORD_ANALYZER_STRATEGY, KNOWLEDGE_STRATEGY, KeywordAnalyzerRegistry, KeywordAnalyzerStrategy, KnowledgeStrategyKey, KnowledgeStrategyRegistry, LLMUsage, LargeLanguageModel, MANAGED_CONNECTION_REGISTRY_TOKEN, MANAGED_QUEUE_HANDLER_REGISTRY_TOKEN, MANAGED_QUEUE_SERVICE_TOKEN, MCP_CAPABILITY_CHANGE_EVENT_TYPES, MODEL_OUTPUT_VALIDATION_ERROR_CODE, ModelOutputValidationError, ModelProvider, ORGANIZATION_METADATA_KEY, OpenAICompatibleReranker, PERMISSION_OPERATION_METADATA_KEY, PLUGIN_CONFIG_RESOLVER_TOKEN, PLUGIN_JOB_PROCESSOR_METADATA, PLUGIN_METADATA, PLUGIN_METADATA_KEY, PLUGIN_VERSION_METADATA_KEY, PLUGIN_WEBHOOK_AUTH_METADATA_KEY, PLUGIN_WEBHOOK_AUTH_SERVICE_TOKEN, PROVIDE_AI_MODEL_LLM, PROVIDE_AI_MODEL_MODERATION, PROVIDE_AI_MODEL_RERANK, PROVIDE_AI_MODEL_SPEECH2TEXT, PROVIDE_AI_MODEL_TEXT_EMBEDDING, PROVIDE_AI_MODEL_TTS, PluginJobProcessor, PluginWebhookAuth, PluginWebhookAuthGuard, RETRIEVER_STRATEGY, RequestContext, RequestContextMiddleware, RequirePermissionOperation, RerankModel, RetrieverRegistry, RetrieverStrategy, SANDBOX_PROVIDER, SANDBOX_RUNTIME_PROVIDER, SANDBOX_SHELL_TIMEOUT_LIMITS_SEC, SANDBOX_WORKSPACE_MAPPER, SKILL_SOURCE_PROVIDER, SPEECH_TO_TEXT_PERMISSION_SERVICE_TOKEN, SPEECH_TO_TEXT_SERVICE_TOKEN, SSOProviderRegistry, SSOProviderStrategyKey, SSO_BINDING_PERMISSION_SERVICE_TOKEN, SSO_PROVIDER, STRATEGY_META_KEY, SYSTEM_GLOBAL_SCOPE, SandboxProviderRegistry, SandboxProviderStrategy, SandboxRuntimeProviderRegistry, SandboxRuntimeProviderStrategy, SandboxWorkspaceMapperRegistry, SandboxWorkspaceMapperStrategy, SkillSourceProviderRegistry, SkillSourceProviderStrategy, Speech2TextChatModel, SpeechToTextModel, StrategyBus, TENANT_GLOBAL_SCOPE_PREFIX, TENANT_GLOBAL_SCOPE_SUFFIX, TEXT_SPLITTER_STRATEGY, TOOLSET_STRATEGY, TextEmbeddingModelManager, TextSplitterRegistry, TextSplitterStrategy, TextToSpeechModel, ToolsetRegistry, ToolsetStrategy, USER_PERMISSION_SERVICE_TOKEN, VECTOR_STORE_STRATEGY, VIDEO_GENERATION_PERMISSION_SERVICE_TOKEN, VIDEO_GENERATION_SERVICE_TOKEN, VIDEO_GENERATOR_FAMILIES, VIEW_EXTENSION_CACHE_SERVICE_TOKEN, VIEW_EXTENSION_PROVIDER, VectorStoreRegistry, VectorStoreStrategy, VideoGenerationModel, ViewExtensionProvider, ViewExtensionProviderRegistry, WORKFLOW_NODE_STRATEGY, WORKFLOW_TRIGGER_STRATEGY, WorkflowNodeRegistry, WorkflowNodeStrategy, WorkflowTriggerRegistry, WorkflowTriggerStrategy, WorkspaceFilesRuntimeCapability, WrapWorkflowNodeExecutionCommand, XPERT_AGENT_MIDDLEWARE_RUNTIME_TOKEN, XPERT_TOOL_METHOD_METADATA, XPERT_TOOL_PROVIDER, XPERT_TOOL_PROVIDER_METADATA, XPERT_TOOL_RESULT_FORMAT_VERSION, XpFileSystem, XpertPrompt, XpertResource, XpertResourceTemplate, XpertServerPlugin, XpertTool, XpertToolProvider, XpertToolProviderCoordinator, XpertToolProviderRegistry, als, appendSandboxMessage, assertConnectorDefinition, buildSandboxTimeoutMessage, calcTokenUsage, calculateLLMUsagePrice, calculateModelPrice, calculateModelUsageCharge, chunkText, countTextTokens, countTokensSafe, createI18nInstance, createPluginLogger, createRuntimeCapability, defineAgentMessageType, defineChannelMessageType, defineMcpApp, defineMcpCapabilities, defineMcpPrompt, defineMcpResource, defineMcpResourceTemplate, defineXpertTool, derivePluginArtifactNamespace, describeXpertToolProvider, downloadRemoteFile, formatSandboxTimeout, getDefaultTenantId, getErrorMessage, getModelContextSize, getPermissionOperationMetadata, getPositionList, getPositionMap, getRequestContext, getRequiredPermissionOperation, getTenantGlobalScopeKey, getXpertToolMethod, isDevelopmentSandboxRuntimeEnvironment, isModelOutputValidationError, isModelUsagePricingConfig, isRemoteFile, isSandboxBackend, isSandboxManagedServiceAdapter, isSandboxServiceProxyAdapter, isSandboxTerminalAdapter, isStrategyInstance, isStructuredMessageType, isTenantGlobalScopeKey, loadYamlFile, mergeCredentials, mergeParentChildChunks, normalizeContextSize, pluginArtifactTableName, prepareToolResult, processAsyncAIGCManagedJob, renderRemoteModuleIframeHtml, renderRemoteReactIframeHtml, renderRemoteVueIframeHtml, resolveModelUsagePricingSnapshot, resolveSandboxBackend, resolveSandboxExecutionOptions, resolveSandboxManagedServiceAdapter, resolveSandboxServiceProxyAdapter, resolveSandboxTerminalAdapter, resolveStrategyMetadataTarget, resolveTenantGlobalScopeKey, resolveTokenUsage, resolveXpertMcpExtensions, runWithRequestContext, runtimeToolProviderComponent, secondsToMilliseconds, setDefaultTenantId, sumTokenUsage, textTokenBoundaries };
|
package/package.json
CHANGED
|
@@ -11,6 +11,9 @@ export type StrategyBusEvent<S = any> = {
|
|
|
11
11
|
cause?: 'refresh' | 'uninstall';
|
|
12
12
|
};
|
|
13
13
|
export declare class StrategyBus {
|
|
14
|
+
private readonly removalGuards;
|
|
15
|
+
registerRemovalGuard(guard: (scopeKey: string, pluginNames: readonly string[]) => Promise<void>): () => void;
|
|
16
|
+
assertCanRemove(scopeKey: string, pluginNames: readonly string[]): Promise<void>;
|
|
14
17
|
private readonly subject;
|
|
15
18
|
readonly events$: import("rxjs").Observable<StrategyBusEvent<any>>;
|
|
16
19
|
upsert<S>(strategyType: string, entry: StrategyEntry<S>): void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DatabaseValue } from './workbench';
|
|
2
|
+
/** Apply a page to a MySQL result without turning its (possibly duplicate) output names into table columns. */
|
|
3
|
+
export declare function paginateMysqlQuery(sql: string, parameters: DatabaseValue[], limit: number, offset: number): {
|
|
4
|
+
sql: string;
|
|
5
|
+
parameters: DatabaseValue[];
|
|
6
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface SqlToken {
|
|
2
|
+
text: string;
|
|
3
|
+
start: number;
|
|
4
|
+
end: number;
|
|
5
|
+
kind: 'word' | 'number' | 'symbol' | 'identifier' | 'literal';
|
|
6
|
+
}
|
|
7
|
+
/** Mask comments and quoted content without changing source offsets. Shared by guards and pagination. */
|
|
8
|
+
export declare function lexWorkbenchSql(source: string): {
|
|
9
|
+
masked: string;
|
|
10
|
+
tokens: SqlToken[];
|
|
11
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const KEYWORD_ANALYZER_STRATEGY = "KEYWORD_ANALYZER_STRATEGY";
|
|
2
|
+
export declare const KeywordAnalyzerStrategy: (provider: string) => <TFunction extends Function, Y>(target: TFunction | object, propertyKey?: string | symbol, descriptor?: TypedPropertyDescriptor<Y>) => void;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface IKeywordAnalyzerStrategy {
|
|
2
|
+
readonly meta: {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
languages: string[];
|
|
6
|
+
/** Change whenever index/query compatibility changes, including dictionary updates. */
|
|
7
|
+
revision: string;
|
|
8
|
+
};
|
|
9
|
+
/** Return ordered lexemes. The host encodes them as data, never as SQL or tsquery syntax. */
|
|
10
|
+
analyze(text: string, purpose: 'index' | 'query'): Promise<readonly string[]>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { DiscoveryService, Reflector } from '@nestjs/core';
|
|
2
|
+
import { BaseStrategyRegistry, StrategySource } from '../../strategy';
|
|
3
|
+
import { IKeywordAnalyzerStrategy } from './strategy.interface';
|
|
4
|
+
export declare class KeywordAnalyzerRegistry extends BaseStrategyRegistry<IKeywordAnalyzerStrategy> {
|
|
5
|
+
constructor(discoveryService: DiscoveryService, reflector: Reflector);
|
|
6
|
+
/** Resolve a pinned source without allowing a higher-priority scope to shadow it. */
|
|
7
|
+
getBySource(provider: string, source: StrategySource, organizationId?: string): IKeywordAnalyzerStrategy | undefined;
|
|
8
|
+
}
|
package/src/lib/rag/index.d.ts
CHANGED