@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
@@ -0,0 +1,99 @@
1
+ export class SkillReconciler {
2
+ reconcile(input) {
3
+ const managed = [];
4
+ const unmanaged = [];
5
+ const conflicted = [];
6
+ const diagnostics = [...(input.diagnostics ?? [])];
7
+ const managedSkillById = new Map(input.managedSkills.map((record) => [record.id, record]));
8
+ const managedSkillByDirectoryName = new Map(input.managedSkills.map((record) => [record.directoryName, record]));
9
+ const targetRootByCli = new Map(input.targetLocations.map((location) => [location.targetCli, location.rootDir]));
10
+ const actualDirectoryKeys = new Set();
11
+ for (const directory of input.directories) {
12
+ const managedSkill = managedSkillByDirectoryName.get(directory.directoryName);
13
+ const managementState = resolveManagementState(directory, managedSkill);
14
+ const entry = createSkillScanEntry(directory, managedSkill, managementState);
15
+ actualDirectoryKeys.add(createDirectoryKey(directory.targetCli, directory.directoryName));
16
+ if (managementState === "managed") {
17
+ managed.push(entry);
18
+ continue;
19
+ }
20
+ if (managementState === "conflicted") {
21
+ conflicted.push(entry);
22
+ continue;
23
+ }
24
+ unmanaged.push(entry);
25
+ }
26
+ for (const binding of input.bindings) {
27
+ if (!binding.enabled) {
28
+ continue;
29
+ }
30
+ const managedSkill = managedSkillById.get(binding.skillId);
31
+ if (!managedSkill) {
32
+ continue;
33
+ }
34
+ const directoryKey = createDirectoryKey(binding.targetCli, managedSkill.directoryName);
35
+ if (actualDirectoryKeys.has(directoryKey)) {
36
+ continue;
37
+ }
38
+ diagnostics.push({
39
+ targetCli: binding.targetCli,
40
+ rootDir: targetRootByCli.get(binding.targetCli) ?? "",
41
+ code: "SKILL_TARGET_SKILL_MISSING",
42
+ detail: `目标 CLI 缺少受管 skill:${managedSkill.directoryName}`,
43
+ directoryName: managedSkill.directoryName,
44
+ directoryPath: null,
45
+ managedSkillId: managedSkill.id
46
+ });
47
+ }
48
+ return {
49
+ managed: sortSkillScanEntries(managed),
50
+ unmanaged: sortSkillScanEntries(unmanaged),
51
+ conflicted: sortSkillScanEntries(conflicted),
52
+ diagnostics: sortSkillScanDiagnostics(diagnostics),
53
+ scannedAt: input.scannedAt
54
+ };
55
+ }
56
+ }
57
+ function resolveManagementState(directory, managedSkill) {
58
+ if (!managedSkill) {
59
+ return "unmanaged";
60
+ }
61
+ return managedSkill.contentHash === directory.contentHash ? "managed" : "conflicted";
62
+ }
63
+ function createSkillScanEntry(directory, managedSkill, managementState) {
64
+ return {
65
+ targetCli: directory.targetCli,
66
+ directoryPath: directory.directoryPath,
67
+ directoryName: directory.directoryName,
68
+ name: directory.name,
69
+ contentHash: directory.contentHash,
70
+ managementState,
71
+ managedSkillId: managedSkill?.id ?? null
72
+ };
73
+ }
74
+ function createDirectoryKey(targetCli, directoryName) {
75
+ return `${targetCli}:${directoryName}`;
76
+ }
77
+ function sortSkillScanEntries(entries) {
78
+ return entries.sort((left, right) => {
79
+ const targetOrder = left.targetCli.localeCompare(right.targetCli);
80
+ if (targetOrder !== 0) {
81
+ return targetOrder;
82
+ }
83
+ return left.directoryName.localeCompare(right.directoryName);
84
+ });
85
+ }
86
+ function sortSkillScanDiagnostics(diagnostics) {
87
+ return diagnostics.sort((left, right) => {
88
+ const targetOrder = left.targetCli.localeCompare(right.targetCli);
89
+ if (targetOrder !== 0) {
90
+ return targetOrder;
91
+ }
92
+ const codeOrder = left.code.localeCompare(right.code);
93
+ if (codeOrder !== 0) {
94
+ return codeOrder;
95
+ }
96
+ return (left.directoryName ?? "").localeCompare(right.directoryName ?? "");
97
+ });
98
+ }
99
+ //# sourceMappingURL=skill-reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-reconciler.js","sourceRoot":"","sources":["../../../../src/modules/skills/skill-reconciler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { SkillTargetBindingRecord, SkillTargetCli } from "../../types/domain.js";
2
+ export interface PlannedSkillSyncTarget {
3
+ targetCli: SkillTargetCli;
4
+ existingBinding: SkillTargetBindingRecord | null;
5
+ }
6
+ export declare class SkillSyncPlanner {
7
+ planRequestedTargets(requestedTargetCli: readonly SkillTargetCli[], existingBindings?: readonly SkillTargetBindingRecord[]): PlannedSkillSyncTarget[];
8
+ }
@@ -0,0 +1,20 @@
1
+ import { AppError } from "../../shared/errors/app-error.js";
2
+ export class SkillSyncPlanner {
3
+ planRequestedTargets(requestedTargetCli, existingBindings = []) {
4
+ const normalizedTargetCli = Array.from(new Set(requestedTargetCli));
5
+ if (normalizedTargetCli.length === 0) {
6
+ throw new AppError({
7
+ statusCode: 400,
8
+ errorCode: "INVALID_INPUT",
9
+ detail: "至少要指定一个目标 CLI",
10
+ field: "targetCli"
11
+ });
12
+ }
13
+ const bindingByTarget = new Map(existingBindings.map((binding) => [binding.targetCli, binding]));
14
+ return normalizedTargetCli.map((targetCli) => ({
15
+ targetCli,
16
+ existingBinding: bindingByTarget.get(targetCli) ?? null
17
+ }));
18
+ }
19
+ }
20
+ //# sourceMappingURL=skill-sync-planner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-sync-planner.js","sourceRoot":"","sources":["../../../../src/modules/skills/skill-sync-planner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAQ5D,MAAM,OAAO,gBAAgB;IAC3B,oBAAoB,CAClB,kBAA6C,EAC7C,mBAAwD,EAAE;QAE1D,MAAM,mBAAmB,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAEpE,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,QAAQ,CAAC;gBACjB,UAAU,EAAE,GAAG;gBACf,SAAS,EAAE,eAAe;gBAC1B,MAAM,EAAE,eAAe;gBACvB,KAAK,EAAE,WAAW;aACnB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,eAAe,GAAG,IAAI,GAAG,CAC7B,gBAAgB,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAU,CAAC,CACzE,CAAC;QAEF,OAAO,mBAAmB,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YAC7C,SAAS;YACT,eAAe,EAAE,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI;SACxD,CAAC,CAAC,CAAC;IACN,CAAC;CACF"}
@@ -0,0 +1,34 @@
1
+ import type { HostConfig } from "../../config/env.js";
2
+ import type { SkillTargetCli } from "../../types/domain.js";
3
+ export interface SkillTargetLocation {
4
+ targetCli: SkillTargetCli;
5
+ rootDir: string;
6
+ }
7
+ export interface SkillTargetAdapter {
8
+ readonly targetCli: SkillTargetCli;
9
+ resolveRootDir(): string;
10
+ }
11
+ export declare class ClaudeCodeSkillTargetAdapter implements SkillTargetAdapter {
12
+ private readonly config;
13
+ readonly targetCli: "claude-code";
14
+ constructor(config: Pick<HostConfig, "claudeCodeHomeDir">);
15
+ resolveRootDir(): string;
16
+ }
17
+ export declare class CodexSkillTargetAdapter implements SkillTargetAdapter {
18
+ private readonly config;
19
+ readonly targetCli: "codex";
20
+ constructor(config: Pick<HostConfig, "codexHomeDir">);
21
+ resolveRootDir(): string;
22
+ }
23
+ export declare class GeminiSkillTargetAdapter implements SkillTargetAdapter {
24
+ private readonly config;
25
+ readonly targetCli: "gemini";
26
+ constructor(config: Pick<HostConfig, "geminiHomeDir">);
27
+ resolveRootDir(): string;
28
+ }
29
+ export declare class OpenCodeSkillTargetAdapter implements SkillTargetAdapter {
30
+ readonly targetCli: "opencode";
31
+ resolveRootDir(): string;
32
+ }
33
+ export declare function createDefaultSkillTargetAdapters(config: Pick<HostConfig, "claudeCodeHomeDir" | "codexHomeDir" | "geminiHomeDir">): SkillTargetAdapter[];
34
+ export declare function resolveSkillTargetLocation(adapters: readonly SkillTargetAdapter[], targetCli: SkillTargetCli): SkillTargetLocation;
@@ -0,0 +1,65 @@
1
+ import os from "node:os";
2
+ import path from "node:path";
3
+ export class ClaudeCodeSkillTargetAdapter {
4
+ config;
5
+ targetCli = "claude-code";
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ resolveRootDir() {
10
+ return path.resolve(this.config.claudeCodeHomeDir, "skills");
11
+ }
12
+ }
13
+ export class CodexSkillTargetAdapter {
14
+ config;
15
+ targetCli = "codex";
16
+ constructor(config) {
17
+ this.config = config;
18
+ }
19
+ resolveRootDir() {
20
+ return path.resolve(this.config.codexHomeDir, "skills");
21
+ }
22
+ }
23
+ export class GeminiSkillTargetAdapter {
24
+ config;
25
+ targetCli = "gemini";
26
+ constructor(config) {
27
+ this.config = config;
28
+ }
29
+ resolveRootDir() {
30
+ return path.resolve(this.config.geminiHomeDir, "skills");
31
+ }
32
+ }
33
+ export class OpenCodeSkillTargetAdapter {
34
+ targetCli = "opencode";
35
+ resolveRootDir() {
36
+ return resolveDefaultOpenCodeSkillsDir();
37
+ }
38
+ }
39
+ export function createDefaultSkillTargetAdapters(config) {
40
+ return [
41
+ new ClaudeCodeSkillTargetAdapter(config),
42
+ new CodexSkillTargetAdapter(config),
43
+ new GeminiSkillTargetAdapter(config),
44
+ new OpenCodeSkillTargetAdapter()
45
+ ];
46
+ }
47
+ export function resolveSkillTargetLocation(adapters, targetCli) {
48
+ const adapter = adapters.find((candidate) => candidate.targetCli === targetCli);
49
+ if (!adapter) {
50
+ throw new Error("SKILL_TARGET_NOT_SUPPORTED");
51
+ }
52
+ return {
53
+ targetCli,
54
+ rootDir: adapter.resolveRootDir()
55
+ };
56
+ }
57
+ function resolveDefaultOpenCodeSkillsDir() {
58
+ const homeDir = os.homedir();
59
+ if (process.platform === "win32") {
60
+ const appDataDir = process.env.APPDATA?.trim();
61
+ return path.resolve(appDataDir || path.join(homeDir, "AppData", "Roaming"), "opencode", "skills");
62
+ }
63
+ return path.resolve(homeDir, ".config", "opencode", "skills");
64
+ }
65
+ //# sourceMappingURL=skill-target-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-target-adapter.js","sourceRoot":"","sources":["../../../../src/modules/skills/skill-target-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,OAAO,4BAA4B;IAGV;IAFpB,SAAS,GAAG,aAAsB,CAAC;IAE5C,YAA6B,MAA6C;QAA7C,WAAM,GAAN,MAAM,CAAuC;IAAG,CAAC;IAE9E,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,iBAAiB,EAAE,QAAQ,CAAC,CAAC;IAC/D,CAAC;CACF;AAED,MAAM,OAAO,uBAAuB;IAGL;IAFpB,SAAS,GAAG,OAAgB,CAAC;IAEtC,YAA6B,MAAwC;QAAxC,WAAM,GAAN,MAAM,CAAkC;IAAG,CAAC;IAEzE,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC1D,CAAC;CACF;AAED,MAAM,OAAO,wBAAwB;IAGN;IAFpB,SAAS,GAAG,QAAiB,CAAC;IAEvC,YAA6B,MAAyC;QAAzC,WAAM,GAAN,MAAM,CAAmC;IAAG,CAAC;IAE1E,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;IAC3D,CAAC;CACF;AAED,MAAM,OAAO,0BAA0B;IAC5B,SAAS,GAAG,UAAmB,CAAC;IAEzC,cAAc;QACZ,OAAO,+BAA+B,EAAE,CAAC;IAC3C,CAAC;CACF;AAED,MAAM,UAAU,gCAAgC,CAC9C,MAAgF;IAEhF,OAAO;QACL,IAAI,4BAA4B,CAAC,MAAM,CAAC;QACxC,IAAI,uBAAuB,CAAC,MAAM,CAAC;QACnC,IAAI,wBAAwB,CAAC,MAAM,CAAC;QACpC,IAAI,0BAA0B,EAAE;KACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,0BAA0B,CACxC,QAAuC,EACvC,SAAyB;IAEzB,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IAEhF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,OAAO;QACL,SAAS;QACT,OAAO,EAAE,OAAO,CAAC,cAAc,EAAE;KAClC,CAAC;AACJ,CAAC;AAED,SAAS,+BAA+B;IACtC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAE7B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QAE/C,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IACpG,CAAC;IAED,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { FastifyReply, FastifyRequest } from "fastify";
2
+ import type { TailscaleConfigUpdateInput } from "./tailscale-service.js";
3
+ import { TailscaleService } from "./tailscale-service.js";
4
+ export declare class TailscaleController {
5
+ private readonly tailscaleService;
6
+ constructor(tailscaleService: TailscaleService);
7
+ readonly getStatus: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
8
+ readonly updateConfig: (request: FastifyRequest<{
9
+ Body: TailscaleConfigUpdateInput;
10
+ }>, reply: FastifyReply) => Promise<void>;
11
+ readonly enable: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
12
+ readonly disable: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
13
+ readonly login: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
14
+ readonly logout: (request: FastifyRequest, reply: FastifyReply) => Promise<void>;
15
+ }
@@ -0,0 +1,33 @@
1
+ import { requireUserId } from "../preferences/common.js";
2
+ export class TailscaleController {
3
+ tailscaleService;
4
+ constructor(tailscaleService) {
5
+ this.tailscaleService = tailscaleService;
6
+ }
7
+ getStatus = async (request, reply) => {
8
+ // 这里显式要求登录态,避免未来系统路由被复用时绕过受保护边界。
9
+ requireUserId(request);
10
+ reply.send(await this.tailscaleService.getStatus());
11
+ };
12
+ updateConfig = async (request, reply) => {
13
+ requireUserId(request);
14
+ reply.send(await this.tailscaleService.updateConfig(request.body ?? {}));
15
+ };
16
+ enable = async (request, reply) => {
17
+ requireUserId(request);
18
+ reply.send(await this.tailscaleService.enable());
19
+ };
20
+ disable = async (request, reply) => {
21
+ requireUserId(request);
22
+ reply.send(await this.tailscaleService.disable());
23
+ };
24
+ login = async (request, reply) => {
25
+ requireUserId(request);
26
+ reply.send(await this.tailscaleService.login());
27
+ };
28
+ logout = async (request, reply) => {
29
+ requireUserId(request);
30
+ reply.send(await this.tailscaleService.logout());
31
+ };
32
+ }
33
+ //# sourceMappingURL=tailscale-controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tailscale-controller.js","sourceRoot":"","sources":["../../../../src/modules/tailscale/tailscale-controller.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAIzD,MAAM,OAAO,mBAAmB;IACD;IAA7B,YAA6B,gBAAkC;QAAlC,qBAAgB,GAAhB,gBAAgB,CAAkB;IAAG,CAAC;IAE1D,SAAS,GAAG,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAiB,EAAE;QACzF,iCAAiC;QACjC,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC;IAEO,YAAY,GAAG,KAAK,EAC3B,OAA6D,EAC7D,KAAmB,EACJ,EAAE;QACjB,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC;IAEO,MAAM,GAAG,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAiB,EAAE;QACtF,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC;IAEO,OAAO,GAAG,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAiB,EAAE;QACvF,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAC;IACpD,CAAC,CAAC;IAEO,KAAK,GAAG,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAiB,EAAE;QACrF,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC;IAEO,MAAM,GAAG,KAAK,EAAE,OAAuB,EAAE,KAAmB,EAAiB,EAAE;QACtF,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC;CACH"}
@@ -0,0 +1,41 @@
1
+ export type TailscaleHelperBackendState = "running" | "needs_login" | "starting" | "stopped" | "error";
2
+ export interface TailscaleHelperSnapshot {
3
+ backendState: TailscaleHelperBackendState;
4
+ loginUrl: string | null;
5
+ hostname: string | null;
6
+ accountName: string | null;
7
+ tailnetFqdn: string | null;
8
+ tailnetIpv4: string | null;
9
+ tailnetIpv6: string | null;
10
+ lastError: string | null;
11
+ }
12
+ export declare class TailscaleHelperClient {
13
+ private readonly child;
14
+ private readonly stdoutReader;
15
+ private readonly pendingRequests;
16
+ private nextRequestId;
17
+ constructor();
18
+ inspectStatus(input: {
19
+ commandPath: string;
20
+ }): Promise<TailscaleHelperSnapshot>;
21
+ enable(input: {
22
+ commandPath: string;
23
+ controlServerUrl: string | null;
24
+ hostname: string | null;
25
+ }): Promise<TailscaleHelperSnapshot>;
26
+ login(input: {
27
+ commandPath: string;
28
+ controlServerUrl: string | null;
29
+ hostname: string | null;
30
+ }): Promise<TailscaleHelperSnapshot>;
31
+ disable(input: {
32
+ commandPath: string;
33
+ }): Promise<TailscaleHelperSnapshot>;
34
+ logout(input: {
35
+ commandPath: string;
36
+ }): Promise<TailscaleHelperSnapshot>;
37
+ dispose(): void;
38
+ private sendRequest;
39
+ private handleResponseLine;
40
+ private rejectAll;
41
+ }
@@ -0,0 +1,135 @@
1
+ import { spawn } from "node:child_process";
2
+ import path from "node:path";
3
+ import readline from "node:readline";
4
+ import { fileURLToPath } from "node:url";
5
+ export class TailscaleHelperClient {
6
+ child;
7
+ stdoutReader;
8
+ pendingRequests = new Map();
9
+ nextRequestId = 1;
10
+ constructor() {
11
+ const launch = resolveHelperLaunch();
12
+ this.child = spawn(launch.command, launch.args, {
13
+ cwd: process.cwd(),
14
+ env: process.env,
15
+ stdio: ["pipe", "pipe", "pipe"]
16
+ });
17
+ this.stdoutReader = readline.createInterface({
18
+ input: this.child.stdout
19
+ });
20
+ this.stdoutReader.on("line", (line) => {
21
+ this.handleResponseLine(line);
22
+ });
23
+ this.child.stderr.on("data", (chunk) => {
24
+ const content = String(chunk).trim();
25
+ if (content) {
26
+ console.warn(`[tailscale-helper] ${content}`);
27
+ }
28
+ });
29
+ this.child.on("error", (error) => {
30
+ this.rejectAll(error);
31
+ });
32
+ this.child.on("exit", (code, signal) => {
33
+ this.rejectAll(new Error(`tailscale helper 已退出:code=${code ?? "null"} signal=${signal ?? "null"}`));
34
+ });
35
+ }
36
+ async inspectStatus(input) {
37
+ return await this.sendRequest({
38
+ type: "status",
39
+ ...input
40
+ });
41
+ }
42
+ async enable(input) {
43
+ return await this.sendRequest({
44
+ type: "enable",
45
+ ...input
46
+ });
47
+ }
48
+ async login(input) {
49
+ return await this.sendRequest({
50
+ type: "login",
51
+ ...input
52
+ });
53
+ }
54
+ async disable(input) {
55
+ return await this.sendRequest({
56
+ type: "disable",
57
+ ...input
58
+ });
59
+ }
60
+ async logout(input) {
61
+ return await this.sendRequest({
62
+ type: "logout",
63
+ ...input
64
+ });
65
+ }
66
+ dispose() {
67
+ this.stdoutReader.close();
68
+ if (!this.child.killed) {
69
+ this.child.kill("SIGTERM");
70
+ }
71
+ }
72
+ async sendRequest(payload) {
73
+ const id = String(this.nextRequestId++);
74
+ return await new Promise((resolve, reject) => {
75
+ this.pendingRequests.set(id, {
76
+ resolve: (value) => {
77
+ resolve(value);
78
+ },
79
+ reject
80
+ });
81
+ this.child.stdin.write(`${JSON.stringify({ id, ...payload })}\n`, (error) => {
82
+ if (!error) {
83
+ return;
84
+ }
85
+ this.pendingRequests.delete(id);
86
+ reject(error);
87
+ });
88
+ });
89
+ }
90
+ handleResponseLine(line) {
91
+ const trimmed = line.trim();
92
+ if (!trimmed.startsWith("{")) {
93
+ return;
94
+ }
95
+ let payload;
96
+ try {
97
+ payload = JSON.parse(trimmed);
98
+ }
99
+ catch {
100
+ return;
101
+ }
102
+ const pending = this.pendingRequests.get(payload.id);
103
+ if (!pending) {
104
+ return;
105
+ }
106
+ this.pendingRequests.delete(payload.id);
107
+ if (payload.ok) {
108
+ pending.resolve(payload.result);
109
+ return;
110
+ }
111
+ pending.reject(new Error(payload.error));
112
+ }
113
+ rejectAll(error) {
114
+ for (const pending of this.pendingRequests.values()) {
115
+ pending.reject(error);
116
+ }
117
+ this.pendingRequests.clear();
118
+ }
119
+ }
120
+ function resolveHelperLaunch() {
121
+ const currentFilePath = fileURLToPath(import.meta.url);
122
+ const extension = path.extname(currentFilePath);
123
+ const helperPath = currentFilePath.replace(/tailscale-helper-client\.(ts|js)$/, `tailscale-helper-process${extension}`);
124
+ if (extension === ".ts") {
125
+ return {
126
+ command: process.execPath,
127
+ args: ["--import", "tsx", helperPath]
128
+ };
129
+ }
130
+ return {
131
+ command: process.execPath,
132
+ args: [helperPath]
133
+ };
134
+ }
135
+ //# sourceMappingURL=tailscale-helper-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tailscale-helper-client.js","sourceRoot":"","sources":["../../../../src/modules/tailscale/tailscale-helper-client.ts"],"names":[],"mappings":"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"}