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

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,917 @@ 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/embedded-config.json
705
+ var embedded_config_default;
706
+ var init_embedded_config = __esm({
707
+ "src/embedded-config.json"() {
708
+ embedded_config_default = {
709
+ scanDirs: [
710
+ "ops",
711
+ "model",
712
+ "graph",
713
+ "infra",
714
+ "runtime",
715
+ "tools"
716
+ ],
717
+ pluginDirs: [
718
+ "plugins-official"
719
+ ],
720
+ cacheTtlHours: 24
721
+ };
722
+ }
723
+ });
724
+
725
+ // src/core/scanner.ts
726
+ import { existsSync as existsSync4, readdirSync, readFileSync as readFileSync2, mkdirSync } from "fs";
727
+ import { join as join3, dirname as dirname3 } from "path";
728
+ import { fileURLToPath as fileURLToPath2 } from "url";
729
+ import { parse as parseYaml } from "yaml";
730
+ function loadScanConfig() {
731
+ const configCandidates = [
732
+ join3(__dirname2, "config", "repository.yaml"),
733
+ join3(__dirname2, "..", "config", "repository.yaml")
734
+ ];
735
+ for (const configPath of configCandidates) {
736
+ try {
737
+ const config = parseYaml(readFileSync2(configPath, "utf-8"));
738
+ if (!config) continue;
739
+ const ttlHours = config.scanCacheTtlHours || 24;
740
+ return {
741
+ skillDirs: config.scanDirs || ["ops", "model", "graph", "infra", "runtime"],
742
+ pluginDirs: config.pluginDirs || ["plugins-official", "plugins-community"],
743
+ cacheTtlMs: ttlHours * 60 * 60 * 1e3
744
+ };
745
+ } catch {
746
+ }
747
+ }
748
+ const embedded = embedded_config_default;
749
+ if (Array.isArray(embedded.scanDirs) && embedded.scanDirs.length > 0) {
750
+ return {
751
+ skillDirs: embedded.scanDirs,
752
+ pluginDirs: Array.isArray(embedded.pluginDirs) && embedded.pluginDirs.length > 0 ? embedded.pluginDirs : ["plugins-official", "plugins-community"],
753
+ cacheTtlMs: (embedded.cacheTtlHours || 24) * 60 * 60 * 1e3
754
+ };
755
+ }
756
+ return {
757
+ skillDirs: ["ops", "model", "graph", "infra", "runtime"],
758
+ pluginDirs: ["plugins-official", "plugins-community"],
759
+ cacheTtlMs: 24 * 60 * 60 * 1e3
760
+ };
761
+ }
762
+ function getScanDirs() {
763
+ return [...SKILL_SCAN_DIRS];
764
+ }
765
+ function getPluginDirs() {
766
+ return [...PLUGIN_SCAN_DIRS];
767
+ }
768
+ function scanSkills(repoPath) {
769
+ const skills = [];
770
+ const seen = /* @__PURE__ */ new Set();
771
+ for (const dir of SKILL_SCAN_DIRS) {
772
+ const fullPath = join3(repoPath, dir);
773
+ if (!existsSync4(fullPath)) continue;
774
+ scanDirectory(fullPath, repoPath, dir, skills, seen);
775
+ }
776
+ for (const pluginDir of PLUGIN_SCAN_DIRS) {
777
+ const pluginParent = join3(repoPath, pluginDir);
778
+ if (!existsSync4(pluginParent)) continue;
779
+ for (const plugin of safeReaddir(pluginParent)) {
780
+ const pluginPath = join3(pluginParent, plugin);
781
+ if (!isDirectory(pluginPath)) continue;
782
+ const skillsDir = join3(pluginPath, "skills");
783
+ if (existsSync4(skillsDir)) {
784
+ scanDirectory(skillsDir, repoPath, `${pluginDir}/${plugin}/skills`, skills, seen);
785
+ }
786
+ const skillDir = join3(pluginPath, "skill");
787
+ if (existsSync4(skillDir)) {
788
+ scanDirectory(skillDir, repoPath, `${pluginDir}/${plugin}/skill`, skills, seen);
789
+ }
790
+ const rootSkillMd = join3(pluginPath, "SKILL.md");
791
+ const initSh = join3(pluginPath, "init.sh");
792
+ if (existsSync4(rootSkillMd) && !existsSync4(initSh)) {
793
+ const frontmatter = parseFrontmatter(rootSkillMd);
794
+ if (frontmatter && !seen.has(frontmatter.name)) {
795
+ seen.add(frontmatter.name);
796
+ skills.push({
797
+ id: frontmatter.name,
798
+ description: frontmatter.description,
799
+ source: `${pluginDir}/${plugin}`,
800
+ filePath: rootSkillMd
801
+ });
802
+ }
803
+ }
804
+ }
805
+ }
806
+ return skills;
807
+ }
808
+ function parseFrontmatter(filePath) {
809
+ try {
810
+ const content = readFileSync2(filePath, "utf-8");
811
+ const lines = content.split("\n");
812
+ if (lines.length < 3) return null;
813
+ if (lines[0].trim() !== "---") return null;
814
+ let endIndex = -1;
815
+ for (let i = 1; i < lines.length; i++) {
816
+ if (lines[i].trim() === "---") {
817
+ endIndex = i;
818
+ break;
819
+ }
820
+ }
821
+ if (endIndex === -1) return null;
822
+ const yamlBlock = lines.slice(1, endIndex).map((l) => l.replace(/\r$/, "")).join("\n");
823
+ const parsed = parseYaml(yamlBlock);
824
+ if (!parsed || typeof parsed !== "object") return null;
825
+ if (!parsed.name || typeof parsed.name !== "string") return null;
826
+ const trimmedName = parsed.name.trim();
827
+ if (!trimmedName || /[\/\\]|\.\./.test(trimmedName) || !/^[a-zA-Z0-9._-]+$/.test(trimmedName)) {
828
+ return null;
829
+ }
830
+ return {
831
+ name: trimmedName,
832
+ description: (parsed.description || "").trim()
833
+ };
834
+ } catch {
835
+ return null;
836
+ }
837
+ }
838
+ function getCurrentCommit(repoPath) {
839
+ try {
840
+ const headFile = join3(repoPath, ".git", "HEAD");
841
+ if (!existsSync4(headFile)) return "unknown";
842
+ const headContent = readFileSync2(headFile, "utf-8").trim();
843
+ if (headContent.startsWith("ref: ")) {
844
+ const refPath = join3(repoPath, ".git", headContent.slice(5));
845
+ if (existsSync4(refPath)) {
846
+ return readFileSync2(refPath, "utf-8").trim();
847
+ }
848
+ const packedRefsPath = join3(repoPath, ".git", "packed-refs");
849
+ if (existsSync4(packedRefsPath)) {
850
+ const packedRefs = readFileSync2(packedRefsPath, "utf-8");
851
+ const refName = headContent.slice(5);
852
+ const lines = packedRefs.split("\n");
853
+ for (const line of lines) {
854
+ if (line.endsWith(refName)) {
855
+ return line.split(" ")[0];
856
+ }
857
+ }
858
+ }
859
+ }
860
+ return headContent;
861
+ } catch {
862
+ return "unknown";
863
+ }
864
+ }
865
+ function readScanCache() {
866
+ try {
867
+ const cachePath = getCachePath();
868
+ if (!existsSync4(cachePath)) return null;
869
+ const content = readFileSync2(cachePath, "utf-8");
870
+ const cache = JSON.parse(content);
871
+ if (!cache.skills || !cache.timestamp) return null;
872
+ const age = Date.now() - cache.timestamp;
873
+ if (age > scanConfig.cacheTtlMs) return null;
874
+ return cache;
875
+ } catch {
876
+ return null;
877
+ }
878
+ }
879
+ function writeScanCache(cache) {
880
+ try {
881
+ const cachePath = getCachePath();
882
+ const cacheDir = dirname3(cachePath);
883
+ if (!existsSync4(cacheDir)) {
884
+ mkdirSync(cacheDir, { recursive: true });
885
+ }
886
+ atomicWriteFileSync(cachePath, JSON.stringify(cache, null, 2));
887
+ } catch {
888
+ }
889
+ }
890
+ function getCachePath() {
891
+ return join3(getCannbotConfigDir(), "scan-cache.json");
892
+ }
893
+ function scanDirectory(dirPath, repoPath, sourcePrefix, skills, seen) {
894
+ for (const entry of safeReaddir(dirPath)) {
895
+ const fullPath = join3(dirPath, entry);
896
+ if (EXCLUDE_DIRS.has(entry)) continue;
897
+ if (!isDirectory(fullPath)) continue;
898
+ const skillMd = join3(fullPath, "SKILL.md");
899
+ if (existsSync4(skillMd)) {
900
+ const frontmatter = parseFrontmatter(skillMd);
901
+ if (frontmatter && !seen.has(frontmatter.name)) {
902
+ seen.add(frontmatter.name);
903
+ skills.push({
904
+ id: frontmatter.name,
905
+ description: frontmatter.description,
906
+ source: sourcePrefix,
907
+ filePath: skillMd
908
+ });
1186
909
  }
910
+ continue;
1187
911
  }
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
- );
912
+ scanDirectory(fullPath, repoPath, sourcePrefix + "/" + entry, skills, seen);
913
+ }
914
+ }
915
+ function safeReaddir(dir) {
916
+ try {
917
+ return readdirSync(dir);
918
+ } catch {
919
+ return [];
920
+ }
921
+ }
922
+ var __filename2, __dirname2, EXCLUDE_DIRS, scanConfig, SKILL_SCAN_DIRS, PLUGIN_SCAN_DIRS;
923
+ var init_scanner = __esm({
924
+ "src/core/scanner.ts"() {
925
+ "use strict";
926
+ init_paths();
927
+ init_fs();
928
+ init_fs_helpers();
929
+ init_embedded_config();
930
+ __filename2 = fileURLToPath2(import.meta.url);
931
+ __dirname2 = dirname3(__filename2);
932
+ EXCLUDE_DIRS = /* @__PURE__ */ new Set([
933
+ "node_modules",
934
+ ".git",
935
+ "asc-devkit",
936
+ "cann-samples",
937
+ "tilelang-ascend",
938
+ ".agents",
939
+ ".opencode",
940
+ ".claude",
941
+ ".claude-plugin",
942
+ "dist",
943
+ "build",
944
+ "references",
945
+ "hooks",
946
+ "operators",
947
+ "workflows",
948
+ "tests",
949
+ "docs",
950
+ "scripts"
951
+ ]);
952
+ scanConfig = loadScanConfig();
953
+ SKILL_SCAN_DIRS = scanConfig.skillDirs;
954
+ PLUGIN_SCAN_DIRS = scanConfig.pluginDirs;
955
+ }
956
+ });
957
+
958
+ // src/embedded-plugins.json
959
+ var embedded_plugins_default;
960
+ var init_embedded_plugins = __esm({
961
+ "src/embedded-plugins.json"() {
962
+ embedded_plugins_default = [
963
+ {
964
+ id: "ops-direct-invoke",
965
+ dir: "plugins-official/ops-direct-invoke",
966
+ displayName: "AscendC Kernel \u76F4\u8C03",
967
+ script: "init.sh",
968
+ aliases: [
969
+ "ops-direct",
970
+ "ascendc-direct",
971
+ "direct",
972
+ "kernel"
973
+ ],
974
+ skills: 0,
975
+ agents: 6,
976
+ 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",
977
+ version: "2.0.0",
978
+ configFile: "AGENTS.md",
979
+ configRootConfigLink: false,
980
+ installSkills: [],
981
+ installAgents: [
982
+ "architect",
983
+ "developer",
984
+ "developer-code",
985
+ "developer-doc",
986
+ "developer-test",
987
+ "qa"
988
+ ]
989
+ },
990
+ {
991
+ id: "ops-direct-invoke-flash",
992
+ dir: "plugins-official/ops-direct-invoke-flash",
993
+ displayName: "AscendC Kernel \u76F4\u8C03\uFF08\u5FEB\u901F\u7248\uFF09",
994
+ script: "init.sh",
995
+ aliases: [
996
+ "flash",
997
+ "kernel-flash"
998
+ ],
999
+ skills: 7,
1000
+ agents: 1,
1001
+ description: "\u4ECE\u6570\u5B66\u516C\u5F0F\u6216\u4EE3\u7801\u7247\u6BB5\u5FEB\u901F\u6784\u5EFA\u5E76\u9A8C\u8BC1 Ascend NPU \u6838\u51FD\u6570",
1002
+ version: "1.2.2",
1003
+ configFile: "AGENTS.md",
1004
+ configRootConfigLink: true,
1005
+ installSkills: [
1006
+ {
1007
+ dir: "plugins-official/ops-direct-invoke-flash/skills",
1008
+ skills: [
1009
+ "ops-direct-invoke-flash"
1010
+ ]
1011
+ },
1012
+ {
1013
+ dir: "ops",
1014
+ skills: [
1015
+ "ascendc-st-design",
1016
+ "ascendc-whitebox-design"
1017
+ ]
1018
+ },
1019
+ {
1020
+ dir: "infra",
1021
+ skills: [
1022
+ "gitcode-toolkit",
1023
+ "gitcode-pr-handler",
1024
+ "gitcode-issue-gen",
1025
+ "gitcode-issue-handler"
1026
+ ]
1027
+ }
1028
+ ],
1029
+ installAgents: [
1030
+ "ops-direct-invoke-flash-reviewer"
1031
+ ]
1032
+ },
1033
+ {
1034
+ id: "ops-registry-invoke",
1035
+ dir: "plugins-official/ops-registry-invoke",
1036
+ displayName: "AscendC \u7B97\u5B50\u6CE8\u518C\u8C03\u7528",
1037
+ script: "init.sh",
1038
+ aliases: [
1039
+ "ops-registry",
1040
+ "ascendc-registry",
1041
+ "registry"
1042
+ ],
1043
+ skills: 30,
1044
+ agents: 7,
1045
+ description: "\u751F\u4EA7\u7EA7 ACLNN \u6CE8\u518C\u7B97\u5B50\u5168\u6D41\u7A0B\uFF1A\u4EE3\u7801\u2192UT/ST\u2192\u4E0A\u5E93",
1046
+ version: "1.2.3",
1047
+ configFile: "AGENTS.md",
1048
+ configRootConfigLink: false,
1049
+ installSkills: [
1050
+ {
1051
+ dir: "ops",
1052
+ skills: [
1053
+ "ascendc-blaze-best-practice",
1054
+ "ascendc-blaze-migration",
1055
+ "ascendc-api-best-practices",
1056
+ "ascendc-code-review",
1057
+ "ascendc-crash-debug",
1058
+ "ascendc-direct-invoke-template",
1059
+ "ascendc-docs-gen",
1060
+ "ascendc-docs-search",
1061
+ "ascendc-env-check",
1062
+ "npu-arch",
1063
+ "ascendc-performance-best-practices",
1064
+ "ascendc-precision-debug",
1065
+ "ascendc-perf-optimize",
1066
+ "ascendc-regbase-best-practice",
1067
+ "ascendc-registry-invoke-template",
1068
+ "ascendc-runtime-debug",
1069
+ "ascendc-st-design",
1070
+ "ascendc-tiling-design",
1071
+ "ascendc-ut-develop",
1072
+ "ascendc-whitebox-design",
1073
+ "ops-precision-standard",
1074
+ "ops-profiling",
1075
+ "ops-simulator",
1076
+ "ops-spec-gen"
1077
+ ]
1078
+ },
1079
+ {
1080
+ dir: "infra",
1081
+ skills: [
1082
+ "gitcode-toolkit",
1083
+ "gitcode-pr-handler",
1084
+ "gitcode-issue-gen",
1085
+ "gitcode-issue-handler"
1086
+ ]
1087
+ },
1088
+ {
1089
+ dir: "plugins-official/ops-registry-invoke",
1090
+ skills: [
1091
+ {
1092
+ name: "workflow",
1093
+ as: "ops-registry-invoke-workflow"
1094
+ }
1095
+ ]
1096
+ },
1097
+ {
1098
+ dir: "plugins-official/ops-registry-invoke/skills",
1099
+ skills: [
1100
+ "spec-to-design"
1101
+ ]
1102
+ }
1103
+ ],
1104
+ installAgents: [
1105
+ "ascendc-ops-architect",
1106
+ "ascendc-ops-spec-reviewer",
1107
+ "ascendc-ops-designer",
1108
+ "ascendc-ops-design-reviewer",
1109
+ "ascendc-ops-tester",
1110
+ "ascendc-ops-test-design-reviewer",
1111
+ "ascendc-ops-developer"
1112
+ ],
1113
+ externalRepos: [
1114
+ {
1115
+ url: "https://gitcode.com/cann/asc-devkit.git",
1116
+ dir: "plugins-official/ops-registry-invoke/reference/cann/asc-devkit",
1117
+ depth: 1,
1118
+ configRootLink: false
1119
+ },
1120
+ {
1121
+ url: "https://gitcode.com/cann/ops-tensor.git",
1122
+ dir: "plugins-official/ops-registry-invoke/ops-tensor",
1123
+ configRootLink: false
1124
+ }
1125
+ ]
1126
+ },
1127
+ {
1128
+ id: "catlass-op-generator",
1129
+ dir: "plugins-official/catlass-op-generator",
1130
+ displayName: "Catlass \u7B97\u5B50\u76F4\u8C03",
1131
+ script: "init.sh",
1132
+ aliases: [
1133
+ "catlass"
1134
+ ],
1135
+ skills: 14,
1136
+ agents: 3,
1137
+ description: "Catlass \u6A21\u677F\u62FC\u88C5 GEMM/Matmul/Epilogue \u7B97\u5B50\u5F00\u53D1",
1138
+ version: "1.0.0",
1139
+ configFile: "AGENTS.md",
1140
+ configRootConfigLink: true,
1141
+ installSkills: [
1142
+ {
1143
+ dir: "ops",
1144
+ skills: [
1145
+ "catlass-op-design",
1146
+ "catlass-op-develop",
1147
+ "catlass-op-perf-tune",
1148
+ "ascendc-tiling-design",
1149
+ "npu-arch",
1150
+ "ascendc-api-best-practices",
1151
+ "ops-precision-standard",
1152
+ "ascendc-docs-search",
1153
+ "ascendc-env-check",
1154
+ "ascendc-precision-debug",
1155
+ "ops-profiling",
1156
+ "ascendc-runtime-debug",
1157
+ "ascendc-code-review",
1158
+ "torch-ascendc-op-extension"
1159
+ ]
1160
+ }
1161
+ ],
1162
+ installAgents: [
1163
+ "catlass-op-architect",
1164
+ "catlass-op-generator",
1165
+ "catlass-op-reviewer"
1166
+ ],
1167
+ externalRepos: [
1168
+ {
1169
+ url: "https://gitcode.com/cann/asc-devkit.git",
1170
+ dir: "plugins-official/catlass-op-generator/asc-devkit",
1171
+ configRootLink: false
1172
+ }
1173
+ ]
1174
+ },
1175
+ {
1176
+ id: "model-infer-optimize",
1177
+ dir: "plugins-official/model-infer-optimize",
1178
+ displayName: "NPU \u63A8\u7406\u4F18\u5316",
1179
+ script: "init.sh",
1180
+ aliases: [
1181
+ "model-infer",
1182
+ "infer",
1183
+ "inference",
1184
+ "sota",
1185
+ "sota-approach",
1186
+ "model-infer-sota"
1187
+ ],
1188
+ skills: 14,
1189
+ agents: 9,
1190
+ 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",
1191
+ version: "1.0.6",
1192
+ configFile: "AGENTS.md",
1193
+ configRootConfigLink: true,
1194
+ installSkills: [
1195
+ {
1196
+ dir: "model",
1197
+ skills: [
1198
+ "model-infer-migrator",
1199
+ "model-infer-parallel-analysis",
1200
+ "model-infer-parallel-impl",
1201
+ "model-infer-kvcache",
1202
+ "model-infer-fusion",
1203
+ "model-infer-quantization",
1204
+ "model-infer-graph-mode",
1205
+ "model-infer-precision-debug",
1206
+ "model-infer-runtime-debug",
1207
+ "model-infer-multi-stream",
1208
+ "model-infer-prefetch",
1209
+ "model-infer-superkernel",
1210
+ "model-infer-profiling",
1211
+ "model-infer-perf-breakdown"
1212
+ ]
1213
+ }
1214
+ ],
1215
+ installAgents: [
1216
+ "model-infer-analyzer",
1217
+ "model-infer-implementer",
1218
+ "model-infer-reviewer",
1219
+ "model-infer-sota-scenario",
1220
+ "model-infer-sota-profiling-instrumenter",
1221
+ "model-infer-sota-profile-analyzer",
1222
+ "model-infer-sota-candidate",
1223
+ "model-infer-sota-implementer",
1224
+ "model-infer-sota-reviewer"
1225
+ ],
1226
+ externalRepos: [
1227
+ {
1228
+ url: "https://gitcode.com/cann/cann-recipes-infer.git",
1229
+ dir: "plugins-official/model-infer-optimize/cann-recipes-infer",
1230
+ depth: 1,
1231
+ configRootLink: true
1232
+ }
1233
+ ]
1234
+ },
1235
+ {
1236
+ id: "pypto-op-orchestrator",
1237
+ dir: "plugins-official/pypto-op-orchestrator",
1238
+ displayName: "PyPTO \u7B97\u5B50\u5F00\u53D1",
1239
+ script: "init.sh",
1240
+ aliases: [
1241
+ "pypto",
1242
+ "pytorch"
1243
+ ],
1244
+ skills: 17,
1245
+ agents: 8,
1246
+ 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",
1247
+ version: "1.2.0",
1248
+ configFile: "AGENTS.md",
1249
+ configRootConfigLink: false,
1250
+ installSkills: [
1251
+ {
1252
+ dir: "ops",
1253
+ skills: [
1254
+ "pypto-orchestration-manual",
1255
+ "pypto-intent-understand",
1256
+ "pypto-op-plan",
1257
+ "pypto-api-explore",
1258
+ "pypto-docs-search",
1259
+ "pypto-golden-generate",
1260
+ "pypto-op-design",
1261
+ "pypto-op-construct",
1262
+ "pypto-op-develop",
1263
+ "pypto-op-verify",
1264
+ "pypto-op-review",
1265
+ "pypto-precision-compare",
1266
+ "pypto-precision-debug",
1267
+ "pypto-general-debug",
1268
+ "pypto-op-perf-tune",
1269
+ "pypto-op-knowledge",
1270
+ "pypto-memory-template"
1271
+ ]
1272
+ }
1273
+ ],
1274
+ installAgents: [
1275
+ "pypto-op-planner",
1276
+ "pypto-op-mathematician",
1277
+ "pypto-op-architect",
1278
+ "pypto-op-designer",
1279
+ "pypto-op-coder",
1280
+ "pypto-op-verifier",
1281
+ "pypto-op-debugger",
1282
+ "pypto-op-optimizer"
1283
+ ],
1284
+ externalRepos: [
1285
+ {
1286
+ url: "https://gitcode.com/cann/pypto.git",
1287
+ dir: "plugins-official/pypto-op-orchestrator/pypto",
1288
+ configRootLink: false
1289
+ }
1290
+ ]
1291
+ },
1292
+ {
1293
+ id: "tilelang-op-orchestrator",
1294
+ dir: "plugins-official/tilelang-op-orchestrator",
1295
+ displayName: "TileLang \u7B97\u5B50\u5F00\u53D1",
1296
+ script: "init.sh",
1297
+ aliases: [
1298
+ "tilelang"
1299
+ ],
1300
+ skills: 9,
1301
+ agents: 3,
1302
+ description: "TileLang Python DSL + @tilelang.jit \u7B97\u5B50\u5F00\u53D1\uFF08\u652F\u6301 Developer/Expert \u53CC\u6A21\u5F0F\uFF09",
1303
+ version: "1.1.0",
1304
+ configFile: "AGENTS.md",
1305
+ configRootConfigLink: false,
1306
+ installSkills: [
1307
+ {
1308
+ dir: "ops",
1309
+ skills: [
1310
+ "tilelang-api-best-practices",
1311
+ "tilelang-env-check",
1312
+ "tilelang-op-design",
1313
+ "tilelang-op-develop",
1314
+ "tilelang-op-test-design",
1315
+ "tilelang-perf-optimization",
1316
+ "tilelang-programming-model-guide",
1317
+ "tilelang-review",
1318
+ "tilelang-submodule-pull"
1319
+ ]
1320
+ }
1321
+ ],
1322
+ installAgents: [
1323
+ "tilelang-op-analyst",
1324
+ "tilelang-op-developer",
1325
+ "tilelang-op-perf-tuner"
1326
+ ],
1327
+ externalRepos: [
1328
+ {
1329
+ url: "https://github.com/tile-ai/tilelang-ascend.git",
1330
+ dir: "plugins-official/tilelang-op-orchestrator/tilelang-ascend",
1331
+ depth: 1,
1332
+ recursive: true,
1333
+ configRootLink: false
1334
+ }
1335
+ ]
1336
+ },
1337
+ {
1338
+ id: "triton-op-generator",
1339
+ dir: "plugins-official/triton-op-generator",
1340
+ displayName: "Triton \u7B97\u5B50\u5F00\u53D1",
1341
+ script: "init.sh",
1342
+ aliases: [
1343
+ "triton"
1344
+ ],
1345
+ skills: 8,
1346
+ agents: 0,
1347
+ 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",
1348
+ version: "1.0.2",
1349
+ configFile: "AGENTS.md",
1350
+ configRootConfigLink: false,
1351
+ installSkills: [
1352
+ {
1353
+ dir: "ops",
1354
+ skills: [
1355
+ "triton-task-extractor",
1356
+ "triton-op-designer",
1357
+ "triton-op-coding",
1358
+ "triton-op-verifier",
1359
+ "triton-latency-optimizer",
1360
+ "triton-precision-debug",
1361
+ "npu-arch",
1362
+ "triton-simulator-optimizer"
1363
+ ]
1364
+ }
1365
+ ],
1366
+ installAgents: []
1367
+ },
1368
+ {
1369
+ id: "torch-compile",
1370
+ dir: "plugins-official/torch-compile",
1371
+ displayName: "torch.compile \u56FE\u6A21\u5F0F",
1372
+ script: "init.sh",
1373
+ aliases: [
1374
+ "torch",
1375
+ "compile",
1376
+ "graph"
1377
+ ],
1378
+ skills: 7,
1379
+ agents: 1,
1380
+ 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",
1381
+ version: "1.0.4",
1382
+ configFile: "AGENTS.md",
1383
+ configRootConfigLink: true,
1384
+ installSkills: [
1385
+ {
1386
+ dir: "graph",
1387
+ skills: [
1388
+ "torch-npugraph-ex-knowledge",
1389
+ "torch-npugraph-ex-template",
1390
+ "torch-npugraph-ex-dfx-triage",
1391
+ "torch-npugraph-ex-compile-error-diagnosis",
1392
+ "torch-npugraph-ex-runtime-error-diagnosis",
1393
+ "torch-npugraph-ex-performance-diagnosis",
1394
+ "torch-custom-ops-guide"
1395
+ ]
1396
+ }
1397
+ ],
1398
+ installAgents: [
1399
+ "torch-npugraph-ex"
1400
+ ]
1401
+ },
1402
+ {
1403
+ id: "ops-code-reviewer",
1404
+ dir: "plugins-official/ops-code-reviewer",
1405
+ displayName: "\u4EE3\u7801\u68C0\u89C6",
1406
+ script: "init.sh",
1407
+ aliases: [
1408
+ "code-review",
1409
+ "reviewer",
1410
+ "review"
1411
+ ],
1412
+ skills: 4,
1413
+ agents: 2,
1414
+ 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",
1415
+ version: "1.1.0",
1416
+ configFile: "AGENTS.md",
1417
+ configRootConfigLink: false,
1418
+ installSkills: [
1419
+ {
1420
+ dir: "ops",
1421
+ skills: [
1422
+ "ascendc-code-review",
1423
+ "ascendc-docs-search",
1424
+ "ascendc-api-best-practices",
1425
+ "npu-arch"
1426
+ ]
1427
+ }
1428
+ ],
1429
+ installAgents: [
1430
+ "ascendc-ops-reviewer",
1431
+ "ascendc-code-summarizer"
1432
+ ]
1433
+ }
1434
+ ];
1200
1435
  }
1436
+ });
1437
+
1438
+ // src/core/registry.ts
1439
+ import { readdirSync as readdirSync2, existsSync as existsSync5 } from "fs";
1440
+ import { join as join4 } from "path";
1441
+ function loadPlugins() {
1442
+ const plugins = [...embedded_plugins_default];
1443
+ plugins.sort(
1444
+ (a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0
1445
+ );
1446
+ return plugins;
1201
1447
  }
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");
1448
+ function mergeDynamicPlugins(repoPath) {
1449
+ if (!existsSync5(repoPath)) return;
1450
+ const existingIds = new Set(PLUGIN_REGISTRY.map((p) => p.id));
1451
+ const dynamic = [];
1452
+ for (const pluginDir of getPluginDirs()) {
1453
+ const parent = join4(repoPath, pluginDir);
1454
+ if (!existsSync5(parent)) continue;
1455
+ let entries = [];
1456
+ try {
1457
+ entries = readdirSync2(parent);
1458
+ } catch {
1459
+ continue;
1460
+ }
1461
+ for (const entry of entries) {
1462
+ const pluginPath = join4(parent, entry);
1463
+ if (!isDirectory(pluginPath)) continue;
1464
+ if (entry === "install-helper") continue;
1465
+ const initSh = join4(pluginPath, "init.sh");
1466
+ if (!existsSync5(initSh)) continue;
1467
+ const pluginId = entry;
1468
+ if (existingIds.has(pluginId)) continue;
1469
+ dynamic.push({
1470
+ id: pluginId,
1471
+ dir: `${pluginDir}/${entry}`,
1472
+ displayName: entry,
1473
+ script: "init.sh",
1474
+ aliases: [],
1475
+ skills: 0,
1476
+ agents: 0,
1477
+ description: ""
1478
+ });
1479
+ existingIds.add(pluginId);
1209
1480
  }
1210
- return join3(base || process.cwd(), ".agents", "skills");
1211
1481
  }
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");
1482
+ if (dynamic.length > 0) {
1483
+ PLUGIN_REGISTRY = [...PLUGIN_REGISTRY, ...dynamic].sort(
1484
+ (a, b) => a.displayName < b.displayName ? -1 : a.displayName > b.displayName ? 1 : 0
1485
+ );
1486
+ }
1219
1487
  }
1220
- function getManifestPath(configRoot) {
1221
- return join3(configRoot, "cannbot-manifest.json");
1488
+ function findPlugin(query) {
1489
+ const normalized = query.toLowerCase().trim();
1490
+ const exactMatch = PLUGIN_REGISTRY.find(
1491
+ (p) => p.id === normalized || p.id === query.trim()
1492
+ );
1493
+ if (exactMatch) return exactMatch;
1494
+ const aliasMatch = PLUGIN_REGISTRY.find(
1495
+ (p) => p.aliases.some((a) => a === normalized)
1496
+ );
1497
+ if (aliasMatch) return aliasMatch;
1498
+ const prefixMatches = PLUGIN_REGISTRY.filter((p) => p.id.startsWith(normalized));
1499
+ if (prefixMatches.length === 1) return prefixMatches[0];
1500
+ return void 0;
1222
1501
  }
1223
- function getCannbotConfigDir() {
1224
- return join3(homedir(), ".cannbot");
1502
+ function getAllPlugins() {
1503
+ return PLUGIN_REGISTRY;
1225
1504
  }
1226
- function getCannbotRepoPath() {
1227
- return join3(getCannbotConfigDir(), "repo");
1505
+ function getPluginById(id) {
1506
+ return PLUGIN_REGISTRY.find((p) => p.id === id);
1228
1507
  }
1229
- var VALID_TOOLS, VALID_LEVELS;
1230
- var init_paths = __esm({
1231
- "src/utils/paths.ts"() {
1508
+ var PLUGIN_REGISTRY;
1509
+ var init_registry = __esm({
1510
+ "src/core/registry.ts"() {
1232
1511
  "use strict";
1233
- init_i18n();
1234
- VALID_TOOLS = ["opencode", "claude", "trae", "cursor", "codex", "copilot", "codearts"];
1235
- VALID_LEVELS = ["project", "global"];
1512
+ init_fs_helpers();
1513
+ init_scanner();
1514
+ init_embedded_plugins();
1515
+ PLUGIN_REGISTRY = loadPlugins();
1236
1516
  }
1237
1517
  });
1238
1518
 
1239
1519
  // src/core/detector.ts
1240
1520
  import { execa } from "execa";
1241
- import { existsSync as existsSync4 } from "fs";
1521
+ import { existsSync as existsSync6 } from "fs";
1242
1522
  import { homedir as homedir2 } from "os";
1243
- import { join as join4 } from "path";
1523
+ import { join as join5 } from "path";
1244
1524
  async function getCommandVersion(cmd, args = ["--version"]) {
1245
1525
  try {
1246
1526
  const result = await execa(cmd, args, { timeout: 5e3 });
@@ -1276,12 +1556,12 @@ async function detectTrae() {
1276
1556
  const home = homedir2();
1277
1557
  const variant = detectTraeVariant();
1278
1558
  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");
1559
+ if (variant === "ide" && existsSync6(join5(home, ".trae-cn"))) {
1560
+ path = join5(home, ".trae-cn");
1561
+ } else if (variant === "plugin" && existsSync6(join5(home, ".marscode"))) {
1562
+ path = join5(home, ".marscode");
1563
+ } else if (variant === "cli" && existsSync6(join5(home, ".traecli"))) {
1564
+ path = join5(home, ".traecli");
1285
1565
  } else if (variant === "unknown") {
1286
1566
  const cmdPath = await getCommandPath("trae");
1287
1567
  if (cmdPath) path = cmdPath;
@@ -1297,7 +1577,7 @@ async function detectCursor() {
1297
1577
  }
1298
1578
  if (process.platform === "darwin") {
1299
1579
  const appPath = "/Applications/Cursor.app";
1300
- if (existsSync4(appPath)) {
1580
+ if (existsSync6(appPath)) {
1301
1581
  return { name: "cursor", path: appPath };
1302
1582
  }
1303
1583
  }
@@ -1310,8 +1590,8 @@ async function detectCodex() {
1310
1590
  return { name: "codex", version, path: cmdPath };
1311
1591
  }
1312
1592
  const home = homedir2();
1313
- const configDir = join4(home, ".codex");
1314
- if (existsSync4(configDir)) {
1593
+ const configDir = join5(home, ".codex");
1594
+ if (existsSync6(configDir)) {
1315
1595
  return { name: "codex", path: configDir };
1316
1596
  }
1317
1597
  return void 0;
@@ -1328,8 +1608,8 @@ async function detectCopilot() {
1328
1608
  }
1329
1609
  async function detectCodeArts() {
1330
1610
  const home = homedir2();
1331
- const configDir = join4(home, ".codeartsdoer");
1332
- if (existsSync4(configDir)) {
1611
+ const configDir = join5(home, ".codeartsdoer");
1612
+ if (existsSync6(configDir)) {
1333
1613
  return { name: "codearts", path: configDir };
1334
1614
  }
1335
1615
  return void 0;
@@ -1376,13 +1656,13 @@ var init_detector = __esm({
1376
1656
  });
1377
1657
 
1378
1658
  // src/core/manifest.ts
1379
- import { existsSync as existsSync5, readFileSync as readFileSync2 } from "fs";
1380
- import { join as join5 } from "path";
1659
+ import { existsSync as existsSync7, readFileSync as readFileSync3 } from "fs";
1660
+ import { join as join6 } from "path";
1381
1661
  function readManifest(configRoot) {
1382
1662
  const manifestPath = getManifestPath(configRoot);
1383
- if (existsSync5(manifestPath)) {
1663
+ if (existsSync7(manifestPath)) {
1384
1664
  try {
1385
- const content = readFileSync2(manifestPath, "utf-8");
1665
+ const content = readFileSync3(manifestPath, "utf-8");
1386
1666
  return JSON.parse(content);
1387
1667
  } catch {
1388
1668
  }
@@ -1393,18 +1673,18 @@ function readAllManifests(configRoot) {
1393
1673
  const manifests = [];
1394
1674
  const plugins = getAllPlugins();
1395
1675
  const standardPath = getManifestPath(configRoot);
1396
- if (existsSync5(standardPath)) {
1676
+ if (existsSync7(standardPath)) {
1397
1677
  try {
1398
- const content = readFileSync2(standardPath, "utf-8");
1678
+ const content = readFileSync3(standardPath, "utf-8");
1399
1679
  manifests.push(JSON.parse(content));
1400
1680
  } catch {
1401
1681
  }
1402
1682
  }
1403
1683
  for (const plugin of plugins) {
1404
- const pluginManifestPath = join5(configRoot, `${plugin.id}-manifest.json`);
1405
- if (existsSync5(pluginManifestPath)) {
1684
+ const pluginManifestPath = join6(configRoot, `${plugin.id}-manifest.json`);
1685
+ if (existsSync7(pluginManifestPath)) {
1406
1686
  try {
1407
- const content = readFileSync2(pluginManifestPath, "utf-8");
1687
+ const content = readFileSync3(pluginManifestPath, "utf-8");
1408
1688
  manifests.push(JSON.parse(content));
1409
1689
  } catch {
1410
1690
  }
@@ -1448,28 +1728,28 @@ function scanInstalled() {
1448
1728
  }
1449
1729
  function verifyPluginFilesExist(configRoot, manifest, tool, level) {
1450
1730
  const skillsDir = getSkillsRoot(tool, level);
1451
- const agentsDir = join5(configRoot, "agents");
1731
+ const agentsDir = join6(configRoot, "agents");
1452
1732
  let hasAnyComponent = false;
1453
1733
  if (manifest.installed_skills && manifest.installed_skills.length > 0) {
1454
1734
  const hasAnySkill = manifest.installed_skills.some((skillId) => {
1455
- const skillPath = join5(skillsDir, skillId);
1456
- return existsSync5(skillPath) || isSymlink(skillPath);
1735
+ const skillPath = join6(skillsDir, skillId);
1736
+ return existsSync7(skillPath) || isSymlink(skillPath);
1457
1737
  });
1458
1738
  if (hasAnySkill) hasAnyComponent = true;
1459
1739
  }
1460
1740
  if (manifest.installed_agents && manifest.installed_agents.length > 0) {
1461
1741
  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);
1742
+ const agentPath = join6(agentsDir, agentId);
1743
+ const agentPathMd = join6(agentsDir, agentId + ".md");
1744
+ return existsSync7(agentPath) || isSymlink(agentPath) || existsSync7(agentPathMd) || isSymlink(agentPathMd);
1465
1745
  });
1466
1746
  if (hasAnyAgent) hasAnyComponent = true;
1467
1747
  }
1468
1748
  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;
1749
+ const configFilePath = level === "project" ? join6(configRoot, "..", agentsFileName) : join6(configRoot, agentsFileName);
1750
+ if (existsSync7(configFilePath) || isSymlink(configFilePath)) hasAnyComponent = true;
1751
+ const pluginManifestPath = join6(configRoot, `${manifest.team}-manifest.json`);
1752
+ if (existsSync7(pluginManifestPath)) hasAnyComponent = true;
1473
1753
  return hasAnyComponent;
1474
1754
  }
1475
1755
  var init_manifest = __esm({
@@ -1620,52 +1900,26 @@ var init_logger = __esm({
1620
1900
  }
1621
1901
  });
1622
1902
 
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
1903
  // src/utils/config.ts
1650
- import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3 } from "fs";
1651
- import { join as join6 } from "path";
1904
+ import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync4 } from "fs";
1905
+ import { join as join7 } from "path";
1652
1906
  import { parse, stringify } from "yaml";
1653
1907
  function getConfigDir() {
1654
1908
  return getCannbotConfigDir();
1655
1909
  }
1656
1910
  function getConfigPath() {
1657
- return join6(getConfigDir(), "config.yaml");
1911
+ return join7(getConfigDir(), "config.yaml");
1658
1912
  }
1659
1913
  function readConfig() {
1660
1914
  const configPath = getConfigPath();
1661
- if (!existsSync7(configPath)) {
1915
+ if (!existsSync8(configPath)) {
1662
1916
  return {
1663
1917
  language: "zh_CN",
1664
1918
  installedPlugins: []
1665
1919
  };
1666
1920
  }
1667
1921
  try {
1668
- const content = readFileSync3(configPath, "utf-8");
1922
+ const content = readFileSync4(configPath, "utf-8");
1669
1923
  const parsed = parse(content);
1670
1924
  return {
1671
1925
  language: parsed.language || "zh_CN",
@@ -1684,8 +1938,8 @@ function readConfig() {
1684
1938
  }
1685
1939
  function writeConfig(config) {
1686
1940
  const configDir = getConfigDir();
1687
- if (!existsSync7(configDir)) {
1688
- mkdirSync(configDir, { recursive: true });
1941
+ if (!existsSync8(configDir)) {
1942
+ mkdirSync2(configDir, { recursive: true });
1689
1943
  }
1690
1944
  const configPath = getConfigPath();
1691
1945
  const content = stringify(config);
@@ -1998,221 +2252,13 @@ import chalk7 from "chalk";
1998
2252
  init_paths();
1999
2253
  init_logger();
2000
2254
  init_i18n();
2255
+ init_scanner();
2001
2256
  import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync6, rmSync as rmSync2 } from "fs";
2002
2257
  import { join as join9, dirname as dirname4 } from "path";
2003
2258
  import { fileURLToPath as fileURLToPath3 } from "url";
2004
2259
  import { execa as execa2 } from "execa";
2005
2260
  import { parse as parseYaml2 } from "yaml";
2006
2261
 
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
2262
  // src/core/skill-registry.ts
2217
2263
  init_i18n();
2218
2264
  var CATEGORY_DEFS = [
@@ -2458,6 +2504,7 @@ init_registry();
2458
2504
 
2459
2505
  // src/core/metadata-sync.ts
2460
2506
  init_registry();
2507
+ init_scanner();
2461
2508
  import { existsSync as existsSync9, readFileSync as readFileSync5, statSync as statSync2, readdirSync as readdirSync3 } from "fs";
2462
2509
  import { join as join8, sep } from "path";
2463
2510
  function readPluginJson(pluginDir) {
@@ -2853,7 +2900,7 @@ function scanInstalledFiles(pluginId, displayName, tool, level, installPath, con
2853
2900
  files.push(configRootConfigPath);
2854
2901
  }
2855
2902
  }
2856
- const repoLinks = externalRepoNames && externalRepoNames.length > 0 ? externalRepoNames : ["asc-devkit", "pypto", "tilelang-ascend", "cann-recipes-infer", "cann-samples"];
2903
+ const repoLinks = externalRepoNames && externalRepoNames.length > 0 ? externalRepoNames : ["asc-devkit", "pypto", "tilelang-ascend", "cann-recipes-infer", "cann-samples", "ops-tensor"];
2857
2904
  for (const repoName of repoLinks) {
2858
2905
  const repoLinkPath = join10(installPath, repoName);
2859
2906
  if (isSymlink(repoLinkPath)) {