notoken-core 1.6.0 → 1.8.0
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/config/ascii-art.json +12 -0
- package/config/chat-responses.json +1019 -0
- package/config/cheat-sheets.json +94 -0
- package/config/concept-clusters.json +31 -0
- package/config/daily-tips.json +105 -0
- package/config/entities.json +93 -0
- package/config/history-today.json +9762 -0
- package/config/image-prompts.json +20 -0
- package/config/intent-vectors.json +1 -0
- package/config/intents.json +5354 -85
- package/config/ollama-models.json +193 -0
- package/config/rules.json +32 -1
- package/config/startup-quotes.json +45 -0
- package/dist/automation/discordPatchright.d.ts +35 -0
- package/dist/automation/discordPatchright.js +424 -0
- package/dist/automation/discordSetup.d.ts +31 -0
- package/dist/automation/discordSetup.js +338 -0
- package/dist/automation/smAutomation.d.ts +82 -0
- package/dist/automation/smAutomation.js +448 -0
- package/dist/conversation/coreference.js +44 -4
- package/dist/conversation/pendingActions.d.ts +55 -0
- package/dist/conversation/pendingActions.js +127 -0
- package/dist/conversation/store.d.ts +72 -0
- package/dist/conversation/store.js +140 -1
- package/dist/conversation/topicTracker.d.ts +36 -0
- package/dist/conversation/topicTracker.js +141 -0
- package/dist/execution/ssh.d.ts +42 -1
- package/dist/execution/ssh.js +538 -3
- package/dist/handlers/executor.d.ts +2 -0
- package/dist/handlers/executor.js +4234 -31
- package/dist/index.d.ts +35 -4
- package/dist/index.js +51 -3
- package/dist/nlp/batchParser.d.ts +30 -0
- package/dist/nlp/batchParser.js +77 -0
- package/dist/nlp/conceptExpansion.d.ts +54 -0
- package/dist/nlp/conceptExpansion.js +136 -0
- package/dist/nlp/conceptRouter.d.ts +49 -0
- package/dist/nlp/conceptRouter.js +302 -0
- package/dist/nlp/confidenceCalibrator.d.ts +62 -0
- package/dist/nlp/confidenceCalibrator.js +116 -0
- package/dist/nlp/correctionLearner.d.ts +45 -0
- package/dist/nlp/correctionLearner.js +207 -0
- package/dist/nlp/entitySpellCorrect.d.ts +35 -0
- package/dist/nlp/entitySpellCorrect.js +141 -0
- package/dist/nlp/knowledgeGraph.d.ts +70 -0
- package/dist/nlp/knowledgeGraph.js +380 -0
- package/dist/nlp/llmFallback.js +28 -1
- package/dist/nlp/multiClassifier.js +91 -6
- package/dist/nlp/multiIntent.d.ts +43 -0
- package/dist/nlp/multiIntent.js +154 -0
- package/dist/nlp/parseIntent.d.ts +6 -1
- package/dist/nlp/parseIntent.js +180 -5
- package/dist/nlp/ruleParser.js +317 -0
- package/dist/nlp/semanticSimilarity.d.ts +30 -0
- package/dist/nlp/semanticSimilarity.js +174 -0
- package/dist/nlp/vocabularyBuilder.d.ts +43 -0
- package/dist/nlp/vocabularyBuilder.js +224 -0
- package/dist/nlp/wikidata.d.ts +49 -0
- package/dist/nlp/wikidata.js +228 -0
- package/dist/policy/confirm.d.ts +10 -0
- package/dist/policy/confirm.js +39 -0
- package/dist/policy/safety.js +6 -4
- package/dist/types/intent.d.ts +8 -0
- package/dist/types/intent.js +1 -0
- package/dist/utils/achievements.d.ts +38 -0
- package/dist/utils/achievements.js +126 -0
- package/dist/utils/aliases.d.ts +5 -0
- package/dist/utils/aliases.js +39 -0
- package/dist/utils/analysis.js +71 -15
- package/dist/utils/bookmarks.d.ts +13 -0
- package/dist/utils/bookmarks.js +51 -0
- package/dist/utils/browser.d.ts +64 -0
- package/dist/utils/browser.js +364 -0
- package/dist/utils/commandHistory.d.ts +20 -0
- package/dist/utils/commandHistory.js +108 -0
- package/dist/utils/completer.d.ts +17 -0
- package/dist/utils/completer.js +79 -0
- package/dist/utils/config.js +32 -2
- package/dist/utils/dbQuery.d.ts +25 -0
- package/dist/utils/dbQuery.js +248 -0
- package/dist/utils/devTools.d.ts +35 -0
- package/dist/utils/devTools.js +95 -0
- package/dist/utils/discordDiag.d.ts +35 -0
- package/dist/utils/discordDiag.js +826 -0
- package/dist/utils/diskCleanup.d.ts +36 -0
- package/dist/utils/diskCleanup.js +775 -0
- package/dist/utils/entityResolver.d.ts +107 -0
- package/dist/utils/entityResolver.js +468 -0
- package/dist/utils/imageGen.d.ts +92 -0
- package/dist/utils/imageGen.js +2031 -0
- package/dist/utils/installTracker.d.ts +57 -0
- package/dist/utils/installTracker.js +160 -0
- package/dist/utils/multiExec.d.ts +21 -0
- package/dist/utils/multiExec.js +141 -0
- package/dist/utils/openclawDiag.d.ts +29 -0
- package/dist/utils/openclawDiag.js +1035 -0
- package/dist/utils/output.js +4 -0
- package/dist/utils/platform.js +2 -1
- package/dist/utils/progressReporter.d.ts +50 -0
- package/dist/utils/progressReporter.js +58 -0
- package/dist/utils/projectDetect.d.ts +44 -0
- package/dist/utils/projectDetect.js +319 -0
- package/dist/utils/projectScanner.d.ts +44 -0
- package/dist/utils/projectScanner.js +312 -0
- package/dist/utils/shellCompat.d.ts +78 -0
- package/dist/utils/shellCompat.js +186 -0
- package/dist/utils/smartArchive.d.ts +16 -0
- package/dist/utils/smartArchive.js +172 -0
- package/dist/utils/smartRetry.d.ts +26 -0
- package/dist/utils/smartRetry.js +114 -0
- package/dist/utils/snippets.d.ts +13 -0
- package/dist/utils/snippets.js +53 -0
- package/dist/utils/stabilityMatrixManager.d.ts +80 -0
- package/dist/utils/stabilityMatrixManager.js +268 -0
- package/dist/utils/teachMode.d.ts +41 -0
- package/dist/utils/teachMode.js +100 -0
- package/dist/utils/timer.d.ts +22 -0
- package/dist/utils/timer.js +52 -0
- package/dist/utils/updater.d.ts +1 -0
- package/dist/utils/updater.js +1 -1
- package/dist/utils/version.d.ts +20 -0
- package/dist/utils/version.js +212 -0
- package/package.json +6 -3
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Natural language → SQL query builder.
|
|
3
|
+
*
|
|
4
|
+
* Translates phrases like:
|
|
5
|
+
* "look at items and find sally" → SELECT * FROM items WHERE ... LIKE '%sally%'
|
|
6
|
+
* "show me all users" → SELECT * FROM users
|
|
7
|
+
* "count orders" → SELECT COUNT(*) FROM orders
|
|
8
|
+
* "show tables" → \dt (postgres) or SHOW TABLES (mysql)
|
|
9
|
+
* "describe users table" → \d users or DESCRIBE users
|
|
10
|
+
* "find orders where total > 100" → SELECT * FROM orders WHERE total > 100
|
|
11
|
+
*/
|
|
12
|
+
const c = {
|
|
13
|
+
reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m",
|
|
14
|
+
green: "\x1b[32m", yellow: "\x1b[33m", cyan: "\x1b[36m", red: "\x1b[31m",
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Build a SQL query from natural language.
|
|
18
|
+
*/
|
|
19
|
+
export function buildQuery(rawText, fields, dbType = "postgres") {
|
|
20
|
+
const text = rawText.toLowerCase();
|
|
21
|
+
const table = fields.table ?? extractTable(text);
|
|
22
|
+
const search = fields.search ?? extractSearchTerm(text);
|
|
23
|
+
// "show tables" / "list tables"
|
|
24
|
+
if (text.match(/show\s+tables|list\s+tables|what\s+tables|which\s+tables/)) {
|
|
25
|
+
return dbType === "postgres"
|
|
26
|
+
? { query: "\\dt", command: buildPsqlCmd(fields, "\\dt"), explanation: "List all tables" }
|
|
27
|
+
: { query: "SHOW TABLES;", command: buildMysqlCmd(fields, "SHOW TABLES;"), explanation: "List all tables" };
|
|
28
|
+
}
|
|
29
|
+
// "describe <table>" / "schema of <table>" / "columns in <table>"
|
|
30
|
+
const describeMatch = text.match(/describe\s+(\w+)|schema\s+(?:of\s+)?(\w+)|columns\s+(?:in\s+|of\s+)?(\w+)|structure\s+(?:of\s+)?(\w+)/);
|
|
31
|
+
if (describeMatch) {
|
|
32
|
+
const t = describeMatch[1] || describeMatch[2] || describeMatch[3] || describeMatch[4];
|
|
33
|
+
return dbType === "postgres"
|
|
34
|
+
? { query: `\\d ${t}`, command: buildPsqlCmd(fields, `\\d ${t}`), explanation: `Describe table ${t}` }
|
|
35
|
+
: { query: `DESCRIBE ${t};`, command: buildMysqlCmd(fields, `DESCRIBE ${t};`), explanation: `Describe table ${t}` };
|
|
36
|
+
}
|
|
37
|
+
// "count <table>"
|
|
38
|
+
if (text.match(/count|how\s+many/)) {
|
|
39
|
+
if (table) {
|
|
40
|
+
const where = extractWhere(text, table);
|
|
41
|
+
const query = where
|
|
42
|
+
? `SELECT COUNT(*) FROM ${table} WHERE ${where};`
|
|
43
|
+
: `SELECT COUNT(*) FROM ${table};`;
|
|
44
|
+
return {
|
|
45
|
+
query,
|
|
46
|
+
command: dbType === "postgres" ? buildPsqlCmd(fields, query) : buildMysqlCmd(fields, query),
|
|
47
|
+
explanation: `Count rows in ${table}${where ? ` where ${where}` : ""}`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Search query: "find sally in items" / "look at items find sally"
|
|
52
|
+
if (table && search) {
|
|
53
|
+
const query = `SELECT * FROM ${table} WHERE ${buildSearchWhere(search, table, dbType)} LIMIT 50;`;
|
|
54
|
+
return {
|
|
55
|
+
query,
|
|
56
|
+
command: dbType === "postgres" ? buildPsqlCmd(fields, query) : buildMysqlCmd(fields, query),
|
|
57
|
+
explanation: `Search ${table} for "${search}"`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Search with no table: "find sally" — search across all tables
|
|
61
|
+
if (search && !table) {
|
|
62
|
+
if (dbType === "postgres") {
|
|
63
|
+
// Build a script that searches all tables for the term
|
|
64
|
+
const query = buildSearchAllTablesPg(search);
|
|
65
|
+
return {
|
|
66
|
+
query,
|
|
67
|
+
command: buildPsqlCmd(fields, query),
|
|
68
|
+
explanation: `Search ALL tables for "${search}"`,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const query = buildSearchAllTablesMysql(search, fields.database ?? "");
|
|
73
|
+
return {
|
|
74
|
+
query,
|
|
75
|
+
command: buildMysqlCmd(fields, query),
|
|
76
|
+
explanation: `Search ALL tables for "${search}"`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Simple select: "show me <table>" / "list <table>" / "all <table>"
|
|
81
|
+
if (table) {
|
|
82
|
+
const where = extractWhere(text, table);
|
|
83
|
+
const limit = extractLimit(text);
|
|
84
|
+
const query = where
|
|
85
|
+
? `SELECT * FROM ${table} WHERE ${where} LIMIT ${limit};`
|
|
86
|
+
: `SELECT * FROM ${table} LIMIT ${limit};`;
|
|
87
|
+
return {
|
|
88
|
+
query,
|
|
89
|
+
command: dbType === "postgres" ? buildPsqlCmd(fields, query) : buildMysqlCmd(fields, query),
|
|
90
|
+
explanation: `Show rows from ${table}${where ? ` where ${where}` : ""}`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
// Fallback: raw query if it looks like SQL
|
|
94
|
+
if (text.match(/^(select|insert|update|delete|create|alter|drop)\s/i)) {
|
|
95
|
+
const query = rawText.trim().endsWith(";") ? rawText.trim() : rawText.trim() + ";";
|
|
96
|
+
return {
|
|
97
|
+
query,
|
|
98
|
+
command: dbType === "postgres" ? buildPsqlCmd(fields, query) : buildMysqlCmd(fields, query),
|
|
99
|
+
explanation: "Raw SQL query",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
query: "",
|
|
104
|
+
command: "",
|
|
105
|
+
explanation: "Could not build a query. Try: show tables, describe <table>, or select * from <table>",
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// ─── Extractors ──────────────────────────────────────────────────────────────
|
|
109
|
+
function extractTable(text) {
|
|
110
|
+
// "in <table>" / "from <table>" / "the <table> table" / "my <table>"
|
|
111
|
+
const patterns = [
|
|
112
|
+
/(?:from|in|at|into)\s+(?:the\s+)?(\w+)\s*(?:table)?/,
|
|
113
|
+
/(?:my|the|all)\s+(\w+)\s*(?:table)?/,
|
|
114
|
+
/(?:look\s+at|show|list|query|search|find\s+in)\s+(?:the\s+)?(?:my\s+)?(\w+)/,
|
|
115
|
+
/(\w+)\s+table/,
|
|
116
|
+
];
|
|
117
|
+
for (const p of patterns) {
|
|
118
|
+
const match = text.match(p);
|
|
119
|
+
if (match) {
|
|
120
|
+
const t = match[1].toLowerCase();
|
|
121
|
+
// Filter out common non-table words
|
|
122
|
+
if (!["me", "all", "the", "my", "this", "that", "it", "and", "on", "to", "for", "with", "where", "tables", "database"].includes(t)) {
|
|
123
|
+
return t;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
function extractSearchTerm(text) {
|
|
130
|
+
// "find <term>" / "has <term>" / "contains <term>" / "with <term>" / "named <term>"
|
|
131
|
+
const patterns = [
|
|
132
|
+
/(?:find|has|contains?|with|named|called|matching|like)\s+(?:the\s+)?['"]?(\w[\w\s]*?)['"]?\s*(?:in|$)/,
|
|
133
|
+
/(?:find|search\s+for|look\s+for)\s+['"]?(\w[\w\s]*?)['"]?\s*(?:in|from|$)/,
|
|
134
|
+
/(?:that\s+has|that\s+contains?)\s+['"]?(\w[\w\s]*?)['"]?/,
|
|
135
|
+
/(?:find\s+(?:the\s+)?(?:one\s+)?(?:that\s+)?(?:has\s+)?)?['"]?(\w+)['"]?\s*$/,
|
|
136
|
+
];
|
|
137
|
+
for (const p of patterns) {
|
|
138
|
+
const match = text.match(p);
|
|
139
|
+
if (match) {
|
|
140
|
+
const term = match[1].trim();
|
|
141
|
+
if (term && !["it", "them", "the", "one", "that"].includes(term.toLowerCase())) {
|
|
142
|
+
return term;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
function extractWhere(text, table) {
|
|
149
|
+
// "where <condition>" — pass through
|
|
150
|
+
const whereMatch = text.match(/where\s+(.+?)(?:\s+limit|\s*$)/);
|
|
151
|
+
if (whereMatch)
|
|
152
|
+
return whereMatch[1].trim();
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
function extractLimit(text) {
|
|
156
|
+
const match = text.match(/(?:limit|top|first|last)\s+(\d+)/);
|
|
157
|
+
if (match)
|
|
158
|
+
return parseInt(match[1]);
|
|
159
|
+
// "show me 20 users" / "10 orders"
|
|
160
|
+
const numMatch = text.match(/(?:show|list|get)\s+(?:me\s+)?(\d+)/);
|
|
161
|
+
if (numMatch)
|
|
162
|
+
return parseInt(numMatch[1]);
|
|
163
|
+
return 50;
|
|
164
|
+
}
|
|
165
|
+
function buildSearchWhere(search, table, dbType) {
|
|
166
|
+
const escaped = escapeSql(search);
|
|
167
|
+
if (dbType === "postgres") {
|
|
168
|
+
// Cast entire row to text and search — works across all columns
|
|
169
|
+
return `${table}::text ILIKE '%${escaped}%'`;
|
|
170
|
+
}
|
|
171
|
+
// MySQL: search common text column names
|
|
172
|
+
return `CONCAT_WS(' ', COALESCE(name,''), COALESCE(title,''), COALESCE(email,''), COALESCE(description,''), COALESCE(username,''), COALESCE(first_name,''), COALESCE(last_name,'')) LIKE '%${escaped}%'`;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Postgres: search all tables for a term.
|
|
176
|
+
* Casts each row to text and checks with ILIKE.
|
|
177
|
+
*/
|
|
178
|
+
function buildSearchAllTablesPg(search) {
|
|
179
|
+
const escaped = escapeSql(search);
|
|
180
|
+
// Use a DO block that iterates through all user tables
|
|
181
|
+
return `DO $$
|
|
182
|
+
DECLARE
|
|
183
|
+
r RECORD;
|
|
184
|
+
tbl TEXT;
|
|
185
|
+
cnt INTEGER;
|
|
186
|
+
BEGIN
|
|
187
|
+
FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public' LOOP
|
|
188
|
+
tbl := r.tablename;
|
|
189
|
+
EXECUTE format('SELECT COUNT(*) FROM %I WHERE %I::text ILIKE $1', tbl, tbl) INTO cnt USING '%${escaped}%';
|
|
190
|
+
IF cnt > 0 THEN
|
|
191
|
+
RAISE NOTICE 'Found % match(es) in table: %', cnt, tbl;
|
|
192
|
+
END IF;
|
|
193
|
+
END LOOP;
|
|
194
|
+
END $$;`;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* MySQL: search all tables for a term.
|
|
198
|
+
*/
|
|
199
|
+
function buildSearchAllTablesMysql(search, database) {
|
|
200
|
+
const escaped = escapeSql(search);
|
|
201
|
+
// MySQL approach: generate SELECT statements for each table
|
|
202
|
+
return `SELECT TABLE_NAME, COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '${database || "DATABASE()"}' AND DATA_TYPE IN ('varchar','text','char','longtext','mediumtext') ORDER BY TABLE_NAME;`;
|
|
203
|
+
}
|
|
204
|
+
function escapeSql(val) {
|
|
205
|
+
return val.replace(/'/g, "''").replace(/\\/g, "\\\\");
|
|
206
|
+
}
|
|
207
|
+
// ─── Command builders ────────────────────────────────────────────────────────
|
|
208
|
+
function buildPsqlCmd(fields, query) {
|
|
209
|
+
const db = fields.database ?? "";
|
|
210
|
+
const host = fields.host ?? "";
|
|
211
|
+
const user = fields.user ?? "";
|
|
212
|
+
const parts = ["psql"];
|
|
213
|
+
if (host)
|
|
214
|
+
parts.push(`-h ${host}`);
|
|
215
|
+
if (user)
|
|
216
|
+
parts.push(`-U ${user}`);
|
|
217
|
+
if (db)
|
|
218
|
+
parts.push(db);
|
|
219
|
+
parts.push(`-c ${JSON.stringify(query)}`);
|
|
220
|
+
return parts.join(" ");
|
|
221
|
+
}
|
|
222
|
+
function buildMysqlCmd(fields, query) {
|
|
223
|
+
const db = fields.database ?? "";
|
|
224
|
+
const host = fields.host ?? "";
|
|
225
|
+
const user = fields.user ?? "";
|
|
226
|
+
const parts = ["mysql"];
|
|
227
|
+
if (host)
|
|
228
|
+
parts.push(`-h ${host}`);
|
|
229
|
+
if (user)
|
|
230
|
+
parts.push(`-u ${user}`);
|
|
231
|
+
if (db)
|
|
232
|
+
parts.push(db);
|
|
233
|
+
parts.push(`-e ${JSON.stringify(query)}`);
|
|
234
|
+
return parts.join(" ");
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Format query result for display — show the SQL, explain it, then run.
|
|
238
|
+
*/
|
|
239
|
+
export function formatQueryPlan(result) {
|
|
240
|
+
if (!result.query)
|
|
241
|
+
return result.explanation;
|
|
242
|
+
const lines = [];
|
|
243
|
+
lines.push(`\n${c.bold}${c.cyan}── Query Plan ──${c.reset}\n`);
|
|
244
|
+
lines.push(` ${c.bold}SQL:${c.reset} ${c.green}${result.query}${c.reset}`);
|
|
245
|
+
lines.push(` ${c.dim}${result.explanation}${c.reset}`);
|
|
246
|
+
lines.push(` ${c.dim}Command: ${result.command}${c.reset}`);
|
|
247
|
+
return lines.join("\n");
|
|
248
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare function formatJson(input: string): {
|
|
2
|
+
formatted: string;
|
|
3
|
+
valid: boolean;
|
|
4
|
+
error?: string;
|
|
5
|
+
};
|
|
6
|
+
export declare function validateJson(input: string): {
|
|
7
|
+
valid: boolean;
|
|
8
|
+
error?: string;
|
|
9
|
+
parsed?: unknown;
|
|
10
|
+
};
|
|
11
|
+
export declare function testRegex(pattern: string, testString: string, flags?: string): {
|
|
12
|
+
matches: RegExpMatchArray[];
|
|
13
|
+
count: number;
|
|
14
|
+
groups: Record<string, string>[];
|
|
15
|
+
};
|
|
16
|
+
export declare function encodeBase64(input: string): string;
|
|
17
|
+
export declare function decodeBase64(input: string): string;
|
|
18
|
+
export declare function encodeUrl(input: string): string;
|
|
19
|
+
export declare function decodeUrl(input: string): string;
|
|
20
|
+
type HashAlgo = "md5" | "sha1" | "sha256";
|
|
21
|
+
export declare function hashString(input: string, algo?: HashAlgo): string;
|
|
22
|
+
export declare function hashFile(filepath: string, algo?: HashAlgo): Promise<string>;
|
|
23
|
+
export declare function generateUuid(): string;
|
|
24
|
+
export declare function convertUnixTimestamp(ts: number | string): {
|
|
25
|
+
unix: number;
|
|
26
|
+
iso: string;
|
|
27
|
+
utc: string;
|
|
28
|
+
local: string;
|
|
29
|
+
};
|
|
30
|
+
export declare function diffStrings(a: string, b: string): {
|
|
31
|
+
added: string[];
|
|
32
|
+
removed: string[];
|
|
33
|
+
diff: string;
|
|
34
|
+
};
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Developer utility tools — JSON, regex, encoding, hashing, UUID, timestamps, diff.
|
|
3
|
+
*/
|
|
4
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
// ── JSON ──
|
|
7
|
+
export function formatJson(input) {
|
|
8
|
+
try {
|
|
9
|
+
const parsed = JSON.parse(input);
|
|
10
|
+
return { formatted: JSON.stringify(parsed, null, 2), valid: true };
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
return { formatted: input, valid: false, error: e.message };
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function validateJson(input) {
|
|
17
|
+
try {
|
|
18
|
+
const parsed = JSON.parse(input);
|
|
19
|
+
return { valid: true, parsed };
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
return { valid: false, error: e.message };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// ── Regex ──
|
|
26
|
+
export function testRegex(pattern, testString, flags = "g") {
|
|
27
|
+
const re = new RegExp(pattern, flags);
|
|
28
|
+
const matches = [];
|
|
29
|
+
const groups = [];
|
|
30
|
+
let m;
|
|
31
|
+
while ((m = re.exec(testString)) !== null) {
|
|
32
|
+
matches.push([...m]);
|
|
33
|
+
if (m.groups)
|
|
34
|
+
groups.push({ ...m.groups });
|
|
35
|
+
if (!re.global)
|
|
36
|
+
break;
|
|
37
|
+
}
|
|
38
|
+
return { matches, count: matches.length, groups };
|
|
39
|
+
}
|
|
40
|
+
// ── Base64 ──
|
|
41
|
+
export function encodeBase64(input) {
|
|
42
|
+
return Buffer.from(input, "utf-8").toString("base64");
|
|
43
|
+
}
|
|
44
|
+
export function decodeBase64(input) {
|
|
45
|
+
return Buffer.from(input, "base64").toString("utf-8");
|
|
46
|
+
}
|
|
47
|
+
// ── URL Encoding ──
|
|
48
|
+
export function encodeUrl(input) {
|
|
49
|
+
return encodeURIComponent(input);
|
|
50
|
+
}
|
|
51
|
+
export function decodeUrl(input) {
|
|
52
|
+
return decodeURIComponent(input);
|
|
53
|
+
}
|
|
54
|
+
export function hashString(input, algo = "sha256") {
|
|
55
|
+
return createHash(algo).update(input, "utf-8").digest("hex");
|
|
56
|
+
}
|
|
57
|
+
export async function hashFile(filepath, algo = "sha256") {
|
|
58
|
+
const buf = await readFile(filepath);
|
|
59
|
+
return createHash(algo).update(buf).digest("hex");
|
|
60
|
+
}
|
|
61
|
+
// ── UUID ──
|
|
62
|
+
export function generateUuid() {
|
|
63
|
+
return randomUUID();
|
|
64
|
+
}
|
|
65
|
+
// ── Timestamps ──
|
|
66
|
+
export function convertUnixTimestamp(ts) {
|
|
67
|
+
const num = typeof ts === "string" ? Number(ts) : ts;
|
|
68
|
+
// Auto-detect seconds vs milliseconds
|
|
69
|
+
const ms = num > 1e12 ? num : num * 1000;
|
|
70
|
+
const d = new Date(ms);
|
|
71
|
+
return {
|
|
72
|
+
unix: Math.floor(ms / 1000),
|
|
73
|
+
iso: d.toISOString(),
|
|
74
|
+
utc: d.toUTCString(),
|
|
75
|
+
local: d.toString(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// ── Simple Word-Level Diff ──
|
|
79
|
+
export function diffStrings(a, b) {
|
|
80
|
+
const wordsA = a.split(/\s+/).filter(Boolean);
|
|
81
|
+
const wordsB = b.split(/\s+/).filter(Boolean);
|
|
82
|
+
const setA = new Set(wordsA);
|
|
83
|
+
const setB = new Set(wordsB);
|
|
84
|
+
const removed = wordsA.filter((w) => !setB.has(w));
|
|
85
|
+
const added = wordsB.filter((w) => !setA.has(w));
|
|
86
|
+
// Build a simple inline diff display
|
|
87
|
+
const lines = [];
|
|
88
|
+
if (removed.length)
|
|
89
|
+
lines.push(`- ${removed.join(" ")}`);
|
|
90
|
+
if (added.length)
|
|
91
|
+
lines.push(`+ ${added.join(" ")}`);
|
|
92
|
+
if (!removed.length && !added.length)
|
|
93
|
+
lines.push("(no differences)");
|
|
94
|
+
return { added, removed, diff: lines.join("\n") };
|
|
95
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discord bot diagnostics, setup, and auto-fix.
|
|
3
|
+
*
|
|
4
|
+
* `diagnoseDiscord()` — runs full checklist and auto-fixes everything:
|
|
5
|
+
* 1. Token valid?
|
|
6
|
+
* 2. Bot in guilds? → auto-invite via patchright
|
|
7
|
+
* 3. Intents enabled in OpenClaw config? → auto-fix
|
|
8
|
+
* 4. DM/group policy correct? → auto-fix
|
|
9
|
+
* 5. OpenClaw version check
|
|
10
|
+
* 6. Restart gateway if config changed
|
|
11
|
+
* 7. Poll gateway connection up to 60s
|
|
12
|
+
* 8. If 4014 error → enable intents via patchright → restart → re-poll
|
|
13
|
+
* 9. Check channels
|
|
14
|
+
* 10. Auto-approve pairing codes
|
|
15
|
+
* 11. Send test message + verify response
|
|
16
|
+
*
|
|
17
|
+
* The full chain runs end-to-end without stopping.
|
|
18
|
+
* User only needs to handle captcha/MFA when patchright prompts.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Live Discord connection monitor.
|
|
22
|
+
* Prints real-time status updates as the gateway connects to Discord.
|
|
23
|
+
* Auto-restarts if stuck, auto-waits through rate limits.
|
|
24
|
+
*
|
|
25
|
+
* Usage: "monitor discord" or "watch discord"
|
|
26
|
+
*/
|
|
27
|
+
export declare function monitorDiscord(maxMinutes?: number): Promise<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Full Discord diagnostic and auto-fix chain.
|
|
30
|
+
*/
|
|
31
|
+
export declare function diagnoseDiscord(): Promise<string>;
|
|
32
|
+
/**
|
|
33
|
+
* Quick Discord status check.
|
|
34
|
+
*/
|
|
35
|
+
export declare function quickDiscordCheck(): Promise<string>;
|