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/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
|
});
|
|
@@ -4966,6 +4968,7 @@ var init_provider_loader = __esm({
|
|
|
4966
4968
|
builtinDirs;
|
|
4967
4969
|
userDir;
|
|
4968
4970
|
upstreamDir;
|
|
4971
|
+
disableUpstream;
|
|
4969
4972
|
watchers = [];
|
|
4970
4973
|
logFn;
|
|
4971
4974
|
versionArchive = null;
|
|
@@ -4984,6 +4987,7 @@ var init_provider_loader = __esm({
|
|
|
4984
4987
|
}
|
|
4985
4988
|
this.userDir = options?.userDir || path6.join(os7.homedir(), ".adhdev", "providers");
|
|
4986
4989
|
this.upstreamDir = path6.join(this.userDir, ".upstream");
|
|
4990
|
+
this.disableUpstream = options?.disableUpstream ?? false;
|
|
4987
4991
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
4988
4992
|
}
|
|
4989
4993
|
log(msg) {
|
|
@@ -5000,11 +5004,13 @@ var init_provider_loader = __esm({
|
|
|
5000
5004
|
loadAll() {
|
|
5001
5005
|
this.providers.clear();
|
|
5002
5006
|
let upstreamCount = 0;
|
|
5003
|
-
if (fs5.existsSync(this.upstreamDir)) {
|
|
5007
|
+
if (!this.disableUpstream && fs5.existsSync(this.upstreamDir)) {
|
|
5004
5008
|
upstreamCount = this.loadDir(this.upstreamDir);
|
|
5005
5009
|
if (upstreamCount > 0) {
|
|
5006
5010
|
this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
|
|
5007
5011
|
}
|
|
5012
|
+
} else if (this.disableUpstream) {
|
|
5013
|
+
this.log("Upstream loading disabled (disableUpstream=true)");
|
|
5008
5014
|
}
|
|
5009
5015
|
if (fs5.existsSync(this.userDir)) {
|
|
5010
5016
|
const userCount = this.loadDir(this.userDir, [".upstream"]);
|
|
@@ -5407,6 +5413,10 @@ var init_provider_loader = __esm({
|
|
|
5407
5413
|
* @returns Whether an update occurred
|
|
5408
5414
|
*/
|
|
5409
5415
|
async fetchLatest() {
|
|
5416
|
+
if (this.disableUpstream) {
|
|
5417
|
+
this.log("Upstream fetch skipped (disableUpstream=true)");
|
|
5418
|
+
return { updated: false };
|
|
5419
|
+
}
|
|
5410
5420
|
const https = require("https");
|
|
5411
5421
|
const { execSync: execSync6 } = require("child_process");
|
|
5412
5422
|
const metaPath = path6.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
@@ -6717,12 +6727,6 @@ var init_reporter = __esm({
|
|
|
6717
6727
|
emitStatusEvent(event) {
|
|
6718
6728
|
LOG.info("StatusEvent", `${event.event} (${event.providerType || event.ideType || ""})`);
|
|
6719
6729
|
this.deps.serverConn?.sendMessage("status_event", event);
|
|
6720
|
-
if (this.deps.p2p?.isConnected) {
|
|
6721
|
-
try {
|
|
6722
|
-
this.deps.p2p.sendStatusEvent?.(event);
|
|
6723
|
-
} catch {
|
|
6724
|
-
}
|
|
6725
|
-
}
|
|
6726
6730
|
}
|
|
6727
6731
|
removeAgentTracking(_key) {
|
|
6728
6732
|
}
|
|
@@ -6800,6 +6804,7 @@ var init_reporter = __esm({
|
|
|
6800
6804
|
peers: p2p?.connectedPeerCount || 0,
|
|
6801
6805
|
screenshotActive: p2p?.screenshotActive || false
|
|
6802
6806
|
},
|
|
6807
|
+
screenshotUsage: this.deps.getScreenshotUsage?.() || null,
|
|
6803
6808
|
connectedExtensions: [],
|
|
6804
6809
|
detectedIdes: this.deps.detectedIdes || [],
|
|
6805
6810
|
availableProviders: this.deps.providerLoader.getAll().map((p) => ({
|
|
@@ -28813,6 +28818,22 @@ var init_dev_server = __esm({
|
|
|
28813
28818
|
lines.push("| focusEditor | `{ focused: true/false }` |");
|
|
28814
28819
|
lines.push("| openPanel | `{ opened: true/false }` |");
|
|
28815
28820
|
lines.push("");
|
|
28821
|
+
lines.push("## \u{1F534} CRITICAL: readChat `status` Lifecycle");
|
|
28822
|
+
lines.push("The `status` field in readChat controls how the dashboard and daemon auto-approve-loop behave.");
|
|
28823
|
+
lines.push("Getting this wrong will break the entire automation pipeline. The status MUST reflect the ACTUAL current state:");
|
|
28824
|
+
lines.push("");
|
|
28825
|
+
lines.push("| Status | When to use | How to detect |");
|
|
28826
|
+
lines.push("|---|---|---|");
|
|
28827
|
+
lines.push("| `idle` | AI is NOT generating, no approval needed | Default state. No stop button, no spinners, no approval pills/buttons |");
|
|
28828
|
+
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 |");
|
|
28829
|
+
lines.push("| `waiting_approval` | AI stopped and needs user action | Actionable buttons like Run/Skip/Accept/Reject are visible AND clickable |");
|
|
28830
|
+
lines.push("");
|
|
28831
|
+
lines.push("### \u26A0\uFE0F Status Detection Gotchas (MUST READ!)");
|
|
28832
|
+
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.');
|
|
28833
|
+
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`.');
|
|
28834
|
+
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.");
|
|
28835
|
+
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`.");
|
|
28836
|
+
lines.push("");
|
|
28816
28837
|
lines.push("## Action");
|
|
28817
28838
|
lines.push("1. Edit the script files to implement working code");
|
|
28818
28839
|
lines.push("2. After editing, TEST each function using the DevConsole API (see below)");
|
|
@@ -28837,7 +28858,7 @@ var init_dev_server = __esm({
|
|
|
28837
28858
|
lines.push("Once you save the file, test it by running:");
|
|
28838
28859
|
lines.push("```bash");
|
|
28839
28860
|
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
28840
|
-
lines.push(`curl -sS -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/
|
|
28861
|
+
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}"}'`);
|
|
28841
28862
|
lines.push("```");
|
|
28842
28863
|
lines.push("");
|
|
28843
28864
|
lines.push("### Task Workflow");
|
|
@@ -28849,12 +28870,44 @@ var init_dev_server = __esm({
|
|
|
28849
28870
|
lines.push("### \u{1F525} Advanced UI Parsing (CRUCIAL for `readChat`)");
|
|
28850
28871
|
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.");
|
|
28851
28872
|
lines.push("To achieve this, you MUST generate a live test scenario:");
|
|
28852
|
-
lines.push(
|
|
28853
|
-
lines.push(
|
|
28873
|
+
lines.push(`1. Early in your process, send a rich prompt to the IDE using the API:`);
|
|
28874
|
+
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"}}'\``);
|
|
28854
28875
|
lines.push("2. Wait a few seconds for the IDE AI to generate these elements in the UI.");
|
|
28855
28876
|
lines.push("3. Use CDP evaluate to deeply inspect the DOM structure of the newly generated tables, code blocks, thought blocks, and tool calls.");
|
|
28856
28877
|
lines.push("4. Ensure `readChat` extracts `content` with precise markdown formatting (especially for tables/code) and assigns correct `kind` tags (`thought`, `tool`, `terminal`).");
|
|
28857
28878
|
lines.push("");
|
|
28879
|
+
lines.push("## \u{1F9EA} MANDATORY: Status Integration Test");
|
|
28880
|
+
lines.push("Before finishing, you MUST run this end-to-end test to verify readChat status transitions work:");
|
|
28881
|
+
lines.push("");
|
|
28882
|
+
lines.push("### Step 1: Baseline \u2014 confirm idle");
|
|
28883
|
+
lines.push("```bash");
|
|
28884
|
+
lines.push(`curl -X POST http://127.0.0.1:${DEV_SERVER_PORT}/api/providers/reload`);
|
|
28885
|
+
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}"}')`);
|
|
28886
|
+
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')"`);
|
|
28887
|
+
lines.push("```");
|
|
28888
|
+
lines.push("");
|
|
28889
|
+
lines.push("### Step 2: Send a message that triggers generation");
|
|
28890
|
+
lines.push("```bash");
|
|
28891
|
+
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"}}'`);
|
|
28892
|
+
lines.push("sleep 2");
|
|
28893
|
+
lines.push("```");
|
|
28894
|
+
lines.push("");
|
|
28895
|
+
lines.push("### Step 3: Check generating OR completed");
|
|
28896
|
+
lines.push("The AI may still be generating OR may have finished already. Either generating or idle is acceptable:");
|
|
28897
|
+
lines.push("```bash");
|
|
28898
|
+
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}"}')`);
|
|
28899
|
+
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}')"`);
|
|
28900
|
+
lines.push("```");
|
|
28901
|
+
lines.push("");
|
|
28902
|
+
lines.push("### Step 4: Wait for completion and verify new message");
|
|
28903
|
+
lines.push("```bash");
|
|
28904
|
+
lines.push("sleep 10");
|
|
28905
|
+
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}"}')`);
|
|
28906
|
+
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)}')"`);
|
|
28907
|
+
lines.push("```");
|
|
28908
|
+
lines.push("");
|
|
28909
|
+
lines.push("If ANY step fails, fix your implementation and re-run the test. Do NOT finish until all 4 steps pass.");
|
|
28910
|
+
lines.push("");
|
|
28858
28911
|
if (userComment) {
|
|
28859
28912
|
lines.push("## \u26A0\uFE0F User Instructions (HIGH PRIORITY)");
|
|
28860
28913
|
lines.push("The user has provided the following additional instructions. Follow them strictly:");
|
|
@@ -29208,10 +29261,13 @@ var init_installer = __esm({
|
|
|
29208
29261
|
// ../daemon-core/src/boot/daemon-lifecycle.ts
|
|
29209
29262
|
async function initDaemonComponents(config2) {
|
|
29210
29263
|
installGlobalInterceptor();
|
|
29264
|
+
const appConfig = loadConfig();
|
|
29265
|
+
const disableUpstream = appConfig.disableUpstream ?? false;
|
|
29211
29266
|
const providerLoader = new ProviderLoader({
|
|
29212
|
-
logFn: config2.providerLogFn
|
|
29267
|
+
logFn: config2.providerLogFn,
|
|
29268
|
+
disableUpstream
|
|
29213
29269
|
});
|
|
29214
|
-
if (!providerLoader.hasUpstream()) {
|
|
29270
|
+
if (!disableUpstream && !providerLoader.hasUpstream()) {
|
|
29215
29271
|
LOG.info("Provider", "No upstream providers found \u2014 downloading from GitHub...");
|
|
29216
29272
|
try {
|
|
29217
29273
|
await providerLoader.fetchLatest();
|
|
@@ -30181,24 +30237,6 @@ ${e?.stack || ""}`);
|
|
|
30181
30237
|
}
|
|
30182
30238
|
return sentAny;
|
|
30183
30239
|
}
|
|
30184
|
-
/** Send status_event directly via P2P (generating_started/completed etc.) */
|
|
30185
|
-
sendStatusEvent(event) {
|
|
30186
|
-
const payload = JSON.stringify({
|
|
30187
|
-
type: "status_event",
|
|
30188
|
-
payload: event,
|
|
30189
|
-
timestamp: Date.now()
|
|
30190
|
-
});
|
|
30191
|
-
let sentAny = false;
|
|
30192
|
-
for (const peer of this.peers.values()) {
|
|
30193
|
-
if (peer.state !== "connected" || !peer.dataChannel) continue;
|
|
30194
|
-
try {
|
|
30195
|
-
peer.dataChannel.sendMessage(payload);
|
|
30196
|
-
sentAny = true;
|
|
30197
|
-
} catch {
|
|
30198
|
-
}
|
|
30199
|
-
}
|
|
30200
|
-
return sentAny;
|
|
30201
|
-
}
|
|
30202
30240
|
/** Broadcast PTY output to all connected peers */
|
|
30203
30241
|
broadcastPtyOutput(cliType, data) {
|
|
30204
30242
|
const prev = this.ptyScrollback.get(cliType) || "";
|
|
@@ -30607,6 +30645,15 @@ var init_screenshot_controller = __esm({
|
|
|
30607
30645
|
LOG.info("Screenshot", `Daily budget reset (${this.dailyBudgetMinutes}min for today)`);
|
|
30608
30646
|
}
|
|
30609
30647
|
}
|
|
30648
|
+
/** Returns current usage stats for reporting to server/dashboard */
|
|
30649
|
+
getUsageStats() {
|
|
30650
|
+
this.checkBudgetReset();
|
|
30651
|
+
return {
|
|
30652
|
+
dailyUsedMinutes: Math.round(this.dailyUsedMs / 6e4),
|
|
30653
|
+
dailyBudgetMinutes: this.dailyBudgetMinutes,
|
|
30654
|
+
budgetExhausted: this.budgetExhausted
|
|
30655
|
+
};
|
|
30656
|
+
}
|
|
30610
30657
|
// ─── Hash ─────────────────────────────────────
|
|
30611
30658
|
/** FNV-1a hash of first 1KB + last 1KB for fast delta detection */
|
|
30612
30659
|
static fnvHash(buf) {
|
|
@@ -30687,7 +30734,7 @@ var init_adhdev_daemon = __esm({
|
|
|
30687
30734
|
fs11 = __toESM(require("fs"));
|
|
30688
30735
|
path14 = __toESM(require("path"));
|
|
30689
30736
|
import_chalk2 = __toESM(require("chalk"));
|
|
30690
|
-
pkgVersion = "0.6.
|
|
30737
|
+
pkgVersion = "0.6.22";
|
|
30691
30738
|
if (pkgVersion === "unknown") {
|
|
30692
30739
|
try {
|
|
30693
30740
|
const possiblePaths = [
|
|
@@ -30754,8 +30801,9 @@ ${err?.stack || ""}`);
|
|
|
30754
30801
|
}
|
|
30755
30802
|
writeDaemonPid(process.pid);
|
|
30756
30803
|
const config2 = loadConfig();
|
|
30757
|
-
|
|
30758
|
-
|
|
30804
|
+
const authToken = config2.machineSecret || config2.connectionToken;
|
|
30805
|
+
if (!authToken) {
|
|
30806
|
+
console.log(import_chalk2.default.red("\n\u2717 No credentials found."));
|
|
30759
30807
|
console.log(import_chalk2.default.gray(" Run `adhdev setup` first.\n"));
|
|
30760
30808
|
process.exit(1);
|
|
30761
30809
|
}
|
|
@@ -30805,7 +30853,7 @@ ${err?.stack || ""}`);
|
|
|
30805
30853
|
const instanceId = `daemon_${config2.machineId}`;
|
|
30806
30854
|
this.serverConn = new ServerConnection({
|
|
30807
30855
|
serverUrl: options.serverUrl || config2.serverUrl,
|
|
30808
|
-
token:
|
|
30856
|
+
token: authToken,
|
|
30809
30857
|
daemonVersion: pkgVersion,
|
|
30810
30858
|
cliInfo: {
|
|
30811
30859
|
type: "adhdev-daemon",
|
|
@@ -30897,7 +30945,8 @@ ${err?.stack || ""}`);
|
|
|
30897
30945
|
detectedIdes: this.components.detectedIdes.value,
|
|
30898
30946
|
ideType: this.ideType,
|
|
30899
30947
|
daemonVersion: pkgVersion,
|
|
30900
|
-
instanceManager: this.components.instanceManager
|
|
30948
|
+
instanceManager: this.components.instanceManager,
|
|
30949
|
+
getScreenshotUsage: () => this.screenshotController?.getUsageStats() || null
|
|
30901
30950
|
});
|
|
30902
30951
|
this.statusReporter.startReporting();
|
|
30903
30952
|
this.components.instanceManager.onEvent((event) => {
|
|
@@ -31200,11 +31249,17 @@ async function quickSetup() {
|
|
|
31200
31249
|
}
|
|
31201
31250
|
markSetupComplete(["daemon"], ["adhdev"]);
|
|
31202
31251
|
if (loginResult) {
|
|
31203
|
-
|
|
31252
|
+
const configUpdate = {
|
|
31204
31253
|
connectionToken: loginResult.connectionToken,
|
|
31205
31254
|
userEmail: loginResult.email,
|
|
31206
31255
|
userName: loginResult.name
|
|
31207
|
-
}
|
|
31256
|
+
};
|
|
31257
|
+
if (loginResult.machineId && loginResult.machineSecret) {
|
|
31258
|
+
configUpdate.machineId = loginResult.machineId;
|
|
31259
|
+
configUpdate.machineSecret = loginResult.machineSecret;
|
|
31260
|
+
console.log(import_chalk3.default.green(` \u2713 Machine registered`));
|
|
31261
|
+
}
|
|
31262
|
+
updateConfig(configUpdate);
|
|
31208
31263
|
}
|
|
31209
31264
|
await installCliOnly();
|
|
31210
31265
|
await startDaemonFlow();
|
|
@@ -31240,7 +31295,16 @@ async function loginFlow() {
|
|
|
31240
31295
|
let userCode;
|
|
31241
31296
|
let verificationUrl;
|
|
31242
31297
|
try {
|
|
31243
|
-
const
|
|
31298
|
+
const os17 = await import("os");
|
|
31299
|
+
const res = await fetch(`${SERVER_URL}/auth/cli/init`, {
|
|
31300
|
+
method: "POST",
|
|
31301
|
+
headers: { "Content-Type": "application/json" },
|
|
31302
|
+
body: JSON.stringify({
|
|
31303
|
+
hostname: os17.hostname(),
|
|
31304
|
+
platform: os17.platform(),
|
|
31305
|
+
arch: os17.arch()
|
|
31306
|
+
})
|
|
31307
|
+
});
|
|
31244
31308
|
if (!res.ok) {
|
|
31245
31309
|
spinner.fail("Failed to connect to server");
|
|
31246
31310
|
return null;
|
|
@@ -31287,10 +31351,27 @@ async function loginFlow() {
|
|
|
31287
31351
|
pollSpinner.succeed(`Authenticated as ${import_chalk3.default.bold(data.user?.email || "user")}`);
|
|
31288
31352
|
return {
|
|
31289
31353
|
connectionToken: data.connectionToken,
|
|
31354
|
+
machineId: data.machineId || void 0,
|
|
31355
|
+
machineSecret: data.machineSecret || void 0,
|
|
31290
31356
|
email: data.user?.email,
|
|
31291
31357
|
name: data.user?.name
|
|
31292
31358
|
};
|
|
31293
31359
|
}
|
|
31360
|
+
if (data.status === "limit_reached") {
|
|
31361
|
+
pollSpinner.fail("Machine limit reached");
|
|
31362
|
+
console.log();
|
|
31363
|
+
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.`));
|
|
31364
|
+
console.log();
|
|
31365
|
+
console.log(import_chalk3.default.yellow(" To fix this, do one of the following:"));
|
|
31366
|
+
console.log(import_chalk3.default.gray(" 1. Remove an unused machine from the dashboard:"));
|
|
31367
|
+
console.log(import_chalk3.default.gray(" https://adhf.dev/account \u2192 Registered Machines \u2192 \u2715 Remove"));
|
|
31368
|
+
console.log(import_chalk3.default.gray(" 2. Upgrade your plan:"));
|
|
31369
|
+
console.log(import_chalk3.default.gray(" https://adhf.dev/account?tab=billing"));
|
|
31370
|
+
console.log();
|
|
31371
|
+
console.log(import_chalk3.default.gray(" Then run `adhdev setup` again."));
|
|
31372
|
+
console.log();
|
|
31373
|
+
return null;
|
|
31374
|
+
}
|
|
31294
31375
|
} catch {
|
|
31295
31376
|
}
|
|
31296
31377
|
}
|