gpteam 0.1.0 → 0.1.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 CHANGED
@@ -6,7 +6,7 @@ Interactive GPTeam API client configurator.
6
6
  npx gpteam
7
7
  ```
8
8
 
9
- The CLI asks for an API key, detects available models, benchmarks all production ingress endpoints with real API requests, then writes the selected client configuration after backing up existing files.
9
+ The CLI asks for an API key, detects available models, benchmarks all production ingress endpoints with real API requests, then backs up old files and writes the selected client configuration.
10
10
 
11
11
  Supported clients:
12
12
 
package/lib/cli.js CHANGED
@@ -20,7 +20,7 @@ export async function runCli(argv = []) {
20
20
  const rl = readline.createInterface({ input, output });
21
21
  try {
22
22
  console.log('GPTeam API 配置助手');
23
- console.log('会先做真实 API 测速,再写入客户端配置;旧配置会自动备份。\n');
23
+ console.log('接下来会用你的 key 跑几次真实请求测速,然后把选中的入口写进客户端配置。原来的配置会先备份。\n');
24
24
 
25
25
  const apiKey = args.key || args.apiKey || await askRequired(rl, '请输入 API key:');
26
26
  const client = await choose(rl, '请选择客户端类型', CLIENTS, args.client);
@@ -43,6 +43,7 @@ export async function runCli(argv = []) {
43
43
 
44
44
  const recommended = results.find((item) => item.successRate > 0) || results[0];
45
45
  const selectedNode = await chooseNode(rl, results, args.node, recommended && recommended.node.id);
46
+ assertNodeConfig(selectedNode);
46
47
  const written = writeClientConfig(client.id, {
47
48
  apiKey,
48
49
  model: model.id,
@@ -54,7 +55,8 @@ export async function runCli(argv = []) {
54
55
 
55
56
  console.log('\n已写入配置:');
56
57
  for (const filePath of written) console.log(`- ${filePath}`);
57
- console.log(`入口:${selectedNode.label}(${describeSplit(selectedNode)}) ${selectedNode.baseUrl}`);
58
+ console.log(`入口:${formatNodeLabel(selectedNode)}`);
59
+ console.log(`地址:${selectedNode.baseUrl}`);
58
60
  } finally {
59
61
  rl.close();
60
62
  }
@@ -117,7 +119,7 @@ async function chooseModel(rl, models, preferred) {
117
119
  if (selected) return selected;
118
120
  console.log('\n可用模型:');
119
121
  models.forEach((model, index) => {
120
- console.log(`${index + 1}. ${model.id}(上下文 ${model.contextLength},输出 ${model.maxOutputTokens})`);
122
+ console.log(`${index + 1}. ${formatModelLabel(model)}`);
121
123
  });
122
124
  const answer = await askRequired(rl, '请选择模型序号:');
123
125
  const index = Math.max(1, Math.min(models.length, Number(answer) || 1)) - 1;
@@ -127,11 +129,11 @@ async function chooseModel(rl, models, preferred) {
127
129
  async function askContextLength(rl, model, preferred) {
128
130
  const max = Number(model.contextLength || 400000);
129
131
  if (preferred) return clamp(Number(preferred), 1, max);
130
- const answer = await rl.question(`请输入上下文长度(最大 ${max},输出上限 ${model.maxOutputTokens},默认 ${max}):`);
132
+ const answer = await rl.question(`请输入上下文长度(最大 ${max},输出上限 ${model.maxOutputTokens},默认 ${max},回车即选择默认):`);
131
133
  return clamp(Number(answer || max), 1, max);
132
134
  }
133
135
 
134
- async function chooseNode(rl, results, preferred, recommendedID) {
136
+ export async function chooseNode(rl, results, preferred, recommendedID) {
135
137
  const nodes = results.map((item) => item.node);
136
138
  const preferredNode = nodes.find((node) => node.id === preferred);
137
139
  if (preferredNode) return preferredNode;
@@ -140,19 +142,20 @@ async function chooseNode(rl, results, preferred, recommendedID) {
140
142
  }
141
143
  return (await choose(rl, '请选择最终写入的入口', nodes.map((node) => ({
142
144
  id: node.id,
143
- label: `${node.label}(${describeSplit(node)})`
145
+ label: formatNodeLabel(node),
146
+ raw: node
144
147
  })))).raw;
145
148
  }
146
149
 
147
150
  async function choose(rl, title, items, preferred) {
148
151
  const found = items.find((item) => item.id === preferred);
149
- if (found) return { ...found, raw: found };
152
+ if (found) return { ...found, raw: found.raw || found };
150
153
  console.log(`\n${title}:`);
151
154
  items.forEach((item, index) => console.log(`${index + 1}. ${item.label}`));
152
155
  const answer = await askRequired(rl, '请输入序号:');
153
156
  const index = Math.max(1, Math.min(items.length, Number(answer) || 1)) - 1;
154
157
  const item = items[index];
155
- return { ...item, raw: item };
158
+ return { ...item, raw: item.raw || item };
156
159
  }
157
160
 
158
161
  async function askRequired(rl, prompt) {
@@ -180,6 +183,22 @@ function clamp(value, min, max) {
180
183
  return Math.max(min, Math.min(max, Math.floor(value)));
181
184
  }
182
185
 
186
+ export function formatModelLabel(model) {
187
+ const context = Number(model.contextLength || 0);
188
+ const outputTokens = Number(model.maxOutputTokens || 0);
189
+ return `${model.id}(输入上下文 ${context},输出上限 ${outputTokens})`;
190
+ }
191
+
192
+ export function formatNodeLabel(node) {
193
+ return `${node.label}(${describeSplit(node)})`;
194
+ }
195
+
196
+ export function assertNodeConfig(node) {
197
+ if (!node || !node.baseUrl) {
198
+ throw new Error('入口配置异常:缺少 baseUrl,已停止写入客户端配置');
199
+ }
200
+ }
201
+
183
202
  function toCamel(value) {
184
203
  return value.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
185
204
  }
package/lib/help.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export const PACKAGE_NAME = 'gpteam';
2
- export const PACKAGE_VERSION = '0.1.0';
2
+ export const PACKAGE_VERSION = '0.1.1';
3
3
 
4
4
  export function getHelpText() {
5
5
  return [
@@ -21,6 +21,6 @@ export function getHelpText() {
21
21
  ' --help 显示帮助',
22
22
  ' --version 显示版本',
23
23
  '',
24
- '说明:测速会真实请求 GET /api/health 和流式 POST /v1/responses,旧配置写入前会自动备份。'
24
+ '说明:测速会请求 GET /api/health 和流式 POST /v1/responses。写新配置前会先备份旧配置。'
25
25
  ].join('\n');
26
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gpteam",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "GPTeam API interactive client configurator and ingress benchmark CLI.",
5
5
  "type": "module",
6
6
  "bin": {