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.
Files changed (123) hide show
  1. package/config/ascii-art.json +12 -0
  2. package/config/chat-responses.json +1019 -0
  3. package/config/cheat-sheets.json +94 -0
  4. package/config/concept-clusters.json +31 -0
  5. package/config/daily-tips.json +105 -0
  6. package/config/entities.json +93 -0
  7. package/config/history-today.json +9762 -0
  8. package/config/image-prompts.json +20 -0
  9. package/config/intent-vectors.json +1 -0
  10. package/config/intents.json +5354 -85
  11. package/config/ollama-models.json +193 -0
  12. package/config/rules.json +32 -1
  13. package/config/startup-quotes.json +45 -0
  14. package/dist/automation/discordPatchright.d.ts +35 -0
  15. package/dist/automation/discordPatchright.js +424 -0
  16. package/dist/automation/discordSetup.d.ts +31 -0
  17. package/dist/automation/discordSetup.js +338 -0
  18. package/dist/automation/smAutomation.d.ts +82 -0
  19. package/dist/automation/smAutomation.js +448 -0
  20. package/dist/conversation/coreference.js +44 -4
  21. package/dist/conversation/pendingActions.d.ts +55 -0
  22. package/dist/conversation/pendingActions.js +127 -0
  23. package/dist/conversation/store.d.ts +72 -0
  24. package/dist/conversation/store.js +140 -1
  25. package/dist/conversation/topicTracker.d.ts +36 -0
  26. package/dist/conversation/topicTracker.js +141 -0
  27. package/dist/execution/ssh.d.ts +42 -1
  28. package/dist/execution/ssh.js +538 -3
  29. package/dist/handlers/executor.d.ts +2 -0
  30. package/dist/handlers/executor.js +4234 -31
  31. package/dist/index.d.ts +35 -4
  32. package/dist/index.js +51 -3
  33. package/dist/nlp/batchParser.d.ts +30 -0
  34. package/dist/nlp/batchParser.js +77 -0
  35. package/dist/nlp/conceptExpansion.d.ts +54 -0
  36. package/dist/nlp/conceptExpansion.js +136 -0
  37. package/dist/nlp/conceptRouter.d.ts +49 -0
  38. package/dist/nlp/conceptRouter.js +302 -0
  39. package/dist/nlp/confidenceCalibrator.d.ts +62 -0
  40. package/dist/nlp/confidenceCalibrator.js +116 -0
  41. package/dist/nlp/correctionLearner.d.ts +45 -0
  42. package/dist/nlp/correctionLearner.js +207 -0
  43. package/dist/nlp/entitySpellCorrect.d.ts +35 -0
  44. package/dist/nlp/entitySpellCorrect.js +141 -0
  45. package/dist/nlp/knowledgeGraph.d.ts +70 -0
  46. package/dist/nlp/knowledgeGraph.js +380 -0
  47. package/dist/nlp/llmFallback.js +28 -1
  48. package/dist/nlp/multiClassifier.js +91 -6
  49. package/dist/nlp/multiIntent.d.ts +43 -0
  50. package/dist/nlp/multiIntent.js +154 -0
  51. package/dist/nlp/parseIntent.d.ts +6 -1
  52. package/dist/nlp/parseIntent.js +180 -5
  53. package/dist/nlp/ruleParser.js +317 -0
  54. package/dist/nlp/semanticSimilarity.d.ts +30 -0
  55. package/dist/nlp/semanticSimilarity.js +174 -0
  56. package/dist/nlp/vocabularyBuilder.d.ts +43 -0
  57. package/dist/nlp/vocabularyBuilder.js +224 -0
  58. package/dist/nlp/wikidata.d.ts +49 -0
  59. package/dist/nlp/wikidata.js +228 -0
  60. package/dist/policy/confirm.d.ts +10 -0
  61. package/dist/policy/confirm.js +39 -0
  62. package/dist/policy/safety.js +6 -4
  63. package/dist/types/intent.d.ts +8 -0
  64. package/dist/types/intent.js +1 -0
  65. package/dist/utils/achievements.d.ts +38 -0
  66. package/dist/utils/achievements.js +126 -0
  67. package/dist/utils/aliases.d.ts +5 -0
  68. package/dist/utils/aliases.js +39 -0
  69. package/dist/utils/analysis.js +71 -15
  70. package/dist/utils/bookmarks.d.ts +13 -0
  71. package/dist/utils/bookmarks.js +51 -0
  72. package/dist/utils/browser.d.ts +64 -0
  73. package/dist/utils/browser.js +364 -0
  74. package/dist/utils/commandHistory.d.ts +20 -0
  75. package/dist/utils/commandHistory.js +108 -0
  76. package/dist/utils/completer.d.ts +17 -0
  77. package/dist/utils/completer.js +79 -0
  78. package/dist/utils/config.js +32 -2
  79. package/dist/utils/dbQuery.d.ts +25 -0
  80. package/dist/utils/dbQuery.js +248 -0
  81. package/dist/utils/devTools.d.ts +35 -0
  82. package/dist/utils/devTools.js +95 -0
  83. package/dist/utils/discordDiag.d.ts +35 -0
  84. package/dist/utils/discordDiag.js +826 -0
  85. package/dist/utils/diskCleanup.d.ts +36 -0
  86. package/dist/utils/diskCleanup.js +775 -0
  87. package/dist/utils/entityResolver.d.ts +107 -0
  88. package/dist/utils/entityResolver.js +468 -0
  89. package/dist/utils/imageGen.d.ts +92 -0
  90. package/dist/utils/imageGen.js +2031 -0
  91. package/dist/utils/installTracker.d.ts +57 -0
  92. package/dist/utils/installTracker.js +160 -0
  93. package/dist/utils/multiExec.d.ts +21 -0
  94. package/dist/utils/multiExec.js +141 -0
  95. package/dist/utils/openclawDiag.d.ts +29 -0
  96. package/dist/utils/openclawDiag.js +1035 -0
  97. package/dist/utils/output.js +4 -0
  98. package/dist/utils/platform.js +2 -1
  99. package/dist/utils/progressReporter.d.ts +50 -0
  100. package/dist/utils/progressReporter.js +58 -0
  101. package/dist/utils/projectDetect.d.ts +44 -0
  102. package/dist/utils/projectDetect.js +319 -0
  103. package/dist/utils/projectScanner.d.ts +44 -0
  104. package/dist/utils/projectScanner.js +312 -0
  105. package/dist/utils/shellCompat.d.ts +78 -0
  106. package/dist/utils/shellCompat.js +186 -0
  107. package/dist/utils/smartArchive.d.ts +16 -0
  108. package/dist/utils/smartArchive.js +172 -0
  109. package/dist/utils/smartRetry.d.ts +26 -0
  110. package/dist/utils/smartRetry.js +114 -0
  111. package/dist/utils/snippets.d.ts +13 -0
  112. package/dist/utils/snippets.js +53 -0
  113. package/dist/utils/stabilityMatrixManager.d.ts +80 -0
  114. package/dist/utils/stabilityMatrixManager.js +268 -0
  115. package/dist/utils/teachMode.d.ts +41 -0
  116. package/dist/utils/teachMode.js +100 -0
  117. package/dist/utils/timer.d.ts +22 -0
  118. package/dist/utils/timer.js +52 -0
  119. package/dist/utils/updater.d.ts +1 -0
  120. package/dist/utils/updater.js +1 -1
  121. package/dist/utils/version.d.ts +20 -0
  122. package/dist/utils/version.js +212 -0
  123. package/package.json +6 -3
