@jingyi0605/codingns 0.2.5 → 0.3.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.
Files changed (109) hide show
  1. package/bin/codingns.mjs +278 -2
  2. package/dist/public/assets/{TerminalPage-BkjqU9NG.js → TerminalPage-Dfw1QUqW.js} +1 -1
  3. package/dist/public/assets/index-DR2rPNi7.css +1 -0
  4. package/dist/public/assets/index-DTOruahn.js +114 -0
  5. package/dist/public/index.html +2 -2
  6. package/dist/server/config/env.d.ts +2 -0
  7. package/dist/server/config/env.js +32 -3
  8. package/dist/server/config/env.js.map +1 -1
  9. package/dist/server/modules/butler/butler-control-session-service.d.ts +3 -1
  10. package/dist/server/modules/butler/butler-control-session-service.js +28 -4
  11. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  12. package/dist/server/modules/butler/butler-session-service.d.ts +1 -0
  13. package/dist/server/modules/butler/butler-session-service.js +72 -15
  14. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  15. package/dist/server/modules/debug-target/debug-target-service.d.ts +5 -2
  16. package/dist/server/modules/debug-target/debug-target-service.js +170 -10
  17. package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
  18. package/dist/server/modules/file/file-constants.d.ts +1 -0
  19. package/dist/server/modules/file/file-constants.js +1 -0
  20. package/dist/server/modules/file/file-constants.js.map +1 -1
  21. package/dist/server/modules/file/file-controller.js +12 -3
  22. package/dist/server/modules/file/file-controller.js.map +1 -1
  23. package/dist/server/modules/file/file-preview-link-service.js +6 -37
  24. package/dist/server/modules/file/file-preview-link-service.js.map +1 -1
  25. package/dist/server/modules/file/file-preview-service.d.ts +6 -12
  26. package/dist/server/modules/file/file-preview-service.js +114 -28
  27. package/dist/server/modules/file/file-preview-service.js.map +1 -1
  28. package/dist/server/modules/file/file-preview-types.d.ts +37 -0
  29. package/dist/server/modules/file/file-preview-types.js +84 -0
  30. package/dist/server/modules/file/file-preview-types.js.map +1 -0
  31. package/dist/server/modules/git/git-controller.d.ts +6 -0
  32. package/dist/server/modules/git/git-controller.js +13 -0
  33. package/dist/server/modules/git/git-controller.js.map +1 -1
  34. package/dist/server/modules/git/git-read-service.d.ts +2 -1
  35. package/dist/server/modules/git/git-read-service.js +100 -0
  36. package/dist/server/modules/git/git-read-service.js.map +1 -1
  37. package/dist/server/modules/git/types.d.ts +23 -0
  38. package/dist/server/modules/sessions/session-activity-authority-service.js +13 -1
  39. package/dist/server/modules/sessions/session-activity-authority-service.js.map +1 -1
  40. package/dist/server/modules/sessions/session-activity-inspector.js +21 -5
  41. package/dist/server/modules/sessions/session-activity-inspector.js.map +1 -1
  42. package/dist/server/modules/sessions/session-history-service.d.ts +8 -2
  43. package/dist/server/modules/sessions/session-history-service.js +117 -42
  44. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  45. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +2 -1
  46. package/dist/server/modules/sessions/session-live-runtime-service.js +12 -0
  47. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  48. package/dist/server/modules/skills/skill-controller.d.ts +23 -0
  49. package/dist/server/modules/skills/skill-controller.js +35 -0
  50. package/dist/server/modules/skills/skill-controller.js.map +1 -0
  51. package/dist/server/modules/skills/skill-manager-service.d.ts +86 -0
  52. package/dist/server/modules/skills/skill-manager-service.js +557 -0
  53. package/dist/server/modules/skills/skill-manager-service.js.map +1 -0
  54. package/dist/server/modules/skills/skill-reconciler.d.ts +21 -0
  55. package/dist/server/modules/skills/skill-reconciler.js +99 -0
  56. package/dist/server/modules/skills/skill-reconciler.js.map +1 -0
  57. package/dist/server/modules/skills/skill-sync-planner.d.ts +8 -0
  58. package/dist/server/modules/skills/skill-sync-planner.js +20 -0
  59. package/dist/server/modules/skills/skill-sync-planner.js.map +1 -0
  60. package/dist/server/modules/skills/skill-target-adapter.d.ts +34 -0
  61. package/dist/server/modules/skills/skill-target-adapter.js +65 -0
  62. package/dist/server/modules/skills/skill-target-adapter.js.map +1 -0
  63. package/dist/server/modules/tailscale/tailscale-controller.d.ts +15 -0
  64. package/dist/server/modules/tailscale/tailscale-controller.js +33 -0
  65. package/dist/server/modules/tailscale/tailscale-controller.js.map +1 -0
  66. package/dist/server/modules/tailscale/tailscale-helper-client.d.ts +41 -0
  67. package/dist/server/modules/tailscale/tailscale-helper-client.js +135 -0
  68. package/dist/server/modules/tailscale/tailscale-helper-client.js.map +1 -0
  69. package/dist/server/modules/tailscale/tailscale-helper-process.d.ts +1 -0
  70. package/dist/server/modules/tailscale/tailscale-helper-process.js +327 -0
  71. package/dist/server/modules/tailscale/tailscale-helper-process.js.map +1 -0
  72. package/dist/server/modules/tailscale/tailscale-manager.d.ts +41 -0
  73. package/dist/server/modules/tailscale/tailscale-manager.js +259 -0
  74. package/dist/server/modules/tailscale/tailscale-manager.js.map +1 -0
  75. package/dist/server/modules/tailscale/tailscale-service.d.ts +43 -0
  76. package/dist/server/modules/tailscale/tailscale-service.js +201 -0
  77. package/dist/server/modules/tailscale/tailscale-service.js.map +1 -0
  78. package/dist/server/routes/git.js +1 -0
  79. package/dist/server/routes/git.js.map +1 -1
  80. package/dist/server/routes/skills.d.ts +3 -0
  81. package/dist/server/routes/skills.js +7 -0
  82. package/dist/server/routes/skills.js.map +1 -0
  83. package/dist/server/routes/system.d.ts +3 -0
  84. package/dist/server/routes/system.js +9 -0
  85. package/dist/server/routes/system.js.map +1 -0
  86. package/dist/server/server/create-server.d.ts +12 -0
  87. package/dist/server/server/create-server.js +42 -3
  88. package/dist/server/server/create-server.js.map +1 -1
  89. package/dist/server/shared/utils/command-availability.d.ts +1 -0
  90. package/dist/server/shared/utils/command-availability.js +26 -3
  91. package/dist/server/shared/utils/command-availability.js.map +1 -1
  92. package/dist/server/storage/repositories/instance-tailscale-repository.d.ts +10 -0
  93. package/dist/server/storage/repositories/instance-tailscale-repository.js +112 -0
  94. package/dist/server/storage/repositories/instance-tailscale-repository.js.map +1 -0
  95. package/dist/server/storage/repositories/managed-skill-repository.d.ts +11 -0
  96. package/dist/server/storage/repositories/managed-skill-repository.js +102 -0
  97. package/dist/server/storage/repositories/managed-skill-repository.js.map +1 -0
  98. package/dist/server/storage/repositories/skill-target-binding-repository.d.ts +10 -0
  99. package/dist/server/storage/repositories/skill-target-binding-repository.js +77 -0
  100. package/dist/server/storage/repositories/skill-target-binding-repository.js.map +1 -0
  101. package/dist/server/storage/sqlite/client.js +10 -0
  102. package/dist/server/storage/sqlite/client.js.map +1 -1
  103. package/dist/server/storage/sqlite/schema.sql +65 -0
  104. package/dist/server/types/domain.d.ts +72 -0
  105. package/dist/server/ws/ws-server.js +4 -4
  106. package/dist/server/ws/ws-server.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/public/assets/index-C6U8-9jg.css +0 -1
  109. package/dist/public/assets/index-CKSumuV2.js +0 -109
