@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,43 @@
1
+ import type Database from "better-sqlite3";
2
+ import type { InstanceTailscaleRepository } from "../../storage/repositories/instance-tailscale-repository.js";
3
+ import type { TailscalePhase } from "../../types/domain.js";
4
+ import type { TailscaleManager } from "./tailscale-manager.js";
5
+ export interface TailscaleConfigUpdateInput {
6
+ controlServerUrl?: string | null;
7
+ hostname?: string | null;
8
+ }
9
+ export interface InstanceTailscaleStatusDto {
10
+ enabled: boolean;
11
+ controlServerUrl: string | null;
12
+ hostname: string | null;
13
+ phase: TailscalePhase;
14
+ connected: boolean;
15
+ loginUrl: string | null;
16
+ accountName: string | null;
17
+ tailnetFqdn: string | null;
18
+ tailnetIpv4: string | null;
19
+ tailnetIpv6: string | null;
20
+ reachableBaseUrl: string | null;
21
+ lastError: string | null;
22
+ observedAt: string | null;
23
+ updatedAt: string | null;
24
+ }
25
+ export declare class TailscaleService {
26
+ private readonly db;
27
+ private readonly repository;
28
+ private readonly manager;
29
+ private readonly defaultStateDir;
30
+ constructor(db: Database.Database, repository: InstanceTailscaleRepository, manager: TailscaleManager, options: {
31
+ defaultStateDir?: string;
32
+ databasePath: string;
33
+ });
34
+ restoreOnStartup(): Promise<void>;
35
+ getStatus(): Promise<InstanceTailscaleStatusDto>;
36
+ updateConfig(input: TailscaleConfigUpdateInput): Promise<InstanceTailscaleStatusDto>;
37
+ enable(): Promise<InstanceTailscaleStatusDto>;
38
+ disable(): Promise<InstanceTailscaleStatusDto>;
39
+ login(): Promise<InstanceTailscaleStatusDto>;
40
+ logout(): Promise<InstanceTailscaleStatusDto>;
41
+ private readStateSnapshot;
42
+ private buildStatusDto;
43
+ }
@@ -0,0 +1,201 @@
1
+ import path from "node:path";
2
+ import { AppError } from "../../shared/errors/app-error.js";
3
+ import { nowIso } from "../../shared/utils/time.js";
4
+ export class TailscaleService {
5
+ db;
6
+ repository;
7
+ manager;
8
+ defaultStateDir;
9
+ constructor(db, repository, manager, options) {
10
+ this.db = db;
11
+ this.repository = repository;
12
+ this.manager = manager;
13
+ this.defaultStateDir = options.defaultStateDir
14
+ ?? path.join(path.dirname(options.databasePath), "tailscale-state");
15
+ }
16
+ async restoreOnStartup() {
17
+ const snapshot = this.readStateSnapshot();
18
+ if (!snapshot.hasPersistedConfig) {
19
+ return;
20
+ }
21
+ if (!snapshot.config.enabled) {
22
+ this.manager.getStatusSync(snapshot.config);
23
+ return;
24
+ }
25
+ await this.manager.restore(snapshot.config);
26
+ }
27
+ async getStatus() {
28
+ const snapshot = this.readStateSnapshot();
29
+ return this.buildStatusDto(snapshot, await this.manager.getStatus(snapshot.config));
30
+ }
31
+ async updateConfig(input) {
32
+ const snapshot = this.readStateSnapshot();
33
+ const timestamp = nowIso();
34
+ const nextConfig = {
35
+ ...snapshot.config,
36
+ controlServerUrl: input.controlServerUrl !== undefined
37
+ ? normalizeControlServerUrl(input.controlServerUrl)
38
+ : snapshot.config.controlServerUrl,
39
+ hostname: input.hostname !== undefined
40
+ ? normalizeHostname(input.hostname)
41
+ : snapshot.config.hostname,
42
+ updatedAt: timestamp
43
+ };
44
+ const transaction = this.db.transaction(() => {
45
+ this.repository.upsertConfig(nextConfig);
46
+ if (nextConfig.enabled) {
47
+ // 这里只同步状态镜像,不主动发起新的登录动作。
48
+ }
49
+ });
50
+ transaction();
51
+ if (nextConfig.enabled) {
52
+ await this.manager.syncConfig(nextConfig);
53
+ }
54
+ return await this.getStatus();
55
+ }
56
+ async enable() {
57
+ const snapshot = this.readStateSnapshot();
58
+ const timestamp = nowIso();
59
+ const nextConfig = {
60
+ ...snapshot.config,
61
+ enabled: true,
62
+ updatedAt: timestamp
63
+ };
64
+ this.repository.upsertConfig(nextConfig);
65
+ const status = await this.manager.enable(nextConfig);
66
+ return this.buildStatusDto({
67
+ config: nextConfig,
68
+ hasPersistedConfig: true
69
+ }, status);
70
+ }
71
+ async disable() {
72
+ const snapshot = this.readStateSnapshot();
73
+ const timestamp = nowIso();
74
+ const nextConfig = {
75
+ ...snapshot.config,
76
+ enabled: false,
77
+ updatedAt: timestamp
78
+ };
79
+ this.repository.upsertConfig(nextConfig);
80
+ const status = await this.manager.disable(nextConfig);
81
+ return this.buildStatusDto({
82
+ config: nextConfig,
83
+ hasPersistedConfig: true
84
+ }, status);
85
+ }
86
+ async login() {
87
+ const snapshot = this.readStateSnapshot();
88
+ if (!snapshot.config.enabled) {
89
+ throw new AppError({
90
+ statusCode: 409,
91
+ errorCode: "TAILSCALE_NOT_ENABLED",
92
+ detail: "当前实例尚未启用 Tailscale"
93
+ });
94
+ }
95
+ const status = await this.manager.requestLogin(snapshot.config);
96
+ return this.buildStatusDto(snapshot, status);
97
+ }
98
+ async logout() {
99
+ const snapshot = this.readStateSnapshot();
100
+ const status = await this.manager.logout(snapshot.config);
101
+ return this.buildStatusDto(snapshot, status);
102
+ }
103
+ readStateSnapshot() {
104
+ const persistedConfig = this.repository.findConfig();
105
+ return {
106
+ config: persistedConfig
107
+ ?? {
108
+ enabled: false,
109
+ controlServerUrl: null,
110
+ hostname: null,
111
+ stateDir: this.defaultStateDir,
112
+ updatedAt: nowIso()
113
+ },
114
+ hasPersistedConfig: persistedConfig !== null
115
+ };
116
+ }
117
+ buildStatusDto(snapshot, effectiveStatus) {
118
+ return {
119
+ enabled: snapshot.config.enabled,
120
+ controlServerUrl: snapshot.config.controlServerUrl,
121
+ hostname: snapshot.config.hostname,
122
+ phase: effectiveStatus.phase,
123
+ connected: effectiveStatus.connected,
124
+ loginUrl: effectiveStatus.loginUrl,
125
+ accountName: effectiveStatus.accountName,
126
+ tailnetFqdn: effectiveStatus.tailnetFqdn,
127
+ tailnetIpv4: effectiveStatus.tailnetIpv4,
128
+ tailnetIpv6: effectiveStatus.tailnetIpv6,
129
+ reachableBaseUrl: effectiveStatus.reachableBaseUrl,
130
+ lastError: effectiveStatus.lastError,
131
+ observedAt: effectiveStatus.observedAt,
132
+ updatedAt: snapshot.hasPersistedConfig ? snapshot.config.updatedAt : null
133
+ };
134
+ }
135
+ }
136
+ function normalizeControlServerUrl(value) {
137
+ if (value === null) {
138
+ return null;
139
+ }
140
+ const normalized = value.trim();
141
+ if (normalized.length === 0) {
142
+ return null;
143
+ }
144
+ let parsed;
145
+ try {
146
+ parsed = new URL(normalized);
147
+ }
148
+ catch {
149
+ throw new AppError({
150
+ statusCode: 400,
151
+ errorCode: "INVALID_INPUT",
152
+ detail: "controlServerUrl 必须是合法的 http 或 https 地址",
153
+ field: "controlServerUrl"
154
+ });
155
+ }
156
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
157
+ throw new AppError({
158
+ statusCode: 400,
159
+ errorCode: "INVALID_INPUT",
160
+ detail: "controlServerUrl 只允许使用 http 或 https 协议",
161
+ field: "controlServerUrl"
162
+ });
163
+ }
164
+ if (parsed.username || parsed.password || parsed.search || parsed.hash) {
165
+ throw new AppError({
166
+ statusCode: 400,
167
+ errorCode: "INVALID_INPUT",
168
+ detail: "controlServerUrl 不能包含账号、查询参数或 hash",
169
+ field: "controlServerUrl"
170
+ });
171
+ }
172
+ const pathname = parsed.pathname === "/" ? "" : parsed.pathname.replace(/\/+$/, "");
173
+ return `${parsed.protocol}//${parsed.host}${pathname}`;
174
+ }
175
+ function normalizeHostname(value) {
176
+ if (value === null) {
177
+ return null;
178
+ }
179
+ const normalized = value.trim();
180
+ if (normalized.length === 0) {
181
+ return null;
182
+ }
183
+ if (normalized.length > 63) {
184
+ throw new AppError({
185
+ statusCode: 400,
186
+ errorCode: "INVALID_INPUT",
187
+ detail: "hostname 最长不能超过 63 个字符",
188
+ field: "hostname"
189
+ });
190
+ }
191
+ if (!/^[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?$/.test(normalized)) {
192
+ throw new AppError({
193
+ statusCode: 400,
194
+ errorCode: "INVALID_INPUT",
195
+ detail: "hostname 只允许字母、数字和连字符,且不能以连字符开头或结尾",
196
+ field: "hostname"
197
+ });
198
+ }
199
+ return normalized;
200
+ }
201
+ //# sourceMappingURL=tailscale-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tailscale-service.js","sourceRoot":"","sources":["../../../../src/modules/tailscale/tailscale-service.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export async function registerGitRoutes(app, gitController) {
2
2
  app.get("/api/git/status", gitController.getStatus);
3
3
  app.get("/api/git/diff", gitController.getDiff);
4
+ app.get("/api/git/commit-detail", gitController.getCommitDetail);
4
5
  app.post("/api/git/stage", gitController.stage);
5
6
  app.post("/api/git/unstage", gitController.unstage);
6
7
  app.post("/api/git/discard", gitController.discard);
@@ -1 +1 @@
1
- {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/routes/git.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAoB,EACpB,aAA4B;IAE5B,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACpD,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACpD,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACpD,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAClD,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACnD,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACnE,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACnE,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClD,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC/D,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACtD,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACxD,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjE,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACtD,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;AAC7D,CAAC"}
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../../src/routes/git.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,GAAoB,EACpB,aAA4B;IAE5B,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACpD,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAChD,GAAG,CAAC,GAAG,CAAC,wBAAwB,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACjE,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACpD,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IACpD,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;IAClD,GAAG,CAAC,GAAG,CAAC,gBAAgB,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACnD,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,aAAa,CAAC,iBAAiB,CAAC,CAAC;IACnE,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IACnE,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClD,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC/D,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACtD,GAAG,CAAC,GAAG,CAAC,mBAAmB,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC;IACxD,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;IAChD,GAAG,CAAC,IAAI,CAAC,0BAA0B,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACjE,GAAG,CAAC,GAAG,CAAC,kBAAkB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACtD,GAAG,CAAC,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FastifyInstance } from "fastify";
2
+ import type { SkillController } from "../modules/skills/skill-controller.js";
3
+ export declare function registerSkillRoutes(app: FastifyInstance, skillController: SkillController): Promise<void>;
@@ -0,0 +1,7 @@
1
+ export async function registerSkillRoutes(app, skillController) {
2
+ app.get("/api/skills/overview", skillController.getOverview);
3
+ app.post("/api/skills", skillController.add);
4
+ app.post("/api/skills/import", skillController.import);
5
+ app.post("/api/skills/sync", skillController.sync);
6
+ }
7
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../../src/routes/skills.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,GAAoB,EACpB,eAAgC;IAEhC,GAAG,CAAC,GAAG,CAAC,sBAAsB,EAAE,eAAe,CAAC,WAAW,CAAC,CAAC;IAC7D,GAAG,CAAC,IAAI,CAAC,aAAa,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC;IAC7C,GAAG,CAAC,IAAI,CAAC,oBAAoB,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IACvD,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE,eAAe,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FastifyInstance } from "fastify";
2
+ import type { TailscaleController } from "../modules/tailscale/tailscale-controller.js";
3
+ export declare function registerSystemRoutes(app: FastifyInstance, tailscaleController: TailscaleController): Promise<void>;
@@ -0,0 +1,9 @@
1
+ export async function registerSystemRoutes(app, tailscaleController) {
2
+ app.get("/api/system/tailscale/status", tailscaleController.getStatus);
3
+ app.put("/api/system/tailscale/config", tailscaleController.updateConfig);
4
+ app.post("/api/system/tailscale/enable", tailscaleController.enable);
5
+ app.post("/api/system/tailscale/disable", tailscaleController.disable);
6
+ app.post("/api/system/tailscale/login", tailscaleController.login);
7
+ app.post("/api/system/tailscale/logout", tailscaleController.logout);
8
+ }
9
+ //# sourceMappingURL=system.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"system.js","sourceRoot":"","sources":["../../../src/routes/system.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,GAAoB,EACpB,mBAAwC;IAExC,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,mBAAmB,CAAC,SAAS,CAAC,CAAC;IACvE,GAAG,CAAC,GAAG,CAAC,8BAA8B,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;IAC1E,GAAG,CAAC,IAAI,CAAC,8BAA8B,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IACrE,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACvE,GAAG,CAAC,IAAI,CAAC,6BAA6B,EAAE,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACnE,GAAG,CAAC,IAAI,CAAC,8BAA8B,EAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC;AACvE,CAAC"}
@@ -32,6 +32,9 @@ import { GitReadService } from "../modules/git/git-read-service.js";
32
32
  import { GitWriteService } from "../modules/git/git-write-service.js";
