adhdev 0.6.21 → 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 +120 -39
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +120 -39
- 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
|
});
|
|
@@ -5134,6 +5136,7 @@ var init_provider_loader = __esm({
|
|
|
5134
5136
|
builtinDirs;
|
|
5135
5137
|
userDir;
|
|
5136
5138
|
upstreamDir;
|
|
5139
|
+
disableUpstream;
|
|
5137
5140
|
watchers = [];
|
|
5138
5141
|
logFn;
|
|
5139
5142
|
versionArchive = null;
|
|
@@ -5152,6 +5155,7 @@ var init_provider_loader = __esm({
|
|
|
5152
5155
|
}
|
|
5153
5156
|
this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
|
|
5154
5157
|
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
5158
|
+
this.disableUpstream = options?.disableUpstream ?? false;
|
|
5155
5159
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
5156
5160
|
}
|
|
5157
5161
|
log(msg) {
|
|
@@ -5168,11 +5172,13 @@ var init_provider_loader = __esm({
|
|
|
5168
5172
|
loadAll() {
|
|
5169
5173
|
this.providers.clear();
|
|
5170
5174
|
let upstreamCount = 0;
|
|
5171
|
-
if (fs5.existsSync(this.upstreamDir)) {
|
|
5175
|
+
if (!this.disableUpstream && fs5.existsSync(this.upstreamDir)) {
|
|
5172
5176
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
5173
5177
|
if (upstreamCount > 0) {
|
|
5174
5178
|
this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
|
|
5175
5179
|
}
|
|
5180
|
+
} else if (this.disableUpstream) {
|
|
5181
|
+
this.log("Upstream loading disabled (disableUpstream=true)");
|
|
5176
5182
|
}
|
|
5177
5183
|
if (fs5.existsSync(this.userDir)) {
|
|
5178
5184
|
const userCount = this.loadDir(this.userDir, [".upstream"]);
|
|
@@ -5575,6 +5581,10 @@ var init_provider_loader = __esm({
|
|
|
5575
5581
|
* @returns Whether an update occurred
|
|
5576
5582
|
*/
|
|
5577
5583
|
async fetchLatest() {
|
|
5584
|
+
if (this.disableUpstream) {
|
|
5585
|
+
this.log("Upstream fetch skipped (disableUpstream=true)");
|
|
5586
|
+
return { updated: false };
|
|
5587
|
+
}
|
|
5578
5588
|
const https = require("https");
|
|
5579
5589
|
const { execSync: execSync7 } = require("child_process");
|
|
5580
5590
|
const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
@@ -6913,12 +6923,6 @@ var init_reporter = __esm({
|
|
|
6913
6923
|
emitStatusEvent(event) {
|
|
6914
6924
|
LOG.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
|
|
6915
6925
|
this.deps.serverConn?.sendMessage("status_event", event);
|
|
6916
|
-
if (this.deps.p2p?.isConnected) {
|
|
6917
|
-
try {
|
|
6918
|
-
this.deps.p2p.sendStatusEvent?.(event);
|
|
6919
|
-
} catch {
|
|
6920
|
-
}
|
|
6921
|
-
}
|
|
6922
6926
|
}
|
|
6923
6927
|
removeAgentTracking(_key) {
|
|
6924
6928
|
}
|
|
@@ -6996,6 +7000,7 @@ var init_reporter = __esm({
|
|
|
6996
7000
|
peers: p2p?.connectedPeerCount || 0,
|
|
6997
7001
|
screenshotActive: p2p?.screenshotActive || false
|
|
6998
7002
|
},
|
|
7003
|
+
screenshotUsage: this.deps.getScreenshotUsage?.() || null,
|
|
6999
7004
|
connectedExtensions: [],
|
|
7000
7005
|
detectedIdes: this.deps.detectedIdes || [],
|
|
7001
7006
|
availableProviders: this.deps.providerLoader.getAll().map((p) => ({
|
|
@@ -29010,6 +29015,22 @@ var init_dev_server = __esm({
|
|
|
29010
29015
|
lines.push("| focusEditor | `{ focused: true/false }` |");
|
|
29011
29016
|
lines.push("| openPanel | `{ opened: true/false }` |");
|
|
29012
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("");
|
|
29013
29034
|
lines.push("## Action");
|
|
29014
29035
|
lines.push("1. Edit the script files to implement working code");
|
|
29015
29036
|
lines.push("2. After editing, TEST each function using the DevConsole API (see below)");
|
|
@@ -29034,7 +29055,7 @@ var init_dev_server = __esm({
|
|
|
29034
29055
|
lines.push("Once you save the file, test it by running:");
|
|
29035
29056
|
lines.push("```bash");
|
|
29036
29057
|
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
29037
|
-
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}"}'`);
|
|
29038
29059
|
lines.push("```");
|
|
29039
29060
|
lines.push("");
|
|
29040
29061
|
lines.push("### Task Workflow");
|
|
@@ -29046,12 +29067,44 @@ var init_dev_server = __esm({
|
|
|
29046
29067
|
lines.push("### \u{1F525} Advanced UI Parsing (CRUCIAL for `readChat`)");
|
|
29047
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.");
|
|
29048
29069
|
lines.push("To achieve this, you MUST generate a live test scenario:");
|
|
29049
|
-
lines.push(
|
|
29050
|
-
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"}}'\``);
|
|
29051
29072
|
lines.push("2. Wait a few seconds for the IDE AI to generate these elements in the UI.");
|
|
29052
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.");
|
|
29053
29074
|
lines.push("4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).");
|
|
29054
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("");
|
|
29055
29108
|
if (userComment) {
|
|
29056
29109
|
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
29057
29110
|
lines.push("The user has provided the following additional instructions. Follow them strictly:");
|
|
@@ -29583,10 +29636,13 @@ var init_installer = __esm({
|
|
|
29583
29636
|
// ../daemon-core/src/boot/daemon-lifecycle.ts
|
|
29584
29637
|
async function initDaemonComponents(config2) {
|
|
29585
29638
|
installGlobalInterceptor();
|
|
29639
|
+
const appConfig = loadConfig();
|
|
29640
|
+
const disableUpstream = appConfig.disableUpstream ?? false;
|
|
29586
29641
|
const providerLoader = new ProviderLoader({
|
|
29587
|
-
logFn: config2.providerLogFn
|
|
29642
|
+
logFn: config2.providerLogFn,
|
|
29643
|
+
disableUpstream
|
|
29588
29644
|
});
|
|
29589
|
-
if (!providerLoader.hasUpstream()) {
|
|
29645
|
+
if (!disableUpstream && !providerLoader.hasUpstream()) {
|
|
29590
29646
|
LOG.info("Provider", "No upstream providers found \u2014 downloading from GitHub...");
|
|
29591
29647
|
try {
|
|
29592
29648
|
await providerLoader.fetchLatest();
|
|
@@ -30621,24 +30677,6 @@ ${e?.stack || ""}`);
|
|
|
30621
30677
|
}
|
|
30622
30678
|
return sentAny;
|
|
30623
30679
|
}
|
|
30624
|
-
/** Send status_event directly via P2P (generating_started/completed etc.) */
|
|
30625
|
-
sendStatusEvent(event) {
|
|
30626
|
-
const payload = JSON.stringify({
|
|
30627
|
-
type: "status_event",
|
|
30628
|
-
payload: event,
|
|
30629
|
-
timestamp: Date.now()
|
|
30630
|
-
});
|
|
30631
|
-
let sentAny = false;
|
|
30632
|
-
for (const peer of this.peers.values()) {
|
|
30633
|
-
if (peer.state !== "connected" || !peer.dataChannel) continue;
|
|
30634
|
-
try {
|
|
30635
|
-
peer.dataChannel.sendMessage(payload);
|
|
30636
|
-
sentAny = true;
|
|
30637
|
-
} catch {
|
|
30638
|
-
}
|
|
30639
|
-
}
|
|
30640
|
-
return sentAny;
|
|
30641
|
-
}
|
|
30642
30680
|
/** Broadcast PTY output to all connected peers */
|
|
30643
30681
|
broadcastPtyOutput(cliType, data) {
|
|
30644
30682
|
const prev = this.ptyScrollback.get(cliType) || "";
|
|
@@ -31047,6 +31085,15 @@ var init_screenshot_controller = __esm({
|
|
|
31047
31085
|
LOG.info("Screenshot", `Daily budget reset (${this.dailyBudgetMinutes}min for today)`);
|
|
31048
31086
|
}
|
|
31049
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
|
+
}
|
|
31050
31097
|
// ─── Hash ─────────────────────────────────────
|
|
31051
31098
|
/** FNV-1a hash of first 1KB + last 1KB for fast delta detection */
|
|
31052
31099
|
static fnvHash(buf) {
|
|
@@ -31127,7 +31174,7 @@ var init_adhdev_daemon = __esm({
|
|
|
31127
31174
|
fs11 = __toESM(require("fs"));
|
|
31128
31175
|
path14 = __toESM(require("path"));
|
|
31129
31176
|
import_chalk2 = __toESM(require("chalk"));
|
|
31130
|
-
pkgVersion = "0.6.
|
|
31177
|
+
pkgVersion = "0.6.22";
|
|
31131
31178
|
if (pkgVersion === "unknown") {
|
|
31132
31179
|
try {
|
|
31133
31180
|
const possiblePaths = [
|
|
@@ -31194,8 +31241,9 @@ ${err?.stack || ""}`);
|
|
|
31194
31241
|
}
|
|
31195
31242
|
writeDaemonPid(process.pid);
|
|
31196
31243
|
const config2 = loadConfig();
|
|
31197
|
-
|
|
31198
|
-
|
|
31244
|
+
const authToken = config2.machineSecret || config2.connectionToken;
|
|
31245
|
+
if (!authToken) {
|
|
31246
|
+
console.log(import_chalk2.default.red("\n\u2717 No credentials found."));
|
|
31199
31247
|
console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
|
|
31200
31248
|
process.exit(1);
|
|
31201
31249
|
}
|
|
@@ -31245,7 +31293,7 @@ ${err?.stack || ""}`);
|
|
|
31245
31293
|
const instanceId = `daemon_${config2.machineId}`;
|
|
31246
31294
|
this.serverConn = new ServerConnection({
|
|
31247
31295
|
serverUrl: options.serverUrl || config2.serverUrl,
|
|
31248
|
-
token:
|
|
31296
|
+
token: authToken,
|
|
31249
31297
|
daemonVersion: pkgVersion,
|
|
31250
31298
|
cliInfo: {
|
|
31251
31299
|
type: "adhdev-daemon",
|
|
@@ -31337,7 +31385,8 @@ ${err?.stack || ""}`);
|
|
|
31337
31385
|
detectedIdes: this.components.detectedIdes.value,
|
|
31338
31386
|
ideType: this.ideType,
|
|
31339
31387
|
daemonVersion: pkgVersion,
|
|
31340
|
-
instanceManager: this.components.instanceManager
|
|
31388
|
+
instanceManager: this.components.instanceManager,
|
|
31389
|
+
getScreenshotUsage: () => this.screenshotController?.getUsageStats() || null
|
|
31341
31390
|
});
|
|
31342
31391
|
this.statusReporter.startReporting();
|
|
31343
31392
|
this.components.instanceManager.onEvent((event) => {
|
|
@@ -31615,11 +31664,17 @@ async function quickSetup() {
|
|
|
31615
31664
|
}
|
|
31616
31665
|
markSetupComplete(["daemon"], ["adhdev"]);
|
|
31617
31666
|
if (loginResult) {
|
|
31618
|
-
|
|
31667
|
+
const configUpdate = {
|
|
31619
31668
|
connectionToken: loginResult.connectionToken,
|
|
31620
31669
|
userEmail: loginResult.email,
|
|
31621
31670
|
userName: loginResult.name
|
|
31622
|
-
}
|
|
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);
|
|
31623
31678
|
}
|
|
31624
31679
|
await installCliOnly();
|
|
31625
31680
|
await startDaemonFlow();
|
|
@@ -31655,7 +31710,16 @@ async function loginFlow() {
|
|
|
31655
31710
|
let userCode;
|
|
31656
31711
|
let verificationUrl;
|
|
31657
31712
|
try {
|
|
31658
|
-
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
|
+
});
|
|
31659
31723
|
if (!res.ok) {
|
|
31660
31724
|
spinner.fail("Failed to connect to server");
|
|
31661
31725
|
return null;
|
|
@@ -31702,10 +31766,27 @@ async function loginFlow() {
|
|
|
31702
31766
|
pollSpinner.succeed(`Authenticated as ${import_chalk3.default.bold(data.user?.email || "user")}`);
|
|
31703
31767
|
return {
|
|
31704
31768
|
connectionToken: data.connectionToken,
|
|
31769
|
+
machineId: data.machineId || void 0,
|
|
31770
|
+
machineSecret: data.machineSecret || void 0,
|
|
31705
31771
|
email: data.user?.email,
|
|
31706
31772
|
name: data.user?.name
|
|
31707
31773
|
};
|
|
31708
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
|
+
}
|
|
31709
31790
|
} catch {
|
|
31710
31791
|
}
|
|
31711
31792
|
}
|