@adhdev/daemon-core 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/index.d.ts CHANGED
@@ -981,6 +981,52 @@ declare class ProviderLoader {
981
981
  });
982
982
  private log;
983
983
  /**
984
+ * Ordered builtin roots used for local fallback/reference data.
985
+ */
986
+ getBuiltinDirs(): string[];
987
+ /**
988
+ * Primary builtin root used for local scaffolding/reference flows.
989
+ */
990
+ getPrimaryBuiltinDir(): string;
991
+ /**
992
+ * User override root (~/.adhdev/providers by default).
993
+ */
994
+ getUserDir(): string;
995
+ /**
996
+ * Auto-updated upstream root (~/.adhdev/providers/.upstream by default).
997
+ */
998
+ getUpstreamDir(): string;
999
+ /**
1000
+ * Provider search order for on-disk lookups.
1001
+ * Highest-priority editable overrides come first.
1002
+ */
1003
+ getProviderRoots(): string[];
1004
+ /**
1005
+ * Canonical provider directory shape for a given root.
1006
+ */
1007
+ getProviderDir(root: string, category: ProviderCategory, type: string): string;
1008
+ /**
1009
+ * Canonical user override directory for a provider.
1010
+ */
1011
+ getUserProviderDir(category: ProviderCategory, type: string): string;
1012
+ /**
1013
+ * Canonical upstream directory for a provider.
1014
+ */
1015
+ getUpstreamProviderDir(category: ProviderCategory, type: string): string;
1016
+ /**
1017
+ * Canonical builtin directory for a provider.
1018
+ */
1019
+ getBuiltinProviderDir(category: ProviderCategory, type: string): string;
1020
+ /**
1021
+ * Find the on-disk directory for a provider by type.
1022
+ * Search order: user override → upstream → builtin fallback.
1023
+ */
1024
+ findProviderDir(type: string): string | null;
1025
+ /**
1026
+ * Resolve a file within a provider directory.
1027
+ */
1028
+ resolveProviderFile(type: string, ...segments: string[]): string | null;
1029
+ /**
984
1030
  * Load all providers (3-tier priority)
985
1031
  * 1. .upstream/ (GitHub auto-download — primary source)
986
1032
  * 2. User custom (~/.adhdev/providers/ excluding .upstream)
@@ -1156,9 +1202,9 @@ declare class ProviderLoader {
1156
1202
  setSetting(type: string, key: string, value: any): boolean;
1157
1203
  /**
1158
1204
  * Find the on-disk directory for a provider by type.
1159
- * Checks builtinDir, upstreamDir, userDir in order.
1205
+ * Preferred shape: root/category/type. Legacy flat root/type is kept temporarily for compatibility.
1160
1206
  */
1161
- private findProviderDir;
1207
+ private findProviderDirInternal;
1162
1208
  /**
1163
1209
  * Build a scripts function map from individual .js files in a directory.
1164
1210
  * Each file is wrapped as: (params?) => fs.readFileSync(filePath, 'utf-8')
@@ -2500,7 +2546,7 @@ declare const DAEMON_WS_PATH = "/ipc";
2500
2546
  * category: 'cli'
2501
2547
  * binary: string — binary name
2502
2548
  * spawn: { command, args, shell, env }
2503
- * patterns: { prompt, generating, approval, ready }
2549
+ * patterns: { prompt, generating, approval, ready } — prompt helps end startup splash-gate early; sendMessage does not wait for it
2504
2550
  * timeouts?: { idleFinish, generatingIdle, maxResponse, approvalCooldown, outputSettle, ... }
2505
2551
  * cleanOutput(raw, lastUserInput): string
2506
2552
  */
