misonL commited on
Commit
e304f38
·
verified ·
1 Parent(s): 4d6d6c8

Deploy ce29b5c to Docker Space

Browse files

Source: MisonL/gpt-image-playground-customer@ce29b5c26187210528cd5ad0057746d85b048249

public/hf-space-deploy-marker.json CHANGED
@@ -1,5 +1,5 @@
1
  {
2
  "schema_version": 1,
3
- "local_sha": "fa03242bd6b72fa8fe64e177f690cb8f81ba2a8c",
4
- "created_at": "2026-06-20T10:52:58.463Z"
5
  }
 
1
  {
2
  "schema_version": 1,
3
+ "local_sha": "ce29b5c26187210528cd5ad0057746d85b048249",
4
+ "created_at": "2026-06-20T13:36:17.547Z"
5
  }
scripts/agent-skill-scripts.test.mjs CHANGED
@@ -3234,6 +3234,8 @@ describe('Agent skill script argument validation', () => {
3234
  assert.match(skillText, /\.env\.agent\.local\.example/);
3235
  assert.match(skillText, /page_sse_real_smoke_status/);
3236
  assert.match(skillText, /responses_image_backend_real_smoke_status/);
 
 
3237
  assert.match(skillText, /summary\.responses_page_sse_generate_smoke/);
3238
  assert.match(skillText, /summary\.real_smoke_checks/);
3239
  assert.match(apiReference, /npm run first-run/);
@@ -3242,6 +3244,8 @@ describe('Agent skill script argument validation', () => {
3242
  assert.match(apiReference, /\.env\.agent\.local\.example/);
3243
  assert.match(apiReference, /page_sse_real_smoke_status/);
3244
  assert.match(apiReference, /responses_image_backend_real_smoke_status/);
 
 
3245
  assert.match(apiReference, /summary\.responses_page_sse_generate_smoke/);
3246
  assert.match(apiReference, /summary\.real_smoke_checks/);
3247
  assert.match(readmeText, /不要手动并行启动多个单张脚本/);
 
3234
  assert.match(skillText, /\.env\.agent\.local\.example/);
3235
  assert.match(skillText, /page_sse_real_smoke_status/);
3236
  assert.match(skillText, /responses_image_backend_real_smoke_status/);
3237
+ assert.match(skillText, /summary\.page_sse_real_smoke/);
3238
+ assert.match(skillText, /兼容聚合状态/);
3239
  assert.match(skillText, /summary\.responses_page_sse_generate_smoke/);
3240
  assert.match(skillText, /summary\.real_smoke_checks/);
3241
  assert.match(apiReference, /npm run first-run/);
 
3244
  assert.match(apiReference, /\.env\.agent\.local\.example/);
3245
  assert.match(apiReference, /page_sse_real_smoke_status/);
3246
  assert.match(apiReference, /responses_image_backend_real_smoke_status/);
3247
+ assert.match(apiReference, /summary\.page_sse_real_smoke/);
3248
+ assert.match(apiReference, /兼容聚合状态/);
3249
  assert.match(apiReference, /summary\.responses_page_sse_generate_smoke/);
3250
  assert.match(apiReference, /summary\.real_smoke_checks/);
3251
  assert.match(readmeText, /不要手动并行启动多个单张脚本/);
scripts/command-center.test.mjs CHANGED
@@ -18,6 +18,7 @@ import {
18
  import { buildFirstRunReport, formatFirstRunText } from './first-run.mjs';
19
  import {
20
  buildAdminCommands,
 
21
  buildImageUpstreamRealSmokeStatus,
22
  parseGitStatusEntries,
23
  readStatusEnvFromFiles,
@@ -221,6 +222,83 @@ describe('Command center scripts', () => {
221
  assert.doesNotMatch(JSON.stringify(status), /user:pass|original\.example|token=secret|original-secret/);
222
  });
223
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
224
  it('loads independent image upstream smoke readiness from env files without overriding shell env', async () => {
225
  const tempDir = await mkdtemp(path.join(os.tmpdir(), 'image-upstream-status-'));
226
  const localEnvPath = path.join(tempDir, '.env.local');
@@ -962,12 +1040,13 @@ describe('Command center scripts', () => {
962
  assert.equal(body.summary.real_smoke_checks.agent_generate_1k, 'passed');
963
  assert.equal(body.summary.real_smoke_checks.responses_page_sse_generate_1k, 'failed');
964
  assert.equal(body.summary.real_smoke_checks.page_sse_edit_2k, 'skipped');
965
- assert.match(
966
- body.layers
967
- .find((layer) => layer.name === 'billable_smoke')
968
- .checks.find((check) => check.name === 'responses_page_sse_generate_1k').output,
969
- /503 Service temporarily unavailable/
970
- );
 
971
  }
972
  );
973
  });
 
18
  import { buildFirstRunReport, formatFirstRunText } from './first-run.mjs';
19
  import {
20
  buildAdminCommands,
21
+ buildImageUpstreamLocalEndpointStatus,
22
  buildImageUpstreamRealSmokeStatus,
23
  parseGitStatusEntries,
24
  readStatusEnvFromFiles,
 
222
  assert.doesNotMatch(JSON.stringify(status), /user:pass|original\.example|token=secret|original-secret/);
223
  });
224
 
225
+ it('checks local real smoke endpoints without exposing URL paths or credentials', async () => {
226
+ const status = await buildImageUpstreamLocalEndpointStatus(
227
+ {
228
+ IMAGE_REAL_SMOKE_ORIGINAL_BASE_URL: 'http://127.0.0.1:3010/v1?ignored=no',
229
+ IMAGE_REAL_SMOKE_ORIGINAL_API_KEY: 'original-secret',
230
+ IMAGE_REAL_SMOKE_GAOREN_BASE_URL: 'http://localhost:3001/v1',
231
+ IMAGE_REAL_SMOKE_GAOREN_API_KEY: 'gaoren-secret',
232
+ IMAGE_REAL_SMOKE_SUB2API_BASE_URL: 'https://sub2api.example/v1',
233
+ IMAGE_REAL_SMOKE_SUB2API_API_KEY: 'sub2api-secret'
234
+ },
235
+ {
236
+ probe: async (endpoint) => ({
237
+ ok: endpoint.port === 3001,
238
+ reason: endpoint.port === 3001 ? undefined : 'connection_refused'
239
+ })
240
+ }
241
+ );
242
+
243
+ assert.deepEqual(status, {
244
+ checked_count: 1,
245
+ unavailable_count: 0,
246
+ unavailable_cases: [],
247
+ results: [
248
+ {
249
+ id: 'gaoren-images-sse',
250
+ endpoint: 'localhost:3001',
251
+ ok: true
252
+ }
253
+ ]
254
+ });
255
+ assert.doesNotMatch(JSON.stringify(status), /secret|\/v1|sub2api\.example|ignored=no/);
256
+ });
257
+
258
+ it('reports unavailable local real smoke endpoints by case id', async () => {
259
+ const status = await buildImageUpstreamLocalEndpointStatus(
260
+ {
261
+ IMAGE_REAL_SMOKE_SUB2API_BASE_URL: 'http://127.0.0.1:3021/v1',
262
+ IMAGE_REAL_SMOKE_SUB2API_API_KEY: 'sub2api-secret',
263
+ IMAGE_REAL_SMOKE_MATSCA_BASE_URL: 'http://[::1]:3090/v1',
264
+ IMAGE_REAL_SMOKE_MATSCA_API_KEY: 'matsca-secret'
265
+ },
266
+ {
267
+ probe: async (endpoint) => ({
268
+ ok: false,
269
+ reason: endpoint.port === 3021 ? 'connection_refused' : 'timeout'
270
+ })
271
+ }
272
+ );
273
+
274
+ assert.deepEqual(status, {
275
+ checked_count: 3,
276
+ unavailable_count: 3,
277
+ unavailable_cases: ['sub2api-images-sse', 'sub2api-responses-json', 'matsca-images-sse'],
278
+ results: [
279
+ {
280
+ id: 'sub2api-images-sse',
281
+ endpoint: '127.0.0.1:3021',
282
+ ok: false,
283
+ reason: 'connection_refused'
284
+ },
285
+ {
286
+ id: 'sub2api-responses-json',
287
+ endpoint: '127.0.0.1:3021',
288
+ ok: false,
289
+ reason: 'connection_refused'
290
+ },
291
+ {
292
+ id: 'matsca-images-sse',
293
+ endpoint: '::1:3090',
294
+ ok: false,
295
+ reason: 'timeout'
296
+ }
297
+ ]
298
+ });
299
+ assert.doesNotMatch(JSON.stringify(status), /secret|\/v1/);
300
+ });
301
+
302
  it('loads independent image upstream smoke readiness from env files without overriding shell env', async () => {
303
  const tempDir = await mkdtemp(path.join(os.tmpdir(), 'image-upstream-status-'));
304
  const localEnvPath = path.join(tempDir, '.env.local');
 
1040
  assert.equal(body.summary.real_smoke_checks.agent_generate_1k, 'passed');
1041
  assert.equal(body.summary.real_smoke_checks.responses_page_sse_generate_1k, 'failed');
1042
  assert.equal(body.summary.real_smoke_checks.page_sse_edit_2k, 'skipped');
1043
+ const pageSseOutput = body.layers
1044
+ .find((layer) => layer.name === 'billable_smoke')
1045
+ .checks.find((check) => check.name === 'responses_page_sse_generate_1k').output;
1046
+ const pageSseFailure = parseJsonPayload(pageSseOutput, 'responses page SSE doctor smoke');
1047
+ assert.equal(pageSseFailure.summary.selected_channel_id, null);
1048
+ assert.equal(pageSseFailure.summary.upstream_host, null);
1049
+ assert.match(pageSseOutput, /503 Service temporarily unavailable/);
1050
  }
1051
  );
1052
  });
scripts/status.mjs CHANGED
@@ -1,11 +1,13 @@
1
  #!/usr/bin/env node
2
 
3
  import { existsSync, readFileSync } from 'node:fs';
 
4
 
5
  import { HF_SPACE_ID, HF_SPACE_URL } from './hf-space-doctor-utils.mjs';
6
  import { isMainModule, parseJsonPayload, printJson, runCommand, runCommandStrict } from './command-center-utils.mjs';
7
 
8
  const REMOTE_STATUS_TIMEOUT_MS = 30_000;
 
9
  const IMAGE_UPSTREAM_REAL_SMOKE_CASES = [
10
  { id: 'original-images-json', prefix: 'IMAGE_REAL_SMOKE_ORIGINAL' },
11
  { id: 'gaoren-images-sse', prefix: 'IMAGE_REAL_SMOKE_GAOREN' },
@@ -127,6 +129,7 @@ function readTargetConfigured(testCase, env) {
127
  const baseUrlError = baseUrl ? readBaseUrlValidationError(baseUrl.value) : undefined;
128
  return {
129
  baseUrl: Boolean(baseUrl),
 
130
  apiKey: Boolean(apiKey),
131
  responsesModel: Boolean(responsesModel),
132
  invalidEnv: baseUrlError ? [{ key: baseUrl.key, reason: baseUrlError }] : []
@@ -175,6 +178,90 @@ export function buildImageUpstreamRealSmokeStatus(env = process.env) {
175
  };
176
  }
177
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  function parseArgs(argv) {
179
  const unknown = argv.find((arg) => !['--help', '-h', '--remote'].includes(arg));
180
  if (unknown) throw new Error(`Unknown option: ${unknown}`);
@@ -194,11 +281,13 @@ Options:
194
  --help Show this help.`);
195
  }
196
 
197
- function buildLocalStatus() {
198
  const packageJson = JSON.parse(readFileSync('package.json', 'utf8'));
199
  const branch = runCommandStrict('git', ['branch', '--show-current']).trim();
200
  const head = runCommandStrict('git', ['rev-parse', '--short', 'HEAD']).trim();
201
  const changed = parseGitStatusEntries(runCommandStrict('git', ['status', '--porcelain=v1', '-z']));
 
 
202
  return {
203
  product: packageJson.name,
204
  version: packageJson.version,
@@ -216,7 +305,10 @@ function buildLocalStatus() {
216
  capabilities: '/api/agent/capabilities',
217
  skill: 'skills/gpt-image-playground-agent/SKILL.md'
218
  },
219
- image_upstream_real_smoke: buildImageUpstreamRealSmokeStatus(readStatusEnvFromFiles(process.env))
 
 
 
220
  };
221
  }
222
 
@@ -244,14 +336,14 @@ function readRemoteStatus() {
244
  );
245
  }
246
 
247
- function main() {
248
  const options = parseArgs(process.argv.slice(2));
249
  if (options.help) {
250
  printHelp();
251
  return;
252
  }
253
 
254
- const status = buildLocalStatus();
255
  printJson({
256
  ok: true,
257
  ...status,
@@ -259,9 +351,9 @@ function main() {
259
  });
260
  }
261
 
262
- try {
263
- if (isMainModule(import.meta.url, process.argv[1])) main();
264
- } catch (error) {
265
- printJson({ ok: false, error: error instanceof Error ? error.message : String(error) });
266
- process.exit(1);
267
  }
 
1
  #!/usr/bin/env node
2
 
3
  import { existsSync, readFileSync } from 'node:fs';
4
+ import net from 'node:net';
5
 
6
  import { HF_SPACE_ID, HF_SPACE_URL } from './hf-space-doctor-utils.mjs';
7
  import { isMainModule, parseJsonPayload, printJson, runCommand, runCommandStrict } from './command-center-utils.mjs';
8
 
9
  const REMOTE_STATUS_TIMEOUT_MS = 30_000;
10
+ const LOCAL_ENDPOINT_TIMEOUT_MS = 500;
11
  const IMAGE_UPSTREAM_REAL_SMOKE_CASES = [
12
  { id: 'original-images-json', prefix: 'IMAGE_REAL_SMOKE_ORIGINAL' },
13
  { id: 'gaoren-images-sse', prefix: 'IMAGE_REAL_SMOKE_GAOREN' },
 
129
  const baseUrlError = baseUrl ? readBaseUrlValidationError(baseUrl.value) : undefined;
130
  return {
131
  baseUrl: Boolean(baseUrl),
132
+ baseUrlValue: baseUrl?.value,
133
  apiKey: Boolean(apiKey),
134
  responsesModel: Boolean(responsesModel),
135
  invalidEnv: baseUrlError ? [{ key: baseUrl.key, reason: baseUrlError }] : []
 
178
  };
179
  }
180
 
181
+ function normalizeLocalHostname(hostname) {
182
+ return hostname.toLowerCase().replace(/^\[|\]$/g, '');
183
+ }
184
+
185
+ function isLocalHostname(hostname) {
186
+ const normalized = normalizeLocalHostname(hostname);
187
+ return normalized === 'localhost' || normalized === '127.0.0.1' || normalized === '::1';
188
+ }
189
+
190
+ function readUrlPort(url) {
191
+ if (url.port) return Number(url.port);
192
+ if (url.protocol === 'http:') return 80;
193
+ if (url.protocol === 'https:') return 443;
194
+ return undefined;
195
+ }
196
+
197
+ function readLocalEndpoint(testCase, env) {
198
+ const target = readTargetConfigured(testCase, env);
199
+ if (!target.baseUrlValue || target.invalidEnv.length > 0) return undefined;
200
+ const url = new URL(target.baseUrlValue);
201
+ if (!isLocalHostname(url.hostname)) return undefined;
202
+ const port = readUrlPort(url);
203
+ if (!port) return undefined;
204
+ return {
205
+ id: testCase.id,
206
+ host: normalizeLocalHostname(url.hostname),
207
+ port
208
+ };
209
+ }
210
+
211
+ function readLocalEndpointTargets(env) {
212
+ return IMAGE_UPSTREAM_REAL_SMOKE_CASES.map((testCase) => readLocalEndpoint(testCase, env)).filter(Boolean);
213
+ }
214
+
215
+ function formatEndpoint(endpoint) {
216
+ return `${endpoint.host}:${endpoint.port}`;
217
+ }
218
+
219
+ function readSocketFailureReason(error) {
220
+ if (error?.code === 'ECONNREFUSED') return 'connection_refused';
221
+ if (error?.code === 'ETIMEDOUT') return 'timeout';
222
+ if (error?.code === 'EHOSTUNREACH') return 'host_unreachable';
223
+ if (error?.code === 'ENETUNREACH') return 'network_unreachable';
224
+ return 'connection_failed';
225
+ }
226
+
227
+ function probeTcpEndpoint(endpoint, options = {}) {
228
+ const timeoutMs = options.timeoutMs || LOCAL_ENDPOINT_TIMEOUT_MS;
229
+ return new Promise((resolve) => {
230
+ const socket = net.createConnection({ host: endpoint.host, port: endpoint.port });
231
+ let settled = false;
232
+ const finish = (result) => {
233
+ if (settled) return;
234
+ settled = true;
235
+ socket.destroy();
236
+ resolve(result);
237
+ };
238
+ socket.setTimeout(timeoutMs, () => finish({ ok: false, reason: 'timeout' }));
239
+ socket.once('connect', () => finish({ ok: true }));
240
+ socket.once('error', (error) => finish({ ok: false, reason: readSocketFailureReason(error) }));
241
+ });
242
+ }
243
+
244
+ export async function buildImageUpstreamLocalEndpointStatus(env = process.env, options = {}) {
245
+ const probe = options.probe || probeTcpEndpoint;
246
+ const results = [];
247
+ for (const endpoint of readLocalEndpointTargets(env)) {
248
+ const result = await probe(endpoint, options);
249
+ results.push({
250
+ id: endpoint.id,
251
+ endpoint: formatEndpoint(endpoint),
252
+ ok: result.ok === true,
253
+ ...(result.ok === true ? {} : { reason: result.reason || 'connection_failed' })
254
+ });
255
+ }
256
+ const unavailable = results.filter((item) => !item.ok);
257
+ return {
258
+ checked_count: results.length,
259
+ unavailable_count: unavailable.length,
260
+ unavailable_cases: unavailable.map((item) => item.id),
261
+ results
262
+ };
263
+ }
264
+
265
  function parseArgs(argv) {
266
  const unknown = argv.find((arg) => !['--help', '-h', '--remote'].includes(arg));
267
  if (unknown) throw new Error(`Unknown option: ${unknown}`);
 
281
  --help Show this help.`);
282
  }
283
 
284
+ async function buildLocalStatus() {
285
  const packageJson = JSON.parse(readFileSync('package.json', 'utf8'));
286
  const branch = runCommandStrict('git', ['branch', '--show-current']).trim();
287
  const head = runCommandStrict('git', ['rev-parse', '--short', 'HEAD']).trim();
288
  const changed = parseGitStatusEntries(runCommandStrict('git', ['status', '--porcelain=v1', '-z']));
289
+ const statusEnv = readStatusEnvFromFiles(process.env);
290
+ const imageUpstreamRealSmoke = buildImageUpstreamRealSmokeStatus(statusEnv);
291
  return {
292
  product: packageJson.name,
293
  version: packageJson.version,
 
305
  capabilities: '/api/agent/capabilities',
306
  skill: 'skills/gpt-image-playground-agent/SKILL.md'
307
  },
308
+ image_upstream_real_smoke: {
309
+ ...imageUpstreamRealSmoke,
310
+ local_endpoint_checks: await buildImageUpstreamLocalEndpointStatus(statusEnv)
311
+ }
312
  };
313
  }
314
 
 
336
  );
337
  }
338
 
339
+ async function main() {
340
  const options = parseArgs(process.argv.slice(2));
341
  if (options.help) {
342
  printHelp();
343
  return;
344
  }
345
 
346
+ const status = await buildLocalStatus();
347
  printJson({
348
  ok: true,
349
  ...status,
 
351
  });
352
  }
353
 
354
+ if (isMainModule(import.meta.url, process.argv[1])) {
355
+ main().catch((error) => {
356
+ printJson({ ok: false, error: error instanceof Error ? error.message : String(error) });
357
+ process.exit(1);
358
+ });
359
  }
skills/gpt-image-playground-agent/SKILL.md CHANGED
@@ -139,6 +139,7 @@ Authorization: Bearer <token>
139
  | `summary.page_sse_auth_ready` | `agent:doctor` | 页面 SSE 鉴权是否已满足;为 `false` 时不要运行 `--page-sse` 真实计费请求。 |
140
  | `page_sse_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 `/api/images` smoke;`state=not_run` 且 `billable=false` 表示它只是只读就绪检查。 |
141
  | `responses_image_backend_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 Responses image_generation smoke;不要把声明支持当作实测通过。 |
 
142
  | `summary.responses_page_sse_generate_smoke` | `agent:doctor` | `--allow-billable` 时对 `responses-image-generation` + page SSE + `responses-sse` 这条文生图路径的真实 smoke 状态;非计费时为 `skipped`。 |
143
  | `summary.real_smoke_checks` | `agent:doctor` | 各真实 smoke 的状态汇总,包含 `agent_generate_1k`、`responses_page_sse_generate_1k`、`agent_edit_1k` 和 `page_sse_edit_2k`。 |
144
  | `private_agent_env.exists` | `first-run --json` | 本机是否存在 `.env.agent.local` 私有配置;Agent CLI 默认从当前仓库根目录读取该文件。 |
 
139
  | `summary.page_sse_auth_ready` | `agent:doctor` | 页面 SSE 鉴权是否已满足;为 `false` 时不要运行 `--page-sse` 真实计费请求。 |
140
  | `page_sse_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 `/api/images` smoke;`state=not_run` 且 `billable=false` 表示它只是只读就绪检查。 |
141
  | `responses_image_backend_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 Responses image_generation smoke;不要把声明支持当作实测通过。 |
142
+ | `summary.page_sse_real_smoke` | `agent:doctor` | Page SSE 真实 smoke 的兼容聚合状态;任一 Page SSE smoke 失败为 `failed`,任一通过且无失败为 `passed`,全部跳过为 `skipped`;精确判断优先看 `summary.real_smoke_checks`。 |
143
  | `summary.responses_page_sse_generate_smoke` | `agent:doctor` | `--allow-billable` 时对 `responses-image-generation` + page SSE + `responses-sse` 这条文生图路径的真实 smoke 状态;非计费时为 `skipped`。 |
144
  | `summary.real_smoke_checks` | `agent:doctor` | 各真实 smoke 的状态汇总,包含 `agent_generate_1k`、`responses_page_sse_generate_1k`、`agent_edit_1k` 和 `page_sse_edit_2k`。 |
145
  | `private_agent_env.exists` | `first-run --json` | 本机是否存在 `.env.agent.local` 私有配置;Agent CLI 默认从当前仓库根目录读取该文件。 |
skills/gpt-image-playground-agent/references/api.md CHANGED
@@ -554,6 +554,7 @@ node "<skill-root>/scripts/diagnose-request.mjs" --base-url https://your-space.h
554
  | `summary.page_sse_auth_ready` | `agent:doctor` | 页面 SSE 鉴权是否已满足;为 `false` 时不要运行 `--page-sse` 真实计费请求。 |
555
  | `page_sse_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 `/api/images` smoke;`state=not_run` 且 `billable=false` 表示它只是只读就绪检查。 |
556
  | `responses_image_backend_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 Responses image_generation smoke;不要把声明支持当作实测通过。 |
 
557
  | `summary.responses_page_sse_generate_smoke` | `agent:doctor` | `--allow-billable` 时对 `responses-image-generation` + page SSE + `responses-sse` 这条文生图路径的真实 smoke 状态;非计费时为 `skipped`。 |
558
  | `summary.real_smoke_checks` | `agent:doctor` | 各真实 smoke 的状态汇总,包含 `agent_generate_1k`、`responses_page_sse_generate_1k`、`agent_edit_1k` 和 `page_sse_edit_2k`。 |
559
  | `private_agent_env.exists` | `first-run --json` | 本机是否存在 `.env.agent.local` 私有配置;Agent CLI 默认从当前仓库根目录读取该文件。 |
 
554
  | `summary.page_sse_auth_ready` | `agent:doctor` | 页面 SSE 鉴权是否已满足;为 `false` 时不要运行 `--page-sse` 真实计费请求。 |
555
  | `page_sse_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 `/api/images` smoke;`state=not_run` 且 `billable=false` 表示它只是只读就绪检查。 |
556
  | `responses_image_backend_real_smoke_status` | `first-run --json` | 结构化说明 `first-run` 未执行真实 Responses image_generation smoke;不要把声明支持当作实测通过。 |
557
+ | `summary.page_sse_real_smoke` | `agent:doctor` | Page SSE 真实 smoke 的兼容聚合状态;任一 Page SSE smoke 失败为 `failed`,任一通过且无失败为 `passed`,全部跳过为 `skipped`;精确判断优先看 `summary.real_smoke_checks`。 |
558
  | `summary.responses_page_sse_generate_smoke` | `agent:doctor` | `--allow-billable` 时对 `responses-image-generation` + page SSE + `responses-sse` 这条文生图路径的真实 smoke 状态;非计费时为 `skipped`。 |
559
  | `summary.real_smoke_checks` | `agent:doctor` | 各真实 smoke 的状态汇总,包含 `agent_generate_1k`、`responses_page_sse_generate_1k`、`agent_edit_1k` 和 `page_sse_edit_2k`。 |
560
  | `private_agent_env.exists` | `first-run --json` | 本机是否存在 `.env.agent.local` 私有配置;Agent CLI 默认从当前仓库根目录读取该文件。 |