{"record":{"id":"656fd08b3e4206f4","repo":"BigPizzaV3/CodexPlusPlus","slug":"codex-http-canvas-user","errorCode":null,"errorMessage":"当前 Codex 的 HTTP 服务尚未就绪，请稍后重试","messagePattern":"当前 Codex 的 HTTP 服务尚未就绪，请稍后重试","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"tools/conversation-canvas/public/canvas.user.js","lineNumber":770,"sourceCode":"        const delay=retryDelayMs*2**attempt;\n        progress(`${error.message}；${Math.ceil(delay/1000)} 秒后自动重试 ${attempt+1}/${maxRetries}（可能重复计费）…`);\n        // Pausing during backoff must not submit another request.\n        let timer;try{await waitForApi(new Promise(resolve=>{timer=setTimeout(resolve,delay);}),signal);}finally{clearTimeout(timer);}\n      }finally{clearInterval(heartbeat);}\n    }\n  }\n  return {run,dispose};\n}\n\n// HTTP uses the app host, with versioned runtime bindings, not renderer fetch/CSP.\nasync function nativeApiRequest(url,options){\n  const localError=message=>Object.assign(Error(message),{canvasApiLocal:true});\n  let native;\n  try{native=await loadNativeRuntime();}catch{throw localError('当前 Codex 版本的 API 适配器不兼容，请更新对话脉络脚本');}\n  if(typeof native.lGt!=='function')throw localError('当前 Codex 版本未提供兼容的 HTTP 服务');\n  native.lGt();\n  const client=native.cGt?.getInstance?.();\n  if(typeof client?.fetch!=='function'||!native.jR?.httpFetch)throw localError('当前 Codex 的 HTTP 服务尚未就绪，请稍后重试');\n  const {onProgress,...fetchOptions}=options;\n  const response=await client.fetch(url,fetchOptions);\n  return readApiResponse(response,options.signal,onProgress);\n}\n\n\nconst canvasNodeSize={width:268,height:132,gapX:88,gapY:34};\n\n// Iterative preorder/reverse traversal keeps deep histories off the JS call stack.\nfunction layoutTaskCanvas(nodes,currentNodeId,collapsed=new Set()){\n  const view=visibleTreeRows(nodes,currentNodeId,collapsed),children=new Map(),positions=new Map();\n  const {width,height,gapX,gapY}=canvasNodeSize;\n  for(const row of view.rows){const list=children.get(row.node.parent)||[];list.push(row.node.id);children.set(row.node.parent,list);}\n  let leaf=0;\n  for(const row of view.rows)if(!children.has(row.node.id))positions.set(row.node.id,leaf++*(height+gapY));\n  for(let i=view.rows.length-1;i>=0;i--){const row=view.rows[i],list=children.get(row.node.id);if(list)positions.set(row.node.id,(positions.get(list[0])+positions.get(list.at(-1)))/2);}\n  const cards=view.rows.map(row=>({...row,x:row.depth*(width+gapX),y:positions.get(row.node.id),width,height}));\n  const byId=new Map(cards.map(card=>[card.node.id,card]));","sourceCodeStart":752,"sourceCodeEnd":788,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6/tools/conversation-canvas/public/canvas.user.js#L752-L788","documentation":"nativeApiRequest() requires the runtime's HTTP client: native.cGt.getInstance() must expose fetch and native.jR.httpFetch must be truthy. When either is absent, the HTTP service exists in principle but is not initialized/ready, so this transient error is thrown.","triggerScenarios":"native runtime loaded and lGt called, but client?.fetch is not a function or native.jR.httpFetch is falsy — the host HTTP service hasn't finished initializing.","commonSituations":"Request issued immediately after app startup before the host service is ready; race during app initialization; Codex build exposing partially initialized bindings.","solutions":["Retry shortly — the message says the service isn't ready yet ('请稍后重试')","Ensure the app/host is fully loaded before triggering organize","Update the userscript if the bindings have changed names","Switch to the external channel as a workaround"],"exampleFix":"// before\nawait nativeApiRequest(url, opts); // fired at app startup\n// after\nawait delay(2000); await nativeApiRequest(url, opts); // retry after host warm-up","handlingStrategy":"retry","validationCode":"const ready = n => typeof n?.lGt==='function' && typeof n?.cGt?.getInstance?.()?.fetch==='function' && !!n?.jR?.httpFetch;\n// poll until ready before requesting","typeGuard":"function httpServiceReady(n){return typeof n?.cGt?.getInstance?.()?.fetch==='function' && !!n?.jR?.httpFetch;}","tryCatchPattern":"try{ await nativeApiRequest(url,opts) }catch(e){ if(e.message.includes('尚未就绪')){ await delay(1500); return nativeApiRequest(url,opts); } throw e; }","preventionTips":["Wait for full app startup before organizing","Add a readiness probe/poll loop before first request","Retry transiently with backoff"],"tags":["initialization","native-runtime","transient"],"backgroundTag":"invalid-state-transition","analyzedSha":"b1ed92e5e4a2d74095d4b8db5af43cef7acba9c6","analyzedAt":"2026-09-19T23:35:21.129Z","contentChangedAt":"2026-09-19T23:35:21.129Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}