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,448 @@
|
|
|
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 { execSync } from "node:child_process";
|
|
16
|
+
import { findStabilityMatrix } from "../utils/stabilityMatrixManager.js";
|
|
17
|
+
const c = {
|
|
18
|
+
reset: "\x1b[0m", bold: "\x1b[1m", dim: "\x1b[2m",
|
|
19
|
+
green: "\x1b[32m", yellow: "\x1b[33m", red: "\x1b[31m", cyan: "\x1b[36m",
|
|
20
|
+
};
|
|
21
|
+
const PS = "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe";
|
|
22
|
+
const PS_WIN = "powershell.exe";
|
|
23
|
+
function tryExec(cmd, timeout = 10000) {
|
|
24
|
+
try {
|
|
25
|
+
return execSync(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout }).trim() || null;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function isWSL() {
|
|
32
|
+
try {
|
|
33
|
+
return !!execSync("grep -qi microsoft /proc/version && echo wsl", {
|
|
34
|
+
encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 2000,
|
|
35
|
+
}).trim();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function ps(script, timeout = 30000) {
|
|
42
|
+
const psExe = isWSL() ? PS : PS_WIN;
|
|
43
|
+
// Escape for bash → powershell
|
|
44
|
+
const escaped = script.replace(/'/g, "''");
|
|
45
|
+
try {
|
|
46
|
+
return execSync(`${psExe} -NoProfile -Command "${escaped}"`, {
|
|
47
|
+
encoding: "utf-8",
|
|
48
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
49
|
+
timeout,
|
|
50
|
+
}).trim() || null;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function psRun(script, timeout = 30000) {
|
|
57
|
+
const psExe = isWSL() ? PS : PS_WIN;
|
|
58
|
+
execSync(`${psExe} -NoProfile -Command "${script.replace(/'/g, "''")}"`, {
|
|
59
|
+
stdio: "inherit",
|
|
60
|
+
timeout,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// ─── Window Management ─────────────────────────────────────────────────────
|
|
64
|
+
export function isSMRunning() {
|
|
65
|
+
return !!ps("Get-Process StabilityMatrix -ErrorAction SilentlyContinue | Select-Object -First 1 -ExpandProperty Id");
|
|
66
|
+
}
|
|
67
|
+
export function launchSM(sm) {
|
|
68
|
+
if (isSMRunning()) {
|
|
69
|
+
console.log(`${c.dim} SM already running${c.reset}`);
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
const smExe = sm.platform === "wsl"
|
|
73
|
+
? tryExec(`wslpath -w "${sm.path}/StabilityMatrix.exe"`)
|
|
74
|
+
: `${sm.path}\\StabilityMatrix.exe`;
|
|
75
|
+
if (!smExe)
|
|
76
|
+
return false;
|
|
77
|
+
console.log(`${c.dim} Launching Stability Matrix...${c.reset}`);
|
|
78
|
+
ps(`Start-Process '${smExe}'`);
|
|
79
|
+
// Wait for window
|
|
80
|
+
for (let i = 0; i < 20; i++) {
|
|
81
|
+
if (isSMRunning())
|
|
82
|
+
return true;
|
|
83
|
+
tryExec("sleep 1");
|
|
84
|
+
}
|
|
85
|
+
return isSMRunning();
|
|
86
|
+
}
|
|
87
|
+
export function focusSMWindow() {
|
|
88
|
+
return !!ps(`
|
|
89
|
+
Add-Type -AssemblyName UIAutomationClient
|
|
90
|
+
$root = [System.Windows.Automation.AutomationElement]::RootElement
|
|
91
|
+
$cond = New-Object System.Windows.Automation.PropertyCondition([System.Windows.Automation.AutomationElement]::NameProperty, 'Stability Matrix')
|
|
92
|
+
$win = $root.FindFirst([System.Windows.Automation.TreeScope]::Children, $cond)
|
|
93
|
+
if ($win) {
|
|
94
|
+
$pattern = $win.GetCurrentPattern([System.Windows.Automation.WindowPattern]::Pattern)
|
|
95
|
+
$pattern.SetWindowVisualState([System.Windows.Automation.WindowVisualState]::Normal)
|
|
96
|
+
Write-Output 'focused'
|
|
97
|
+
}
|
|
98
|
+
`);
|
|
99
|
+
}
|
|
100
|
+
// ─── UI Automation Helpers ─────────────────────────────────────────────────
|
|
101
|
+
/**
|
|
102
|
+
* Find a UI element by name/automationId and click it.
|
|
103
|
+
*/
|
|
104
|
+
export function clickButton(name, timeout = 10000) {
|
|
105
|
+
const script = `
|
|
106
|
+
Add-Type -AssemblyName UIAutomationClient
|
|
107
|
+
Add-Type -AssemblyName UIAutomationTypes
|
|
108
|
+
|
|
109
|
+
$root = [System.Windows.Automation.AutomationElement]::RootElement
|
|
110
|
+
|
|
111
|
+
# Find SM window
|
|
112
|
+
$smCond = New-Object System.Windows.Automation.PropertyCondition(
|
|
113
|
+
[System.Windows.Automation.AutomationElement]::NameProperty, 'Stability Matrix')
|
|
114
|
+
$smWin = $root.FindFirst([System.Windows.Automation.TreeScope]::Children, $smCond)
|
|
115
|
+
|
|
116
|
+
if (-not $smWin) {
|
|
117
|
+
# Try partial match
|
|
118
|
+
$procs = Get-Process StabilityMatrix -ErrorAction SilentlyContinue
|
|
119
|
+
if ($procs) {
|
|
120
|
+
$smCond = New-Object System.Windows.Automation.PropertyCondition(
|
|
121
|
+
[System.Windows.Automation.AutomationElement]::ProcessIdProperty, $procs[0].Id)
|
|
122
|
+
$smWin = $root.FindFirst([System.Windows.Automation.TreeScope]::Children, $smCond)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (-not $smWin) { Write-Output 'WINDOW_NOT_FOUND'; exit 1 }
|
|
127
|
+
|
|
128
|
+
# Find button by name
|
|
129
|
+
$btnCond = New-Object System.Windows.Automation.PropertyCondition(
|
|
130
|
+
[System.Windows.Automation.AutomationElement]::NameProperty, '${name}')
|
|
131
|
+
$btn = $smWin.FindFirst([System.Windows.Automation.TreeScope]::Descendants, $btnCond)
|
|
132
|
+
|
|
133
|
+
if (-not $btn) {
|
|
134
|
+
# Try AutomationId
|
|
135
|
+
$btnCond = New-Object System.Windows.Automation.PropertyCondition(
|
|
136
|
+
[System.Windows.Automation.AutomationElement]::AutomationIdProperty, '${name}')
|
|
137
|
+
$btn = $smWin.FindFirst([System.Windows.Automation.TreeScope]::Descendants, $btnCond)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (-not $btn) { Write-Output 'BUTTON_NOT_FOUND'; exit 1 }
|
|
141
|
+
|
|
142
|
+
# Click it
|
|
143
|
+
$invokePattern = $btn.GetCurrentPattern([System.Windows.Automation.InvokePattern]::Pattern)
|
|
144
|
+
$invokePattern.Invoke()
|
|
145
|
+
Write-Output 'CLICKED'
|
|
146
|
+
`;
|
|
147
|
+
const result = ps(script, timeout);
|
|
148
|
+
return result === "CLICKED";
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Find a UI element by partial text match and click it.
|
|
152
|
+
*/
|
|
153
|
+
export function clickByText(text) {
|
|
154
|
+
const script = `
|
|
155
|
+
Add-Type -AssemblyName UIAutomationClient
|
|
156
|
+
Add-Type -AssemblyName UIAutomationTypes
|
|
157
|
+
|
|
158
|
+
$root = [System.Windows.Automation.AutomationElement]::RootElement
|
|
159
|
+
$procs = Get-Process StabilityMatrix -ErrorAction SilentlyContinue
|
|
160
|
+
if (-not $procs) { Write-Output 'NOT_RUNNING'; exit 1 }
|
|
161
|
+
|
|
162
|
+
$smCond = New-Object System.Windows.Automation.PropertyCondition(
|
|
163
|
+
[System.Windows.Automation.AutomationElement]::ProcessIdProperty, $procs[0].Id)
|
|
164
|
+
$smWin = $root.FindFirst([System.Windows.Automation.TreeScope]::Children, $smCond)
|
|
165
|
+
if (-not $smWin) { Write-Output 'WINDOW_NOT_FOUND'; exit 1 }
|
|
166
|
+
|
|
167
|
+
# Search all descendants for text match
|
|
168
|
+
$all = $smWin.FindAll([System.Windows.Automation.TreeScope]::Descendants,
|
|
169
|
+
[System.Windows.Automation.Condition]::TrueCondition)
|
|
170
|
+
|
|
171
|
+
foreach ($el in $all) {
|
|
172
|
+
$elName = $el.Current.Name
|
|
173
|
+
if ($elName -like '*${text}*') {
|
|
174
|
+
try {
|
|
175
|
+
$invokePattern = $el.GetCurrentPattern([System.Windows.Automation.InvokePattern]::Pattern)
|
|
176
|
+
$invokePattern.Invoke()
|
|
177
|
+
Write-Output "CLICKED: $elName"
|
|
178
|
+
exit 0
|
|
179
|
+
} catch {
|
|
180
|
+
# Try SelectionItemPattern for list items
|
|
181
|
+
try {
|
|
182
|
+
$selectPattern = $el.GetCurrentPattern([System.Windows.Automation.SelectionItemPattern]::Pattern)
|
|
183
|
+
$selectPattern.Select()
|
|
184
|
+
Write-Output "SELECTED: $elName"
|
|
185
|
+
exit 0
|
|
186
|
+
} catch {}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
Write-Output 'TEXT_NOT_FOUND'
|
|
191
|
+
`;
|
|
192
|
+
const result = ps(script, 15000);
|
|
193
|
+
return !!result && (result.startsWith("CLICKED") || result.startsWith("SELECTED"));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* List all clickable elements in SM window (for debugging).
|
|
197
|
+
*/
|
|
198
|
+
export function listUIElements() {
|
|
199
|
+
const script = `
|
|
200
|
+
Add-Type -AssemblyName UIAutomationClient
|
|
201
|
+
$root = [System.Windows.Automation.AutomationElement]::RootElement
|
|
202
|
+
$procs = Get-Process StabilityMatrix -ErrorAction SilentlyContinue
|
|
203
|
+
if (-not $procs) { exit 1 }
|
|
204
|
+
|
|
205
|
+
$smCond = New-Object System.Windows.Automation.PropertyCondition(
|
|
206
|
+
[System.Windows.Automation.AutomationElement]::ProcessIdProperty, $procs[0].Id)
|
|
207
|
+
$smWin = $root.FindFirst([System.Windows.Automation.TreeScope]::Children, $smCond)
|
|
208
|
+
if (-not $smWin) { exit 1 }
|
|
209
|
+
|
|
210
|
+
$all = $smWin.FindAll([System.Windows.Automation.TreeScope]::Descendants,
|
|
211
|
+
[System.Windows.Automation.Condition]::TrueCondition)
|
|
212
|
+
|
|
213
|
+
foreach ($el in $all) {
|
|
214
|
+
$name = $el.Current.Name
|
|
215
|
+
$type = $el.Current.ControlType.ProgrammaticName
|
|
216
|
+
$id = $el.Current.AutomationId
|
|
217
|
+
if ($name -or $id) {
|
|
218
|
+
Write-Output "$type | $name | $id"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
`;
|
|
222
|
+
const result = ps(script, 20000);
|
|
223
|
+
return result ? result.split("\n").filter(l => l.trim()) : [];
|
|
224
|
+
}
|
|
225
|
+
// ─── High-Level Actions ────────────────────────────────────────────────────
|
|
226
|
+
/**
|
|
227
|
+
* Full automated install flow:
|
|
228
|
+
* 1. Launch SM
|
|
229
|
+
* 2. Click "Add Package"
|
|
230
|
+
* 3. Select package (Forge, ComfyUI, etc.)
|
|
231
|
+
* 4. Click Install
|
|
232
|
+
* 5. Wait for completion
|
|
233
|
+
* 6. Click Launch
|
|
234
|
+
*/
|
|
235
|
+
export async function automateInstallPackage(packageName = "Stable Diffusion WebUI Forge") {
|
|
236
|
+
const sm = findStabilityMatrix();
|
|
237
|
+
if (!sm)
|
|
238
|
+
return { success: false, message: "Stability Matrix not found" };
|
|
239
|
+
console.log(`${c.cyan}Step 1/${c.reset} Launching Stability Matrix...`);
|
|
240
|
+
if (!launchSM(sm)) {
|
|
241
|
+
return { success: false, message: "Could not launch Stability Matrix" };
|
|
242
|
+
}
|
|
243
|
+
// Wait for UI to be ready
|
|
244
|
+
await sleep(3000);
|
|
245
|
+
console.log(`${c.cyan}Step 2/${c.reset} Looking for Add Package button...`);
|
|
246
|
+
// SM uses Avalonia UI — try common button names
|
|
247
|
+
let clicked = clickButton("Add Package") || clickButton("AddPackageButton") || clickByText("Add");
|
|
248
|
+
if (!clicked) {
|
|
249
|
+
// List elements to help debug
|
|
250
|
+
console.log(`${c.dim} Could not find Add Package button. Available elements:${c.reset}`);
|
|
251
|
+
const elements = listUIElements();
|
|
252
|
+
const relevant = elements.filter(e => e.toLowerCase().includes("add") || e.toLowerCase().includes("install") ||
|
|
253
|
+
e.toLowerCase().includes("package") || e.toLowerCase().includes("button")).slice(0, 10);
|
|
254
|
+
for (const el of relevant) {
|
|
255
|
+
console.log(`${c.dim} ${el}${c.reset}`);
|
|
256
|
+
}
|
|
257
|
+
return { success: false, message: "Could not find Add Package button — SM UI may have changed" };
|
|
258
|
+
}
|
|
259
|
+
await sleep(2000);
|
|
260
|
+
console.log(`${c.cyan}Step 3/${c.reset} Selecting ${packageName}...`);
|
|
261
|
+
clicked = clickByText(packageName);
|
|
262
|
+
if (!clicked) {
|
|
263
|
+
console.log(`${c.yellow}⚠${c.reset} Could not find "${packageName}" in package list`);
|
|
264
|
+
return { success: false, message: `Package "${packageName}" not found in SM` };
|
|
265
|
+
}
|
|
266
|
+
await sleep(1000);
|
|
267
|
+
console.log(`${c.cyan}Step 4/${c.reset} Clicking Install...`);
|
|
268
|
+
clicked = clickButton("Install") || clickByText("Install");
|
|
269
|
+
if (!clicked) {
|
|
270
|
+
return { success: false, message: "Could not find Install button" };
|
|
271
|
+
}
|
|
272
|
+
console.log(`${c.cyan}Step 5/${c.reset} Installation started — monitoring progress...`);
|
|
273
|
+
console.log(`${c.dim} SM is downloading Python, models, and all dependencies.${c.reset}`);
|
|
274
|
+
console.log(`${c.dim} This may take 10-30 minutes.${c.reset}`);
|
|
275
|
+
// Monitor by checking if the install is still running
|
|
276
|
+
// SM shows a progress bar — we can check if the Launch button appears
|
|
277
|
+
for (let i = 0; i < 120; i++) { // Up to 60 minutes
|
|
278
|
+
await sleep(30000);
|
|
279
|
+
const elapsed = (i + 1) * 30;
|
|
280
|
+
console.log(`${c.dim} ${Math.floor(elapsed / 60)}m ${elapsed % 60}s elapsed...${c.reset}`);
|
|
281
|
+
// Check if Launch button appeared (install done)
|
|
282
|
+
if (clickButton("Launch") || clickByText("Launch")) {
|
|
283
|
+
console.log(`${c.green}✓${c.reset} Installation complete — package launched!`);
|
|
284
|
+
return { success: true, message: `${c.green}✓${c.reset} ${packageName} installed and launched via Stability Matrix` };
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return { success: false, message: "Installation timed out after 60 minutes" };
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Launch the active package.
|
|
291
|
+
*/
|
|
292
|
+
export async function automateLaunch() {
|
|
293
|
+
const sm = findStabilityMatrix();
|
|
294
|
+
if (!sm)
|
|
295
|
+
return { success: false, message: "Stability Matrix not found" };
|
|
296
|
+
if (!launchSM(sm)) {
|
|
297
|
+
return { success: false, message: "Could not launch SM" };
|
|
298
|
+
}
|
|
299
|
+
await sleep(3000);
|
|
300
|
+
console.log(`${c.dim} Clicking Launch...${c.reset}`);
|
|
301
|
+
const clicked = clickButton("Launch") || clickByText("Launch");
|
|
302
|
+
if (!clicked) {
|
|
303
|
+
return { success: false, message: "Could not find Launch button — package may not be installed" };
|
|
304
|
+
}
|
|
305
|
+
return { success: true, message: `${c.green}✓${c.reset} Package launching...` };
|
|
306
|
+
}
|
|
307
|
+
// ─── Status & Diagnostics ──────────────────────────────────────────────────
|
|
308
|
+
/**
|
|
309
|
+
* Check SD API from the Windows side (bypasses WSL networking issues).
|
|
310
|
+
*/
|
|
311
|
+
export function checkAPIFromWindows(port = 7860) {
|
|
312
|
+
const result = ps(`
|
|
313
|
+
try {
|
|
314
|
+
$r = Invoke-WebRequest -Uri "http://127.0.0.1:${port}/sdapi/v1/sd-models" -TimeoutSec 5
|
|
315
|
+
Write-Output "OK:$($r.StatusCode):$($r.Content.Substring(0, [Math]::Min(500, $r.Content.Length)))"
|
|
316
|
+
} catch {
|
|
317
|
+
$code = 0
|
|
318
|
+
if ($_.Exception.Response) { $code = [int]$_.Exception.Response.StatusCode }
|
|
319
|
+
Write-Output "FAIL:$code:$($_.Exception.Message)"
|
|
320
|
+
}
|
|
321
|
+
`, 10000);
|
|
322
|
+
if (!result)
|
|
323
|
+
return { running: false, statusCode: 0 };
|
|
324
|
+
const [status, code, body] = result.split(":", 3);
|
|
325
|
+
if (status === "OK") {
|
|
326
|
+
try {
|
|
327
|
+
const models = JSON.parse(body).map((m) => m.model_name);
|
|
328
|
+
return { running: true, statusCode: parseInt(code), models };
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
return { running: true, statusCode: parseInt(code) };
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return { running: false, statusCode: parseInt(code) || 0 };
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Check what port SD is listening on from Windows.
|
|
338
|
+
*/
|
|
339
|
+
export function findSDPort() {
|
|
340
|
+
const result = ps(`
|
|
341
|
+
$ports = @(7860, 7861, 8188, 9090)
|
|
342
|
+
foreach ($p in $ports) {
|
|
343
|
+
$tcp = Get-NetTCPConnection -LocalPort $p -ErrorAction SilentlyContinue
|
|
344
|
+
if ($tcp) { Write-Output $p; exit }
|
|
345
|
+
}
|
|
346
|
+
Write-Output "NONE"
|
|
347
|
+
`, 10000);
|
|
348
|
+
if (!result || result === "NONE")
|
|
349
|
+
return null;
|
|
350
|
+
return parseInt(result);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Get Python process info from Windows.
|
|
354
|
+
*/
|
|
355
|
+
export function getPythonProcesses() {
|
|
356
|
+
const result = ps(`
|
|
357
|
+
Get-Process python* -ErrorAction SilentlyContinue | ForEach-Object {
|
|
358
|
+
Write-Output "$($_.Id)|$($_.WorkingSet64)|$($_.Path)"
|
|
359
|
+
}
|
|
360
|
+
`, 10000);
|
|
361
|
+
if (!result)
|
|
362
|
+
return [];
|
|
363
|
+
return result.split("\n").filter(l => l.includes("|")).map(line => {
|
|
364
|
+
const [pid, ram, path] = line.split("|");
|
|
365
|
+
return { pid: parseInt(pid), ram: parseInt(ram), path: path?.trim() ?? "" };
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Full diagnostic — check everything and report.
|
|
370
|
+
*/
|
|
371
|
+
export async function diagnoseSD() {
|
|
372
|
+
const lines = [];
|
|
373
|
+
lines.push(`${c.bold}${c.cyan}SD Diagnostic Report${c.reset}\n`);
|
|
374
|
+
// 1. SM process
|
|
375
|
+
const smRunning = isSMRunning();
|
|
376
|
+
lines.push(`${smRunning ? c.green + "✓" : c.red + "✗"}${c.reset} Stability Matrix: ${smRunning ? "running" : "not running"}`);
|
|
377
|
+
// 2. Python processes
|
|
378
|
+
const pythons = getPythonProcesses();
|
|
379
|
+
const sdPython = pythons.filter(p => p.path.includes("reforge") || p.path.includes("StabilityMatrix") || p.ram > 1_000_000_000);
|
|
380
|
+
lines.push(`${sdPython.length > 0 ? c.green + "✓" : c.red + "✗"}${c.reset} Python processes: ${sdPython.length} SD-related`);
|
|
381
|
+
for (const p of sdPython) {
|
|
382
|
+
lines.push(` ${c.dim}PID ${p.pid} — ${(p.ram / 1073741824).toFixed(1)}GB RAM — ${p.path}${c.reset}`);
|
|
383
|
+
}
|
|
384
|
+
// 3. Port
|
|
385
|
+
const port = findSDPort();
|
|
386
|
+
lines.push(`${port ? c.green + "✓" : c.yellow + "⚠"}${c.reset} Port: ${port ? `${port} listening` : "no SD port detected"}`);
|
|
387
|
+
// 4. API
|
|
388
|
+
if (port) {
|
|
389
|
+
const api = checkAPIFromWindows(port);
|
|
390
|
+
lines.push(`${api.running ? c.green + "✓" : c.yellow + "⚠"}${c.reset} API: ${api.running ? `responding (HTTP ${api.statusCode})` : `not ready (HTTP ${api.statusCode}) — still loading`}`);
|
|
391
|
+
if (api.models) {
|
|
392
|
+
lines.push(` ${c.dim}Models: ${api.models.join(", ")}${c.reset}`);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
lines.push(`${c.red}✗${c.reset} API: no port listening — SD may have failed to start`);
|
|
397
|
+
}
|
|
398
|
+
// 5. WSL↔Windows connectivity
|
|
399
|
+
if (port && isWSL()) {
|
|
400
|
+
const winIP = tryExec("cat /etc/resolv.conf | grep nameserver | awk '{print $2}'");
|
|
401
|
+
const wslReach = tryExec(`curl -sf --max-time 2 http://${winIP}:${port}/ 2>/dev/null`);
|
|
402
|
+
const localReach = tryExec(`curl -sf --max-time 2 http://localhost:${port}/ 2>/dev/null`);
|
|
403
|
+
lines.push(`${localReach ? c.green + "✓" : c.yellow + "⚠"}${c.reset} WSL localhost:${port}: ${localReach ? "reachable" : "not reachable"}`);
|
|
404
|
+
lines.push(`${wslReach ? c.green + "✓" : c.yellow + "⚠"}${c.reset} WSL→Windows (${winIP}:${port}): ${wslReach ? "reachable" : "not reachable — need --listen flag"}`);
|
|
405
|
+
}
|
|
406
|
+
// 6. SM settings check
|
|
407
|
+
const sm = findStabilityMatrix();
|
|
408
|
+
if (sm) {
|
|
409
|
+
const { getActivePackage: getActive } = await import("../utils/stabilityMatrixManager.js");
|
|
410
|
+
const active = getActive(sm);
|
|
411
|
+
if (active) {
|
|
412
|
+
const hasApi = active.LaunchArgs.some(a => a.Name === "--api" && a.OptionValue === true);
|
|
413
|
+
const hasListen = active.LaunchArgs.some(a => a.Name === "--listen" && a.OptionValue === true);
|
|
414
|
+
lines.push(`${hasApi ? c.green + "✓" : c.red + "✗"}${c.reset} --api flag: ${hasApi ? "enabled" : "DISABLED — enable with: notoken sd config --api"}`);
|
|
415
|
+
lines.push(`${hasListen ? c.green + "✓" : c.yellow + "⚠"}${c.reset} --listen flag: ${hasListen ? "enabled" : "disabled — needed for WSL access"}`);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
return lines.join("\n");
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Stop SD — kill Python processes running the package.
|
|
422
|
+
*/
|
|
423
|
+
export function stopSD() {
|
|
424
|
+
ps(`
|
|
425
|
+
Get-Process python* -ErrorAction SilentlyContinue | Where-Object {
|
|
426
|
+
$_.Path -like '*reforge*' -or $_.Path -like '*StabilityMatrix*'
|
|
427
|
+
} | Stop-Process -Force
|
|
428
|
+
`, 10000);
|
|
429
|
+
return `${c.green}✓${c.reset} SD processes stopped`;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Restart SD — stop then launch.
|
|
433
|
+
*/
|
|
434
|
+
export async function restartSD() {
|
|
435
|
+
stopSD();
|
|
436
|
+
await sleep(2000);
|
|
437
|
+
const sm = findStabilityMatrix();
|
|
438
|
+
if (!sm)
|
|
439
|
+
return `${c.red}✗${c.reset} SM not found`;
|
|
440
|
+
if (!isSMRunning())
|
|
441
|
+
launchSM(sm);
|
|
442
|
+
await sleep(3000);
|
|
443
|
+
clickButton("LaunchButton");
|
|
444
|
+
return `${c.green}✓${c.reset} SD restarting — check status in a minute`;
|
|
445
|
+
}
|
|
446
|
+
function sleep(ms) {
|
|
447
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
448
|
+
}
|
|
@@ -13,7 +13,7 @@ import { getLastEntity, getRecentTurns } from "./store.js";
|
|
|
13
13
|
*/
|
|
14
14
|
// Patterns that signal a reference to a previous turn
|
|
15
15
|
const REPEAT_PATTERNS = [
|
|
16
|
-
/^(do it|do that|run it|run that|same thing|again|repeat|redo|re-?run)\b/i,
|
|
16
|
+
/^(do it|do that|run it|run that|same thing|again|repeat|redo|re-?run|try again|retry|one more time|run again|do it again|try that again|go again|try it now|try now|try it|let.?s try|give it another|another try)\b/i,
|
|
17
17
|
/^same\b/i,
|
|
18
18
|
];
|
|
19
19
|
const PRONOUN_PATTERNS = [
|
|
@@ -24,6 +24,18 @@ const PRONOUN_PATTERNS = [
|
|
|
24
24
|
{ pattern: /\bthat (file|path|directory)\b/i, refType: "path" },
|
|
25
25
|
{ pattern: /\bthere\b/i, refType: "environment" },
|
|
26
26
|
{ pattern: /\bthat (env|environment|box|machine)\b/i, refType: "environment" },
|
|
27
|
+
// "the other" — refers to the second-most-recent entity (not the one we just acted on)
|
|
28
|
+
{ pattern: /\bthe other (one|service|server|thing)\b/i, refType: "service", offset: 1 },
|
|
29
|
+
{ pattern: /\bthe other (env|environment|box|machine|server)\b/i, refType: "environment", offset: 1 },
|
|
30
|
+
{ pattern: /\bthe other\b/i, refType: "any", offset: 1 },
|
|
31
|
+
{ pattern: /\bnot that one\b/i, refType: "any", offset: 1 },
|
|
32
|
+
{ pattern: /\bnot this one\b/i, refType: "any", offset: 1 },
|
|
33
|
+
{ pattern: /\bno not this one\b/i, refType: "any", offset: 1 },
|
|
34
|
+
{ pattern: /\bno not that one\b/i, refType: "any", offset: 1 },
|
|
35
|
+
{ pattern: /\bnot that\b/i, refType: "any", offset: 1 },
|
|
36
|
+
{ pattern: /\bthe previous one\b/i, refType: "any", offset: 1 },
|
|
37
|
+
{ pattern: /\bthe one before\b/i, refType: "any", offset: 1 },
|
|
38
|
+
{ pattern: /\bthe first one\b/i, refType: "any", offset: 1 },
|
|
27
39
|
];
|
|
28
40
|
const OVERRIDE_PATTERNS = [
|
|
29
41
|
{ pattern: /\bbut (?:on|in) (\w+)\b/i, field: "environment" },
|
|
@@ -42,6 +54,27 @@ export function resolveCoreferences(rawText, conv) {
|
|
|
42
54
|
let resolvedIntent;
|
|
43
55
|
const recentTurns = getRecentTurns(conv, 5);
|
|
44
56
|
const lastUserTurn = recentTurns[recentTurns.length - 1];
|
|
57
|
+
// 0. Check for "the other thing" / "try the other thing" — second-to-last command
|
|
58
|
+
const otherThingPattern = /^(?:try |do |run )?the other (?:thing|one|command)\b/i;
|
|
59
|
+
if (otherThingPattern.test(rawText.trim())) {
|
|
60
|
+
isReference = true;
|
|
61
|
+
const prevTurn = recentTurns[recentTurns.length - 2];
|
|
62
|
+
if (prevTurn?.intent && prevTurn.fields) {
|
|
63
|
+
resolvedIntent = {
|
|
64
|
+
intent: prevTurn.intent,
|
|
65
|
+
confidence: 0.8,
|
|
66
|
+
rawText,
|
|
67
|
+
fields: { ...prevTurn.fields },
|
|
68
|
+
};
|
|
69
|
+
resolvedText = prevTurn.rawText;
|
|
70
|
+
resolutions.push({
|
|
71
|
+
original: rawText,
|
|
72
|
+
resolved: prevTurn.rawText,
|
|
73
|
+
source: "last_turn",
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return { resolvedText, isReference, resolvedIntent, resolutions };
|
|
77
|
+
}
|
|
45
78
|
// 1. Check for full repeat patterns ("do it again", "same thing")
|
|
46
79
|
for (const pattern of REPEAT_PATTERNS) {
|
|
47
80
|
if (pattern.test(rawText.trim())) {
|
|
@@ -73,13 +106,20 @@ export function resolveCoreferences(rawText, conv) {
|
|
|
73
106
|
return { resolvedText, isReference, resolvedIntent, resolutions };
|
|
74
107
|
}
|
|
75
108
|
}
|
|
76
|
-
// 2. Resolve pronouns ("restart it", "check that service")
|
|
77
|
-
for (const { pattern, refType } of PRONOUN_PATTERNS) {
|
|
109
|
+
// 2. Resolve pronouns ("restart it", "check that service", "the other one")
|
|
110
|
+
for (const { pattern, refType, offset } of PRONOUN_PATTERNS) {
|
|
78
111
|
const match = rawText.match(pattern);
|
|
79
112
|
if (!match)
|
|
80
113
|
continue;
|
|
81
114
|
let resolved;
|
|
82
|
-
if (
|
|
115
|
+
if (offset && offset > 0) {
|
|
116
|
+
// "the other" — get the Nth entity (skip the most recent)
|
|
117
|
+
const candidates = refType === "any"
|
|
118
|
+
? [...conv.knowledgeTree].sort((a, b) => b.lastMentioned - a.lastMentioned)
|
|
119
|
+
: conv.knowledgeTree.filter(n => n.type === refType).sort((a, b) => b.lastMentioned - a.lastMentioned);
|
|
120
|
+
resolved = candidates[offset]; // offset=1 means second-most-recent
|
|
121
|
+
}
|
|
122
|
+
else if (refType === "any") {
|
|
83
123
|
// "it" → most recent service, then most recent entity
|
|
84
124
|
resolved = getLastEntity(conv, "service")
|
|
85
125
|
?? getLastEntity(conv, "path")
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pending Actions.
|
|
3
|
+
*
|
|
4
|
+
* Tracks suggestions NoToken makes so when the user says
|
|
5
|
+
* "ok", "try that", "do it", "run it", "yes" — it knows what to execute.
|
|
6
|
+
*
|
|
7
|
+
* Examples:
|
|
8
|
+
* NoToken: "✓ Installed. Start: notoken start stable-diffusion"
|
|
9
|
+
* User: "ok try it"
|
|
10
|
+
* → executes "notoken start stable-diffusion"
|
|
11
|
+
*
|
|
12
|
+
* NoToken: "Update available: 1.5.0 → 1.7.0"
|
|
13
|
+
* User: "yes do it"
|
|
14
|
+
* → executes update
|
|
15
|
+
*/
|
|
16
|
+
export interface PendingAction {
|
|
17
|
+
/** What to execute — either an intent name or a raw command */
|
|
18
|
+
action: string;
|
|
19
|
+
/** Human description */
|
|
20
|
+
description: string;
|
|
21
|
+
/** Type: intent to parse, or command to run directly */
|
|
22
|
+
type: "intent" | "command";
|
|
23
|
+
/** When it was suggested (auto-set by suggestAction) */
|
|
24
|
+
timestamp?: number;
|
|
25
|
+
/** The raw text/fields for the intent */
|
|
26
|
+
fields?: Record<string, unknown>;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Store an action that NoToken is suggesting to the user.
|
|
30
|
+
* Most recent is at the end.
|
|
31
|
+
*/
|
|
32
|
+
export declare function suggestAction(action: PendingAction): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get the most recent pending action (if any, and if not too old).
|
|
35
|
+
* Actions expire after 5 minutes.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getLastPendingAction(): PendingAction | null;
|
|
38
|
+
/**
|
|
39
|
+
* Pop (consume) the last pending action.
|
|
40
|
+
*/
|
|
41
|
+
export declare function consumePendingAction(): PendingAction | null;
|
|
42
|
+
/**
|
|
43
|
+
* Check if user is giving a directive about the pending action.
|
|
44
|
+
* E.g. "put it on F drive", "install it on D:", "no use /mnt/f"
|
|
45
|
+
* Returns the resolved new text if yes, null otherwise.
|
|
46
|
+
*/
|
|
47
|
+
export declare function isRedirectingPendingAction(text: string): string | null;
|
|
48
|
+
/**
|
|
49
|
+
* Check if user input is an affirmation to execute a pending action.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isAffirmation(text: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Clear all pending actions.
|
|
54
|
+
*/
|
|
55
|
+
export declare function clearPendingActions(): void;
|