@adhdev/daemon-core 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/index.d.ts +13 -1
- package/dist/index.js +181 -18
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/boot/daemon-lifecycle.ts +5 -2
- package/src/commands/handler.ts +85 -0
- package/src/config/config.ts +9 -0
- package/src/daemon/dev-server.ts +72 -8
- package/src/providers/provider-loader.ts +11 -1
- package/src/status/reporter.ts +3 -8
package/dist/index.d.ts
CHANGED
|
@@ -168,6 +168,7 @@ interface ADHDevConfig {
|
|
|
168
168
|
recentWorkspaceActivity?: WorkspaceActivityEntry[];
|
|
169
169
|
machineNickname: string | null;
|
|
170
170
|
machineId?: string;
|
|
171
|
+
machineSecret?: string | null;
|
|
171
172
|
cliHistory: CliHistoryEntry[];
|
|
172
173
|
providerSettings: Record<string, Record<string, any>>;
|
|
173
174
|
ideSettings: Record<string, {
|
|
@@ -175,6 +176,7 @@ interface ADHDevConfig {
|
|
|
175
176
|
enabled: boolean;
|
|
176
177
|
}>;
|
|
177
178
|
}>;
|
|
179
|
+
disableUpstream?: boolean;
|
|
178
180
|
}
|
|
179
181
|
interface CliHistoryEntry {
|
|
180
182
|
cliType: string;
|
|
@@ -957,6 +959,7 @@ declare class ProviderLoader {
|
|
|
957
959
|
private builtinDirs;
|
|
958
960
|
private userDir;
|
|
959
961
|
private upstreamDir;
|
|
962
|
+
private disableUpstream;
|
|
960
963
|
private watchers;
|
|
961
964
|
private logFn;
|
|
962
965
|
private versionArchive;
|
|
@@ -969,6 +972,8 @@ declare class ProviderLoader {
|
|
|
969
972
|
builtinDir?: string | string[];
|
|
970
973
|
userDir?: string;
|
|
971
974
|
logFn?: (msg: string) => void;
|
|
975
|
+
/** Disable upstream auto-download (for dev/testing/OSS) */
|
|
976
|
+
disableUpstream?: boolean;
|
|
972
977
|
});
|
|
973
978
|
private log;
|
|
974
979
|
/**
|
|
@@ -1720,6 +1725,9 @@ declare class DaemonCommandHandler implements CommandHelpers {
|
|
|
1720
1725
|
private dispatch;
|
|
1721
1726
|
private handleGetRecentWorkspaces;
|
|
1722
1727
|
private handleRefreshScripts;
|
|
1728
|
+
private proxyDevServerPost;
|
|
1729
|
+
private proxyDevServerGet;
|
|
1730
|
+
private proxyDevServerScaffold;
|
|
1723
1731
|
}
|
|
1724
1732
|
|
|
1725
1733
|
/**
|
|
@@ -2199,7 +2207,6 @@ interface StatusReporterDeps {
|
|
|
2199
2207
|
connectedPeerCount: number;
|
|
2200
2208
|
screenshotActive: boolean;
|
|
2201
2209
|
sendStatus(data: any): void;
|
|
2202
|
-
sendStatusEvent?(event: Record<string, unknown>): boolean;
|
|
2203
2210
|
} | null;
|
|
2204
2211
|
providerLoader: {
|
|
2205
2212
|
resolve(type: string): any;
|
|
@@ -2219,6 +2226,11 @@ interface StatusReporterDeps {
|
|
|
2219
2226
|
collectAllStates(): ProviderState[];
|
|
2220
2227
|
collectStatesByCategory(cat: string): ProviderState[];
|
|
2221
2228
|
};
|
|
2229
|
+
getScreenshotUsage?: () => {
|
|
2230
|
+
dailyUsedMinutes: number;
|
|
2231
|
+
dailyBudgetMinutes: number;
|
|
2232
|
+
budgetExhausted: boolean;
|
|
2233
|
+
} | null;
|
|
2222
2234
|
}
|
|
2223
2235
|
declare class DaemonStatusReporter {
|
|
2224
2236
|
private deps;
|
package/dist/index.js
CHANGED
|
@@ -361,9 +361,11 @@ var init_config = __esm({
|
|
|
361
361
|
recentWorkspaceActivity: [],
|
|
362
362
|
machineNickname: null,
|
|
363
363
|
machineId: void 0,
|
|
364
|
+
machineSecret: null,
|
|
364
365
|
cliHistory: [],
|
|
365
366
|
providerSettings: {},
|
|
366
|
-
ideSettings: {}
|
|
367
|
+
ideSettings: {},
|
|
368
|
+
disableUpstream: false
|
|
367
369
|
};
|
|
368
370
|
}
|
|
369
371
|
});
|
|
@@ -5573,6 +5575,15 @@ var DaemonCommandHandler = class {
|
|
|
5573
5575
|
return handleExtensionScript(this, args, "listModes");
|
|
5574
5576
|
case "set_extension_mode":
|
|
5575
5577
|
return handleExtensionScript(this, args, "setMode");
|
|
5578
|
+
// ─── Provider Auto-Fix / Clone (DevServer proxy) ──────────
|
|
5579
|
+
case "provider_auto_fix":
|
|
5580
|
+
return this.proxyDevServerPost(args, "auto-implement");
|
|
5581
|
+
case "provider_auto_fix_cancel":
|
|
5582
|
+
return this.proxyDevServerPost(args, "auto-implement/cancel");
|
|
5583
|
+
case "provider_auto_fix_status":
|
|
5584
|
+
return this.proxyDevServerGet(args, "auto-implement/status");
|
|
5585
|
+
case "provider_clone":
|
|
5586
|
+
return this.proxyDevServerScaffold(args);
|
|
5576
5587
|
default:
|
|
5577
5588
|
return { success: false, error: `Unknown command: ${cmd}` };
|
|
5578
5589
|
}
|
|
@@ -5600,6 +5611,95 @@ var DaemonCommandHandler = class {
|
|
|
5600
5611
|
}
|
|
5601
5612
|
return { success: false, error: "ProviderLoader not initialized" };
|
|
5602
5613
|
}
|
|
5614
|
+
// ─── DevServer HTTP proxy helpers ─────────────────
|
|
5615
|
+
// These bridge WS commands to the DevServer REST API (localhost:19280)
|
|
5616
|
+
async proxyDevServerPost(args, endpoint) {
|
|
5617
|
+
const { providerType, ...body } = args || {};
|
|
5618
|
+
if (!providerType) return { success: false, error: "providerType required" };
|
|
5619
|
+
try {
|
|
5620
|
+
const http3 = await import("http");
|
|
5621
|
+
const postData = JSON.stringify(body);
|
|
5622
|
+
const result = await new Promise((resolve8, reject) => {
|
|
5623
|
+
const req = http3.request({
|
|
5624
|
+
hostname: "127.0.0.1",
|
|
5625
|
+
port: 19280,
|
|
5626
|
+
path: `/api/providers/${providerType}/${endpoint}`,
|
|
5627
|
+
method: "POST",
|
|
5628
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(postData) }
|
|
5629
|
+
}, (res) => {
|
|
5630
|
+
let data = "";
|
|
5631
|
+
res.on("data", (chunk) => data += chunk);
|
|
5632
|
+
res.on("end", () => {
|
|
5633
|
+
try {
|
|
5634
|
+
resolve8(JSON.parse(data));
|
|
5635
|
+
} catch {
|
|
5636
|
+
resolve8({ raw: data });
|
|
5637
|
+
}
|
|
5638
|
+
});
|
|
5639
|
+
});
|
|
5640
|
+
req.on("error", reject);
|
|
5641
|
+
req.write(postData);
|
|
5642
|
+
req.end();
|
|
5643
|
+
});
|
|
5644
|
+
return { success: true, ...result };
|
|
5645
|
+
} catch (e) {
|
|
5646
|
+
return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
|
|
5647
|
+
}
|
|
5648
|
+
}
|
|
5649
|
+
async proxyDevServerGet(args, endpoint) {
|
|
5650
|
+
const { providerType } = args || {};
|
|
5651
|
+
if (!providerType) return { success: false, error: "providerType required" };
|
|
5652
|
+
try {
|
|
5653
|
+
const http3 = await import("http");
|
|
5654
|
+
const result = await new Promise((resolve8, reject) => {
|
|
5655
|
+
http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
|
|
5656
|
+
let data = "";
|
|
5657
|
+
res.on("data", (chunk) => data += chunk);
|
|
5658
|
+
res.on("end", () => {
|
|
5659
|
+
try {
|
|
5660
|
+
resolve8(JSON.parse(data));
|
|
5661
|
+
} catch {
|
|
5662
|
+
resolve8({ raw: data });
|
|
5663
|
+
}
|
|
5664
|
+
});
|
|
5665
|
+
}).on("error", reject);
|
|
5666
|
+
});
|
|
5667
|
+
return { success: true, ...result };
|
|
5668
|
+
} catch (e) {
|
|
5669
|
+
return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
async proxyDevServerScaffold(args) {
|
|
5673
|
+
try {
|
|
5674
|
+
const http3 = await import("http");
|
|
5675
|
+
const postData = JSON.stringify(args || {});
|
|
5676
|
+
const result = await new Promise((resolve8, reject) => {
|
|
5677
|
+
const req = http3.request({
|
|
5678
|
+
hostname: "127.0.0.1",
|
|
5679
|
+
port: 19280,
|
|
5680
|
+
path: "/api/scaffold",
|
|
5681
|
+
method: "POST",
|
|
5682
|
+
headers: { "Content-Type": "application/json", "Content-Length": Buffer.byteLength(postData) }
|
|
5683
|
+
}, (res) => {
|
|
5684
|
+
let data = "";
|
|
5685
|
+
res.on("data", (chunk) => data += chunk);
|
|
5686
|
+
res.on("end", () => {
|
|
5687
|
+
try {
|
|
5688
|
+
resolve8(JSON.parse(data));
|
|
5689
|
+
} catch {
|
|
5690
|
+
resolve8({ raw: data });
|
|
5691
|
+
}
|
|
5692
|
+
});
|
|
5693
|
+
});
|
|
5694
|
+
req.on("error", reject);
|
|
5695
|
+
req.write(postData);
|
|
5696
|
+
req.end();
|
|
5697
|
+
});
|
|
5698
|
+
return { success: true, ...result };
|
|
5699
|
+
} catch (e) {
|
|
5700
|
+
return { success: false, error: `DevServer unreachable: ${e.message}. Start daemon with --dev flag.` };
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5603
5703
|
};
|
|
5604
5704
|
|
|
5605
5705
|
// src/launch.ts
|
|
@@ -5618,6 +5718,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
5618
5718
|
builtinDirs;
|
|
5619
5719
|
userDir;
|
|
5620
5720
|
upstreamDir;
|
|
5721
|
+
disableUpstream;
|
|
5621
5722
|
watchers = [];
|
|
5622
5723
|
logFn;
|
|
5623
5724
|
versionArchive = null;
|
|
@@ -5636,6 +5737,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
5636
5737
|
}
|
|
5637
5738
|
this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
|
|
5638
5739
|
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
5740
|
+
this.disableUpstream = options?.disableUpstream ?? false;
|
|
5639
5741
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
5640
5742
|
}
|
|
5641
5743
|
log(msg) {
|
|
@@ -5652,11 +5754,13 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
5652
5754
|
loadAll() {
|
|
5653
5755
|
this.providers.clear();
|
|
5654
5756
|
let upstreamCount = 0;
|
|
5655
|
-
if (fs5.existsSync(this.upstreamDir)) {
|
|
5757
|
+
if (!this.disableUpstream && fs5.existsSync(this.upstreamDir)) {
|
|
5656
5758
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
5657
5759
|
if (upstreamCount > 0) {
|
|
5658
5760
|
this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
|
|
5659
5761
|
}
|
|
5762
|
+
} else if (this.disableUpstream) {
|
|
5763
|
+
this.log("Upstream loading disabled (disableUpstream=true)");
|
|
5660
5764
|
}
|
|
5661
5765
|
if (fs5.existsSync(this.userDir)) {
|
|
5662
5766
|
const userCount = this.loadDir(this.userDir, [".upstream"]);
|
|
@@ -6059,6 +6163,10 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
6059
6163
|
* @returns Whether an update occurred
|
|
6060
6164
|
*/
|
|
6061
6165
|
async fetchLatest() {
|
|
6166
|
+
if (this.disableUpstream) {
|
|
6167
|
+
this.log("Upstream fetch skipped (disableUpstream=true)");
|
|
6168
|
+
return { updated: false };
|
|
6169
|
+
}
|
|
6062
6170
|
const https = require("https");
|
|
6063
6171
|
const { execSync: execSync7 } = require("child_process");
|
|
6064
6172
|
const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
@@ -7360,12 +7468,6 @@ var DaemonStatusReporter = class {
|
|
|
7360
7468
|
emitStatusEvent(event) {
|
|
7361
7469
|
LOG.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
|
|
7362
7470
|
this.deps.serverConn?.sendMessage("status_event", event);
|
|
7363
|
-
if (this.deps.p2p?.isConnected) {
|
|
7364
|
-
try {
|
|
7365
|
-
this.deps.p2p.sendStatusEvent?.(event);
|
|
7366
|
-
} catch {
|
|
7367
|
-
}
|
|
7368
|
-
}
|
|
7369
7471
|
}
|
|
7370
7472
|
removeAgentTracking(_key) {
|
|
7371
7473
|
}
|
|
@@ -7443,6 +7545,7 @@ var DaemonStatusReporter = class {
|
|
|
7443
7545
|
peers: p2p?.connectedPeerCount || 0,
|
|
7444
7546
|
screenshotActive: p2p?.screenshotActive || false
|
|
7445
7547
|
},
|
|
7548
|
+
screenshotUsage: this.deps.getScreenshotUsage?.() || null,
|
|
7446
7549
|
connectedExtensions: [],
|
|
7447
7550
|
detectedIdes: this.deps.detectedIdes || [],
|
|
7448
7551
|
availableProviders: this.deps.providerLoader.getAll().map((p) => ({
|
|
@@ -11926,7 +12029,7 @@ var DevServer = class _DevServer {
|
|
|
11926
12029
|
// ─── Phase 2: Auto-Implement Backend ───
|
|
11927
12030
|
async handleAutoImplement(type, req, res) {
|
|
11928
12031
|
const body = await this.readBody(req);
|
|
11929
|
-
const { agent = "claude-cli", functions, reference = "antigravity", model } = body;
|
|
12032
|
+
const { agent = "claude-cli", functions, reference = "antigravity", model, comment } = body;
|
|
11930
12033
|
if (!functions || !Array.isArray(functions) || functions.length === 0) {
|
|
11931
12034
|
this.json(res, 400, { error: 'functions[] is required (e.g. ["readChat", "sendMessage"])' });
|
|
11932
12035
|
return;
|
|
@@ -11975,7 +12078,7 @@ var DevServer = class _DevServer {
|
|
|
11975
12078
|
}
|
|
11976
12079
|
}
|
|
11977
12080
|
}
|
|
11978
|
-
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts);
|
|
12081
|
+
const prompt = this.buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, comment);
|
|
11979
12082
|
const tmpDir = path12.join(os14.tmpdir(), "adhdev-autoimpl");
|
|
11980
12083
|
if (!fs9.existsSync(tmpDir)) fs9.mkdirSync(tmpDir, { recursive: true });
|
|
11981
12084
|
const promptFile = path12.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
@@ -12158,6 +12261,7 @@ var DevServer = class _DevServer {
|
|
|
12158
12261
|
}
|
|
12159
12262
|
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)` } });
|
|
12160
12263
|
this.autoImplStatus = { running: true, type, progress: [] };
|
|
12264
|
+
const spawnedAt = Date.now();
|
|
12161
12265
|
let child;
|
|
12162
12266
|
let isPty = false;
|
|
12163
12267
|
const { spawn: spawnFn } = await import("child_process");
|
|
@@ -12210,8 +12314,9 @@ var DevServer = class _DevServer {
|
|
|
12210
12314
|
const checkAutoApproval = (chunk, writeFn) => {
|
|
12211
12315
|
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, " ");
|
|
12212
12316
|
approvalBuffer = (approvalBuffer + cleanData).slice(-1500);
|
|
12213
|
-
|
|
12214
|
-
|
|
12317
|
+
const elapsed = Date.now() - spawnedAt;
|
|
12318
|
+
if (elapsed > 15e3 && approvalBuffer.includes("AUTO_IMPLEMENT_FINISHED")) {
|
|
12319
|
+
this.log(`Agent finished task after ${Math.round(elapsed / 1e3)}s. Terminating interactive CLI session to unblock pipeline.`);
|
|
12215
12320
|
this.sendAutoImplSSE({ event: "output", data: { chunk: `
|
|
12216
12321
|
[\u{1F916} ADHDev Pipeline] Completion token detected. Proceeding...
|
|
12217
12322
|
`, stream: "stdout" } });
|
|
@@ -12313,7 +12418,7 @@ var DevServer = class _DevServer {
|
|
|
12313
12418
|
this.json(res, 500, { error: `Auto-implement failed: ${e.message}` });
|
|
12314
12419
|
}
|
|
12315
12420
|
}
|
|
12316
|
-
buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts) {
|
|
12421
|
+
buildAutoImplPrompt(type, provider, providerDir, functions, domContext, referenceScripts, userComment) {
|
|
12317
12422
|
const lines = [];
|
|
12318
12423
|
lines.push("You are implementing browser automation scripts for an IDE provider.");
|
|
12319
12424
|
lines.push("Be concise. Do NOT explain your reasoning. Just edit files directly.");
|
|
@@ -12425,6 +12530,22 @@ var DevServer = class _DevServer {
|
|
|
12425
12530
|
lines.push("| focusEditor | `{ focused: true/false }` |");
|
|
12426
12531
|
lines.push("| openPanel | `{ opened: true/false }` |");
|
|
12427
12532
|
lines.push("");
|
|
12533
|
+
lines.push("## \u{1F534} CRITICAL: readChat `status` Lifecycle");
|
|
12534
|
+
lines.push("The `status` field in readChat controls how the dashboard and daemon auto-approve-loop behave.");
|
|
12535
|
+
lines.push("Getting this wrong will break the entire automation pipeline. The status MUST reflect the ACTUAL current state:");
|
|
12536
|
+
lines.push("");
|
|
12537
|
+
lines.push("| Status | When to use | How to detect |");
|
|
12538
|
+
lines.push("|---|---|---|");
|
|
12539
|
+
lines.push("| `idle` | AI is NOT generating, no approval needed | Default state. No stop button, no spinners, no approval pills/buttons |");
|
|
12540
|
+
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 |");
|
|
12541
|
+
lines.push("| `waiting_approval` | AI stopped and needs user action | Actionable buttons like Run/Skip/Accept/Reject are visible AND clickable |");
|
|
12542
|
+
lines.push("");
|
|
12543
|
+
lines.push("### \u26A0\uFE0F Status Detection Gotchas (MUST READ!)");
|
|
12544
|
+
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.');
|
|
12545
|
+
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`.');
|
|
12546
|
+
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.");
|
|
12547
|
+
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`.");
|
|
12548
|
+
lines.push("");
|
|
12428
12549
|
lines.push("## Action");
|
|
12429
12550
|
lines.push("1. Edit the script files to implement working code");
|
|
12430
12551
|
lines.push("2. After editing, TEST each function using the DevConsole API (see below)");
|
|
@@ -12449,7 +12570,7 @@ var DevServer = class _DevServer {
|
|
|
12449
12570
|
lines.push("Once you save the file, test it by running:");
|
|
12450
12571
|
lines.push("```bash");
|
|
12451
12572
|
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
12452
|
-
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/
|
|
12573
|
+
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}"}'`);
|
|
12453
12574
|
lines.push("```");
|
|
12454
12575
|
lines.push("");
|
|
12455
12576
|
lines.push("### Task Workflow");
|
|
@@ -12461,12 +12582,51 @@ var DevServer = class _DevServer {
|
|
|
12461
12582
|
lines.push("### \u{1F525} Advanced UI Parsing (CRUCIAL for `readChat`)");
|
|
12462
12583
|
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.");
|
|
12463
12584
|
lines.push("To achieve this, you MUST generate a live test scenario:");
|
|
12464
|
-
lines.push(
|
|
12465
|
-
lines.push(
|
|
12585
|
+
lines.push(`1. Early in your process, send a rich prompt to the IDE using the API:`);
|
|
12586
|
+
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"}}'\``);
|
|
12466
12587
|
lines.push("2. Wait a few seconds for the IDE AI to generate these elements in the UI.");
|
|
12467
12588
|
lines.push("3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.");
|
|
12468
12589
|
lines.push("4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).");
|
|
12469
12590
|
lines.push("");
|
|
12591
|
+
lines.push("## \u{1F9EA} MANDATORY: Status Integration Test");
|
|
12592
|
+
lines.push("Before finishing, you MUST run this end-to-end test to verify readChat status transitions work:");
|
|
12593
|
+
lines.push("");
|
|
12594
|
+
lines.push("### Step 1: Baseline \u2014 confirm idle");
|
|
12595
|
+
lines.push("```bash");
|
|
12596
|
+
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
12597
|
+
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}"}')`);
|
|
12598
|
+
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')"`);
|
|
12599
|
+
lines.push("```");
|
|
12600
|
+
lines.push("");
|
|
12601
|
+
lines.push("### Step 2: Send a message that triggers generation");
|
|
12602
|
+
lines.push("```bash");
|
|
12603
|
+
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"}}'`);
|
|
12604
|
+
lines.push("sleep 2");
|
|
12605
|
+
lines.push("```");
|
|
12606
|
+
lines.push("");
|
|
12607
|
+
lines.push("### Step 3: Check generating OR completed");
|
|
12608
|
+
lines.push("The AI may still be generating OR may have finished already. Either generating or idle is acceptable:");
|
|
12609
|
+
lines.push("```bash");
|
|
12610
|
+
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}"}')`);
|
|
12611
|
+
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}')"`);
|
|
12612
|
+
lines.push("```");
|
|
12613
|
+
lines.push("");
|
|
12614
|
+
lines.push("### Step 4: Wait for completion and verify new message");
|
|
12615
|
+
lines.push("```bash");
|
|
12616
|
+
lines.push("sleep 10");
|
|
12617
|
+
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}"}')`);
|
|
12618
|
+
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)}')"`);
|
|
12619
|
+
lines.push("```");
|
|
12620
|
+
lines.push("");
|
|
12621
|
+
lines.push("If ANY step fails, fix your implementation and re-run the test. Do NOT finish until all 4 steps pass.");
|
|
12622
|
+
lines.push("");
|
|
12623
|
+
if (userComment) {
|
|
12624
|
+
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
12625
|
+
lines.push("The user has provided the following additional instructions. Follow them strictly:");
|
|
12626
|
+
lines.push("");
|
|
12627
|
+
lines.push(userComment);
|
|
12628
|
+
lines.push("");
|
|
12629
|
+
}
|
|
12470
12630
|
lines.push("Start NOW. Do not ask for permission. Explore the DOM -> Code -> Test.");
|
|
12471
12631
|
return lines.join("\n");
|
|
12472
12632
|
}
|
|
@@ -12988,10 +13148,13 @@ init_logger();
|
|
|
12988
13148
|
init_config();
|
|
12989
13149
|
async function initDaemonComponents(config) {
|
|
12990
13150
|
installGlobalInterceptor();
|
|
13151
|
+
const appConfig = loadConfig();
|
|
13152
|
+
const disableUpstream = appConfig.disableUpstream ?? false;
|
|
12991
13153
|
const providerLoader = new ProviderLoader({
|
|
12992
|
-
logFn: config.providerLogFn
|
|
13154
|
+
logFn: config.providerLogFn,
|
|
13155
|
+
disableUpstream
|
|
12993
13156
|
});
|
|
12994
|
-
if (!providerLoader.hasUpstream()) {
|
|
13157
|
+
if (!disableUpstream && !providerLoader.hasUpstream()) {
|
|
12995
13158
|
LOG.info("Provider", "No upstream providers found \u2014 downloading from GitHub...");
|
|
12996
13159
|
try {
|
|
12997
13160
|
await providerLoader.fetchLatest();
|