@@ -0,0 +1,338 @@
1
+ /**
2
+ * Automated Discord bot setup via Playwright.
3
+ *
4
+ * Opens the Discord Developer Portal, walks the user through login,
5
+ * then automates: create application, create bot, copy token, enable
6
+ * Message Content Intent, generate OAuth2 invite URL, open it.
7
+ *
8
+ * The user only needs to:
9
+ * 1. Log in to Discord (notoken never touches credentials)
10
+ * 2. Pick which server to add the bot to
11
+ *
12
+ * Returns the bot token for OpenClaw channel registration.
13
+ */
14
+ const c = {
15
+ reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m",
16
+ green: "\x1b[32m", yellow: "\x1b[33m", red: "\x1b[31m", cyan: "\x1b[36m",
17
+ };
18
+ /**
19
+ * Detect available browser executable on the system.
20
+ * Prefers Edge (available on Windows), falls back to Chrome, then Chromium.
21
+ */
22
+ async function findBrowserPath() {
23
+ const { execSync } = await import("node:child_process");
24
+ const candidates = [
25
+ // Windows browsers via WSL
26
+ "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe",
27
+ "/mnt/c/Program Files/Google/Chrome/Application/chrome.exe",
28
+ "/mnt/c/Program Files/BraveSoftware/Brave-Browser/Application/brave.exe",
29
+ // Linux browsers
30
+ "/usr/bin/google-chrome",
31
+ "/usr/bin/chromium-browser",
32
+ "/usr/bin/chromium",
33
+ "/usr/bin/microsoft-edge",
34
+ ];
35
+ for (const path of candidates) {
36
+ try {
37
+ execSync(`ls "${path}" 2>/dev/null`, { stdio: "pipe" });
38
+ return path;
39
+ }
40
+ catch { /* not found */ }
41
+ }
42
+ return null;
43
+ }
44
+ /**
45
+ * Run the automated Discord bot setup.
46
+ *
47
+ * @param appName - Name for the Discord application (default: "OpenClaw")
48
+ * @param headless - Run headless (default: false — user needs to see login)
49
+ */
50
+ export async function automateDiscordBotSetup(appName = "OpenClaw", headless = false) {
51
+ // Dynamic import — Playwright is optional, not a core dependency
52
+ let playwright;
53
+ try {
54
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
55
+ playwright = await Function('return import("playwright")')();
56
+ }
57
+ catch {
58
+ return {
59
+ success: false,
60
+ error: "Playwright not installed. Run: npm install -g playwright && npx playwright install chromium",
61
+ };
62
+ }
63
+ const browserPath = await findBrowserPath();
64
+ console.log(`\n${c.bold}${c.cyan}── Discord Bot Setup ──${c.reset}\n`);
65
+ let browser;
66
+ let context;
67
+ let page;
68
+ try {
69
+ // Launch browser — use Windows Edge if available for visible UI
70
+ console.log(` ${c.dim}Launching browser...${c.reset}`);
71
+ if (browserPath?.includes("/mnt/c/")) {
72
+ // Windows browser via WSL — use channel launch
73
+ const winPath = browserPath
74
+ .replace("/mnt/c/", "C:\\")
75
+ .replace(/\//g, "\\");
76
+ browser = await playwright.chromium.launch({
77
+ headless: false, // Must be visible for user login
78
+ executablePath: browserPath,
79
+ args: ["--no-sandbox"],
80
+ });
81
+ }
82
+ else {
83
+ browser = await playwright.chromium.launch({
84
+ headless,
85
+ args: ["--no-sandbox"],
86
+ });
87
+ }
88
+ context = await browser.newContext({
89
+ viewport: { width: 1280, height: 900 },
90
+ });
91
+ page = await context.newPage();
92
+ // ── Step 1: Navigate to Discord Developer Portal ──
93
+ console.log(` ${c.bold}1.${c.reset} Opening Discord Developer Portal...`);
94
+ await page.goto("https://discord.com/developers/applications", {
95
+ waitUntil: "networkidle",
96
+ timeout: 30_000,
97
+ });
98
+ // Check if login is needed
99
+ const url = page.url();
100
+ if (url.includes("/login")) {
101
+ console.log(`\n ${c.yellow}${c.bold}Please log in to Discord in the browser window.${c.reset}`);
102
+ console.log(` ${c.dim}Waiting for you to complete login...${c.reset}\n`);
103
+ // Wait for redirect to developer portal after login (up to 5 minutes)
104
+ await page.waitForURL("**/developers/applications**", { timeout: 300_000 });
105
+ console.log(` ${c.green}✓${c.reset} Logged in successfully!\n`);
106
+ }
107
+ else {
108
+ console.log(` ${c.green}✓${c.reset} Already logged in.\n`);
109
+ }
110
+ // ── Step 2: Create New Application ──
111
+ console.log(` ${c.bold}2.${c.reset} Creating application "${appName}"...`);
112
+ await page.waitForTimeout(2000);
113
+ // Click "New Application" button
114
+ const newAppBtn = page.locator('button:has-text("New Application"), div[class*="actionButton"]:has-text("New Application")');
115
+ await newAppBtn.waitFor({ timeout: 10_000 });
116
+ await newAppBtn.click();
117
+ // Fill in the application name
118
+ await page.waitForTimeout(1000);
119
+ const nameInput = page.locator('input[placeholder*="name"], input[name="name"]').first();
120
+ await nameInput.waitFor({ timeout: 5_000 });
121
+ await nameInput.fill(appName);
122
+ // Check the ToS checkbox if present
123
+ const tosCheckbox = page.locator('input[type="checkbox"], label:has-text("policy")').first();
124
+ if (await tosCheckbox.isVisible({ timeout: 2000 }).catch(() => false)) {
125
+ await tosCheckbox.click();
126
+ }
127
+ // Click Create
128
+ const createBtn = page.locator('button:has-text("Create")').first();
129
+ await createBtn.click();
130
+ await page.waitForTimeout(3000);
131
+ // Get the application ID from the URL
132
+ const appUrl = page.url();
133
+ const appIdMatch = appUrl.match(/applications\/(\d+)/);
134
+ const applicationId = appIdMatch?.[1] ?? "";
135
+ console.log(` ${c.green}✓${c.reset} Application created${applicationId ? ` (ID: ${applicationId})` : ""}\n`);
136
+ // ── Step 3: Navigate to Bot tab and create bot ──
137
+ console.log(` ${c.bold}3.${c.reset} Setting up bot...`);
138
+ // Click "Bot" in sidebar
139
+ const botTab = page.locator('a:has-text("Bot"), div[class*="item"]:has-text("Bot")').first();
140
+ await botTab.click();
141
+ await page.waitForTimeout(2000);
142
+ // Click "Reset Token" or "Add Bot" if needed
143
+ const resetTokenBtn = page.locator('button:has-text("Reset Token")').first();
144
+ const addBotBtn = page.locator('button:has-text("Add Bot")').first();
145
+ if (await addBotBtn.isVisible({ timeout: 2000 }).catch(() => false)) {
146
+ await addBotBtn.click();
147
+ await page.waitForTimeout(1000);
148
+ // Confirm
149
+ const confirmBtn = page.locator('button:has-text("Yes, do it!")').first();
150
+ if (await confirmBtn.isVisible({ timeout: 2000 }).catch(() => false)) {
151
+ await confirmBtn.click();
152
+ }
153
+ await page.waitForTimeout(2000);
154
+ }
155
+ // Reset/reveal token
156
+ if (await resetTokenBtn.isVisible({ timeout: 3000 }).catch(() => false)) {
157
+ await resetTokenBtn.click();
158
+ await page.waitForTimeout(1000);
159
+ // Confirm reset
160
+ const confirmReset = page.locator('button:has-text("Yes, do it!")').first();
161
+ if (await confirmReset.isVisible({ timeout: 2000 }).catch(() => false)) {
162
+ await confirmReset.click();
163
+ }
164
+ }
165
+ // Wait for token to appear and copy it
166
+ await page.waitForTimeout(2000);
167
+ let botToken = "";
168
+ // Try to find the token in an input or code element
169
+ const tokenInput = page.locator('input[value*="."], span[class*="token"], div[class*="token"] input').first();
170
+ if (await tokenInput.isVisible({ timeout: 3000 }).catch(() => false)) {
171
+ botToken = await tokenInput.inputValue().catch(() => "");
172
+ if (!botToken) {
173
+ botToken = await tokenInput.textContent().catch(() => "") ?? "";
174
+ }
175
+ }
176
+ // Try clicking "Copy" button if token not grabbed directly
177
+ if (!botToken) {
178
+ const copyBtn = page.locator('button:has-text("Copy")').first();
179
+ if (await copyBtn.isVisible({ timeout: 2000 }).catch(() => false)) {
180
+ await copyBtn.click();
181
+ // Token is now in clipboard — try to read it
182
+ try {
183
+ botToken = await page.evaluate(() => navigator.clipboard.readText());
184
+ }
185
+ catch {
186
+ // Clipboard access denied — ask user
187
+ }
188
+ }
189
+ }
190
+ if (botToken) {
191
+ console.log(` ${c.green}✓${c.reset} Bot token captured\n`);
192
+ }
193
+ else {
194
+ console.log(` ${c.yellow}⚠${c.reset} Could not auto-capture token.`);
195
+ console.log(` ${c.bold}Please copy the bot token from the browser and paste it here.${c.reset}\n`);
196
+ }
197
+ // ── Step 4: Enable Message Content Intent ──
198
+ console.log(` ${c.bold}4.${c.reset} Enabling Message Content Intent...`);
199
+ // Scroll down to Privileged Gateway Intents
200
+ await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight));
201
+ await page.waitForTimeout(1000);
202
+ // Find and enable Message Content Intent toggle
203
+ const messageContentLabel = page.locator('text=Message Content Intent, label:has-text("MESSAGE CONTENT INTENT")').first();
204
+ if (await messageContentLabel.isVisible({ timeout: 3000 }).catch(() => false)) {
205
+ // Find the toggle near this label
206
+ const toggle = page.locator('div:has-text("MESSAGE CONTENT INTENT") input[type="checkbox"], div:has-text("Message Content Intent") [role="switch"]').first();
207
+ if (await toggle.isVisible({ timeout: 2000 }).catch(() => false)) {
208
+ const isChecked = await toggle.isChecked().catch(() => false);
209
+ if (!isChecked) {
210
+ await toggle.click();
211
+ await page.waitForTimeout(500);
212
+ }
213
+ }
214
+ }
215
+ // Save changes
216
+ const saveBtn = page.locator('button:has-text("Save Changes")').first();
217
+ if (await saveBtn.isVisible({ timeout: 2000 }).catch(() => false)) {
218
+ await saveBtn.click();
219
+ await page.waitForTimeout(1000);
220
+ }
221
+ console.log(` ${c.green}✓${c.reset} Message Content Intent enabled\n`);
222
+ // ── Step 5: Generate OAuth2 invite URL ──
223
+ console.log(` ${c.bold}5.${c.reset} Generating invite URL...`);
224
+ // Navigate to OAuth2 → URL Generator
225
+ const oauth2Tab = page.locator('a:has-text("OAuth2"), div[class*="item"]:has-text("OAuth2")').first();
226
+ await oauth2Tab.click();
227
+ await page.waitForTimeout(1000);
228
+ // Look for URL Generator sub-tab
229
+ const urlGenTab = page.locator('a:has-text("URL Generator"), div:has-text("URL Generator")').first();
230
+ if (await urlGenTab.isVisible({ timeout: 3000 }).catch(() => false)) {
231
+ await urlGenTab.click();
232
+ await page.waitForTimeout(1000);
233
+ }
234
+ // Select "bot" scope
235
+ const botScope = page.locator('label:has-text("bot"), input[value="bot"]').first();
236
+ if (await botScope.isVisible({ timeout: 3000 }).catch(() => false)) {
237
+ await botScope.click();
238
+ await page.waitForTimeout(1000);
239
+ }
240
+ // Select permissions: Send Messages, Read Messages
241
+ for (const perm of ["Send Messages", "Read Message History", "View Channels"]) {
242
+ const permLabel = page.locator(`label:has-text("${perm}")`).first();
243
+ if (await permLabel.isVisible({ timeout: 1000 }).catch(() => false)) {
244
+ await permLabel.click();
245
+ await page.waitForTimeout(300);
246
+ }
247
+ }
248
+ // Copy the generated URL
249
+ await page.waitForTimeout(1000);
250
+ let inviteUrl = "";
251
+ const urlInput = page.locator('input[value*="discord.com/oauth2"], input[value*="discord.com/api/oauth2"]').first();
252
+ if (await urlInput.isVisible({ timeout: 3000 }).catch(() => false)) {
253
+ inviteUrl = await urlInput.inputValue();
254
+ }
255
+ if (inviteUrl) {
256
+ console.log(` ${c.green}✓${c.reset} Invite URL generated\n`);
257
+ // ── Step 6: Open invite URL to add bot to server ──
258
+ console.log(` ${c.bold}6.${c.reset} Opening bot invite page...`);
259
+ console.log(` ${c.yellow}${c.bold}Pick your Discord server in the browser to add the bot.${c.reset}\n`);
260
+ await page.goto(inviteUrl);
261
+ // Wait for user to authorize (page changes after clicking Authorize)
262
+ await page.waitForURL("**/oauth2/authorized**", { timeout: 120_000 }).catch(() => { });
263
+ console.log(` ${c.green}✓${c.reset} Bot added to server!\n`);
264
+ }
265
+ else {
266
+ console.log(` ${c.yellow}⚠${c.reset} Could not auto-generate invite URL.`);
267
+ if (applicationId) {
268
+ inviteUrl = `https://discord.com/api/oauth2/authorize?client_id=${applicationId}&permissions=68608&scope=bot`;
269
+ console.log(` ${c.dim}Manual invite URL: ${inviteUrl}${c.reset}\n`);
270
+ }
271
+ }
272
+ // Close browser
273
+ await browser.close();
274
+ return {
275
+ success: !!botToken,
276
+ botToken: botToken || undefined,
277
+ applicationId: applicationId || undefined,
278
+ inviteUrl: inviteUrl || undefined,
279
+ error: botToken ? undefined : "Could not auto-capture bot token. Please copy it manually from the Discord Developer Portal.",
280
+ };
281
+ }
282
+ catch (err) {
283
+ const msg = err.message ?? String(err);
284
+ console.log(`\n ${c.red}✗ Automation error: ${msg.split("\n")[0]}${c.reset}`);
285
+ // Try to close browser gracefully
286
+ try {
287
+ await browser?.close();
288
+ }
289
+ catch { /* */ }
290
+ return { success: false, error: msg };
291
+ }
292
+ }
293
+ /**
294
+ * Full Discord setup flow — automate browser + register with OpenClaw.
295
+ */
296
+ export async function setupDiscordChannel(appName = "OpenClaw") {
297
+ const result = await automateDiscordBotSetup(appName);
298
+ if (result.success && result.botToken) {
299
+ // Register with OpenClaw
300
+ console.log(`${c.bold}${c.cyan}── Registering with OpenClaw ──${c.reset}\n`);
301
+ try {
302
+ const { execSync } = await import("node:child_process");
303
+ const nvmPrefix = `for d in "$HOME/.nvm" "/home/"*"/.nvm" "/root/.nvm"; do [ -s "$d/nvm.sh" ] && export NVM_DIR="$d" && . "$d/nvm.sh" && break; done 2>/dev/null; nvm use 22 > /dev/null 2>&1;`;
304
+ // Try direct Node 22 path first
305
+ const node22Paths = ["/home/ino/.nvm/versions/node/v22.22.2/bin/node"];
306
+ let node22 = "node";
307
+ for (const p of node22Paths) {
308
+ try {
309
+ execSync(`ls "${p}"`, { stdio: "pipe" });
310
+ node22 = p;
311
+ break;
312
+ }
313
+ catch { /* */ }
314
+ }
315
+ const ocBin = execSync("readlink -f $(which openclaw) 2>/dev/null || which openclaw", { encoding: "utf-8" }).trim();
316
+ execSync(`${node22} ${ocBin} channels add --channel discord --token "${result.botToken}"`, { stdio: "inherit", timeout: 15_000 });
317
+ console.log(`\n ${c.green}✓${c.reset} Discord channel registered with OpenClaw!`);
318
+ // Restart gateway to pick up new channel
319
+ console.log(` ${c.dim}Restarting gateway...${c.reset}`);
320
+ execSync("pkill -f openclaw-gateway 2>/dev/null", { stdio: "pipe" }).toString();
321
+ return [
322
+ `\n${c.green}${c.bold}✓ Discord bot setup complete!${c.reset}\n`,
323
+ ` ${c.bold}Bot:${c.reset} ${appName}`,
324
+ result.applicationId ? ` ${c.bold}App ID:${c.reset} ${result.applicationId}` : "",
325
+ ` ${c.bold}Channel:${c.reset} Discord — registered with OpenClaw`,
326
+ `\n ${c.dim}Restart OpenClaw: "restart openclaw"${c.reset}`,
327
+ ` ${c.dim}Then chat with OpenClaw in your Discord server!${c.reset}`,
328
+ ].filter(Boolean).join("\n");
329
+ }
330
+ catch (err) {
331
+ return `${c.yellow}⚠${c.reset} Bot created but OpenClaw registration failed.\n Token: ${result.botToken}\n ${c.dim}Register manually: openclaw channels add --channel discord --token ${result.botToken}${c.reset}`;
332
+ }
333
+ }
334
+ if (result.error) {
335
+ return `${c.yellow}⚠${c.reset} ${result.error}\n\n ${c.dim}If you have the token, say: "setup discord with token YOUR_TOKEN"${c.reset}`;
336
+ }
337
+ return `${c.red}✗ Discord setup failed.${c.reset}`;
338
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Stability Matrix UI Automation via PowerShell.
3
+ *
4
+ * Uses Windows UIAutomation COM API through PowerShell to:
5
+ * - Launch SM and wait for window
6
+ * - Click "Add Package" button
7
+ * - Select the right package (Forge, ComfyUI, etc.)
8
+ * - Click Install and monitor progress
9
+ * - Click Launch when done
10
+ * - Configure settings
11
+ *
12
+ * All automation runs on Windows side via PowerShell.
13
+ * From WSL, commands are sent through /mnt/c/.../powershell.exe
14
+ */
15
+ import { type SMLocation } from "../utils/stabilityMatrixManager.js";
16
+ export declare function isSMRunning(): boolean;
17
+ export declare function launchSM(sm: SMLocation): boolean;
18
+ export declare function focusSMWindow(): boolean;
19
+ /**
20
+ * Find a UI element by name/automationId and click it.
21
+ */
22
+ export declare function clickButton(name: string, timeout?: number): boolean;
23
+ /**
24
+ * Find a UI element by partial text match and click it.
25
+ */
26
+ export declare function clickByText(text: string): boolean;
27
+ /**
28
+ * List all clickable elements in SM window (for debugging).
29
+ */
30
+ export declare function listUIElements(): string[];
31
+ /**
32
+ * Full automated install flow:
33
+ * 1. Launch SM
34
+ * 2. Click "Add Package"
35
+ * 3. Select package (Forge, ComfyUI, etc.)
36
+ * 4. Click Install
37
+ * 5. Wait for completion
38
+ * 6. Click Launch
39
+ */
40
+ export declare function automateInstallPackage(packageName?: string): Promise<{
41
+ success: boolean;
42
+ message: string;
43
+ }>;
44
+ /**
45
+ * Launch the active package.
46
+ */
47
+ export declare function automateLaunch(): Promise<{
48
+ success: boolean;
49
+ message: string;
50
+ }>;
51
+ /**
52
+ * Check SD API from the Windows side (bypasses WSL networking issues).
53
+ */
54
+ export declare function checkAPIFromWindows(port?: number): {
55
+ running: boolean;
56
+ statusCode: number;
57
+ models?: string[];
58
+ };
59
+ /**
60
+ * Check what port SD is listening on from Windows.
61
+ */
62
+ export declare function findSDPort(): number | null;
63
+ /**
64
+ * Get Python process info from Windows.
65
+ */
66
+ export declare function getPythonProcesses(): Array<{
67
+ pid: number;
68
+ ram: number;
69
+ path: string;
70
+ }>;
71
+ /**
72
+ * Full diagnostic — check everything and report.
73
+ */
74
+ export declare function diagnoseSD(): Promise<string>;
75
+ /**
76
+ * Stop SD — kill Python processes running the package.
77
+ */
78
+ export declare function stopSD(): string;
79
+ /**
80
+ * Restart SD — stop then launch.
81
+ */
82
+ export declare function restartSD(): Promise<string>;