@kaitranntt/ccs 5.9.0 → 5.10.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -2
- package/VERSION +1 -1
- package/dist/ccs.js +12 -0
- package/dist/ccs.js.map +1 -1
- package/dist/cliproxy/account-manager.d.ts +97 -0
- package/dist/cliproxy/account-manager.d.ts.map +1 -0
- package/dist/cliproxy/account-manager.js +314 -0
- package/dist/cliproxy/account-manager.js.map +1 -0
- package/dist/cliproxy/auth-handler.d.ts +19 -1
- package/dist/cliproxy/auth-handler.d.ts.map +1 -1
- package/dist/cliproxy/auth-handler.js +71 -7
- package/dist/cliproxy/auth-handler.js.map +1 -1
- package/dist/cliproxy/binary-manager.d.ts +2 -2
- package/dist/cliproxy/binary-manager.js +2 -2
- package/dist/cliproxy/model-catalog.d.ts +12 -0
- package/dist/cliproxy/model-catalog.d.ts.map +1 -1
- package/dist/cliproxy/model-catalog.js +31 -11
- package/dist/cliproxy/model-catalog.js.map +1 -1
- package/dist/cliproxy/model-config.d.ts.map +1 -1
- package/dist/cliproxy/model-config.js +14 -2
- package/dist/cliproxy/model-config.js.map +1 -1
- package/dist/cliproxy/platform-detector.d.ts +2 -2
- package/dist/cliproxy/platform-detector.js +1 -1
- package/dist/commands/cliproxy-command.d.ts.map +1 -1
- package/dist/commands/cliproxy-command.js +92 -54
- package/dist/commands/cliproxy-command.js.map +1 -1
- package/dist/commands/config-command.d.ts +11 -0
- package/dist/commands/config-command.d.ts.map +1 -0
- package/dist/commands/config-command.js +111 -0
- package/dist/commands/config-command.js.map +1 -0
- package/dist/commands/help-command.d.ts.map +1 -1
- package/dist/commands/help-command.js +4 -1
- package/dist/commands/help-command.js.map +1 -1
- package/dist/glmt/glmt-proxy.d.ts +6 -0
- package/dist/glmt/glmt-proxy.d.ts.map +1 -1
- package/dist/glmt/glmt-proxy.js +23 -2
- package/dist/glmt/glmt-proxy.js.map +1 -1
- package/dist/management/doctor.d.ts.map +1 -1
- package/dist/management/doctor.js +19 -7
- package/dist/management/doctor.js.map +1 -1
- package/dist/types/config.d.ts +2 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js.map +1 -1
- package/dist/ui/assets/form-utils-Bjfa1DVH.js +20 -0
- package/dist/ui/assets/icons-D-Y22K9Z.js +1 -0
- package/dist/ui/assets/index-M5ru6OPu.js +9 -0
- package/dist/ui/assets/index-ZXu5MvSE.css +1 -0
- package/dist/ui/assets/radix-ui-Ba6LUgyw.js +51 -0
- package/dist/ui/assets/react-vendor-CW-MU7-e.js +3 -0
- package/dist/ui/assets/tanstack-MD0629v8.js +4 -0
- package/dist/ui/favicon.ico +0 -0
- package/dist/ui/favicons/android-chrome-192x192.png +0 -0
- package/dist/ui/favicons/android-chrome-512x512.png +0 -0
- package/dist/ui/favicons/android-chrome-512x512.webp +0 -0
- package/dist/ui/favicons/apple-touch-icon.png +0 -0
- package/dist/ui/favicons/favicon-16x16.png +0 -0
- package/dist/ui/favicons/favicon-32x32.png +0 -0
- package/dist/ui/favicons/favicon.ico +0 -0
- package/dist/ui/index.html +30 -0
- package/dist/ui/logo/ccs-logo-256.png +0 -0
- package/dist/ui/logo/ccs-logo-zoomed-web.png +0 -0
- package/dist/ui/logo/ccs-social-media.png +0 -0
- package/dist/ui/logo/ccs-social-media.webp +0 -0
- package/dist/utils/port-utils.d.ts +19 -0
- package/dist/utils/port-utils.d.ts.map +1 -0
- package/dist/utils/port-utils.js +113 -0
- package/dist/utils/port-utils.js.map +1 -0
- package/dist/web-server/file-watcher.d.ts +15 -0
- package/dist/web-server/file-watcher.d.ts.map +1 -0
- package/dist/web-server/file-watcher.js +88 -0
- package/dist/web-server/file-watcher.js.map +1 -0
- package/dist/web-server/health-service.d.ts +35 -0
- package/dist/web-server/health-service.d.ts.map +1 -0
- package/dist/web-server/health-service.js +223 -0
- package/dist/web-server/health-service.js.map +1 -0
- package/dist/web-server/index.d.ts +25 -0
- package/dist/web-server/index.d.ts.map +1 -0
- package/dist/web-server/index.js +89 -0
- package/dist/web-server/index.js.map +1 -0
- package/dist/web-server/overview-routes.d.ts +7 -0
- package/dist/web-server/overview-routes.d.ts.map +1 -0
- package/dist/web-server/overview-routes.js +80 -0
- package/dist/web-server/overview-routes.js.map +1 -0
- package/dist/web-server/routes.d.ts +7 -0
- package/dist/web-server/routes.d.ts.map +1 -0
- package/dist/web-server/routes.js +570 -0
- package/dist/web-server/routes.js.map +1 -0
- package/dist/web-server/shared-routes.d.ts +7 -0
- package/dist/web-server/shared-routes.d.ts.map +1 -0
- package/dist/web-server/shared-routes.js +167 -0
- package/dist/web-server/shared-routes.js.map +1 -0
- package/dist/web-server/shutdown.d.ts +14 -0
- package/dist/web-server/shutdown.d.ts.map +1 -0
- package/dist/web-server/shutdown.js +36 -0
- package/dist/web-server/shutdown.js.map +1 -0
- package/dist/web-server/websocket.d.ts +14 -0
- package/dist/web-server/websocket.d.ts.map +1 -0
- package/dist/web-server/websocket.js +82 -0
- package/dist/web-server/websocket.js.map +1 -0
- package/package.json +26 -6
- package/scripts/clean-dist.js +46 -0
- package/scripts/completion/ccs.bash +69 -10
- package/scripts/completion/ccs.fish +128 -47
- package/scripts/completion/ccs.ps1 +179 -14
- package/scripts/completion/ccs.zsh +107 -28
- package/scripts/pre-release.sh +39 -0
- package/scripts/verify-bundle.js +49 -0
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared Data Routes (Phase 07)
|
|
4
|
+
*
|
|
5
|
+
* API routes for commands, skills, agents from ~/.ccs/shared/
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
24
|
+
if (mod && mod.__esModule) return mod;
|
|
25
|
+
var result = {};
|
|
26
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
27
|
+
__setModuleDefault(result, mod);
|
|
28
|
+
return result;
|
|
29
|
+
};
|
|
30
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
+
exports.sharedRoutes = void 0;
|
|
32
|
+
const express_1 = require("express");
|
|
33
|
+
const fs = __importStar(require("fs"));
|
|
34
|
+
const path = __importStar(require("path"));
|
|
35
|
+
const os = __importStar(require("os"));
|
|
36
|
+
const config_manager_1 = require("../utils/config-manager");
|
|
37
|
+
exports.sharedRoutes = (0, express_1.Router)();
|
|
38
|
+
/**
|
|
39
|
+
* GET /api/shared/commands
|
|
40
|
+
*/
|
|
41
|
+
exports.sharedRoutes.get('/commands', (_req, res) => {
|
|
42
|
+
const items = getSharedItems('commands');
|
|
43
|
+
res.json({ items });
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* GET /api/shared/skills
|
|
47
|
+
*/
|
|
48
|
+
exports.sharedRoutes.get('/skills', (_req, res) => {
|
|
49
|
+
const items = getSharedItems('skills');
|
|
50
|
+
res.json({ items });
|
|
51
|
+
});
|
|
52
|
+
/**
|
|
53
|
+
* GET /api/shared/agents
|
|
54
|
+
*/
|
|
55
|
+
exports.sharedRoutes.get('/agents', (_req, res) => {
|
|
56
|
+
const items = getSharedItems('agents');
|
|
57
|
+
res.json({ items });
|
|
58
|
+
});
|
|
59
|
+
/**
|
|
60
|
+
* GET /api/shared/summary
|
|
61
|
+
*/
|
|
62
|
+
exports.sharedRoutes.get('/summary', (_req, res) => {
|
|
63
|
+
const commands = getSharedItems('commands').length;
|
|
64
|
+
const skills = getSharedItems('skills').length;
|
|
65
|
+
const agents = getSharedItems('agents').length;
|
|
66
|
+
res.json({
|
|
67
|
+
commands,
|
|
68
|
+
skills,
|
|
69
|
+
agents,
|
|
70
|
+
total: commands + skills + agents,
|
|
71
|
+
symlinkStatus: checkSymlinkStatus(),
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
function getSharedItems(type) {
|
|
75
|
+
const ccsDir = (0, config_manager_1.getCcsDir)();
|
|
76
|
+
const sharedDir = path.join(ccsDir, 'shared', type);
|
|
77
|
+
if (!fs.existsSync(sharedDir)) {
|
|
78
|
+
return [];
|
|
79
|
+
}
|
|
80
|
+
const items = [];
|
|
81
|
+
try {
|
|
82
|
+
const entries = fs.readdirSync(sharedDir, { withFileTypes: true });
|
|
83
|
+
for (const entry of entries) {
|
|
84
|
+
if (entry.isDirectory()) {
|
|
85
|
+
// Skill/Agent: look for prompt.md
|
|
86
|
+
const promptPath = path.join(sharedDir, entry.name, 'prompt.md');
|
|
87
|
+
if (fs.existsSync(promptPath)) {
|
|
88
|
+
const content = fs.readFileSync(promptPath, 'utf8');
|
|
89
|
+
const description = extractDescription(content);
|
|
90
|
+
items.push({
|
|
91
|
+
name: entry.name,
|
|
92
|
+
description,
|
|
93
|
+
path: path.join(sharedDir, entry.name),
|
|
94
|
+
type: type === 'commands' ? 'command' : type.slice(0, -1),
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
else if (entry.name.endsWith('.md')) {
|
|
99
|
+
// Command: .md file
|
|
100
|
+
const filePath = path.join(sharedDir, entry.name);
|
|
101
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
102
|
+
const description = extractDescription(content);
|
|
103
|
+
items.push({
|
|
104
|
+
name: entry.name.replace('.md', ''),
|
|
105
|
+
description,
|
|
106
|
+
path: filePath,
|
|
107
|
+
type: 'command',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Directory read failed
|
|
114
|
+
}
|
|
115
|
+
return items.sort((a, b) => a.name.localeCompare(b.name));
|
|
116
|
+
}
|
|
117
|
+
function extractDescription(content) {
|
|
118
|
+
// Extract first non-empty, non-heading line
|
|
119
|
+
const lines = content.split('\n');
|
|
120
|
+
for (const line of lines) {
|
|
121
|
+
const trimmed = line.trim();
|
|
122
|
+
if (trimmed && !trimmed.startsWith('#') && !trimmed.startsWith('---')) {
|
|
123
|
+
return trimmed.slice(0, 100);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return 'No description';
|
|
127
|
+
}
|
|
128
|
+
function checkSymlinkStatus() {
|
|
129
|
+
const ccsDir = (0, config_manager_1.getCcsDir)();
|
|
130
|
+
const sharedDir = path.join(ccsDir, 'shared');
|
|
131
|
+
if (!fs.existsSync(sharedDir)) {
|
|
132
|
+
return { valid: false, message: 'Shared directory not found' };
|
|
133
|
+
}
|
|
134
|
+
// Check all three symlinks: commands, skills, agents
|
|
135
|
+
const linkTypes = ['commands', 'skills', 'agents'];
|
|
136
|
+
let validLinks = 0;
|
|
137
|
+
for (const linkType of linkTypes) {
|
|
138
|
+
const linkPath = path.join(sharedDir, linkType);
|
|
139
|
+
try {
|
|
140
|
+
if (fs.existsSync(linkPath)) {
|
|
141
|
+
const stats = fs.lstatSync(linkPath);
|
|
142
|
+
if (stats.isSymbolicLink()) {
|
|
143
|
+
const target = fs.readlinkSync(linkPath);
|
|
144
|
+
// Check if it points to ~/.claude/{linkType}
|
|
145
|
+
const expectedTarget = path.join(os.homedir(), '.claude', linkType);
|
|
146
|
+
if (path.resolve(path.dirname(linkPath), target) === path.resolve(expectedTarget)) {
|
|
147
|
+
validLinks++;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// Not a symlink or read error
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if (validLinks === linkTypes.length) {
|
|
157
|
+
return { valid: true, message: 'Symlinks active' };
|
|
158
|
+
}
|
|
159
|
+
else if (validLinks > 0) {
|
|
160
|
+
return {
|
|
161
|
+
valid: false,
|
|
162
|
+
message: `Symlinks partially configured (${validLinks}/${linkTypes.length})`,
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
return { valid: false, message: 'Symlinks not configured' };
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=shared-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-routes.js","sourceRoot":"","sources":["../../src/web-server/shared-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Graceful Shutdown Handler
|
|
3
|
+
*
|
|
4
|
+
* Handles SIGINT/SIGTERM signals to gracefully close WebSocket connections
|
|
5
|
+
* and HTTP server before process exit.
|
|
6
|
+
*/
|
|
7
|
+
/// <reference types="node" />
|
|
8
|
+
import { Server as HTTPServer } from 'http';
|
|
9
|
+
import { WebSocketServer } from 'ws';
|
|
10
|
+
/**
|
|
11
|
+
* Setup graceful shutdown handlers for SIGINT and SIGTERM
|
|
12
|
+
*/
|
|
13
|
+
export declare function setupGracefulShutdown(server: HTTPServer, _wss: WebSocketServer, cleanup?: () => void): void;
|
|
14
|
+
//# sourceMappingURL=shutdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.d.ts","sourceRoot":"","sources":["../../src/web-server/shutdown.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;;AAEH,OAAO,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAIrC;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,eAAe,EACrB,OAAO,CAAC,EAAE,MAAM,IAAI,GACnB,IAAI,CAwBN"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Graceful Shutdown Handler
|
|
4
|
+
*
|
|
5
|
+
* Handles SIGINT/SIGTERM signals to gracefully close WebSocket connections
|
|
6
|
+
* and HTTP server before process exit.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.setupGracefulShutdown = void 0;
|
|
10
|
+
const SHUTDOWN_TIMEOUT = 10000; // 10 seconds
|
|
11
|
+
/**
|
|
12
|
+
* Setup graceful shutdown handlers for SIGINT and SIGTERM
|
|
13
|
+
*/
|
|
14
|
+
function setupGracefulShutdown(server, _wss, cleanup) {
|
|
15
|
+
const shutdown = () => {
|
|
16
|
+
console.log('\n[i] Shutting down gracefully...');
|
|
17
|
+
// Run cleanup first (closes file watchers + WebSocket clients)
|
|
18
|
+
if (cleanup) {
|
|
19
|
+
cleanup();
|
|
20
|
+
}
|
|
21
|
+
// Close HTTP server
|
|
22
|
+
server.close(() => {
|
|
23
|
+
console.log('[OK] Server closed');
|
|
24
|
+
process.exit(0);
|
|
25
|
+
});
|
|
26
|
+
// Force shutdown if graceful shutdown takes too long
|
|
27
|
+
setTimeout(() => {
|
|
28
|
+
console.log('[!] Force shutdown (timeout exceeded)');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}, SHUTDOWN_TIMEOUT);
|
|
31
|
+
};
|
|
32
|
+
process.on('SIGINT', shutdown);
|
|
33
|
+
process.on('SIGTERM', shutdown);
|
|
34
|
+
}
|
|
35
|
+
exports.setupGracefulShutdown = setupGracefulShutdown;
|
|
36
|
+
//# sourceMappingURL=shutdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shutdown.js","sourceRoot":"","sources":["../../src/web-server/shutdown.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAKH,MAAM,gBAAgB,GAAG,KAAM,CAAC,CAAC,aAAa;AAE9C;;GAEG;AACH,SAAgB,qBAAqB,CACnC,MAAkB,EAClB,IAAqB,EACrB,OAAoB;IAEpB,MAAM,QAAQ,GAAG,GAAG,EAAE;QACpB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QAEjD,+DAA+D;QAC/D,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,oBAAoB;QACpB,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE;YAChB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,qDAAqD;QACrD,UAAU,CAAC,GAAG,EAAE;YACd,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;YACrD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,EAAE,gBAAgB,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC;AA5BD,sDA4BC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Handler (Phase 04)
|
|
3
|
+
*
|
|
4
|
+
* Manages WebSocket connections, broadcasts file changes, and handles client messages.
|
|
5
|
+
*/
|
|
6
|
+
import { WebSocketServer } from 'ws';
|
|
7
|
+
export interface WSMessage {
|
|
8
|
+
type: string;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export declare function setupWebSocket(wss: WebSocketServer): {
|
|
12
|
+
cleanup: () => void;
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=websocket.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/web-server/websocket.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAa,MAAM,IAAI,CAAC;AAGhD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG;IAAE,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CA8E5E"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket Handler (Phase 04)
|
|
4
|
+
*
|
|
5
|
+
* Manages WebSocket connections, broadcasts file changes, and handles client messages.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.setupWebSocket = void 0;
|
|
9
|
+
const ws_1 = require("ws");
|
|
10
|
+
const file_watcher_1 = require("./file-watcher");
|
|
11
|
+
function setupWebSocket(wss) {
|
|
12
|
+
// Track connected clients
|
|
13
|
+
const clients = new Set();
|
|
14
|
+
// Broadcast message to all clients
|
|
15
|
+
function broadcast(message) {
|
|
16
|
+
const data = JSON.stringify(message);
|
|
17
|
+
clients.forEach((client) => {
|
|
18
|
+
if (client.readyState === ws_1.WebSocket.OPEN) {
|
|
19
|
+
client.send(data);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Handle new connections
|
|
24
|
+
wss.on('connection', (ws) => {
|
|
25
|
+
clients.add(ws);
|
|
26
|
+
console.log(`[WS] Client connected (${clients.size} total)`);
|
|
27
|
+
// Send welcome message
|
|
28
|
+
ws.send(JSON.stringify({ type: 'connected', timestamp: Date.now() }));
|
|
29
|
+
// Handle client messages
|
|
30
|
+
ws.on('message', (data) => {
|
|
31
|
+
try {
|
|
32
|
+
const message = JSON.parse(data.toString());
|
|
33
|
+
handleClientMessage(ws, message);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
console.log('[WS] Invalid message format');
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// Handle disconnect
|
|
40
|
+
ws.on('close', () => {
|
|
41
|
+
clients.delete(ws);
|
|
42
|
+
console.log(`[WS] Client disconnected (${clients.size} remaining)`);
|
|
43
|
+
});
|
|
44
|
+
ws.on('error', (err) => {
|
|
45
|
+
console.log(`[WS] Error: ${err.message}`);
|
|
46
|
+
clients.delete(ws);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
// Handle incoming client messages
|
|
50
|
+
function handleClientMessage(ws, message) {
|
|
51
|
+
switch (message.type) {
|
|
52
|
+
case 'ping':
|
|
53
|
+
ws.send(JSON.stringify({ type: 'pong', timestamp: Date.now() }));
|
|
54
|
+
break;
|
|
55
|
+
case 'subscribe':
|
|
56
|
+
// Future: selective subscriptions
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
console.log(`[WS] Unknown message type: ${message.type}`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// Setup file watcher
|
|
63
|
+
const watcher = (0, file_watcher_1.createFileWatcher)((event) => {
|
|
64
|
+
console.log(`[FS] ${event.type}: ${event.path}`);
|
|
65
|
+
broadcast({
|
|
66
|
+
type: event.type,
|
|
67
|
+
path: event.path,
|
|
68
|
+
timestamp: event.timestamp,
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
// Cleanup function
|
|
72
|
+
const cleanup = () => {
|
|
73
|
+
watcher.close();
|
|
74
|
+
clients.forEach((client) => {
|
|
75
|
+
client.close(1001, 'Server shutting down');
|
|
76
|
+
});
|
|
77
|
+
clients.clear();
|
|
78
|
+
};
|
|
79
|
+
return { cleanup };
|
|
80
|
+
}
|
|
81
|
+
exports.setupWebSocket = setupWebSocket;
|
|
82
|
+
//# sourceMappingURL=websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/web-server/websocket.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaitranntt/ccs",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.0-dev.1",
|
|
4
4
|
"description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -52,45 +52,65 @@
|
|
|
52
52
|
"scripts": {
|
|
53
53
|
"build": "tsc && node scripts/add-shebang.js",
|
|
54
54
|
"build:watch": "tsc --watch",
|
|
55
|
-
"
|
|
55
|
+
"build:server": "tsc && node scripts/add-shebang.js",
|
|
56
|
+
"build:all": "bun run ui:build && bun run build:server",
|
|
57
|
+
"prebuild": "node scripts/clean-dist.js",
|
|
58
|
+
"prebuild:all": "rm -rf dist tsconfig.tsbuildinfo",
|
|
59
|
+
"postbuild:all": "node scripts/verify-bundle.js",
|
|
56
60
|
"typecheck": "tsc --noEmit",
|
|
57
61
|
"lint": "eslint src/",
|
|
58
62
|
"lint:fix": "eslint src/ --fix",
|
|
59
63
|
"format": "prettier --write src/",
|
|
60
64
|
"format:check": "prettier --check src/",
|
|
61
65
|
"validate": "bun run typecheck && bun run lint:fix && bun run format:check && bun run test",
|
|
66
|
+
"verify:bundle": "node scripts/verify-bundle.js",
|
|
62
67
|
"test": "bun run build && bun run test:all",
|
|
63
68
|
"test:all": "bun test",
|
|
64
69
|
"test:unit": "bun test tests/unit/",
|
|
65
70
|
"test:npm": "bun test tests/npm/",
|
|
66
71
|
"test:native": "bash tests/native/unix/edge-cases.sh",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
72
|
+
"dev": "bun run build:server && bun dist/ccs.js config --dev",
|
|
73
|
+
"ui:build": "cd ui && bun run build",
|
|
74
|
+
"ui:preview": "cd ui && bun run preview",
|
|
75
|
+
"ui:validate": "cd ui && bun run validate",
|
|
76
|
+
"prepublishOnly": "bun run build:all && bun run validate && node scripts/sync-version.js",
|
|
77
|
+
"prepack": "bun run build:all && bun run validate && node scripts/sync-version.js",
|
|
69
78
|
"prepare": "husky",
|
|
70
79
|
"postinstall": "node scripts/postinstall.js"
|
|
71
80
|
},
|
|
72
81
|
"dependencies": {
|
|
73
82
|
"boxen": "^8.0.1",
|
|
74
83
|
"chalk": "^5.6.2",
|
|
84
|
+
"chokidar": "^5.0.0",
|
|
75
85
|
"cli-table3": "^0.6.5",
|
|
86
|
+
"express": "^4.18.2",
|
|
87
|
+
"get-port": "^7.0.0",
|
|
76
88
|
"gradient-string": "^3.0.0",
|
|
77
89
|
"listr2": "^9.0.5",
|
|
78
|
-
"
|
|
90
|
+
"open": "^10.1.0",
|
|
91
|
+
"ora": "^9.0.0",
|
|
92
|
+
"ws": "^8.16.0"
|
|
79
93
|
},
|
|
80
94
|
"devDependencies": {
|
|
81
95
|
"@commitlint/cli": "^20.1.0",
|
|
82
96
|
"@commitlint/config-conventional": "^20.0.0",
|
|
83
97
|
"@semantic-release/changelog": "^6.0.3",
|
|
84
98
|
"@semantic-release/git": "^10.0.1",
|
|
99
|
+
"@tailwindcss/vite": "^4.1.17",
|
|
100
|
+
"@types/chokidar": "^2.1.7",
|
|
101
|
+
"@types/express": "^4.17.21",
|
|
85
102
|
"@types/node": "^20.19.25",
|
|
103
|
+
"@types/ws": "^8.5.10",
|
|
86
104
|
"@typescript-eslint/eslint-plugin": "^8.48.0",
|
|
87
105
|
"@typescript-eslint/parser": "^8.48.0",
|
|
106
|
+
"@vitejs/plugin-react": "^5.1.1",
|
|
88
107
|
"eslint": "^9.39.1",
|
|
89
108
|
"eslint-config-prettier": "^10.1.8",
|
|
90
109
|
"husky": "^9.1.7",
|
|
91
110
|
"mocha": "^11.7.5",
|
|
92
111
|
"prettier": "^3.6.2",
|
|
93
112
|
"semantic-release": "^25.0.2",
|
|
94
|
-
"typescript": "5.3"
|
|
113
|
+
"typescript": "5.3",
|
|
114
|
+
"vite": "^7.2.4"
|
|
95
115
|
}
|
|
96
116
|
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clean dist directory while preserving UI bundle
|
|
5
|
+
* The UI bundle is built separately and should not be deleted during regular builds
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const DIST_DIR = path.join(__dirname, '../dist');
|
|
12
|
+
const TSCONFIG_BUILDINFO = path.join(__dirname, '../tsconfig.tsbuildinfo');
|
|
13
|
+
|
|
14
|
+
// Directories to preserve (from UI build)
|
|
15
|
+
const PRESERVE = new Set(['ui']);
|
|
16
|
+
|
|
17
|
+
function cleanDist() {
|
|
18
|
+
// Remove tsconfig.tsbuildinfo
|
|
19
|
+
if (fs.existsSync(TSCONFIG_BUILDINFO)) {
|
|
20
|
+
fs.unlinkSync(TSCONFIG_BUILDINFO);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// If dist doesn't exist, nothing to clean
|
|
24
|
+
if (!fs.existsSync(DIST_DIR)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const entries = fs.readdirSync(DIST_DIR, { withFileTypes: true });
|
|
29
|
+
|
|
30
|
+
for (const entry of entries) {
|
|
31
|
+
// Skip preserved directories
|
|
32
|
+
if (PRESERVE.has(entry.name)) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const fullPath = path.join(DIST_DIR, entry.name);
|
|
37
|
+
|
|
38
|
+
if (entry.isDirectory()) {
|
|
39
|
+
fs.rmSync(fullPath, { recursive: true, force: true });
|
|
40
|
+
} else {
|
|
41
|
+
fs.unlinkSync(fullPath);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
cleanDist();
|
|
@@ -18,8 +18,9 @@ _ccs_completion() {
|
|
|
18
18
|
|
|
19
19
|
# Top-level completion (first argument)
|
|
20
20
|
if [[ ${COMP_CWORD} -eq 1 ]]; then
|
|
21
|
-
local commands="auth
|
|
21
|
+
local commands="auth api cliproxy doctor sync update"
|
|
22
22
|
local flags="--help --version --shell-completion -h -v -sc"
|
|
23
|
+
local cliproxy_profiles="gemini codex agy qwen"
|
|
23
24
|
local profiles=""
|
|
24
25
|
|
|
25
26
|
# Add profiles from config.json (settings-based profiles)
|
|
@@ -32,12 +33,24 @@ _ccs_completion() {
|
|
|
32
33
|
profiles="$profiles $(jq -r '.profiles | keys[]' ~/.ccs/profiles.json 2>/dev/null || true)"
|
|
33
34
|
fi
|
|
34
35
|
|
|
36
|
+
# Add cliproxy variants from config.json
|
|
37
|
+
if [[ -f ~/.ccs/config.json ]]; then
|
|
38
|
+
profiles="$profiles $(jq -r '.cliproxy | keys[]' ~/.ccs/config.json 2>/dev/null || true)"
|
|
39
|
+
fi
|
|
40
|
+
|
|
35
41
|
# Combine all options
|
|
36
|
-
local opts="$commands $flags $profiles"
|
|
42
|
+
local opts="$commands $flags $cliproxy_profiles $profiles"
|
|
37
43
|
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
|
|
38
44
|
return 0
|
|
39
45
|
fi
|
|
40
46
|
|
|
47
|
+
# CLIProxy provider flags (gemini, codex, agy, qwen)
|
|
48
|
+
if [[ ${COMP_WORDS[1]} =~ ^(gemini|codex|agy|qwen)$ ]]; then
|
|
49
|
+
local provider_flags="--auth --config --logout --headless --help -h"
|
|
50
|
+
COMPREPLY=( $(compgen -W "${provider_flags}" -- ${cur}) )
|
|
51
|
+
return 0
|
|
52
|
+
fi
|
|
53
|
+
|
|
41
54
|
# auth subcommands
|
|
42
55
|
if [[ ${prev} == "auth" ]]; then
|
|
43
56
|
local auth_commands="create list show remove default --help -h"
|
|
@@ -45,15 +58,54 @@ _ccs_completion() {
|
|
|
45
58
|
return 0
|
|
46
59
|
fi
|
|
47
60
|
|
|
48
|
-
#
|
|
49
|
-
if [[ ${prev} == "
|
|
50
|
-
local
|
|
51
|
-
COMPREPLY=( $(compgen -W "${
|
|
61
|
+
# api subcommands
|
|
62
|
+
if [[ ${prev} == "api" ]]; then
|
|
63
|
+
local api_commands="create list remove --help -h"
|
|
64
|
+
COMPREPLY=( $(compgen -W "${api_commands}" -- ${cur}) )
|
|
65
|
+
return 0
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# cliproxy subcommands
|
|
69
|
+
if [[ ${prev} == "cliproxy" ]]; then
|
|
70
|
+
local cliproxy_commands="create list remove --install --latest --help -h"
|
|
71
|
+
COMPREPLY=( $(compgen -W "${cliproxy_commands}" -- ${cur}) )
|
|
52
72
|
return 0
|
|
53
73
|
fi
|
|
54
74
|
|
|
55
|
-
# Completion for
|
|
56
|
-
if [[ ${COMP_WORDS[1]} == "
|
|
75
|
+
# Completion for cliproxy subcommands
|
|
76
|
+
if [[ ${COMP_WORDS[1]} == "cliproxy" ]]; then
|
|
77
|
+
case "${prev}" in
|
|
78
|
+
remove|delete|rm)
|
|
79
|
+
# Complete with cliproxy variant names
|
|
80
|
+
if [[ -f ~/.ccs/config.json ]]; then
|
|
81
|
+
local variants=$(jq -r '.cliproxy | keys[]' ~/.ccs/config.json 2>/dev/null || true)
|
|
82
|
+
COMPREPLY=( $(compgen -W "${variants}" -- ${cur}) )
|
|
83
|
+
fi
|
|
84
|
+
return 0
|
|
85
|
+
;;
|
|
86
|
+
create)
|
|
87
|
+
# Complete with create flags
|
|
88
|
+
COMPREPLY=( $(compgen -W "--provider --model --force --yes -y" -- ${cur}) )
|
|
89
|
+
return 0
|
|
90
|
+
;;
|
|
91
|
+
--provider)
|
|
92
|
+
# Complete with provider names
|
|
93
|
+
COMPREPLY=( $(compgen -W "gemini codex agy qwen" -- ${cur}) )
|
|
94
|
+
return 0
|
|
95
|
+
;;
|
|
96
|
+
list|ls)
|
|
97
|
+
# No flags for list
|
|
98
|
+
return 0
|
|
99
|
+
;;
|
|
100
|
+
--install)
|
|
101
|
+
# User enters version number
|
|
102
|
+
return 0
|
|
103
|
+
;;
|
|
104
|
+
esac
|
|
105
|
+
fi
|
|
106
|
+
|
|
107
|
+
# Completion for api subcommands
|
|
108
|
+
if [[ ${COMP_WORDS[1]} == "api" ]]; then
|
|
57
109
|
case "${prev}" in
|
|
58
110
|
remove|delete|rm)
|
|
59
111
|
# Complete with settings profile names
|
|
@@ -87,7 +139,8 @@ _ccs_completion() {
|
|
|
87
139
|
return 0
|
|
88
140
|
;;
|
|
89
141
|
create)
|
|
90
|
-
#
|
|
142
|
+
# Complete with create flags
|
|
143
|
+
COMPREPLY=( $(compgen -W "--force" -- ${cur}) )
|
|
91
144
|
return 0
|
|
92
145
|
;;
|
|
93
146
|
list)
|
|
@@ -104,8 +157,14 @@ _ccs_completion() {
|
|
|
104
157
|
return 0
|
|
105
158
|
fi
|
|
106
159
|
|
|
160
|
+
# Flags for update command
|
|
161
|
+
if [[ ${COMP_WORDS[1]} == "update" ]]; then
|
|
162
|
+
COMPREPLY=( $(compgen -W "--force --beta --dev --help -h" -- ${cur}) )
|
|
163
|
+
return 0
|
|
164
|
+
fi
|
|
165
|
+
|
|
107
166
|
# Flags for shell-completion command
|
|
108
|
-
if [[ ${prev} == "--shell-completion" ]]; then
|
|
167
|
+
if [[ ${prev} == "--shell-completion" || ${prev} == "-sc" ]]; then
|
|
109
168
|
COMPREPLY=( $(compgen -W "--bash --zsh --fish --powershell" -- ${cur}) )
|
|
110
169
|
return 0
|
|
111
170
|
fi
|