33
33
  import { PreferenceProfileService } from "../modules/preferences/profile-service.js";
34
34
  import { QuickPhraseService } from "../modules/preferences/quick-phrase-service.js";
35
+ import { SkillManagerService } from "../modules/skills/skill-manager-service.js";
36
+ import { TailscaleManager } from "../modules/tailscale/tailscale-manager.js";
37
+ import { TailscaleService } from "../modules/tailscale/tailscale-service.js";
35
38
  import { SessionChangedFileService } from "../modules/sessions/session-changed-file-service.js";
36
39
  import { SessionHistoryService } from "../modules/sessions/session-history-service.js";
37
40
  import { SessionLiveRuntimeService } from "../modules/sessions/session-live-runtime-service.js";
@@ -70,6 +73,7 @@ import { DebugTargetRepository } from "../storage/repositories/debug-target-repo
70
73
  import { FileContextBindingRepository } from "../storage/repositories/file-context-binding-repository.js";
71
74
  import { FrameworkAnalysisResultRepository } from "../storage/repositories/framework-analysis-result-repository.js";
72
75
  import { GitRemoteCredentialRepository } from "../storage/repositories/git-remote-credential-repository.js";
76
+ import { ManagedSkillRepository } from "../storage/repositories/managed-skill-repository.js";
73
77
  import { PortLeaseRepository } from "../storage/repositories/port-lease-repository.js";
