clawaid 1.0.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/README.md +118 -0
- package/dist/diagnose.d.ts +41 -0
- package/dist/diagnose.d.ts.map +1 -0
- package/dist/diagnose.js +410 -0
- package/dist/diagnose.js.map +1 -0
- package/dist/execute.d.ts +16 -0
- package/dist/execute.d.ts.map +1 -0
- package/dist/execute.js +153 -0
- package/dist/execute.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +115 -0
- package/dist/index.js.map +1 -0
- package/dist/loop.d.ts +43 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +316 -0
- package/dist/loop.js.map +1 -0
- package/dist/observe.d.ts +29 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +330 -0
- package/dist/observe.js.map +1 -0
- package/dist/rules.d.ts +11 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +300 -0
- package/dist/rules.js.map +1 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +126 -0
- package/dist/server.js.map +1 -0
- package/dist/verify.d.ts +10 -0
- package/dist/verify.d.ts.map +1 -0
- package/dist/verify.js +29 -0
- package/dist/verify.js.map +1 -0
- package/package.json +32 -0
- package/web/index.html +1226 -0
package/dist/execute.js
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.executeActions = executeActions;
|
|
37
|
+
exports.formatExecuteResults = formatExecuteResults;
|
|
38
|
+
const child_process_1 = require("child_process");
|
|
39
|
+
const util_1 = require("util");
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const os = __importStar(require("os"));
|
|
42
|
+
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
43
|
+
async function runCommand(cmd, timeout = 30000) {
|
|
44
|
+
try {
|
|
45
|
+
const { stdout, stderr } = await execAsync(cmd, {
|
|
46
|
+
timeout,
|
|
47
|
+
env: {
|
|
48
|
+
...process.env,
|
|
49
|
+
PATH: '/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:' + (process.env.PATH || ''),
|
|
50
|
+
HOME: os.homedir(),
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
const output = (stdout + (stderr ? '\n' + stderr : '')).trim();
|
|
54
|
+
return { success: true, output: output || '[command completed with no output]' };
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
if (err && typeof err === 'object' && 'stdout' in err && 'stderr' in err) {
|
|
58
|
+
const e = err;
|
|
59
|
+
const out = (e.stdout || '').trim();
|
|
60
|
+
const errOut = (e.stderr || '').trim();
|
|
61
|
+
const combined = [out, errOut].filter(Boolean).join('\n');
|
|
62
|
+
// Some commands return non-zero but still succeed (e.g., kill when process doesn't exist)
|
|
63
|
+
return { success: false, output: combined || e.message, error: e.message };
|
|
64
|
+
}
|
|
65
|
+
return { success: false, output: '', error: err.message };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function backupFile(filePath) {
|
|
69
|
+
const expandedPath = filePath.replace('~', os.homedir());
|
|
70
|
+
const backupPath = expandedPath + '.bak.' + Date.now();
|
|
71
|
+
if (fs.existsSync(expandedPath)) {
|
|
72
|
+
fs.copyFileSync(expandedPath, backupPath);
|
|
73
|
+
return backupPath;
|
|
74
|
+
}
|
|
75
|
+
return '';
|
|
76
|
+
}
|
|
77
|
+
async function executeActions(actions, onProgress, dryRun = false) {
|
|
78
|
+
const results = [];
|
|
79
|
+
const progress = (msg, result) => {
|
|
80
|
+
if (onProgress)
|
|
81
|
+
onProgress(msg, result);
|
|
82
|
+
};
|
|
83
|
+
if (dryRun) {
|
|
84
|
+
progress('ā ļø DRY-RUN mode ā showing what would be executed:');
|
|
85
|
+
for (let i = 0; i < actions.length; i++) {
|
|
86
|
+
const action = actions[i];
|
|
87
|
+
progress(` Step ${i + 1}: ${action.description}`);
|
|
88
|
+
progress(` $ ${action.command}`);
|
|
89
|
+
progress(` Risk: ${action.risk} | Type: ${action.type}`);
|
|
90
|
+
results.push({
|
|
91
|
+
action,
|
|
92
|
+
success: true,
|
|
93
|
+
output: '[dry-run: not executed]',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return { results, allSucceeded: true, summary: `Dry run: ${actions.length} actions shown (not executed)` };
|
|
97
|
+
}
|
|
98
|
+
for (let i = 0; i < actions.length; i++) {
|
|
99
|
+
const action = actions[i];
|
|
100
|
+
progress(`Step ${i + 1}/${actions.length}: ${action.description}`);
|
|
101
|
+
let backupPath;
|
|
102
|
+
// Backup file if needed
|
|
103
|
+
if (action.type === 'file_edit' && action.backup) {
|
|
104
|
+
try {
|
|
105
|
+
progress(` ā Creating backup...`);
|
|
106
|
+
const backupCmd = action.backup.replace('~', os.homedir());
|
|
107
|
+
// Extract file path from backup command or action command
|
|
108
|
+
const fileMatch = action.command.match(/['"]?([~\/][^'"]+)['"]?/);
|
|
109
|
+
if (fileMatch) {
|
|
110
|
+
backupPath = await backupFile(fileMatch[1]);
|
|
111
|
+
if (backupPath) {
|
|
112
|
+
progress(` ā Backed up to: ${backupPath}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
progress(` ā Backup warning: ${e.message}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Execute the command
|
|
121
|
+
progress(` ā Running: ${action.command}`);
|
|
122
|
+
const { success, output, error } = await runCommand(action.command);
|
|
123
|
+
const result = {
|
|
124
|
+
action,
|
|
125
|
+
success,
|
|
126
|
+
output,
|
|
127
|
+
error,
|
|
128
|
+
backupPath,
|
|
129
|
+
};
|
|
130
|
+
results.push(result);
|
|
131
|
+
progress(` ā ${success ? 'ā Success' : 'ā Failed'}: ${output.slice(0, 200)}`, result);
|
|
132
|
+
// If a high-risk action fails, stop
|
|
133
|
+
if (!success && action.risk === 'high') {
|
|
134
|
+
progress(`High-risk action failed, stopping execution for safety.`);
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
// Small delay between actions
|
|
138
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
139
|
+
}
|
|
140
|
+
const allSucceeded = results.length > 0 && results.every(r => r.success);
|
|
141
|
+
const successCount = results.filter(r => r.success).length;
|
|
142
|
+
const summary = `Executed ${results.length} actions: ${successCount} succeeded, ${results.length - successCount} failed`;
|
|
143
|
+
return { results, allSucceeded, summary };
|
|
144
|
+
}
|
|
145
|
+
function formatExecuteResults(results) {
|
|
146
|
+
return results.map((r, i) => {
|
|
147
|
+
const status = r.success ? 'ā' : 'ā';
|
|
148
|
+
return `${status} Step ${i + 1}: ${r.action.description}
|
|
149
|
+
Command: ${r.action.command}
|
|
150
|
+
Output: ${r.output.slice(0, 300)}${r.error ? `\n Error: ${r.error}` : ''}${r.backupPath ? `\n Backup: ${r.backupPath}` : ''}`;
|
|
151
|
+
}).join('\n\n');
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=execute.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"execute.js","sourceRoot":"","sources":["../src/execute.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const http = __importStar(require("http"));
|
|
38
|
+
const server_1 = require("./server");
|
|
39
|
+
// Find a free port
|
|
40
|
+
async function findFreePort(start = 7357) {
|
|
41
|
+
return new Promise((resolve) => {
|
|
42
|
+
const server = http.createServer();
|
|
43
|
+
server.listen(start, '127.0.0.1', () => {
|
|
44
|
+
const port = server.address().port;
|
|
45
|
+
server.close(() => resolve(port));
|
|
46
|
+
});
|
|
47
|
+
server.on('error', () => {
|
|
48
|
+
resolve(findFreePort(start + 1));
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async function openBrowser(url) {
|
|
53
|
+
const { exec } = await Promise.resolve().then(() => __importStar(require('child_process')));
|
|
54
|
+
const { promisify } = await Promise.resolve().then(() => __importStar(require('util')));
|
|
55
|
+
const execAsync = promisify(exec);
|
|
56
|
+
const platform = process.platform;
|
|
57
|
+
let cmd;
|
|
58
|
+
if (platform === 'darwin') {
|
|
59
|
+
cmd = `open "${url}"`;
|
|
60
|
+
}
|
|
61
|
+
else if (platform === 'win32') {
|
|
62
|
+
cmd = `start "" "${url}"`;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
cmd = `xdg-open "${url}"`;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
await execAsync(cmd);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
console.log(`Please open your browser to: ${url}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function main() {
|
|
75
|
+
const dryRun = process.argv.includes('--dry-run');
|
|
76
|
+
const noOpen = process.argv.includes('--no-open');
|
|
77
|
+
const mockIdx = process.argv.indexOf('--mock');
|
|
78
|
+
const mockScenario = mockIdx !== -1 ? process.argv[mockIdx + 1] : undefined;
|
|
79
|
+
const portIdx = process.argv.indexOf('--port');
|
|
80
|
+
const requestedPort = portIdx !== -1 ? parseInt(process.argv[portIdx + 1], 10) : undefined;
|
|
81
|
+
if (mockScenario) {
|
|
82
|
+
console.log(`š§Ŗ MOCK mode: using scenario "${mockScenario}"\n`);
|
|
83
|
+
global.__clawaid_mock = mockScenario;
|
|
84
|
+
}
|
|
85
|
+
console.log('\n𩺠ClawAid\n');
|
|
86
|
+
if (dryRun)
|
|
87
|
+
console.log('ā ļø DRY-RUN mode: fixes will NOT be executed\n');
|
|
88
|
+
console.log('Finding available port...');
|
|
89
|
+
// Export dry-run flag so server can access it
|
|
90
|
+
global.__clawaid_dry_run = dryRun;
|
|
91
|
+
const port = requestedPort || await findFreePort(7357);
|
|
92
|
+
const url = `http://127.0.0.1:${port}`;
|
|
93
|
+
console.log('Starting diagnostic server...');
|
|
94
|
+
await (0, server_1.createServer)(port);
|
|
95
|
+
console.log(`\nā Server running at ${url}`);
|
|
96
|
+
if (!noOpen) {
|
|
97
|
+
console.log('Opening browser...\n');
|
|
98
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
99
|
+
await openBrowser(url);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log('Browser auto-open disabled (--no-open)\n');
|
|
103
|
+
}
|
|
104
|
+
console.log('ClawAid is running. Press Ctrl+C to stop.\n');
|
|
105
|
+
// Keep process alive
|
|
106
|
+
process.on('SIGINT', () => {
|
|
107
|
+
console.log('\nShutting down ClawAid...');
|
|
108
|
+
process.exit(0);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
main().catch((err) => {
|
|
112
|
+
console.error('Failed to start ClawAid:', err);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/loop.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ObservationResult } from './observe';
|
|
2
|
+
import { DiagnosisResult } from './diagnose';
|
|
3
|
+
export type LoopState = 'idle' | 'observing' | 'diagnosing' | 'showing_options' | 'auto_executing' | 'executing' | 'verifying' | 'fixed' | 'not_fixed' | 'healthy' | 'needs_api_key' | 'error';
|
|
4
|
+
export interface LoopEvent {
|
|
5
|
+
type: 'state_change' | 'progress' | 'diagnosis' | 'action_result' | 'verify_result' | 'request_input' | 'complete' | 'error';
|
|
6
|
+
data: unknown;
|
|
7
|
+
}
|
|
8
|
+
export type EventCallback = (event: LoopEvent) => void;
|
|
9
|
+
export interface LoopContext {
|
|
10
|
+
apiKey: string;
|
|
11
|
+
originalObservation?: ObservationResult;
|
|
12
|
+
originalObservationText?: string;
|
|
13
|
+
currentDiagnosis?: DiagnosisResult;
|
|
14
|
+
attemptHistory: string[];
|
|
15
|
+
roundNumber: number;
|
|
16
|
+
}
|
|
17
|
+
export declare class DoctorLoop {
|
|
18
|
+
private callback;
|
|
19
|
+
private context;
|
|
20
|
+
private state;
|
|
21
|
+
private stopped;
|
|
22
|
+
constructor(callback: EventCallback, apiKey?: string);
|
|
23
|
+
setApiKey(key: string): void;
|
|
24
|
+
stop(): void;
|
|
25
|
+
private emit;
|
|
26
|
+
private setState;
|
|
27
|
+
private progress;
|
|
28
|
+
start(): Promise<void>;
|
|
29
|
+
provideInput(field: string, value: string): Promise<void>;
|
|
30
|
+
private runMainLoop;
|
|
31
|
+
/**
|
|
32
|
+
* Called when user clicks "Fix" on an option card.
|
|
33
|
+
* optionId: "A", "B", "C" ā if omitted, use the recommended option.
|
|
34
|
+
*/
|
|
35
|
+
startFix(optionId?: string): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Continue with round 2 or 3 after a failed fix attempt.
|
|
38
|
+
*/
|
|
39
|
+
private continueAfterFailure;
|
|
40
|
+
private executeOption;
|
|
41
|
+
private buildDiagnosticReport;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmD,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC/F,OAAO,EAAY,eAAe,EAA+B,MAAM,YAAY,CAAC;AAIpF,MAAM,MAAM,SAAS,GACjB,MAAM,GACN,WAAW,GACX,YAAY,GACZ,iBAAiB,GACjB,gBAAgB,GAChB,WAAW,GACX,WAAW,GACX,OAAO,GACP,WAAW,GACX,SAAS,GACT,eAAe,GACf,OAAO,CAAC;AAEZ,MAAM,WAAW,SAAS;IACxB,IAAI,EACA,cAAc,GACd,UAAU,GACV,WAAW,GACX,eAAe,GACf,eAAe,GACf,eAAe,GACf,UAAU,GACV,OAAO,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,iBAAiB,CAAC;IACxC,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,gBAAgB,CAAC,EAAE,eAAe,CAAC;IACnC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAS;gBAEZ,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAK;IAShD,SAAS,CAAC,GAAG,EAAE,MAAM;IAIrB,IAAI;IAIJ,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,QAAQ;IAIV,KAAK;IAwBL,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;YAQjC,WAAW;IAiEzB;;;OAGG;IACG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM;IAkChC;;OAEG;YACW,oBAAoB;YA4FpB,aAAa;IAwE3B,OAAO,CAAC,qBAAqB;CAqB9B"}
|
package/dist/loop.js
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DoctorLoop = void 0;
|
|
4
|
+
const observe_1 = require("./observe");
|
|
5
|
+
const diagnose_1 = require("./diagnose");
|
|
6
|
+
const execute_1 = require("./execute");
|
|
7
|
+
const verify_1 = require("./verify");
|
|
8
|
+
class DoctorLoop {
|
|
9
|
+
constructor(callback, apiKey = '') {
|
|
10
|
+
this.state = 'idle';
|
|
11
|
+
this.stopped = false;
|
|
12
|
+
this.callback = callback;
|
|
13
|
+
this.context = {
|
|
14
|
+
apiKey,
|
|
15
|
+
attemptHistory: [],
|
|
16
|
+
roundNumber: 0,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
setApiKey(key) {
|
|
20
|
+
this.context.apiKey = key;
|
|
21
|
+
}
|
|
22
|
+
stop() {
|
|
23
|
+
this.stopped = true;
|
|
24
|
+
}
|
|
25
|
+
emit(event) {
|
|
26
|
+
this.callback(event);
|
|
27
|
+
}
|
|
28
|
+
setState(state) {
|
|
29
|
+
this.state = state;
|
|
30
|
+
this.emit({ type: 'state_change', data: { state } });
|
|
31
|
+
}
|
|
32
|
+
progress(msg) {
|
|
33
|
+
this.emit({ type: 'progress', data: { message: msg } });
|
|
34
|
+
}
|
|
35
|
+
async start() {
|
|
36
|
+
// Check for API key first
|
|
37
|
+
const autoKey = (0, diagnose_1.extractApiKey)();
|
|
38
|
+
if (autoKey) {
|
|
39
|
+
this.context.apiKey = autoKey;
|
|
40
|
+
this.progress('Found OpenRouter API key in OpenClaw config ā');
|
|
41
|
+
}
|
|
42
|
+
else if (!this.context.apiKey) {
|
|
43
|
+
this.setState('needs_api_key');
|
|
44
|
+
this.emit({
|
|
45
|
+
type: 'request_input',
|
|
46
|
+
data: {
|
|
47
|
+
field: 'apiKey',
|
|
48
|
+
label: 'OpenRouter API Key',
|
|
49
|
+
placeholder: 'sk-or-...',
|
|
50
|
+
hint: 'š Local only. Not stored. Only sent to OpenRouter for AI diagnosis.',
|
|
51
|
+
instructions: 'ClawAid needs an OpenRouter API key to call Claude for diagnosis. Your existing OpenClaw config does not have an OpenRouter key.',
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
return; // Wait for user to provide key via provideInput()
|
|
55
|
+
}
|
|
56
|
+
await this.runMainLoop();
|
|
57
|
+
}
|
|
58
|
+
async provideInput(field, value) {
|
|
59
|
+
if (field === 'apiKey') {
|
|
60
|
+
this.context.apiKey = value;
|
|
61
|
+
this.progress('API key received, starting diagnosis...');
|
|
62
|
+
await this.runMainLoop();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async runMainLoop() {
|
|
66
|
+
// āā Round 1: Observe + Diagnose āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
67
|
+
this.setState('observing');
|
|
68
|
+
this.progress('š Gathering system information...');
|
|
69
|
+
const mockScenario = global.__clawaid_mock;
|
|
70
|
+
const observation = mockScenario
|
|
71
|
+
? (0, observe_1.loadMockObservation)(mockScenario)
|
|
72
|
+
: await (0, observe_1.observe)((msg) => this.progress(msg));
|
|
73
|
+
this.context.originalObservation = observation;
|
|
74
|
+
this.context.originalObservationText = (0, observe_1.formatObservation)(observation);
|
|
75
|
+
this.progress('ā System scan complete');
|
|
76
|
+
this.progress('š” Sending data to AI for analysis...');
|
|
77
|
+
this.setState('diagnosing');
|
|
78
|
+
this.progress('š¤ AI is analyzing your system...');
|
|
79
|
+
try {
|
|
80
|
+
const diagnosis = await (0, diagnose_1.diagnose)({
|
|
81
|
+
apiKey: this.context.apiKey,
|
|
82
|
+
observationData: this.context.originalObservationText,
|
|
83
|
+
});
|
|
84
|
+
this.context.currentDiagnosis = diagnosis;
|
|
85
|
+
// Healthy?
|
|
86
|
+
if (diagnosis.healthy && diagnosis.options.length === 0) {
|
|
87
|
+
this.progress('ā
' + (diagnosis.diagnosis || 'OpenClaw is running normally. No issues detected.'));
|
|
88
|
+
this.setState('healthy');
|
|
89
|
+
this.emit({
|
|
90
|
+
type: 'complete',
|
|
91
|
+
data: { fixed: false, healthy: true, explanation: diagnosis.diagnosis, warnings: diagnosis.warnings || [], reasoning: diagnosis.reasoning || [] },
|
|
92
|
+
});
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.emit({
|
|
96
|
+
type: 'diagnosis',
|
|
97
|
+
data: {
|
|
98
|
+
diagnosis: diagnosis.diagnosis,
|
|
99
|
+
confidence: diagnosis.confidence,
|
|
100
|
+
rootCause: diagnosis.rootCause,
|
|
101
|
+
reasoning: diagnosis.reasoning || [],
|
|
102
|
+
warnings: diagnosis.warnings || [],
|
|
103
|
+
options: diagnosis.options,
|
|
104
|
+
alternativeHypotheses: diagnosis.alternativeHypotheses,
|
|
105
|
+
round: 1,
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
// Always show options to user and wait for their choice
|
|
109
|
+
this.setState('showing_options');
|
|
110
|
+
return; // Resumes via startFix(optionId)
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
this.progress(`ā AI analysis failed: ${err.message}`);
|
|
114
|
+
this.setState('error');
|
|
115
|
+
this.emit({ type: 'error', data: { message: err.message } });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
// Auto-fix failed ā round 2 with updated observation
|
|
119
|
+
await this.continueAfterFailure(2);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Called when user clicks "Fix" on an option card.
|
|
123
|
+
* optionId: "A", "B", "C" ā if omitted, use the recommended option.
|
|
124
|
+
*/
|
|
125
|
+
async startFix(optionId) {
|
|
126
|
+
if (!this.context.currentDiagnosis) {
|
|
127
|
+
this.progress('No diagnosis available. Please restart.');
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const options = this.context.currentDiagnosis.options;
|
|
131
|
+
let chosen;
|
|
132
|
+
if (optionId) {
|
|
133
|
+
chosen = options.find(o => o.id === optionId);
|
|
134
|
+
}
|
|
135
|
+
if (!chosen) {
|
|
136
|
+
chosen = options.find(o => o.recommended) || options[0];
|
|
137
|
+
}
|
|
138
|
+
if (!chosen) {
|
|
139
|
+
this.progress('ā ļø No option found to execute.');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
this.context.roundNumber = 1;
|
|
143
|
+
const fixed = await this.executeOption(chosen);
|
|
144
|
+
if (fixed) {
|
|
145
|
+
this.setState('fixed');
|
|
146
|
+
this.emit({ type: 'complete', data: { fixed: true, explanation: 'OpenClaw has been successfully repaired!' } });
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
// Not fixed after round 1 user choice ā round 2
|
|
150
|
+
await this.continueAfterFailure(2);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Continue with round 2 or 3 after a failed fix attempt.
|
|
154
|
+
*/
|
|
155
|
+
async continueAfterFailure(round) {
|
|
156
|
+
if (this.stopped)
|
|
157
|
+
return;
|
|
158
|
+
// Round 3: give up
|
|
159
|
+
if (round > 3) {
|
|
160
|
+
this.setState('not_fixed');
|
|
161
|
+
this.progress('\nš After 3 repair rounds, the issue persists.');
|
|
162
|
+
this.emit({
|
|
163
|
+
type: 'complete',
|
|
164
|
+
data: {
|
|
165
|
+
fixed: false,
|
|
166
|
+
explanation: 'The issue could not be automatically resolved after 3 attempts.',
|
|
167
|
+
diagnosticReport: this.buildDiagnosticReport(),
|
|
168
|
+
}
|
|
169
|
+
});
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
// Re-observe
|
|
173
|
+
this.setState('observing');
|
|
174
|
+
this.progress(`\nš Round ${round}: Re-scanning system...`);
|
|
175
|
+
const mockScenario = global.__clawaid_mock;
|
|
176
|
+
let currentObsText;
|
|
177
|
+
try {
|
|
178
|
+
const currentObs = mockScenario
|
|
179
|
+
? (0, observe_1.loadMockObservation)(mockScenario)
|
|
180
|
+
: await (0, observe_1.observe)((msg) => this.progress(msg));
|
|
181
|
+
currentObsText = (0, observe_1.formatObservation)(currentObs);
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
this.progress(`Observation error: ${err.message}`);
|
|
185
|
+
currentObsText = this.context.originalObservationText || '';
|
|
186
|
+
}
|
|
187
|
+
// Re-diagnose
|
|
188
|
+
this.setState('diagnosing');
|
|
189
|
+
this.progress('š¤ AI is re-analyzing with attempt history...');
|
|
190
|
+
try {
|
|
191
|
+
const newDiagnosis = await (0, diagnose_1.diagnose)({
|
|
192
|
+
apiKey: this.context.apiKey,
|
|
193
|
+
observationData: currentObsText,
|
|
194
|
+
previousAttempts: this.context.attemptHistory,
|
|
195
|
+
round,
|
|
196
|
+
});
|
|
197
|
+
this.context.currentDiagnosis = newDiagnosis;
|
|
198
|
+
if (newDiagnosis.healthy && newDiagnosis.options.length === 0) {
|
|
199
|
+
this.progress('ā
' + (newDiagnosis.diagnosis || 'OpenClaw is running normally. No issues detected.'));
|
|
200
|
+
this.setState('healthy');
|
|
201
|
+
this.emit({ type: 'complete', data: { fixed: false, healthy: true, explanation: newDiagnosis.diagnosis, warnings: newDiagnosis.warnings || [], reasoning: newDiagnosis.reasoning || [] } });
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
this.emit({
|
|
205
|
+
type: 'diagnosis',
|
|
206
|
+
data: {
|
|
207
|
+
diagnosis: newDiagnosis.diagnosis,
|
|
208
|
+
confidence: newDiagnosis.confidence,
|
|
209
|
+
rootCause: newDiagnosis.rootCause,
|
|
210
|
+
reasoning: newDiagnosis.reasoning || [],
|
|
211
|
+
options: newDiagnosis.options,
|
|
212
|
+
alternativeHypotheses: newDiagnosis.alternativeHypotheses,
|
|
213
|
+
round,
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
// Round 3 = give up, just show report
|
|
217
|
+
if (round === 3) {
|
|
218
|
+
this.setState('not_fixed');
|
|
219
|
+
this.emit({
|
|
220
|
+
type: 'complete',
|
|
221
|
+
data: {
|
|
222
|
+
fixed: false,
|
|
223
|
+
explanation: 'The issue could not be automatically resolved after 3 attempts.',
|
|
224
|
+
diagnosticReport: this.buildDiagnosticReport(),
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// Always show options to user and wait for their choice
|
|
230
|
+
this.setState('showing_options');
|
|
231
|
+
this.context.roundNumber = round;
|
|
232
|
+
}
|
|
233
|
+
catch (err) {
|
|
234
|
+
this.progress(`ā AI analysis failed: ${err.message}`);
|
|
235
|
+
this.setState('error');
|
|
236
|
+
this.emit({ type: 'error', data: { message: err.message } });
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async executeOption(option) {
|
|
240
|
+
if (option.steps.length === 0) {
|
|
241
|
+
this.progress('ā ļø No steps in this option.');
|
|
242
|
+
return false;
|
|
243
|
+
}
|
|
244
|
+
const dryRun = Boolean(global.__clawaid_dry_run);
|
|
245
|
+
this.setState('auto_executing');
|
|
246
|
+
this.progress(`\nš§ ${dryRun ? '[DRY-RUN] ' : ''}Executing: ${option.title} (${option.steps.length} step${option.steps.length > 1 ? 's' : ''})...`);
|
|
247
|
+
const executeResult = await (0, execute_1.executeActions)(option.steps, (msg, result) => {
|
|
248
|
+
this.progress(msg);
|
|
249
|
+
if (result) {
|
|
250
|
+
this.emit({ type: 'action_result', data: result });
|
|
251
|
+
}
|
|
252
|
+
}, dryRun);
|
|
253
|
+
// Record this attempt
|
|
254
|
+
const attemptSummary = `
|
|
255
|
+
### Attempt ${this.context.roundNumber + 1} ā Option ${option.id}: ${option.title}
|
|
256
|
+
Diagnosis: ${this.context.currentDiagnosis?.diagnosis || ''}
|
|
257
|
+
Root cause: ${this.context.currentDiagnosis?.rootCause || ''}
|
|
258
|
+
Steps taken:
|
|
259
|
+
${(0, execute_1.formatExecuteResults)(executeResult.results)}
|
|
260
|
+
Result: ${executeResult.summary}
|
|
261
|
+
`.trim();
|
|
262
|
+
this.context.attemptHistory.push(attemptSummary);
|
|
263
|
+
this.context.roundNumber++;
|
|
264
|
+
// In dry-run mode, skip verification
|
|
265
|
+
if (dryRun) {
|
|
266
|
+
this.progress('\nā ļø DRY-RUN: Skipping verification (nothing was executed).');
|
|
267
|
+
this.emit({ type: 'verify_result', data: { fixed: false, explanation: 'Dry-run mode ā no changes made.' } });
|
|
268
|
+
return false;
|
|
269
|
+
}
|
|
270
|
+
// Verify
|
|
271
|
+
this.setState('verifying');
|
|
272
|
+
this.progress('\nš Verifying repair...');
|
|
273
|
+
try {
|
|
274
|
+
const verifyResult = await (0, verify_1.verify)(this.context.apiKey, this.context.originalObservationText || '', executeResult.results.map(r => `${r.action.command}: ${r.output}`), (msg) => this.progress(msg));
|
|
275
|
+
this.emit({
|
|
276
|
+
type: 'verify_result',
|
|
277
|
+
data: { fixed: verifyResult.fixed, explanation: verifyResult.explanation },
|
|
278
|
+
});
|
|
279
|
+
if (verifyResult.fixed) {
|
|
280
|
+
this.progress(`\nā
${verifyResult.explanation}`);
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
this.progress(`\nā ļø Not yet fixed: ${verifyResult.explanation}`);
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
catch (err) {
|
|
289
|
+
this.progress(`Verification error: ${err.message}`);
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
buildDiagnosticReport() {
|
|
294
|
+
return `
|
|
295
|
+
# ClawAid - Diagnostic Report
|
|
296
|
+
Generated: ${new Date().toISOString()}
|
|
297
|
+
|
|
298
|
+
## System State (Initial)
|
|
299
|
+
${this.context.originalObservationText || 'Not captured'}
|
|
300
|
+
|
|
301
|
+
## Repair Attempts (${this.context.attemptHistory.length} total)
|
|
302
|
+
${this.context.attemptHistory.join('\n\n---\n\n')}
|
|
303
|
+
|
|
304
|
+
## Summary
|
|
305
|
+
After ${this.context.roundNumber} repair round(s), the issue was not automatically resolved.
|
|
306
|
+
Please review the diagnostic data above and consult the OpenClaw community for assistance.
|
|
307
|
+
|
|
308
|
+
## Resources
|
|
309
|
+
- OpenClaw Discord: https://discord.gg/openclaw
|
|
310
|
+
- Run manually: openclaw doctor
|
|
311
|
+
- View logs: openclaw logs --follow
|
|
312
|
+
`.trim();
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
exports.DoctorLoop = DoctorLoop;
|
|
316
|
+
//# sourceMappingURL=loop.js.map
|