@adhdev/daemon-core 0.6.51 → 0.6.53

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.6.51",
3
+ "version": "0.6.53",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -730,39 +730,7 @@ export class DevServer {
730
730
 
731
731
  /** Find the provider directory on disk */
732
732
  private findProviderDir(type: string): string | null {
733
- const provider = this.providerLoader.getMeta(type);
734
- if (!provider) return null;
735
- const cat = provider.category;
736
- const builtinDir = (this.providerLoader as any).builtinDirs?.[0] || path.resolve(__dirname, '../providers/_builtin');
737
- const userDir = path.join(os.homedir(), '.adhdev', 'providers');
738
-
739
- // Direct match first
740
- const directCandidates = [
741
- path.join(userDir, type),
742
- path.join(builtinDir, cat, type),
743
- path.join(builtinDir, type),
744
- ];
745
- for (const d of directCandidates) {
746
- if (fs.existsSync(path.join(d, 'provider.json'))) return d;
747
- }
748
-
749
- // Scan category dir for matching type field
750
- const catDir = path.join(builtinDir, cat);
751
- if (fs.existsSync(catDir)) {
752
- try {
753
- for (const entry of fs.readdirSync(catDir, { withFileTypes: true })) {
754
- if (!entry.isDirectory()) continue;
755
- const jsonPath = path.join(catDir, entry.name, 'provider.json');
756
- if (fs.existsSync(jsonPath)) {
757
- try {
758
- const data = JSON.parse(fs.readFileSync(jsonPath, 'utf-8'));
759
- if (data.type === type) return path.join(catDir, entry.name);
760
- } catch { /* skip */ }
761
- }
762
- }
763
- } catch { /* skip */ }
764
- }
765
- return null;
733
+ return this.providerLoader.findProviderDir(type);
766
734
  }
767
735
 
768
736
  /** GET /api/providers/:type/files — list all files in provider directory */
@@ -1140,10 +1108,9 @@ export class DevServer {
1140
1108
 
1141
1109
  let targetDir: string;
1142
1110
  if (location === 'user') {
1143
- targetDir = path.join(os.homedir(), '.adhdev', 'providers', type);
1111
+ targetDir = this.providerLoader.getUserProviderDir(category, type);
1144
1112
  } else {
1145
- const builtinDir = (this.providerLoader as any).builtinDirs?.[0] || path.resolve(__dirname, '../providers/_builtin');
1146
- targetDir = path.join(builtinDir, category, type);
1113
+ targetDir = this.providerLoader.getBuiltinProviderDir(category, type);
1147
1114
  }
1148
1115
 
1149
1116
  const jsonPath = path.join(targetDir, 'provider.json');
@@ -1928,7 +1895,7 @@ export class DevServer {
1928
1895
  this.sendAutoImplSSE({ event: 'progress', data: { function: '_init', status: 'loading_reference', message: `레퍼런스 스크립트 로드 중 (${reference})...` } });
1929
1896
 
1930
1897
  let referenceScripts: Record<string, string> = {};
1931
- const builtinDir = (this.providerLoader as any).builtinDirs?.[0] || path.resolve(__dirname, '../providers/_builtin');
1898
+ const builtinDir = this.providerLoader.getPrimaryBuiltinDir();
1932
1899
  const refDir = path.join(builtinDir, 'ide', reference);
1933
1900
  if (fs.existsSync(refDir)) {
1934
1901
  // Find latest versioned scripts dir
@@ -77,6 +77,87 @@ export class ProviderLoader {
77
77
 
78
78
  // ─── Public API ────────────────────────────────
79
79
 
80
+ /**
81
+ * Ordered builtin roots used for local fallback/reference data.
82
+ */
83
+ getBuiltinDirs(): string[] {
84
+ return [...this.builtinDirs];
85
+ }
86
+
87
+ /**
88
+ * Primary builtin root used for local scaffolding/reference flows.
89
+ */
90
+ getPrimaryBuiltinDir(): string {
91
+ return this.builtinDirs[0];
92
+ }
93
+
94
+ /**
95
+ * User override root (~/.adhdev/providers by default).
96
+ */
97
+ getUserDir(): string {
98
+ return this.userDir;
99
+ }
100
+
101
+ /**
102
+ * Auto-updated upstream root (~/.adhdev/providers/.upstream by default).
103
+ */
104
+ getUpstreamDir(): string {
105
+ return this.upstreamDir;
106
+ }
107
+
108
+ /**
109
+ * Provider search order for on-disk lookups.
110
+ * Highest-priority editable overrides come first.
111
+ */
112
+ getProviderRoots(): string[] {
113
+ return [this.userDir, this.upstreamDir, ...this.builtinDirs];
114
+ }
115
+
116
+ /**
117
+ * Canonical provider directory shape for a given root.
118
+ */
119
+ getProviderDir(root: string, category: ProviderCategory, type: string): string {
120
+ return path.join(root, category, type);
121
+ }
122
+
123
+ /**
124
+ * Canonical user override directory for a provider.
125
+ */
126
+ getUserProviderDir(category: ProviderCategory, type: string): string {
127
+ return this.getProviderDir(this.userDir, category, type);
128
+ }
129
+
130
+ /**
131
+ * Canonical upstream directory for a provider.
132
+ */
133
+ getUpstreamProviderDir(category: ProviderCategory, type: string): string {
134
+ return this.getProviderDir(this.upstreamDir, category, type);
135
+ }
136
+
137
+ /**
138
+ * Canonical builtin directory for a provider.
139
+ */
140
+ getBuiltinProviderDir(category: ProviderCategory, type: string): string {
141
+ return this.getProviderDir(this.getPrimaryBuiltinDir(), category, type);
142
+ }
143
+
144
+ /**
145
+ * Find the on-disk directory for a provider by type.
146
+ * Search order: user override → upstream → builtin fallback.
147
+ */
148
+ findProviderDir(type: string): string | null {
149
+ return this.findProviderDirInternal(type);
150
+ }
151
+
152
+ /**
153
+ * Resolve a file within a provider directory.
154
+ */
155
+ resolveProviderFile(type: string, ...segments: string[]): string | null {
156
+ const dir = this.findProviderDirInternal(type);
157
+ if (!dir) return null;
158
+ return path.join(dir, ...segments);
159
+ }
160
+
80
161
  /**
81
162
  * Load all providers (3-tier priority)
82
163
  * 1. .upstream/ (GitHub auto-download — primary source)
@@ -455,7 +536,7 @@ export class ProviderLoader {
455
536
  * Tries scripts.js first, then individual .js files.
456
537
  */
457
538
  private loadScriptsFromDir(type: string, scriptDir: string): Record<string, any> | null {
458
- const providerDir = this.findProviderDir(type);
539
+ const providerDir = this.findProviderDirInternal(type);
459
540
  if (!providerDir) {
460
541
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
461
542
  return null;
@@ -857,20 +938,18 @@ export class ProviderLoader {
857
938
 
858
939
  /**
859
940
  * Find the on-disk directory for a provider by type.
860
- * Checks builtinDir, upstreamDir, userDir in order.
941
+ * Canonical shape: root/category/type.
861
942
  */
862
- private findProviderDir(type: string): string | null {
943
+ private findProviderDirInternal(type: string): string | null {
863
944
  const provider = this.providers.get(type);
864
945
  if (!provider) return null;
865
946
  const cat = provider.category;
866
947
 
867
- const searchRoots = [this.userDir, this.upstreamDir, ...this.builtinDirs];
948
+ const searchRoots = this.getProviderRoots();
868
949
  for (const root of searchRoots) {
869
950
  if (!fs.existsSync(root)) continue;
870
- // Direct: root/type or root/cat/type
871
- for (const candidate of [path.join(root, type), path.join(root, cat, type)]) {
872
- if (fs.existsSync(path.join(candidate, 'provider.json'))) return candidate;
873
- }
951
+ const candidate = this.getProviderDir(root, cat, type);
952
+ if (fs.existsSync(path.join(candidate, 'provider.json'))) return candidate;
874
953
  // Scan category dir for type match
875
954
  const catDir = path.join(root, cat);
876
955
  if (fs.existsSync(catDir)) {