@@ -2574,6 +2620,9 @@ declare class ProviderCliAdapter implements CliAdapter {
2574
2620
  private idleTimeout;
2575
2621
  private ready;
2576
2622
  private startupBuffer;
2623
+ /** After spawn: briefly skip generating/settle so splash/redraw does not flip status; not used to gate sendMessage */
2624
+ private startupParseGate;
2625
+ private spawnAt;
2577
2626
  private onPtyDataCallback;
2578
2627
  private ptyOutputBuffer;
2579
2628
  private ptyOutputFlushTimer;
package/dist/index.js CHANGED
@@ -780,6 +780,9 @@ var init_provider_cli_adapter = __esm({
780
780
  idleTimeout = null;
781
781
  ready = false;
782
782
  startupBuffer = "";
783
+ /** After spawn: briefly skip generating/settle so splash/redraw does not flip status; not used to gate sendMessage */
784
+ startupParseGate = false;
785
+ spawnAt = 0;
783
786
  // PTY I/O
784
787
  onPtyDataCallback = null;
785
788
  ptyOutputBuffer = "";
@@ -893,9 +896,15 @@ var init_provider_cli_adapter = __esm({
893
896
  this.ptyProcess = null;
894
897
  this.setStatus("stopped", "pty_exit");
895
898
  this.ready = false;
899
+ this.startupParseGate = false;
900
+ this.spawnAt = 0;
896
901
  this.onStatusChange?.();
897
902
  });
898
- this.setStatus("starting", "spawn");
903
+ this.spawnAt = Date.now();
904
+ this.startupParseGate = true;
905
+ this.startupBuffer = "";
906
+ this.ready = true;
907
+ this.setStatus("idle", "pty_ready");
899
908
  this.onStatusChange?.();
900
909
  }
901
910
  // ─── Output state machine ────────────────────────────
@@ -911,7 +920,7 @@ var init_provider_cli_adapter = __esm({
911
920
  }
912
921
  }
913
922
  this.recentOutputBuffer = (this.recentOutputBuffer + cleanData).slice(-1e3);
914
- if (!this.ready) {
923
+ if (this.startupParseGate) {
915
924
  this.startupBuffer += cleanData;
916
925
  LOG.info("CLI", `[${this.cliType}] startup chunk (${cleanData.length} chars): ${cleanData.slice(0, 200).replace(/\n/g, "\\n")}`);
917
926
  const dialogPatterns = [
@@ -926,13 +935,19 @@ var init_provider_cli_adapter = __esm({
926
935
  this.startupBuffer = "";
927
936
  return;
928
937
  }
929
- if (patterns.prompt.some((p) => p.test(this.startupBuffer))) {
930
- this.ready = true;
931
- this.setStatus("idle", "prompt_matched");
932
- LOG.info("CLI", `[${this.cliType}] \u2713 Ready`);
933
- this.onStatusChange?.();
938
+ const elapsed = Date.now() - this.spawnAt;
939
+ const bufCap = this.startupBuffer.length > 12e3;
940
+ const promptMatched = patterns.prompt.some((p) => p.test(this.startupBuffer));
941
+ if (promptMatched || elapsed > 8e3 || bufCap) {
942
+ this.startupParseGate = false;
943
+ if (promptMatched) {
944
+ LOG.info("CLI", `[${this.cliType}] \u2713 Startup gate end (prompt matched)`);
945
+ } else {
946
+ LOG.info("CLI", `[${this.cliType}] startup gate end (${elapsed}ms, cap=${bufCap}, prompt=${promptMatched})`);
947
+ }
948
+ } else {
949
+ return;
934
950
  }
935
- return;
936
951
  }
937
952
  if (cleanData.trim().length > 5) {
938
953
  LOG.debug("CLI", `[${this.cliType}] output chunk (${cleanData.length}): ${cleanData.slice(0, 300).replace(/\n/g, "\\n")}`);
@@ -1140,6 +1155,8 @@ var init_provider_cli_adapter = __esm({
1140
1155
  this.ptyProcess = null;
1141
1156
  this.setStatus("stopped", "stop_cmd");
1142
1157
  this.ready = false;
1158
+ this.startupParseGate = false;
1159
+ this.spawnAt = 0;
1143
1160
  this.onStatusChange?.();
1144
1161
  }, this.timeouts.shutdownGrace);
1145
1162
  }
@@ -1186,16 +1203,29 @@ var init_provider_cli_adapter = __esm({
1186
1203
  * Used by DevServer /api/cli/debug endpoint.
1187
1204
  */
1188
1205
  getDebugState() {
1206
+ const sb = this.startupBuffer;
1207
+ const testOnStartup = (p) => {
1208
+ const flags = p.flags.includes("g") ? p.flags.replace(/g/g, "") : p.flags;
1209
+ return new RegExp(p.source, flags).test(sb);
1210
+ };
1211
+ const promptDiagnostics = this.provider.patterns.prompt.map((p) => ({
1212
+ pattern: p.toString(),
1213
+ matchedAgainstStartupBuffer: testOnStartup(p)
1214
+ }));
1189
1215
  return {
1190
1216
  type: this.cliType,
1191
1217
  name: this.cliName,
1192
1218
  status: this.currentStatus,
1193
1219
  ready: this.ready,
1220
+ startupParseGate: this.startupParseGate,
1221
+ spawnAt: this.spawnAt,
1194
1222
  workingDir: this.workingDir,
1195
1223
  messages: this.messages.slice(-20),
1196
1224
  messageCount: this.messages.length,
1197
- // Buffers
1198
- startupBuffer: this.startupBuffer.slice(-500),
1225
+ // Buffers (longer tails here than in periodic logs — for matching provider.json patterns)
1226
+ startupBuffer: sb.slice(-4e3),
1227
+ startupBufferLength: sb.length,
1228
+ promptDiagnostics,
1199
1229
  recentOutputBuffer: this.recentOutputBuffer.slice(-500),
1200
1230
  settledBuffer: this.settledBuffer.slice(-500),
1201
1231
  responseBuffer: this.responseBuffer.slice(-500),
@@ -5819,6 +5849,76 @@ var ProviderLoader = class _ProviderLoader {
5819
5849
  }
5820
5850
  // ─── Public API ────────────────────────────────
5821
5851
  /**
5852
+ * Ordered builtin roots used for local fallback/reference data.
5853
+ */
5854
+ getBuiltinDirs() {
5855
+ return [...this.builtinDirs];
5856
+ }
5857
+ /**
5858
+ * Primary builtin root used for local scaffolding/reference flows.
5859
+ */
5860
+ getPrimaryBuiltinDir() {
5861
+ return this.builtinDirs[0];
5862
+ }
5863
+ /**
5864
+ * User override root (~/.adhdev/providers by default).
5865
+ */
5866
+ getUserDir() {
5867
+ return this.userDir;
5868
+ }
5869
+ /**
5870
+ * Auto-updated upstream root (~/.adhdev/providers/.upstream by default).
5871
+ */
5872
+ getUpstreamDir() {
5873
+ return this.upstreamDir;
5874
+ }
5875
+ /**
5876
+ * Provider search order for on-disk lookups.
5877
+ * Highest-priority editable overrides come first.
5878
+ */
5879
+ getProviderRoots() {
5880
+ return [this.userDir, this.upstreamDir, ...this.builtinDirs];
5881
+ }
5882
+ /**
5883
+ * Canonical provider directory shape for a given root.
5884
+ */
5885
+ getProviderDir(root, category, type) {
5886
+ return path6.join(root, category, type);
5887
+ }
5888
+ /**
5889
+ * Canonical user override directory for a provider.
5890
+ */
5891
+ getUserProviderDir(category, type) {
5892
+ return this.getProviderDir(this.userDir, category, type);
5893
+ }
5894
+ /**
5895
+ * Canonical upstream directory for a provider.
5896
+ */
5897
+ getUpstreamProviderDir(category, type) {
5898
+ return this.getProviderDir(this.upstreamDir, category, type);
5899
+ }
5900
+ /**
5901
+ * Canonical builtin directory for a provider.
5902
+ */
5903
+ getBuiltinProviderDir(category, type) {
5904
+ return this.getProviderDir(this.getPrimaryBuiltinDir(), category, type);
5905
+ }
5906
+ /**
5907
+ * Find the on-disk directory for a provider by type.
5908
+ * Search order: user override → upstream → builtin fallback.
5909
+ */
5910
+ findProviderDir(type) {
5911
+ return this.findProviderDirInternal(type);
5912
+ }
5913
+ /**
5914
+ * Resolve a file within a provider directory.
5915
+ */
5916
+ resolveProviderFile(type, ...segments) {
5917
+ const dir = this.findProviderDirInternal(type);
5918
+ if (!dir) return null;
5919
+ return path6.join(dir, ...segments);
5920
+ }
5921
+ /**
5822
5922
  * Load all providers (3-tier priority)
5823
5923
  * 1. .upstream/ (GitHub auto-download — primary source)
5824
5924
  * 2. User custom (~/.adhdev/providers/ excluding .upstream)
@@ -6144,7 +6244,7 @@ var ProviderLoader = class _ProviderLoader {
6144
6244
  * Tries scripts.js first, then individual .js files.
6145
6245
  */
6146
6246
  loadScriptsFromDir(type, scriptDir) {
6147
- const providerDir = this.findProviderDir(type);
6247
+ const providerDir = this.findProviderDirInternal(type);
6148
6248
  if (!providerDir) {
6149
6249
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
6150
6250
  return null;
@@ -6505,16 +6605,16 @@ var ProviderLoader = class _ProviderLoader {
6505
6605
  // ─── Private ───────────────────────────────────
6506
6606
  /**
6507
6607
  * Find the on-disk directory for a provider by type.
6508
- * Checks builtinDir, upstreamDir, userDir in order.
6608
+ * Preferred shape: root/category/type. Legacy flat root/type is kept temporarily for compatibility.
6509
6609
  */
6510
- findProviderDir(type) {
6610
+ findProviderDirInternal(type) {
6511
6611
  const provider = this.providers.get(type);
6512
6612
  if (!provider) return null;
6513
6613
  const cat = provider.category;
6514
- const searchRoots = [this.userDir, this.upstreamDir, ...this.builtinDirs];
6614
+ const searchRoots = this.getProviderRoots();
6515
6615
  for (const root of searchRoots) {
6516
6616
  if (!fs5.existsSync(root)) continue;
6517
- for (const candidate of [path6.join(root, type), path6.join(root, cat, type)]) {
6617
+ for (const candidate of [this.getProviderDir(root, cat, type), path6.join(root, type)]) {
6518
6618
  if (fs5.existsSync(path6.join(candidate, "provider.json"))) return candidate;
6519
6619
  }
6520
6620
  const catDir = path6.join(root, cat);
@@ -10982,37 +11082,7 @@ var DevServer = class _DevServer {
10982
11082
  // ─── Provider File Explorer ───
10983
11083
  /** Find the provider directory on disk */
10984
11084
  findProviderDir(type) {
10985
- const provider = this.providerLoader.getMeta(type);
10986
- if (!provider) return null;
10987
- const cat = provider.category;
10988
- const builtinDir = this.providerLoader.builtinDirs?.[0] || path12.resolve(__dirname, "../providers/_builtin");
10989
- const userDir = path12.join(os14.homedir(), ".adhdev", "providers");
10990
- const directCandidates = [
10991
- path12.join(userDir, type),
10992
- path12.join(builtinDir, cat, type),
10993
- path12.join(builtinDir, type)
10994
- ];
10995
- for (const d of directCandidates) {
10996
- if (fs9.existsSync(path12.join(d, "provider.json"))) return d;
10997
- }
10998
- const catDir = path12.join(builtinDir, cat);
10999
- if (fs9.existsSync(catDir)) {
11000
- try {
11001
- for (const entry of fs9.readdirSync(catDir, { withFileTypes: true })) {
11002
- if (!entry.isDirectory()) continue;
11003
- const jsonPath = path12.join(catDir, entry.name, "provider.json");
11004
- if (fs9.existsSync(jsonPath)) {
11005
- try {
11006
- const data = JSON.parse(fs9.readFileSync(jsonPath, "utf-8"));
11007
- if (data.type === type) return path12.join(catDir, entry.name);
11008
- } catch {
11009
- }
11010
- }
11011
- }
11012
- } catch {
11013
- }
11014
- }
11015
- return null;
11085
+ return this.providerLoader.findProviderDir(type);
11016
11086
  }
11017
11087
  /** GET /api/providers/:type/files — list all files in provider directory */
11018
11088
  async handleListFiles(type, _req, res) {
@@ -11407,10 +11477,9 @@ var DevServer = class _DevServer {
11407
11477
  }
11408
11478
  let targetDir;
11409
11479
  if (location === "user") {
11410
- targetDir = path12.join(os14.homedir(), ".adhdev", "providers", type);
11480
+ targetDir = this.providerLoader.getUserProviderDir(category, type);
11411
11481
  } else {
11412
- const builtinDir = this.providerLoader.builtinDirs?.[0] || path12.resolve(__dirname, "../providers/_builtin");
11413
- targetDir = path12.join(builtinDir, category, type);
11482
+ targetDir = this.providerLoader.getBuiltinProviderDir(category, type);
11414
11483
  }
11415
11484
  const jsonPath = path12.join(targetDir, "provider.json");
11416
11485
  if (fs9.existsSync(jsonPath)) {
@@ -12219,7 +12288,7 @@ var DevServer = class _DevServer {
12219
12288
  const domContext = null;
12220
12289
  this.sendAutoImplSSE({ event: "progress", data: { function: "_init", status: "loading_reference", message: `\uB808\uD37C\uB7F0\uC2A4 \uC2A4\uD06C\uB9BD\uD2B8 \uB85C\uB4DC \uC911 (${reference})...` } });
12221
12290
  let referenceScripts = {};
12222
- const builtinDir = this.providerLoader.builtinDirs?.[0] || path12.resolve(__dirname, "../providers/_builtin");
12291
+ const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
12223
12292
  const refDir = path12.join(builtinDir, "ide", reference);
12224
12293
  if (fs9.existsSync(refDir)) {
12225
12294
  const scriptsDir = path12.join(refDir, "scripts");