autosnippet 1.7.1 → 1.7.3

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.
Files changed (44) hide show
  1. package/bin/cli-commands.js +8 -4
  2. package/bin/create-snippet.js +32 -0
  3. package/bin/dashboard/routes/core.js +348 -0
  4. package/bin/dashboard/routes/search.js +28 -6
  5. package/bin/dashboard-server.js +1 -1
  6. package/checksums.json +2 -2
  7. package/dashboard/dist/assets/index-BoYBT7s4.js +76 -0
  8. package/dashboard/dist/assets/index-ZqaWRulp.css +1 -0
  9. package/dashboard/dist/assets/{react-markdown-7bJxN3JQ.js → react-markdown-DEEoHGnk.js} +1 -1
  10. package/dashboard/dist/assets/{syntax-highlighter-CeRnirGv.js → syntax-highlighter-4Pe1PNPg.js} +1 -1
  11. package/dashboard/dist/assets/{vendor-DH6lfeAo.js → vendor-CJtnAZ4B.js} +97 -67
  12. package/dashboard/dist/index.html +5 -5
  13. package/lib/ai/providers/GoogleGeminiProvider.js +20 -6
  14. package/lib/application/services/ContextServiceV2.js +8 -2
  15. package/lib/application/services/IntelligentServiceLayer.js +1 -1
  16. package/lib/application/services/SearchServiceV2.js +11 -2
  17. package/lib/cli/searchCommand.js +2 -2
  18. package/lib/context/IndexingPipeline.js +2 -1
  19. package/lib/context/WindowContextManager.js +374 -0
  20. package/lib/infrastructure/vector/VectorMath.js +47 -4
  21. package/lib/search/unifiedSearch.js +1 -1
  22. package/lib/simulation/DirectiveEmulator.js +323 -0
  23. package/lib/simulation/EditorState.js +389 -0
  24. package/lib/simulation/OperationExecutor.js +430 -0
  25. package/lib/simulation/PermissionManager.js +269 -0
  26. package/lib/simulation/SimulatorInsertionManager.js +93 -0
  27. package/lib/simulation/VirtualFileSystem.js +313 -0
  28. package/lib/simulation/XcodeSimulator.js +431 -0
  29. package/lib/simulation/XcodeSimulatorAPIClient.js +345 -0
  30. package/lib/simulation/index.js +15 -0
  31. package/lib/watch/FileWatchService.js +18 -7
  32. package/lib/watch/handlers/SearchHandler.js +43 -7
  33. package/package.json +1 -1
  34. package/resources/asd-entry/main.swift +39 -9
  35. package/scripts/clear-old-vector-index.js +77 -0
  36. package/scripts/clear-vector-cache.js +76 -0
  37. package/scripts/demo-permission-system.js +390 -0
  38. package/scripts/test-permission-manager.js +193 -0
  39. package/scripts/test-xcode-simulator-advanced.js +265 -0
  40. package/scripts/test-xcode-simulator.js +308 -0
  41. package/skills/autosnippet-candidates/SKILL.md +1 -1
  42. package/bin/dashboard/routes/search.js.bak +0 -1005
  43. package/dashboard/dist/assets/index-CEIgT22d.css +0 -1
  44. package/dashboard/dist/assets/index-PaYWyIXW.js +0 -56
