cicy-desktop 2.1.237 → 2.1.239
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/package.json +9 -16
- package/src/sidecar/cicy-code.js +32 -9
- package/src/sidecar/container-scripts/cicy-code-update.sh +6 -1
- package/src/sidecar/host-mihomo.js +40 -10
- package/src/sidecar/runtime.js +144 -64
- package/src/tabbrowser/tab-shell.html +5 -1
- package/.kiro/steering/dev-workflow.md +0 -166
- package/AGENTS.md +0 -275
- package/CLAUDE_HANDOFF.md +0 -168
- package/DESIGN.md +0 -66
- package/DOCKER.md +0 -85
- package/Dockerfile +0 -46
- package/TODO-anti-detection.md +0 -326
- package/copy-to-desktop.sh +0 -26
- package/docs/AUTOMATION-API.md +0 -342
- package/docs/REQUEST_MONITORING.md +0 -435
- package/docs/REST-API-FEATURE.md +0 -155
- package/docs/REST-API.md +0 -276
- package/docs/backend-selector-design.md +0 -204
- package/docs/chrome-proxy.md +0 -142
- package/docs/cicy-desktop-current-execution-bridge.md +0 -509
- package/docs/feature-distributed-multi-agent.md +0 -555
- package/docs/worklog-2026-03-27.md +0 -108
- package/docs/yaml.md +0 -255
- package/generate-openapi.js +0 -162
- package/jest.config.js +0 -13
- package/jest.setup.global.js +0 -16
- package/jest.teardown.global.js +0 -10
- package/service.sh +0 -164
- package/update-desktop.sh +0 -33
package/docs/yaml.md
DELETED
|
@@ -1,255 +0,0 @@
|
|
|
1
|
-
# YAML 支持文档
|
|
2
|
-
|
|
3
|
-
## 概述
|
|
4
|
-
|
|
5
|
-
CiCy Desktop Server 支持 YAML 和 JSON 双格式,**默认使用 YAML** 以节省 token 消耗。
|
|
6
|
-
|
|
7
|
-
## 为什么选择 YAML?
|
|
8
|
-
|
|
9
|
-
### Token 节省对比
|
|
10
|
-
|
|
11
|
-
**JSON 格式(~100 字符):**
|
|
12
|
-
```json
|
|
13
|
-
{"name":"open_window","arguments":{"url":"https://google.com","reuseWindow":false}}
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
**YAML 格式(~70 字符):**
|
|
17
|
-
```yaml
|
|
18
|
-
name: open_window
|
|
19
|
-
arguments:
|
|
20
|
-
url: https://google.com
|
|
21
|
-
reuseWindow: false
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
**节省约 30-45% token!**
|
|
25
|
-
|
|
26
|
-
### 其他优势
|
|
27
|
-
|
|
28
|
-
- ✅ 更易读易写
|
|
29
|
-
- ✅ 无需大量引号和逗号
|
|
30
|
-
- ✅ 支持注释(虽然在 API 调用中不常用)
|
|
31
|
-
- ✅ 更自然的缩进结构
|
|
32
|
-
|
|
33
|
-
## 服务器端支持
|
|
34
|
-
|
|
35
|
-
### Accept 头控制
|
|
36
|
-
|
|
37
|
-
服务器根据 `Accept` 头返回相应格式:
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
# 请求 YAML 响应
|
|
41
|
-
curl -H "Accept: application/yaml" http://localhost:8101/rpc
|
|
42
|
-
|
|
43
|
-
# 请求 JSON 响应(默认)
|
|
44
|
-
curl -H "Accept: application/json" http://localhost:8101/rpc
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### 响应格式对比
|
|
48
|
-
|
|
49
|
-
**YAML 响应(~50 字符):**
|
|
50
|
-
```yaml
|
|
51
|
-
jsonrpc: '2.0'
|
|
52
|
-
id: 1
|
|
53
|
-
result:
|
|
54
|
-
content:
|
|
55
|
-
- type: text
|
|
56
|
-
text: Pong
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
**JSON 响应(~90 字符):**
|
|
60
|
-
```json
|
|
61
|
-
{"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"Pong"}]}}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
## cicy-rpc 工具
|
|
65
|
-
|
|
66
|
-
### 默认行为
|
|
67
|
-
|
|
68
|
-
`cicy-rpc` 默认使用 YAML 格式:
|
|
69
|
-
|
|
70
|
-
```bash
|
|
71
|
-
# YAML(默认,无需标志)
|
|
72
|
-
cicy-rpc "
|
|
73
|
-
name: ping
|
|
74
|
-
arguments: {}
|
|
75
|
-
"
|
|
76
|
-
|
|
77
|
-
# JSON(需要 --json 或 -j)
|
|
78
|
-
cicy-rpc --json '{"name":"ping","arguments":{}}'
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
### 自动处理
|
|
82
|
-
|
|
83
|
-
工具自动处理格式转换:
|
|
84
|
-
|
|
85
|
-
1. **输入处理**:
|
|
86
|
-
- YAML 输入 → 使用 `yq` 转换为 JSON
|
|
87
|
-
- JSON 输入 → 直接使用
|
|
88
|
-
|
|
89
|
-
2. **Accept 头**:
|
|
90
|
-
- YAML 模式 → `Accept: application/yaml`
|
|
91
|
-
- JSON 模式 → `Accept: application/json`
|
|
92
|
-
|
|
93
|
-
3. **输出解析**:
|
|
94
|
-
- YAML 响应 → 使用 `yq` 解析
|
|
95
|
-
- JSON 响应 → 使用 `jq` 解析
|
|
96
|
-
|
|
97
|
-
## 依赖安装
|
|
98
|
-
|
|
99
|
-
### 服务器端
|
|
100
|
-
|
|
101
|
-
```bash
|
|
102
|
-
npm install js-yaml
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
### 客户端
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
pip install yq --break-system-packages
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
## 实际使用示例
|
|
112
|
-
|
|
113
|
-
### 打开窗口
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
cicy-rpc "
|
|
117
|
-
name: open_window
|
|
118
|
-
arguments:
|
|
119
|
-
url: https://gemini.google.com
|
|
120
|
-
"
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### 设置窗口位置
|
|
124
|
-
|
|
125
|
-
```bash
|
|
126
|
-
cicy-rpc "
|
|
127
|
-
name: set_window_bounds
|
|
128
|
-
arguments:
|
|
129
|
-
win_id: 1
|
|
130
|
-
x: 1320
|
|
131
|
-
y: 0
|
|
132
|
-
width: 360
|
|
133
|
-
height: 720
|
|
134
|
-
"
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### 执行 JavaScript
|
|
138
|
-
|
|
139
|
-
```bash
|
|
140
|
-
cicy-rpc "
|
|
141
|
-
name: exec_js
|
|
142
|
-
arguments:
|
|
143
|
-
win_id: 1
|
|
144
|
-
code: document.title
|
|
145
|
-
"
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
### 复杂参数
|
|
149
|
-
|
|
150
|
-
```bash
|
|
151
|
-
cicy-rpc "
|
|
152
|
-
name: open_window
|
|
153
|
-
arguments:
|
|
154
|
-
url: https://example.com
|
|
155
|
-
accountIdx: 1
|
|
156
|
-
reuseWindow: false
|
|
157
|
-
options:
|
|
158
|
-
width: 1280
|
|
159
|
-
height: 720
|
|
160
|
-
"
|
|
161
|
-
```
|
|
162
|
-
|
|
163
|
-
## 性能影响
|
|
164
|
-
|
|
165
|
-
### Token 消耗
|
|
166
|
-
|
|
167
|
-
- **YAML**: 平均节省 30-45% 字符
|
|
168
|
-
- **网络传输**: 响应体积减少约 40%
|
|
169
|
-
- **解析速度**: YAML 略慢,但差异可忽略
|
|
170
|
-
|
|
171
|
-
### 推荐使用场景
|
|
172
|
-
|
|
173
|
-
- ✅ **AI 对话**: 使用 YAML(节省 token)
|
|
174
|
-
- ✅ **命令行工具**: 使用 YAML(易读易写)
|
|
175
|
-
- ⚠️ **程序化调用**: JSON 或 YAML 均可
|
|
176
|
-
- ⚠️ **性能关键**: JSON(解析更快)
|
|
177
|
-
|
|
178
|
-
## 故障排除
|
|
179
|
-
|
|
180
|
-
### yq 未安装
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
❌ Error: yq not found. Install with: pip install yq --break-system-packages
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
**解决方案:**
|
|
187
|
-
```bash
|
|
188
|
-
pip install yq --break-system-packages
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
### YAML 语法错误
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
❌ Error: yaml.scanner.ScannerError: mapping values are not allowed here
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
**解决方案:**
|
|
198
|
-
- 检查缩进(使用空格,不要用 Tab)
|
|
199
|
-
- 确保冒号后有空格
|
|
200
|
-
- 检查特殊字符是否需要引号
|
|
201
|
-
|
|
202
|
-
### 服务器不支持 YAML
|
|
203
|
-
|
|
204
|
-
如果服务器版本较旧,使用 JSON 格式:
|
|
205
|
-
|
|
206
|
-
```bash
|
|
207
|
-
cicy-rpc --json '{"name":"ping","arguments":{}}'
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
## 技术实现
|
|
211
|
-
|
|
212
|
-
### 服务器端 (Node.js)
|
|
213
|
-
|
|
214
|
-
```javascript
|
|
215
|
-
const yaml = require('js-yaml');
|
|
216
|
-
|
|
217
|
-
app.post("/rpc", async (req, res) => {
|
|
218
|
-
const acceptHeader = req.get('Accept') || 'application/json';
|
|
219
|
-
const useYaml = acceptHeader.includes('application/yaml');
|
|
220
|
-
|
|
221
|
-
const response = { /* ... */ };
|
|
222
|
-
|
|
223
|
-
if (useYaml) {
|
|
224
|
-
res.type('application/yaml').send(yaml.dump(response));
|
|
225
|
-
} else {
|
|
226
|
-
res.json(response);
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
### 客户端 (Bash)
|
|
232
|
-
|
|
233
|
-
```bash
|
|
234
|
-
# YAML 转 JSON
|
|
235
|
-
PARAMS=$(echo "$PARAMS_INPUT" | yq -c .)
|
|
236
|
-
|
|
237
|
-
# 设置 Accept 头
|
|
238
|
-
ACCEPT_HEADER="application/yaml"
|
|
239
|
-
|
|
240
|
-
# 解析 YAML 响应
|
|
241
|
-
curl ... | yq -r '.result.content[].text'
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
## 最佳实践
|
|
245
|
-
|
|
246
|
-
1. **默认使用 YAML** - 节省 token 和带宽
|
|
247
|
-
2. **复杂嵌套使用 JSON** - 避免 YAML 缩进问题
|
|
248
|
-
3. **程序化调用优先 JSON** - 更好的库支持
|
|
249
|
-
4. **命令行优先 YAML** - 更易读易写
|
|
250
|
-
|
|
251
|
-
## 参考资源
|
|
252
|
-
|
|
253
|
-
- [YAML 规范](https://yaml.org/)
|
|
254
|
-
- [js-yaml 文档](https://github.com/nodeca/js-yaml)
|
|
255
|
-
- [yq 文档](https://github.com/kislyuk/yq)
|
package/generate-openapi.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Copyright 2026 CiCy AI
|
|
3
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const yaml = require('js-yaml');
|
|
9
|
-
|
|
10
|
-
// 从服务器获取工具列表和 schemas
|
|
11
|
-
async function getToolsWithSchemas() {
|
|
12
|
-
const http = require('http');
|
|
13
|
-
const tokenPath = path.join(require('os').homedir(), 'cicy-ai', 'global.json');
|
|
14
|
-
const config = JSON.parse(fs.readFileSync(tokenPath, 'utf8'));
|
|
15
|
-
const token = config.api_token || '';
|
|
16
|
-
|
|
17
|
-
// 获取工具列表
|
|
18
|
-
const tools = await new Promise((resolve, reject) => {
|
|
19
|
-
http.get('http://localhost:8101/rpc/tools', {
|
|
20
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
21
|
-
}, (res) => {
|
|
22
|
-
let data = '';
|
|
23
|
-
res.on('data', chunk => data += chunk);
|
|
24
|
-
res.on('end', () => resolve(JSON.parse(data).tools));
|
|
25
|
-
}).on('error', reject);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// 获取 schemas
|
|
29
|
-
const schemas = await new Promise((resolve, reject) => {
|
|
30
|
-
http.get('http://localhost:8101/rpc/schemas', {
|
|
31
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
32
|
-
}, (res) => {
|
|
33
|
-
let data = '';
|
|
34
|
-
res.on('data', chunk => data += chunk);
|
|
35
|
-
res.on('end', () => resolve(JSON.parse(data).schemas));
|
|
36
|
-
}).on('error', reject);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return tools.map(tool => ({
|
|
40
|
-
...tool,
|
|
41
|
-
schema: schemas[tool.name] || { type: 'object' }
|
|
42
|
-
}));
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function generateOpenAPI() {
|
|
46
|
-
const tools = await getToolsWithSchemas();
|
|
47
|
-
|
|
48
|
-
const openapi = {
|
|
49
|
-
openapi: '3.0.0',
|
|
50
|
-
info: {
|
|
51
|
-
title: 'CiCy Desktop REST API',
|
|
52
|
-
version: '1.0.0',
|
|
53
|
-
description: `REST API for CiCy Desktop tools - ${tools.length} tools available`,
|
|
54
|
-
},
|
|
55
|
-
servers: [
|
|
56
|
-
{
|
|
57
|
-
url: 'http://localhost:8101',
|
|
58
|
-
description: 'Local server',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
url: 'https://gcp-8101.cicy.de5.net',
|
|
62
|
-
description: 'Remote server',
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
components: {
|
|
66
|
-
securitySchemes: {
|
|
67
|
-
bearerAuth: {
|
|
68
|
-
type: 'http',
|
|
69
|
-
scheme: 'bearer',
|
|
70
|
-
bearerFormat: 'token',
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
security: [{ bearerAuth: [] }],
|
|
75
|
-
paths: {}
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
// 添加 /rpc/tools 端点
|
|
79
|
-
openapi.paths['/rpc/tools'] = {
|
|
80
|
-
get: {
|
|
81
|
-
summary: 'List all available tools',
|
|
82
|
-
tags: ['Tools'],
|
|
83
|
-
security: [{ bearerAuth: [] }],
|
|
84
|
-
responses: {
|
|
85
|
-
200: {
|
|
86
|
-
description: 'List of tools',
|
|
87
|
-
content: {
|
|
88
|
-
'application/json': {
|
|
89
|
-
schema: {
|
|
90
|
-
type: 'object',
|
|
91
|
-
properties: {
|
|
92
|
-
tools: {
|
|
93
|
-
type: 'array',
|
|
94
|
-
items: {
|
|
95
|
-
type: 'object',
|
|
96
|
-
properties: {
|
|
97
|
-
name: { type: 'string' },
|
|
98
|
-
description: { type: 'string' }
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
// 为每个工具生成端点
|
|
112
|
-
for (const tool of tools) {
|
|
113
|
-
openapi.paths[`/rpc/${tool.name}`] = {
|
|
114
|
-
post: {
|
|
115
|
-
description: tool.description,
|
|
116
|
-
tags: ['Tools'],
|
|
117
|
-
security: [{ bearerAuth: [] }],
|
|
118
|
-
requestBody: {
|
|
119
|
-
required: true,
|
|
120
|
-
content: {
|
|
121
|
-
'application/json': {
|
|
122
|
-
schema: tool.schema
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
},
|
|
126
|
-
responses: {
|
|
127
|
-
200: {
|
|
128
|
-
description: 'Tool execution result',
|
|
129
|
-
content: {
|
|
130
|
-
'application/json': {
|
|
131
|
-
schema: {
|
|
132
|
-
type: 'object',
|
|
133
|
-
properties: {
|
|
134
|
-
content: {
|
|
135
|
-
type: 'array',
|
|
136
|
-
items: {
|
|
137
|
-
type: 'object',
|
|
138
|
-
properties: {
|
|
139
|
-
type: { type: 'string' },
|
|
140
|
-
text: { type: 'string' }
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
},
|
|
149
|
-
404: { description: 'Tool not found' },
|
|
150
|
-
500: { description: 'Execution error' }
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// 保存为 YAML
|
|
157
|
-
const yamlContent = yaml.dump(openapi, { lineWidth: -1 });
|
|
158
|
-
fs.writeFileSync('openapi.yml', yamlContent);
|
|
159
|
-
console.log('✅ Generated: openapi.yml');
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
generateOpenAPI().catch(console.error);
|
package/jest.config.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 CiCy AI
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
|
-
module.exports = {
|
|
5
|
-
testEnvironment: "node",
|
|
6
|
-
testMatch: ["<rootDir>/tests/**/*.test.js"],
|
|
7
|
-
testTimeout: 30000,
|
|
8
|
-
maxWorkers: 1,
|
|
9
|
-
globalSetup: "<rootDir>/jest.setup.global.js",
|
|
10
|
-
globalTeardown: "<rootDir>/jest.teardown.global.js",
|
|
11
|
-
forceExit: true,
|
|
12
|
-
detectOpenHandles: false,
|
|
13
|
-
};
|
package/jest.setup.global.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 CiCy AI
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
|
-
const { startTestServer } = require('./tests/mcp/setup-test-server');
|
|
5
|
-
|
|
6
|
-
module.exports = async () => {
|
|
7
|
-
console.log('\n🚀 Starting test server...\n');
|
|
8
|
-
try {
|
|
9
|
-
await startTestServer();
|
|
10
|
-
console.log('\n✅ Test server ready\n');
|
|
11
|
-
} catch (error) {
|
|
12
|
-
console.error('\n❌ Failed to start test server:', error.message);
|
|
13
|
-
console.log('\n⚠️ Continuing without SSE connection...\n');
|
|
14
|
-
// 不抛出错误,让测试继续(服务器已启动,只是 SSE 连接失败)
|
|
15
|
-
}
|
|
16
|
-
};
|
package/jest.teardown.global.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
// Copyright 2026 CiCy AI
|
|
2
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
-
|
|
4
|
-
const { stopTestServer } = require('./tests/mcp/setup-test-server');
|
|
5
|
-
|
|
6
|
-
module.exports = async () => {
|
|
7
|
-
console.log('\n🛑 Stopping test server...\n');
|
|
8
|
-
await stopTestServer();
|
|
9
|
-
console.log('\n✅ Test server stopped\n');
|
|
10
|
-
};
|
package/service.sh
DELETED
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# CiCy Desktop 服务管理脚本
|
|
4
|
-
|
|
5
|
-
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
6
|
-
PROJECT_DIR="$SCRIPT_DIR"
|
|
7
|
-
PID_FILE="$PROJECT_DIR/.cicy-desktop.pid"
|
|
8
|
-
LOG_FILE="$HOME/logs/cicy-desktop-service.log"
|
|
9
|
-
|
|
10
|
-
# 创建日志目录
|
|
11
|
-
mkdir -p "$(dirname "$LOG_FILE")"
|
|
12
|
-
|
|
13
|
-
# 显示帮助信息
|
|
14
|
-
show_help() {
|
|
15
|
-
echo "CiCy Desktop 服务管理"
|
|
16
|
-
echo ""
|
|
17
|
-
echo "用法: $0 {start|stop|restart|status|logs}"
|
|
18
|
-
echo ""
|
|
19
|
-
echo "命令:"
|
|
20
|
-
echo " start - 启动服务"
|
|
21
|
-
echo " stop - 停止服务"
|
|
22
|
-
echo " restart - 重启服务"
|
|
23
|
-
echo " status - 查看状态"
|
|
24
|
-
echo " logs - 查看日志"
|
|
25
|
-
echo ""
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
# 启动服务
|
|
29
|
-
start_service() {
|
|
30
|
-
if [ -f "$PID_FILE" ]; then
|
|
31
|
-
local pid=$(cat "$PID_FILE")
|
|
32
|
-
if ps -p "$pid" > /dev/null 2>&1; then
|
|
33
|
-
echo "✅ 服务已在运行 (PID: $pid)"
|
|
34
|
-
return 0
|
|
35
|
-
else
|
|
36
|
-
rm -f "$PID_FILE"
|
|
37
|
-
fi
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
echo "🚀 正在启动 CiCy Desktop 服务..."
|
|
41
|
-
|
|
42
|
-
cd "$PROJECT_DIR"
|
|
43
|
-
|
|
44
|
-
# 检查依赖
|
|
45
|
-
if [ ! -d "node_modules" ]; then
|
|
46
|
-
echo "📦 正在安装依赖..."
|
|
47
|
-
npm install
|
|
48
|
-
fi
|
|
49
|
-
|
|
50
|
-
# 后台启动服务
|
|
51
|
-
nohup npm start > "$LOG_FILE" 2>&1 &
|
|
52
|
-
local pid=$!
|
|
53
|
-
|
|
54
|
-
# 保存 PID
|
|
55
|
-
echo "$pid" > "$PID_FILE"
|
|
56
|
-
|
|
57
|
-
# 等待服务启动
|
|
58
|
-
sleep 3
|
|
59
|
-
|
|
60
|
-
if ps -p "$pid" > /dev/null 2>&1; then
|
|
61
|
-
echo "✅ 服务启动成功 (PID: $pid)"
|
|
62
|
-
echo "📋 端口: 8101"
|
|
63
|
-
echo "📋 日志: $LOG_FILE"
|
|
64
|
-
echo "📋 MCP 端点: http://localhost:8101/mcp"
|
|
65
|
-
echo "📋 API 文档: http://localhost:8101/docs"
|
|
66
|
-
else
|
|
67
|
-
echo "❌ 服务启动失败"
|
|
68
|
-
rm -f "$PID_FILE"
|
|
69
|
-
return 1
|
|
70
|
-
fi
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
# 停止服务
|
|
74
|
-
stop_service() {
|
|
75
|
-
if [ ! -f "$PID_FILE" ]; then
|
|
76
|
-
echo "⚠️ 服务未运行"
|
|
77
|
-
return 0
|
|
78
|
-
fi
|
|
79
|
-
|
|
80
|
-
local pid=$(cat "$PID_FILE")
|
|
81
|
-
|
|
82
|
-
if ps -p "$pid" > /dev/null 2>&1; then
|
|
83
|
-
echo "🛑 正在停止服务 (PID: $pid)..."
|
|
84
|
-
kill "$pid"
|
|
85
|
-
|
|
86
|
-
# 等待进程结束
|
|
87
|
-
local count=0
|
|
88
|
-
while ps -p "$pid" > /dev/null 2>&1 && [ $count -lt 10 ]; do
|
|
89
|
-
sleep 1
|
|
90
|
-
count=$((count + 1))
|
|
91
|
-
done
|
|
92
|
-
|
|
93
|
-
if ps -p "$pid" > /dev/null 2>&1; then
|
|
94
|
-
echo "⚠️ 强制停止服务..."
|
|
95
|
-
kill -9 "$pid"
|
|
96
|
-
fi
|
|
97
|
-
|
|
98
|
-
echo "✅ 服务已停止"
|
|
99
|
-
else
|
|
100
|
-
echo "⚠️ 服务进程不存在"
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
rm -f "$PID_FILE"
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
# 查看状态
|
|
107
|
-
show_status() {
|
|
108
|
-
if [ -f "$PID_FILE" ]; then
|
|
109
|
-
local pid=$(cat "$PID_FILE")
|
|
110
|
-
if ps -p "$pid" > /dev/null 2>&1; then
|
|
111
|
-
echo "✅ 服务运行中 (PID: $pid)"
|
|
112
|
-
echo "📋 端口: 8101"
|
|
113
|
-
echo "📋 日志: $LOG_FILE"
|
|
114
|
-
|
|
115
|
-
# 检查端口是否监听
|
|
116
|
-
if lsof -i :8101 > /dev/null 2>&1; then
|
|
117
|
-
echo "📋 端口 8101 正在监听"
|
|
118
|
-
else
|
|
119
|
-
echo "⚠️ 端口 8101 未监听"
|
|
120
|
-
fi
|
|
121
|
-
else
|
|
122
|
-
echo "❌ 服务进程不存在 (PID 文件存在但进程已死)"
|
|
123
|
-
rm -f "$PID_FILE"
|
|
124
|
-
fi
|
|
125
|
-
else
|
|
126
|
-
echo "⚠️ 服务未运行"
|
|
127
|
-
fi
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
# 查看日志
|
|
131
|
-
show_logs() {
|
|
132
|
-
if [ -f "$LOG_FILE" ]; then
|
|
133
|
-
echo "📋 日志文件: $LOG_FILE"
|
|
134
|
-
echo "----------------------------------------"
|
|
135
|
-
tail -f "$LOG_FILE"
|
|
136
|
-
else
|
|
137
|
-
echo "⚠️ 日志文件不存在: $LOG_FILE"
|
|
138
|
-
fi
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
# 主逻辑
|
|
142
|
-
case "$1" in
|
|
143
|
-
start)
|
|
144
|
-
start_service
|
|
145
|
-
;;
|
|
146
|
-
stop)
|
|
147
|
-
stop_service
|
|
148
|
-
;;
|
|
149
|
-
restart)
|
|
150
|
-
stop_service
|
|
151
|
-
sleep 2
|
|
152
|
-
start_service
|
|
153
|
-
;;
|
|
154
|
-
status)
|
|
155
|
-
show_status
|
|
156
|
-
;;
|
|
157
|
-
logs)
|
|
158
|
-
show_logs
|
|
159
|
-
;;
|
|
160
|
-
*)
|
|
161
|
-
show_help
|
|
162
|
-
exit 1
|
|
163
|
-
;;
|
|
164
|
-
esac
|
package/update-desktop.sh
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
echo "🔄 更新桌面启动脚本..."
|
|
4
|
-
|
|
5
|
-
# 设置路径
|
|
6
|
-
DESKTOP_FILE="$HOME/Desktop/cicy-desktop.command"
|
|
7
|
-
SOURCE_FILE="./cicy-desktop-simple.command"
|
|
8
|
-
|
|
9
|
-
# 备份现有文件
|
|
10
|
-
if [ -f "$DESKTOP_FILE" ]; then
|
|
11
|
-
echo "📋 备份现有文件..."
|
|
12
|
-
cp "$DESKTOP_FILE" "$DESKTOP_FILE.old"
|
|
13
|
-
fi
|
|
14
|
-
|
|
15
|
-
# 复制新文件
|
|
16
|
-
echo "📁 复制新文件..."
|
|
17
|
-
cp "$SOURCE_FILE" "$DESKTOP_FILE"
|
|
18
|
-
|
|
19
|
-
# 设置权限
|
|
20
|
-
echo "🔐 设置执行权限..."
|
|
21
|
-
chmod +x "$DESKTOP_FILE"
|
|
22
|
-
|
|
23
|
-
# 验证
|
|
24
|
-
if [ -f "$DESKTOP_FILE" ] && [ -x "$DESKTOP_FILE" ]; then
|
|
25
|
-
echo "✅ 更新完成!"
|
|
26
|
-
echo "📁 文件: $DESKTOP_FILE"
|
|
27
|
-
echo "🔐 权限: $(ls -l "$DESKTOP_FILE" | cut -d' ' -f1)"
|
|
28
|
-
echo ""
|
|
29
|
-
echo "现在可以双击桌面上的 cicy-desktop.command 启动服务了!"
|
|
30
|
-
else
|
|
31
|
-
echo "❌ 更新失败"
|
|
32
|
-
exit 1
|
|
33
|
-
fi
|