@cannbot-ai/install-helper 1.1.14 → 1.1.15-beta.0

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.js CHANGED
@@ -48,567 +48,6 @@ var init_fs_helpers = __esm({
48
48
  }
49
49
  });
50
50
 
51
- // src/embedded-plugins.json
52
- var embedded_plugins_default;
53
- var init_embedded_plugins = __esm({
54
- "src/embedded-plugins.json"() {
55
- embedded_plugins_default = [
56
- {
57
- id: "ops-direct-invoke",
58
- dir: "plugins-official/ops-direct-invoke",
59
- displayName: "AscendC Kernel \u76F4\u8C03",
60
- script: "init.sh",
61
- aliases: [
62
- "ops-direct",
63
- "ascendc-direct",
64
- "direct",
65
- "kernel"
66
- ],
67
- skills: 0,
68
- agents: 6,
69
- description: "skill \u9A71\u52A8\u591A\u89D2\u8272\u76F4\u8C03\u7B97\u5B50\u5F00\u53D1\u5DE5\u4F5C\u6D41\uFF1APM \u8C03\u5EA6 architect/developer/qa \u56E2\u961F\uFF0C8 \u9636\u6BB5 7 CP \u5168\u6D41\u7A0B\uFF0C\u652F\u6301\u9759\u9ED8\u6A21\u5F0F\u4E0E\u7B97\u5B50\u4ED3\u7EE7\u627F\u5B9A\u5236",
70
- version: "2.0.0",
71
- configFile: "AGENTS.md",
72
- configRootConfigLink: false,
73
- installSkills: [],
74
- installAgents: [
75
- "architect",
76
- "developer",
77
- "developer-code",
78
- "developer-doc",
79
- "developer-test",
80
- "qa"
81
- ]
82
- },
83
- {
84
- id: "ops-direct-invoke-flash",
85
- dir: "plugins-official/ops-direct-invoke-flash",
86
- displayName: "AscendC Kernel \u76F4\u8C03\uFF08\u5FEB\u901F\u7248\uFF09",
87
- script: "init.sh",
88
- aliases: [
89
- "flash",
90
- "kernel-flash"
91
- ],
92
- skills: 7,
93
- agents: 1,
94
- description: "\u4ECE\u6570\u5B66\u516C\u5F0F\u6216\u4EE3\u7801\u7247\u6BB5\u5FEB\u901F\u6784\u5EFA\u5E76\u9A8C\u8BC1 Ascend NPU \u6838\u51FD\u6570",
95
- version: "1.2.2",
96
- configFile: "AGENTS.md",
97
- configRootConfigLink: true,
98
- installSkills: [
99
- {
100
- dir: "plugins-official/ops-direct-invoke-flash/skills",
101
- skills: [
102
- "ops-direct-invoke-flash"
103
- ]
104
- },
105
- {
106
- dir: "ops",
107
- skills: [
108
- "ascendc-st-design",
109
- "ascendc-whitebox-design"
110
- ]
111
- },
112
- {
113
- dir: "infra",
114
- skills: [
115
- "gitcode-toolkit",
116
- "gitcode-pr-handler",
117
- "gitcode-issue-gen",
118
- "gitcode-issue-handler"
119
- ]
120
- }
121
- ],
122
- installAgents: [
123
- "ops-direct-invoke-flash-reviewer"
124
- ]
125
- },
126
- {
127
- id: "ops-registry-invoke",
128
- dir: "plugins-official/ops-registry-invoke",
129
- displayName: "AscendC \u7B97\u5B50\u6CE8\u518C\u8C03\u7528",
130
- script: "init.sh",
131
- aliases: [
132
- "ops-registry",
133
- "ascendc-registry",
134
- "registry"
135
- ],
136
- skills: 30,
137
- agents: 7,
138
- description: "\u751F\u4EA7\u7EA7 ACLNN \u6CE8\u518C\u7B97\u5B50\u5168\u6D41\u7A0B\uFF1A\u4EE3\u7801\u2192UT/ST\u2192\u4E0A\u5E93",
139
- version: "1.2.3",
140
- configFile: "AGENTS.md",
141
- configRootConfigLink: false,
142
- installSkills: [
143
- {
144
- dir: "ops",
145
- skills: [
146
- "ascendc-blaze-best-practice",
147
- "ascendc-blaze-migration",
148
- "ascendc-api-best-practices",
149
- "ascendc-code-review",
150
- "ascendc-crash-debug",
151
- "ascendc-direct-invoke-template",
152
- "ascendc-docs-gen",
153
- "ascendc-docs-search",
154
- "ascendc-env-check",
155
- "npu-arch",
156
- "ascendc-performance-best-practices",
157
- "ascendc-precision-debug",
158
- "ascendc-perf-optimize",
159
- "ascendc-regbase-best-practice",
160
- "ascendc-registry-invoke-template",
161
- "ascendc-runtime-debug",
162
- "ascendc-st-design",
163
- "ascendc-tiling-design",
164
- "ascendc-ut-develop",
165
- "ascendc-whitebox-design",
166
- "ops-precision-standard",
167
- "ops-profiling",
168
- "ops-simulator",
169
- "ops-spec-gen"
170
- ]
171
- },
172
- {
173
- dir: "infra",
174
- skills: [
175
- "gitcode-toolkit",
176
- "gitcode-pr-handler",
177
- "gitcode-issue-gen",
178
- "gitcode-issue-handler"
179
- ]
180
- },
181
- {
182
- dir: "plugins-official/ops-registry-invoke",
183
- skills: [
184
- {
185
- name: "workflow",
186
- as: "ops-registry-invoke-workflow"
187
- }
188
- ]
189
- },
190
- {
191
- dir: "plugins-official/ops-registry-invoke/skills",
192
- skills: [
193
- "spec-to-design"
194
- ]
195
- }
196
- ],
197
- installAgents: [
198
- "ascendc-ops-architect",
199
- "ascendc-ops-spec-reviewer",
200
- "ascendc-ops-designer",
201
- "ascendc-ops-design-reviewer",
202
- "ascendc-ops-tester",
203
- "ascendc-ops-test-design-reviewer",
204
- "ascendc-ops-developer"
205
- ],
206
- externalRepos: [
207
- {
208
- url: "https://gitcode.com/cann/asc-devkit.git",
209
- dir: "plugins-official/ops-registry-invoke/reference/cann/asc-devkit",
210
- depth: 1,
211
- configRootLink: false
212
- },
213
- {
214
- url: "https://gitcode.com/cann/ops-tensor.git",
215
- dir: "plugins-official/ops-registry-invoke/ops-tensor",
216
- configRootLink: false
217
- }
218
- ]
219
- },
220
- {
221
- id: "catlass-op-generator",
222
- dir: "plugins-official/catlass-op-generator",
223
- displayName: "Catlass \u7B97\u5B50\u76F4\u8C03",
224
- script: "init.sh",
225
- aliases: [
226
- "catlass"
227
- ],
228
- skills: 14,
229
- agents: 3,
230
- description: "Catlass \u6A21\u677F\u62FC\u88C5 GEMM/Matmul/Epilogue \u7B97\u5B50\u5F00\u53D1",
231
- version: "1.0.0",
232
- configFile: "AGENTS.md",
233
- configRootConfigLink: true,
234
- installSkills: [
235
- {
236
- dir: "ops",
237
- skills: [
238
- "catlass-op-design",
239
- "catlass-op-develop",
240
- "catlass-op-perf-tune",
241
- "ascendc-tiling-design",
242
- "npu-arch",
243
- "ascendc-api-best-practices",
244
- "ops-precision-standard",
245
- "ascendc-docs-search",
246
- "ascendc-env-check",
247
- "ascendc-precision-debug",
248
- "ops-profiling",
249
- "ascendc-runtime-debug",
250
- "ascendc-code-review",
251
- "torch-ascendc-op-extension"
252
- ]
253
- }
254
- ],
255
- installAgents: [
256
- "catlass-op-architect",
257
- "catlass-op-generator",
258
- "catlass-op-reviewer"
259
- ],
260
- externalRepos: [
261
- {
262
- url: "https://gitcode.com/cann/asc-devkit.git",
263
- dir: "plugins-official/catlass-op-generator/asc-devkit",
264
- configRootLink: false
265
- }
266
- ]
267
- },
268
- {
269
- id: "model-infer-optimize",
270
- dir: "plugins-official/model-infer-optimize",
271
- displayName: "NPU \u63A8\u7406\u4F18\u5316",
272
- script: "init.sh",
273
- aliases: [
274
- "model-infer",
275
- "infer",
276
- "inference",
277
- "sota",
278
- "sota-approach",
279
- "model-infer-sota"
280
- ],
281
- skills: 14,
282
- agents: 9,
283
- description: "NPU \u6A21\u578B\u63A8\u7406\u7AEF\u5230\u7AEF\u4F18\u5316\uFF0C\u6DB5\u76D6\u56FA\u5B9A\u9636\u6BB5\u4F18\u5316\uFF08\u5E76\u884C/KVCache/\u878D\u5408/\u91CF\u5316/\u56FE\u6A21\u5F0F\uFF09\u4E0E baseline \u4E4B\u4E0A profiling \u9A71\u52A8\u7684\u63A2\u7D22\u5F0F\u4F18\u5316\uFF08\u6309\u9700\u8C03\u7528\u591A\u6D41/\u9884\u53D6/SuperKernel \u7B49\u5355\u70B9\u4F18\u5316\uFF09",
284
- version: "1.0.6",
285
- configFile: "AGENTS.md",
286
- configRootConfigLink: true,
287
- installSkills: [
288
- {
289
- dir: "model",
290
- skills: [
291
- "model-infer-migrator",
292
- "model-infer-parallel-analysis",
293
- "model-infer-parallel-impl",
294
- "model-infer-kvcache",
295
- "model-infer-fusion",
296
- "model-infer-quantization",
297
- "model-infer-graph-mode",
298
- "model-infer-precision-debug",
299
- "model-infer-runtime-debug",
300
- "model-infer-multi-stream",
301
- "model-infer-prefetch",
302
- "model-infer-superkernel",
303
- "model-infer-profiling",
304
- "model-infer-perf-breakdown"
305
- ]
306
- }
307
- ],
308
- installAgents: [
309
- "model-infer-analyzer",
310
- "model-infer-implementer",
311
- "model-infer-reviewer",
312
- "model-infer-sota-scenario",
313
- "model-infer-sota-profiling-instrumenter",
314
- "model-infer-sota-profile-analyzer",
315
- "model-infer-sota-candidate",
316
- "model-infer-sota-implementer",
317
- "model-infer-sota-reviewer"
318
- ],
319
- externalRepos: [
320
- {
321
- url: "https://gitcode.com/cann/cann-recipes-infer.git",
322
- dir: "plugins-official/model-infer-optimize/cann-recipes-infer",
323
- depth: 1,
324
- configRootLink: true
325
- }
326
- ]
327
- },
328
- {
329
- id: "pypto-op-orchestrator",
330
- dir: "plugins-official/pypto-op-orchestrator",
331
- displayName: "PyPTO \u7B97\u5B50\u5F00\u53D1",
332
- script: "init.sh",
333
- aliases: [
334
- "pypto",
335
- "pytorch"
336
- ],
337
- skills: 17,
338
- agents: 8,
339
- description: "PyPTO Python API \u7B97\u5B50\u5168\u6D41\u7A0B\u5F00\u53D1\uFF0C\u8986\u76D6\u9700\u6C42\u7406\u89E3\u3001API \u63A2\u7D22\u3001\u5B9E\u73B0\u4E0E\u8C03\u4F18",
340
- version: "1.2.0",
341
- configFile: "AGENTS.md",
342
- configRootConfigLink: false,
343
- installSkills: [
344
- {
345
- dir: "ops",
346
- skills: [
347
- "pypto-orchestration-manual",
348
- "pypto-intent-understand",
349
- "pypto-op-plan",
350
- "pypto-api-explore",
351
- "pypto-docs-search",
352
- "pypto-golden-generate",
353
- "pypto-op-design",
354
- "pypto-op-construct",
355
- "pypto-op-develop",
356
- "pypto-op-verify",
357
- "pypto-op-review",
358
- "pypto-precision-compare",
359
- "pypto-precision-debug",
360
- "pypto-general-debug",
361
- "pypto-op-perf-tune",
362
- "pypto-op-knowledge",
363
- "pypto-memory-template"
364
- ]
365
- }
366
- ],
367
- installAgents: [
368
- "pypto-op-planner",
369
- "pypto-op-mathematician",
370
- "pypto-op-architect",
371
- "pypto-op-designer",
372
- "pypto-op-coder",
373
- "pypto-op-verifier",
374
- "pypto-op-debugger",
375
- "pypto-op-optimizer"
376
- ],
377
- externalRepos: [
378
- {
379
- url: "https://gitcode.com/cann/pypto.git",
380
- dir: "plugins-official/pypto-op-orchestrator/pypto",
381
- configRootLink: false
382
- }
383
- ]
384
- },
385
- {
386
- id: "tilelang-op-orchestrator",
387
- dir: "plugins-official/tilelang-op-orchestrator",
388
- displayName: "TileLang \u7B97\u5B50\u5F00\u53D1",
389
- script: "init.sh",
390
- aliases: [
391
- "tilelang"
392
- ],
393
- skills: 9,
394
- agents: 3,
395
- description: "TileLang Python DSL + @tilelang.jit \u7B97\u5B50\u5F00\u53D1\uFF08\u652F\u6301 Developer/Expert \u53CC\u6A21\u5F0F\uFF09",
396
- version: "1.1.0",
397
- configFile: "AGENTS.md",
398
- configRootConfigLink: false,
399
- installSkills: [
400
- {
401
- dir: "ops",
402
- skills: [
403
- "tilelang-api-best-practices",
404
- "tilelang-env-check",
405
- "tilelang-op-design",
406
- "tilelang-op-develop",
407
- "tilelang-op-test-design",
408
- "tilelang-perf-optimization",
409
- "tilelang-programming-model-guide",
410
- "tilelang-review",
411
- "tilelang-submodule-pull"
412
- ]
413
- }
414
- ],
415
- installAgents: [
416
- "tilelang-op-analyst",
417
- "tilelang-op-developer",
418
- "tilelang-op-perf-tuner"
419
- ],
420
- externalRepos: [
421
- {
422
- url: "https://github.com/tile-ai/tilelang-ascend.git",
423
- dir: "plugins-official/tilelang-op-orchestrator/tilelang-ascend",
424
- depth: 1,
425
- recursive: true,
426
- configRootLink: false
427
- }
428
- ]
429
- },
430
- {
431
- id: "triton-op-generator",
432
- dir: "plugins-official/triton-op-generator",
433
- displayName: "Triton \u7B97\u5B50\u5F00\u53D1",
434
- script: "init.sh",
435
- aliases: [
436
- "triton"
437
- ],
438
- skills: 8,
439
- agents: 0,
440
- description: "Triton-Ascend \u7B97\u5B50 6 \u9636\u6BB5\u81EA\u52A8\u751F\u6210\u4E0E\u4F18\u5316\uFF08\u63CF\u8FF0\u2192\u4EE3\u7801\u2192\u9A8C\u8BC1\u2192\u4F18\u5316\uFF09",
441
- version: "1.0.2",
442
- configFile: "AGENTS.md",
443
- configRootConfigLink: false,
444
- installSkills: [
445
- {
446
- dir: "ops",
447
- skills: [
448
- "triton-task-extractor",
449
- "triton-op-designer",
450
- "triton-op-coding",
451
- "triton-op-verifier",
452
- "triton-latency-optimizer",
453
- "triton-precision-debug",
454
- "npu-arch",
455
- "triton-simulator-optimizer"
456
- ]
457
- }
458
- ],
459
- installAgents: []
460
- },
461
- {
462
- id: "torch-compile",
463
- dir: "plugins-official/torch-compile",
464
- displayName: "torch.compile \u56FE\u6A21\u5F0F",
465
- script: "init.sh",
466
- aliases: [
467
- "torch",
468
- "compile",
469
- "graph"
470
- ],
471
- skills: 7,
472
- agents: 1,
473
- description: "NPU \u56FE\u6A21\u5F0F npugraph_ex \u914D\u7F6E\u3001\u811A\u672C\u8FC1\u79FB\u3001\u7F16\u8BD1\u8BCA\u65AD\u4E0E\u81EA\u5B9A\u4E49\u7B97\u5B50\u5165\u56FE",
474
- version: "1.0.4",
475
- configFile: "AGENTS.md",
476
- configRootConfigLink: true,
477
- installSkills: [
478
- {
479
- dir: "graph",
480
- skills: [
481
- "torch-npugraph-ex-knowledge",
482
- "torch-npugraph-ex-template",
483
- "torch-npugraph-ex-dfx-triage",
484
- "torch-npugraph-ex-compile-error-diagnosis",
485
- "torch-npugraph-ex-runtime-error-diagnosis",
486
- "torch-npugraph-ex-performance-diagnosis",
487
- "torch-custom-ops-guide"
488
- ]
489
- }
490
- ],
491
- installAgents: [
492
- "torch-npugraph-ex"
493
- ]
494
- },
495
- {
496
- id: "ops-code-reviewer",
497
- dir: "plugins-official/ops-code-reviewer",
498
- displayName: "\u4EE3\u7801\u68C0\u89C6",
499
- script: "init.sh",
500
- aliases: [
501
- "code-review",
502
- "reviewer",
503
- "review"
504
- ],
505
- skills: 4,
506
- agents: 2,
507
- description: "Ascend C \u7B97\u5B50\u4EE3\u7801 4 \u9636\u6BB5\u5168\u91CF\u68C0\u89C6\uFF08\u4E3B Agent \u7F16\u6392 + \u5B50 Agent \u5E76\u884C\u68C0\u89C6\uFF09",
508
- version: "1.1.0",
509
- configFile: "AGENTS.md",
510
- configRootConfigLink: false,
511
- installSkills: [
512
- {
513
- dir: "ops",
514
- skills: [
515
- "ascendc-code-review",
516
- "ascendc-docs-search",
517
- "ascendc-api-best-practices",
518
- "npu-arch"
519
- ]
520
- }
521
- ],
522
- installAgents: [
523
- "ascendc-ops-reviewer",
524
- "ascendc-code-summarizer"
525
- ]
526
- }
527
- ];
528
- }
529
- });
530
-
531
- // src/core/registry.ts
532
- import { readdirSync, existsSync } from "fs";
533
- import { join } from "path";
534
- function loadPlugins() {
535
- const plugins = [...embedded_plugins_default];
536
- plugins.sort(
537
- (a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0
538
- );
539
- return plugins;
540
- }
541
- function mergeDynamicPlugins(repoPath) {
542
- if (!existsSync(repoPath)) return;
543
- const existingIds = new Set(PLUGIN_REGISTRY.map((p) => p.id));
544
- const dynamic = [];
545
- for (const pluginDir of PLUGIN_DIRS) {
546
- const parent = join(repoPath, pluginDir);
547
- if (!existsSync(parent)) continue;
548
- let entries = [];
549
- try {
550
- entries = readdirSync(parent);
551
- } catch {
552
- continue;
553
- }
554
- for (const entry of entries) {
555
- const pluginPath = join(parent, entry);
556
- if (!isDirectory(pluginPath)) continue;
557
- if (entry === "install-helper") continue;
558
- const initSh = join(pluginPath, "init.sh");
559
- if (!existsSync(initSh)) continue;
560
- const pluginId = entry;
561
- if (existingIds.has(pluginId)) continue;
562
- dynamic.push({
563
- id: pluginId,
564
- dir: `${pluginDir}/${entry}`,
565
- displayName: entry,
566
- script: "init.sh",
567
- aliases: [],
568
- skills: 0,
569
- agents: 0,
570
- description: ""
571
- });
572
- existingIds.add(pluginId);
573
- }
574
- }
575
- if (dynamic.length > 0) {
576
- PLUGIN_REGISTRY = [...PLUGIN_REGISTRY, ...dynamic].sort(
577
- (a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0
578
- );
579
- }
580
- }
581
- function findPlugin(query) {
582
- const normalized = query.toLowerCase().trim();
583
- const exactMatch = PLUGIN_REGISTRY.find(
584
- (p) => p.id === normalized || p.id === query.trim()
585
- );
586
- if (exactMatch) return exactMatch;
587
- const aliasMatch = PLUGIN_REGISTRY.find(
588
- (p) => p.aliases.some((a) => a === normalized)
589
- );
590
- if (aliasMatch) return aliasMatch;
591
- const prefixMatches = PLUGIN_REGISTRY.filter((p) => p.id.startsWith(normalized));
592
- if (prefixMatches.length === 1) return prefixMatches[0];
593
- return void 0;
594
- }
595
- function getAllPlugins() {
596
- return PLUGIN_REGISTRY;
597
- }
598
- function getPluginById(id) {
599
- return PLUGIN_REGISTRY.find((p) => p.id === id);
600
- }
601
- var PLUGIN_REGISTRY, PLUGIN_DIRS;
602
- var init_registry = __esm({
603
- "src/core/registry.ts"() {
604
- "use strict";
605
- init_fs_helpers();
606
- init_embedded_plugins();
607
- PLUGIN_REGISTRY = loadPlugins();
608
- PLUGIN_DIRS = ["plugins-official", "plugins-community"];
609
- }
610
- });
611
-
612
51
  // src/locales/zh_CN.json
613
52
  var zh_CN_default;
614
53
  var init_zh_CN = __esm({
@@ -714,7 +153,7 @@ var init_zh_CN = __esm({
714
153
  info_aliases: "\u522B\u540D",
715
154
  uninstall_not_found: "\u672A\u627E\u5230",
716
155
  uninstall_no_record: "\u672A\u627E\u5230\u5B89\u88C5\u8BB0\u5F55\uFF0C\u53EF\u80FD\u672A\u5B89\u88C5\u6216\u5B89\u88C5\u8BB0\u5F55\u5DF2\u635F\u574F",
717
- uninstall_no_record_hint: "\u5982\u9700\u5F3A\u5236\u6E05\u7406\uFF0C\u8BF7\u624B\u52A8\u5220\u9664 .opencode/ \u6216 .claude/ \u76EE\u5F55\u4E2D\u7684\u76F8\u5173\u6587\u4EF6",
156
+ uninstall_no_record_hint: "\u5982\u9700\u5F3A\u5236\u6E05\u7406\uFF0C\u8BF7\u624B\u52A8\u5220\u9664\u5BF9\u5E94\u5DE5\u5177\u914D\u7F6E\u76EE\u5F55\u4E2D\u7684\u76F8\u5173\u6587\u4EF6\uFF08\u5982 .opencode/\u3001.claude/\u3001.trae/\u3001.cursor/\u3001.codex/ \u4E0E .agents/\u3001.github/\u3001.codeartsdoer/\uFF09",
718
157
  uninstall_in_progress: "\u6B63\u5728\u5378\u8F7D",
719
158
  uninstall_summary_format: "{name}\uFF08\u79FB\u9664 {files} \u4E2A\u6587\u4EF6\uFF0C{dirs} \u4E2A\u76EE\u5F55\uFF09",
720
159
  uninstall_files_gone: "\u7684\u6587\u4EF6\u5DF2\u4E0D\u5B58\u5728\uFF0C\u5DF2\u6E05\u7406\u5B89\u88C5\u8BB0\u5F55",
@@ -939,7 +378,7 @@ var init_en_US = __esm({
939
378
  info_aliases: "Aliases",
940
379
  uninstall_not_found: "Not found",
941
380
  uninstall_no_record: "No install record found, may not be installed or record is corrupted",
942
- uninstall_no_record_hint: "For manual cleanup, delete related files in .opencode/ or .claude/ directory",
381
+ uninstall_no_record_hint: "For manual cleanup, delete related files in the tool's config directory (e.g. .opencode/, .claude/, .trae/, .cursor/, .codex/ with .agents/, .github/, .codeartsdoer/)",
943
382
  uninstall_in_progress: "Uninstalling",
944
383
  uninstall_summary_format: "{name} (removed {files} files, {dirs} directories)",
945
384
  uninstall_files_gone: " files no longer exist, install record cleaned",
@@ -1060,22 +499,22 @@ var init_en_US = __esm({
1060
499
  });
1061
500
 
1062
501
  // src/utils/i18n.ts
1063
- import { readFileSync, existsSync as existsSync2 } from "fs";
1064
- import { join as join2, dirname } from "path";
502
+ import { readFileSync, existsSync } from "fs";
503
+ import { join, dirname } from "path";
1065
504
  import { fileURLToPath } from "url";
1066
505
  function loadLocale(locale) {
1067
506
  const embedded = EMBEDDED_LOCALES[locale];
1068
507
  if (embedded) return embedded;
1069
- const localePath = join2(__dirname, "locales", `${locale}.json`);
1070
- if (existsSync2(localePath)) {
508
+ const localePath = join(__dirname, "locales", `${locale}.json`);
509
+ if (existsSync(localePath)) {
1071
510
  try {
1072
511
  const content = readFileSync(localePath, "utf-8");
1073
512
  return JSON.parse(content);
1074
513
  } catch {
1075
514
  }
1076
515
  }
1077
- const fallbackPath = join2(__dirname, "locales", "zh_CN.json");
1078
- if (existsSync2(fallbackPath)) {
516
+ const fallbackPath = join(__dirname, "locales", "zh_CN.json");
517
+ if (existsSync(fallbackPath)) {
1079
518
  try {
1080
519
  const content = readFileSync(fallbackPath, "utf-8");
1081
520
  return JSON.parse(content);
@@ -1110,8 +549,8 @@ var init_i18n = __esm({
1110
549
 
1111
550
  // src/utils/paths.ts
1112
551
  import { homedir } from "os";
1113
- import { join as join3 } from "path";
1114
- import { existsSync as existsSync3 } from "fs";
552
+ import { join as join2 } from "path";
553
+ import { existsSync as existsSync2 } from "fs";
1115
554
  function validateTool(tool) {
1116
555
  if (!VALID_TOOLS.includes(tool)) {
1117
556
  throw new Error(
@@ -1130,9 +569,9 @@ function validateLevel(level) {
1130
569
  }
1131
570
  function detectTraeVariant() {
1132
571
  const home = homedir();
1133
- if (existsSync3(join3(home, ".trae-cn"))) return "ide";
1134
- if (existsSync3(join3(home, ".marscode"))) return "plugin";
1135
- if (existsSync3(join3(home, ".traecli"))) return "cli";
572
+ if (existsSync2(join2(home, ".trae-cn"))) return "ide";
573
+ if (existsSync2(join2(home, ".marscode"))) return "plugin";
574
+ if (existsSync2(join2(home, ".traecli"))) return "cli";
1136
575
  return "unknown";
1137
576
  }
1138
577
  function getConfigRoot(tool, level, base) {
@@ -1140,28 +579,28 @@ function getConfigRoot(tool, level, base) {
1140
579
  if (level === "global") {
1141
580
  switch (tool) {
1142
581
  case "opencode":
1143
- return join3(home, ".config", "opencode");
582
+ return join2(home, ".config", "opencode");
1144
583
  case "claude":
1145
- return join3(home, ".claude");
584
+ return join2(home, ".claude");
1146
585
  case "trae": {
1147
586
  const variant = detectTraeVariant();
1148
587
  switch (variant) {
1149
588
  case "plugin":
1150
- return join3(home, ".marscode");
589
+ return join2(home, ".marscode");
1151
590
  case "cli":
1152
- return join3(home, ".traecli");
591
+ return join2(home, ".traecli");
1153
592
  default:
1154
- return join3(home, ".trae-cn");
593
+ return join2(home, ".trae-cn");
1155
594
  }
1156
595
  }
1157
596
  case "cursor":
1158
- return join3(home, ".cursor");
597
+ return join2(home, ".cursor");
1159
598
  case "codex":
1160
- return join3(home, ".codex");
599
+ return join2(home, ".codex");
1161
600
  case "copilot":
1162
- return join3(home, ".copilot");
601
+ return join2(home, ".copilot");
1163
602
  case "codearts":
1164
- return join3(home, ".codeartsdoer");
603
+ return join2(home, ".codeartsdoer");
1165
604
  default:
1166
605
  throw new Error(
1167
606
  t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
@@ -1171,76 +610,887 @@ function getConfigRoot(tool, level, base) {
1171
610
  const baseDir = base || process.cwd();
1172
611
  switch (tool) {
1173
612
  case "opencode":
1174
- return join3(baseDir, ".opencode");
613
+ return join2(baseDir, ".opencode");
1175
614
  case "claude":
1176
- return join3(baseDir, ".claude");
615
+ return join2(baseDir, ".claude");
1177
616
  case "trae": {
1178
617
  const variant = detectTraeVariant();
1179
618
  switch (variant) {
1180
619
  case "plugin":
1181
- return join3(baseDir, ".marscode");
620
+ return join2(baseDir, ".marscode");
1182
621
  case "cli":
1183
- return join3(baseDir, ".traecli");
622
+ return join2(baseDir, ".traecli");
1184
623
  default:
1185
- return join3(baseDir, ".trae");
624
+ return join2(baseDir, ".trae");
625
+ }
626
+ }
627
+ case "cursor":
628
+ return join2(baseDir, ".cursor");
629
+ case "codex":
630
+ return join2(baseDir, ".codex");
631
+ case "copilot":
632
+ return join2(baseDir, ".github");
633
+ case "codearts":
634
+ return join2(baseDir, ".codeartsdoer");
635
+ default:
636
+ throw new Error(
637
+ t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
638
+ );
639
+ }
640
+ }
641
+ function getConfigFileName(tool) {
642
+ return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
643
+ }
644
+ function getSkillsRoot(tool, level, base) {
645
+ if (tool === "codex") {
646
+ if (level === "global") {
647
+ return join2(homedir(), ".agents", "skills");
648
+ }
649
+ return join2(base || process.cwd(), ".agents", "skills");
650
+ }
651
+ return join2(getConfigRoot(tool, level, base), "skills");
652
+ }
653
+ function getAgentsFileName(tool) {
654
+ return getConfigFileName(tool);
655
+ }
656
+ function getAgentsDir(configRoot) {
657
+ return join2(configRoot, "agents");
658
+ }
659
+ function getManifestPath(configRoot) {
660
+ return join2(configRoot, "cannbot-manifest.json");
661
+ }
662
+ function getCannbotConfigDir() {
663
+ return join2(homedir(), ".cannbot");
664
+ }
665
+ function getCannbotRepoPath() {
666
+ return join2(getCannbotConfigDir(), "repo");
667
+ }
668
+ var VALID_TOOLS, VALID_LEVELS;
669
+ var init_paths = __esm({
670
+ "src/utils/paths.ts"() {
671
+ "use strict";
672
+ init_i18n();
673
+ VALID_TOOLS = ["opencode", "claude", "trae", "cursor", "codex", "copilot", "codearts"];
674
+ VALID_LEVELS = ["project", "global"];
675
+ }
676
+ });
677
+
678
+ // src/utils/fs.ts
679
+ import { writeFileSync, renameSync, existsSync as existsSync3, unlinkSync as unlinkSync2 } from "fs";
680
+ import { dirname as dirname2 } from "path";
681
+ function atomicWriteFileSync(filePath, data, encoding = "utf-8") {
682
+ const dir = dirname2(filePath);
683
+ if (!existsSync3(dir)) {
684
+ throw new Error(`Directory does not exist: ${dir}`);
685
+ }
686
+ const tmpPath = `${filePath}.tmp`;
687
+ writeFileSync(tmpPath, data, encoding);
688
+ try {
689
+ renameSync(tmpPath, filePath);
690
+ } catch (e) {
691
+ try {
692
+ unlinkSync2(tmpPath);
693
+ } catch {
694
+ }
695
+ throw e;
696
+ }
697
+ }
698
+ var init_fs = __esm({
699
+ "src/utils/fs.ts"() {
700
+ "use strict";
701
+ }
702
+ });
703
+
704
+ // src/core/scanner.ts
705
+ import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync2, mkdirSync } from "fs";
706
+ import { join as join3, dirname as dirname3 } from "path";
707
+ import { fileURLToPath as fileURLToPath2 } from "url";
708
+ import { parse as parseYaml } from "yaml";
709
+ function loadScanConfig() {
710
+ const configCandidates = [
711
+ join3(__dirname2, "config", "repository.yaml"),
712
+ join3(__dirname2, "..", "config", "repository.yaml")
713
+ ];
714
+ for (const configPath of configCandidates) {
715
+ try {
716
+ const config = parseYaml(readFileSync2(configPath, "utf-8"));
717
+ if (!config) continue;
718
+ const ttlHours = config.scanCacheTtlHours || 24;
719
+ return {
720
+ skillDirs: config.scanDirs || ["ops", "model", "graph", "infra", "runtime"],
721
+ pluginDirs: config.pluginDirs || ["plugins-official", "plugins-community"],
722
+ cacheTtlMs: ttlHours * 60 * 60 * 1e3
723
+ };
724
+ } catch {
725
+ }
726
+ }
727
+ return {
728
+ skillDirs: ["ops", "model", "graph", "infra", "runtime"],
729
+ pluginDirs: ["plugins-official", "plugins-community"],
730
+ cacheTtlMs: 24 * 60 * 60 * 1e3
731
+ };
732
+ }
733
+ function getScanDirs() {
734
+ return [...SKILL_SCAN_DIRS];
735
+ }
736
+ function getPluginDirs() {
737
+ return [...PLUGIN_SCAN_DIRS];
738
+ }
739
+ function scanSkills(repoPath) {
740
+ const skills = [];
741
+ const seen = /* @__PURE__ */ new Set();
742
+ for (const dir of SKILL_SCAN_DIRS) {
743
+ const fullPath = join3(repoPath, dir);
744
+ if (!existsSync4(fullPath)) continue;
745
+ scanDirectory(fullPath, repoPath, dir, skills, seen);
746
+ }
747
+ for (const pluginDir of PLUGIN_SCAN_DIRS) {
748
+ const pluginParent = join3(repoPath, pluginDir);
749
+ if (!existsSync4(pluginParent)) continue;
750
+ for (const plugin of safeReaddir(pluginParent)) {
751
+ const pluginPath = join3(pluginParent, plugin);
752
+ if (!isDirectory(pluginPath)) continue;
753
+ const skillsDir = join3(pluginPath, "skills");
754
+ if (existsSync4(skillsDir)) {
755
+ scanDirectory(skillsDir, repoPath, `${pluginDir}/${plugin}/skills`, skills, seen);
756
+ }
757
+ const skillDir = join3(pluginPath, "skill");
758
+ if (existsSync4(skillDir)) {
759
+ scanDirectory(skillDir, repoPath, `${pluginDir}/${plugin}/skill`, skills, seen);
760
+ }
761
+ const rootSkillMd = join3(pluginPath, "SKILL.md");
762
+ const initSh = join3(pluginPath, "init.sh");
763
+ if (existsSync4(rootSkillMd) && !existsSync4(initSh)) {
764
+ const frontmatter = parseFrontmatter(rootSkillMd);
765
+ if (frontmatter && !seen.has(frontmatter.name)) {
766
+ seen.add(frontmatter.name);
767
+ skills.push({
768
+ id: frontmatter.name,
769
+ description: frontmatter.description,
770
+ source: `${pluginDir}/${plugin}`,
771
+ filePath: rootSkillMd
772
+ });
773
+ }
774
+ }
775
+ }
776
+ }
777
+ return skills;
778
+ }
779
+ function parseFrontmatter(filePath) {
780
+ try {
781
+ const content = readFileSync2(filePath, "utf-8");
782
+ const lines = content.split("\n");
783
+ if (lines.length < 3) return null;
784
+ if (lines[0].trim() !== "---") return null;
785
+ let endIndex = -1;
786
+ for (let i = 1; i < lines.length; i++) {
787
+ if (lines[i].trim() === "---") {
788
+ endIndex = i;
789
+ break;
790
+ }
791
+ }
792
+ if (endIndex === -1) return null;
793
+ const yamlBlock = lines.slice(1, endIndex).map((l) => l.replace(/\r$/, "")).join("\n");
794
+ const parsed = parseYaml(yamlBlock);
795
+ if (!parsed || typeof parsed !== "object") return null;
796
+ if (!parsed.name || typeof parsed.name !== "string") return null;
797
+ const trimmedName = parsed.name.trim();
798
+ if (!trimmedName || /[\/\\]|\.\./.test(trimmedName) || !/^[a-zA-Z0-9._-]+$/.test(trimmedName)) {
799
+ return null;
800
+ }
801
+ return {
802
+ name: trimmedName,
803
+ description: (parsed.description || "").trim()
804
+ };
805
+ } catch {
806
+ return null;
807
+ }
808
+ }
809
+ function getCurrentCommit(repoPath) {
810
+ try {
811
+ const headFile = join3(repoPath, ".git", "HEAD");
812
+ if (!existsSync4(headFile)) return "unknown";
813
+ const headContent = readFileSync2(headFile, "utf-8").trim();
814
+ if (headContent.startsWith("ref: ")) {
815
+ const refPath = join3(repoPath, ".git", headContent.slice(5));
816
+ if (existsSync4(refPath)) {
817
+ return readFileSync2(refPath, "utf-8").trim();
818
+ }
819
+ const packedRefsPath = join3(repoPath, ".git", "packed-refs");
820
+ if (existsSync4(packedRefsPath)) {
821
+ const packedRefs = readFileSync2(packedRefsPath, "utf-8");
822
+ const refName = headContent.slice(5);
823
+ const lines = packedRefs.split("\n");
824
+ for (const line of lines) {
825
+ if (line.endsWith(refName)) {
826
+ return line.split(" ")[0];
827
+ }
828
+ }
829
+ }
830
+ }
831
+ return headContent;
832
+ } catch {
833
+ return "unknown";
834
+ }
835
+ }
836
+ function readScanCache() {
837
+ try {
838
+ const cachePath = getCachePath();
839
+ if (!existsSync4(cachePath)) return null;
840
+ const content = readFileSync2(cachePath, "utf-8");
841
+ const cache = JSON.parse(content);
842
+ if (!cache.skills || !cache.timestamp) return null;
843
+ const age = Date.now() - cache.timestamp;
844
+ if (age > scanConfig.cacheTtlMs) return null;
845
+ return cache;
846
+ } catch {
847
+ return null;
848
+ }
849
+ }
850
+ function writeScanCache(cache) {
851
+ try {
852
+ const cachePath = getCachePath();
853
+ const cacheDir = dirname3(cachePath);
854
+ if (!existsSync4(cacheDir)) {
855
+ mkdirSync(cacheDir, { recursive: true });
856
+ }
857
+ atomicWriteFileSync(cachePath, JSON.stringify(cache, null, 2));
858
+ } catch {
859
+ }
860
+ }
861
+ function getCachePath() {
862
+ return join3(getCannbotConfigDir(), "scan-cache.json");
863
+ }
864
+ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
865
+ for (const entry of safeReaddir(dirPath)) {
866
+ const fullPath = join3(dirPath, entry);
867
+ if (EXCLUDE_DIRS.has(entry)) continue;
868
+ if (!isDirectory(fullPath)) continue;
869
+ const skillMd = join3(fullPath, "SKILL.md");
870
+ if (existsSync4(skillMd)) {
871
+ const frontmatter = parseFrontmatter(skillMd);
872
+ if (frontmatter && !seen.has(frontmatter.name)) {
873
+ seen.add(frontmatter.name);
874
+ skills.push({
875
+ id: frontmatter.name,
876
+ description: frontmatter.description,
877
+ source: sourcePrefix,
878
+ filePath: skillMd
879
+ });
1186
880
  }
881
+ continue;
1187
882
  }
1188
- case "cursor":
1189
- return join3(baseDir, ".cursor");
1190
- case "codex":
1191
- return join3(baseDir, ".codex");
1192
- case "copilot":
1193
- return join3(baseDir, ".github");
1194
- case "codearts":
1195
- return join3(baseDir, ".codeartsdoer");
1196
- default:
1197
- throw new Error(
1198
- t("error_invalid_tool").replace("{tool}", tool).replace("{tools}", VALID_TOOLS.join(", "))
1199
- );
883
+ scanDirectory(fullPath, repoPath, sourcePrefix + "/" + entry, skills, seen);
884
+ }
885
+ }
886
+ function safeReaddir(dir) {
887
+ try {
888
+ return readdirSync(dir);
889
+ } catch {
890
+ return [];
891
+ }
892
+ }
893
+ var __filename2, __dirname2, EXCLUDE_DIRS, scanConfig, SKILL_SCAN_DIRS, PLUGIN_SCAN_DIRS;
894
+ var init_scanner = __esm({
895
+ "src/core/scanner.ts"() {
896
+ "use strict";
897
+ init_paths();
898
+ init_fs();
899
+ init_fs_helpers();
900
+ __filename2 = fileURLToPath2(import.meta.url);
901
+ __dirname2 = dirname3(__filename2);
902
+ EXCLUDE_DIRS = /* @__PURE__ */ new Set([
903
+ "node_modules",
904
+ ".git",
905
+ "asc-devkit",
906
+ "cann-samples",
907
+ "tilelang-ascend",
908
+ ".agents",
909
+ ".opencode",
910
+ ".claude",
911
+ ".claude-plugin",
912
+ "dist",
913
+ "build",
914
+ "references",
915
+ "hooks",
916
+ "operators",
917
+ "workflows",
918
+ "tests",
919
+ "docs",
920
+ "scripts"
921
+ ]);
922
+ scanConfig = loadScanConfig();
923
+ SKILL_SCAN_DIRS = scanConfig.skillDirs;
924
+ PLUGIN_SCAN_DIRS = scanConfig.pluginDirs;
925
+ }
926
+ });
927
+
928
+ // src/embedded-plugins.json
929
+ var embedded_plugins_default;
930
+ var init_embedded_plugins = __esm({
931
+ "src/embedded-plugins.json"() {
932
+ embedded_plugins_default = [
933
+ {
934
+ id: "ops-direct-invoke",
935
+ dir: "plugins-official/ops-direct-invoke",
936
+ displayName: "AscendC Kernel \u76F4\u8C03",
937
+ script: "init.sh",
938
+ aliases: [
939
+ "ops-direct",
940
+ "ascendc-direct",
941
+ "direct",
942
+ "kernel"
943
+ ],
944
+ skills: 0,
945
+ agents: 6,
946
+ description: "skill \u9A71\u52A8\u591A\u89D2\u8272\u76F4\u8C03\u7B97\u5B50\u5F00\u53D1\u5DE5\u4F5C\u6D41\uFF1APM \u8C03\u5EA6 architect/developer/qa \u56E2\u961F\uFF0C8 \u9636\u6BB5 7 CP \u5168\u6D41\u7A0B\uFF0C\u652F\u6301\u9759\u9ED8\u6A21\u5F0F\u4E0E\u7B97\u5B50\u4ED3\u7EE7\u627F\u5B9A\u5236",
947
+ version: "2.0.0",
948
+ configFile: "AGENTS.md",
949
+ configRootConfigLink: false,
950
+ installSkills: [],
951
+ installAgents: [
952
+ "architect",
953
+ "developer",
954
+ "developer-code",
955
+ "developer-doc",
956
+ "developer-test",
957
+ "qa"
958
+ ]
959
+ },
960
+ {
961
+ id: "ops-direct-invoke-flash",
962
+ dir: "plugins-official/ops-direct-invoke-flash",
963
+ displayName: "AscendC Kernel \u76F4\u8C03\uFF08\u5FEB\u901F\u7248\uFF09",
964
+ script: "init.sh",
965
+ aliases: [
966
+ "flash",
967
+ "kernel-flash"
968
+ ],
969
+ skills: 7,
970
+ agents: 1,
971
+ description: "\u4ECE\u6570\u5B66\u516C\u5F0F\u6216\u4EE3\u7801\u7247\u6BB5\u5FEB\u901F\u6784\u5EFA\u5E76\u9A8C\u8BC1 Ascend NPU \u6838\u51FD\u6570",
972
+ version: "1.2.2",
973
+ configFile: "AGENTS.md",
974
+ configRootConfigLink: true,
975
+ installSkills: [
976
+ {
977
+ dir: "plugins-official/ops-direct-invoke-flash/skills",
978
+ skills: [
979
+ "ops-direct-invoke-flash"
980
+ ]
981
+ },
982
+ {
983
+ dir: "ops",
984
+ skills: [
985
+ "ascendc-st-design",
986
+ "ascendc-whitebox-design"
987
+ ]
988
+ },
989
+ {
990
+ dir: "infra",
991
+ skills: [
992
+ "gitcode-toolkit",
993
+ "gitcode-pr-handler",
994
+ "gitcode-issue-gen",
995
+ "gitcode-issue-handler"
996
+ ]
997
+ }
998
+ ],
999
+ installAgents: [
1000
+ "ops-direct-invoke-flash-reviewer"
1001
+ ]
1002
+ },
1003
+ {
1004
+ id: "ops-registry-invoke",
1005
+ dir: "plugins-official/ops-registry-invoke",
1006
+ displayName: "AscendC \u7B97\u5B50\u6CE8\u518C\u8C03\u7528",
1007
+ script: "init.sh",
1008
+ aliases: [
1009
+ "ops-registry",
1010
+ "ascendc-registry",
1011
+ "registry"
1012
+ ],
1013
+ skills: 30,
1014
+ agents: 7,
1015
+ description: "\u751F\u4EA7\u7EA7 ACLNN \u6CE8\u518C\u7B97\u5B50\u5168\u6D41\u7A0B\uFF1A\u4EE3\u7801\u2192UT/ST\u2192\u4E0A\u5E93",
1016
+ version: "1.2.3",
1017
+ configFile: "AGENTS.md",
1018
+ configRootConfigLink: false,
1019
+ installSkills: [
1020
+ {
1021
+ dir: "ops",
1022
+ skills: [
1023
+ "ascendc-blaze-best-practice",
1024
+ "ascendc-blaze-migration",
1025
+ "ascendc-api-best-practices",
1026
+ "ascendc-code-review",
1027
+ "ascendc-crash-debug",
1028
+ "ascendc-direct-invoke-template",
1029
+ "ascendc-docs-gen",
1030
+ "ascendc-docs-search",
1031
+ "ascendc-env-check",
1032
+ "npu-arch",
1033
+ "ascendc-performance-best-practices",
1034
+ "ascendc-precision-debug",
1035
+ "ascendc-perf-optimize",
1036
+ "ascendc-regbase-best-practice",
1037
+ "ascendc-registry-invoke-template",
1038
+ "ascendc-runtime-debug",
1039
+ "ascendc-st-design",
1040
+ "ascendc-tiling-design",
1041
+ "ascendc-ut-develop",
1042
+ "ascendc-whitebox-design",
1043
+ "ops-precision-standard",
1044
+ "ops-profiling",
1045
+ "ops-simulator",
1046
+ "ops-spec-gen"
1047
+ ]
1048
+ },
1049
+ {
1050
+ dir: "infra",
1051
+ skills: [
1052
+ "gitcode-toolkit",
1053
+ "gitcode-pr-handler",
1054
+ "gitcode-issue-gen",
1055
+ "gitcode-issue-handler"
1056
+ ]
1057
+ },
1058
+ {
1059
+ dir: "plugins-official/ops-registry-invoke",
1060
+ skills: [
1061
+ {
1062
+ name: "workflow",
1063
+ as: "ops-registry-invoke-workflow"
1064
+ }
1065
+ ]
1066
+ },
1067
+ {
1068
+ dir: "plugins-official/ops-registry-invoke/skills",
1069
+ skills: [
1070
+ "spec-to-design"
1071
+ ]
1072
+ }
1073
+ ],
1074
+ installAgents: [
1075
+ "ascendc-ops-architect",
1076
+ "ascendc-ops-spec-reviewer",
1077
+ "ascendc-ops-designer",
1078
+ "ascendc-ops-design-reviewer",
1079
+ "ascendc-ops-tester",
1080
+ "ascendc-ops-test-design-reviewer",
1081
+ "ascendc-ops-developer"
1082
+ ],
1083
+ externalRepos: [
1084
+ {
1085
+ url: "https://gitcode.com/cann/asc-devkit.git",
1086
+ dir: "plugins-official/ops-registry-invoke/reference/cann/asc-devkit",
1087
+ depth: 1,
1088
+ configRootLink: false
1089
+ },
1090
+ {
1091
+ url: "https://gitcode.com/cann/ops-tensor.git",
1092
+ dir: "plugins-official/ops-registry-invoke/ops-tensor",
1093
+ configRootLink: false
1094
+ }
1095
+ ]
1096
+ },
1097
+ {
1098
+ id: "catlass-op-generator",
1099
+ dir: "plugins-official/catlass-op-generator",
1100
+ displayName: "Catlass \u7B97\u5B50\u76F4\u8C03",
1101
+ script: "init.sh",
1102
+ aliases: [
1103
+ "catlass"
1104
+ ],
1105
+ skills: 14,
1106
+ agents: 3,
1107
+ description: "Catlass \u6A21\u677F\u62FC\u88C5 GEMM/Matmul/Epilogue \u7B97\u5B50\u5F00\u53D1",
1108
+ version: "1.0.0",
1109
+ configFile: "AGENTS.md",
1110
+ configRootConfigLink: true,
1111
+ installSkills: [
1112
+ {
1113
+ dir: "ops",
1114
+ skills: [
1115
+ "catlass-op-design",
1116
+ "catlass-op-develop",
1117
+ "catlass-op-perf-tune",
1118
+ "ascendc-tiling-design",
1119
+ "npu-arch",
1120
+ "ascendc-api-best-practices",
1121
+ "ops-precision-standard",
1122
+ "ascendc-docs-search",
1123
+ "ascendc-env-check",
1124
+ "ascendc-precision-debug",
1125
+ "ops-profiling",
1126
+ "ascendc-runtime-debug",
1127
+ "ascendc-code-review",
1128
+ "torch-ascendc-op-extension"
1129
+ ]
1130
+ }
1131
+ ],
1132
+ installAgents: [
1133
+ "catlass-op-architect",
1134
+ "catlass-op-generator",
1135
+ "catlass-op-reviewer"
1136
+ ],
1137
+ externalRepos: [
1138
+ {
1139
+ url: "https://gitcode.com/cann/asc-devkit.git",
1140
+ dir: "plugins-official/catlass-op-generator/asc-devkit",
1141
+ configRootLink: false
1142
+ }
1143
+ ]
1144
+ },
1145
+ {
1146
+ id: "model-infer-optimize",
1147
+ dir: "plugins-official/model-infer-optimize",
1148
+ displayName: "NPU \u63A8\u7406\u4F18\u5316",
1149
+ script: "init.sh",
1150
+ aliases: [
1151
+ "model-infer",
1152
+ "infer",
1153
+ "inference",
1154
+ "sota",
1155
+ "sota-approach",
1156
+ "model-infer-sota"
1157
+ ],
1158
+ skills: 14,
1159
+ agents: 9,
1160
+ description: "NPU \u6A21\u578B\u63A8\u7406\u7AEF\u5230\u7AEF\u4F18\u5316\uFF0C\u6DB5\u76D6\u56FA\u5B9A\u9636\u6BB5\u4F18\u5316\uFF08\u5E76\u884C/KVCache/\u878D\u5408/\u91CF\u5316/\u56FE\u6A21\u5F0F\uFF09\u4E0E baseline \u4E4B\u4E0A profiling \u9A71\u52A8\u7684\u63A2\u7D22\u5F0F\u4F18\u5316\uFF08\u6309\u9700\u8C03\u7528\u591A\u6D41/\u9884\u53D6/SuperKernel \u7B49\u5355\u70B9\u4F18\u5316\uFF09",
1161
+ version: "1.0.6",
1162
+ configFile: "AGENTS.md",
1163
+ configRootConfigLink: true,
1164
+ installSkills: [
1165
+ {
1166
+ dir: "model",
1167
+ skills: [
1168
+ "model-infer-migrator",
1169
+ "model-infer-parallel-analysis",
1170
+ "model-infer-parallel-impl",
1171
+ "model-infer-kvcache",
1172
+ "model-infer-fusion",
1173
+ "model-infer-quantization",
1174
+ "model-infer-graph-mode",
1175
+ "model-infer-precision-debug",
1176
+ "model-infer-runtime-debug",
1177
+ "model-infer-multi-stream",
1178
+ "model-infer-prefetch",
1179
+ "model-infer-superkernel",
1180
+ "model-infer-profiling",
1181
+ "model-infer-perf-breakdown"
1182
+ ]
1183
+ }
1184
+ ],
1185
+ installAgents: [
1186
+ "model-infer-analyzer",
1187
+ "model-infer-implementer",
1188
+ "model-infer-reviewer",
1189
+ "model-infer-sota-scenario",
1190
+ "model-infer-sota-profiling-instrumenter",
1191
+ "model-infer-sota-profile-analyzer",
1192
+ "model-infer-sota-candidate",
1193
+ "model-infer-sota-implementer",
1194
+ "model-infer-sota-reviewer"
1195
+ ],
1196
+ externalRepos: [
1197
+ {
1198
+ url: "https://gitcode.com/cann/cann-recipes-infer.git",
1199
+ dir: "plugins-official/model-infer-optimize/cann-recipes-infer",
1200
+ depth: 1,
1201
+ configRootLink: true
1202
+ }
1203
+ ]
1204
+ },
1205
+ {
1206
+ id: "pypto-op-orchestrator",
1207
+ dir: "plugins-official/pypto-op-orchestrator",
1208
+ displayName: "PyPTO \u7B97\u5B50\u5F00\u53D1",
1209
+ script: "init.sh",
1210
+ aliases: [
1211
+ "pypto",
1212
+ "pytorch"
1213
+ ],
1214
+ skills: 17,
1215
+ agents: 8,
1216
+ description: "PyPTO Python API \u7B97\u5B50\u5168\u6D41\u7A0B\u5F00\u53D1\uFF0C\u8986\u76D6\u9700\u6C42\u7406\u89E3\u3001API \u63A2\u7D22\u3001\u5B9E\u73B0\u4E0E\u8C03\u4F18",
1217
+ version: "1.2.0",
1218
+ configFile: "AGENTS.md",
1219
+ configRootConfigLink: false,
1220
+ installSkills: [
1221
+ {
1222
+ dir: "ops",
1223
+ skills: [
1224
+ "pypto-orchestration-manual",
1225
+ "pypto-intent-understand",
1226
+ "pypto-op-plan",
1227
+ "pypto-api-explore",
1228
+ "pypto-docs-search",
1229
+ "pypto-golden-generate",
1230
+ "pypto-op-design",
1231
+ "pypto-op-construct",
1232
+ "pypto-op-develop",
1233
+ "pypto-op-verify",
1234
+ "pypto-op-review",
1235
+ "pypto-precision-compare",
1236
+ "pypto-precision-debug",
1237
+ "pypto-general-debug",
1238
+ "pypto-op-perf-tune",
1239
+ "pypto-op-knowledge",
1240
+ "pypto-memory-template"
1241
+ ]
1242
+ }
1243
+ ],
1244
+ installAgents: [
1245
+ "pypto-op-planner",
1246
+ "pypto-op-mathematician",
1247
+ "pypto-op-architect",
1248
+ "pypto-op-designer",
1249
+ "pypto-op-coder",
1250
+ "pypto-op-verifier",
1251
+ "pypto-op-debugger",
1252
+ "pypto-op-optimizer"
1253
+ ],
1254
+ externalRepos: [
1255
+ {
1256
+ url: "https://gitcode.com/cann/pypto.git",
1257
+ dir: "plugins-official/pypto-op-orchestrator/pypto",
1258
+ configRootLink: false
1259
+ }
1260
+ ]
1261
+ },
1262
+ {
1263
+ id: "tilelang-op-orchestrator",
1264
+ dir: "plugins-official/tilelang-op-orchestrator",
1265
+ displayName: "TileLang \u7B97\u5B50\u5F00\u53D1",
1266
+ script: "init.sh",
1267
+ aliases: [
1268
+ "tilelang"
1269
+ ],
1270
+ skills: 9,
1271
+ agents: 3,
1272
+ description: "TileLang Python DSL + @tilelang.jit \u7B97\u5B50\u5F00\u53D1\uFF08\u652F\u6301 Developer/Expert \u53CC\u6A21\u5F0F\uFF09",
1273
+ version: "1.1.0",
1274
+ configFile: "AGENTS.md",
1275
+ configRootConfigLink: false,
1276
+ installSkills: [
1277
+ {
1278
+ dir: "ops",
1279
+ skills: [
1280
+ "tilelang-api-best-practices",
1281
+ "tilelang-env-check",
1282
+ "tilelang-op-design",
1283
+ "tilelang-op-develop",
1284
+ "tilelang-op-test-design",
1285
+ "tilelang-perf-optimization",
1286
+ "tilelang-programming-model-guide",
1287
+ "tilelang-review",
1288
+ "tilelang-submodule-pull"
1289
+ ]
1290
+ }
1291
+ ],
1292
+ installAgents: [
1293
+ "tilelang-op-analyst",
1294
+ "tilelang-op-developer",
1295
+ "tilelang-op-perf-tuner"
1296
+ ],
1297
+ externalRepos: [
1298
+ {
1299
+ url: "https://github.com/tile-ai/tilelang-ascend.git",
1300
+ dir: "plugins-official/tilelang-op-orchestrator/tilelang-ascend",
1301
+ depth: 1,
1302
+ recursive: true,
1303
+ configRootLink: false
1304
+ }
1305
+ ]
1306
+ },
1307
+ {
1308
+ id: "triton-op-generator",
1309
+ dir: "plugins-official/triton-op-generator",
1310
+ displayName: "Triton \u7B97\u5B50\u5F00\u53D1",
1311
+ script: "init.sh",
1312
+ aliases: [
1313
+ "triton"
1314
+ ],
1315
+ skills: 8,
1316
+ agents: 0,
1317
+ description: "Triton-Ascend \u7B97\u5B50 6 \u9636\u6BB5\u81EA\u52A8\u751F\u6210\u4E0E\u4F18\u5316\uFF08\u63CF\u8FF0\u2192\u4EE3\u7801\u2192\u9A8C\u8BC1\u2192\u4F18\u5316\uFF09",
1318
+ version: "1.0.2",
1319
+ configFile: "AGENTS.md",
1320
+ configRootConfigLink: false,
1321
+ installSkills: [
1322
+ {
1323
+ dir: "ops",
1324
+ skills: [
1325
+ "triton-task-extractor",
1326
+ "triton-op-designer",
1327
+ "triton-op-coding",
1328
+ "triton-op-verifier",
1329
+ "triton-latency-optimizer",
1330
+ "triton-precision-debug",
1331
+ "npu-arch",
1332
+ "triton-simulator-optimizer"
1333
+ ]
1334
+ }
1335
+ ],
1336
+ installAgents: []
1337
+ },
1338
+ {
1339
+ id: "torch-compile",
1340
+ dir: "plugins-official/torch-compile",
1341
+ displayName: "torch.compile \u56FE\u6A21\u5F0F",
1342
+ script: "init.sh",
1343
+ aliases: [
1344
+ "torch",
1345
+ "compile",
1346
+ "graph"
1347
+ ],
1348
+ skills: 7,
1349
+ agents: 1,
1350
+ description: "NPU \u56FE\u6A21\u5F0F npugraph_ex \u914D\u7F6E\u3001\u811A\u672C\u8FC1\u79FB\u3001\u7F16\u8BD1\u8BCA\u65AD\u4E0E\u81EA\u5B9A\u4E49\u7B97\u5B50\u5165\u56FE",
1351
+ version: "1.0.4",
1352
+ configFile: "AGENTS.md",
1353
+ configRootConfigLink: true,
1354
+ installSkills: [
1355
+ {
1356
+ dir: "graph",
1357
+ skills: [
1358
+ "torch-npugraph-ex-knowledge",
1359
+ "torch-npugraph-ex-template",
1360
+ "torch-npugraph-ex-dfx-triage",
1361
+ "torch-npugraph-ex-compile-error-diagnosis",
1362
+ "torch-npugraph-ex-runtime-error-diagnosis",
1363
+ "torch-npugraph-ex-performance-diagnosis",
1364
+ "torch-custom-ops-guide"
1365
+ ]
1366
+ }
1367
+ ],
1368
+ installAgents: [
1369
+ "torch-npugraph-ex"
1370
+ ]
1371
+ },
1372
+ {
1373
+ id: "ops-code-reviewer",
1374
+ dir: "plugins-official/ops-code-reviewer",
1375
+ displayName: "\u4EE3\u7801\u68C0\u89C6",
1376
+ script: "init.sh",
1377
+ aliases: [
1378
+ "code-review",
1379
+ "reviewer",
1380
+ "review"
1381
+ ],
1382
+ skills: 4,
1383
+ agents: 2,
1384
+ description: "Ascend C \u7B97\u5B50\u4EE3\u7801 4 \u9636\u6BB5\u5168\u91CF\u68C0\u89C6\uFF08\u4E3B Agent \u7F16\u6392 + \u5B50 Agent \u5E76\u884C\u68C0\u89C6\uFF09",
1385
+ version: "1.1.0",
1386
+ configFile: "AGENTS.md",
1387
+ configRootConfigLink: false,
1388
+ installSkills: [
1389
+ {
1390
+ dir: "ops",
1391
+ skills: [
1392
+ "ascendc-code-review",
1393
+ "ascendc-docs-search",
1394
+ "ascendc-api-best-practices",
1395
+ "npu-arch"
1396
+ ]
1397
+ }
1398
+ ],
1399
+ installAgents: [
1400
+ "ascendc-ops-reviewer",
1401
+ "ascendc-code-summarizer"
1402
+ ]
1403
+ }
1404
+ ];
1200
1405
  }
1406
+ });
1407
+
1408
+ // src/core/registry.ts
1409
+ import { readdirSync as readdirSync2, existsSync as existsSync5 } from "fs";
1410
+ import { join as join4 } from "path";
1411
+ function loadPlugins() {
1412
+ const plugins = [...embedded_plugins_default];
1413
+ plugins.sort(
1414
+ (a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0
1415
+ );
1416
+ return plugins;
1201
1417
  }
1202
- function getConfigFileName(tool) {
1203
- return tool === "claude" ? "CLAUDE.md" : "AGENTS.md";
1204
- }
1205
- function getSkillsRoot(tool, level, base) {
1206
- if (tool === "codex") {
1207
- if (level === "global") {
1208
- return join3(homedir(), ".agents", "skills");
1418
+ function mergeDynamicPlugins(repoPath) {
1419
+ if (!existsSync5(repoPath)) return;
1420
+ const existingIds = new Set(PLUGIN_REGISTRY.map((p) => p.id));
1421
+ const dynamic = [];
1422
+ for (const pluginDir of getPluginDirs()) {
1423
+ const parent = join4(repoPath, pluginDir);
1424
+ if (!existsSync5(parent)) continue;
1425
+ let entries = [];
1426
+ try {
1427
+ entries = readdirSync2(parent);
1428
+ } catch {
1429
+ continue;
1430
+ }
1431
+ for (const entry of entries) {
1432
+ const pluginPath = join4(parent, entry);
1433
+ if (!isDirectory(pluginPath)) continue;
1434
+ if (entry === "install-helper") continue;
1435
+ const initSh = join4(pluginPath, "init.sh");
1436
+ if (!existsSync5(initSh)) continue;
1437
+ const pluginId = entry;
1438
+ if (existingIds.has(pluginId)) continue;
1439
+ dynamic.push({
1440
+ id: pluginId,
1441
+ dir: `${pluginDir}/${entry}`,
1442
+ displayName: entry,
1443
+ script: "init.sh",
1444
+ aliases: [],
1445
+ skills: 0,
1446
+ agents: 0,
1447
+ description: ""
1448
+ });
1449
+ existingIds.add(pluginId);
1209
1450
  }
1210
- return join3(base || process.cwd(), ".agents", "skills");
1211
1451
  }
1212
- return join3(getConfigRoot(tool, level, base), "skills");
1213
- }
1214
- function getAgentsFileName(tool) {
1215
- return getConfigFileName(tool);
1216
- }
1217
- function getAgentsDir(configRoot) {
1218
- return join3(configRoot, "agents");
1452
+ if (dynamic.length > 0) {
1453
+ PLUGIN_REGISTRY = [...PLUGIN_REGISTRY, ...dynamic].sort(
1454
+ (a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0
1455
+ );
1456
+ }
1219
1457
  }
1220
- function getManifestPath(configRoot) {
1221
- return join3(configRoot, "cannbot-manifest.json");
1458
+ function findPlugin(query) {
1459
+ const normalized = query.toLowerCase().trim();
1460
+ const exactMatch = PLUGIN_REGISTRY.find(
1461
+ (p) => p.id === normalized || p.id === query.trim()
1462
+ );
1463
+ if (exactMatch) return exactMatch;
1464
+ const aliasMatch = PLUGIN_REGISTRY.find(
1465
+ (p) => p.aliases.some((a) => a === normalized)
1466
+ );
1467
+ if (aliasMatch) return aliasMatch;
1468
+ const prefixMatches = PLUGIN_REGISTRY.filter((p) => p.id.startsWith(normalized));
1469
+ if (prefixMatches.length === 1) return prefixMatches[0];
1470
+ return void 0;
1222
1471
  }
1223
- function getCannbotConfigDir() {
1224
- return join3(homedir(), ".cannbot");
1472
+ function getAllPlugins() {
1473
+ return PLUGIN_REGISTRY;
1225
1474
  }
1226
- function getCannbotRepoPath() {
1227
- return join3(getCannbotConfigDir(), "repo");
1475
+ function getPluginById(id) {
1476
+ return PLUGIN_REGISTRY.find((p) => p.id === id);
1228
1477
  }
1229
- var VALID_TOOLS, VALID_LEVELS;
1230
- var init_paths = __esm({
1231
- "src/utils/paths.ts"() {
1478
+ var PLUGIN_REGISTRY;
1479
+ var init_registry = __esm({
1480
+ "src/core/registry.ts"() {
1232
1481
  "use strict";
1233
- init_i18n();
1234
- VALID_TOOLS = ["opencode", "claude", "trae", "cursor", "codex", "copilot", "codearts"];
1235
- VALID_LEVELS = ["project", "global"];
1482
+ init_fs_helpers();
1483
+ init_scanner();
1484
+ init_embedded_plugins();
1485
+ PLUGIN_REGISTRY = loadPlugins();
1236
1486
  }
1237
1487
  });
1238
1488
 
1239
1489
  // src/core/detector.ts
1240
1490
  import { execa } from "execa";
1241
- import { existsSync as existsSync4 } from "fs";
1491
+ import { existsSync as existsSync6 } from "fs";
1242
1492
  import { homedir as homedir2 } from "os";
1243
- import { join as join4 } from "path";
1493
+ import { join as join5 } from "path";
1244
1494
  async function getCommandVersion(cmd, args = ["--version"]) {
1245
1495
  try {
1246
1496
  const result = await execa(cmd, args, { timeout: 5e3 });
@@ -1276,12 +1526,12 @@ async function detectTrae() {
1276
1526
  const home = homedir2();
1277
1527
  const variant = detectTraeVariant();
1278
1528
  let path;
1279
- if (variant === "ide" && existsSync4(join4(home, ".trae-cn"))) {
1280
- path = join4(home, ".trae-cn");
1281
- } else if (variant === "plugin" && existsSync4(join4(home, ".marscode"))) {
1282
- path = join4(home, ".marscode");
1283
- } else if (variant === "cli" && existsSync4(join4(home, ".traecli"))) {
1284
- path = join4(home, ".traecli");
1529
+ if (variant === "ide" && existsSync6(join5(home, ".trae-cn"))) {
1530
+ path = join5(home, ".trae-cn");
1531
+ } else if (variant === "plugin" && existsSync6(join5(home, ".marscode"))) {
1532
+ path = join5(home, ".marscode");
1533
+ } else if (variant === "cli" && existsSync6(join5(home, ".traecli"))) {
1534
+ path = join5(home, ".traecli");
1285
1535
  } else if (variant === "unknown") {
1286
1536
  const cmdPath = await getCommandPath("trae");
1287
1537
  if (cmdPath) path = cmdPath;
@@ -1297,7 +1547,7 @@ async function detectCursor() {
1297
1547
  }
1298
1548
  if (process.platform === "darwin") {
1299
1549
  const appPath = "/Applications/Cursor.app";
1300
- if (existsSync4(appPath)) {
1550
+ if (existsSync6(appPath)) {
1301
1551
  return { name: "cursor", path: appPath };
1302
1552
  }
1303
1553
  }
@@ -1310,8 +1560,8 @@ async function detectCodex() {
1310
1560
  return { name: "codex", version, path: cmdPath };
1311
1561
  }
1312
1562
  const home = homedir2();
1313
- const configDir = join4(home, ".codex");
1314
- if (existsSync4(configDir)) {
1563
+ const configDir = join5(home, ".codex");
1564
+ if (existsSync6(configDir)) {
1315
1565
  return { name: "codex", path: configDir };
1316
1566
  }
1317
1567
  return void 0;
@@ -1328,8 +1578,8 @@ async function detectCopilot() {
1328
1578
  }
1329
1579
  async function detectCodeArts() {
1330
1580
  const home = homedir2();
1331
- const configDir = join4(home, ".codeartsdoer");
1332
- if (existsSync4(configDir)) {
1581
+ const configDir = join5(home, ".codeartsdoer");
1582
+ if (existsSync6(configDir)) {
1333
1583
  return { name: "codearts", path: configDir };
1334
1584
  }
1335
1585
  return void 0;
@@ -1376,13 +1626,13 @@ var init_detector = __esm({
1376
1626
  });
1377
1627
 
1378
1628
  // src/core/manifest.ts
1379
- import { existsSync as existsSync5, readFileSync as readFileSync2 } from "fs";
1380
- import { join as join5 } from "path";
1629
+ import { existsSync as existsSync7, readFileSync as readFileSync3 } from "fs";
1630
+ import { join as join6 } from "path";
1381
1631
  function readManifest(configRoot) {
1382
1632
  const manifestPath = getManifestPath(configRoot);
1383
- if (existsSync5(manifestPath)) {
1633
+ if (existsSync7(manifestPath)) {
1384
1634
  try {
1385
- const content = readFileSync2(manifestPath, "utf-8");
1635
+ const content = readFileSync3(manifestPath, "utf-8");
1386
1636
  return JSON.parse(content);
1387
1637
  } catch {
1388
1638
  }
@@ -1393,18 +1643,18 @@ function readAllManifests(configRoot) {
1393
1643
  const manifests = [];
1394
1644
  const plugins = getAllPlugins();
1395
1645
  const standardPath = getManifestPath(configRoot);
1396
- if (existsSync5(standardPath)) {
1646
+ if (existsSync7(standardPath)) {
1397
1647
  try {
1398
- const content = readFileSync2(standardPath, "utf-8");
1648
+ const content = readFileSync3(standardPath, "utf-8");
1399
1649
  manifests.push(JSON.parse(content));
1400
1650
  } catch {
1401
1651
  }
1402
1652
  }
1403
1653
  for (const plugin of plugins) {
1404
- const pluginManifestPath = join5(configRoot, `${plugin.id}-manifest.json`);
1405
- if (existsSync5(pluginManifestPath)) {
1654
+ const pluginManifestPath = join6(configRoot, `${plugin.id}-manifest.json`);
1655
+ if (existsSync7(pluginManifestPath)) {
1406
1656
  try {
1407
- const content = readFileSync2(pluginManifestPath, "utf-8");
1657
+ const content = readFileSync3(pluginManifestPath, "utf-8");
1408
1658
  manifests.push(JSON.parse(content));
1409
1659
  } catch {
1410
1660
  }
@@ -1448,28 +1698,28 @@ function scanInstalled() {
1448
1698
  }
1449
1699
  function verifyPluginFilesExist(configRoot, manifest, tool, level) {
1450
1700
  const skillsDir = getSkillsRoot(tool, level);
1451
- const agentsDir = join5(configRoot, "agents");
1701
+ const agentsDir = join6(configRoot, "agents");
1452
1702
  let hasAnyComponent = false;
1453
1703
  if (manifest.installed_skills && manifest.installed_skills.length > 0) {
1454
1704
  const hasAnySkill = manifest.installed_skills.some((skillId) => {
1455
- const skillPath = join5(skillsDir, skillId);
1456
- return existsSync5(skillPath) || isSymlink(skillPath);
1705
+ const skillPath = join6(skillsDir, skillId);
1706
+ return existsSync7(skillPath) || isSymlink(skillPath);
1457
1707
  });
1458
1708
  if (hasAnySkill) hasAnyComponent = true;
1459
1709
  }
1460
1710
  if (manifest.installed_agents && manifest.installed_agents.length > 0) {
1461
1711
  const hasAnyAgent = manifest.installed_agents.some((agentId) => {
1462
- const agentPath = join5(agentsDir, agentId);
1463
- const agentPathMd = join5(agentsDir, agentId + ".md");
1464
- return existsSync5(agentPath) || isSymlink(agentPath) || existsSync5(agentPathMd) || isSymlink(agentPathMd);
1712
+ const agentPath = join6(agentsDir, agentId);
1713
+ const agentPathMd = join6(agentsDir, agentId + ".md");
1714
+ return existsSync7(agentPath) || isSymlink(agentPath) || existsSync7(agentPathMd) || isSymlink(agentPathMd);
1465
1715
  });
1466
1716
  if (hasAnyAgent) hasAnyComponent = true;
1467
1717
  }
1468
1718
  const agentsFileName = getAgentsFileName(tool);
1469
- const configFilePath = level === "project" ? join5(configRoot, "..", agentsFileName) : join5(configRoot, agentsFileName);
1470
- if (existsSync5(configFilePath) || isSymlink(configFilePath)) hasAnyComponent = true;
1471
- const pluginManifestPath = join5(configRoot, `${manifest.team}-manifest.json`);
1472
- if (existsSync5(pluginManifestPath)) hasAnyComponent = true;
1719
+ const configFilePath = level === "project" ? join6(configRoot, "..", agentsFileName) : join6(configRoot, agentsFileName);
1720
+ if (existsSync7(configFilePath) || isSymlink(configFilePath)) hasAnyComponent = true;
1721
+ const pluginManifestPath = join6(configRoot, `${manifest.team}-manifest.json`);
1722
+ if (existsSync7(pluginManifestPath)) hasAnyComponent = true;
1473
1723
  return hasAnyComponent;
1474
1724
  }
1475
1725
  var init_manifest = __esm({
@@ -1620,52 +1870,26 @@ var init_logger = __esm({
1620
1870
  }
1621
1871
  });
1622
1872
 
1623
- // src/utils/fs.ts
1624
- import { writeFileSync, renameSync, existsSync as existsSync6, unlinkSync as unlinkSync2 } from "fs";
1625
- import { dirname as dirname2 } from "path";
1626
- function atomicWriteFileSync(filePath, data, encoding = "utf-8") {
1627
- const dir = dirname2(filePath);
1628
- if (!existsSync6(dir)) {
1629
- throw new Error(`Directory does not exist: ${dir}`);
1630
- }
1631
- const tmpPath = `${filePath}.tmp`;
1632
- writeFileSync(tmpPath, data, encoding);
1633
- try {
1634
- renameSync(tmpPath, filePath);
1635
- } catch (e) {
1636
- try {
1637
- unlinkSync2(tmpPath);
1638
- } catch {
1639
- }
1640
- throw e;
1641
- }
1642
- }
1643
- var init_fs = __esm({
1644
- "src/utils/fs.ts"() {
1645
- "use strict";
1646
- }
1647
- });
1648
-
1649
1873
  // src/utils/config.ts
1650
- import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3 } from "fs";
1651
- import { join as join6 } from "path";
1874
+ import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync4 } from "fs";
1875
+ import { join as join7 } from "path";
1652
1876
  import { parse, stringify } from "yaml";
1653
1877
  function getConfigDir() {
1654
1878
  return getCannbotConfigDir();
1655
1879
  }
1656
1880
  function getConfigPath() {
1657
- return join6(getConfigDir(), "config.yaml");
1881
+ return join7(getConfigDir(), "config.yaml");
1658
1882
  }
1659
1883
  function readConfig() {
1660
1884
  const configPath = getConfigPath();
1661
- if (!existsSync7(configPath)) {
1885
+ if (!existsSync8(configPath)) {
1662
1886
  return {
1663
1887
  language: "zh_CN",
1664
1888
  installedPlugins: []
1665
1889
  };
1666
1890
  }
1667
1891
  try {
1668
- const content = readFileSync3(configPath, "utf-8");
1892
+ const content = readFileSync4(configPath, "utf-8");
1669
1893
  const parsed = parse(content);
1670
1894
  return {
1671
1895
  language: parsed.language || "zh_CN",
@@ -1684,8 +1908,8 @@ function readConfig() {
1684
1908
  }
1685
1909
  function writeConfig(config) {
1686
1910
  const configDir = getConfigDir();
1687
- if (!existsSync7(configDir)) {
1688
- mkdirSync(configDir, { recursive: true });
1911
+ if (!existsSync8(configDir)) {
1912
+ mkdirSync2(configDir, { recursive: true });
1689
1913
  }
1690
1914
  const configPath = getConfigPath();
1691
1915
  const content = stringify(config);
@@ -1998,221 +2222,13 @@ import chalk7 from "chalk";
1998
2222
  init_paths();
1999
2223
  init_logger();
2000
2224
  init_i18n();
2225
+ init_scanner();
2001
2226
  import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync6, rmSync as rmSync2 } from "fs";
2002
2227
  import { join as join9, dirname as dirname4 } from "path";
2003
2228
  import { fileURLToPath as fileURLToPath3 } from "url";
2004
2229
  import { execa as execa2 } from "execa";
2005
2230
  import { parse as parseYaml2 } from "yaml";
2006
2231
 
2007
- // src/core/scanner.ts
2008
- init_paths();
2009
- init_fs();
2010
- init_fs_helpers();
2011
- import { existsSync as existsSync8, readdirSync as readdirSync2, readFileSync as readFileSync4, mkdirSync as mkdirSync2 } from "fs";
2012
- import { join as join7, dirname as dirname3 } from "path";
2013
- import { fileURLToPath as fileURLToPath2 } from "url";
2014
- import { parse as parseYaml } from "yaml";
2015
- var __filename2 = fileURLToPath2(import.meta.url);
2016
- var __dirname2 = dirname3(__filename2);
2017
- var EXCLUDE_DIRS = /* @__PURE__ */ new Set([
2018
- "node_modules",
2019
- ".git",
2020
- "asc-devkit",
2021
- "cann-samples",
2022
- "tilelang-ascend",
2023
- ".agents",
2024
- ".opencode",
2025
- ".claude",
2026
- ".claude-plugin",
2027
- "dist",
2028
- "build",
2029
- "references",
2030
- "hooks",
2031
- "operators",
2032
- "workflows",
2033
- "tests",
2034
- "docs",
2035
- "scripts"
2036
- ]);
2037
- function loadScanConfig() {
2038
- const configPath = join7(__dirname2, "config", "repository.yaml");
2039
- try {
2040
- const config = parseYaml(readFileSync4(configPath, "utf-8"));
2041
- const ttlHours = config.scanCacheTtlHours || 24;
2042
- return {
2043
- skillDirs: config.scanDirs || ["ops", "model", "graph", "infra", "runtime"],
2044
- pluginDirs: config.pluginDirs || ["plugins-official", "plugins-community"],
2045
- cacheTtlMs: ttlHours * 60 * 60 * 1e3
2046
- };
2047
- } catch {
2048
- return {
2049
- skillDirs: ["ops", "model", "graph", "infra", "runtime"],
2050
- pluginDirs: ["plugins-official", "plugins-community"],
2051
- cacheTtlMs: 24 * 60 * 60 * 1e3
2052
- };
2053
- }
2054
- }
2055
- var scanConfig = loadScanConfig();
2056
- var SKILL_SCAN_DIRS = scanConfig.skillDirs;
2057
- var PLUGIN_SCAN_DIRS = scanConfig.pluginDirs;
2058
- function getScanDirs() {
2059
- return [...SKILL_SCAN_DIRS];
2060
- }
2061
- function scanSkills(repoPath) {
2062
- const skills = [];
2063
- const seen = /* @__PURE__ */ new Set();
2064
- for (const dir of SKILL_SCAN_DIRS) {
2065
- const fullPath = join7(repoPath, dir);
2066
- if (!existsSync8(fullPath)) continue;
2067
- scanDirectory(fullPath, repoPath, dir, skills, seen);
2068
- }
2069
- for (const pluginDir of PLUGIN_SCAN_DIRS) {
2070
- const pluginParent = join7(repoPath, pluginDir);
2071
- if (!existsSync8(pluginParent)) continue;
2072
- for (const plugin of safeReaddir(pluginParent)) {
2073
- const pluginPath = join7(pluginParent, plugin);
2074
- if (!isDirectory(pluginPath)) continue;
2075
- const skillsDir = join7(pluginPath, "skills");
2076
- if (existsSync8(skillsDir)) {
2077
- scanDirectory(skillsDir, repoPath, `${pluginDir}/${plugin}/skills`, skills, seen);
2078
- }
2079
- const skillDir = join7(pluginPath, "skill");
2080
- if (existsSync8(skillDir)) {
2081
- scanDirectory(skillDir, repoPath, `${pluginDir}/${plugin}/skill`, skills, seen);
2082
- }
2083
- const rootSkillMd = join7(pluginPath, "SKILL.md");
2084
- const initSh = join7(pluginPath, "init.sh");
2085
- if (existsSync8(rootSkillMd) && !existsSync8(initSh)) {
2086
- const frontmatter = parseFrontmatter(rootSkillMd);
2087
- if (frontmatter && !seen.has(frontmatter.name)) {
2088
- seen.add(frontmatter.name);
2089
- skills.push({
2090
- id: frontmatter.name,
2091
- description: frontmatter.description,
2092
- source: `${pluginDir}/${plugin}`,
2093
- filePath: rootSkillMd
2094
- });
2095
- }
2096
- }
2097
- }
2098
- }
2099
- return skills;
2100
- }
2101
- function parseFrontmatter(filePath) {
2102
- try {
2103
- const content = readFileSync4(filePath, "utf-8");
2104
- const lines = content.split("\n");
2105
- if (lines.length < 3) return null;
2106
- if (lines[0].trim() !== "---") return null;
2107
- let endIndex = -1;
2108
- for (let i = 1; i < lines.length; i++) {
2109
- if (lines[i].trim() === "---") {
2110
- endIndex = i;
2111
- break;
2112
- }
2113
- }
2114
- if (endIndex === -1) return null;
2115
- const yamlBlock = lines.slice(1, endIndex).map((l) => l.replace(/\r$/, "")).join("\n");
2116
- const parsed = parseYaml(yamlBlock);
2117
- if (!parsed || typeof parsed !== "object") return null;
2118
- if (!parsed.name || typeof parsed.name !== "string") return null;
2119
- const trimmedName = parsed.name.trim();
2120
- if (!trimmedName || /[\/\\]|\.\./.test(trimmedName) || !/^[a-zA-Z0-9._-]+$/.test(trimmedName)) {
2121
- return null;
2122
- }
2123
- return {
2124
- name: trimmedName,
2125
- description: (parsed.description || "").trim()
2126
- };
2127
- } catch {
2128
- return null;
2129
- }
2130
- }
2131
- function getCurrentCommit(repoPath) {
2132
- try {
2133
- const headFile = join7(repoPath, ".git", "HEAD");
2134
- if (!existsSync8(headFile)) return "unknown";
2135
- const headContent = readFileSync4(headFile, "utf-8").trim();
2136
- if (headContent.startsWith("ref: ")) {
2137
- const refPath = join7(repoPath, ".git", headContent.slice(5));
2138
- if (existsSync8(refPath)) {
2139
- return readFileSync4(refPath, "utf-8").trim();
2140
- }
2141
- const packedRefsPath = join7(repoPath, ".git", "packed-refs");
2142
- if (existsSync8(packedRefsPath)) {
2143
- const packedRefs = readFileSync4(packedRefsPath, "utf-8");
2144
- const refName = headContent.slice(5);
2145
- const lines = packedRefs.split("\n");
2146
- for (const line of lines) {
2147
- if (line.endsWith(refName)) {
2148
- return line.split(" ")[0];
2149
- }
2150
- }
2151
- }
2152
- }
2153
- return headContent;
2154
- } catch {
2155
- return "unknown";
2156
- }
2157
- }
2158
- function readScanCache() {
2159
- try {
2160
- const cachePath = getCachePath();
2161
- if (!existsSync8(cachePath)) return null;
2162
- const content = readFileSync4(cachePath, "utf-8");
2163
- const cache = JSON.parse(content);
2164
- if (!cache.skills || !cache.timestamp) return null;
2165
- const age = Date.now() - cache.timestamp;
2166
- if (age > scanConfig.cacheTtlMs) return null;
2167
- return cache;
2168
- } catch {
2169
- return null;
2170
- }
2171
- }
2172
- function writeScanCache(cache) {
2173
- try {
2174
- const cachePath = getCachePath();
2175
- const cacheDir = dirname3(cachePath);
2176
- if (!existsSync8(cacheDir)) {
2177
- mkdirSync2(cacheDir, { recursive: true });
2178
- }
2179
- atomicWriteFileSync(cachePath, JSON.stringify(cache, null, 2));
2180
- } catch {
2181
- }
2182
- }
2183
- function getCachePath() {
2184
- return join7(getCannbotConfigDir(), "scan-cache.json");
2185
- }
2186
- function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
2187
- for (const entry of safeReaddir(dirPath)) {
2188
- const fullPath = join7(dirPath, entry);
2189
- if (EXCLUDE_DIRS.has(entry)) continue;
2190
- if (!isDirectory(fullPath)) continue;
2191
- const skillMd = join7(fullPath, "SKILL.md");
2192
- if (existsSync8(skillMd)) {
2193
- const frontmatter = parseFrontmatter(skillMd);
2194
- if (frontmatter && !seen.has(frontmatter.name)) {
2195
- seen.add(frontmatter.name);
2196
- skills.push({
2197
- id: frontmatter.name,
2198
- description: frontmatter.description,
2199
- source: sourcePrefix,
2200
- filePath: skillMd
2201
- });
2202
- }
2203
- continue;
2204
- }
2205
- scanDirectory(fullPath, repoPath, sourcePrefix + "/" + entry, skills, seen);
2206
- }
2207
- }
2208
- function safeReaddir(dir) {
2209
- try {
2210
- return readdirSync2(dir);
2211
- } catch {
2212
- return [];
2213
- }
2214
- }
2215
-
2216
2232
  // src/core/skill-registry.ts
2217
2233
  init_i18n();
2218
2234
  var CATEGORY_DEFS = [
@@ -2458,6 +2474,7 @@ init_registry();
2458
2474
 
2459
2475
  // src/core/metadata-sync.ts
2460
2476
  init_registry();
2477
+ init_scanner();
2461
2478
  import { existsSync as existsSync9, readFileSync as readFileSync5, statSync as statSync2, readdirSync as readdirSync3 } from "fs";
2462
2479
  import { join as join8, sep } from "path";
2463
2480
  function readPluginJson(pluginDir) {
@@ -2853,7 +2870,7 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
2853
2870
  files.push(configRootConfigPath);
2854
2871
  }
2855
2872
  }
2856
- const repoLinks = externalRepoNames && externalRepoNames.length > 0 ? externalRepoNames : ["asc-devkit", "pypto", "tilelang-ascend", "cann-recipes-infer", "cann-samples"];
2873
+ const repoLinks = externalRepoNames && externalRepoNames.length > 0 ? externalRepoNames : ["asc-devkit", "pypto", "tilelang-ascend", "cann-recipes-infer", "cann-samples", "ops-tensor"];
2857
2874
  for (const repoName of repoLinks) {
2858
2875
  const repoLinkPath = join10(installPath, repoName);
2859
2876
  if (isSymlink(repoLinkPath)) {