adhdev 0.6.50 → 0.6.52

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 CHANGED
@@ -5242,6 +5242,76 @@ var init_provider_loader = __esm({
5242
5242
  }
5243
5243
  // ─── Public API ────────────────────────────────
5244
5244
  /**
5245
+ * Ordered builtin roots used for local fallback/reference data.
5246
+ */
5247
+ getBuiltinDirs() {
5248
+ return [...this.builtinDirs];
5249
+ }
5250
+ /**
5251
+ * Primary builtin root used for local scaffolding/reference flows.
5252
+ */
5253
+ getPrimaryBuiltinDir() {
5254
+ return this.builtinDirs[0];
5255
+ }
5256
+ /**
5257
+ * User override root (~/.adhdev/providers by default).
5258
+ */
5259
+ getUserDir() {
5260
+ return this.userDir;
5261
+ }
5262
+ /**
5263
+ * Auto-updated upstream root (~/.adhdev/providers/.upstream by default).
5264
+ */
5265
+ getUpstreamDir() {
5266
+ return this.upstreamDir;
5267
+ }
5268
+ /**
5269
+ * Provider search order for on-disk lookups.
5270
+ * Highest-priority editable overrides come first.
5271
+ */
5272
+ getProviderRoots() {
5273
+ return [this.userDir, this.upstreamDir, ...this.builtinDirs];
5274
+ }
5275
+ /**
5276
+ * Canonical provider directory shape for a given root.
5277
+ */
5278
+ getProviderDir(root, category, type) {
5279
+ return path6.join(root, category, type);
5280
+ }
5281
+ /**
5282
+ * Canonical user override directory for a provider.
5283
+ */
5284
+ getUserProviderDir(category, type) {
5285
+ return this.getProviderDir(this.userDir, category, type);
5286
+ }
5287
+ /**
5288
+ * Canonical upstream directory for a provider.
5289
+ */
5290
+ getUpstreamProviderDir(category, type) {
5291
+ return this.getProviderDir(this.upstreamDir, category, type);
5292
+ }
5293
+ /**
5294
+ * Canonical builtin directory for a provider.
5295
+ */
5296
+ getBuiltinProviderDir(category, type) {
5297
+ return this.getProviderDir(this.getPrimaryBuiltinDir(), category, type);
5298
+ }
5299
+ /**
5300
+ * Find the on-disk directory for a provider by type.
5301
+ * Search order: user override → upstream → builtin fallback.
5302
+ */
5303
+ findProviderDir(type) {
5304
+ return this.findProviderDirInternal(type);
5305
+ }
5306
+ /**
5307
+ * Resolve a file within a provider directory.
5308
+ */
5309
+ resolveProviderFile(type, ...segments) {
5310
+ const dir = this.findProviderDirInternal(type);
5311
+ if (!dir) return null;
5312
+ return path6.join(dir, ...segments);
5313
+ }
5314
+ /**
5245
5315
  * Load all providers (3-tier priority)
5246
5316
  * 1. .upstream/ (GitHub auto-download — primary source)
5247
5317
  * 2. User custom (~/.adhdev/providers/ excluding .upstream)
@@ -5567,7 +5637,7 @@ var init_provider_loader = __esm({
5567
5637
  * Tries scripts.js first, then individual .js files.
5568
5638
  */
5569
5639
  loadScriptsFromDir(type, scriptDir) {
5570
- const providerDir = this.findProviderDir(type);
5640
+ const providerDir = this.findProviderDirInternal(type);
5571
5641
  if (!providerDir) {
5572
5642
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
5573
5643
  return null;
@@ -5928,16 +5998,16 @@ var init_provider_loader = __esm({
5928
5998
  // ─── Private ───────────────────────────────────
5929
5999
  /**
5930
6000
  * Find the on-disk directory for a provider by type.
5931
- * Checks builtinDir, upstreamDir, userDir in order.
6001
+ * Preferred shape: root/category/type. Legacy flat root/type is kept temporarily for compatibility.
5932
6002
  */
5933
- findProviderDir(type) {
6003
+ findProviderDirInternal(type) {
5934
6004
  const provider = this.providers.get(type);
5935
6005
  if (!provider) return null;
5936
6006
  const cat = provider.category;
5937
- const searchRoots = [this.userDir, this.upstreamDir, ...this.builtinDirs];
6007
+ const searchRoots = this.getProviderRoots();
5938
6008
  for (const root of searchRoots) {
5939
6009
  if (!fs5.existsSync(root)) continue;
5940
- for (const candidate of [path6.join(root, type), path6.join(root, cat, type)]) {
6010
+ for (const candidate of [this.getProviderDir(root, cat, type), path6.join(root, type)]) {
5941
6011
  if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
5942
6012
  }
5943
6013
  const catDir = path6.join(root, cat);
@@ -7356,6 +7426,9 @@ var init_provider_cli_adapter = __esm({
7356
7426
  idleTimeout = null;
7357
7427
  ready = false;
7358
7428
  startupBuffer = "";
7429
+ /** After spawn: briefly skip generating/settle so splash/redraw does not flip status; not used to gate sendMessage */
7430
+ startupParseGate = false;
7431
+ spawnAt = 0;
7359
7432
  // PTY I/O
7360
7433
  onPtyDataCallback = null;
7361
7434
  ptyOutputBuffer = "";
@@ -7469,9 +7542,15 @@ var init_provider_cli_adapter = __esm({
7469
7542
  this.ptyProcess = null;
7470
7543
  this.setStatus("stopped", "pty_exit");
7471
7544
  this.ready = false;
7545
+ this.startupParseGate = false;
7546
+ this.spawnAt = 0;
7472
7547
  this.onStatusChange?.();
7473
7548
  });
7474
- this.setStatus("starting", "spawn");
7549
+ this.spawnAt = Date.now();
7550
+ this.startupParseGate = true;
7551
+ this.startupBuffer = "";
7552
+ this.ready = true;
7553
+ this.setStatus("idle", "pty_ready");
7475
7554
  this.onStatusChange?.();
7476
7555
  }
7477
7556
  // ─── Output state machine ────────────────────────────
@@ -7487,7 +7566,7 @@ var init_provider_cli_adapter = __esm({
7487
7566
  }
7488
7567
  }
7489
7568
  this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
7490
- if (!this.ready) {
7569
+ if (this.startupParseGate) {
7491
7570
  this.startupBuffer += cleanData;
7492
7571
  LOG.info("CLI", `[${this.cliType}] startup chunk (${cleanData.length} chars): ${cleanData.slice(0, 200).replace(/\n/g, "\\n")}`);
7493
7572
  const dialogPatterns = [
@@ -7502,13 +7581,19 @@ var init_provider_cli_adapter = __esm({
7502
7581
  this.startupBuffer = "";
7503
7582
  return;
7504
7583
  }
7505
- if (patterns.prompt.some((p) => p.test(this.startupBuffer))) {
7506
- this.ready = true;
7507
- this.setStatus("idle", "prompt_matched");
7508
- LOG.info("CLI", `[${this.cliType}] \u2713 Ready`);
7509
- this.onStatusChange?.();
7584
+ const elapsed = Date.now() - this.spawnAt;
7585
+ const bufCap = this.startupBuffer.length > 12e3;
7586
+ const promptMatched = patterns.prompt.some((p) => p.test(this.startupBuffer));
7587
+ if (promptMatched || elapsed > 8e3 || bufCap) {
7588
+ this.startupParseGate = false;
7589
+ if (promptMatched) {
7590
+ LOG.info("CLI", `[${this.cliType}] \u2713 Startup gate end (prompt matched)`);
7591
+ } else {
7592
+ LOG.info("CLI", `[${this.cliType}] startup gate end (${elapsed}ms, cap=${bufCap}, prompt=${promptMatched})`);
7593
+ }
7594
+ } else {
7595
+ return;
7510
7596
  }
7511
- return;
7512
7597
  }
7513
7598
  if (cleanData.trim().length > 5) {
7514
7599
  LOG.debug("CLI", `[${this.cliType}] output chunk (${cleanData.length}): ${cleanData.slice(0, 300).replace(/\n/g, "\\n")}`);
@@ -7716,6 +7801,8 @@ var init_provider_cli_adapter = __esm({
7716
7801
  this.ptyProcess = null;
7717
7802
  this.setStatus("stopped", "stop_cmd");
7718
7803
  this.ready = false;
7804
+ this.startupParseGate = false;
7805
+ this.spawnAt = 0;
7719
7806
  this.onStatusChange?.();
7720
7807
  }, this.timeouts.shutdownGrace);
7721
7808
  }
@@ -7762,16 +7849,29 @@ var init_provider_cli_adapter = __esm({
7762
7849
  * Used by DevServer /api/cli/debug endpoint.
7763
7850
  */
7764
7851
  getDebugState() {
7852
+ const sb = this.startupBuffer;
7853
+ const testOnStartup = (p) => {
7854
+ const flags = p.flags.includes("g") ? p.flags.replace(/g/g, "") : p.flags;
7855
+ return new RegExp(p.source, flags).test(sb);
7856
+ };
7857
+ const promptDiagnostics = this.provider.patterns.prompt.map((p) => ({
7858
+ pattern: p.toString(),
7859
+ matchedAgainstStartupBuffer: testOnStartup(p)
7860
+ }));
7765
7861
  return {
7766
7862
  type: this.cliType,
7767
7863
  name: this.cliName,
7768
7864
  status: this.currentStatus,
7769
7865
  ready: this.ready,
7866
+ startupParseGate: this.startupParseGate,
7867
+ spawnAt: this.spawnAt,
7770
7868
  workingDir: this.workingDir,
7771
7869
  messages: this.messages.slice(-20),
7772
7870
  messageCount: this.messages.length,
7773
- // Buffers
7774
- startupBuffer: this.startupBuffer.slice(-500),
7871
+ // Buffers (longer tails here than in periodic logs — for matching provider.json patterns)
7872
+ startupBuffer: sb.slice(-4e3),
7873
+ startupBufferLength: sb.length,
7874
+ promptDiagnostics,
7775
7875
  recentOutputBuffer: this.recentOutputBuffer.slice(-500),
7776
7876
  settledBuffer: this.settledBuffer.slice(-500),
7777
7877
  responseBuffer: this.responseBuffer.slice(-500),
@@ -27467,37 +27567,7 @@ var init_dev_server = __esm({
27467
27567
  // ─── Provider File Explorer ───
27468
27568
  /** Find the provider directory on disk */
27469
27569
  findProviderDir(type) {
27470
- const provider = this.providerLoader.getMeta(type);
27471
- if (!provider) return null;
27472
- const cat = provider.category;
27473
- const builtinDir = this.providerLoader.builtinDirs?.[0] || path12.resolve(__dirname, "../providers/_builtin");
27474
- const userDir = path12.join(os14.homedir(), ".adhdev", "providers");
27475
- const directCandidates = [
27476
- path12.join(userDir, type),
27477
- path12.join(builtinDir, cat, type),
27478
- path12.join(builtinDir, type)
27479
- ];
27480
- for (const d of directCandidates) {
27481
- if (fs9.existsSync(path12.join(d, "provider.json"))) return d;
27482
- }
27483
- const catDir = path12.join(builtinDir, cat);
27484
- if (fs9.existsSync(catDir)) {
27485
- try {
27486
- for (const entry of fs9.readdirSync(catDir, { withFileTypes: true })) {
27487
- if (!entry.isDirectory()) continue;
27488
- const jsonPath = path12.join(catDir, entry.name, "provider.json");
27489
- if (fs9.existsSync(jsonPath)) {
27490
- try {
27491
- const data = JSON.parse(fs9.readFileSync(jsonPath, "utf-8"));
27492
- if (data.type === type) return path12.join(catDir, entry.name);
27493
- } catch {
27494
- }
27495
- }
27496
- }
27497
- } catch {
27498
- }
27499
- }
27500
- return null;
27570
+ return this.providerLoader.findProviderDir(type);
27501
27571
  }
27502
27572
  /** GET /api/providers/:type/files — list all files in provider directory */
27503
27573
  async handleListFiles(type, _req, res) {
@@ -27892,10 +27962,9 @@ var init_dev_server = __esm({
27892
27962
  }
27893
27963
  let targetDir;
27894
27964
  if (location === "user") {
27895
- targetDir = path12.join(os14.homedir(), ".adhdev", "providers", type);
27965
+ targetDir = this.providerLoader.getUserProviderDir(category, type);
27896
27966
  } else {
27897
- const builtinDir = this.providerLoader.builtinDirs?.[0] || path12.resolve(__dirname, "../providers/_builtin");
27898
- targetDir = path12.join(builtinDir, category, type);
27967
+ targetDir = this.providerLoader.getBuiltinProviderDir(category, type);
27899
27968
  }
27900
27969
  const jsonPath = path12.join(targetDir, "provider.json");
27901
27970
  if (fs9.existsSync(jsonPath)) {
@@ -28704,7 +28773,7 @@ var init_dev_server = __esm({
28704
28773
  const domContext = null;
28705
28774
  this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "loading_reference", message: `\uB808\uD37C\uB7F0\uC2A4 \uC2A4\uD06C\uB9BD\uD2B8 \uB85C\uB4DC \uC911 (${reference})...` } });
28706
28775
  let referenceScripts = {};
28707
- const builtinDir = this.providerLoader.builtinDirs?.[0] || path12.resolve(__dirname, "../providers/_builtin");
28776
+ const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
28708
28777
  const refDir = path12.join(builtinDir, "ide", reference);
28709
28778
  if (fs9.existsSync(refDir)) {
28710
28779
  const scriptsDir = path12.join(refDir, "scripts");
@@ -31354,7 +31423,7 @@ var init_adhdev_daemon = __esm({
31354
31423
  fs11 = __toESM(require("fs"));
31355
31424
  path14 = __toESM(require("path"));
31356
31425
  import_chalk2 = __toESM(require("chalk"));
31357
- pkgVersion = "0.6.50";
31426
+ pkgVersion = "0.6.52";
31358
31427
  if (pkgVersion === "unknown") {
31359
31428
  try {
31360
31429
  const possiblePaths = [
@@ -32979,11 +33048,9 @@ function registerProviderCommands(program2) {
32979
33048
  }).catch(async () => {
32980
33049
  const pathMod = await import("path");
32981
33050
  const fsMod = await import("fs");
32982
- const osMod = await import("os");
32983
33051
  const { ProviderLoader: ProviderLoader2 } = await Promise.resolve().then(() => (init_src(), src_exports));
32984
33052
  const loader = new ProviderLoader2();
32985
- const bDir = loader.builtinDirs[0];
32986
- let targetDir = location === "builtin" ? pathMod.join(bDir, category, type) : pathMod.join(osMod.homedir(), ".adhdev", "providers", type);
33053
+ let targetDir = location === "builtin" ? loader.getBuiltinProviderDir(category, type) : loader.getUserProviderDir(category, type);
32987
33054
  if (fsMod.existsSync(targetDir)) return { error: `Provider already exists at ${targetDir}` };
32988
33055
  const isExt = category === "extension";
32989
33056
  const isIde = category === "ide";
@@ -33039,12 +33106,9 @@ function registerProviderCommands(program2) {
33039
33106
  const loader = new ProviderLoader2();
33040
33107
  loader.loadAll();
33041
33108
  const allProviders = loader.getAll();
33042
- const osMod = await import("os");
33043
- const pathMod = await import("path");
33044
33109
  const fsMod = await import("fs");
33045
- const userProviderDir = pathMod.join(osMod.homedir(), ".adhdev", "providers");
33046
33110
  const isUserProvider = (p) => {
33047
- const dir = pathMod.join(userProviderDir, p.type);
33111
+ const dir = loader.getUserProviderDir(p.category, p.type);
33048
33112
  return fsMod.existsSync(dir) && !dir.includes(".upstream");
33049
33113
  };
33050
33114
  let type = typeArg;
@@ -33089,23 +33153,21 @@ function registerProviderCommands(program2) {
33089
33153
  console.log(import_chalk6.default.red("\n\u2717 Fix aborted.\n"));
33090
33154
  process.exit(1);
33091
33155
  }
33092
- const pathMod2 = await import("path");
33156
+ const pathMod = await import("path");
33093
33157
  const fsMod2 = await import("fs");
33094
- const osMod2 = await import("os");
33095
- const bDir = loader.builtinDirs[0];
33096
- const builtinSrc = pathMod2.join(bDir, providerToFix.category, type);
33097
- const downloadedSrc = pathMod2.join(osMod2.homedir(), ".adhdev", "providers", ".upstream", providerToFix.category, type);
33158
+ const builtinSrc = loader.getBuiltinProviderDir(providerToFix.category, type);
33159
+ const downloadedSrc = loader.getUpstreamProviderDir(providerToFix.category, type);
33098
33160
  const sourceDir = fsMod2.existsSync(builtinSrc) ? builtinSrc : downloadedSrc;
33099
33161
  if (actionAnswer.action === "clone") {
33100
33162
  const newType = `my-${type}`;
33101
- const targetDir = pathMod2.join(osMod2.homedir(), ".adhdev", "providers", newType);
33163
+ const targetDir = loader.getUserProviderDir(providerToFix.category, newType);
33102
33164
  if (fsMod2.existsSync(targetDir)) {
33103
33165
  console.log(import_chalk6.default.red(`
33104
33166
  \u2717 Target directory already exists: ${targetDir}. Please delete it or fix it directly.`));
33105
33167
  process.exit(1);
33106
33168
  }
33107
33169
  fsMod2.cpSync(sourceDir, targetDir, { recursive: true });
33108
- const pJsonPath = pathMod2.join(targetDir, "provider.json");
33170
+ const pJsonPath = pathMod.join(targetDir, "provider.json");
33109
33171
  if (fsMod2.existsSync(pJsonPath)) {
33110
33172
  const pJson = JSON.parse(fsMod2.readFileSync(pJsonPath, "utf8"));
33111
33173
  pJson.type = newType;
@@ -33116,11 +33178,11 @@ function registerProviderCommands(program2) {
33116
33178
  \u2713 Successfully cloned to [${newType}]`));
33117
33179
  type = newType;
33118
33180
  } else if (actionAnswer.action === "inplace") {
33119
- const targetDir = pathMod2.join(osMod2.homedir(), ".adhdev", "providers", type);
33181
+ const targetDir = loader.getUserProviderDir(providerToFix.category, type);
33120
33182
  if (!fsMod2.existsSync(targetDir)) {
33121
33183
  fsMod2.cpSync(sourceDir, targetDir, { recursive: true });
33122
33184
  }
33123
- const pJsonPath = pathMod2.join(targetDir, "provider.json");
33185
+ const pJsonPath = pathMod.join(targetDir, "provider.json");
33124
33186
  if (fsMod2.existsSync(pJsonPath)) {
33125
33187
  const pJson = JSON.parse(fsMod2.readFileSync(pJsonPath, "utf8"));
33126
33188
  pJson.disableUpstream = true;
@@ -33235,11 +33297,14 @@ function registerProviderCommands(program2) {
33235
33297
  if (!startResult.started || !startResult.sseUrl) {
33236
33298
  throw new Error(`Unexpected response: ${JSON.stringify(startResult)}`);
33237
33299
  }
33238
- const pathMod2 = await import("path");
33239
- const osPaths = await import("os");
33240
- const targetDir = pathMod2.join(osPaths.homedir(), ".adhdev", "providers", type);
33300
+ const pathMod = await import("path");
33301
+ const { ProviderLoader: ProviderLoader3 } = await Promise.resolve().then(() => (init_src(), src_exports));
33302
+ const loader2 = new ProviderLoader3();
33303
+ loader2.loadAll();
33304
+ const providerMeta = loader2.getMeta(type);
33305
+ const targetDir = providerMeta ? loader2.getUserProviderDir(providerMeta.category, type) : pathMod.join(loader2.getUserDir(), type);
33241
33306
  const fsMock = await import("fs");
33242
- const logFile2 = pathMod2.join(targetDir, `auto-impl.log`);
33307
+ const logFile2 = pathMod.join(targetDir, `auto-impl.log`);
33243
33308
  fsMock.writeFileSync(logFile2, `=== Auto-Impl Started ===
33244
33309
  `);
33245
33310
  console.log(import_chalk6.default.gray(` Agent logs: ${logFile2}`));
@@ -33417,11 +33482,21 @@ function registerProviderCommands(program2) {
33417
33482
  }).catch(async () => {
33418
33483
  const pathMod = await import("path");
33419
33484
  const fsMod = await import("fs");
33420
- const osMod = await import("os");
33485
+ const { ProviderLoader: ProviderLoader2 } = await Promise.resolve().then(() => (init_src(), src_exports));
33486
+ const loader = new ProviderLoader2();
33487
+ loader.loadAll();
33488
+ const providerMeta = loader.getMeta(type);
33421
33489
  const possiblePaths = [
33422
- pathMod.join(osMod.homedir(), ".adhdev", "providers", type, "provider.js"),
33423
- pathMod.join(new (await Promise.resolve().then(() => (init_src(), src_exports))).ProviderLoader().builtinDirs[0], "ide", type, "provider.js"),
33424
- pathMod.join(new (await Promise.resolve().then(() => (init_src(), src_exports))).ProviderLoader().builtinDirs[0], "extension", type, "provider.js")
33490
+ ...providerMeta ? [
33491
+ pathMod.join(loader.getUserProviderDir(providerMeta.category, type), "provider.js"),
33492
+ pathMod.join(loader.getUpstreamProviderDir(providerMeta.category, type), "provider.js"),
33493
+ pathMod.join(loader.getBuiltinProviderDir(providerMeta.category, type), "provider.js")
33494
+ ] : [],
33495
+ pathMod.join(loader.getUserDir(), type, "provider.js"),
33496
+ pathMod.join(loader.getUpstreamDir(), "ide", type, "provider.js"),
33497
+ pathMod.join(loader.getUpstreamDir(), "extension", type, "provider.js"),
33498
+ pathMod.join(loader.getPrimaryBuiltinDir(), "ide", type, "provider.js"),
33499
+ pathMod.join(loader.getPrimaryBuiltinDir(), "extension", type, "provider.js")
33425
33500
  ];
33426
33501
  for (const p of possiblePaths) {
33427
33502
  if (fsMod.existsSync(p)) {