@@ -25,6 +25,11 @@ function registerCommands(cmd, ctx) {
25
25
  // 配置 version 选项
26
26
  cmd.version(pjson.version, '-v, --version', 'output the current version');
27
27
 
28
+ // 全局选项(用于非交互/预置输入)
29
+ cmd
30
+ .option('-p, --preset <path>', 'preset input JSON path')
31
+ .option('-y, --yes', 'run without interactive prompts');
32
+
28
33
  function getSpecFile(callback) {
29
34
  findPath.findASSpecPath(CMD_PATH, callback);
30
35
  }
@@ -380,7 +385,7 @@ function registerCommands(cmd, ctx) {
380
385
  cmd
381
386
  .command('create')
382
387
  .alias('c')
383
- .option('-ai', '--use-ai', 'use AI to create snippet')
388
+ .option('-a, --use-ai', 'use AI to create snippet')
384
389
  .description('create an Xcode Snippet, in the file directory marked with `// autosnippet:code`')
385
390
  .action(async (options) => {
386
391
  const { preset: presetPath, yes } = getGlobalOptions();
@@ -503,7 +508,7 @@ function registerCommands(cmd, ctx) {
503
508
  const projectRoot = options.dir || process.env.ASD_CWD || CMD_PATH;
504
509
 
505
510
  // 提示用户 watch 功能已包含
506
- const isDebugMode = process.env.ASD_DEBUG_WATCH === '1' || process.env.ASD_DEBUG_SEARCH === '1';
511
+ const isDebugMode = process.env.ASD_DEBUG === '1';
507
512
  if (isDebugMode) {
508
513
  console.log('💡 调试模式已启用,将显示文件监听日志');
509
514
  }
@@ -611,8 +616,7 @@ Advanced:
611
616
  asd install:full --parser # 全量安装 + Swift 解析器
612
617
 
613
618
  Debug modes:
614
- ASD_DEBUG_WATCH=1 asd ui # Dashboard + 文件监听日志
615
- ASD_DEBUG_SEARCH=1 asd ui # Dashboard + 搜索调试日志
619
+ ASD_DEBUG=1 asd ui # 开发者模式:显示所有调试日志
616
620
 
617
621
  Notes:
618
622
  - 老命令仍可用:i/c/e/u/w/s 只是别名,不会破坏现有脚本。
@@ -221,6 +221,37 @@ function createCodeSnippets(specFile, answers, updateSnippet, selectedFilePath)
221
221
  }
222
222
  }
223
223
 
224
+ /**
225
+ * 使用预置输入创建 snippet(无交互)
226
+ * @param {string} specFile
227
+ * @param {object} preset
228
+ * @returns {Promise<boolean>}
229
+ */
230
+ async function createCodeSnippetsWithPreset(specFile, preset) {
231
+ try {
232
+ if (!preset || !preset.title || !preset.completion_first) {
233
+ console.error('❌ 预置输入缺少必要字段: title / completion_first');
234
+ return false;
235
+ }
236
+
237
+ let selectedFilePath = process.env.ASD_ACODE_FILE || null;
238
+ if (!selectedFilePath) {
239
+ const filesWithACode = await findFilesWithACode(CMD_PATH);
240
+ if (!filesWithACode.length) {
241
+ console.error('❌ 未找到包含 // autosnippet:code 标记的文件');
242
+ return false;
243
+ }
244
+ selectedFilePath = filesWithACode[0].path;
245
+ }
246
+
247
+ createCodeSnippets(specFile, preset, null, selectedFilePath);
248
+ return true;
249
+ } catch (err) {
250
+ console.error('❌ 预置创建失败:', err.message);
251
+ return false;
252
+ }
253
+ }
254
+
224
255
  function readStream(specFile, filePathArr, snippet, isHaveHeader) {
225
256
  if (filePathArr.length === 0) {
226
257
  console.log('未找到由 // as:code 或 // autosnippet:code 标识的代码块,请检查当前文件目录。');
@@ -488,6 +519,7 @@ async function createFromFileWithAi(projectRoot, specFile, selectedFilePath) {
488
519
  }
489
520
 
490
521
  exports.createCodeSnippets = createCodeSnippets;
522
+ exports.createCodeSnippetsWithPreset = createCodeSnippetsWithPreset;
491
523
  exports.updateCodeSnippets = updateCodeSnippets;
492
524
  exports.saveFromFile = saveFromFile;
493
525
  exports.findFilesWithACode = findFilesWithACode;
@@ -11,6 +11,14 @@ function registerCoreRoutes(app, ctx) {
11
11
  unescapeSnippetLine,
12
12
  } = ctx;
13
13
 
14
+ const resolveProjectPath = (inputPath) => {
15
+ if (!inputPath) return null;
16
+ const rawPath = String(inputPath);
17
+ return path.isAbsolute(rawPath)
18
+ ? path.resolve(rawPath)
19
+ : path.resolve(projectRoot, rawPath);
20
+ };
21
+
14
22
  // API: 健康检查(用于检测 Dashboard 是否运行)
15
23
  app.get('/api/health', (req, res) => {
16
24
  res.json({
@@ -180,6 +188,346 @@ function registerCoreRoutes(app, ctx) {
180
188
  res.status(500).json({ error: err.message });
181
189
  }
182
190
  });
191
+
192
+ // API: 获取文件树(仅 .h .m .swift 文件和文件夹)
193
+ app.get('/api/files/tree', (req, res) => {
194
+ try {
195
+ const rootPath = projectRoot;
196
+ const allowedExtensions = ['.h', '.m', '.swift'];
197
+
198
+ const buildTree = (dirPath, maxDepth = 10, currentDepth = 0) => {
199
+ if (currentDepth >= maxDepth) return { type: 'folder', name: '...', path: dirPath, children: [] };
200
+
201
+ try {
202
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
203
+ const children = [];
204
+
205
+ for (const entry of entries) {
206
+ // 跳过隐藏文件和常见的构建/依赖文件夹
207
+ if (entry.name.startsWith('.') ||
208
+ ['node_modules', 'build', 'dist', 'DerivedData', 'Pods', '.git'].includes(entry.name)) {
209
+ continue;
210
+ }
211
+
212
+ const fullPath = path.join(dirPath, entry.name);
213
+ const relativePath = path.relative(rootPath, fullPath);
214
+
215
+ if (entry.isDirectory()) {
216
+ const subtree = buildTree(fullPath, maxDepth, currentDepth + 1);
217
+ if (subtree.children && subtree.children.length > 0) {
218
+ children.push(subtree);
219
+ }
220
+ } else if (entry.isFile()) {
221
+ const ext = path.extname(entry.name).toLowerCase();
222
+ if (allowedExtensions.includes(ext)) {
223
+ children.push({
224
+ type: 'file',
225
+ name: entry.name,
226
+ path: fullPath,
227
+ relativePath: relativePath,
228
+ ext: ext
229
+ });
230
+ }
231
+ }
232
+ }
233
+
234
+ return {
235
+ type: 'folder',
236
+ name: path.basename(dirPath) || dirPath,
237
+ path: dirPath,
238
+ relativePath: path.relative(rootPath, dirPath) || '',
239
+ children: children.sort((a, b) => {
240
+ // 文件夹优先,然后按名字排序
241
+ if (a.type !== b.type) return a.type === 'folder' ? -1 : 1;
242
+ return a.name.localeCompare(b.name);
243
+ })
244
+ };
245
+ } catch (err) {
246
+ console.error(`[File Tree Error] ${dirPath}:`, err.message);
247
+ return { type: 'folder', name: path.basename(dirPath), path: dirPath, children: [] };
248
+ }
249
+ };
250
+
251
+ const tree = buildTree(rootPath);
252
+ res.json({ tree, projectRoot });
253
+ } catch (err) {
254
+ console.error('[API Error]', err);
255
+ res.status(500).json({ error: err.message });
256
+ }
257
+ });
258
+
259
+ // API: 获取文件树(用于 Xcode 模拟器)
260
+ app.get('/api/tree', (req, res) => {
261
+ try {
262
+ const sourceFileExts = ['.h', '.m', '.swift']; // 只显示这些扩展名的文件
263
+
264
+ const buildTree = (dirPath, maxDepth = 3, currentDepth = 0) => {
265
+ if (currentDepth >= maxDepth) return null;
266
+
267
+ if (!fs.existsSync(dirPath)) {
268
+ return null;
269
+ }
270
+
271
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
272
+ const filtered = entries.filter(e => {
273
+ if (e.name.startsWith('.')) return false;
274
+ if (e.name === 'node_modules') return false;
275
+
276
+ // 如果是文件,只保留指定扩展名的文件
277
+ if (!e.isDirectory()) {
278
+ const ext = path.extname(e.name).toLowerCase();
279
+ return sourceFileExts.includes(ext);
280
+ }
281
+
282
+ return true; // 文件夹总是保留(用于递归遍历)
283
+ });
284
+
285
+ const children = filtered.map(entry => {
286
+ const fullPath = path.join(dirPath, entry.name);
287
+ const relPath = path.relative(projectRoot, fullPath);
288
+
289
+ if (entry.isDirectory()) {
290
+ const subtree = buildTree(fullPath, maxDepth, currentDepth + 1);
291
+ // 只返回有内容的文件夹
292
+ if (subtree && subtree.children && subtree.children.length > 0) {
293
+ return {
294
+ type: 'folder',
295
+ name: entry.name,
296
+ path: relPath.replace(/\\/g, '/'),
297
+ children: subtree.children
298
+ };
299
+ }
300
+ return null; // 空文件夹不显示
301
+ } else {
302
+ return {
303
+ type: 'file',
304
+ name: entry.name,
305
+ path: relPath.replace(/\\/g, '/')
306
+ };
307
+ }
308
+ }).filter(item => item !== null) // 移除空文件夹
309
+ .sort((a, b) => {
310
+ if (a.type === b.type) return a.name.localeCompare(b.name);
311
+ return a.type === 'folder' ? -1 : 1;
312
+ });
313
+
314
+ return {
315
+ type: 'folder',
316
+ name: path.basename(dirPath),
317
+ path: path.relative(projectRoot, dirPath).replace(/\\/g, '/'),
318
+ children
319
+ };
320
+ };
321
+
322
+ const srcPath = path.join(projectRoot, 'src');
323
+ const tree = fs.existsSync(srcPath) ? buildTree(srcPath, 4) : buildTree(projectRoot, 3);
324
+ res.json(tree);
325
+ } catch (err) {
326
+ console.error('[API Error]', err);
327
+ res.status(500).json({ error: err.message });
328
+ }
329
+ });
330
+
331
+ // API: 保存文件内容(用于 Xcode 模拟器)
332
+ app.post('/api/save', (req, res) => {
333
+ try {
334
+ const { path: filePath, content } = req.body;
335
+
336
+ if (!filePath || content === undefined) {
337
+ return res.status(400).json({ error: 'Missing path or content' });
338
+ }
339
+
340
+ // 验证路径安全性
341
+ const resolvedPath = resolveProjectPath(filePath);
342
+ const projectRootResolved = path.resolve(projectRoot);
343
+
344
+ if (!resolvedPath.startsWith(projectRootResolved)) {
345
+ return res.status(403).json({ error: 'Access denied' });
346
+ }
347
+
348
+ // 确保目录存在
349
+ const dir = path.dirname(resolvedPath);
350
+ if (!fs.existsSync(dir)) {
351
+ fs.mkdirSync(dir, { recursive: true });
352
+ }
353
+
354
+ fs.writeFileSync(resolvedPath, content, 'utf8');
355
+ res.json({ success: true, path: filePath });
356
+ } catch (err) {
357
+ console.error('[API Error]', err);
358
+ res.status(500).json({ error: err.message });
359
+ }
360
+ });
361
+
362
+ // API: 执行 Xcode 编辑器中的指令(search/create/audit)
363
+ // ⚠️ 已禁用:不再通过临时文件触发 watch - 模拟器搜索处理已关闭
364
+ app.post('/api/execute', async (req, res) => {
365
+ try {
366
+ const { type, query, line, content } = req.body;
367
+
368
+ if (!type || !query) {
369
+ return res.status(400).json({ error: 'Missing type or query' });
370
+ }
371
+
372
+ console.log(`[API Execute] 模拟器搜索已禁用: type=${type}, query=${query}`);
373
+
374
+ // 对于搜索请求,直接返回搜索结果(不创建临时文件)
375
+ let searchResults = [];
376
+ if (type === 'search') {
377
+ const rootSpecPath = Paths.getProjectSpecPath(projectRoot);
378
+ try {
379
+ const rootSpec = specRepository.readSpecFile(rootSpecPath);
380
+
381
+ // 遍历所有 snippets,查找匹配的
382
+ for (const [snippetId, snippet] of Object.entries(rootSpec.snippets || {})) {
383
+ if (!snippet) continue;
384
+
385
+ const title = snippet.title || '';
386
+ const body = snippet.body || '';
387
+ const category = snippet.category || '';
388
+ const trigger = snippet.trigger || '';
389
+
390
+ // 搜索关键词匹配
391
+ if (title.toLowerCase().includes(query.toLowerCase()) ||
392
+ body.toLowerCase().includes(query.toLowerCase()) ||
393
+ trigger.toLowerCase().includes(query.toLowerCase()) ||
394
+ category.toLowerCase().includes(query.toLowerCase())) {
395
+ searchResults.push({
396
+ id: snippetId,
397
+ title: title || snippetId,
398
+ body: body,
399
+ category: category,
400
+ language: snippet.language || 'swift',
401
+ trigger: trigger
402
+ });
403
+ }
404
+ }
405
+
406
+ // 限制返回最多 10 个结果
407
+ searchResults = searchResults.slice(0, 10);
408
+ console.log(`[API Execute] 搜索到 ${searchResults.length} 个结果: ${query}`);
409
+ } catch (err) {
410
+ console.warn(`[API Execute] 搜索失败: ${err.message}`);
411
+ }
412
+ }
413
+
414
+ // 等待一段时间让 watch 处理
415
+ await new Promise(resolve => setTimeout(resolve, 2000));
416
+
417
+ // 清理临时文件(延迟 3 秒后删除,给 SearchHandler 足够的时间读取)
418
+ setTimeout(() => {
419
+ try {
420
+ if (fs.existsSync(tempFilePath)) {
421
+ fs.unlinkSync(tempFilePath);
422
+ console.log(`[API Execute] 已清理临时文件: ${tempFilePath}`);
423
+ }
424
+ } catch (err) {
425
+ console.error(`[API Execute] 清理临时文件失败: ${err.message}`);
426
+ }
427
+ }, 3000);
428
+
429
+ // 返回成功响应
430
+ res.json({
431
+ success: true,
432
+ type,
433
+ query,
434
+ line,
435
+ message: `已触发 ${type} 指令,watch 监听器正在处理...`,
436
+ results: searchResults, // 搜索结果(如果有)
437
+ timestamp: Date.now()
438
+ });
439
+ } catch (err) {
440
+ console.error('[API Execute Error]', err);
441
+ res.status(500).json({ error: err.message });
442
+ }
443
+ });
444
+
445
+ // API: 读取文件内容
446
+ app.get('/api/files/read', (req, res) => {
447
+ try {
448
+ let filePath = req.query.path || '';
449
+ // 验证路径安全性(防止路径遍历)
450
+ const resolvedPath = resolveProjectPath(filePath);
451
+ if (!resolvedPath) {
452
+ return res.status(400).json({ error: 'Missing path' });
453
+ }
454
+ const projectRootResolved = path.resolve(projectRoot);
455
+
456
+ if (!resolvedPath.startsWith(projectRootResolved)) {
457
+ return res.status(403).json({ error: 'Access denied' });
458
+ }
459
+
460
+ if (!fs.existsSync(resolvedPath)) {
461
+ return res.status(404).json({ error: 'File not found' });
462
+ }
463
+
464
+ const content = fs.readFileSync(resolvedPath, 'utf8');
465
+ res.json({
466
+ content,
467
+ path: resolvedPath,
468
+ relativePath: path.relative(projectRoot, resolvedPath).replace(/\\/g, '/')
469
+ });
470
+ } catch (err) {
471
+ console.error('[API Error]', err);
472
+ res.status(500).json({ error: err.message });
473
+ }
474
+ });
475
+
476
+ // API: 调用原生弹窗(macOS Native UI)
477
+ app.post('/api/native-dialog', async (req, res) => {
478
+ try {
479
+ const { type, title, message, options } = req.body;
480
+ const { execFileSync } = require('child_process');
481
+
482
+ // 使用 AutoSnippet 项目根目录(相对于此文件)
483
+ const autoSnippetRoot = path.resolve(__dirname, '../../..');
484
+ const nativeUiPath = path.join(autoSnippetRoot, 'resources/native-ui/native-ui');
485
+
486
+ console.log('[Native Dialog] Request:', { type, title, options });
487
+ console.log('[Native Dialog] Native UI path:', nativeUiPath);
488
+
489
+ // 检查 native-ui 是否存在
490
+ if (!fs.existsSync(nativeUiPath)) {
491
+ console.error('[Native Dialog] Binary not found at:', nativeUiPath);
492
+ return res.status(503).json({
493
+ error: 'Native UI not built',
494
+ fallback: true,
495
+ suggestion: 'Run: npm run build:native-ui'
496
+ });
497
+ }
498
+
499
+ let result = null;
500
+
501
+ if (type === 'preview') {
502
+ // 预览确认弹窗
503
+ console.log('[Native Dialog] Executing preview...');
504
+ execFileSync(nativeUiPath, ['preview', title || 'Preview', message || ''], {
505
+ stdio: ['ignore', 'pipe', 'inherit']
506
+ });
507
+ result = { confirmed: true };
508
+ console.log('[Native Dialog] Preview confirmed');
509
+ } else if (type === 'list' && options && Array.isArray(options)) {
510
+ // 列表选择弹窗
511
+ console.log('[Native Dialog] Executing list with options:', options);
512
+ const args = ['list', ...options];
513
+ const output = execFileSync(nativeUiPath, args, {
514
+ encoding: 'utf8',
515
+ stdio: ['ignore', 'pipe', 'inherit']
516
+ }).trim();
517
+ const selectedIndex = parseInt(output, 10);
518
+ result = { selectedIndex, selectedOption: options[selectedIndex] };
519
+ console.log('[Native Dialog] User selected:', result);
520
+ } else {
521
+ return res.status(400).json({ error: 'Invalid dialog type or missing options' });
522
+ }
523
+
524
+ res.json({ success: true, result });
525
+ } catch (err) {
526
+ console.error('[Native Dialog Error]', err);
527
+ // 用户取消或其他错误
528
+ res.json({ success: false, cancelled: true, error: err.message });
529
+ }
530
+ });
183
531
  }
184
532
 
185
533
  module.exports = {
@@ -168,6 +168,19 @@ function registerSearchRoutes(app, ctx) {
168
168
  }
169
169
 
170
170
  // 4. 合并和评分
171
+ // 路径标准化:移除多种前缀形式(兼容不同的数据来源)
172
+ // 源头修复:lib/context/IndexingPipeline.js 现在只保存相对路径,不含前缀
173
+ // 此函数处理来自不同来源的数据格式不一致问题
174
+ function normalizePath(pathStr) {
175
+ if (!pathStr) return pathStr;
176
+ // 移除前缀,优先级从高到低:
177
+ // 1. "recipe_" 前缀(来自向量索引的id字段)
178
+ // 2. "AutoSnippet/recipes/" 或 "AutoSnippet\\recipes\\"(旧形式的sourcePath)
179
+ return pathStr
180
+ .replace(/^recipe_/, '') // 移除 vr.id 中的 "recipe_" 前缀
181
+ .replace(/^AutoSnippet[\\/]recipes[\\/]/, ''); // 移除旧 sourcePath 前缀
182
+ }
183
+
171
184
  debug(taskId, '4️⃣ Merge & Score Start', {
172
185
  vectorCount: vectorResults.length,
173
186
  keywordCount: keywordResults.length
@@ -175,23 +188,32 @@ function registerSearchRoutes(app, ctx) {
175
188
  const mergedMap = new Map();
176
189
 
177
190
  for (const vr of vectorResults) {
178
- const key = vr.metadata?.name || vr.id || '';
191
+ const rawName = vr.metadata?.name || vr.id || '';
192
+ const normalizedName = normalizePath(rawName);
193
+ const key = normalizedName || rawName;
179
194
  if (!mergedMap.has(key)) {
180
195
  mergedMap.set(key, {
181
- name: key,
196
+ name: normalizedName,
182
197
  content: vr.content || '',
183
198
  _vectorScore: vr._vectorScore,
184
199
  _keywordScore: 0,
185
- ...vr
200
+ ...vr,
201
+ _originalName: rawName
186
202
  });
187
203
  }
188
204
  }
189
205
 
190
206
  for (const kr of keywordResults) {
191
- if (!mergedMap.has(kr.name)) {
192
- mergedMap.set(kr.name, kr);
207
+ const normalizedName = normalizePath(kr.name);
208
+ const key = normalizedName || kr.name;
209
+ if (!mergedMap.has(key)) {
210
+ mergedMap.set(key, {
211
+ ...kr,
212
+ name: normalizedName,
213
+ _originalName: kr.name
214
+ });
193
215
  } else {
194
- const existing = mergedMap.get(kr.name);
216
+ const existing = mergedMap.get(key);
195
217
  existing._keywordScore = kr._keywordScore;
196
218
  existing._contextMatches = kr._contextMatches;
197
219
  existing._isContextRelevant = kr._isContextRelevant;
@@ -132,7 +132,7 @@ async function launch(projectRoot, port = 3000, options = {}) {
132
132
  const forceBuild = options.forceBuild === true || process.env.ASD_UI_BUILD === '1' || process.env.ASD_UI_REBUILD === '1';
133
133
 
134
134
  // 1. 在后台启动 Watcher(支持调试模式)
135
- const isDebugMode = process.env.ASD_DEBUG_WATCH === '1' || process.env.ASD_DEBUG_SEARCH === '1';
135
+ const isDebugMode = process.env.ASD_DEBUG === '1';
136
136
  if (isDebugMode) {
137
137
  console.log(`[Dashboard] 正在启动项目监听器(调试模式)...`);
138
138
  } else {
package/checksums.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "bin/asd-cli.js": "858bb8c4a13969e6f0c89e86ee501ebeedc024d80522484b5228358711b02bdb",
3
- "bin/dashboard-server.js": "07eb8b5c75ac39fa6ff4178aa4a68476fc243649d4e2385e1da4f1dfe2f726cc",
3
+ "bin/dashboard-server.js": "e51705f6e4e96515555ad96885ebcf4791a5091d79c795a479004c46c5fed1b1",
4
4
  "lib/writeGuard.js": "74213c17149406d8c4f8ca0fb41c4da05e59fc105d9052124c799bd8343ab37d",
5
5
  "lib/rateLimit.js": "c93b1bace6535b75ee6c0f2184c7176dd7b6bc2398cb1f93832b1c7c7374bc1e",
6
6
  "lib/services/context/ContextService.js": "76d595e5b311a8b75a77483c1b35120245a8e4d80186ea648947e84d1f89bae1",
7
- "lib/application/services/ContextServiceV2.js": "032a6a9c67c50ba3a532c0c70dc31661dc599f276032305283cfa0e98930da4b",
7
+ "lib/application/services/ContextServiceV2.js": "808bd0f495e12289e0351f76a0587d80768b7cb36626fba9bbcbdead7b8fe761",
8
8
  "lib/context/adapters/MilvusAdapter.js": "b5438d013b78b73cf4c15d4f480737abe4bc03c82271e949c11702426b57c2c2",
9
9
  "lib/context/adapters/JsonAdapter.js": "49fbd46f32ace04ec0ddac1195b61c16f9906d9047ab5824a8a0cb55ecbcbc4d",
10
10
  "lib/ai/AiFactory.js": "fa759c85afa8014e5c23ed5f30b406619a8412baeb594d62470d2ac3c35d97f3",