package/bin/codingns.mjs CHANGED
@@ -21,6 +21,9 @@ switch (command) {
21
21
  case "assistant":
22
22
  await runAssistantCommand(argv);
23
23
  break;
24
+ case "skills":
25
+ await runSkillsCommand(argv);
26
+ break;
24
27
  default:
25
28
  console.error(`[codingns] 不支持的命令:${command}`);
26
29
  printHelp(1);
@@ -70,6 +73,7 @@ async function runStartCommand(argv) {
70
73
  host,
71
74
  port,
72
75
  webUiDir: path.join(distRoot, "public"),
76
+ webUiPort: port,
73
77
  databasePath: path.join(dataDir, "host.sqlite"),
74
78
  releaseManifestRoot: path.join(dataDir, "releases"),
75
79
  serverUpdatePackageName: "@jingyi0605/codingns",
@@ -248,6 +252,84 @@ async function runAssistantCommand(argv) {
248
252
  }
249
253
  }
250
254
 
255
+ async function runSkillsCommand(argv) {
256
+ const [action, ...rest] = argv;
257
+
258
+ if (!action || action === "help" || action === "--help" || action === "-h") {
259
+ printSkillsHelpTopic(buildSkillsHelpTopic(rest[0]), 0);
260
+ }
261
+
262
+ if (rest.length > 0 && isHelpToken(rest[0])) {
263
+ printSkillsHelpTopic(buildSkillsHelpTopic(action), 0);
264
+ }
265
+
266
+ switch (action) {
267
+ case "overview":
268
+ await printAssistantResponse(await requestSkills({
269
+ method: "GET",
270
+ path: "/api/skills/overview",
271
+ argv: rest,
272
+ supportedOptions: ["target"],
273
+ repeatableOptions: ["target"],
274
+ helpTopic: "skills.overview"
275
+ }, (options) => {
276
+ const targets = readMultiOptionValues(options.values.target);
277
+
278
+ return targets.length > 0
279
+ ? { targetCli: targets.join(",") }
280
+ : null;
281
+ }));
282
+ return;
283
+ case "add":
284
+ await printAssistantResponse(await requestSkills({
285
+ method: "POST",
286
+ path: "/api/skills",
287
+ argv: rest,
288
+ supportedOptions: ["source", "target", "source-type"],
289
+ repeatableOptions: ["target"],
290
+ helpTopic: "skills.add"
291
+ }, (options) => ({
292
+ sourcePath: requireOptionValue(options.values.source, "source"),
293
+ targetCli: requireMultiOptionValues(options.values.target, "target"),
294
+ sourceType: readOptionalTrimmedValue(options.values["source-type"]) ?? "local-import"
295
+ })));
296
+ return;
297
+ case "import":
298
+ await printAssistantResponse(await requestSkills({
299
+ method: "POST",
300
+ path: "/api/skills/import",
301
+ argv: rest,
302
+ supportedOptions: ["cli", "path", "expected-hash", "target"],
303
+ repeatableOptions: ["target"],
304
+ helpTopic: "skills.import"
305
+ }, (options) => ({
306
+ targetCli: requireOptionValue(options.values.cli, "cli"),
307
+ directoryPath: requireOptionValue(options.values.path, "path"),
308
+ expectedContentHash: readOptionalTrimmedValue(options.values["expected-hash"]),
309
+ additionalTargetCli: readMultiOptionValues(options.values.target)
310
+ })));
311
+ return;
312
+ case "sync": {
313
+ const [skillId, ...tail] = rest;
314
+ await printAssistantResponse(await requestSkills({
315
+ method: "POST",
316
+ path: "/api/skills/sync",
317
+ argv: tail,
318
+ supportedOptions: ["target"],
319
+ repeatableOptions: ["target"],
320
+ helpTopic: "skills.sync"
321
+ }, (options) => ({
322
+ skillId: requirePositional(skillId, "skillId"),
323
+ targetCli: requireMultiOptionValues(options.values.target, "target")
324
+ })));
325
+ return;
326
+ }
327
+ default:
328
+ console.error(`[codingns] 不支持的 skills 子命令:${action}`);
329
+ printSkillsHelpTopic("skills", 1);
330
+ }
331
+ }
332
+
251
333
  async function requestAssistant(command, buildPayload) {
252
334
  const options = parseArgs(command.argv, {
253
335
  supportedOptions: [
@@ -321,6 +403,80 @@ async function requestAssistant(command, buildPayload) {
321
403
  return responseBody ?? rawBody;
322
404
  }
323
405
 
406
+ async function requestSkills(command, buildPayload) {
407
+ const options = parseArgs(command.argv, {
408
+ supportedOptions: [
409
+ "base-url",
410
+ "token",
411
+ ...(command.supportedOptions ?? [])
412
+ ],
413
+ repeatableOptions: command.repeatableOptions ?? []
414
+ });
415
+
416
+ if (options.help) {
417
+ printSkillsHelpTopic(command.helpTopic ?? "skills", 0);
418
+ }
419
+
420
+ if (options.errors.length > 0) {
421
+ for (const error of options.errors) {
422
+ console.error(`[codingns] ${error}`);
423
+ }
424
+ printSkillsHelpTopic(command.helpTopic ?? "skills", 1);
425
+ }
426
+
427
+ const baseUrl = resolveAssistantBaseUrl(options.values["base-url"]);
428
+ const accessToken = resolveAssistantAccessToken(options.values.token);
429
+ const url = new URL(command.path, appendTrailingSlash(baseUrl));
430
+ const payload = buildPayload ? buildPayload(options) : null;
431
+
432
+ if (command.method === "GET" && payload) {
433
+ for (const [key, value] of Object.entries(payload)) {
434
+ if (typeof value === "string" && value.length > 0) {
435
+ url.searchParams.set(key, value);
436
+ }
437
+ }
438
+ }
439
+
440
+ let response;
441
+
442
+ try {
443
+ response = await fetch(url, {
444
+ method: command.method,
445
+ headers: {
446
+ Authorization: `Bearer ${accessToken}`,
447
+ ...(command.method === "POST" ? { "Content-Type": "application/json" } : {})
448
+ },
449
+ body: command.method === "POST" ? JSON.stringify(payload ?? {}) : undefined
450
+ });
451
+ } catch (error) {
452
+ const message = error instanceof Error ? error.message : "未知网络错误";
453
+ console.error(JSON.stringify({
454
+ ok: false,
455
+ detail: `Skill 管理请求失败:${message}`,
456
+ target: url.toString()
457
+ }, null, 2));
458
+ process.exit(1);
459
+ }
460
+
461
+ const rawBody = await response.text();
462
+ const responseBody = tryParseJson(rawBody);
463
+
464
+ if (!response.ok) {
465
+ const detail = typeof responseBody?.detail === "string"
466
+ ? responseBody.detail
467
+ : `HTTP ${response.status}`;
468
+ console.error(JSON.stringify({
469
+ ok: false,
470
+ status: response.status,
471
+ detail,
472
+ body: responseBody ?? rawBody
473
+ }, null, 2));
474
+ process.exit(1);
475
+ }
476
+
477
+ return responseBody ?? rawBody;
478
+ }
479
+
324
480
  async function printAssistantResponse(payload) {
325
481
  if (typeof payload === "string") {
326
482
  console.log(payload);
@@ -336,6 +492,7 @@ function parseArgs(argv, input = {}) {
336
492
  const errors = [];
337
493
  const supportedOptions = new Set(input.supportedOptions ?? []);
338
494
  const supportedFlags = new Set(input.supportedFlags ?? []);
495
+ const repeatableOptions = new Set(input.repeatableOptions ?? []);
339
496
  let index = 0;
340
497
 
341
498
  while (index < argv.length) {
@@ -378,7 +535,12 @@ function parseArgs(argv, input = {}) {
378
535
  }
379
536
 
380
537
  if (inlineValue !== undefined) {
381
- values[rawName] = inlineValue;
538
+ if (repeatableOptions.has(rawName)) {
539
+ const current = values[rawName];
540
+ values[rawName] = Array.isArray(current) ? [...current, inlineValue] : current ? [current, inlineValue] : [inlineValue];
541
+ } else {
542
+ values[rawName] = inlineValue;
543
+ }
382
544
  index += 1;
383
545
  continue;
384
546
  }
@@ -391,7 +553,12 @@ function parseArgs(argv, input = {}) {
391
553
  continue;
392
554
  }
393
555
 
394
- values[rawName] = nextValue;
556
+ if (repeatableOptions.has(rawName)) {
557
+ const current = values[rawName];
558
+ values[rawName] = Array.isArray(current) ? [...current, nextValue] : current ? [current, nextValue] : [nextValue];
559
+ } else {
560
+ values[rawName] = nextValue;
561
+ }
395
562
  index += 2;
396
563
  }
397
564
 
@@ -447,6 +614,19 @@ function readOptionalTrimmedValue(value) {
447
614
  return normalized.length > 0 ? normalized : null;
448
615
  }
449
616
 
617
+ function readMultiOptionValues(value) {
618
+ const values = Array.isArray(value)
619
+ ? value
620
+ : typeof value === "string"
621
+ ? [value]
622
+ : [];
623
+
624
+ return values
625
+ .flatMap((item) => item.split(","))
626
+ .map((item) => item.trim())
627
+ .filter((item) => item.length > 0);
628
+ }
629
+
450
630
  function requireOptionValue(value, field) {
451
631
  const normalized = readOptionalTrimmedValue(value);
452
632
 
@@ -457,6 +637,16 @@ function requireOptionValue(value, field) {
457
637
  return normalized;
458
638
  }
459
639
 
640
+ function requireMultiOptionValues(value, field) {
641
+ const normalized = readMultiOptionValues(value);
642
+
643
+ if (normalized.length === 0) {
644
+ fail(`参数 --${field} 不能为空`);
645
+ }
646
+
647
+ return normalized;
648
+ }
649
+
460
650
  function requirePositional(value, field) {
461
651
  const normalized = typeof value === "string" ? value.trim() : "";
462
652
 
@@ -549,6 +739,7 @@ codingns 用法:
549
739
 
550
740
  codingns start [--host 0.0.0.0] [--port 3002] [--data-dir ~/.codingns] [--demo]
551
741
  codingns assistant <group> <action> [options]
742
+ codingns skills <action> [options]
552
743
 
553
744
  说明:
554
745
 
@@ -564,6 +755,12 @@ assistant 例子:
564
755
  codingns assistant projects list --status active --token <token>
565
756
  codingns assistant sessions send <sessionId> --message "继续修复类型错误" --token <token>
566
757
  codingns assistant terminals send <terminalId> --input "npm test\\n" --token <token>
758
+
759
+ skills 例子:
760
+
761
+ codingns skills overview --token <token>
762
+ codingns skills add --source ./my-skill --target codex --token <token>
763
+ codingns skills sync <skillId> --target gemini --token <token>
567
764
  `.trim();
568
765
 
569
766
  if (exitCode === 0) {
@@ -587,6 +784,18 @@ function printAssistantHelpTopic(topic, exitCode) {
587
784
  process.exit(exitCode);
588
785
  }
589
786
 
787
+ function printSkillsHelpTopic(topic, exitCode) {
788
+ const output = getSkillsHelpText(topic);
789
+
790
+ if (exitCode === 0) {
791
+ console.log(output);
792
+ } else {
793
+ console.error(output);
794
+ }
795
+
796
+ process.exit(exitCode);
797
+ }
798
+
590
799
  function getAssistantHelpText(topic) {
591
800
  switch (topic) {
592
801
  case "capabilities":
@@ -777,6 +986,65 @@ codingns assistant 用法:
777
986
  }
778
987
  }
779
988
 
989
+ function getSkillsHelpText(topic) {
990
+ switch (topic) {
991
+ case "skills.overview":
992
+ return `
993
+ codingns skills overview
994
+
995
+ 用途:
996
+ 查看当前 Host 聚合后的 skill 概况,包括受管、未纳管、冲突和诊断结果。
997
+
998
+ 用法:
999
+ codingns skills overview [--target codex] [--target gemini] --token <token>
1000
+ `.trim();
1001
+ case "skills.add":
1002
+ return `
1003
+ codingns skills add
1004
+
1005
+ 用途:
1006
+ 把本地 skill 目录纳入统一管理,并只同步到你指定的目标 CLI。
1007
+
1008
+ 用法:
1009
+ codingns skills add --source <path> --target <cli> [--target <cli>] [--source-type local-import|builtin|managed-copy] --token <token>
1010
+ `.trim();
1011
+ case "skills.import":
1012
+ return `
1013
+ codingns skills import
1014
+
1015
+ 用途:
1016
+ 把某个 CLI 目录里已存在但未纳管的 skill 导入 SSOT,并可顺带同步到其他目标。
1017
+
1018
+ 用法:
1019
+ codingns skills import --cli <cli> --path <directoryPath> [--expected-hash <hash>] [--target <cli>] --token <token>
1020
+ `.trim();
1021
+ case "skills.sync":
1022
+ return `
1023
+ codingns skills sync
1024
+
1025
+ 用途:
1026
+ 把指定受管 skill 再同步到一个或多个目标 CLI。
1027
+
1028
+ 用法:
1029
+ codingns skills sync <skillId> --target <cli> [--target <cli>] --token <token>
1030
+ `.trim();
1031
+ default:
1032
+ return `
1033
+ codingns skills 用法:
1034
+
1035
+ codingns skills overview [--target <cli>] --token <token>
1036
+ codingns skills add --source <path> --target <cli> [--target <cli>] [--source-type local-import|builtin|managed-copy] --token <token>
1037
+ codingns skills import --cli <cli> --path <directoryPath> [--expected-hash <hash>] [--target <cli>] --token <token>
1038
+ codingns skills sync <skillId> --target <cli> [--target <cli>] --token <token>
1039
+
1040
+ 环境变量:
1041
+
1042
+ CODINGNS_BASE_URL 默认 Host 地址,未传时默认 http://127.0.0.1:3002
1043
+ CODINGNS_ACCESS_TOKEN 默认 Bearer token
1044
+ `.trim();
1045
+ }
1046
+ }
1047
+
780
1048
  function buildAssistantHelpTopic(action, rest) {
781
1049
  if (!action || action === "--help" || action === "-h") {
782
1050
  return "assistant";
@@ -789,6 +1057,14 @@ function buildAssistantHelpTopic(action, rest) {
789
1057
  return `${action}.${rest[0]}`;
790
1058
  }
791
1059
 
1060
+ function buildSkillsHelpTopic(action) {
1061
+ if (!action || action === "--help" || action === "-h") {
1062
+ return "skills";
1063
+ }
1064
+
1065
+ return `skills.${action}`;
1066
+ }
1067
+
792
1068
  function isHelpToken(value) {
793
1069
  return value === "help" || value === "--help" || value === "-h";
794
1070
  }
@@ -1,4 +1,4 @@
1
- var pl=Object.defineProperty;var gl=(e,t,i)=>t in e?pl(e,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[t]=i;var Ze=(e,t,i)=>gl(e,typeof t!="symbol"?t+"":t,i);import{C as vl,a as Bn,g as Sl,u as bl,b as wl,r as w,c as yl,s as Cl,d as xl,e as kl,f as El,t as b,h as Tl,l as Go,i as Rl,w as Bl,j as Ml,k as _,T as Dl,M as Ll,m as rr,n as Mn,o as Pl,p as Al,q as Zo,v as Il,x as Nl,y as Ol,z as Fl}from"./index-CKSumuV2.js";/**
1
+ var pl=Object.defineProperty;var gl=(e,t,i)=>t in e?pl(e,t,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[t]=i;var Ze=(e,t,i)=>gl(e,typeof t!="symbol"?t+"":t,i);import{C as vl,a as Bn,g as Sl,u as bl,b as wl,r as w,c as yl,s as Cl,d as xl,e as kl,f as El,t as b,h as Tl,l as Go,i as Rl,w as Bl,j as Ml,k as _,T as Dl,M as Ll,m as rr,n as Mn,o as Pl,p as Al,q as Zo,v as Il,x as Nl,y as Ol,z as Fl}from"./index-DTOruahn.js";/**
2
2
  * Copyright (c) 2014-2024 The xterm.js authors. All rights reserved.
3
3
  * @license MIT
4
4
  *