gpteam 0.1.31 → 0.1.33

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
@@ -27,7 +27,7 @@ The Image MCP exposes an async-first local job flow plus a legacy compatibility
27
27
  - `get_capabilities`: returns supported sizes, formats, quality values, async support, cancellation semantics, queue limits, and image-to-image support.
28
28
  - `generate_image`: legacy compatibility alias. It now creates the same async job and returns `job_id` immediately instead of blocking until the image is complete.
29
29
 
30
- Image MCP results are returned as stable JSON text and MCP `structuredContent`. Successful results include final file path, model, action, size, format, quality, byte size, SHA-256, MIME type, image dimensions, duration, retry count, `job_id`, `trace_id`, and optional `idempotency_key`. Error results use stable `error.code`, `error.message`, `error.retryable`, `error.stage`, `error.upstream_status`, and `error.trace_id` fields while keeping compatibility fields such as `category` and `http_status`.
30
+ Image MCP results are returned as stable JSON text and MCP `structuredContent`. Successful results include final file path, model, action, size, format, quality, byte size, SHA-256, MIME type, image dimensions, duration, retry count, `job_id`, `trace_id`, and optional `idempotency_key`. `2K` and `4K` are output size tiers; completed results report the final image width and height so clients can verify the delivered dimensions. Error results use stable `error.code`, `error.message`, `error.retryable`, `error.stage`, `error.upstream_status`, and `error.trace_id` fields while keeping compatibility fields such as `category` and `http_status`.
31
31
 
32
32
  The MCP supports normal text-to-image generation and image-to-image/edit inputs. Pass `images` as data URLs, HTTPS URLs, or local file paths. For easier tool calling, `image`, `image_path`, `image_paths`, `input_image`, and `input_images` are accepted as aliases. Pass `mask` or `mask_path` the same way for masked edits. `input_fidelity` is accepted for compatibility but is not forwarded to the current GPTEAM Image 2 bridge because upstream Codex image edits reject it. The MCP requests GPTEAM image endpoints with `stream=true` and reads the final image event, so long image jobs get early stream bytes instead of sitting idle until the final JSON body. File writes create missing directories, avoid overwriting existing files by adding `-v2`, `-v3`, etc., and validate PNG/JPEG/WebP before returning success. `overwrite: true` is available for explicit replacement. `return_revised_prompt` controls whether the upstream revised prompt is included in the result.
33
33
 
package/lib/config.js CHANGED
@@ -59,9 +59,9 @@ export function writeCodexConfig(settings) {
59
59
  'requires_openai_auth = true',
60
60
  'supports_websockets = true'
61
61
  ];
62
- const websocketFeature = settings.websocket === true
63
- ? ['[features]', 'responses_websockets_v2 = true']
64
- : [];
62
+ const restWithFeatures = mergeCodexFeatureLines(rest, {
63
+ responses_websockets_v2: settings.websocket === true ? 'true' : null
64
+ });
65
65
  const mcpCommand = codexImageMCPCommand();
66
66
  const mcpEnv = imageMCPEnv(settings);
