adhdev 0.6.19 → 0.6.22
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/dist/cli/index.js +246 -45
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +232 -44
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -362,9 +362,11 @@ var init_config = __esm({
|
|
|
362
362
|
recentWorkspaceActivity: [],
|
|
363
363
|
machineNickname: null,
|
|
364
364
|
machineId: void 0,
|
|
365
|
+
machineSecret: null,
|
|
365
366
|
cliHistory: [],
|
|
366
367
|
providerSettings: {},
|
|
367
|
-
ideSettings: {}
|
|
368
|
+
ideSettings: {},
|
|
369
|
+
disableUpstream: false
|
|
368
370
|
};
|
|
369
371
|
}
|
|
370
372
|
});
|
|
@@ -4990,6 +4992,15 @@ var init_handler = __esm({
|
|
|
4990
4992
|
return handleExtensionScript(this, args, "listModes");
|
|
4991
4993
|
case "set_extension_mode":
|
|
4992
4994
|
return handleExtensionScript(this, args, "setMode");
|
|
4995
|
+
// ─── Provider Auto-Fix / Clone (DevServer proxy) ──────────
|
|
4996
|
+
case "provider_auto_fix":
|
|
4997
|
+
return this.proxyDevServerPost(args, "auto-implement");
|
|
4998
|
+
case "provider_auto_fix_cancel":
|
|
4999
|
+
return this.proxyDevServerPost(args, "auto-implement/cancel");
|
|
5000
|
+
case "provider_auto_fix_status":
|
|
5001
|
+
return this.proxyDevServerGet(args, "auto-implement/status");
|
|
5002
|
+
case "provider_clone":
|
|
5003
|
+
return this.proxyDevServerScaffold(args);
|
|
4993
5004
|
default:
|
|
4994
5005
|
return { success: false, error: `Unknown command: ${cmd}` };
|
|
4995
5006
|
}
|
|
@@ -5017,6 +5028,95 @@ var init_handler = __esm({
|
|
|
5017
5028
|
}
|
|
5018
5029
|
return { success: false, error: "ProviderLoader not initialized" };
|
|
5019
5030
|
}
|
|
5031
|
+
// ─── DevServer HTTP proxy helpers ─────────────────
|
|
5032
|
+
// These bridge WS commands to the DevServer REST API (localhost:19280)
|
|
5033
|
+
async proxyDevServerPost(args, endpoint) {
|
|
5034
|
+
const { providerType, ...body } = args || {};
|
|
5035
|
+
if (!providerType) return { success: false, error: "providerType required" };
|
|
5036
|
+
try {
|
|
5037
|
+
const http3 = await import("http");
|
|
5038
|
+
const postData = JSON.stringify(body);
|
|
5039
|
+
const result = await new Promise((resolve8, reject) => {
|
|
5040
|
+
const req = http3.request({
|
|
5041
|
+
hostname: "127.0.0.1",
|
|
5042
|
+
port: 19280,
|
|
5043
|
+
path: `/api/providers/${providerType}/${endpoint}`,
|
|
5044
|
+
method: "POST",
|
|
5045
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(postData) }
|
|
5046
|
+
}, (res) => {
|
|
5047
|
+
let data = "";
|
|
5048
|
+
res.on("data", (chunk) => data += chunk);
|
|
5049
|
+
res.on("end", () => {
|
|
5050
|
+
try {
|
|
5051
|
+
resolve8(JSON.parse(data));
|
|
5052
|
+
} catch {
|
|
5053
|
+
resolve8({ raw: data });
|
|
5054
|
+
}
|
|
5055
|
+
});
|
|
5056
|
+
});
|
|
5057
|
+
req.on("error", reject);
|
|
5058
|
+
req.write(postData);
|
|
5059
|
+
req.end();
|
|
5060
|
+
});
|
|
5061
|
+
return { success: true, ...result };
|
|
5062
|
+
} catch (e) {
|
|
5063
|
+
return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
|
|
5064
|
+
}
|
|
5065
|
+
}
|
|
5066
|
+
async proxyDevServerGet(args, endpoint) {
|
|
5067
|
+
const { providerType } = args || {};
|
|
5068
|
+
if (!providerType) return { success: false, error: "providerType required" };
|
|
5069
|
+
try {
|
|
5070
|
+
const http3 = await import("http");
|
|
5071
|
+
const result = await new Promise((resolve8, reject) => {
|
|
5072
|
+
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
5073
|
+
let data = "";
|
|
5074
|
+
res.on("data", (chunk) => data += chunk);
|
|
5075
|
+
res.on("end", () => {
|
|
5076
|
+
try {
|
|
5077
|
+
resolve8(JSON.parse(data));
|
|
5078
|
+
} catch {
|
|
5079
|
+
resolve8({ raw: data });
|
|
5080
|
+
}
|
|
5081
|
+
});
|
|
5082
|
+
}).on("error", reject);
|
|
5083
|
+
});
|
|
5084
|
+
return { success: true, ...result };
|
|
5085
|
+
} catch (e) {
|
|
5086
|
+
return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
|
|
5087
|
+
}
|
|
5088
|
+
}
|
|
5089
|
+
async proxyDevServerScaffold(args) {
|
|
5090
|
+
try {
|
|
5091
|
+
const http3 = await import("http");
|
|
5092
|
+
const postData = JSON.stringify(args || {});
|
|
5093
|
+
const result = await new Promise((resolve8, reject) => {
|
|
5094
|
+
const req = http3.request({
|
|
5095
|
+
hostname: "127.0.0.1",
|
|
5096
|
+
port: 19280,
|
|
5097
|
+
path: "/api/scaffold",
|
|
5098
|
+
method: "POST",
|
|
5099
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(postData) }
|
|
5100
|
+
}, (res) => {
|
|
5101
|
+
let data = "";
|
|
5102
|
+
res.on("data", (chunk) => data += chunk);
|
|
5103
|
+
res.on("end", () => {
|
|
5104
|
+
try {
|
|
5105
|
+
resolve8(JSON.parse(data));
|
|
5106
|
+
} catch {
|
|
5107
|
+
resolve8({ raw: data });
|
|
5108
|
+
}
|
|
5109
|
+
});
|
|
5110
|
+
});
|
|
5111
|
+
req.on("error", reject);
|
|
5112
|
+
req.write(postData);
|
|
5113
|
+
req.end();
|
|
5114
|
+
});
|
|
5115
|
+
return { success: true, ...result };
|
|
5116
|
+
} catch (e) {
|
|
5117
|
+
return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
|
|
5118
|
+
}
|
|
5119
|
+
}
|
|
5020
5120
|
};
|
|
5021
5121
|
}
|
|
5022
5122
|
});
|
|
@@ -5036,6 +5136,7 @@ var init_provider_loader = __esm({
|
|
|
5036
5136
|
builtinDirs;
|
|
5037
5137
|
userDir;
|
|
5038
5138
|
upstreamDir;
|
|
5139
|
+
disableUpstream;
|
|
5039
5140
|
watchers = [];
|
|
5040
5141
|
logFn;
|
|
5041
5142
|
versionArchive = null;
|
|
@@ -5054,6 +5155,7 @@ var init_provider_loader = __esm({
|
|
|
5054
5155
|
}
|
|
5055
5156
|
this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
|
|
5056
5157
|
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
5158
|
+
this.disableUpstream = options?.disableUpstream ?? false;
|
|
5057
5159
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
5058
5160
|
}
|
|
5059
5161
|
log(msg) {
|
|
@@ -5070,11 +5172,13 @@ var init_provider_loader = __esm({
|
|
|
5070
5172
|
loadAll() {
|
|
5071
5173
|
this.providers.clear();
|
|
5072
5174
|
let upstreamCount = 0;
|
|
5073
|
-
if (fs5.existsSync(this.upstreamDir)) {
|
|
5175
|
+
if (!this.disableUpstream && fs5.existsSync(this.upstreamDir)) {
|
|
5074
5176
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
5075
5177
|
if (upstreamCount > 0) {
|
|
5076
5178
|
this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
|
|
5077
5179
|
}
|
|
5180
|
+
} else if (this.disableUpstream) {
|
|
5181
|
+
this.log("Upstream loading disabled (disableUpstream=true)");
|
|
5078
5182
|
}
|
|
5079
5183
|
if (fs5.existsSync(this.userDir)) {
|
|
5080
5184
|
const userCount = this.loadDir(this.userDir, [".upstream"]);
|
|
@@ -5477,6 +5581,10 @@ var init_provider_loader = __esm({
|
|
|
5477
5581
|
* @returns Whether an update occurred
|
|
5478
5582
|
*/
|
|
5479
5583
|
async fetchLatest() {
|
|
5584
|
+
if (this.disableUpstream) {
|
|
5585
|
+
this.log("Upstream fetch skipped (disableUpstream=true)");
|
|
5586
|
+
return { updated: false };
|
|
5587
|
+
}
|
|
5480
5588
|
const https = require("https");
|
|
5481
5589
|
const { execSync: execSync7 } = require("child_process");
|
|
5482
5590
|
const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
@@ -6815,12 +6923,6 @@ var init_reporter = __esm({
|
|
|
6815
6923
|
emitStatusEvent(event) {
|
|
6816
6924
|
LOG.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
|
|
6817
6925
|
this.deps.serverConn?.sendMessage("status_event", event);
|
|
6818
|
-
if (this.deps.p2p?.isConnected) {
|
|
6819
|
-
try {
|
|
6820
|
-
this.deps.p2p.sendStatusEvent?.(event);
|
|
6821
|
-
} catch {
|
|
6822
|
-
}
|
|
6823
|
-
}
|
|
6824
6926
|
}
|
|
6825
6927
|
removeAgentTracking(_key) {
|
|
6826
6928
|
}
|
|
@@ -6898,6 +7000,7 @@ var init_reporter = __esm({
|
|
|
6898
7000
|
peers: p2p?.connectedPeerCount || 0,
|
|
6899
7001
|
screenshotActive: p2p?.screenshotActive || false
|
|
6900
7002
|
},
|
|
7003
|
+
screenshotUsage: this.deps.getScreenshotUsage?.() || null,
|
|
6901
7004
|
connectedExtensions: [],
|
|
6902
7005
|
detectedIdes: this.deps.detectedIdes || [],
|
|
6903
7006
|
availableProviders: this.deps.providerLoader.getAll().map((p) => ({
|
|
@@ -28411,7 +28514,7 @@ var init_dev_server = __esm({
|
|
|
28411
28514
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
28412
28515
|
async handleAutoImplement(type, req, res) {
|
|
28413
28516
|
const body = await this.readBody(req);
|
|
28414
|
-
const { agent = "claude-cli", functions, reference = "antigravity", model } = body;
|
|
28517
|
+
const { agent = "claude-cli", functions, reference = "antigravity", model, comment } = body;
|
|
28415
28518
|
if (!functions || !Array.isArray(functions) || functions.length === 0) {
|
|
28416
28519
|
this.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
|
|
28417
28520
|
return;
|
|
@@ -28460,7 +28563,7 @@ var init_dev_server = __esm({
|
|
|
28460
28563
|
}
|
|
28461
28564
|
}
|
|
28462
28565
|
}
|
|
28463
|
-
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts);
|
|
28566
|
+
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment);
|
|
28464
28567
|
const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
|
|
28465
28568
|
if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
|
|
28466
28569
|
const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
@@ -28643,6 +28746,7 @@ var init_dev_server = __esm({
|
|
|
28643
28746
|
}
|
|
28644
28747
|
this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "spawning", message: `\uC5D0\uC774\uC804\uD2B8 \uC2E4\uD589 \uC911: ${shellCmd.substring(0, 200)}... (prompt: ${prompt.length} chars)` } });
|
|
28645
28748
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
28749
|
+
const spawnedAt = Date.now();
|
|
28646
28750
|
let child;
|
|
28647
28751
|
let isPty = false;
|
|
28648
28752
|
const { spawn: spawnFn } = await import("child_process");
|
|
@@ -28695,8 +28799,9 @@ var init_dev_server = __esm({
|
|
|
28695
28799
|
const checkAutoApproval = (chunk, writeFn) => {
|
|
28696
28800
|
const cleanData = chunk.replace(/\x1B\[\d*[A-HJKSTfG]/g, " ").replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "").replace(/\x1B\][^\x07]*\x07/g, "").replace(/\x1B\][^\x1B]*\x1B\\/g, "").replace(/ +/g, " ");
|
|
28697
28801
|
approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
|
|
28698
|
-
|
|
28699
|
-
|
|
28802
|
+
const elapsed = Date.now() - spawnedAt;
|
|
28803
|
+
if (elapsed > 15e3 && approvalBuffer.includes("AUTO_IMPLEMENT_FINISHED")) {
|
|
28804
|
+
this.log(`Agent finished task after ${Math.round(elapsed / 1e3)}s. Terminating interactive CLI session to unblock pipeline.`);
|
|
28700
28805
|
this.sendAutoImplSSE({ event: "output", data: { chunk: `
|
|
28701
28806
|
[\u{1F916} ADHDev Pipeline] Completion token detected. Proceeding...
|
|
28702
28807
|
`, stream: "stdout" } });
|
|
@@ -28798,7 +28903,7 @@ var init_dev_server = __esm({
|
|
|
28798
28903
|
this.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
28799
28904
|
}
|
|
28800
28905
|
}
|
|
28801
|
-
buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts) {
|
|
28906
|
+
buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, userComment) {
|
|
28802
28907
|
const lines = [];
|
|
28803
28908
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
28804
28909
|
lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
|
|
@@ -28910,6 +29015,22 @@ var init_dev_server = __esm({
|
|
|
28910
29015
|
lines.push("| focusEditor | `{ focused: true/false }` |");
|
|
28911
29016
|
lines.push("| openPanel | `{ opened: true/false }` |");
|
|
28912
29017
|
lines.push("");
|
|
29018
|
+
lines.push("## \u{1F534} CRITICAL: readChat `status` Lifecycle");
|
|
29019
|
+
lines.push("The `status` field in readChat controls how the dashboard and daemon auto-approve-loop behave.");
|
|
29020
|
+
lines.push("Getting this wrong will break the entire automation pipeline. The status MUST reflect the ACTUAL current state:");
|
|
29021
|
+
lines.push("");
|
|
29022
|
+
lines.push("| Status | When to use | How to detect |");
|
|
29023
|
+
lines.push("|---|---|---|");
|
|
29024
|
+
lines.push("| `idle` | AI is NOT generating, no approval needed | Default state. No stop button, no spinners, no approval pills/buttons |");
|
|
29025
|
+
lines.push("| `generating` | AI is actively streaming/thinking | ANY of: (1) Stop/Cancel button visible, (2) CSS animation (animate-spin/pulse/bounce), (3) floating state text like Thinking/Generating/Sailing, (4) streaming indicator class |");
|
|
29026
|
+
lines.push("| `waiting_approval` | AI stopped and needs user action | Actionable buttons like Run/Skip/Accept/Reject are visible AND clickable |");
|
|
29027
|
+
lines.push("");
|
|
29028
|
+
lines.push("### \u26A0\uFE0F Status Detection Gotchas (MUST READ!)");
|
|
29029
|
+
lines.push('1. **FALSE POSITIVES from old messages**: Chat history may contain text like "Command Awaiting Approval" from PAST turns. If you search the entire chat panel for this text, you will get false matches from parent divs whose innerText includes ALL child text. ONLY match small leaf elements (under 80 chars) or use explicit button/pill selectors.');
|
|
29030
|
+
lines.push('2. **Awaiting Approval pill without actions**: Some IDEs show a floating pill/banner saying "Awaiting Approval" that is just a scroll-to indicator (not an actual approval dialog). If this pill exists but NO actionable buttons (Run/Skip/Accept/Reject) exist anywhere in the panel, the status should be `idle`, NOT `waiting_approval`.');
|
|
29031
|
+
lines.push("3. **generating detection must be multi-signal**: Do NOT rely on just one indicator. Check ALL of: stop buttons, CSS animations, floating state labels, streaming classes. IDEs differ widely.");
|
|
29032
|
+
lines.push("4. **activeModal must include actions**: When `status` is `waiting_approval`, the `activeModal` object MUST include a non-empty `actions` array listing the button labels. If you cannot find any action buttons, the status is NOT `waiting_approval`.");
|
|
29033
|
+
lines.push("");
|
|
28913
29034
|
lines.push("## Action");
|
|
28914
29035
|
lines.push("1. Edit the script files to implement working code");
|
|
28915
29036
|
lines.push("2. After editing, TEST each function using the DevConsole API (see below)");
|
|
@@ -28934,7 +29055,7 @@ var init_dev_server = __esm({
|
|
|
28934
29055
|
lines.push("Once you save the file, test it by running:");
|
|
28935
29056
|
lines.push("```bash");
|
|
28936
29057
|
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
28937
|
-
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/
|
|
29058
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}'`);
|
|
28938
29059
|
lines.push("```");
|
|
28939
29060
|
lines.push("");
|
|
28940
29061
|
lines.push("### Task Workflow");
|
|
@@ -28946,12 +29067,51 @@ var init_dev_server = __esm({
|
|
|
28946
29067
|
lines.push("### \u{1F525} Advanced UI Parsing (CRUCIAL for `readChat`)");
|
|
28947
29068
|
lines.push("Your `readChat` must flawlessly parse complex UI elements (tables, code blocks, tool calls, and AI thoughts). The quality must match the `antigravity` reference.");
|
|
28948
29069
|
lines.push("To achieve this, you MUST generate a live test scenario:");
|
|
28949
|
-
lines.push(
|
|
28950
|
-
lines.push(
|
|
29070
|
+
lines.push(`1. Early in your process, send a rich prompt to the IDE using the API:`);
|
|
29071
|
+
lines.push(` \`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "sendMessage", "type": "${type}", "ideType": "${type}", "args": {"message": "Write a python script, draw a markdown table, use a tool, and show your reasoning/thought process"}}'\``);
|
|
28951
29072
|
lines.push("2. Wait a few seconds for the IDE AI to generate these elements in the UI.");
|
|
28952
29073
|
lines.push("3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.");
|
|
28953
29074
|
lines.push("4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).");
|
|
28954
29075
|
lines.push("");
|
|
29076
|
+
lines.push("## \u{1F9EA} MANDATORY: Status Integration Test");
|
|
29077
|
+
lines.push("Before finishing, you MUST run this end-to-end test to verify readChat status transitions work:");
|
|
29078
|
+
lines.push("");
|
|
29079
|
+
lines.push("### Step 1: Baseline \u2014 confirm idle");
|
|
29080
|
+
lines.push("```bash");
|
|
29081
|
+
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
29082
|
+
lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}')`);
|
|
29083
|
+
lines.push(`echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); r=d.get('result',d); r=json.loads(r) if isinstance(r,str) else r; assert r.get('status')=='idle', f'Expected idle, got {r.get(chr(34)+chr(115)+chr(116)+chr(97)+chr(116)+chr(117)+chr(115)+chr(34))}'; print('Step 1 PASS: status=idle')"`);
|
|
29084
|
+
lines.push("```");
|
|
29085
|
+
lines.push("");
|
|
29086
|
+
lines.push("### Step 2: Send a message that triggers generation");
|
|
29087
|
+
lines.push("```bash");
|
|
29088
|
+
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "sendMessage", "type": "${type}", "ideType": "${type}", "args": {"message": "Say hello in one word"}}'`);
|
|
29089
|
+
lines.push("sleep 2");
|
|
29090
|
+
lines.push("```");
|
|
29091
|
+
lines.push("");
|
|
29092
|
+
lines.push("### Step 3: Check generating OR completed");
|
|
29093
|
+
lines.push("The AI may still be generating OR may have finished already. Either generating or idle is acceptable:");
|
|
29094
|
+
lines.push("```bash");
|
|
29095
|
+
lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}')`);
|
|
29096
|
+
lines.push(`echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); r=d.get('result',d); r=json.loads(r) if isinstance(r,str) else r; s=r.get('status'); assert s in ('generating','idle','waiting_approval'), f'Unexpected: {s}'; print(f'Step 3 PASS: status={s}')"`);
|
|
29097
|
+
lines.push("```");
|
|
29098
|
+
lines.push("");
|
|
29099
|
+
lines.push("### Step 4: Wait for completion and verify new message");
|
|
29100
|
+
lines.push("```bash");
|
|
29101
|
+
lines.push("sleep 10");
|
|
29102
|
+
lines.push(`RESULT=$(curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/scripts/run -H "Content-Type: application/json" -d '{"script": "readChat", "type": "${type}", "ideType": "${type}"}')`);
|
|
29103
|
+
lines.push(`echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); r=d.get('result',d); r=json.loads(r) if isinstance(r,str) else r; s=r.get('status'); msgs=r.get('messages',[]); assert s=='idle', f'Expected idle, got {s}'; assert len(msgs)>0, 'No messages'; print(f'Step 4 PASS: status={s}, messages={len(msgs)}')"`);
|
|
29104
|
+
lines.push("```");
|
|
29105
|
+
lines.push("");
|
|
29106
|
+
lines.push("If ANY step fails, fix your implementation and re-run the test. Do NOT finish until all 4 steps pass.");
|
|
29107
|
+
lines.push("");
|
|
29108
|
+
if (userComment) {
|
|
29109
|
+
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
29110
|
+
lines.push("The user has provided the following additional instructions. Follow them strictly:");
|
|
29111
|
+
lines.push("");
|
|
29112
|
+
lines.push(userComment);
|
|
29113
|
+
lines.push("");
|
|
29114
|
+
}
|
|
28955
29115
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
28956
29116
|
return lines.join("\n");
|
|
28957
29117
|
}
|
|
@@ -29476,10 +29636,13 @@ var init_installer = __esm({
|
|
|
29476
29636
|
// ../daemon-core/src/boot/daemon-lifecycle.ts
|
|
29477
29637
|
async function initDaemonComponents(config2) {
|
|
29478
29638
|
installGlobalInterceptor();
|
|
29639
|
+
const appConfig = loadConfig();
|
|
29640
|
+
const disableUpstream = appConfig.disableUpstream ?? false;
|
|
29479
29641
|
const providerLoader = new ProviderLoader({
|
|
29480
|
-
logFn: config2.providerLogFn
|
|
29642
|
+
logFn: config2.providerLogFn,
|
|
29643
|
+
disableUpstream
|
|
29481
29644
|
});
|
|
29482
|
-
if (!providerLoader.hasUpstream()) {
|
|
29645
|
+
if (!disableUpstream && !providerLoader.hasUpstream()) {
|
|
29483
29646
|
LOG.info("Provider", "No upstream providers found \u2014 downloading from GitHub...");
|
|
29484
29647
|
try {
|
|
29485
29648
|
await providerLoader.fetchLatest();
|
|
@@ -30514,24 +30677,6 @@ ${e?.stack || ""}`);
|
|
|
30514
30677
|
}
|
|
30515
30678
|
return sentAny;
|
|
30516
30679
|
}
|
|
30517
|
-
/** Send status_event directly via P2P (generating_started/completed etc.) */
|
|
30518
|
-
sendStatusEvent(event) {
|
|
30519
|
-
const payload = JSON.stringify({
|
|
30520
|
-
type: "status_event",
|
|
30521
|
-
payload: event,
|
|
30522
|
-
timestamp: Date.now()
|
|
30523
|
-
});
|
|
30524
|
-
let sentAny = false;
|
|
30525
|
-
for (const peer of this.peers.values()) {
|
|
30526
|
-
if (peer.state !== "connected" || !peer.dataChannel) continue;
|
|
30527
|
-
try {
|
|
30528
|
-
peer.dataChannel.sendMessage(payload);
|
|
30529
|
-
sentAny = true;
|
|
30530
|
-
} catch {
|
|
30531
|
-
}
|
|
30532
|
-
}
|
|
30533
|
-
return sentAny;
|
|
30534
|
-
}
|
|
30535
30680
|
/** Broadcast PTY output to all connected peers */
|
|
30536
30681
|
broadcastPtyOutput(cliType, data) {
|
|
30537
30682
|
const prev = this.ptyScrollback.get(cliType) || "";
|
|
@@ -30940,6 +31085,15 @@ var init_screenshot_controller = __esm({
|
|
|
30940
31085
|
LOG.info("Screenshot", `Daily budget reset (${this.dailyBudgetMinutes}min for today)`);
|
|
30941
31086
|
}
|
|
30942
31087
|
}
|
|
31088
|
+
/** Returns current usage stats for reporting to server/dashboard */
|
|
31089
|
+
getUsageStats() {
|
|
31090
|
+
this.checkBudgetReset();
|
|
31091
|
+
return {
|
|
31092
|
+
dailyUsedMinutes: Math.round(this.dailyUsedMs / 6e4),
|
|
31093
|
+
dailyBudgetMinutes: this.dailyBudgetMinutes,
|
|
31094
|
+
budgetExhausted: this.budgetExhausted
|
|
31095
|
+
};
|
|
31096
|
+
}
|
|
30943
31097
|
// ─── Hash ─────────────────────────────────────
|
|
30944
31098
|
/** FNV-1a hash of first 1KB + last 1KB for fast delta detection */
|
|
30945
31099
|
static fnvHash(buf) {
|
|
@@ -31020,7 +31174,7 @@ var init_adhdev_daemon = __esm({
|
|
|
31020
31174
|
fs11 = __toESM(require("fs"));
|
|
31021
31175
|
path14 = __toESM(require("path"));
|
|
31022
31176
|
import_chalk2 = __toESM(require("chalk"));
|
|
31023
|
-
pkgVersion = "0.6.
|
|
31177
|
+
pkgVersion = "0.6.22";
|
|
31024
31178
|
if (pkgVersion === "unknown") {
|
|
31025
31179
|
try {
|
|
31026
31180
|
const possiblePaths = [
|
|
@@ -31087,8 +31241,9 @@ ${err?.stack || ""}`);
|
|
|
31087
31241
|
}
|
|
31088
31242
|
writeDaemonPid(process.pid);
|
|
31089
31243
|
const config2 = loadConfig();
|
|
31090
|
-
|
|
31091
|
-
|
|
31244
|
+
const authToken = config2.machineSecret || config2.connectionToken;
|
|
31245
|
+
if (!authToken) {
|
|
31246
|
+
console.log(import_chalk2.default.red("\n\u2717 No credentials found."));
|
|
31092
31247
|
console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
|
|
31093
31248
|
process.exit(1);
|
|
31094
31249
|
}
|
|
@@ -31138,7 +31293,7 @@ ${err?.stack || ""}`);
|
|
|
31138
31293
|
const instanceId = `daemon_${config2.machineId}`;
|
|
31139
31294
|
this.serverConn = new ServerConnection({
|
|
31140
31295
|
serverUrl: options.serverUrl || config2.serverUrl,
|
|
31141
|
-
token:
|
|
31296
|
+
token: authToken,
|
|
31142
31297
|
daemonVersion: pkgVersion,
|
|
31143
31298
|
cliInfo: {
|
|
31144
31299
|
type: "adhdev-daemon",
|
|
@@ -31230,7 +31385,8 @@ ${err?.stack || ""}`);
|
|
|
31230
31385
|
detectedIdes: this.components.detectedIdes.value,
|
|
31231
31386
|
ideType: this.ideType,
|
|
31232
31387
|
daemonVersion: pkgVersion,
|
|
31233
|
-
instanceManager: this.components.instanceManager
|
|
31388
|
+
instanceManager: this.components.instanceManager,
|
|
31389
|
+
getScreenshotUsage: () => this.screenshotController?.getUsageStats() || null
|
|
31234
31390
|
});
|
|
31235
31391
|
this.statusReporter.startReporting();
|
|
31236
31392
|
this.components.instanceManager.onEvent((event) => {
|
|
@@ -31508,11 +31664,17 @@ async function quickSetup() {
|
|
|
31508
31664
|
}
|
|
31509
31665
|
markSetupComplete(["daemon"], ["adhdev"]);
|
|
31510
31666
|
if (loginResult) {
|
|
31511
|
-
|
|
31667
|
+
const configUpdate = {
|
|
31512
31668
|
connectionToken: loginResult.connectionToken,
|
|
31513
31669
|
userEmail: loginResult.email,
|
|
31514
31670
|
userName: loginResult.name
|
|
31515
|
-
}
|
|
31671
|
+
};
|
|
31672
|
+
if (loginResult.machineId && loginResult.machineSecret) {
|
|
31673
|
+
configUpdate.machineId = loginResult.machineId;
|
|
31674
|
+
configUpdate.machineSecret = loginResult.machineSecret;
|
|
31675
|
+
console.log(import_chalk3.default.green(` \u2713 Machine registered`));
|
|
31676
|
+
}
|
|
31677
|
+
updateConfig(configUpdate);
|
|
31516
31678
|
}
|
|
31517
31679
|
await installCliOnly();
|
|
31518
31680
|
await startDaemonFlow();
|
|
@@ -31548,7 +31710,16 @@ async function loginFlow() {
|
|
|
31548
31710
|
let userCode;
|
|
31549
31711
|
let verificationUrl;
|
|
31550
31712
|
try {
|
|
31551
|
-
const
|
|
31713
|
+
const os17 = await import("os");
|
|
31714
|
+
const res = await fetch(`${SERVER_URL}/auth/cli/init`, {
|
|
31715
|
+
method: "POST",
|
|
31716
|
+
headers: { "Content-Type": "application/json" },
|
|
31717
|
+
body: JSON.stringify({
|
|
31718
|
+
hostname: os17.hostname(),
|
|
31719
|
+
platform: os17.platform(),
|
|
31720
|
+
arch: os17.arch()
|
|
31721
|
+
})
|
|
31722
|
+
});
|
|
31552
31723
|
if (!res.ok) {
|
|
31553
31724
|
spinner.fail("Failed to connect to server");
|
|
31554
31725
|
return null;
|
|
@@ -31595,10 +31766,27 @@ async function loginFlow() {
|
|
|
31595
31766
|
pollSpinner.succeed(`Authenticated as ${import_chalk3.default.bold(data.user?.email || "user")}`);
|
|
31596
31767
|
return {
|
|
31597
31768
|
connectionToken: data.connectionToken,
|
|
31769
|
+
machineId: data.machineId || void 0,
|
|
31770
|
+
machineSecret: data.machineSecret || void 0,
|
|
31598
31771
|
email: data.user?.email,
|
|
31599
31772
|
name: data.user?.name
|
|
31600
31773
|
};
|
|
31601
31774
|
}
|
|
31775
|
+
if (data.status === "limit_reached") {
|
|
31776
|
+
pollSpinner.fail("Machine limit reached");
|
|
31777
|
+
console.log();
|
|
31778
|
+
console.log(import_chalk3.default.red(` \u2717 Your ${import_chalk3.default.bold(data.plan || "free")} plan allows ${data.limit} machine(s), and you have ${data.current} registered.`));
|
|
31779
|
+
console.log();
|
|
31780
|
+
console.log(import_chalk3.default.yellow(" To fix this, do one of the following:"));
|
|
31781
|
+
console.log(import_chalk3.default.gray(" 1. Remove an unused machine from the dashboard:"));
|
|
31782
|
+
console.log(import_chalk3.default.gray(" https://adhf.dev/account \u2192 Registered Machines \u2192 \u2715 Remove"));
|
|
31783
|
+
console.log(import_chalk3.default.gray(" 2. Upgrade your plan:"));
|
|
31784
|
+
console.log(import_chalk3.default.gray(" https://adhf.dev/account?tab=billing"));
|
|
31785
|
+
console.log();
|
|
31786
|
+
console.log(import_chalk3.default.gray(" Then run `adhdev setup` again."));
|
|
31787
|
+
console.log();
|
|
31788
|
+
return null;
|
|
31789
|
+
}
|
|
31602
31790
|
} catch {
|
|
31603
31791
|
}
|
|
31604
31792
|
}
|
|
@@ -32619,7 +32807,7 @@ function registerProviderCommands(program2) {
|
|
|
32619
32807
|
process.exit(1);
|
|
32620
32808
|
}
|
|
32621
32809
|
});
|
|
32622
|
-
provider.command("fix [type] [scripts...]").description("Auto-implement provider scripts using AI reading the target IDE DOM").option("-a, --agent <agent>", "AI agent to use (e.g. claude-cli, gemini-cli, codex-cli, or any ACP provider like cline-acp)", "codex-cli").option("-m, --model <model>", "Model override (e.g. claude-sonnet-3.5, gemini-2.0-pro)").option("-r, --reference <ref>", "Reference provider to learn from", "antigravity").action(async (typeArg, scripts, options) => {
|
|
32810
|
+
provider.command("fix [type] [scripts...]").description("Auto-implement provider scripts using AI reading the target IDE DOM").option("-a, --agent <agent>", "AI agent to use (e.g. claude-cli, gemini-cli, codex-cli, or any ACP provider like cline-acp)", "codex-cli").option("-m, --model <model>", "Model override (e.g. claude-sonnet-3.5, gemini-2.0-pro)").option("-r, --reference <ref>", "Reference provider to learn from", "antigravity").option("-c, --comment <text>", 'Additional instructions for the AI agent (e.g. "focus on shadow DOM handling")').action(async (typeArg, scripts, options) => {
|
|
32623
32811
|
try {
|
|
32624
32812
|
const http3 = await import("http");
|
|
32625
32813
|
const inquirer2 = (await import("inquirer")).default;
|
|
@@ -32749,14 +32937,27 @@ function registerProviderCommands(program2) {
|
|
|
32749
32937
|
process.exit(0);
|
|
32750
32938
|
}
|
|
32751
32939
|
}
|
|
32940
|
+
let userComment = options.comment || "";
|
|
32941
|
+
if (!typeArg && !userComment) {
|
|
32942
|
+
const commentAnswer = await inquirer2.prompt([{
|
|
32943
|
+
type: "input",
|
|
32944
|
+
name: "comment",
|
|
32945
|
+
message: "Additional instructions for the agent (press Enter to skip):"
|
|
32946
|
+
}]);
|
|
32947
|
+
userComment = commentAnswer.comment || "";
|
|
32948
|
+
}
|
|
32752
32949
|
let consecutiveFailures = 0;
|
|
32753
32950
|
console.log(import_chalk6.default.bold(`
|
|
32754
32951
|
\u25B6\uFE0F Generating [${functionsToFix.length}] function(s) natively via autonomous agent for ${type}...`));
|
|
32952
|
+
if (userComment) {
|
|
32953
|
+
console.log(import_chalk6.default.gray(` \u{1F4AC} Comment: ${userComment}`));
|
|
32954
|
+
}
|
|
32755
32955
|
try {
|
|
32756
32956
|
const postData = JSON.stringify({
|
|
32757
32957
|
functions: functionsToFix,
|
|
32758
32958
|
agent: agentName,
|
|
32759
32959
|
...modelName ? { model: modelName } : {},
|
|
32960
|
+
...userComment ? { comment: userComment } : {},
|
|
32760
32961
|
reference
|
|
32761
32962
|
});
|
|
32762
32963
|
const startResult = await new Promise((resolve8, reject) => {
|