ccnew 0.1.10 → 0.1.12
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 +28 -28
- package/build/icon.ico +0 -0
- package/build/icon.png +0 -0
- package/core/constants.js +1 -1
- package/core/desktop-service.js +4 -4
- package/core/desktop-state.js +1 -1
- package/core/index.js +10 -7
- package/desktop/assets/fml-icon.png +0 -0
- package/desktop/assets/march-mark.svg +15 -18
- package/desktop/main.js +4 -4
- package/desktop/renderer/app.js +1 -1
- package/desktop/renderer/index.html +4 -4
- package/package.json +8 -8
- package/scripts/desktop-pack-win.mjs +4 -4
- package/scripts/postinstall.mjs +8 -8
- package/scripts/prepublish-check.mjs +3 -3
- package/site/assets/fml-icon.png +0 -0
- package/site/assets/march-mark.svg +15 -18
- package/site/index.html +18 -18
- package/src/App.tsx +113 -11
- package/src/components/layout/app-sidebar.tsx +7 -7
- package/src/components/ui/logo-mark.tsx +17 -19
- package/src/features/prompts/prompts-view.tsx +1 -1
- package/src/lib/client.ts +4 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ccnew
|
|
2
2
|
|
|
3
|
-
`
|
|
3
|
+
`ccnew` is a relay configuration manager for:
|
|
4
4
|
|
|
5
5
|
- Codex
|
|
6
6
|
- OpenCode
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
It exposes one install command and one primary setup command:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
npm i -g
|
|
13
|
-
|
|
12
|
+
npm i -g ccnew
|
|
13
|
+
ccnew fhl
|
|
14
14
|
```
|
|
15
15
|
|
|
16
16
|
## Main Commands
|
|
@@ -18,52 +18,52 @@ ccon fhl
|
|
|
18
18
|
Quick setup:
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
ccnew fhl
|
|
22
|
+
ccnew fhl sk-your-key
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
Interactive menu:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
ccnew
|
|
29
|
+
ccnew menu
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
Standard setup:
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
ccnew setup -k sk-your-key
|
|
36
|
+
ccnew setup --preset fhl -k sk-your-key
|
|
37
37
|
```
|
|
38
38
|
|
|
39
39
|
Platform management:
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
ccnew cx list
|
|
43
|
+
ccnew cx current
|
|
44
|
+
ccnew cx add -n fhl -u https://www.fhl.mom -k sk-xxx --model gpt-5.4
|
|
45
|
+
ccnew cx use fhl
|
|
46
|
+
ccnew oc list
|
|
47
|
+
ccnew ow list
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
Presets and probe:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
ccnew preset list
|
|
54
|
+
ccnew preset add -n team-a --provider-name teama --base-url https://example.com
|
|
55
|
+
ccnew preset use team-a -k sk-xxx -p codex,opencode
|
|
56
|
+
ccnew probe -u https://www.fhl.mom -u https://www.fhl.mom/v1
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
## Defaults
|
|
60
60
|
|
|
61
61
|
- Codex / OpenCode route: `https://www.fhl.mom`
|
|
62
62
|
- OpenClaw route: `https://www.fhl.mom/v1`
|
|
63
|
-
- Primary setup command: `
|
|
63
|
+
- Primary setup command: `ccnew fhl`
|
|
64
64
|
- Default provider name: `fhl`
|
|
65
65
|
|
|
66
|
-
`
|
|
66
|
+
`ccnew fhl` follows the old `gmn1` style selection flow when `--platform` is omitted:
|
|
67
67
|
|
|
68
68
|
- `Codex` checked by default
|
|
69
69
|
- `OpenCode` checked by default
|
|
@@ -89,12 +89,12 @@ npm run desktop:check
|
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
npm pack
|
|
92
|
-
npm uninstall -g
|
|
93
|
-
npm install -g .\\
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
92
|
+
npm uninstall -g ccnew
|
|
93
|
+
npm install -g .\\ccnew-0.1.12.tgz
|
|
94
|
+
ccnew --help
|
|
95
|
+
ccnew fhl --help
|
|
96
|
+
ccnew gmn1 --help
|
|
97
|
+
ccnew fhl sk-demo-1234 --platform codex --no-probe
|
|
98
98
|
```
|
|
99
99
|
|
|
100
100
|
## Publish
|
package/build/icon.ico
CHANGED
|
Binary file
|
package/build/icon.png
CHANGED
|
Binary file
|
package/core/constants.js
CHANGED
package/core/desktop-service.js
CHANGED
|
@@ -121,8 +121,8 @@ export function getDesktopSnapshot() {
|
|
|
121
121
|
const routing = buildRoutingSnapshot(buildRoutingContexts());
|
|
122
122
|
|
|
123
123
|
return {
|
|
124
|
-
appName: "
|
|
125
|
-
version: "0.1.
|
|
124
|
+
appName: "ccnew",
|
|
125
|
+
version: "0.1.12",
|
|
126
126
|
generatedAt: new Date().toISOString(),
|
|
127
127
|
models: MODEL_DEFINITIONS,
|
|
128
128
|
platforms: SUPPORTED_PLATFORMS.map((platform) =>
|
|
@@ -361,8 +361,8 @@ export function exportPresetsToDesktop(filePath) {
|
|
|
361
361
|
}
|
|
362
362
|
|
|
363
363
|
writeJson(targetPath, {
|
|
364
|
-
appName: "
|
|
365
|
-
version: "0.1.
|
|
364
|
+
appName: "ccnew",
|
|
365
|
+
version: "0.1.12",
|
|
366
366
|
exportedAt: new Date().toISOString(),
|
|
367
367
|
presets: listPresets()
|
|
368
368
|
});
|
package/core/desktop-state.js
CHANGED
|
@@ -132,7 +132,7 @@ function buildManagedPromptContent(prompts, platformLabel) {
|
|
|
132
132
|
)
|
|
133
133
|
.join("\n\n");
|
|
134
134
|
|
|
135
|
-
return `${PROMPT_MARKER_BEGIN}\n#
|
|
135
|
+
return `${PROMPT_MARKER_BEGIN}\n# ccnew ${platformLabel} prompts\n\n${body}\n${PROMPT_MARKER_END}\n`;
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
function inferMcpDescription(entry) {
|
package/core/index.js
CHANGED
|
@@ -38,6 +38,9 @@ import { getPreset, listPresets, removePreset, upsertPreset } from "./presets.js
|
|
|
38
38
|
|
|
39
39
|
const CLI_ENTRY_NAME = (() => {
|
|
40
40
|
const script = `${process.argv[1] || ""}`.toLowerCase();
|
|
41
|
+
if (script.includes("ccnew")) {
|
|
42
|
+
return "ccnew";
|
|
43
|
+
}
|
|
41
44
|
if (script.includes("ccon")) {
|
|
42
45
|
return "ccon";
|
|
43
46
|
}
|
|
@@ -69,10 +72,10 @@ function printSuccessBanner() {
|
|
|
69
72
|
function printCliBanner() {
|
|
70
73
|
const width = 60;
|
|
71
74
|
const lines = [
|
|
72
|
-
{ text: "
|
|
75
|
+
{ text: "ccnew", color: chalk.hex("#f4ede3") },
|
|
73
76
|
{ text: "quiet relay setup for Codex / OpenCode / OpenClaw", color: chalk.hex("#b8ab9a") },
|
|
74
77
|
{ text: "route https://www.fhl.mom", color: chalk.hex("#d8c19a") },
|
|
75
|
-
{ text: "start
|
|
78
|
+
{ text: "start ccnew fhl", color: chalk.hex("#e7b36b") }
|
|
76
79
|
];
|
|
77
80
|
|
|
78
81
|
const borderColor = chalk.hex("#7b6a58");
|
|
@@ -278,7 +281,7 @@ async function resolveShortcutPlatformsLikeGmn1(platformsArg) {
|
|
|
278
281
|
choices: [
|
|
279
282
|
{ name: "Codex(需单独订阅 OpenAI 套餐)", value: "codex" },
|
|
280
283
|
{ name: "OpenCode(与 Codex 共享 OpenAI 套餐)", value: "opencode" },
|
|
281
|
-
{ name: "OpenClaw(
|
|
284
|
+
{ name: "OpenClaw(ccnew /v1 端点,默认不选中)", value: "openclaw" },
|
|
282
285
|
{ name: "全部(将依次配置 Codex、OpenCode、OpenClaw)", value: "all" }
|
|
283
286
|
],
|
|
284
287
|
default: ["codex", "opencode"],
|
|
@@ -432,7 +435,7 @@ async function runSetup(rawOptions = {}) {
|
|
|
432
435
|
console.log(chalk.gray(`使用预设: ${options._resolvedPreset.name}`));
|
|
433
436
|
}
|
|
434
437
|
} else {
|
|
435
|
-
printHeader("
|
|
438
|
+
printHeader("ccnew cli setup");
|
|
436
439
|
if (options._resolvedPreset) {
|
|
437
440
|
console.log(chalk.gray(`使用预设: ${options._resolvedPreset.name}`));
|
|
438
441
|
}
|
|
@@ -1123,7 +1126,7 @@ async function runMainMenu() {
|
|
|
1123
1126
|
{
|
|
1124
1127
|
type: "list",
|
|
1125
1128
|
name: "action",
|
|
1126
|
-
message: "
|
|
1129
|
+
message: "ccnew menu",
|
|
1127
1130
|
choices: [
|
|
1128
1131
|
{ name: "快速安装", value: "setup" },
|
|
1129
1132
|
{ name: "自定义安装", value: "advanced-setup" },
|
|
@@ -1163,8 +1166,8 @@ async function runMainMenu() {
|
|
|
1163
1166
|
const program = new Command();
|
|
1164
1167
|
program
|
|
1165
1168
|
.name(CLI_ENTRY_NAME)
|
|
1166
|
-
.description("
|
|
1167
|
-
.version("0.1.
|
|
1169
|
+
.description("ccnew relay manager")
|
|
1170
|
+
.version("0.1.12");
|
|
1168
1171
|
|
|
1169
1172
|
program
|
|
1170
1173
|
.command("menu")
|
|
Binary file
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
2
|
<defs>
|
|
3
|
-
<linearGradient id="
|
|
4
|
-
<stop stop-color="#
|
|
5
|
-
<stop offset="0.
|
|
6
|
-
<stop offset="1" stop-color="#
|
|
3
|
+
<linearGradient id="ccnew-bg" x1="16" y1="12" x2="108" y2="116" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#FFF3E4"/>
|
|
5
|
+
<stop offset="0.52" stop-color="#EFC597"/>
|
|
6
|
+
<stop offset="1" stop-color="#CD7B4A"/>
|
|
7
7
|
</linearGradient>
|
|
8
|
-
<radialGradient id="
|
|
9
|
-
<stop stop-color="#
|
|
10
|
-
<stop offset="1" stop-color="#
|
|
8
|
+
<radialGradient id="ccnew-glow" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(96 28) rotate(135) scale(42)">
|
|
9
|
+
<stop stop-color="#F7A56B" stop-opacity="0.86"/>
|
|
10
|
+
<stop offset="1" stop-color="#F7A56B" stop-opacity="0"/>
|
|
11
11
|
</radialGradient>
|
|
12
|
-
<linearGradient id="
|
|
13
|
-
<stop stop-color="#
|
|
14
|
-
<stop offset="1" stop-color="#
|
|
12
|
+
<linearGradient id="ccnew-highlight" x1="90" y1="24" x2="110" y2="44" gradientUnits="userSpaceOnUse">
|
|
13
|
+
<stop stop-color="#FFF5EA"/>
|
|
14
|
+
<stop offset="1" stop-color="#FFF5EA" stop-opacity="0.2"/>
|
|
15
15
|
</linearGradient>
|
|
16
16
|
</defs>
|
|
17
|
-
<rect x="8" y="8" width="112" height="112" rx="30" fill="url(#
|
|
17
|
+
<rect x="8" y="8" width="112" height="112" rx="30" fill="url(#ccnew-bg)"/>
|
|
18
18
|
<rect x="8.75" y="8.75" width="110.5" height="110.5" rx="29.25" stroke="rgba(255,255,255,0.12)" stroke-width="1.5"/>
|
|
19
|
-
<circle cx="96" cy="28" r="30" fill="url(#
|
|
20
|
-
<path d="
|
|
21
|
-
<path d="
|
|
22
|
-
<path d="
|
|
23
|
-
<path d="M60 92V36L74 62L88 36V92" stroke="url(#fml-stroke)" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
24
|
-
<path d="M102 36V92" stroke="#F3C46C" stroke-width="10" stroke-linecap="round"/>
|
|
25
|
-
<path d="M88 92H102" stroke="#F3C46C" stroke-width="10" stroke-linecap="round"/>
|
|
19
|
+
<circle cx="96" cy="28" r="30" fill="url(#ccnew-glow)" opacity="0.62"/>
|
|
20
|
+
<path d="M50 30C36.75 30 26 44.33 26 64C26 83.67 36.75 98 50 98" stroke="#4B2A1A" stroke-width="11.5" stroke-linecap="round"/>
|
|
21
|
+
<path d="M90 30C76.75 30 66 44.33 66 64C66 83.67 76.75 98 90 98" stroke="#4B2A1A" stroke-width="11.5" stroke-linecap="round"/>
|
|
22
|
+
<path d="M90 30C97.58 30 102.66 34.72 105.04 39.42" stroke="url(#ccnew-highlight)" stroke-width="4.5" stroke-linecap="round"/>
|
|
26
23
|
</svg>
|
package/desktop/main.js
CHANGED
|
@@ -70,7 +70,7 @@ async function openPathFromDesktop(targetPath) {
|
|
|
70
70
|
|
|
71
71
|
async function choosePresetImportPath() {
|
|
72
72
|
const result = await dialog.showOpenDialog({
|
|
73
|
-
title: "导入
|
|
73
|
+
title: "导入 ccnew 预设",
|
|
74
74
|
properties: ["openFile"],
|
|
75
75
|
filters: [{ name: "JSON", extensions: ["json"] }]
|
|
76
76
|
});
|
|
@@ -84,8 +84,8 @@ async function choosePresetImportPath() {
|
|
|
84
84
|
|
|
85
85
|
async function choosePresetExportPath() {
|
|
86
86
|
const result = await dialog.showSaveDialog({
|
|
87
|
-
title: "导出
|
|
88
|
-
defaultPath: path.join(os.homedir(), `
|
|
87
|
+
title: "导出 ccnew 预设",
|
|
88
|
+
defaultPath: path.join(os.homedir(), `ccnew-presets-${new Date().toISOString().slice(0, 10)}.json`),
|
|
89
89
|
filters: [{ name: "JSON", extensions: ["json"] }]
|
|
90
90
|
});
|
|
91
91
|
|
|
@@ -129,7 +129,7 @@ function createWindow() {
|
|
|
129
129
|
minHeight: 760,
|
|
130
130
|
backgroundColor: "#f4efe6",
|
|
131
131
|
autoHideMenuBar: true,
|
|
132
|
-
title: "
|
|
132
|
+
title: "ccnew",
|
|
133
133
|
icon: windowIcon,
|
|
134
134
|
webPreferences: {
|
|
135
135
|
preload: path.join(__dirname, "preload.cjs"),
|
package/desktop/renderer/app.js
CHANGED
|
@@ -203,7 +203,7 @@ function populateForm(platform) {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
function renderHeader(platform) {
|
|
206
|
-
heroTitle.textContent = `
|
|
206
|
+
heroTitle.textContent = `ccnew / ${platform.label}`;
|
|
207
207
|
heroSubtitle.textContent = `保存 ${platform.providerCount} 个 Provider,当前启用 ${platform.currentProviderName || "无"}。`;
|
|
208
208
|
}
|
|
209
209
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>
|
|
6
|
+
<title>ccnew</title>
|
|
7
7
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
9
9
|
<link
|
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
<div class="shell">
|
|
17
17
|
<aside class="sidebar">
|
|
18
18
|
<div class="brand">
|
|
19
|
-
<img src="../assets/fml-icon.png" alt="
|
|
19
|
+
<img src="../assets/fml-icon.png" alt="ccnew" />
|
|
20
20
|
<div>
|
|
21
|
-
<strong>
|
|
21
|
+
<strong>ccnew</strong>
|
|
22
22
|
<span>relay desktop</span>
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
<header class="hero">
|
|
37
37
|
<div>
|
|
38
38
|
<span class="eyebrow">Desktop Control Panel</span>
|
|
39
|
-
<h1 id="heroTitle">
|
|
39
|
+
<h1 id="heroTitle">ccnew</h1>
|
|
40
40
|
<p id="heroSubtitle">统一管理 Provider、写入本地配置、测速和快速切换。</p>
|
|
41
41
|
</div>
|
|
42
42
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ccnew",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.12",
|
|
4
|
+
"description": "ccnew relay manager for Codex, OpenCode, and OpenClaw.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "desktop/main.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"
|
|
8
|
+
"ccnew": "core/index.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"core",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"config",
|
|
48
48
|
"cli"
|
|
49
49
|
],
|
|
50
|
-
"author": "
|
|
50
|
+
"author": "ccnew",
|
|
51
51
|
"license": "MIT",
|
|
52
52
|
"engines": {
|
|
53
53
|
"node": ">=18.0.0"
|
|
@@ -77,9 +77,9 @@
|
|
|
77
77
|
"vite": "^7.1.12"
|
|
78
78
|
},
|
|
79
79
|
"build": {
|
|
80
|
-
"appId": "cn.
|
|
81
|
-
"productName": "
|
|
82
|
-
"executableName": "
|
|
80
|
+
"appId": "cn.ccnew.desktop",
|
|
81
|
+
"productName": "ccnew",
|
|
82
|
+
"executableName": "ccnew",
|
|
83
83
|
"npmRebuild": false,
|
|
84
84
|
"directories": {
|
|
85
85
|
"output": "release",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"nsis",
|
|
101
101
|
"portable"
|
|
102
102
|
],
|
|
103
|
-
"artifactName": "
|
|
103
|
+
"artifactName": "ccnew-${version}-${arch}.${ext}"
|
|
104
104
|
},
|
|
105
105
|
"nsis": {
|
|
106
106
|
"oneClick": false,
|
|
@@ -6,7 +6,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6
6
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
7
|
const __dirname = path.dirname(__filename);
|
|
8
8
|
const rootDir = path.resolve(__dirname, "..");
|
|
9
|
-
const outputDir = path.join(rootDir, "release", "
|
|
9
|
+
const outputDir = path.join(rootDir, "release", "ccnew-win-unpacked");
|
|
10
10
|
const appDir = path.join(outputDir, "resources", "app");
|
|
11
11
|
const electronDist = path.join(rootDir, "node_modules", "electron", "dist");
|
|
12
12
|
|
|
@@ -58,8 +58,8 @@ async function main() {
|
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
const electronExe = path.join(outputDir, "electron.exe");
|
|
61
|
-
const
|
|
62
|
-
await fs.copyFile(electronExe,
|
|
61
|
+
const ccnewExe = path.join(outputDir, "ccnew.exe");
|
|
62
|
+
await fs.copyFile(electronExe, ccnewExe);
|
|
63
63
|
await fs.rm(electronExe, { force: true });
|
|
64
64
|
|
|
65
65
|
for (const entry of copyEntries) {
|
|
@@ -68,7 +68,7 @@ async function main() {
|
|
|
68
68
|
|
|
69
69
|
await fs.writeFile(
|
|
70
70
|
path.join(outputDir, "PACKED_BY.txt"),
|
|
71
|
-
`
|
|
71
|
+
`ccnew windows package\ncreatedAt=${new Date().toISOString()}\nmode=custom-electron-copy\n`,
|
|
72
72
|
"utf8"
|
|
73
73
|
);
|
|
74
74
|
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -27,22 +27,22 @@ function blue(text) {
|
|
|
27
27
|
const banner = [
|
|
28
28
|
"",
|
|
29
29
|
blue(".--------------------------------------------------------------."),
|
|
30
|
-
`${blue("|")} ${cyan("
|
|
30
|
+
`${blue("|")} ${cyan("ccnew".padEnd(60, " "))} ${blue("|")}`,
|
|
31
31
|
`${blue("|")} ${dim("quiet relay setup for Codex / OpenCode / OpenClaw".padEnd(60, " "))} ${blue("|")}`,
|
|
32
32
|
`${blue("|")} ${green("route https://www.fhl.mom".padEnd(60, " "))} ${blue("|")}`,
|
|
33
|
-
`${blue("|")} ${yellow("start
|
|
33
|
+
`${blue("|")} ${yellow("start ccnew fhl".padEnd(60, " "))} ${blue("|")}`,
|
|
34
34
|
blue("'--------------------------------------------------------------'"),
|
|
35
35
|
"",
|
|
36
36
|
" Quick Start:",
|
|
37
|
-
` ${cyan("npm i -g
|
|
38
|
-
` ${cyan("
|
|
37
|
+
` ${cyan("npm i -g ccnew")}`,
|
|
38
|
+
` ${cyan("ccnew fhl")}`,
|
|
39
39
|
"",
|
|
40
40
|
" Useful Commands:",
|
|
41
|
-
` ${cyan("
|
|
42
|
-
` ${cyan("
|
|
43
|
-
` ${cyan("
|
|
41
|
+
` ${cyan("ccnew --help")}`,
|
|
42
|
+
` ${cyan("ccnew fhl --help")}`,
|
|
43
|
+
` ${cyan("ccnew preset --help")}`,
|
|
44
44
|
"",
|
|
45
|
-
dim(" If install output looks quiet, run `
|
|
45
|
+
dim(" If install output looks quiet, run `ccnew --help` to verify the CLI is ready."),
|
|
46
46
|
""
|
|
47
47
|
];
|
|
48
48
|
|
|
@@ -39,11 +39,11 @@ if (DEFAULT_OPENCLAW_BASE_URL !== "https://www.fhl.mom/v1") {
|
|
|
39
39
|
throw new Error(`Unexpected OpenClaw base URL: ${DEFAULT_OPENCLAW_BASE_URL}`);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
assertContains("site/index.html", "
|
|
42
|
+
assertContains("site/index.html", "ccnew");
|
|
43
43
|
assertContains("site/index.html", "https://www.fhl.mom");
|
|
44
44
|
assertContains("site/index.html", "https://www.fhl.mom/v1");
|
|
45
|
-
assertContains("site/index.html", "
|
|
46
|
-
assertContains("desktop/renderer/index.html", "
|
|
45
|
+
assertContains("site/index.html", "ccnew fhl");
|
|
46
|
+
assertContains("desktop/renderer/index.html", "ccnew");
|
|
47
47
|
assertContains("desktop/renderer/index.html", "https://www.fhl.mom");
|
|
48
48
|
|
|
49
49
|
run("CLI syntax check", process.execPath, ["--check", "./core/index.js"]);
|
package/site/assets/fml-icon.png
CHANGED
|
Binary file
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
<svg width="128" height="128" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
2
|
<defs>
|
|
3
|
-
<linearGradient id="
|
|
4
|
-
<stop stop-color="#
|
|
5
|
-
<stop offset="0.
|
|
6
|
-
<stop offset="1" stop-color="#
|
|
3
|
+
<linearGradient id="ccnew-bg" x1="16" y1="12" x2="108" y2="116" gradientUnits="userSpaceOnUse">
|
|
4
|
+
<stop stop-color="#FFF3E4"/>
|
|
5
|
+
<stop offset="0.52" stop-color="#EFC597"/>
|
|
6
|
+
<stop offset="1" stop-color="#CD7B4A"/>
|
|
7
7
|
</linearGradient>
|
|
8
|
-
<radialGradient id="
|
|
9
|
-
<stop stop-color="#
|
|
10
|
-
<stop offset="1" stop-color="#
|
|
8
|
+
<radialGradient id="ccnew-glow" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(96 28) rotate(135) scale(42)">
|
|
9
|
+
<stop stop-color="#F7A56B" stop-opacity="0.86"/>
|
|
10
|
+
<stop offset="1" stop-color="#F7A56B" stop-opacity="0"/>
|
|
11
11
|
</radialGradient>
|
|
12
|
-
<linearGradient id="
|
|
13
|
-
<stop stop-color="#
|
|
14
|
-
<stop offset="1" stop-color="#
|
|
12
|
+
<linearGradient id="ccnew-highlight" x1="90" y1="24" x2="110" y2="44" gradientUnits="userSpaceOnUse">
|
|
13
|
+
<stop stop-color="#FFF5EA"/>
|
|
14
|
+
<stop offset="1" stop-color="#FFF5EA" stop-opacity="0.2"/>
|
|
15
15
|
</linearGradient>
|
|
16
16
|
</defs>
|
|
17
|
-
<rect x="8" y="8" width="112" height="112" rx="30" fill="url(#
|
|
17
|
+
<rect x="8" y="8" width="112" height="112" rx="30" fill="url(#ccnew-bg)"/>
|
|
18
18
|
<rect x="8.75" y="8.75" width="110.5" height="110.5" rx="29.25" stroke="rgba(255,255,255,0.12)" stroke-width="1.5"/>
|
|
19
|
-
<circle cx="96" cy="28" r="30" fill="url(#
|
|
20
|
-
<path d="
|
|
21
|
-
<path d="
|
|
22
|
-
<path d="
|
|
23
|
-
<path d="M60 92V36L74 62L88 36V92" stroke="url(#fml-stroke)" stroke-width="10" stroke-linecap="round" stroke-linejoin="round"/>
|
|
24
|
-
<path d="M102 36V92" stroke="#F3C46C" stroke-width="10" stroke-linecap="round"/>
|
|
25
|
-
<path d="M88 92H102" stroke="#F3C46C" stroke-width="10" stroke-linecap="round"/>
|
|
19
|
+
<circle cx="96" cy="28" r="30" fill="url(#ccnew-glow)" opacity="0.62"/>
|
|
20
|
+
<path d="M50 30C36.75 30 26 44.33 26 64C26 83.67 36.75 98 50 98" stroke="#4B2A1A" stroke-width="11.5" stroke-linecap="round"/>
|
|
21
|
+
<path d="M90 30C76.75 30 66 44.33 66 64C66 83.67 76.75 98 90 98" stroke="#4B2A1A" stroke-width="11.5" stroke-linecap="round"/>
|
|
22
|
+
<path d="M90 30C97.58 30 102.66 34.72 105.04 39.42" stroke="url(#ccnew-highlight)" stroke-width="4.5" stroke-linecap="round"/>
|
|
26
23
|
</svg>
|
package/site/index.html
CHANGED
|
@@ -3,10 +3,10 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>
|
|
6
|
+
<title>ccnew | 下载与界面预览</title>
|
|
7
7
|
<meta
|
|
8
8
|
name="description"
|
|
9
|
-
content="
|
|
9
|
+
content="ccnew 是一个面向 Codex、OpenCode 与 OpenClaw 的统一配置桌面端,支持一键接入 www.fhl.mom。"
|
|
10
10
|
/>
|
|
11
11
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
12
12
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
@@ -19,10 +19,10 @@
|
|
|
19
19
|
<body>
|
|
20
20
|
<div class="page-shell">
|
|
21
21
|
<header class="topbar">
|
|
22
|
-
<a class="brand" href="#hero" aria-label="
|
|
23
|
-
<img src="./assets/fml-icon.png" alt="
|
|
22
|
+
<a class="brand" href="#hero" aria-label="ccnew">
|
|
23
|
+
<img src="./assets/fml-icon.png" alt="ccnew" />
|
|
24
24
|
<span class="brand-copy">
|
|
25
|
-
<strong>
|
|
25
|
+
<strong>ccnew</strong>
|
|
26
26
|
<em>Relay Desktop</em>
|
|
27
27
|
</span>
|
|
28
28
|
</a>
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
<div class="hero-copy">
|
|
43
43
|
<div class="hero-eyebrow">
|
|
44
44
|
<span class="eyebrow-dot"></span>
|
|
45
|
-
<span>
|
|
45
|
+
<span>ccnew Relay Workspace</span>
|
|
46
46
|
</div>
|
|
47
47
|
<h1>客户只装一个包,只记一条命令。</h1>
|
|
48
48
|
<p>
|
|
49
|
-
客户安装 <code>
|
|
49
|
+
客户安装 <code>ccnew</code> 后执行 <code>ccnew fhl</code>,默认就会把 Codex、OpenCode 接到
|
|
50
50
|
<code>https://www.fhl.mom</code>,OpenClaw 走 <code>https://www.fhl.mom/v1</code>,并按
|
|
51
51
|
<code>gmn1</code> 的交互逻辑选择要配置的平台。
|
|
52
52
|
</p>
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
</ul>
|
|
73
73
|
|
|
74
74
|
<div class="command-strip" aria-label="Quick Start Commands">
|
|
75
|
-
<code>npm i -g
|
|
76
|
-
<code>
|
|
75
|
+
<code>npm i -g ccnew</code>
|
|
76
|
+
<code>ccnew fhl</code>
|
|
77
77
|
</div>
|
|
78
78
|
</div>
|
|
79
79
|
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
|
|
88
88
|
<article class="console-metric">
|
|
89
89
|
<span class="hero-card-label">Quick Setup</span>
|
|
90
|
-
<strong>
|
|
90
|
+
<strong>ccnew fhl</strong>
|
|
91
91
|
<p>默认勾选 Codex + OpenCode,OpenClaw 保持可选,不再全部强塞进去。</p>
|
|
92
92
|
</article>
|
|
93
93
|
</div>
|
|
@@ -99,12 +99,12 @@
|
|
|
99
99
|
<span></span>
|
|
100
100
|
<span></span>
|
|
101
101
|
</div>
|
|
102
|
-
<small>
|
|
102
|
+
<small>ccnew / Quick Flow</small>
|
|
103
103
|
</div>
|
|
104
104
|
|
|
105
105
|
<div class="terminal-lines">
|
|
106
|
-
<div class="terminal-line prompt">$ npm i -g
|
|
107
|
-
<div class="terminal-line prompt">$
|
|
106
|
+
<div class="terminal-line prompt">$ npm i -g ccnew</div>
|
|
107
|
+
<div class="terminal-line prompt">$ ccnew fhl</div>
|
|
108
108
|
<div class="terminal-line note">[x] Codex [x] OpenCode [ ] OpenClaw</div>
|
|
109
109
|
<div class="terminal-line success">route ready -> https://www.fhl.mom</div>
|
|
110
110
|
</div>
|
|
@@ -132,7 +132,7 @@
|
|
|
132
132
|
<div class="sidebar-brand">
|
|
133
133
|
<img src="./assets/march-mark.svg" alt="" />
|
|
134
134
|
<div>
|
|
135
|
-
<strong>
|
|
135
|
+
<strong>ccnew</strong>
|
|
136
136
|
<span>Relay Desktop</span>
|
|
137
137
|
</div>
|
|
138
138
|
</div>
|
|
@@ -248,17 +248,17 @@
|
|
|
248
248
|
</div>
|
|
249
249
|
|
|
250
250
|
<div class="download-grid">
|
|
251
|
-
<a class="download-card active" data-platform="windows" href="/downloads/
|
|
251
|
+
<a class="download-card active" data-platform="windows" href="/downloads/ccnew-windows-x64.exe">
|
|
252
252
|
<strong>Windows x64</strong>
|
|
253
253
|
<span>.exe Installer</span>
|
|
254
254
|
<small>推荐首发版本</small>
|
|
255
255
|
</a>
|
|
256
|
-
<a class="download-card" data-platform="macos" href="/downloads/
|
|
256
|
+
<a class="download-card" data-platform="macos" href="/downloads/ccnew-macos.dmg">
|
|
257
257
|
<strong>macOS</strong>
|
|
258
258
|
<span>.dmg Installer</span>
|
|
259
259
|
<small>Apple Silicon / Intel</small>
|
|
260
260
|
</a>
|
|
261
|
-
<a class="download-card" data-platform="linux" href="/downloads/
|
|
261
|
+
<a class="download-card" data-platform="linux" href="/downloads/ccnew-linux.AppImage">
|
|
262
262
|
<strong>Linux</strong>
|
|
263
263
|
<span>.AppImage</span>
|
|
264
264
|
<small>无需额外安装器</small>
|
|
@@ -284,7 +284,7 @@
|
|
|
284
284
|
<article>
|
|
285
285
|
<span>03</span>
|
|
286
286
|
<h3>品牌露出统一</h3>
|
|
287
|
-
<p>外显品牌统一到
|
|
287
|
+
<p>外显品牌统一到 ccnew,命令入口和桌面名称保持一致,观感更完整。</p>
|
|
288
288
|
</article>
|
|
289
289
|
</section>
|
|
290
290
|
|
package/src/App.tsx
CHANGED
|
@@ -167,16 +167,71 @@ function platformLabel(id: PlatformId) {
|
|
|
167
167
|
return "OpenClaw";
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
type NoteTone = "brand" | "info" | "success" | "warn";
|
|
171
|
+
|
|
172
|
+
function noteToneClasses(tone: NoteTone) {
|
|
173
|
+
if (tone === "info") {
|
|
174
|
+
return {
|
|
175
|
+
card: "border-[#cfe2ff] bg-[#f5f9ff]",
|
|
176
|
+
title: "text-[#245ea8]",
|
|
177
|
+
body: "text-[#44627f]"
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
if (tone === "success") {
|
|
181
|
+
return {
|
|
182
|
+
card: "border-[#cfe7d8] bg-[#f5fbf7]",
|
|
183
|
+
title: "text-[#2f7a58]",
|
|
184
|
+
body: "text-[#4a6a5d]"
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
if (tone === "warn") {
|
|
188
|
+
return {
|
|
189
|
+
card: "border-[#ecd8c8] bg-[#fff6ef]",
|
|
190
|
+
title: "text-[#a3572c]",
|
|
191
|
+
body: "text-[#7d5a43]"
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
195
|
+
card: "border-[#eadbcd] bg-[#fcf6ef]",
|
|
196
|
+
title: "text-[#8e5631]",
|
|
197
|
+
body: "text-[#6e533f]"
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function NoteCard(props: { title: string; tone?: NoteTone; children: any }) {
|
|
202
|
+
const tone = noteToneClasses(props.tone || "brand");
|
|
203
|
+
return (
|
|
204
|
+
<div className={cx("rounded-[24px] border px-4 py-4 shadow-[0_18px_40px_rgba(115,75,43,0.06)]", tone.card)}>
|
|
205
|
+
<div className={cx("text-[11px] font-semibold uppercase tracking-[0.22em]", tone.title)}>{props.title}</div>
|
|
206
|
+
<div className={cx("mt-3 space-y-2 text-sm leading-6", tone.body)}>{props.children}</div>
|
|
207
|
+
</div>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function FieldHint(props: { children: any }) {
|
|
212
|
+
return <p className="mt-2 text-xs leading-6 text-[#7d624d]">{props.children}</p>;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function StatusNote(props: { text: string | null }) {
|
|
216
|
+
if (!props.text) return null;
|
|
217
|
+
|
|
218
|
+
const tone: NoteTone =
|
|
219
|
+
/失败|不可用|删除|错误/.test(props.text) ? "warn" : /已保存|已应用|已导入|已导出|已打开|可连通/.test(props.text) ? "success" : "info";
|
|
220
|
+
const classes = noteToneClasses(tone);
|
|
221
|
+
|
|
222
|
+
return <div className={cx("rounded-2xl border px-4 py-3 text-xs leading-6", classes.card, classes.body)}>{props.text}</div>;
|
|
223
|
+
}
|
|
224
|
+
|
|
170
225
|
function BrandMark() {
|
|
171
226
|
return (
|
|
172
|
-
<div className="relative grid h-14 w-14 place-items-center overflow-hidden rounded-[
|
|
173
|
-
<div className="absolute inset-[
|
|
227
|
+
<div className="relative grid h-14 w-14 place-items-center overflow-hidden rounded-[22px] bg-[linear-gradient(155deg,#fff3e4_0%,#efc597_46%,#cd7b4a_100%)] shadow-[0_22px_44px_rgba(126,72,39,0.24)] ring-1 ring-[#f4dcc3]">
|
|
228
|
+
<div className="absolute inset-[5px] rounded-[18px] bg-[linear-gradient(180deg,rgba(255,255,255,0.28),rgba(255,255,255,0.02))]" />
|
|
229
|
+
<div className="absolute right-[8px] top-[8px] h-3.5 w-3.5 rounded-full bg-[#f07b49]/85 blur-[0.5px]" />
|
|
230
|
+
{/* 参考 Claude 的暖调极简产品气质,但保持 ccnew 自己的双 C 识别。 */}
|
|
174
231
|
<svg viewBox="0 0 64 64" className="relative h-8 w-8" fill="none" aria-hidden="true">
|
|
175
|
-
<path d="
|
|
176
|
-
<path d="
|
|
177
|
-
<path d="
|
|
178
|
-
<path d="M35 48V16L44 33L53 16V48" stroke="#d8fbf2" strokeWidth="5.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
179
|
-
<path d="M58 16V48H48" stroke="#f3c46c" strokeWidth="5.5" strokeLinecap="round" strokeLinejoin="round" />
|
|
232
|
+
<path d="M26 13C18.27 13 12 21.06 12 32C12 42.94 18.27 51 26 51" stroke="#4b2a1a" strokeWidth="6.5" strokeLinecap="round" />
|
|
233
|
+
<path d="M50 13C42.27 13 36 21.06 36 32C36 42.94 42.27 51 50 51" stroke="#4b2a1a" strokeWidth="6.5" strokeLinecap="round" />
|
|
234
|
+
<path d="M50 13C54.42 13 57.39 15.76 58.78 18.5" stroke="#fff5ea" strokeOpacity="0.72" strokeWidth="3" strokeLinecap="round" />
|
|
180
235
|
</svg>
|
|
181
236
|
</div>
|
|
182
237
|
);
|
|
@@ -656,7 +711,7 @@ export default function App() {
|
|
|
656
711
|
{platform.label} {workspace.activeSectionMeta.title}
|
|
657
712
|
</h2>
|
|
658
713
|
<p className="mt-2 max-w-2xl text-sm leading-6 text-slate-500">
|
|
659
|
-
{activeSection === "providers" ? "这里支持新增、编辑、切换、刷新和连通性检测,配置会立即回写工作区。" : "布局参考 CC Switch 的信息结构,同时延续
|
|
714
|
+
{activeSection === "providers" ? "这里支持新增、编辑、切换、刷新和连通性检测,配置会立即回写工作区。" : "布局参考 CC Switch 的信息结构,同时延续 ccnew 的产品化品牌风格。"}
|
|
660
715
|
</p>
|
|
661
716
|
</div>
|
|
662
717
|
|
|
@@ -706,6 +761,12 @@ export default function App() {
|
|
|
706
761
|
|
|
707
762
|
{activeSection === "providers" ? (
|
|
708
763
|
<div className="mt-6 space-y-4">
|
|
764
|
+
<NoteCard title="中文注释" tone="brand">
|
|
765
|
+
<div>这里把“配置”和“写入结果”放在同一页,第一次用时不用来回翻文件。</div>
|
|
766
|
+
<div>如果只是给客户走一键接入,优先记住两步:先装包,再执行 <code className="rounded bg-white/70 px-1.5 py-0.5 text-[11px] text-[#7a4f35]">ccnew fhl</code>。</div>
|
|
767
|
+
<div>需要精调时再改服务商名称、基础地址和模型,避免把首次配置做成一页复杂参数表。</div>
|
|
768
|
+
</NoteCard>
|
|
769
|
+
|
|
709
770
|
<section className="rounded-[24px] border border-slate-200/80 bg-slate-50 px-5 py-4">
|
|
710
771
|
<div className="flex flex-wrap items-start justify-between gap-4">
|
|
711
772
|
<div>
|
|
@@ -769,7 +830,9 @@ export default function App() {
|
|
|
769
830
|
</div>
|
|
770
831
|
))}
|
|
771
832
|
</div>
|
|
772
|
-
|
|
833
|
+
<div className="mt-3">
|
|
834
|
+
<StatusNote text={presetMessage} />
|
|
835
|
+
</div>
|
|
773
836
|
</section>
|
|
774
837
|
|
|
775
838
|
<section className="rounded-[24px] border border-slate-200/80 bg-slate-50 px-5 py-4">
|
|
@@ -1042,7 +1105,7 @@ export default function App() {
|
|
|
1042
1105
|
</div>
|
|
1043
1106
|
</div>
|
|
1044
1107
|
))}
|
|
1045
|
-
|
|
1108
|
+
<StatusNote text={targetPathMessage} />
|
|
1046
1109
|
</div>
|
|
1047
1110
|
</section>
|
|
1048
1111
|
</aside>
|
|
@@ -1070,6 +1133,12 @@ export default function App() {
|
|
|
1070
1133
|
submit();
|
|
1071
1134
|
}}
|
|
1072
1135
|
>
|
|
1136
|
+
<NoteCard title="中文说明" tone="brand">
|
|
1137
|
+
<div>基础地址填当前服务商的主入口即可;如果你后面切到 OpenClaw,系统会按它的 /v1 线路处理。</div>
|
|
1138
|
+
<div>“测试地址”只做连通性检查,不会立刻改写配置文件。</div>
|
|
1139
|
+
<div>如果你想沿用已有路由,可以先点“从当前导入”,再只改需要变动的字段。</div>
|
|
1140
|
+
</NoteCard>
|
|
1141
|
+
|
|
1073
1142
|
<label className="block">
|
|
1074
1143
|
<div className="mb-2 text-sm font-medium text-slate-600">服务商名称</div>
|
|
1075
1144
|
<input
|
|
@@ -1078,6 +1147,7 @@ export default function App() {
|
|
|
1078
1147
|
placeholder="default"
|
|
1079
1148
|
className="h-12 w-full rounded-2xl border border-slate-200 bg-[#fbfbfc] px-4 text-sm text-slate-900 outline-none transition focus:border-[#1677ff] focus:bg-white"
|
|
1080
1149
|
/>
|
|
1150
|
+
<FieldHint>中文注释:这个名字会出现在路由列表里,建议用能一眼认出的客户名或中转名。</FieldHint>
|
|
1081
1151
|
</label>
|
|
1082
1152
|
<label className="block">
|
|
1083
1153
|
<div className="mb-2 text-sm font-medium text-slate-600">基础地址</div>
|
|
@@ -1087,8 +1157,11 @@ export default function App() {
|
|
|
1087
1157
|
placeholder="https://api.openai.com"
|
|
1088
1158
|
className="h-12 w-full rounded-2xl border border-slate-200 bg-[#fbfbfc] px-4 text-sm text-slate-900 outline-none transition focus:border-[#1677ff] focus:bg-white"
|
|
1089
1159
|
/>
|
|
1160
|
+
<FieldHint>中文注释:Codex / OpenCode 走主地址;如果目标是 FHL,就填 <code className="rounded bg-white px-1.5 py-0.5 text-[11px] text-[#7a4f35]">https://www.fhl.mom</code>。</FieldHint>
|
|
1090
1161
|
<div className="mt-3 flex items-center justify-between gap-3">
|
|
1091
|
-
<div className="
|
|
1162
|
+
<div className="min-w-0 flex-1">
|
|
1163
|
+
<StatusNote text={candidateProbeText || "可先测试地址可用性,再保存。"} />
|
|
1164
|
+
</div>
|
|
1092
1165
|
<button
|
|
1093
1166
|
type="button"
|
|
1094
1167
|
onClick={probeCandidateBaseUrl}
|
|
@@ -1108,6 +1181,7 @@ export default function App() {
|
|
|
1108
1181
|
placeholder="sk-..."
|
|
1109
1182
|
className="h-12 w-full rounded-2xl border border-slate-200 bg-[#fbfbfc] px-4 text-sm text-slate-900 outline-none transition focus:border-[#1677ff] focus:bg-white"
|
|
1110
1183
|
/>
|
|
1184
|
+
<FieldHint>中文注释:这里填真实密钥;如果你只是改地址和模型,最好先从当前路由导入,避免把已保存密钥覆盖成空值。</FieldHint>
|
|
1111
1185
|
</label>
|
|
1112
1186
|
<label className="block">
|
|
1113
1187
|
<div className="mb-2 text-sm font-medium text-slate-600">模型</div>
|
|
@@ -1122,6 +1196,7 @@ export default function App() {
|
|
|
1122
1196
|
</option>
|
|
1123
1197
|
))}
|
|
1124
1198
|
</select>
|
|
1199
|
+
<FieldHint>中文注释:默认先用 <code className="rounded bg-white px-1.5 py-0.5 text-[11px] text-[#7a4f35]">gpt-5.4</code> 更稳,客户记忆成本最低。</FieldHint>
|
|
1125
1200
|
</label>
|
|
1126
1201
|
<div className="flex items-center justify-end gap-3 pt-3">
|
|
1127
1202
|
<button type="button" onClick={closeDialog} className="inline-flex h-11 items-center justify-center rounded-2xl border border-slate-200 px-5 text-sm font-medium text-slate-600 transition hover:border-slate-300 hover:text-slate-900">
|
|
@@ -1205,6 +1280,28 @@ export default function App() {
|
|
|
1205
1280
|
submitResourceEditor();
|
|
1206
1281
|
}}
|
|
1207
1282
|
>
|
|
1283
|
+
<NoteCard title="填写建议" tone="info">
|
|
1284
|
+
{resourceEditor.kind === "mcp" ? (
|
|
1285
|
+
<>
|
|
1286
|
+
<div>stdio 模式填写 command / args;HTTP 模式填写 URL / headers,不要两套一起混填。</div>
|
|
1287
|
+
<div>环境变量和请求头都按 <code className="rounded bg-white/80 px-1.5 py-0.5 text-[11px] text-[#335c8a]">KEY=VALUE</code> 一行一个填写。</div>
|
|
1288
|
+
<div>启用平台决定这个 MCP 会在哪些客户端出现,没勾的平台不会加载。</div>
|
|
1289
|
+
</>
|
|
1290
|
+
) : resourceEditor.kind === "prompt" ? (
|
|
1291
|
+
<>
|
|
1292
|
+
<div>描述里建议写清用途和边界,方便后面回头看时知道这段提示词是干什么的。</div>
|
|
1293
|
+
<div>如果希望多个客户端共用,就把作用范围选成“全局”;只想影响单个平台时再单独选。</div>
|
|
1294
|
+
<div>提示词内容建议直接写完整版本,减少后续拼接造成的歧义。</div>
|
|
1295
|
+
</>
|
|
1296
|
+
) : (
|
|
1297
|
+
<>
|
|
1298
|
+
<div>技能名称尽量和目录最后一级一致,后面排查时更容易对上。</div>
|
|
1299
|
+
<div>技能目录建议填稳定路径,不要依赖临时下载目录。</div>
|
|
1300
|
+
<div>启用平台只是控制显示和加载范围,不会移动你的实际技能文件。</div>
|
|
1301
|
+
</>
|
|
1302
|
+
)}
|
|
1303
|
+
</NoteCard>
|
|
1304
|
+
|
|
1208
1305
|
{resourceEditor.kind === "mcp" ? (
|
|
1209
1306
|
<>
|
|
1210
1307
|
<label className="block">
|
|
@@ -1275,6 +1372,7 @@ export default function App() {
|
|
|
1275
1372
|
<option value="stdio">stdio</option>
|
|
1276
1373
|
<option value="http">http</option>
|
|
1277
1374
|
</select>
|
|
1375
|
+
<FieldHint>中文注释:本地命令型 MCP 选 stdio;远端服务型 MCP 选 http。</FieldHint>
|
|
1278
1376
|
</label>
|
|
1279
1377
|
{resourceEditor.transport === "stdio" ? (
|
|
1280
1378
|
<>
|
|
@@ -1329,6 +1427,7 @@ export default function App() {
|
|
|
1329
1427
|
rows={4}
|
|
1330
1428
|
className="w-full rounded-2xl border border-slate-200 bg-[#fbfbfc] px-4 py-3 text-sm text-slate-900 outline-none transition focus:border-[#1677ff] focus:bg-white"
|
|
1331
1429
|
/>
|
|
1430
|
+
<FieldHint>中文注释:每行一个环境变量,例如 <code className="rounded bg-white px-1.5 py-0.5 text-[11px] text-[#7a4f35]">TOKEN=xxx</code>。</FieldHint>
|
|
1332
1431
|
</label>
|
|
1333
1432
|
</>
|
|
1334
1433
|
) : (
|
|
@@ -1358,6 +1457,7 @@ export default function App() {
|
|
|
1358
1457
|
rows={4}
|
|
1359
1458
|
className="w-full rounded-2xl border border-slate-200 bg-[#fbfbfc] px-4 py-3 text-sm text-slate-900 outline-none transition focus:border-[#1677ff] focus:bg-white"
|
|
1360
1459
|
/>
|
|
1460
|
+
<FieldHint>中文注释:请求头也是每行一个键值,常见写法如 <code className="rounded bg-white px-1.5 py-0.5 text-[11px] text-[#7a4f35]">Authorization=Bearer ...</code>。</FieldHint>
|
|
1361
1461
|
</label>
|
|
1362
1462
|
</>
|
|
1363
1463
|
)}
|
|
@@ -1444,6 +1544,7 @@ export default function App() {
|
|
|
1444
1544
|
</option>
|
|
1445
1545
|
))}
|
|
1446
1546
|
</select>
|
|
1547
|
+
<FieldHint>中文注释:全局会对所有客户端生效;如果只是给某个平台加专用提示词,就单独选那个平台。</FieldHint>
|
|
1447
1548
|
</label>
|
|
1448
1549
|
<label className="flex items-center gap-3 rounded-2xl border border-slate-200 bg-[#fbfbfc] px-4 py-3">
|
|
1449
1550
|
<input
|
|
@@ -1473,6 +1574,7 @@ export default function App() {
|
|
|
1473
1574
|
placeholder="例如:openai-docs"
|
|
1474
1575
|
className="h-12 w-full rounded-2xl border border-slate-200 bg-[#fbfbfc] px-4 text-sm text-slate-900 outline-none transition focus:border-[#1677ff] focus:bg-white"
|
|
1475
1576
|
/>
|
|
1577
|
+
<FieldHint>中文注释:推荐填绝对路径或固定技能仓库目录,避免下次启动找不到。</FieldHint>
|
|
1476
1578
|
</label>
|
|
1477
1579
|
<label className="block">
|
|
1478
1580
|
<div className="mb-2 text-sm font-medium text-slate-600">描述</div>
|
|
@@ -19,8 +19,8 @@ export function AppSidebar(props: {
|
|
|
19
19
|
<div className="flex items-center gap-3 px-2">
|
|
20
20
|
<LogoMark />
|
|
21
21
|
<div>
|
|
22
|
-
<div className="text-[11px] font-semibold uppercase tracking-[0.34em] text-
|
|
23
|
-
<div className="font-['Space_Grotesk'] text-xl font-bold text-slate-50">
|
|
22
|
+
<div className="text-[11px] font-semibold uppercase tracking-[0.34em] text-[#c9a27e]">ccnew</div>
|
|
23
|
+
<div className="font-['Space_Grotesk'] text-xl font-bold text-slate-50">Relay</div>
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
26
|
|
|
@@ -45,14 +45,14 @@ export function AppSidebar(props: {
|
|
|
45
45
|
className={clsx(
|
|
46
46
|
"flex w-full items-center gap-3 rounded-2xl border px-3 py-3 text-left transition",
|
|
47
47
|
item.id === props.activePlatform
|
|
48
|
-
? "border-
|
|
48
|
+
? "border-[#d6b08a]/30 bg-[#c98a5a]/[0.12]"
|
|
49
49
|
: "border-white/6 bg-white/[0.02] hover:bg-white/[0.045]"
|
|
50
50
|
)}
|
|
51
51
|
>
|
|
52
52
|
<div
|
|
53
53
|
className={clsx(
|
|
54
54
|
"rounded-xl p-2",
|
|
55
|
-
item.id === props.activePlatform ? "bg-
|
|
55
|
+
item.id === props.activePlatform ? "bg-[#c98a5a]/15 text-[#f6d4b6]" : "bg-slate-900/70 text-slate-400"
|
|
56
56
|
)}
|
|
57
57
|
>
|
|
58
58
|
<Icon className="h-4 w-4" />
|
|
@@ -92,10 +92,10 @@ export function AppSidebar(props: {
|
|
|
92
92
|
</div>
|
|
93
93
|
</div>
|
|
94
94
|
|
|
95
|
-
<div className="mt-auto rounded-[24px] border border-
|
|
96
|
-
<div className="text-[11px] uppercase tracking-[0.3em] text-
|
|
95
|
+
<div className="mt-auto rounded-[24px] border border-[#d6b08a]/20 bg-gradient-to-br from-[#fff1e2]/[0.09] to-[#c98a5a]/[0.08] p-4">
|
|
96
|
+
<div className="text-[11px] uppercase tracking-[0.3em] text-[#e2c2a5]/75">Visual Target</div>
|
|
97
97
|
<div className="mt-3 text-sm font-medium leading-6 text-slate-200">
|
|
98
|
-
|
|
98
|
+
Warm, branded, and easier to scan at first glance. Keep the structure tight, but make the tone feel like a real product.
|
|
99
99
|
</div>
|
|
100
100
|
</div>
|
|
101
101
|
</aside>
|
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
export function LogoMark() {
|
|
2
2
|
return (
|
|
3
|
-
<div className="h-11 w-11 drop-shadow-[0_16px_30px_rgba(
|
|
3
|
+
<div className="h-11 w-11 drop-shadow-[0_16px_30px_rgba(126,72,39,0.24)]">
|
|
4
4
|
<svg viewBox="0 0 128 128" className="h-11 w-11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
5
|
<defs>
|
|
6
|
-
<linearGradient id="
|
|
7
|
-
<stop stopColor="#
|
|
8
|
-
<stop offset="0.
|
|
9
|
-
<stop offset="1" stopColor="#
|
|
6
|
+
<linearGradient id="ccnew-bg-react" x1="16" y1="12" x2="108" y2="116" gradientUnits="userSpaceOnUse">
|
|
7
|
+
<stop stopColor="#FFF3E4" />
|
|
8
|
+
<stop offset="0.52" stopColor="#EFC597" />
|
|
9
|
+
<stop offset="1" stopColor="#CD7B4A" />
|
|
10
10
|
</linearGradient>
|
|
11
|
-
<radialGradient id="
|
|
12
|
-
<stop stopColor="#
|
|
13
|
-
<stop offset="1" stopColor="#
|
|
11
|
+
<radialGradient id="ccnew-glow-react" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(96 28) rotate(135) scale(42)">
|
|
12
|
+
<stop stopColor="#F7A56B" stopOpacity="0.86" />
|
|
13
|
+
<stop offset="1" stopColor="#F7A56B" stopOpacity="0" />
|
|
14
14
|
</radialGradient>
|
|
15
|
-
<linearGradient id="
|
|
16
|
-
<stop stopColor="#
|
|
17
|
-
<stop offset="1" stopColor="#
|
|
15
|
+
<linearGradient id="ccnew-highlight-react" x1="90" y1="24" x2="110" y2="44" gradientUnits="userSpaceOnUse">
|
|
16
|
+
<stop stopColor="#FFF5EA" />
|
|
17
|
+
<stop offset="1" stopColor="#FFF5EA" stopOpacity="0.2" />
|
|
18
18
|
</linearGradient>
|
|
19
19
|
</defs>
|
|
20
|
-
<rect x="8" y="8" width="112" height="112" rx="30" fill="url(#
|
|
20
|
+
<rect x="8" y="8" width="112" height="112" rx="30" fill="url(#ccnew-bg-react)" />
|
|
21
21
|
<rect x="8.75" y="8.75" width="110.5" height="110.5" rx="29.25" stroke="rgba(255,255,255,0.12)" strokeWidth="1.5" />
|
|
22
|
-
<circle cx="96" cy="28" r="30" fill="url(#
|
|
23
|
-
|
|
24
|
-
<path d="
|
|
25
|
-
<path d="
|
|
26
|
-
<path d="
|
|
27
|
-
<path d="M88 92H102" stroke="#F3C46C" strokeWidth="10" strokeLinecap="round" />
|
|
28
|
-
<path d="M102 36V92" stroke="#F3C46C" strokeWidth="10" strokeLinecap="round" />
|
|
22
|
+
<circle cx="96" cy="28" r="30" fill="url(#ccnew-glow-react)" opacity="0.62" />
|
|
23
|
+
{/* 暖色底配双 C 几何符号,桌面图标缩小时也能识别。 */}
|
|
24
|
+
<path d="M50 30C36.75 30 26 44.33 26 64C26 83.67 36.75 98 50 98" stroke="#4B2A1A" strokeWidth="11.5" strokeLinecap="round" />
|
|
25
|
+
<path d="M90 30C76.75 30 66 44.33 66 64C66 83.67 76.75 98 90 98" stroke="#4B2A1A" strokeWidth="11.5" strokeLinecap="round" />
|
|
26
|
+
<path d="M90 30C97.58 30 102.66 34.72 105.04 39.42" stroke="url(#ccnew-highlight-react)" strokeWidth="4.5" strokeLinecap="round" />
|
|
29
27
|
</svg>
|
|
30
28
|
</div>
|
|
31
29
|
);
|
|
@@ -31,7 +31,7 @@ export function PromptsView() {
|
|
|
31
31
|
Prompt editor
|
|
32
32
|
</h2>
|
|
33
33
|
<div className="mt-5 rounded-[20px] border border-white/6 bg-[#0b121a] p-4 text-sm leading-7 text-slate-300">
|
|
34
|
-
You are a coding assistant for
|
|
34
|
+
You are a coding assistant for ccnew. Prioritize provider workflows, desktop release preparation,
|
|
35
35
|
route health, and concrete implementation over abstract planning.
|
|
36
36
|
</div>
|
|
37
37
|
</article>
|
package/src/lib/client.ts
CHANGED
|
@@ -178,8 +178,8 @@ function createInitialState(): StoredSnapshot {
|
|
|
178
178
|
];
|
|
179
179
|
|
|
180
180
|
return {
|
|
181
|
-
appName: "
|
|
182
|
-
version: "0.1.
|
|
181
|
+
appName: "ccnew",
|
|
182
|
+
version: "0.1.12",
|
|
183
183
|
generatedAt: now(),
|
|
184
184
|
models: [...DEFAULT_MODELS],
|
|
185
185
|
platforms,
|
|
@@ -279,8 +279,8 @@ async function getSnapshotInternal(): Promise<AppSnapshot> {
|
|
|
279
279
|
if (bridge) {
|
|
280
280
|
const response = (await bridge.getSnapshot()) as DesktopSnapshotResponse;
|
|
281
281
|
const snapshot: AppSnapshot = {
|
|
282
|
-
appName: response.appName || "
|
|
283
|
-
version: response.version || "0.1.
|
|
282
|
+
appName: response.appName || "ccnew",
|
|
283
|
+
version: response.version || "0.1.12",
|
|
284
284
|
generatedAt: response.generatedAt || now(),
|
|
285
285
|
models: sanitizeModels((response.models || []).map((item) => (typeof item === "string" ? item : item?.id || "")).filter(Boolean)),
|
|
286
286
|
platforms: response.platforms || [],
|