74
78
  import { RecentFileRepository } from "../storage/repositories/recent-file-repository.js";
75
79
  import { RuntimeBindingRepository } from "../storage/repositories/runtime-binding-repository.js";
@@ -83,6 +87,8 @@ import { SessionMessageOriginRepository } from "../storage/repositories/session-
83
87
  import { SessionSendQueueRepository } from "../storage/repositories/session-send-queue-repository.js";
84
88
  import { SessionStateRepository } from "../storage/repositories/session-state-repository.js";
85
89
  import { SessionStatusSnapshotRepository } from "../storage/repositories/session-status-snapshot-repository.js";
90
+ import { InstanceTailscaleRepository } from "../storage/repositories/instance-tailscale-repository.js";
91
+ import { SkillTargetBindingRepository } from "../storage/repositories/skill-target-binding-repository.js";
86
92
  import { TerminalCommandTemplateRepository } from "../storage/repositories/terminal-command-template-repository.js";
87
93
  import { TerminalInstanceRepository } from "../storage/repositories/terminal-instance-repository.js";
88
94
  import { TerminalLogFileRepository } from "../storage/repositories/terminal-log-file-repository.js";
@@ -129,6 +135,7 @@ export declare function createServer(config: HostConfig): {
129
135
  verificationRunRepository: VerificationRunRepository;
130
136
  commitRuleProfileRepository: CommitRuleProfileRepository;
131
137
  gitRemoteCredentialRepository: GitRemoteCredentialRepository;
138
+ managedSkillRepository: ManagedSkillRepository;
132
139
  recentFileRepository: RecentFileRepository;
133
140
  fileContextBindingRepository: FileContextBindingRepository;
134
141
  sessionBindingRepository: SessionBindingRepository;
@@ -141,6 +148,8 @@ export declare function createServer(config: HostConfig): {
141
148
  sessionSendQueueRepository: SessionSendQueueRepository;
142
149
  sessionStateRepository: SessionStateRepository;
143
150
  sessionStatusSnapshotRepository: SessionStatusSnapshotRepository;
151
+ instanceTailscaleRepository: InstanceTailscaleRepository;
152
+ skillTargetBindingRepository: SkillTargetBindingRepository;
144
153
  userQuickPhrasePreferenceRepository: UserQuickPhrasePreferenceRepository;
145
154
  userPreferenceProfileRepository: UserPreferenceProfileRepository;
146
155
  terminalInstanceRepository: TerminalInstanceRepository;
@@ -190,6 +199,9 @@ export declare function createServer(config: HostConfig): {
190
199
  commitOrchestrator: CommitOrchestrator;
191
200
  quickPhraseService: QuickPhraseService;
192
201
  preferenceProfileService: PreferenceProfileService;
202
+ skillManagerService: SkillManagerService;
203
+ tailscaleManager: TailscaleManager;
204
+ tailscaleService: TailscaleService;
193
205
  runtimeObservabilityService: RuntimeObservabilityService;
194
206
  sessionHistoryService: SessionHistoryService;
195
207
  sessionChangedFileService: SessionChangedFileService;
@@ -63,6 +63,13 @@ import { PreferenceProfileService } from "../modules/preferences/profile-service
63
63
  import { QuickPhraseController } from "../modules/preferences/quick-phrase-controller.js";
64
64
  import { QuickPhraseService } from "../modules/preferences/quick-phrase-service.js";
65
65
  import { ProviderController } from "../modules/provider/provider-controller.js";
66
+ import { SkillController } from "../modules/skills/skill-controller.js";
67
+ import { SkillManagerService } from "../modules/skills/skill-manager-service.js";
68
+ import { createDefaultSkillTargetAdapters } from "../modules/skills/skill-target-adapter.js";
69
+ import { TailscaleManager } from "../modules/tailscale/tailscale-manager.js";
70
+ import { TailscaleController } from "../modules/tailscale/tailscale-controller.js";
71
+ import { TailscaleHelperClient } from "../modules/tailscale/tailscale-helper-client.js";
72
+ import { TailscaleService } from "../modules/tailscale/tailscale-service.js";
66
73
  import { SessionController } from "../modules/sessions/session-controller.js";
67
74
  import { SessionChangedFileService } from "../modules/sessions/session-changed-file-service.js";
68
75
  import { SessionActivityAuthorityService } from "../modules/sessions/session-activity-authority-service.js";
@@ -105,10 +112,12 @@ import { registerPublicRoutes } from "../routes/public.js";
105
112
  import { registerProxyRoutes } from "../routes/proxy.js";
106
113
  import { registerSessionContextRoutes } from "../routes/session-contexts.js";
107
114
  import { registerSessionRoutes } from "../routes/sessions.js";
115
+ import { registerSkillRoutes } from "../routes/skills.js";
108
116
  import { registerTerminalRoutes } from "../routes/terminals.js";
109
117
  import { registerWorkbenchRoutes } from "../routes/workbench.js";
110
118
  import { registerWorktreeRoutes } from "../routes/worktrees.js";
111
119
  import { registerWorkspaceRoutes } from "../routes/workspaces.js";
120
+ import { registerSystemRoutes } from "../routes/system.js";
112
121
  import { DemoCleanupService, DemoOnlineTracker } from "../modules/demo/demo-cleanup-service.js";
113
122
  import { setErrorHandler } from "../shared/http/error-handler.js";
114
123
  import { startTerminalDebugEventLoopLagMonitor } from "../shared/utils/terminal-debug-log.js";
@@ -136,6 +145,7 @@ import { DebugTargetRepository } from "../storage/repositories/debug-target-repo
136
145
  import { FileContextBindingRepository } from "../storage/repositories/file-context-binding-repository.js";
137
146
  import { FrameworkAnalysisResultRepository } from "../storage/repositories/framework-analysis-result-repository.js";
138
147
  import { GitRemoteCredentialRepository } from "../storage/repositories/git-remote-credential-repository.js";
148
+ import { ManagedSkillRepository } from "../storage/repositories/managed-skill-repository.js";
139
149
  import { PortLeaseRepository } from "../storage/repositories/port-lease-repository.js";
140
150
  import { RecentFileRepository } from "../storage/repositories/recent-file-repository.js";
141
151
  import { RuntimeBindingRepository } from "../storage/repositories/runtime-binding-repository.js";
@@ -149,6 +159,8 @@ import { SessionMessageOriginRepository } from "../storage/repositories/session-
149
159
  import { SessionSendQueueRepository } from "../storage/repositories/session-send-queue-repository.js";
150
160
  import { SessionStateRepository } from "../storage/repositories/session-state-repository.js";
151
161
  import { SessionStatusSnapshotRepository } from "../storage/repositories/session-status-snapshot-repository.js";
162
+ import { InstanceTailscaleRepository } from "../storage/repositories/instance-tailscale-repository.js";
163
+ import { SkillTargetBindingRepository } from "../storage/repositories/skill-target-binding-repository.js";
152
164
  import { TerminalCommandTemplateRepository } from "../storage/repositories/terminal-command-template-repository.js";
153
165
  import { TerminalInstanceRepository } from "../storage/repositories/terminal-instance-repository.js";
154
166
  import { TerminalLogFileRepository } from "../storage/repositories/terminal-log-file-repository.js";
@@ -204,6 +216,7 @@ export function createServer(config) {
204
216
  verificationRunRepository: new VerificationRunRepository(database.db),
205
217
  commitRuleProfileRepository: new CommitRuleProfileRepository(database.db),
206
218
  gitRemoteCredentialRepository: new GitRemoteCredentialRepository(database.db),
219
+ managedSkillRepository: new ManagedSkillRepository(database.db),
207
220
  recentFileRepository: new RecentFileRepository(database.db),
208
221
  fileContextBindingRepository: new FileContextBindingRepository(database.db),
209
222
  sessionBindingRepository: new SessionBindingRepository(database.db),
@@ -216,6 +229,8 @@ export function createServer(config) {
216
229
  sessionSendQueueRepository: new SessionSendQueueRepository(database.db),
217
230
  sessionStateRepository: new SessionStateRepository(database.db),
218
231
  sessionStatusSnapshotRepository: new SessionStatusSnapshotRepository(database.db),
232
+ instanceTailscaleRepository: new InstanceTailscaleRepository(database.db),
233
+ skillTargetBindingRepository: new SkillTargetBindingRepository(database.db),
219
234
  userQuickPhrasePreferenceRepository: new UserQuickPhrasePreferenceRepository(database.db),
220
235
  userPreferenceProfileRepository: new UserPreferenceProfileRepository(database.db),
221
236
  terminalInstanceRepository: new TerminalInstanceRepository(database.db),
@@ -253,7 +268,7 @@ export function createServer(config) {
253
268
  const fileTreeService = new FileTreeService(fileAccessGuard);
254
269
  const fileSearchService = new FileSearchService(fileAccessGuard);
255
270
  const fileContentService = new FileContentService(fileAccessGuard, recentFileService, repositories.fileContextBindingRepository, fileVersionChecker);
256
- const filePreviewService = new FilePreviewService(fileAccessGuard, fileContentService);
271
+ const filePreviewService = new FilePreviewService(fileAccessGuard, fileContentService, recentFileService);
257
272
  const filePreviewLinkService = new FilePreviewLinkService(fileAccessGuard, config.filePreviewTokenSecret);
258
273
  const workspaceRepoGuard = new WorkspaceRepoGuard(workspaceService, gitCommandRunner);
259
274
  const gitReadService = new GitReadService(gitCommandRunner, workspaceRepoGuard);
@@ -262,6 +277,17 @@ export function createServer(config) {
262
277
  const gitRuleRepository = new GitRuleRepository(repositories.commitRuleProfileRepository);
263
278
  const quickPhraseService = new QuickPhraseService(repositories.userQuickPhrasePreferenceRepository);
264
279
  const preferenceProfileService = new PreferenceProfileService(repositories.userPreferenceProfileRepository);
280
+ const tailscaleHelperClient = new TailscaleHelperClient();
281
+ const tailscaleManager = new TailscaleManager(repositories.bootstrapStateRepository, repositories.instanceTailscaleRepository, tailscaleHelperClient, {
282
+ commandPath: config.tailscaleCliPath,
283
+ webUiPort: config.webUiPort
284
+ });
285
+ const tailscaleService = new TailscaleService(database.db, repositories.instanceTailscaleRepository, tailscaleManager, {
286
+ databasePath: config.databasePath
287
+ });
288
+ const skillManagerService = new SkillManagerService(repositories.managedSkillRepository, repositories.skillTargetBindingRepository, createDefaultSkillTargetAdapters(config), {
289
+ ssotRootDir: path.join(path.dirname(config.databasePath), "skills")
290
+ });
265
291
  const commitRuleEngine = new CommitRuleEngine();
266
292
  const commitDraftService = new CommitDraftService(gitReadService);
267
293
  const commitOrchestrator = new CommitOrchestrator(gitRuleRepository, commitRuleEngine, commitDraftService, gitWriteService, repositories.aiFallbackEditRepository);
@@ -271,6 +297,7 @@ export function createServer(config) {
271
297
  const sessionHistoryService = new SessionHistoryService(database.db, repositories.workspaceRepository, repositories.sessionBindingRepository, sessionChangedFileService, repositories.sessionIndexRepository, sessionMessageAttachmentService, repositories.sessionStateRepository, repositories.sessionStatusSnapshotRepository, config, sessionActivityAuthorityService, repositories.sessionMessageOriginRepository, repositories.sessionForkRepository, {}, taskManager);
272
298
  runtimeObservabilityService = new RuntimeObservabilityService(() => sessionHistoryService.observeBackgroundTaskMetrics(), () => schedulerMetrics.observe(), eventLoopMonitor, taskActivityLog);
273
299
  const sessionLiveRuntimeService = new SessionLiveRuntimeService(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, repositories.sessionBindingRepository, repositories.authUserRepository, repositories.sessionSendQueueRepository, repositories.sessionIndexRepository, repositories.sessionStateRepository, repositories.sessionStatusSnapshotRepository, config, sessionActivityAuthorityService);
300
+ sessionHistoryService.registerLiveActivityObservationResolver((sessionId) => sessionLiveRuntimeService.resolveLiveActivityObservation(sessionId));
274
301
  const butlerRuntimeRootDir = path.join(path.dirname(config.databasePath), "butler-runtime");
275
302
  const butlerRuntimeConfig = {
276
303
  ...config,
@@ -288,8 +315,11 @@ export function createServer(config) {
288
315
  claudeCodeHomeDir: path.join(butlerRuntimeRootDir, "follow-up-claude-home")
289
316
  };
290
317
  const butlerSessionLiveRuntimeService = new SessionLiveRuntimeService(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, repositories.sessionBindingRepository, repositories.authUserRepository, repositories.sessionSendQueueRepository, repositories.sessionIndexRepository, repositories.sessionStateRepository, repositories.sessionStatusSnapshotRepository, butlerRuntimeConfig, sessionActivityAuthorityService);
318
+ sessionHistoryService.registerLiveActivityObservationResolver((sessionId) => butlerSessionLiveRuntimeService.resolveLiveActivityObservation(sessionId));
291
319
  const butlerSummarySessionLiveRuntimeService = new SessionLiveRuntimeService(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, repositories.sessionBindingRepository, repositories.authUserRepository, repositories.sessionSendQueueRepository, repositories.sessionIndexRepository, repositories.sessionStateRepository, repositories.sessionStatusSnapshotRepository, butlerSummaryRuntimeConfig, sessionActivityAuthorityService);
320
+ sessionHistoryService.registerLiveActivityObservationResolver((sessionId) => butlerSummarySessionLiveRuntimeService.resolveLiveActivityObservation(sessionId));
292
321
  const butlerFollowUpSessionLiveRuntimeService = new SessionLiveRuntimeService(sessionHistoryService, sessionMessageAttachmentService, workspaceService, sessionChangedFileService, repositories.sessionBindingRepository, repositories.authUserRepository, repositories.sessionSendQueueRepository, repositories.sessionIndexRepository, repositories.sessionStateRepository, repositories.sessionStatusSnapshotRepository, butlerFollowUpRuntimeConfig, sessionActivityAuthorityService);
322
+ sessionHistoryService.registerLiveActivityObservationResolver((sessionId) => butlerFollowUpSessionLiveRuntimeService.resolveLiveActivityObservation(sessionId));
293
323
  const worktreeManager = new WorktreeManager(workspaceService, repositories.workspaceWorktreeRepository, gitReadService, gitCommandRunner);
294
324
  const worktreeSyncService = new WorktreeSyncService(workspaceService, repositories.workspaceWorktreeRepository, gitCommandRunner);
295
325
  const worktreeMergeService = new WorktreeMergeService(workspaceService, repositories.workspaceWorktreeRepository, gitReadService, gitCommandRunner, worktreeSyncService);
@@ -339,7 +369,7 @@ export function createServer(config) {
339
369
  const butlerFollowUpTerminalSubscription = sessionLiveRuntimeService.registerTerminalStateListener(async (event) => {
340
370
  await butlerFollowUpService.handleSessionTerminal(event.sessionId, event.timestamp);
341
371
  });
342
- const butlerControlSessionService = new ButlerControlSessionService(butlerProfileService, repositories.butlerControlSessionRepository, workspaceService, sessionHistoryService, butlerSessionLiveRuntimeService, butlerContextAggregator, butlerAuthService, butlerRuntimeConfig.codexHomeDir, config.codexHomeDir);
372
+ const butlerControlSessionService = new ButlerControlSessionService(butlerProfileService, repositories.butlerControlSessionRepository, workspaceService, sessionHistoryService, butlerSessionLiveRuntimeService, butlerContextAggregator, butlerAuthService, skillManagerService, butlerRuntimeConfig.codexHomeDir, config.codexHomeDir);
343
373
  const butlerControlActionService = new ButlerControlActionService(butlerProfileService, repositories.butlerControlSessionRepository, repositories.butlerControlEventRepository, butlerProjectService, butlerSessionService, patrolRunService, patrolExecutionService, verificationRunService, butlerContextAggregator);
344
374
  const fileContextService = new FileContextService(sessionHistoryService, repositories.fileContextBindingRepository);
345
375
  const terminalService = new TerminalService(database.db, repositories.terminalInstanceRepository, repositories.terminalRuntimeSessionRepository, workspaceService, config.terminalIdleTimeoutSeconds, {
@@ -348,7 +378,7 @@ export function createServer(config) {
348
378
  terminalLogFileRepository: repositories.terminalLogFileRepository,
349
379
  terminalLogSegmentRepository: repositories.terminalLogSegmentRepository
350
380
  });
351
- const debugTargetService = new DebugTargetService(database.db, workspaceService, repositories.workspaceWorktreeRepository, repositories.debugTargetRepository, repositories.debugServiceRepository, repositories.frameworkAnalysisResultRepository, repositories.debugRuntimeSessionRepository, repositories.portLeaseRepository, repositories.runtimeBindingRepository, repositories.aiFallbackEditRepository, terminalService, repositories.terminalInstanceRepository, taskManager);
381
+ const debugTargetService = new DebugTargetService(database.db, workspaceService, repositories.workspaceWorktreeRepository, repositories.debugTargetRepository, repositories.debugServiceRepository, repositories.frameworkAnalysisResultRepository, repositories.debugRuntimeSessionRepository, repositories.portLeaseRepository, repositories.runtimeBindingRepository, repositories.aiFallbackEditRepository, repositories.terminalCommandTemplateRepository, terminalService, repositories.terminalInstanceRepository, taskManager);
352
382
  const debugRuntimeReconciliationScheduler = new DebugRuntimeReconciliationScheduler(debugTargetService, {
353
383
  schedulerMetrics
354
384
  });
@@ -371,6 +401,8 @@ export function createServer(config) {
371
401
  const sessionController = new SessionController(sessionHistoryService, sessionLiveRuntimeService, repositories.butlerControlSessionRepository);
372
402
  const assistantCapabilityController = new AssistantCapabilityController(new AssistantCapabilityService(butlerProjectService, butlerSessionService, sessionHistoryService, sessionLiveRuntimeService, terminalService));
373
403
  const providerController = new ProviderController(sessionHistoryService, sessionLiveRuntimeService, config);
404
+ const skillController = new SkillController(skillManagerService);
405
+ const tailscaleController = new TailscaleController(tailscaleService);
374
406
  const quickPhraseController = new QuickPhraseController(quickPhraseService);
375
407
  const profileController = new ProfileController(preferenceProfileService);
376
408
  const fileController = new FileController(fileTreeService, fileContentService, fileSearchService, recentFileService, filePreviewService, filePreviewLinkService);
@@ -393,6 +425,7 @@ export function createServer(config) {
393
425
  app.setErrorHandler(setErrorHandler);
394
426
  app.addHook("onReady", async () => {
395
427
  await debugTargetService.runBackgroundRuntimeReconciliation("debug_target.startup_runtime_recovery");
428
+ await tailscaleService.restoreOnStartup();
396
429
  });
397
430
  // Demo 模式:自动创建演示用户
398
431
  if (config.demoMode) {
@@ -414,6 +447,8 @@ export function createServer(config) {
414
447
  void registerButlerRoutes(app, butlerController);
415
448
  void registerSessionRoutes(app, sessionController);
416
449
  void registerPreferenceRoutes(app, quickPhraseController, profileController);
450
+ void registerSkillRoutes(app, skillController);
451
+ void registerSystemRoutes(app, tailscaleController);
417
452
  void registerFileRoutes(app, fileController);
418
453
  void registerSessionContextRoutes(app, fileContextController);
419
454
  void registerTerminalRoutes(app, terminalController);
@@ -442,6 +477,7 @@ export function createServer(config) {
442
477
  await sessionLiveRuntimeService.dispose();
443
478
  await wsHandle.close();
444
479
  gitCommandRunner.dispose();
480
+ tailscaleHelperClient.dispose();
445
481
  database.close();
446
482
  });
447
483
  return {
@@ -491,6 +527,9 @@ export function createServer(config) {
491
527
  commitOrchestrator,
492
528
  quickPhraseService,
493
529
  preferenceProfileService,
530
+ skillManagerService,
531
+ tailscaleManager,
532
+ tailscaleService,
494
533
  runtimeObservabilityService,
495
534
  sessionHistoryService,
496
535
  sessionChangedFileService,