gpteam 0.1.3 → 0.1.4

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
@@ -8,6 +8,8 @@ npx gpteam
8
8
 
9
9
  The CLI asks for an API key, validates it with `/v1/models`, detects available models, benchmarks all production ingress endpoints with real API requests, then backs up old files and writes the selected client configuration. The next steps are blocked until the key validation succeeds. Ingress endpoints are benchmarked in parallel, while rounds for the same endpoint remain sequential to keep real API request pressure bounded. Failed benchmark rows show their error reason in the result table.
10
10
 
11
+ Recommendation order is deterministic: success rate first, then a latency score using first SSE event, total completion time, and health-check time. Model prompts use "configurable context" wording because the value is written to the client-side Codex `model_context_window`; it must not be confused with a public marketing total-window label.
12
+
11
13
  Codex config writing follows the same safety pattern as cc-switch: keep top-level fields separate from provider tables, preserve unrelated sections such as MCP servers, and stop before writing if the generated TOML would contain duplicate keys.
12
14
 
13
15
  Supported clients:
package/lib/bench.js CHANGED
@@ -13,7 +13,7 @@ export async function benchmarkNodes(nodes, options) {
13
13
  }
14
14
  return summarizeNode(node, samples);
15
15
  }));
16
- return results.sort((a, b) => scoreResult(a) - scoreResult(b));
16
+ return results.sort(compareResults);
17
17
  }
18
18
 
19
19
  export async function benchmarkNode(node, options) {
@@ -50,9 +50,17 @@ export function formatMs(value) {
50
50
  return `${(value / 1000).toFixed(2)}s`;
51
51
  }
52
52
 
53
- function scoreResult(result) {
54
- if (!result.successRate) return Number.MAX_SAFE_INTEGER;
55
- return (result.firstEventMs || 999999) + (result.totalMs || 999999) - result.successRate * 1000;
53
+ function compareResults(a, b) {
54
+ const successDelta = b.successRate - a.successRate;
55
+ if (successDelta !== 0) return successDelta;
56
+ return scoreLatency(a) - scoreLatency(b);
57
+ }
58
+
59
+ function scoreLatency(result) {
60
+ const firstEventMs = Number.isFinite(result.firstEventMs) ? result.firstEventMs : 999999;
61
+ const totalMs = Number.isFinite(result.totalMs) ? result.totalMs : 999999;
62
+ const healthMs = Number.isFinite(result.healthMs) ? result.healthMs : 999999;
63
+ return firstEventMs * 0.6 + totalMs * 0.35 + healthMs * 0.05;
56
64
  }
57
65
 
58
66
  async function measureHealth(url) {
package/lib/cli.js CHANGED
@@ -35,6 +35,7 @@ export async function runCli(argv = []) {
35
35
 
36
36
  console.log('\n开始真实测速:GET /api/health + POST /v1/responses stream=true');
37
37
  console.log('测速会按入口并行执行,每个入口内部仍按轮次顺序执行,避免同时打出过多真实请求。');
38
+ console.log('推荐规则:成功率优先,其次按首包、完成、健康检查的综合延迟排序。');
38
39
  console.log(`模型:${model.id},测速输出上限:${maxOutputTokens}`);
39
40
  const results = await benchmarkNodes(INGRESS_NODES, {
40
41
  apiKey,
@@ -123,7 +124,7 @@ async function chooseModel(rl, models, preferred) {
123
124
  async function askContextLength(rl, model, preferred) {
124
125
  const max = Number(model.contextLength || 400000);
125
126
  if (preferred) return clamp(Number(preferred), 1, max);
126
- const answer = await rl.question(`请输入上下文窗口(最大 ${max},输出上限 ${model.maxOutputTokens},默认 ${max},回车即选择默认):`);
127
+ const answer = await rl.question(`请输入可配置上下文长度(最大 ${max},输出上限 ${model.maxOutputTokens},默认 ${max},回车即选择默认):`);
127
128
  return clamp(Number(answer || max), 1, max);
128
129
  }
129
130
 
@@ -180,7 +181,7 @@ function clamp(value, min, max) {
180
181
  export function formatModelLabel(model) {
181
182
  const context = Number(model.contextLength || 0);
182
183
  const outputTokens = Number(model.maxOutputTokens || 0);
183
- return `${model.id}(上下文窗口 ${context},输出上限 ${outputTokens})`;
184
+ return `${model.id}(可配置上下文 ${context},输出上限 ${outputTokens})`;
184
185
  }
185
186
 
186
187
  export function formatNodeLabel(node) {
package/lib/help.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export const PACKAGE_NAME = 'gpteam';
2
- export const PACKAGE_VERSION = '0.1.3';
2
+ export const PACKAGE_VERSION = '0.1.4';
3
3
 
4
4
  export function getHelpText() {
5
5
  return [
@@ -13,7 +13,7 @@ export function getHelpText() {
13
13
  ' --api-key <key> 预填 API key',
14
14
  ' --client <id> codex / opencode / claude-code / openclaw',
15
15
  ' --model <id> 预选模型,例如 gpt-5.5',
16
- ' --context <tokens> 预设上下文窗口',
16
+ ' --context <tokens> 预设可配置上下文长度',
17
17
  ' --effort <level> 按模型支持项预选,常见为 none / low / medium / high / xhigh',
18
18
  ' --node <id> jp-direct / jp-split / hk-split / us-split',
19
19
  ' --rounds <n> 每个入口测速轮数,默认 3',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gpteam",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "GPTeam API interactive client configurator and ingress benchmark CLI.",
5
5
  "type": "module",
6
6
  "bin": {