67
67
  const managedImageMCP = [
@@ -82,8 +82,7 @@ export function writeCodexConfig(settings) {
82
82
  const next = joinTomlSections([
83
83
  managedRoot.join('\n'),
84
84
  rootLines.join('\n'),
85
- rest.join('\n'),
86
- websocketFeature.join('\n'),
85
+ restWithFeatures.join('\n'),
87
86
  imageMCPEnabled(settings) ? managedImageMCP.join('\n') : '',
88
87
  managedProvider.join('\n')
89
88
  ]);
@@ -520,11 +519,16 @@ function joinTomlSections(sections) {
520
519
 
521
520
  function assertNoDuplicateTomlKeys(text) {
522
521
  const seen = new Map();
522
+ const seenTables = new Set();
523
523
  let section = '<root>';
524
524
  for (const line of String(text || '').split(/\r?\n/)) {
525
525
  const table = line.match(/^\s*\[([^\]]+)\]\s*$/);
526
526
  if (table) {
527
527
  section = table[1];
528
+ if (seenTables.has(section)) {
529
+ throw new Error(`生成的 Codex 配置存在重复表:${section},已停止写入`);
530
+ }
531
+ seenTables.add(section);
528
532
  if (!seen.has(section)) seen.set(section, new Set());
529
533
  continue;
530
534
  }
@@ -566,10 +570,59 @@ function isManagedProviderLine(line) {
566
570
  return /^\s*(name|base_url|wire_api|requires_openai_auth|supports_websockets)\s*=/.test(line);
567
571
  }
568
572
 
573
+ function isFeaturesHeader(line) {
574
+ return /^\s*\[features\]\s*$/.test(line);
575
+ }
576
+
577
+ function isManagedFeatureLine(line) {
578
+ return /^\s*responses_websockets_v2\s*=/.test(line);
579
+ }
580
+
569
581
  function isSalvageableRootLine(line) {
570
582
  return /^\s*(js_repl_node_path|preferred_auth_method|personality|plan_mode_reasoning_effort|service_tier)\s*=/.test(line);
571
583
  }
572
584
 
585
+ function mergeCodexFeatureLines(lines, features) {
586
+ const featureLines = Object.entries(features || {})
587
+ .filter(([, value]) => value !== null && value !== undefined)
588
+ .map(([key, value]) => `${key} = ${value}`);
589
+ const out = [];
590
+ let inFeatures = false;
591
+ let featuresTableSeen = false;
592
+ let managedLinesInserted = false;
593
+
594
+ for (const line of lines) {
595
+ if (isTableHeader(line)) {
596
+ if (inFeatures && !managedLinesInserted) {
597
+ appendManagedFeatureLines(out, featureLines);
598
+ if (out.length && out[out.length - 1].trim()) out.push('');
599
+ managedLinesInserted = true;
600
+ }
601
+ inFeatures = isFeaturesHeader(line);
602
+ if (inFeatures) featuresTableSeen = true;
603
+ out.push(line);
604
+ continue;
605
+ }
606
+ if (inFeatures && isManagedFeatureLine(line)) continue;
607
+ out.push(line);
608
+ }
609
+
610
+ if (inFeatures && !managedLinesInserted) {
611
+ appendManagedFeatureLines(out, featureLines);
612
+ managedLinesInserted = true;
613
+ }
614
+ if (!featuresTableSeen && featureLines.length > 0) {
615
+ if (out.length && out[out.length - 1].trim()) out.push('');
616
+ out.push('[features]', ...featureLines);
617
+ }
618
+ return trimEmptyEdges(out);
619
+ }
620
+
621
+ function appendManagedFeatureLines(out, featureLines) {
622
+ while (out.length && !out[out.length - 1].trim()) out.pop();
623
+ out.push(...featureLines);
624
+ }
625
+
573
626
  function backupIfExists(filePath) {
574
627
  if (!fs.existsSync(filePath)) return;
575
628
  const stamp = new Date().toISOString().replace(/[-:]/g, '').replace(/\..+/, '').replace('T', '-');
package/lib/help.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export const PACKAGE_NAME = 'gpteam';
2
- export const PACKAGE_VERSION = '0.1.31';
2
+ export const PACKAGE_VERSION = '0.1.33';
3
3
 
4
4
  export function getHelpText() {
5
5
  return [
@@ -314,6 +314,7 @@ export function getCapabilities(options = {}) {
314
314
  popular_sizes: POPULAR_IMAGE_SIZES,
315
315
  size_presets: ['1K', '2K', '4K', 'auto'],
316
316
  size_constraints: IMAGE_SIZE_CONSTRAINTS,
317
+ output_size_contract: '2K and 4K are delivered output size tiers; successful results include final width and height.',
317
318
  aspect_ratios: ['1:1', '3:2', '2:3', '16:9', '9:16', 'custom'],
318
319
  supports_custom_size: true,
319
320
  formats: IMAGE_FORMATS,
@@ -27,7 +27,7 @@ const imageInputProperties = {
27
27
  },
28
28
  size: {
29
29
  type: 'string',
30
- description: `图片尺寸。支持 auto、常用尺寸 ${POPULAR_IMAGE_SIZES.map((item) => `${item.label} ${item.size}`).join('、')},也支持满足约束的自定义宽高,例如 9:16 可用 1152x2048 或 2160x3840。`
30
+ description: `图片尺寸。支持 auto、常用尺寸 ${POPULAR_IMAGE_SIZES.map((item) => `${item.label} ${item.size}`).join('、')},也支持满足约束的自定义宽高,例如 9:16 可用 1152x2048 或 2160x3840。2K/4K 是正式输出规格,完成结果会返回最终图片宽高。`
31
31
  },
32
32
  quality: {
33
33
  type: 'string',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gpteam",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
4
4
  "description": "GPTEAM API interactive client configurator and ingress benchmark CLI.",
5
5
  "type": "module",
6
6
  "bin": {