alchemylab 3.0.2 → 3.0.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/dist/cli.js CHANGED
@@ -1679,7 +1679,7 @@ if(k=s.sessionId,y=s.model,v=s.serverUrl,b=s.initialBranch,S=s.pickupGuidance??n
1679
1679
  if(/refused to spawn a second coder|already has a live coder/.test(t))return m.info("Spawn refused by the record; not falling back",{requestId:u,error:t}),{success:!1,sessionId:null,error:t,refused:!0}
1680
1680
  m.warn("Session preparation failed \u2014 spawning without pre-created session",{error:t}),v=r(l)||void 0}let I=i
1681
1681
  if(S&&(I=`${S}\n\n---\n\n${i}`,m.info("Pickup guidance composed into spawn prompt",{requestId:u,sessionId:k})),k&&v){const e=await(0,n.deliverInitialPrompt)({serverUrl:v,sessionId:k,agent:t,prompt:I,model:y,directory:l,...w?{tools:w}:{}})
1682
- return e.success?(m.info("Spawned action agent",{agent:t,sessionId:k,requestId:u}),{success:!0,sessionId:k,...y?{model:y}:{}}):{success:!1,sessionId:k,error:e.error||"Prompt delivery failed"}}const $=(0,s.spawnDetachedSubagent)({agent:t,prompt:I,cwd:c,sessionId:k||void 0,serverUrl:v,model:y,initialBranch:b,allowParallel:p??!1,onSpawn:e=>{e&&g&&g(e)}})
1682
+ return e.success?(m.info("Spawned action agent",{agent:t,sessionId:k,requestId:u}),{success:!0,sessionId:k,...y?{model:y}:{},...e.messageId?{promptMessageId:e.messageId}:{}}):{success:!1,sessionId:k,error:e.error||"Prompt delivery failed"}}const $=(0,s.spawnDetachedSubagent)({agent:t,prompt:I,cwd:c,sessionId:k||void 0,serverUrl:v,model:y,initialBranch:b,allowParallel:p??!1,onSpawn:e=>{e&&g&&g(e)}})
1683
1683
  return $.success?(m.info("Spawned action agent (legacy CLI fallback)",{agent:t,sessionId:k,pid:$.pid,requestId:u}),{success:!0,sessionId:k,pid:$.pid,...y?{model:y}:{}}):{success:!1,sessionId:k,error:$.error||"Spawn failed"}}
1684
1684
  const s=t(48035),n=t(15899),o=t(58824),i=t(60833),a=t(61292)
1685
1685
  exports.fR=9e4},47078(e,exports,t){"use strict"
@@ -1899,8 +1899,8 @@ const r=e.data,u=Array.isArray(r.acceptanceCriteria)&&r.acceptanceCriteria.lengt
1899
1899
  return p.success?(i.info("Driver spawned",{requestId:n,sessionId:p.sessionId}),{success:!0,message:`Driver spawned for ${n} (session ${p.sessionId})`}):{success:!1,message:`Failed to spawn driver for ${n}`,error:p.error}}catch(e){const t=(0,r.getErrorMessage)(e)
1900
1900
  return i.error("start-drive action failed",{requestId:n,error:t}),{success:!1,message:`Drive dispatch failed for ${n}`,error:t}}}
1901
1901
  const r=t(58824),s=t(28148)},93503(e,exports,t){"use strict"
1902
- async function r(e,t,r){try{const s=await(0,f.readAllPages)(e.apiClient,t=>`/api/projects/${e.projectId}/requests?inFlight=true&limit=100&offset=${t}`),n=e=>String(e??"").toLowerCase().replace(/[^a-z0-9]+/g," ").trim(),o=n(t?.title)
1903
- return o?s.filter(e=>e&&(e.localId??e.id)!==r&&["open","in_progress","ready_for_review"].includes(e.status)&&n(e.title)===o).map(e=>e.localId??e.id):[]}catch{return[]}}async function s(e,t,r,s=5e3){const n=(0,v.getOpenCodeUrlFromConfig)(e.projectPath)
1902
+ async function r(e,t,r){try{const s=await(0,m.readAllPages)(e.apiClient,t=>`/api/projects/${e.projectId}/requests?inFlight=true&limit=100&offset=${t}`),n=e=>String(e??"").toLowerCase().replace(/[^a-z0-9]+/g," ").trim(),o=n(t?.title)
1903
+ return o?s.filter(e=>e&&(e.localId??e.id)!==r&&["open","in_progress","ready_for_review"].includes(e.status)&&n(e.title)===o).map(e=>e.localId??e.id):[]}catch{return[]}}async function s(e,t,r,s=5e3){const n=(0,k.getOpenCodeUrlFromConfig)(e.projectPath)
1904
1904
  if(!n)return!0
1905
1905
  const o=Date.now()+r
1906
1906
  let i=!1
@@ -1911,100 +1911,103 @@ if(!Array.isArray(r)||r.some(e=>e?.name===t))return!0}catch{return!0}if(Date.now
1911
1911
  i||(i=!0,e.logger.info("start-worker: waiting for the agent to load in the runtime",{agent:t})),await new Promise(e=>setTimeout(e,s))}}async function n(e,t,r){let s=""
1912
1912
  try{const r=await e.apiClient.get(`/api/projects/${e.projectId}/requests/${t}/record-for-agents`)
1913
1913
  s=String((r?.data??r)?.text??"")}catch{}try{return function(e,t){const r=Array.isArray(e?.acceptanceCriteria)?e.acceptanceCriteria:[]
1914
- return[`## Description\n${String(e?.description??"").trim()||"_No description provided._"}`,`## Acceptance Criteria\n${(0,I.formatCriteriaWithHashes)(r)}`,...t&&t.trim()?[t.trim()]:[]].join("\n\n")}(r,s)}catch{return""}}async function o(e,t){if(!t)return null
1915
- try{const r=(0,A.simpleGit)(e),s=await r.diffSummary([`${t}..HEAD`])
1916
- return{files:s.files.map(e=>({file:e.file,insertions:e.insertions??0,deletions:e.deletions??0})),insertions:s.insertions,deletions:s.deletions}}catch{return null}}async function i(e,t){if(!t)return[]
1917
- try{const r=(0,A.simpleGit)(e)
1918
- return(await r.raw(["diff","--name-only",`${t}^1`,t]).catch(async()=>r.raw(["diff","--name-only",`${t}^`,t]))).split("\n").map(e=>e.trim()).filter(Boolean)}catch{return[]}}async function a(e,t,r){const{apiClient:s,projectId:n,projectPath:a,logger:c}=e,{p:l,req:d,worker:u,startPrompt:h,toolMask:f,deps:g}=t,y=r.sessionId
1919
- if(r.reopenLocalId)try{await s.patch(`/api/projects/${n}/cli-sessions/${encodeURIComponent(r.reopenLocalId)}`,{status:"active"})}catch(e){c.warn("session routing: could not reopen the cold worker",{requestId:l.requestId,sessionId:y,error:(0,S.getErrorMessage)(e)})}let I=null
1920
- try{const e=await s.post(`/api/projects/${n}/requests/${l.requestId}/pickup-compose`,{sessionId:y,agentType:u,warm:!0})
1921
- I=(e?.data??e)?.text??null,I=await(0,C.withInFlightFiles)(a,I,e?.data??e)}catch(e){c.warn("session routing: warm pickup guidance failed; sending the request alone",{requestId:l.requestId,error:(0,S.getErrorMessage)(e)})}let $=null
1922
- try{const e=r.previousRequestId?await s.get(`/api/projects/${n}/requests/${r.previousRequestId}`):null,t=(e?.data??e)?.mergeCommitSha??(e?.data??e)?.merge_commit_sha??null,[c,l]=await Promise.all([o(a,t),i(a,t)])
1923
- $=(0,E.sinceYouLastLookedBlock)(c,r.previousRequestId,l)}catch{}const j=[(_=l.requestId,T=r.previousRequestId,x=r.area,[`${x?"Your next request":"Next request in your thread"}: ${_}. This is a NEW record: ${T?`${T} is closed and must not be reopened, re-verified or amended`:"the request you finished before is closed"}. Work on ${_}'s branch, not the old one.`,...x?["It is separate work in the same area, not a follow-up: take nothing over from what you did before except what you know of the code."]:[],"You already have this project in context, so do not re-read the map or the files you know; open only what this request changes."].join("\n")),h,$,I].filter(Boolean).join("\n\n"),A=await(g.deliver??((t,r)=>(0,w.deliverPrompt)(e,t,r,{kind:"inserted-prompt-generic",partPayload:{requestId:l.requestId,source:l.source},...(0,m.hasMask)(f)?{toolDenies:f}:{}})))(y,j)
1924
- var _,T,x
1925
- if(!1===A?.ok)return c.warn("session routing: delivery to the warm worker failed; spawning a fresh one",{requestId:l.requestId,sessionId:y,error:A?.error}),!1
1926
- try{await async function(e,t,r){const{apiClient:s,projectId:n,logger:o}=e
1914
+ return[`## Description\n${String(e?.description??"").trim()||"_No description provided._"}`,`## Acceptance Criteria\n${(0,j.formatCriteriaWithHashes)(r)}`,...t&&t.trim()?[t.trim()]:[]].join("\n\n")}(r,s)}catch{return""}}function o(e,t,r,s){const n=[t?.roundOf?`The user wrote on the page of ${t.roundOf}, which is completed. Their message is ${e.requestId}; its record is at the end of this message. If you only answer it, what you write last in this turn is your reply to them, and nothing else is needed. If you change the project for it, the change is ${e.requestId}'s: make it and complete ${e.requestId} as you complete any request.`:`Implement ${e.requestId} ("${t?.title??""}") and own its full lifecycle. It was registered via ${e.source??"a registration door"}.`,s?"Its record, as get_request_information shows it now, is at the end of this message: start from it, and read the request again only when you need what changed since. If something it BUILDS ON does not exist in this project, call request_operations premise-block with the reason instead of starting. New content the request introduces is not a missing premise.":"Read it with get_request_information first. If something it BUILDS ON does not exist in this project, call request_operations premise-block with the reason instead of starting. New content the request introduces is not a missing premise.",...t?.roundOf?[]:[`If its acceptance criteria ALREADY hold as the code stands, do no work: complete ${e.requestId} yourself as a verification-only completion, naming exactly which criteria hold and where. Nobody else closes it: a report saying so left req000210 in progress with nobody working it.`,'Otherwise build what it asks (its own choices go in an opening brief when the pickup briefing asks for one), run the relevant validation, and complete the request with evidence. A value the request states is the value: a version number, a label, a default. Do not bump or "improve" it (two coders raised a footer version the user had just set, 2026-09-07).']]
1915
+ return r.length&&n.push(`Possible duplicates already open with the same title: ${r.join(", ")}. Check before doing the work twice; if one already covers it, cancel ${e.requestId} as superseded.`),e.userNote&&n.push(`From the user: ${e.userNote}`),e.rules?.length&&n.push(function(e){const t=e.filter(e=>"told"===e.enforcement),r=e.filter(e=>"told"!==e.enforcement),s=[...t.map(e=>`- [guidance:${e.id}] ${e.text}`),...r.map(e=>`- [guidance:${e.id}] (reviewed, ${e.severity}) ${e.text}`)]
1916
+ return`The workflow's guidance for this work (the user's; where an item conflicts with the brief above, the guidance wins).${r.length?" A reviewer checks the reviewed ones by id at the review gate: 'block' ones must hold, 'advise' ones are expected.":""} When the user's own words make an exception to an item for this request, record it with guidance exception (its id as listed, their words, the scope they said); when the request contradicts an item and they have not said, guidance conflict, and follow the guidance until they answer.\n${s.join("\n")}`}(e.rules)),s&&n.push(`\n# ${e.requestId}: ${t?.title??""}\n${s}`),n.join("\n")}async function i(e,t){if(!t)return null
1917
+ try{const r=(0,_.simpleGit)(e),s=await r.diffSummary([`${t}..HEAD`])
1918
+ return{files:s.files.map(e=>({file:e.file,insertions:e.insertions??0,deletions:e.deletions??0})),insertions:s.insertions,deletions:s.deletions}}catch{return null}}async function a(e,t){if(!t)return[]
1919
+ try{const r=(0,_.simpleGit)(e)
1920
+ return(await r.raw(["diff","--name-only",`${t}^1`,t]).catch(async()=>r.raw(["diff","--name-only",`${t}^`,t]))).split("\n").map(e=>e.trim()).filter(Boolean)}catch{return[]}}async function c(e,t,r){const{apiClient:s,projectId:n,projectPath:o,logger:c}=e,{p:l,req:d,worker:u,startPrompt:h,toolMask:p,deps:m}=t,w=r.sessionId
1921
+ if(r.reopenLocalId)try{await s.patch(`/api/projects/${n}/cli-sessions/${encodeURIComponent(r.reopenLocalId)}`,{status:"active"})}catch(e){c.warn("session routing: could not reopen the cold worker",{requestId:l.requestId,sessionId:w,error:(0,$.getErrorMessage)(e)})}const v=!!t.req?.roundOf&&!!l.unitWorker&&w===l.unitWorker,b=v?s.post(`/api/projects/${n}/requests/${l.requestId}/pickup-compose`,{sessionId:w,agentType:u,warm:!0}).catch(()=>null):null
1922
+ let j=null
1923
+ if(!v)try{const e=await s.post(`/api/projects/${n}/requests/${l.requestId}/pickup-compose`,{sessionId:w,agentType:u,warm:!0})
1924
+ j=(e?.data??e)?.text??null,j=await(0,T.withInFlightFiles)(o,j,e?.data??e)}catch(e){c.warn("session routing: warm pickup guidance failed; sending the request alone",{requestId:l.requestId,error:(0,$.getErrorMessage)(e)})}let E=null
1925
+ if(!v)try{const e=r.previousRequestId?await s.get(`/api/projects/${n}/requests/${r.previousRequestId}`):null,t=(e?.data??e)?.mergeCommitSha??(e?.data??e)?.merge_commit_sha??null,[c,l]=await Promise.all([i(o,t),a(o,t)])
1926
+ E=(0,C.sinceYouLastLookedBlock)(c,r.previousRequestId,l)}catch{}const A=!!t.req?.roundOf,_=[A?null:(M=l.requestId,R=r.previousRequestId,P=r.area,[`${P?"Your next request":"Next request in your thread"}: ${M}. This is a NEW record: ${R?`${R} is closed and must not be reopened, re-verified or amended`:"the request you finished before is closed"}. Work on ${M}'s branch, not the old one.`,...P?["It is separate work in the same area, not a follow-up: take nothing over from what you did before except what you know of the code."]:[],"You already have this project in context, so do not re-read the map or the files you know; open only what this request changes."].join("\n")),h,E,j].filter(Boolean).join("\n\n"),x=await(m.deliver??((t,r)=>(0,y.deliverPrompt)(e,t,r,{kind:A?"unit-start":"inserted-prompt-generic",partPayload:{requestId:l.requestId,source:l.source},...(0,g.hasMask)(p)?{toolDenies:p}:{}})))(w,_)
1927
+ var M,R,P
1928
+ if(!1===x?.ok)return c.warn("session routing: delivery to the warm worker failed; spawning a fresh one",{requestId:l.requestId,sessionId:w,error:x?.error}),!1
1929
+ try{b&&await b,await async function(e,t,r){const{apiClient:s,projectId:n,logger:o}=e
1927
1930
  try{const e=await s.get(`/api/projects/${n}/session-request-associations?activeOnly=true&limit=500`),i=(e?.data??e??[]).filter(e=>(e?.requestLocalId??e?.request_local_id)===t).map(e=>String(e?.opencodeSessionId??e?.opencode_session_id??"")).filter(e=>e&&e!==r)
1928
1931
  if(!i.length)return
1929
- await s.post(`/api/projects/${n}/session-request-associations/end-all`,{requestLocalId:t}),o.info("session routing: released prior workers before hand-off",{requestId:t,released:i.length})}catch(e){o.warn("session routing: could not release prior workers",{requestId:t,error:(0,S.getErrorMessage)(e)})}}(e,l.requestId,y),await s.post(`/api/projects/${n}/session-request-associations`,{opencodeSessionId:y,requestLocalId:l.requestId,agentType:u})
1932
+ await s.post(`/api/projects/${n}/session-request-associations/end-all`,{requestLocalId:t}),o.info("session routing: released prior workers before hand-off",{requestId:t,released:i.length})}catch(e){o.warn("session routing: could not release prior workers",{requestId:t,error:(0,$.getErrorMessage)(e)})}}(e,l.requestId,w),await s.post(`/api/projects/${n}/session-request-associations`,{opencodeSessionId:w,requestLocalId:l.requestId,agentType:u})
1930
1933
  const t=`[${l.requestId}] ${l.verb??"Implement"} ${String(d?.title??"").trim()}`.trim().slice(0,160)
1931
- try{const e=(0,v.getOpenCodeUrlFromConfig)(a)
1932
- e&&await fetch(`${e.replace(/\/$/,"")}/session/${y}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:t}),signal:AbortSignal.timeout(5e3)}),await s.post(`/api/projects/${n}/cli-sessions`,{externalSessionId:y,providerId:"opencode",title:t})}catch(e){c.warn("session routing: warm worker not retitled",{requestId:l.requestId,sessionId:y,error:(0,S.getErrorMessage)(e)})}}catch(e){c.warn("session routing: could not associate the warm worker with the request",{requestId:l.requestId,sessionId:y,error:(0,S.getErrorMessage)(e)})}try{await(0,b.ensureRequestWorktree)(a,l.requestId,c)}catch(e){c.warn("start-worker: worktree for the warm worker failed",{requestId:l.requestId,error:(0,S.getErrorMessage)(e)})}return c.info(r.area?"session routing: request handed to a warm worker of its area (no thread link)":"session routing: request handed to the warm worker already on its thread",{requestId:l.requestId,sessionId:y,previous:r.previousRequestId}),"request"===(0,p.kindProfile)(d?.type).branch&&(g.prewarm??k.prewarmWorkerBox)(e,y,l.requestId),!0}async function c(e,t){const{apiClient:r,projectId:n,projectPath:o,logger:i}=e,{p:a,req:c,worker:l,startPrompt:d,toolMask:u,deps:h}=t,f="string"==typeof a.verb&&a.verb.trim()||(0,p.kindProfile)(c?.type).verb,w=(e,t)=>{const r=String(t??"").slice(0,50)
1934
+ try{const e=(0,k.getOpenCodeUrlFromConfig)(o)
1935
+ e&&await fetch(`${e.replace(/\/$/,"")}/session/${w}`,{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:t}),signal:AbortSignal.timeout(5e3)}),await s.post(`/api/projects/${n}/cli-sessions`,{externalSessionId:w,providerId:"opencode",title:t})}catch(e){c.warn("session routing: warm worker not retitled",{requestId:l.requestId,sessionId:w,error:(0,$.getErrorMessage)(e)})}}catch(e){c.warn("session routing: could not associate the warm worker with the request",{requestId:l.requestId,sessionId:w,error:(0,$.getErrorMessage)(e)})}try{await(0,S.ensureRequestWorktree)(o,l.requestId,c)}catch(e){c.warn("start-worker: worktree for the warm worker failed",{requestId:l.requestId,error:(0,$.getErrorMessage)(e)})}return c.info(r.area?"session routing: request handed to a warm worker of its area (no thread link)":"session routing: request handed to the warm worker already on its thread",{requestId:l.requestId,sessionId:w,previous:r.previousRequestId}),"request"===(0,f.kindProfile)(d?.type).branch&&(m.prewarm??I.prewarmWorkerBox)(e,w,l.requestId),!0}async function l(e,t){const{apiClient:r,projectId:n,projectPath:o,logger:i}=e,{p:a,req:c,worker:l,startPrompt:d,toolMask:u,deps:h}=t,p="string"==typeof a.verb&&a.verb.trim()||(0,f.kindProfile)(c?.type).verb,m=(e,t)=>{const r=String(t??"").slice(0,50)
1933
1936
  return r.toLowerCase().startsWith(`${e.toLowerCase()} `)?r:`${e} ${r}`},y=function(e){if(e&&(e.tier||e.provider))return{...e.tier?{modelTier:e.tier}:{},...e.provider?{provider:e.provider}:{}}}(a.model)
1934
1937
  if(!await(h.agentLoaded??s)(e,l,39e4))return{success:!1,message:`start-worker: the agent "${l}" has not loaded in this project's runtime, so ${a.requestId} has nobody to start on. A new or changed agent loads when running work pauses; start the request again then, or restart AlchemyLab in the project folder.`,error:"agent_not_loaded"}
1935
- const v=h.spawnCoder??(async()=>(0,g.spawnActionAgent)({agent:l,prompt:d,cwd:o,projectPath:o,projectId:n,title:`[${a.requestId}] ${w(f,c?.title)}`,requestId:a.requestId,parentSessionId:a.hubSessionId,apiClient:r,logger:i,trackChildPid:e.trackChildPid,...(0,m.hasMask)(u)?{toolMask:u}:{},...y?{modelOverride:y}:{}})),b=await v(d,{modelOverride:y})
1936
- return b?.refused?(i.info("start-worker: the request already has its worker; nothing spawned",{requestId:a.requestId,reason:b?.error}),{success:!0,message:`${a.requestId} already has its worker; no second one started`}):b?.success&&b?.sessionId?(i.info("session routing: worker spawned onto the request",{requestId:a.requestId,worker:l,sessionId:b.sessionId}),"request"===(0,p.kindProfile)(c?.type).branch&&(h.prewarm??k.prewarmWorkerBox)(e,b.sessionId,a.requestId),{success:!0,message:`${a.requestId} handed to ${l} ${b.sessionId}`}):{success:!1,message:`start-worker: could not start a ${l} session for ${a.requestId}`,error:b?.error??"spawn_failed"}}async function l(e,t,r){const{apiClient:s,projectId:n,projectPath:o}=e,i=(0,v.getOpenCodeUrlFromConfig)(o)
1938
+ const b=h.spawnCoder??(async()=>(0,w.spawnActionAgent)({agent:l,prompt:d,cwd:o,projectPath:o,projectId:n,title:`[${a.requestId}] ${m(p,c?.title)}`,requestId:a.requestId,parentSessionId:a.hubSessionId,apiClient:r,logger:i,trackChildPid:e.trackChildPid,...(0,g.hasMask)(u)?{toolMask:u}:{},...y?{modelOverride:y}:{}})),k=await b(d,{modelOverride:y})
1939
+ return k?.refused?(i.info("start-worker: the request already has its worker; nothing spawned",{requestId:a.requestId,reason:k?.error}),{success:!0,message:`${a.requestId} already has its worker; no second one started`}):k?.success&&k?.sessionId?(i.info("session routing: worker spawned onto the request",{requestId:a.requestId,worker:l,sessionId:k.sessionId}),c?.roundOf&&"string"==typeof k.promptMessageId&&k.promptMessageId&&(0,v.trackInboxChatTurn)(e,k.sessionId,Date.now(),k.promptMessageId,void 0,void 0,void 0,void 0,{kind:"unit-start",requestId:a.requestId}),"request"===(0,f.kindProfile)(c?.type).branch&&(h.prewarm??I.prewarmWorkerBox)(e,k.sessionId,a.requestId),{success:!0,message:`${a.requestId} handed to ${l} ${k.sessionId}`}):{success:!1,message:`start-worker: could not start a ${l} session for ${a.requestId}`,error:k?.error??"spawn_failed"}}async function d(e,t,r){const{apiClient:s,projectId:n,projectPath:o}=e,i=(0,k.getOpenCodeUrlFromConfig)(o)
1937
1940
  if(!i)return{busy:!1,liveElsewhere:null}
1938
- const a=await(0,w.sessionBusy)(i.replace(/\/$/,""),t)
1939
- return a?{busy:a,liveElsewhere:await d(e,t,r)}:{busy:!1,liveElsewhere:null}}async function d(e,t,r){const{apiClient:s,projectId:n}=e
1941
+ const a=await(0,y.sessionBusy)(i.replace(/\/$/,""),t)
1942
+ return a?{busy:a,liveElsewhere:await u(e,t,r)}:{busy:!1,liveElsewhere:null}}async function u(e,t,r){const{apiClient:s,projectId:n}=e
1940
1943
  try{const e=await s.get(`/api/projects/${n}/session-request-associations/by-session/${encodeURIComponent(t)}`),o=Array.isArray(e?.data)?e.data:Array.isArray(e)?e:[],i=Array.from(new Set(o.map(e=>String(e?.requestLocalId??e?.request_local_id??"")).filter(e=>/^req\d+$/.test(e)&&e!==r)))
1941
1944
  for(const e of i){const t=await s.get(`/api/projects/${n}/requests/${e}`).catch(()=>null),r=String((t?.data??t)?.status??"")
1942
- if(!x.has(r))return e}return null}catch{return null}}async function u(e,t){if(t)try{const r=await e.apiClient.get(`/api/projects/${e.projectId}/requests/${t}`),s=(r?.data??r)?.mergeCommitSha??(r?.data??r)?.merge_commit_sha??null
1945
+ if(!R.has(r))return e}return null}catch{return null}}async function h(e,t){if(t)try{const r=await e.apiClient.get(`/api/projects/${e.projectId}/requests/${t}`),s=(r?.data??r)?.mergeCommitSha??(r?.data??r)?.merge_commit_sha??null
1943
1946
  if(!s)return
1944
- const[n,a]=await Promise.all([o(e.projectPath,s),i(e.projectPath,s)])
1947
+ const[n,o]=await Promise.all([i(e.projectPath,s),a(e.projectPath,s)])
1945
1948
  if(!n)return
1946
- const c=new Set(a)
1947
- return n.files.filter(e=>c.has(e.file)).reduce((e,t)=>e+t.insertions+t.deletions,0)}catch{return}}async function h(e,t){const{apiClient:r,projectId:s,projectPath:n,logger:o}=e,i=e.startWorkerDeps??{}
1948
- try{const a=await r.get(`/api/projects/${s}`),c=(0,$.readWarmCoderPolicy)((a?.data??a)?.metadata)
1949
+ const c=new Set(o)
1950
+ return n.files.filter(e=>c.has(e.file)).reduce((e,t)=>e+t.insertions+t.deletions,0)}catch{return}}async function p(e,t){const{apiClient:r,projectId:s,projectPath:n,logger:o}=e,i=e.startWorkerDeps??{}
1951
+ try{const a=await r.get(`/api/projects/${s}`),c=(0,E.readWarmCoderPolicy)((a?.data??a)?.metadata)
1949
1952
  if(!c.enabled)return{why:"off"}
1950
- const l=(0,v.getOpenCodeUrlFromConfig)(n),h=i.reloadedAt??(0,j.configReloadedAt)(n),p=i.lastCall??(e=>l?(0,j.readLastCall)(l,e):Promise.resolve({})),m=i.modelLimits??(l?await(0,j.readModelLimits)(l):new Map),g=new Set,w=new Map
1953
+ const l=(0,k.getOpenCodeUrlFromConfig)(n),d=i.reloadedAt??(0,A.configReloadedAt)(n),p=i.lastCall??(e=>l?(0,A.readLastCall)(l,e):Promise.resolve({})),f=i.modelLimits??(l?await(0,A.readModelLimits)(l):new Map),g=new Set,w=new Map
1951
1954
  if(l){const[e,t]=await Promise.all([fetch(`${l}/session`,{signal:AbortSignal.timeout(6e3)}).catch(()=>null),fetch(`${l}/session/status`,{signal:AbortSignal.timeout(6e3)}).catch(()=>null)])
1952
1955
  if(e?.ok){const t=await e.json().catch(()=>[])
1953
1956
  for(const e of t)w.set(e.id,Number(e.time?.updated??e.time?.created??0))}if(t?.ok){const e=await t.json().catch(()=>({}))
1954
- for(const[t,r]of Object.entries(e??{}))"busy"===r?.type&&g.add(t)}}const y=await(0,f.readAllPages)(r,e=>`/api/projects/${s}/cli-sessions?status=active&limit=100&offset=${e}`),b=new Set
1957
+ for(const[t,r]of Object.entries(e??{}))"busy"===r?.type&&g.add(t)}}const y=await(0,m.readAllPages)(r,e=>`/api/projects/${s}/cli-sessions?status=active&limit=100&offset=${e}`),v=new Set
1955
1958
  try{const e=await r.get(`/api/projects/${s}/requests/${t.requestId}/arc`)
1956
- for(const t of(e?.data??e)?.requests??[])t?.localId&&b.add(String(t.localId))}catch{}if(t.planDocumentId)try{const e=await(0,f.readAllPages)(r,e=>`/api/projects/${s}/requests?planDocumentId=${encodeURIComponent(t.planDocumentId)}&limit=100&offset=${e}`)
1957
- for(const t of e)(t?.localId??t?.id)&&b.add(String(t.localId??t.id))}catch{}for(const e of t.waitedOn??[])/^req\d{6}$/.test(e)&&b.add(e)
1958
- b.delete(t.requestId)
1959
- const k=new Map,S=new Map,I=new Map
1959
+ for(const t of(e?.data??e)?.requests??[])t?.localId&&v.add(String(t.localId))}catch{}if(t.planDocumentId)try{const e=await(0,m.readAllPages)(r,e=>`/api/projects/${s}/requests?planDocumentId=${encodeURIComponent(t.planDocumentId)}&limit=100&offset=${e}`)
1960
+ for(const t of e)(t?.localId??t?.id)&&v.add(String(t.localId??t.id))}catch{}for(const e of t.waitedOn??[])/^req\d{6}$/.test(e)&&v.add(e)
1961
+ v.delete(t.requestId)
1962
+ const b=new Map,S=new Map,I=new Map
1960
1963
  try{const e=await r.get(`/api/projects/${s}/session-request-associations?limit=500`)
1961
1964
  for(const r of e?.data??e??[]){const e=String(r?.opencodeSessionId??r?.opencode_session_id??""),s=String(r?.requestLocalId??r?.request_local_id??"")
1962
1965
  if(!e||!s||s===t.requestId)continue
1963
- b.has(s)&&k.set(e,(k.get(e)??0)+1)
1966
+ v.has(s)&&b.set(e,(b.get(e)??0)+1)
1964
1967
  const n=Date.parse(r?.startedAt??r?.started_at??"")||0
1965
- n>=(I.get(e)??-1)&&(I.set(e,n),S.set(e,s))}}catch{}const E=new Set(y.map(e=>e?.externalSessionId).filter(Boolean))
1966
- if(c.coldResume)for(const e of Array.from(k.keys()))if(!E.has(e))try{const t=await r.get(`/api/projects/${s}/cli-sessions/external/opencode/${encodeURIComponent(e)}`),n=t?.data??t
1967
- n?.externalSessionId&&"archived"===n.status&&y.push(n)}catch{}const A=new Map,C=[]
1968
+ n>=(I.get(e)??-1)&&(I.set(e,n),S.set(e,s))}}catch{}const $=new Set(y.map(e=>e?.externalSessionId).filter(Boolean))
1969
+ if(c.coldResume)for(const e of Array.from(b.keys()))if(!$.has(e))try{const t=await r.get(`/api/projects/${s}/cli-sessions/external/opencode/${encodeURIComponent(e)}`),n=t?.data??t
1970
+ n?.externalSessionId&&"archived"===n.status&&y.push(n)}catch{}const j=new Map,C=[]
1968
1971
  for(const n of y){const o=n?.externalSessionId
1969
- if(!o||!(0,$.sameWorkerRole)(n.agentType,t.worker))continue
1972
+ if(!o||!(0,E.sameWorkerRole)(n.agentType,t.worker))continue
1970
1973
  const a=/\[(req\d{6})\]/.exec(String(n.title??""))
1971
1974
  !S.has(o)&&a&&S.set(o,a[1])
1972
- let l="",f=[]
1975
+ let l="",m=[]
1973
1976
  const y=S.get(o)
1974
1977
  if(y)try{const e=await r.get(`/api/projects/${s}/requests/${y}`)
1975
1978
  l=String((e?.data??e)?.type??"")
1976
1979
  const t=(e?.data??e)?.areas
1977
- Array.isArray(t)&&(f=t.map(String))}catch{}const v=(0,$.sharedAreas)(t.areas,f),b=g.has(o);(n.localId??n.id)&&A.set(o,String(n.localId??n.id))
1978
- const I=(k.get(o)??0)>0,j=c.areaReuse&&v>0,E=I||j?await p(o):{},_=Math.max(w.get(o)??0,E.atMs??0)||Date.parse(n.updatedAt??n.createdAt??"")||0,T=E.providerID&&E.modelID?m.get(`${E.providerID}/${E.modelID}`):void 0,x="archived"!==n.status&&(0,$.isCacheWarm)(Date.now(),{lastActiveMs:_,providerID:E.providerID},h),M=c.coldResume&&I&&!b&&!x?await(i.changedSince??(t=>u(e,t)))(y):void 0
1979
- C.push({...void 0!==E.contextTokens?{contextTokens:E.contextTokens}:{},...void 0!==M?{changedSinceLines:M}:{},...I||j?{contextCeiling:(0,$.contextCeilingFor)(T)}:{},providerID:E.providerID??null,externalSessionId:o,agentType:n.agentType,threadRequests:k.get(o)??0,sharedAreas:v,modelKey:(0,$.modelKeyOf)(t.kindModels,l),toolsKey:(0,$.toolsKeyOf)(l),lastActiveMs:_,busy:b,busyElsewhere:b&&(k.get(o)??0)>0?!!await d(e,o,t.requestId):void 0,archived:"archived"===n.status})}const _=(0,$.pickWarmCoder)(c,Date.now(),{worker:t.worker,modelKey:(0,$.modelKeyOf)(t.kindModels,t.kind),toolsKey:(0,$.toolsKeyOf)(t.kind)},C,h)
1980
- if(!_.reuse){const e=C.filter(e=>(e.threadRequests??0)>0&&(e.archived||!(0,$.isCacheWarm)(Date.now(),e,h))&&(void 0!==e.contextTokens||void 0!==e.changedSinceLines))
1980
+ Array.isArray(t)&&(m=t.map(String))}catch{}const v=(0,E.sharedAreas)(t.areas,m),k=g.has(o);(n.localId??n.id)&&j.set(o,String(n.localId??n.id))
1981
+ const I=(b.get(o)??0)>0,$=c.areaReuse&&v>0,A=I||$?await p(o):{},_=Math.max(w.get(o)??0,A.atMs??0)||Date.parse(n.updatedAt??n.createdAt??"")||0,T=A.providerID&&A.modelID?f.get(`${A.providerID}/${A.modelID}`):void 0,x="archived"!==n.status&&(0,E.isCacheWarm)(Date.now(),{lastActiveMs:_,providerID:A.providerID},d),M=c.coldResume&&I&&!k&&!x?await(i.changedSince??(t=>h(e,t)))(y):void 0
1982
+ C.push({...void 0!==A.contextTokens?{contextTokens:A.contextTokens}:{},...void 0!==M?{changedSinceLines:M}:{},...I||$?{contextCeiling:(0,E.contextCeilingFor)(T)}:{},providerID:A.providerID??null,externalSessionId:o,agentType:n.agentType,threadRequests:b.get(o)??0,sharedAreas:v,modelKey:(0,E.modelKeyOf)(t.kindModels,l),toolsKey:(0,E.toolsKeyOf)(l),lastActiveMs:_,busy:k,busyElsewhere:k&&(b.get(o)??0)>0?!!await u(e,o,t.requestId):void 0,archived:"archived"===n.status})}const _=(0,E.pickWarmCoder)(c,Date.now(),{worker:t.worker,modelKey:(0,E.modelKeyOf)(t.kindModels,t.kind),toolsKey:(0,E.toolsKeyOf)(t.kind)},C,d)
1983
+ if(!_.reuse){const e=C.filter(e=>(e.threadRequests??0)>0&&(e.archived||!(0,E.isCacheWarm)(Date.now(),e,d))&&(void 0!==e.contextTokens||void 0!==e.changedSinceLines))
1981
1984
  return e.length&&o.info("session routing: cold thread worker weighed and not resumed",{requestId:t.requestId,why:_.why,limits:{contextTokens:c.coldMaxContextTokens,changedLines:c.coldMaxChangedLines},weighed:e.map(e=>({sessionId:e.externalSessionId,contextTokens:e.contextTokens,changedSinceLines:e.changedSinceLines}))}),{why:_.why}}const T=C.find(e=>e.externalSessionId===_.sessionId)
1982
- return o.info(_.cold?"session routing: cold worker chosen (it built this thread and its code is still current)":_.area?"session routing: warm worker of the same area chosen (no thread link)":"session routing: warm worker chosen",{requestId:t.requestId,sessionId:_.sessionId,threadRequestsWorked:k.get(_.sessionId)??0,..._.area?{sharedAreas:T?.sharedAreas}:{},contextTokens:T?.contextTokens,contextCeiling:T?.contextCeiling,provider:T?.providerID??void 0,afterTurn:!!_.afterTurn,candidates:C.length,..._.cold?{changedSinceLines:T?.changedSinceLines,archived:!!T?.archived}:{}}),{sessionId:_.sessionId,previousRequestId:S.get(_.sessionId),..._.afterTurn?{afterTurn:!0}:{},..._.area?{area:!0}:{},..._.cold&&T?.archived?{reopenLocalId:A.get(_.sessionId)}:{}}}catch(e){return o.warn("session routing: warm-worker survey failed; spawning",{error:(0,S.getErrorMessage)(e)}),{why:"no-candidate"}}}exports.handleStartWorkerAction=async function(e,t){const s=e,{apiClient:o,projectId:i,logger:d}=t
1985
+ return o.info(_.cold?"session routing: cold worker chosen (it built this thread and its code is still current)":_.area?"session routing: warm worker of the same area chosen (no thread link)":"session routing: warm worker chosen",{requestId:t.requestId,sessionId:_.sessionId,threadRequestsWorked:b.get(_.sessionId)??0,..._.area?{sharedAreas:T?.sharedAreas}:{},contextTokens:T?.contextTokens,contextCeiling:T?.contextCeiling,provider:T?.providerID??void 0,afterTurn:!!_.afterTurn,candidates:C.length,..._.cold?{changedSinceLines:T?.changedSinceLines,archived:!!T?.archived}:{}}),{sessionId:_.sessionId,previousRequestId:S.get(_.sessionId),..._.afterTurn?{afterTurn:!0}:{},..._.area?{area:!0}:{},..._.cold&&T?.archived?{reopenLocalId:j.get(_.sessionId)}:{}}}catch(e){return o.warn("session routing: warm-worker survey failed; spawning",{error:(0,$.getErrorMessage)(e)}),{why:"no-candidate"}}}exports.handleStartWorkerAction=async function(e,t){const s=e,{apiClient:i,projectId:a,logger:u}=t
1983
1986
  if(!s.requestId)return{success:!1,message:"requestId is required",error:"missing_params"}
1984
- const u=t.startWorkerDeps??{},g=await o.get(`/api/projects/${i}/requests/${s.requestId}`),w=g?.data??g
1985
- if(!w||!["open"].includes(w.status))return{success:!0,message:`${s.requestId} is ${w?.status??"unknown"}: nothing to start`}
1986
- const v=T.get(s.requestId)
1987
+ const h=t.startWorkerDeps??{},w=await i.get(`/api/projects/${a}/requests/${s.requestId}`),y=w?.data??w
1988
+ if(!y||!["open"].includes(y.status))return{success:!0,message:`${s.requestId} is ${y?.status??"unknown"}: nothing to start`}
1989
+ const v=M.get(s.requestId)
1987
1990
  if(v)return{success:!0,message:`${s.requestId} starts on ${v} when its current turn ends`}
1988
- try{const e=async e=>{const t=await o.get(`/api/projects/${i}/requests/${e}`)
1991
+ if(y.roundOf&&"string"==typeof s.unitWorker&&s.unitWorker&&null!==(0,f.kindProfile)(y.type).worker)try{const[e,r]=await Promise.all([(h.turnState??d)(t,s.unitWorker,s.requestId),(h.requestRecord??n)(t,s.requestId,y)])
1992
+ if(!e.busy){const e="string"==typeof s.worker&&s.worker.trim()||(0,f.kindProfile)(y?.type).worker||"worker",n=(0,g.spawnToolMask)({kind:y?.type,hasTestProcess:"boolean"==typeof s.hasTestProcess?s.hasTestProcess:void 0}),i={p:s,req:y,worker:e,startPrompt:o(s,y,[],r),toolMask:n,deps:h}
1993
+ if(await c(t,i,{sessionId:s.unitWorker,previousRequestId:y.roundOf}))return{success:!0,message:`${s.requestId} handed to ${y.roundOf}'s own ${e} ${s.unitWorker}`}}}catch(e){u.info("session routing: the unit did not go straight to its request's worker; the ordinary start takes it",{requestId:s.requestId,error:(0,$.getErrorMessage)(e)})}try{const e=async e=>{const t=await i.get(`/api/projects/${a}/requests/${e}`)
1989
1994
  return(t?.data??t)?.type}
1990
- t.projectPath&&await(0,_.defaultBranchHasCode)(t.projectPath,e)&&(await(0,_.reportProjectHasCode)(i,!0,(e,t)=>o.patch(e,t)),await o.post(`/api/projects/${i}/requests/${s.requestId}/test-setup-offer`,{...s.creatorSessionId?{creatorSessionId:s.creatorSessionId}:{}}))}catch(e){d.warn("test-check card could not be asked for (the start goes on)",{requestId:s.requestId,error:(0,S.getErrorMessage)(e)})}const b=await(u.openDuplicates??r)(t,w,s.requestId),k=await(u.requestRecord??n)(t,s.requestId,w),I=function(e,t,r,s){const n=[`Implement ${e.requestId} ("${t?.title??""}") and own its full lifecycle. It was registered via ${e.source??"a registration door"}.`,s?"Its record, as get_request_information shows it now, is at the end of this message: start from it, and read the request again only when you need what changed since. If something it BUILDS ON does not exist in this project, call request_operations premise-block with the reason instead of starting. New content the request introduces is not a missing premise.":"Read it with get_request_information first. If something it BUILDS ON does not exist in this project, call request_operations premise-block with the reason instead of starting. New content the request introduces is not a missing premise.",...t?.roundOf?[]:[`If its acceptance criteria ALREADY hold as the code stands, do no work: complete ${e.requestId} yourself as a verification-only completion, naming exactly which criteria hold and where. Nobody else closes it: a report saying so left req000210 in progress with nobody working it.`,'Otherwise build what it asks (its own choices go in an opening brief when the pickup briefing asks for one), run the relevant validation, and complete the request with evidence. A value the request states is the value: a version number, a label, a default. Do not bump or "improve" it (two coders raised a footer version the user had just set, 2026-09-07).']]
1991
- return r.length&&n.push(`Possible duplicates already open with the same title: ${r.join(", ")}. Check before doing the work twice; if one already covers it, cancel ${e.requestId} as superseded.`),e.userNote&&n.push(`From the user: ${e.userNote}`),e.rules?.length&&n.push(function(e){const t=e.filter(e=>"told"===e.enforcement),r=e.filter(e=>"told"!==e.enforcement),s=[...t.map(e=>`- [guidance:${e.id}] ${e.text}`),...r.map(e=>`- [guidance:${e.id}] (reviewed, ${e.severity}) ${e.text}`)]
1992
- return`The workflow's guidance for this work (the user's; where an item conflicts with the brief above, the guidance wins).${r.length?" A reviewer checks the reviewed ones by id at the review gate: 'block' ones must hold, 'advise' ones are expected.":""} When the user's own words make an exception to an item for this request, record it with guidance exception (its id as listed, their words, the scope they said); when the request contradicts an item and they have not said, guidance conflict, and follow the guidance until they answer.\n${s.join("\n")}`}(e.rules)),s&&n.push(`\n# ${e.requestId}: ${t?.title??""}\n${s}`),n.join("\n")}(s,w,b,k),j="string"==typeof s.worker&&s.worker.trim()||(0,p.kindProfile)(w?.type).worker||"worker",E=(0,m.spawnToolMask)({kind:w?.type,hasTestProcess:"boolean"==typeof s.hasTestProcess?s.hasTestProcess:void 0});(0,m.hasMask)(E)&&d.info("session routing: narrowing the worker tool surface for this request",{requestId:s.requestId,worker:j,off:Object.keys(E)})
1993
- const A={p:s,req:w,worker:j,startPrompt:I,toolMask:E,deps:u}
1994
- let C=null
1995
- const x=w?.filedBySession??w?.filed_by_session,M=w?.filedByAgent??w?.filed_by_agent
1996
- if("string"==typeof x&&x&&(0,$.sameWorkerRole)(M,j))try{if((await(0,f.readAllPages)(o,e=>`/api/projects/${i}/cli-sessions?status=active&limit=100&offset=${e}`)).some(e=>e?.externalSessionId===x)){const e=await(u.turnState??l)(t,x,s.requestId)
1997
- e.liveElsewhere?d.info("session routing: the filer is mid-turn on another live request; not handing it this one",{requestId:s.requestId,sessionId:x,on:e.liveElsewhere}):(C={sessionId:x},d.info("session routing: the session that filed this request keeps it",{requestId:s.requestId,sessionId:x}))}}catch{}if(C=C??await(u.pickWarm??h)(t,{worker:j,requestId:s.requestId,kind:w?.type,kindModels:s.kindModels,planDocumentId:w?.planDocumentId??w?.plan_document_id??null,areas:Array.isArray(w?.areas)?w.areas.map(String):[],waitedOn:Array.isArray(w?.waitedOn)?w.waitedOn.map(String):[]}),C?.sessionId){const e=C.sessionId,r=await(u.turnState??l)(t,e,s.requestId)
1998
- if(r.liveElsewhere)d.info("session routing: the chosen worker is mid-turn on another live request; spawning instead",{requestId:s.requestId,sessionId:e,on:r.liveElsewhere})
1999
- else{if(r.busy)return T.set(s.requestId,e),(u.whenIdle??((e,r)=>(0,y.whenSessionIdle)(e,async()=>(await l(t,e,s.requestId)).busy,r)))(e,e=>{(async function(e,t,r,s){const{apiClient:n,projectId:o,logger:i}=e,{p:d}=t
2000
- try{const u=await n.get(`/api/projects/${o}/requests/${d.requestId}`),h=u?.data??u
2001
- if(!h||"open"!==h.status)return void i.info("session routing: the request moved on while its worker finished a turn; nothing to hand over",{requestId:d.requestId,status:h?.status??"unknown"})
2002
- const p=await(t.deps.turnState??l)(e,r.sessionId,d.requestId)
2003
- if("idle"===s&&!p.busy&&!p.liveElsewhere&&await a(e,{...t,req:h},r))return
2004
- i.info("session routing: the worker did not come free for this start; spawning",{requestId:d.requestId,sessionId:r.sessionId,why:s,busy:p.busy,on:p.liveElsewhere}),await c(e,{...t,req:h})}catch(e){i.warn("session routing: the start after a turn failed",{requestId:d.requestId,sessionId:r.sessionId,error:(0,S.getErrorMessage)(e)})}})(t,A,C,e).finally(()=>T.delete(s.requestId))}),d.info("session routing: the thread's worker is finishing a turn; the start is handed over when it ends",{requestId:s.requestId,sessionId:e,previous:C.previousRequestId}),{success:!0,message:`${s.requestId} starts on warm ${j} ${e} when its current turn ends (the thread shares the session)`}
2005
- if(await a(t,A,C))return{success:!0,message:`${s.requestId} handed to warm ${j} ${e} (${C.area?"same area, separate work":"the thread shares the session"})`}}}else C?.why&&d.info(`session routing: spawning, because ${(0,$.whyNotReused)(C.why)}`,{requestId:s.requestId,why:C.why})
2006
- return c(t,A)}
2007
- const p=t(87780),f=t(5641),m=t(45687),g=t(28148),w=t(17039),y=t(67078),v=t(60833),b=t(2424),k=t(23687),S=t(58824),I=t(65454),$=t(64469),j=t(81570),E=t(76379),A=t(83807),C=t(47912),_=t(71879),T=new Map,x=new Set(["completed","canceled","reverted"])},82928(e,exports,t){"use strict"
1995
+ t.projectPath&&await(0,x.defaultBranchHasCode)(t.projectPath,e)&&(await(0,x.reportProjectHasCode)(a,!0,(e,t)=>i.patch(e,t)),await i.post(`/api/projects/${a}/requests/${s.requestId}/test-setup-offer`,{...s.creatorSessionId?{creatorSessionId:s.creatorSessionId}:{}}))}catch(e){u.warn("test-check card could not be asked for (the start goes on)",{requestId:s.requestId,error:(0,$.getErrorMessage)(e)})}const k=await(h.openDuplicates??r)(t,y,s.requestId),S=await(h.requestRecord??n)(t,s.requestId,y),I=o(s,y,k,S),j="string"==typeof s.worker&&s.worker.trim()||(0,f.kindProfile)(y?.type).worker||"worker",A=(0,g.spawnToolMask)({kind:y?.type,hasTestProcess:"boolean"==typeof s.hasTestProcess?s.hasTestProcess:void 0});(0,g.hasMask)(A)&&u.info("session routing: narrowing the worker tool surface for this request",{requestId:s.requestId,worker:j,off:Object.keys(A)})
1996
+ const C={p:s,req:y,worker:j,startPrompt:I,toolMask:A,deps:h}
1997
+ let _=null
1998
+ const T=y?.filedBySession??y?.filed_by_session,R=y?.filedByAgent??y?.filed_by_agent
1999
+ if("string"==typeof T&&T&&(0,E.sameWorkerRole)(R,j))try{if((await(0,m.readAllPages)(i,e=>`/api/projects/${a}/cli-sessions?status=active&limit=100&offset=${e}`)).some(e=>e?.externalSessionId===T)){const e=await(h.turnState??d)(t,T,s.requestId)
2000
+ e.liveElsewhere?u.info("session routing: the filer is mid-turn on another live request; not handing it this one",{requestId:s.requestId,sessionId:T,on:e.liveElsewhere}):(_={sessionId:T},u.info("session routing: the session that filed this request keeps it",{requestId:s.requestId,sessionId:T}))}}catch{}if(_=_??await(h.pickWarm??p)(t,{worker:j,requestId:s.requestId,kind:y?.type,kindModels:s.kindModels,planDocumentId:y?.planDocumentId??y?.plan_document_id??null,areas:Array.isArray(y?.areas)?y.areas.map(String):[],waitedOn:Array.isArray(y?.waitedOn)?y.waitedOn.map(String):[]}),_?.sessionId){const e=_.sessionId,r=await(h.turnState??d)(t,e,s.requestId)
2001
+ if(r.liveElsewhere)u.info("session routing: the chosen worker is mid-turn on another live request; spawning instead",{requestId:s.requestId,sessionId:e,on:r.liveElsewhere})
2002
+ else{if(r.busy)return M.set(s.requestId,e),(h.whenIdle??((e,r)=>(0,b.whenSessionIdle)(e,async()=>(await d(t,e,s.requestId)).busy,r)))(e,e=>{(async function(e,t,r,s){const{apiClient:n,projectId:o,logger:i}=e,{p:a}=t
2003
+ try{const u=await n.get(`/api/projects/${o}/requests/${a.requestId}`),h=u?.data??u
2004
+ if(!h||"open"!==h.status)return void i.info("session routing: the request moved on while its worker finished a turn; nothing to hand over",{requestId:a.requestId,status:h?.status??"unknown"})
2005
+ const p=await(t.deps.turnState??d)(e,r.sessionId,a.requestId)
2006
+ if("idle"===s&&!p.busy&&!p.liveElsewhere&&await c(e,{...t,req:h},r))return
2007
+ i.info("session routing: the worker did not come free for this start; spawning",{requestId:a.requestId,sessionId:r.sessionId,why:s,busy:p.busy,on:p.liveElsewhere}),await l(e,{...t,req:h})}catch(e){i.warn("session routing: the start after a turn failed",{requestId:a.requestId,sessionId:r.sessionId,error:(0,$.getErrorMessage)(e)})}})(t,C,_,e).finally(()=>M.delete(s.requestId))}),u.info("session routing: the thread's worker is finishing a turn; the start is handed over when it ends",{requestId:s.requestId,sessionId:e,previous:_.previousRequestId}),{success:!0,message:`${s.requestId} starts on warm ${j} ${e} when its current turn ends (the thread shares the session)`}
2008
+ if(await c(t,C,_))return{success:!0,message:`${s.requestId} handed to warm ${j} ${e} (${_.area?"same area, separate work":"the thread shares the session"})`}}}else _?.why&&u.info(`session routing: spawning, because ${(0,E.whyNotReused)(_.why)}`,{requestId:s.requestId,why:_.why})
2009
+ return l(t,C)}
2010
+ const f=t(87780),m=t(5641),g=t(45687),w=t(28148),y=t(17039),v=t(86116),b=t(67078),k=t(60833),S=t(2424),I=t(23687),$=t(58824),j=t(65454),E=t(64469),A=t(81570),C=t(76379),_=t(83807),T=t(47912),x=t(71879),M=new Map,R=new Set(["completed","canceled","reverted"])},82928(e,exports,t){"use strict"
2008
2011
  function r(e){let t=0
2009
2012
  for(const r of[...e??[]].reverse())if("user"===r?.info?.role&&!(r.parts??[]).some(e=>!0===e?.metadata?.alchemy?.payload?.nudge&&!0===e?.metadata?.alchemy?.payload?.restart)){if(!(r.parts??[]).some(e=>!0===e?.metadata?.alchemy?.payload?.nudge))break
2010
2013
  t++}return t}function s(e,t){return(e??[]).some(e=>"assistant"===e?.info?.role&&(e.info.time?.created??0)>t&&(e.parts??[]).some(e=>"tool"===e?.type))}function n(e,t){const r=String(e??"").match(/^ProviderQuotaError(?:\(([\w-]+)\))?/)
@@ -5533,18 +5536,18 @@ const i=(async()=>{try{const r=await e.get(`/api/projects/${s}/agents`),n=r?.dat
5533
5536
  return t.set(s,{agents:n,timestamp:Date.now()}),n}finally{r.delete(s)}})()
5534
5537
  return r.set(s,i),i}
5535
5538
  const t=new Map,r=new Map},86116(e,exports,t){"use strict"
5536
- function r(e){return!!e.systemNoteRequestId||!!e.systemWake}function s(e){return se.join(e,".alchemy_lab","inbox-watches.json")}function n(e){try{const t=[...ce.entries()].filter(([,t])=>t.projectPath===e).map(([e,t])=>({sessionId:e,exchanges:t.exchanges.map(e=>({markerMessageId:e.markerMessageId,injectedAtMs:e.injectedAtMs,...e.exchangeKey?{exchangeKey:e.exchangeKey}:{},...e.askAnnotationId?{askAnnotationId:e.askAnnotationId}:{},...e.systemNoteRequestId?{systemNoteRequestId:e.systemNoteRequestId}:{},...e.systemWake?{systemWake:e.systemWake}:{},...e.resumes?{resumes:e.resumes}:{}})),...t.resumed?{resumed:!0}:{},...t.asideAnswered?.length?{asideAnswered:t.asideAnswered}:{},...t.relayedIds?.length?{relayedIds:t.relayedIds}:{},...t.held?.length?{held:t.held}:{}})),r=s(e)
5537
- if(0===t.length)return void(re.existsSync(r)&&re.unlinkSync(r))
5539
+ function r(e){return!!e.systemNoteRequestId||!!e.systemWake}function s(e){return ne.join(e,".alchemy_lab","inbox-watches.json")}function n(e){try{const t=[...le.entries()].filter(([,t])=>t.projectPath===e).map(([e,t])=>({sessionId:e,exchanges:t.exchanges.map(e=>({markerMessageId:e.markerMessageId,injectedAtMs:e.injectedAtMs,...e.exchangeKey?{exchangeKey:e.exchangeKey}:{},...e.askAnnotationId?{askAnnotationId:e.askAnnotationId}:{},...e.systemNoteRequestId?{systemNoteRequestId:e.systemNoteRequestId}:{},...e.systemWake?{systemWake:e.systemWake}:{},...e.resumes?{resumes:e.resumes}:{}})),...t.resumed?{resumed:!0}:{},...t.asideAnswered?.length?{asideAnswered:t.asideAnswered}:{},...t.relayedIds?.length?{relayedIds:t.relayedIds}:{},...t.held?.length?{held:t.held}:{}})),r=s(e)
5540
+ if(0===t.length)return void(se.existsSync(r)&&se.unlinkSync(r))
5538
5541
  const n=`${r}.tmp-${process.pid}`
5539
- re.writeFileSync(n,JSON.stringify(t)),re.renameSync(n,r)}catch{}}function o(e){if(Array.isArray(e.exchanges))return e.exchanges.filter(e=>"string"==typeof e?.markerMessageId).map(e=>({markerMessageId:e.markerMessageId,injectedAtMs:e.injectedAtMs||Date.now(),...e.exchangeKey?{exchangeKey:e.exchangeKey}:{},...e.askAnnotationId?{askAnnotationId:e.askAnnotationId}:{},...e.systemNoteRequestId?{systemNoteRequestId:e.systemNoteRequestId}:{},..."string"==typeof e.systemWake?.kind&&e.systemWake.kind?{systemWake:{kind:e.systemWake.kind,..."string"==typeof e.systemWake.requestId?{requestId:e.systemWake.requestId}:{}}}:{},..."string"==typeof e.resumes&&e.resumes?{resumes:e.resumes}:{}}))
5542
+ se.writeFileSync(n,JSON.stringify(t)),se.renameSync(n,r)}catch{}}function o(e){if(Array.isArray(e.exchanges))return e.exchanges.filter(e=>"string"==typeof e?.markerMessageId).map(e=>({markerMessageId:e.markerMessageId,injectedAtMs:e.injectedAtMs||Date.now(),...e.exchangeKey?{exchangeKey:e.exchangeKey}:{},...e.askAnnotationId?{askAnnotationId:e.askAnnotationId}:{},...e.systemNoteRequestId?{systemNoteRequestId:e.systemNoteRequestId}:{},..."string"==typeof e.systemWake?.kind&&e.systemWake.kind?{systemWake:{kind:e.systemWake.kind,..."string"==typeof e.systemWake.requestId?{requestId:e.systemWake.requestId}:{}}}:{},..."string"==typeof e.resumes&&e.resumes?{resumes:e.resumes}:{}}))
5540
5543
  if("string"!=typeof e.markerMessageId)return[]
5541
5544
  const t={markerMessageId:e.markerMessageId,injectedAtMs:e.injectedAtMs||Date.now(),...e.exchangeKey?{exchangeKey:e.exchangeKey}:{}}
5542
- return e.originMarkerId&&e.originMarkerId!==e.markerMessageId?[{markerMessageId:e.originMarkerId,injectedAtMs:e.originInjectedAtMs||t.injectedAtMs,...e.originExchangeKey?{exchangeKey:e.originExchangeKey}:{}},t]:[t]}function i(e,t,r,s,o,i,a,c,l){const d={markerMessageId:s,injectedAtMs:r,...o?{exchangeKey:o}:{},...i?{askAnnotationId:i}:{},...a?{systemNoteRequestId:a}:{},...l?{systemWake:l}:{},...c?{resumes:c}:{}},u=ce.get(t)
5545
+ return e.originMarkerId&&e.originMarkerId!==e.markerMessageId?[{markerMessageId:e.originMarkerId,injectedAtMs:e.originInjectedAtMs||t.injectedAtMs,...e.originExchangeKey?{exchangeKey:e.originExchangeKey}:{}},t]:[t]}function i(e,t,r,s,o,i,a,c,l){const d={markerMessageId:s,injectedAtMs:r,...o?{exchangeKey:o}:{},...i?{askAnnotationId:i}:{},...a?{systemNoteRequestId:a}:{},...l?{systemWake:l}:{},...c?{resumes:c}:{}},u=le.get(t)
5543
5546
  if(u){if(u.exchanges.some(e=>e.markerMessageId===s))return
5544
- return clearTimeout(u.deadline),u.exchanges.push(d),u.hardCapAtMs=r+ie,u.deadline=setTimeout(()=>{R(t)},oe),n(u.projectPath),void u.logger.info("inbox-chat loop: another message joins the watched turn",{sessionId:t,injectedAtMs:r,markerMessageId:s,open:u.exchanges.length})}const h={projectId:e.projectId,projectPath:e.projectPath,apiClient:e.apiClient,logger:e.logger,exchanges:[d],hardCapAtMs:r+ie,deadline:setTimeout(()=>{R(t)},oe),poll:setInterval(()=>{M(t,!1)},4e3),checking:!1,context:e}
5545
- ce.set(t,h)
5546
- const p=function(e){const t=de.get(e)
5547
- return t?(de.delete(e),Date.now()-t.at<=ue?t.detail:void 0):void 0}(t)
5547
+ return clearTimeout(u.deadline),u.exchanges.push(d),u.hardCapAtMs=r+ae,u.deadline=setTimeout(()=>{R(t)},ie),n(u.projectPath),void u.logger.info("inbox-chat loop: another message joins the watched turn",{sessionId:t,injectedAtMs:r,markerMessageId:s,open:u.exchanges.length})}const h={projectId:e.projectId,projectPath:e.projectPath,apiClient:e.apiClient,logger:e.logger,exchanges:[d],hardCapAtMs:r+ae,deadline:setTimeout(()=>{R(t)},ie),poll:setInterval(()=>{M(t,!1)},4e3),checking:!1,context:e}
5548
+ le.set(t,h)
5549
+ const p=function(e){const t=ue.get(e)
5550
+ return t?(ue.delete(e),Date.now()-t.at<=he?t.detail:void 0):void 0}(t)
5548
5551
  p&&(h.serveError=p,setTimeout(()=>{M(t,!1)},0)),n(e.projectPath),e.logger.info("inbox-chat loop: watching turn",{sessionId:t,injectedAtMs:r,markerMessageId:s})}function a(e){return!e.askAnnotationId&&!r(e)}function c(e){const t=e??{},r="string"==typeof t.name&&t.name?t.name:"UnknownError",s=t.data?.providerID&&t.data?.modelID?`${t.data.providerID}/${t.data.modelID}`:""
5549
5552
  if("UnknownError"!==r)return s?`${r} ${s}`:r
5550
5553
  const n="string"==typeof t.data?.message?t.data.message.trim():"",o=/model not found:?\s*([^\s/]+\/[^\s.]+)/i.exec(n)
@@ -5552,13 +5555,13 @@ return o?`ProviderModelNotFoundError ${o[1]}`:/^[A-Z][A-Za-z]*Error$/.test(n)?n:
5552
5555
  const s=e.findIndex(e=>e.id===t)
5553
5556
  return-1===s||e.slice(s+1).some(e=>"assistant"===e.role)?null:r}function u(e,t=60){const r=e.trim()
5554
5557
  if(!r)return!1
5555
- if(pe.test(r))return!1
5556
- const s=fe.test(r)
5557
- return r.length>=(s?Math.ceil(t/3):t)?!(he.test(r)&&r.length<(s?40:120)):/[.!?\u3002\uff01\uff1f]/.test(r)&&!he.test(r)&&r.length>=(s?8:24)}function h(e){const t=new Set
5558
+ if(fe.test(r))return!1
5559
+ const s=me.test(r)
5560
+ return r.length>=(s?Math.ceil(t/3):t)?!(pe.test(r)&&r.length<(s?40:120)):/[.!?\u3002\uff01\uff1f]/.test(r)&&!pe.test(r)&&r.length>=(s?8:24)}function h(e){const t=new Set
5558
5561
  for(const r of e.toLowerCase().replace(/[*_`#>]/g," ").split(/[^\p{L}\p{N}.,']+/u)){const e=r.replace(/^[.,']+|[.,']+$/g,"")
5559
- if(e){for(const r of e.match(me)??[])if(1!==r.length)for(let e=0;e+1<r.length;e++)t.add(r.slice(e,e+2))
5562
+ if(e){for(const r of e.match(ge)??[])if(1!==r.length)for(let e=0;e+1<r.length;e++)t.add(r.slice(e,e+2))
5560
5563
  else t.add(r)
5561
- for(const r of e.replace(me," ").split(/\s+/))r&&(/^req\d+$/.test(r)||/\p{N}/u.test(r)||r.length>=4)&&t.add(r)}}return t}function p(e,t){const r=h(e),s=h(t)
5564
+ for(const r of e.replace(ge," ").split(/\s+/))r&&(/^req\d+$/.test(r)||/\p{N}/u.test(r)||r.length>=4)&&t.add(r)}}return t}function p(e,t){const r=h(e),s=h(t)
5562
5565
  if(0===s.size)return!1
5563
5566
  let n=0
5564
5567
  for(const e of s)r.has(e)&&n++
@@ -5571,7 +5574,7 @@ if("user"===o.role&&w(e,r,t))break
5571
5574
  "assistant"===o.role&&o.completed&&o.text.trim()&&(s.push(o.text.trim()),n=I(o))}if(0===s.length)return null
5572
5575
  const o=s[s.length-1],i=s.find(e=>u(e))
5573
5576
  if(!i||i===o)return{reply:o}
5574
- const a=b(e,t,i),c=(ge.test(y(i.split(/\n{2,}/)[0]??"")[0]??"")||n)&&u(o,40)||a&&u(o,40)&&!p(i,o)?o:void 0
5577
+ const a=b(e,t,i),c=(we.test(y(i.split(/\n{2,}/)[0]??"")[0]??"")||n)&&u(o,40)||a&&u(o,40)&&!p(i,o)?o:void 0
5575
5578
  return c?{reply:v(i,c)}:{reply:i}}function m(e,t){const r=e.findIndex(e=>e.id===t)
5576
5579
  if(-1===r)return null
5577
5580
  let s=null
@@ -5588,13 +5591,13 @@ let s=0
5588
5591
  for(const e of t)r.has(e)&&s++
5589
5592
  return s/t.size>=.6},n=[]
5590
5593
  for(const t of e.split(/\n{2,}/)){if(/^\s*(?:[-*\u2022]|\d+[.)])\s/m.test(t)){s(t)||n.push(t.trim())
5591
- continue}const e=y(t).filter(e=>!ge.test(e)&&!s(e))
5594
+ continue}const e=y(t).filter(e=>!we.test(e)&&!s(e))
5592
5595
  e.length&&n.push(e.join(" "))}return n.length?`${n.join("\n\n")}\n\n${t.trim()}`:t.trim()}function b(e,t,r){const s=e.findIndex(e=>e.id===t)
5593
5596
  if(-1===s)return!1
5594
5597
  let n=!1
5595
5598
  for(let t=s+1;t<e.length;t++){const s=e[t]
5596
5599
  if("assistant"===s.role){if(!n){if(!s.completed||s.text.trim()!==r)continue
5597
- n=!0}for(const e of s.tools??[])if(!we.test(e))return!0}}return!1}function k(e,t,r=[],s=[]){const n=e.findIndex(e=>e.id===t)
5600
+ n=!0}for(const e of s.tools??[])if(!ye.test(e))return!0}}return!1}function k(e,t,r=[],s=[]){const n=e.findIndex(e=>e.id===t)
5598
5601
  if(-1===n)return e
5599
5602
  let o=!1,i=!0
5600
5603
  return e.filter((e,a)=>a<=n||"assistant"!==e.role||!e.parentId||(e.parentId===t?(o=!0,i=!0,!0):!e.aside&&(s.includes(e.parentId)||(i=!o&&!r.includes(e.parentId)),i)))}function S(e,t){const r=e.findIndex(e=>e.id===t)
@@ -5623,19 +5626,19 @@ if(-1===r)return!1
5623
5626
  let s=null
5624
5627
  for(let t=r+1;t<e.length;t++){const n=e[t]
5625
5628
  if("user"===n.role&&w(e,r,t))break
5626
- "assistant"===n.role&&(s=n)}return"MessageAbortedError"===s?.errorName}function _(e){ye.add(e),ye.size>500&&ye.delete(ye.values().next().value)}async function T(e,t,r){const s={projectId:t.projectId,projectPath:t.projectPath,apiClient:t.apiClient,logger:t.logger},o=await(0,ee.deliverPrompt)(s,e,r,{kind:"inserted-prompt",partPayload:{nudge:!0}})
5629
+ "assistant"===n.role&&(s=n)}return"MessageAbortedError"===s?.errorName}function _(e){ve.add(e),ve.size>500&&ve.delete(ve.values().next().value)}async function T(e,t,r){const s={projectId:t.projectId,projectPath:t.projectPath,apiClient:t.apiClient,logger:t.logger},o=await(0,te.deliverPrompt)(s,e,r,{kind:"inserted-prompt",partPayload:{nudge:!0}})
5627
5630
  if(!o.ok||!o.messageId)return t.logger.warn("inbox-chat loop: could not resume a turn",{sessionId:e,error:o.error}),!1
5628
5631
  const i=Date.now(),a=t.exchanges[t.exchanges.length-1]
5629
- return t.resumed=!0,t.serveError=void 0,a.markerMessageId=o.messageId,a.injectedAtMs=i,t.hardCapAtMs=i+ie,clearTimeout(t.deadline),t.deadline=setTimeout(()=>{R(e)},oe),n(t.projectPath),!0}function x(e,t){const r=e.findIndex(e=>e.id===t)
5632
+ return t.resumed=!0,t.serveError=void 0,a.markerMessageId=o.messageId,a.injectedAtMs=i,t.hardCapAtMs=i+ae,clearTimeout(t.deadline),t.deadline=setTimeout(()=>{R(e)},ie),n(t.projectPath),!0}function x(e,t){const r=e.findIndex(e=>e.id===t)
5630
5633
  if(-1===r)return!1
5631
5634
  let s=!1
5632
5635
  for(let t=r+1;t<e.length;t++){const r=e[t]
5633
5636
  if("assistant"===r.role){if(r.text.trim())return!1
5634
5637
  if(r.errorName)return!1
5635
- r.completed&&(s=!0)}}return s}async function M(e,t){const s=ce.get(e)
5636
- if(s&&!s.checking)if((0,ne.isProjectPaused)())t&&(s.deadline=setTimeout(()=>{R(e)},oe))
5638
+ r.completed&&(s=!0)}}return s}async function M(e,t){const s=le.get(e)
5639
+ if(s&&!s.checking)if((0,oe.isProjectPaused)())t&&(s.deadline=setTimeout(()=>{R(e)},ie))
5637
5640
  else{s.checking=!0
5638
- try{const n=(0,Y.getOpenCodeUrlFromConfig)(s.projectPath)?.replace(/\/$/,"")
5641
+ try{const n=(0,J.getOpenCodeUrlFromConfig)(s.projectPath)?.replace(/\/$/,"")
5639
5642
  if(!n)return void(t&&await D(e,s,{turnDied:!0}))
5640
5643
  const o=await async function(e,t){try{const r=await fetch(`${e}/session/status`,{signal:AbortSignal.timeout(5e3)})
5641
5644
  if(!r.ok)return null
@@ -5643,39 +5646,39 @@ const s=await r.json(),n=s?.[t]?.type
5643
5646
  return!!n&&"idle"!==n}catch{return null}}(n,e)
5644
5647
  if(null===o&&!t)return
5645
5648
  const i=o??!0,l=await async function(e,t){try{const r=await fetch(`${e}/session/${t}/message?limit=100`,{signal:AbortSignal.timeout(1e4)})
5646
- return r.ok?(await r.json()).map(e=>({id:e.info?.id||"",role:e.info?.role||"unknown",text:(0,X.replyText)(e.parts),created:e.info?.time?.created??0,tools:(e.parts||[]).filter(e=>"tool"===e.type&&e.tool).map(e=>{const t=e?.state?.input?.operation
5647
- return String(e.tool)+("string"==typeof t&&t?`:${t}`:"")}),web:(0,Q.webLooksOf)(e.parts),...e.info?.parentID?{parentId:String(e.info.parentID)}:{},completed:!!e.info?.time?.completed,...e.info?.time?.completed?{completedAt:e.info.time.completed}:{},...e.info?.finish?{finish:String(e.info.finish)}:{},...(e.parts||[]).some(e=>"text"===e?.type&&"final_answer"===e?.metadata?.openai?.phase)?{finalAnswer:!0}:{},...(e.parts||[]).some(e=>"text"===e?.type&&"commentary"===e?.metadata?.openai?.phase)?{commentary:!0}:{},...!0===e.info?.aside?{aside:!0}:{},...(()=>{if("user"!==e.info?.role)return{}
5649
+ return r.ok?(await r.json()).map(e=>({id:e.info?.id||"",role:e.info?.role||"unknown",text:(0,Q.replyText)(e.parts),created:e.info?.time?.created??0,tools:(e.parts||[]).filter(e=>"tool"===e.type&&e.tool).map(e=>{const t=e?.state?.input?.operation
5650
+ return String(e.tool)+("string"==typeof t&&t?`:${t}`:"")}),web:(0,Z.webLooksOf)(e.parts),...e.info?.parentID?{parentId:String(e.info.parentID)}:{},completed:!!e.info?.time?.completed,...e.info?.time?.completed?{completedAt:e.info.time.completed}:{},...e.info?.finish?{finish:String(e.info.finish)}:{},...(e.parts||[]).some(e=>"text"===e?.type&&"final_answer"===e?.metadata?.openai?.phase)?{finalAnswer:!0}:{},...(e.parts||[]).some(e=>"text"===e?.type&&"commentary"===e?.metadata?.openai?.phase)?{commentary:!0}:{},...!0===e.info?.aside?{aside:!0}:{},...(()=>{if("user"!==e.info?.role)return{}
5648
5651
  const t=(e.parts||[]).map(e=>e?.metadata?.alchemy).find(e=>e&&"string"==typeof e.kind)
5649
- return t?{alchemyKind:String(t.kind),...(0,te.holdsDuringUserTurn)(t.kind,t.payload)?{heldKind:!0}:{}}:{}})(),...e.info?.error?.name?{errorName:String(e.info.error.name),errorDetail:c(e.info.error),errorFatal:(0,Z.isFatalTurnError)(e.info.error),...(0,Z.isFatalTurnError)(e.info.error)?{errorRefusal:(0,Z.turnRefusal)(e.info.error,e.info)}:{}}:{}})).sort((e,t)=>e.created-t.created):null}catch{return null}}(n,e),u=s.exchanges.map(e=>e.markerMessageId),h=[...s.exchanges.filter(r).map(e=>e.markerMessageId),...(l??[]).filter(e=>"user"===e.role&&e.heldKind).map(e=>e.id)],p=e=>k(l??[],e.markerMessageId,u.filter(t=>t!==e.markerMessageId),s.asideAnswered??[])
5652
+ return t?{alchemyKind:String(t.kind),...(0,re.holdsDuringUserTurn)(t.kind,t.payload)?{heldKind:!0}:{}}:{}})(),...e.info?.error?.name?{errorName:String(e.info.error.name),errorDetail:c(e.info.error),errorFatal:(0,ee.isFatalTurnError)(e.info.error),...(0,ee.isFatalTurnError)(e.info.error)?{errorRefusal:(0,ee.turnRefusal)(e.info.error,e.info)}:{}}:{}})).sort((e,t)=>e.created-t.created):null}catch{return null}}(n,e),u=s.exchanges.map(e=>e.markerMessageId),h=[...s.exchanges.filter(r).map(e=>e.markerMessageId),...(l??[]).filter(e=>"user"===e.role&&e.heldKind).map(e=>e.id)],p=e=>k(l??[],e.markerMessageId,u.filter(t=>t!==e.markerMessageId),s.asideAnswered??[])
5650
5653
  if(l){for(const t of[...s.exchanges]){if(!s.exchanges.includes(t))continue
5651
5654
  if(r(t))continue
5652
5655
  const n=(l??[]).find(e=>e.aside&&e.parentId===t.markerMessageId&&e.completed&&!e.errorName&&e.text.trim())
5653
- if(n){s.asideAnswered=[...s.asideAnswered??[],t.markerMessageId],L(s,[n.id]),await N(e,s,t,{turnText:n.text.trim().slice(0,ae),aside:!0},!1)
5656
+ if(n){s.asideAnswered=[...s.asideAnswered??[],t.markerMessageId],L(s,[n.id]),await N(e,s,t,{turnText:n.text.trim().slice(0,ce),aside:!0},!1)
5654
5657
  continue}const o=U(p(t),s)
5655
5658
  if(!S(o,t.markerMessageId))continue
5656
5659
  const a=f(o,t.markerMessageId)
5657
- a&&(i&&s.logger.info("inbox-chat loop: answer complete mid-turn, relayed while the session works on",{sessionId:e,markerMessageId:t.markerMessageId}),await N(e,s,t,{turnText:(0,Q.withSources)(a.reply.slice(0,ae),j(o,t.markerMessageId)),turnTrace:$(o,t.markerMessageId)??void 0,askedBefore:H(o,t.markerMessageId)})&&!t.askAnnotationId&&L(s,W(o,t.markerMessageId)))}if(0===s.exchanges.length)return void P(e,s)}if(i&&!t)return
5658
- if(i&&t&&Date.now()<s.hardCapAtMs)return s.deadline=setTimeout(()=>{R(e)},oe),void s.logger.info("inbox-chat loop: session busy at deadline, extending watch",{sessionId:e})
5660
+ a&&(i&&s.logger.info("inbox-chat loop: answer complete mid-turn, relayed while the session works on",{sessionId:e,markerMessageId:t.markerMessageId}),await N(e,s,t,{turnText:(0,Z.withSources)(a.reply.slice(0,ce),j(o,t.markerMessageId)),turnTrace:$(o,t.markerMessageId)??void 0,askedBefore:H(o,t.markerMessageId)})&&!t.askAnnotationId&&L(s,W(o,t.markerMessageId)))}if(0===s.exchanges.length)return void P(e,s)}if(i&&!t)return
5661
+ if(i&&t&&Date.now()<s.hardCapAtMs)return s.deadline=setTimeout(()=>{R(e)},ie),void s.logger.info("inbox-chat loop: session busy at deadline, extending watch",{sessionId:e})
5659
5662
  if(l&&C(l,(s.resumed?s.exchanges[s.exchanges.length-1]:s.exchanges[0]).markerMessageId))return void await D(e,s,{turnDied:!0,turnError:"MessageAbortedError"})
5660
5663
  const g=l?A(l,s.exchanges[0].markerMessageId):null
5661
5664
  if(g){if(g.transient&&!s.resumed&&await async function(e,t,r){const s=await T(e,t,"Your previous turn was cut off by a transient provider error (the connection to the model dropped), not by anything you did. A tool call that seemed to vanish may still have run: check before repeating one that changes something. Carry on answering the user's last message from where you stopped.")
5662
5665
  return s&&t.logger.warn("inbox-chat loop: turn cut off by a provider error; resumed it once",{sessionId:e,error:r,markerMessageId:t.exchanges[t.exchanges.length-1].markerMessageId}),s}(e,s,g.detail))return
5663
- return _(g.messageId),void await D(e,s,{turnDied:!0,turnError:s.resumed?`${g.detail}, twice`:g.detail,...g.refusal?{turnRefusal:g.refusal}:{}})}if(l){for(const n of s.exchanges.filter(e=>e.askAnnotationId||r(e))){const r=U(p(n),s),o=n.systemWake?m(r,n.markerMessageId):null,i=n.systemWake?o?{reply:o}:null:f(r,n.markerMessageId);(!n.systemWake||i||t||x(r,n.markerMessageId))&&await N(e,s,n,i?{turnText:i.reply.slice(0,ae),changed:B(r,n.markerMessageId)}:{turnSilent:!0},!1)}if(0===s.exchanges.length)return void P(e,s)
5666
+ return _(g.messageId),void await D(e,s,{turnDied:!0,turnError:s.resumed?`${g.detail}, twice`:g.detail,...g.refusal?{turnRefusal:g.refusal}:{}})}if(l){for(const n of s.exchanges.filter(e=>e.askAnnotationId||r(e))){const r=U(p(n),s),o=n.systemWake?m(r,n.markerMessageId):null,i=n.systemWake?o?{reply:o}:null:f(r,n.markerMessageId);(!n.systemWake||i||t||x(r,n.markerMessageId))&&await N(e,s,n,i?{turnText:i.reply.slice(0,ce),changed:B(r,n.markerMessageId)}:{turnSilent:!0},!1)}if(0===s.exchanges.length)return void P(e,s)
5664
5667
  if(!s.exchanges.some(a)){const t=s.exchanges[s.exchanges.length-1],r=E(l,t.markerMessageId)??d(l,t.markerMessageId,s.serveError)
5665
5668
  return void(r&&await D(e,s,{turnDied:!0,turnError:r}))}}const w=s.exchanges[s.exchanges.length-1],y=s.exchanges[0],v=U((l??[]).filter(e=>!(e.aside&&e.parentId!==y.markerMessageId||"assistant"===e.role&&e.parentId&&h.includes(e.parentId))),s),b=l?f(v,y.markerMessageId):null
5666
- if(b)return void await O(e,s,{turnText:(0,Q.withSources)(b.reply.slice(0,ae),j(v,y.markerMessageId)),turnTrace:$(v,y.markerMessageId)??void 0,askedBefore:H(v,w.markerMessageId)})
5669
+ if(b)return void await O(e,s,{turnText:(0,Z.withSources)(b.reply.slice(0,ce),j(v,y.markerMessageId)),turnTrace:$(v,y.markerMessageId)??void 0,askedBefore:H(v,w.markerMessageId)})
5667
5670
  const I=l?E(l,w.markerMessageId):null
5668
5671
  if(I)return void await D(e,s,{turnDied:!0,turnError:I})
5669
5672
  const M=l?d(l,w.markerMessageId,s.serveError):null
5670
5673
  if(M)return s.logger.warn("inbox-chat loop: turn died before an assistant message existed",{sessionId:e,error:M}),void await D(e,s,{turnDied:!0,turnError:M})
5671
5674
  if(l&&x(v,y.markerMessageId))return s.logger.info("inbox-chat loop: turn concluded silently (no text, no error)",{sessionId:e}),void await O(e,s,{turnSilent:!0})
5672
- t&&await D(e,s,{turnDied:!0})}finally{const t=ce.get(e)
5673
- t&&(t.checking=!1)}}}async function R(e){await M(e,!0)}function P(e,t){clearTimeout(t.deadline),clearInterval(t.poll),ce.get(e)===t&&ce.delete(e),n(t.projectPath),function(e,t){const r=t.held??[]
5675
+ t&&await D(e,s,{turnDied:!0})}finally{const t=le.get(e)
5676
+ t&&(t.checking=!1)}}}async function R(e){await M(e,!0)}function P(e,t){clearTimeout(t.deadline),clearInterval(t.poll),le.get(e)===t&&le.delete(e),n(t.projectPath),function(e,t){const r=t.held??[]
5674
5677
  if(t.held=[],0===r.length)return
5675
- const s=t.context,n=le
5676
- !s||!n&&r.some(e=>"deliver"!==e.via)?t.logger.error("inbox-chat loop: held system notes could not be delivered (no deliverer)",{sessionId:e,held:r.length}):setImmediate(()=>{(async()=>{for(const o of r)try{if("deliver"===o.via){const e=await(0,ee.deliverPrompt)(s,o.sessionId,o.message,{...o.opts??{},...o.kind?{kind:o.kind}:{},...o.partPayload?{partPayload:o.partPayload}:{}})
5678
+ const s=t.context,n=de
5679
+ !s||!n&&r.some(e=>"deliver"!==e.via)?t.logger.error("inbox-chat loop: held system notes could not be delivered (no deliverer)",{sessionId:e,held:r.length}):setImmediate(()=>{(async()=>{for(const o of r)try{if("deliver"===o.via){const e=await(0,te.deliverPrompt)(s,o.sessionId,o.message,{...o.opts??{},...o.kind?{kind:o.kind}:{},...o.partPayload?{partPayload:o.partPayload}:{}})
5677
5680
  if(!e.ok)throw new Error(e.detail??String(e.error))}else await n(o,s)
5678
- t.logger.info("inbox-chat loop: held system note delivered",{sessionId:e,kind:o.kind??null})}catch(r){t.logger.error("inbox-chat loop: held system note delivery failed",{sessionId:e,error:(0,J.getErrorMessage)(r)})}})()})}(e,t)}async function O(e,t,r){const s=t.exchanges[t.exchanges.length-1],n=t.exchanges.filter(e=>e!==s&&!e.askAnnotationId).map(e=>e.exchangeKey).filter(e=>!!e)
5681
+ t.logger.info("inbox-chat loop: held system note delivered",{sessionId:e,kind:o.kind??null})}catch(r){t.logger.error("inbox-chat loop: held system note delivery failed",{sessionId:e,error:(0,X.getErrorMessage)(r)})}})()})}(e,t)}async function O(e,t,r){const s=t.exchanges[t.exchanges.length-1],n=t.exchanges.filter(e=>e!==s&&!e.askAnnotationId).map(e=>e.exchangeKey).filter(e=>!!e)
5679
5682
  P(e,t),await F(e,t,s,{...r,absorbs:n})}async function D(e,t,r){const s=[...t.exchanges]
5680
5683
  P(e,t)
5681
5684
  for(const n of s)await F(e,t,n,r)}function q(e,t,s=!0){if(!s||t.askAnnotationId||r(t))return[]
@@ -5684,22 +5687,25 @@ return e.slice(0,Math.max(0,n)).filter(e=>!e.askAnnotationId&&!r(e))}async funct
5684
5687
  return t.exchanges=t.exchanges.filter(e=>e!==r&&!i.includes(e)),n(t.projectPath),i.length&&t.logger.info("inbox-chat loop: earlier messages answered by this reply",{sessionId:e,markers:i.map(e=>e.markerMessageId)}),F(e,t,r,{...s,absorbs:i.map(e=>e.exchangeKey).filter(e=>!!e)})}async function F(e,t,r,s){if(r.askAnnotationId)return async function(e,t,r,s){const n={sessionId:e,...s.turnDied?{turnDied:!0}:s.turnSilent?{turnSilent:!0}:{turnText:s.turnText??""}}
5685
5688
  for(const s of[0,2e3,8e3]){s>0&&await new Promise(e=>setTimeout(e,s))
5686
5689
  try{const s=await t.apiClient.post(`/api/projects/${t.projectId}/annotations/${encodeURIComponent(r)}/ask-outcome`,n)
5687
- if(!1!==s?.success)return t.logger.info("inbox-chat loop: document ask outcome reported",{sessionId:e,annotationId:r,posted:s?.data?.posted,reason:s?.data?.reason}),!0===s?.data?.posted}catch(s){t.logger.warn("inbox-chat loop: document ask outcome failed",{sessionId:e,annotationId:r,error:(0,J.getErrorMessage)(s)})}}return t.logger.error("inbox-chat loop: document ask outcome undeliverable after retries",{sessionId:e,annotationId:r}),!1}(e,t,r.askAnnotationId,s)
5688
- if(r.systemWake)return async function(e,t,r,s,n){const o=n.turnDied||n.turnSilent||!(0,te.wakeLineIsForUser)(s.kind,!0===n.changed)?"":(n.turnText??"").trim(),i={sessionId:e,wake:s.kind,...s.requestId?{requestId:s.requestId}:{},injectedAt:new Date(r.injectedAtMs).toISOString(),...o?{turnText:o.slice(0,ae)}:{}}
5690
+ if(!1!==s?.success)return t.logger.info("inbox-chat loop: document ask outcome reported",{sessionId:e,annotationId:r,posted:s?.data?.posted,reason:s?.data?.reason}),!0===s?.data?.posted}catch(s){t.logger.warn("inbox-chat loop: document ask outcome failed",{sessionId:e,annotationId:r,error:(0,X.getErrorMessage)(s)})}}return t.logger.error("inbox-chat loop: document ask outcome undeliverable after retries",{sessionId:e,annotationId:r}),!1}(e,t,r.askAnnotationId,s)
5691
+ if(r.systemWake)return async function(e,t,r,s,n){const o=n.turnDied||n.turnSilent||!(0,re.wakeLineIsForUser)(s.kind,!0===n.changed)?"":(n.turnText??"").trim()
5692
+ let i=!1
5693
+ if("unit-start"===s.kind&&s.requestId&&o)try{const e=await fetch(`${(0,Y.getActionServerBaseUrl)()}/api/request-diff-stats?requestId=${encodeURIComponent(s.requestId)}`,{signal:AbortSignal.timeout(5e3)}),t=e.ok?(await e.json())?.data:null
5694
+ i=!!t&&0===t.filesChanged&&0===t.additions&&0===t.deletions}catch{}const a={sessionId:e,wake:s.kind,...s.requestId?{requestId:s.requestId}:{},injectedAt:new Date(r.injectedAtMs).toISOString(),...o?{turnText:o.slice(0,ce)}:{},...i?{diffNone:!0}:{}}
5689
5695
  for(const r of[0,2e3,8e3]){r>0&&await new Promise(e=>setTimeout(e,r))
5690
- try{const r=await t.apiClient.post(`/api/projects/${t.projectId}/system-turn-note`,i)
5691
- if(!1!==r?.success)return t.logger.info("inbox-chat loop: system wake turn reported",{sessionId:e,wake:s.kind,requestId:s.requestId??null,posted:r?.data?.posted,reason:r?.data?.reason}),!0===r?.data?.posted}catch(r){t.logger.warn("inbox-chat loop: system wake turn report failed",{sessionId:e,wake:s.kind,error:(0,J.getErrorMessage)(r)})}}return t.logger.error("inbox-chat loop: system wake turn undeliverable after retries; its closing line is lost",{sessionId:e,wake:s.kind}),!1}(e,t,r,r.systemWake,s)
5696
+ try{const r=await t.apiClient.post(`/api/projects/${t.projectId}/system-turn-note`,a)
5697
+ if(!1!==r?.success)return t.logger.info("inbox-chat loop: system wake turn reported",{sessionId:e,wake:s.kind,requestId:s.requestId??null,posted:r?.data?.posted,reason:r?.data?.reason}),!0===r?.data?.posted}catch(r){t.logger.warn("inbox-chat loop: system wake turn report failed",{sessionId:e,wake:s.kind,error:(0,X.getErrorMessage)(r)})}}return t.logger.error("inbox-chat loop: system wake turn undeliverable after retries; its closing line is lost",{sessionId:e,wake:s.kind}),!1}(e,t,r,r.systemWake,s)
5692
5698
  if(r.systemNoteRequestId)return async function(e,t,r,s){const n=(s.turnText??"").trim()
5693
5699
  if(!n||s.turnDied||s.turnSilent||!s.changed)return!1
5694
- try{const s=await t.apiClient.post(`/api/projects/${t.projectId}/system-turn-note`,{sessionId:e,requestId:r.systemNoteRequestId,injectedAt:new Date(r.injectedAtMs).toISOString(),turnText:n.slice(0,ae)})
5695
- return t.logger.info("inbox-chat loop: system turn note reported",{sessionId:e,requestId:r.systemNoteRequestId,posted:s?.data?.posted,reason:s?.data?.reason}),!0===s?.data?.posted}catch(r){return t.logger.warn("inbox-chat loop: system turn note failed",{sessionId:e,error:(0,J.getErrorMessage)(r)}),!1}}(e,t,r,s)
5700
+ try{const s=await t.apiClient.post(`/api/projects/${t.projectId}/system-turn-note`,{sessionId:e,requestId:r.systemNoteRequestId,injectedAt:new Date(r.injectedAtMs).toISOString(),turnText:n.slice(0,ce)})
5701
+ return t.logger.info("inbox-chat loop: system turn note reported",{sessionId:e,requestId:r.systemNoteRequestId,posted:s?.data?.posted,reason:s?.data?.reason}),!0===s?.data?.posted}catch(r){return t.logger.warn("inbox-chat loop: system turn note failed",{sessionId:e,error:(0,X.getErrorMessage)(r)}),!1}}(e,t,r,s)
5696
5702
  const n={sessionId:e,markerMessageId:r.markerMessageId,injectedAt:new Date(r.injectedAtMs).toISOString(),...r.exchangeKey?{exchangeKey:r.exchangeKey}:{},...r.resumes?{resumesMarkerId:r.resumes}:{},...s.turnDied?{turnDied:!0,...s.turnError?{turnError:s.turnError}:{},...s.turnRefusal?{turnErrorMessage:s.turnRefusal.message,turnErrorScope:s.turnRefusal.scope,...s.turnRefusal.model?{turnErrorModel:s.turnRefusal.model}:{}}:{}}:s.turnSilent?{turnSilent:!0}:{turnText:s.turnText??"",...s.followUpText?{followUpText:s.followUpText}:{},...s.turnTrace?{turnTrace:s.turnTrace}:{}},...s.askedBefore?{askedBefore:s.askedBefore}:{},...s.absorbs?{absorbs:s.absorbs}:{},...s.aside?{aside:!0}:{}},o=[0,2e3,8e3]
5697
5703
  for(let r=0;r<o.length;r++){o[r]>0&&await new Promise(e=>setTimeout(e,o[r]))
5698
5704
  try{const o=await t.apiClient.post(`/api/projects/${t.projectId}/inbox-chat/loop-check`,n)
5699
5705
  if(!1!==o?.success)return t.logger.info("inbox-chat loop: turn outcome reported",{sessionId:e,died:!!s.turnDied,relayed:o?.data?.relayed,reason:o?.data?.reason}),!0
5700
- t.logger.warn("inbox-chat loop: loop-check rejected",{sessionId:e,attempt:r,error:o?.error})}catch(s){t.logger.warn("inbox-chat loop: loop-check failed",{sessionId:e,attempt:r,error:(0,J.getErrorMessage)(s)})}}return t.logger.error("inbox-chat loop: loop-check undeliverable after retries \u2014 reply relay lost",{sessionId:e}),!1}function L(e,t){0!==t.length&&(e.relayedIds=[...new Set([...e.relayedIds??[],...t])].slice(-200),n(e.projectPath))}function U(e,t){const r=new Set(t.relayedIds??[])
5706
+ t.logger.warn("inbox-chat loop: loop-check rejected",{sessionId:e,attempt:r,error:o?.error})}catch(s){t.logger.warn("inbox-chat loop: loop-check failed",{sessionId:e,attempt:r,error:(0,X.getErrorMessage)(s)})}}return t.logger.error("inbox-chat loop: loop-check undeliverable after retries \u2014 reply relay lost",{sessionId:e}),!1}function L(e,t){0!==t.length&&(e.relayedIds=[...new Set([...e.relayedIds??[],...t])].slice(-200),n(e.projectPath))}function U(e,t){const r=new Set(t.relayedIds??[])
5701
5707
  return r.size?e.filter(e=>!("assistant"===e.role&&r.has(e.id))):e}function B(e,t){const r=e.findIndex(e=>e.id===t)
5702
- return-1!==r&&e.slice(r+1).some(e=>"assistant"===e.role&&(e.tools??[]).some(e=>!we.test(e)))}function H(e,t){const r=e.findIndex(e=>e.id===t)
5708
+ return-1!==r&&e.slice(r+1).some(e=>"assistant"===e.role&&(e.tools??[]).some(e=>!ye.test(e)))}function H(e,t){const r=e.findIndex(e=>e.id===t)
5703
5709
  if(-1===r)return
5704
5710
  const s=e.slice(r+1).find(e=>"assistant"===e.role&&e.created>0)
5705
5711
  return s?new Date(s.created).toISOString():void 0}function W(e,t){const r=e.findIndex(e=>e.id===t)
@@ -5711,34 +5717,34 @@ return t},G(e)},function(e){if(e&&e.__esModule)return e
5711
5717
  var t={}
5712
5718
  if(null!=e)for(var r=G(e),s=0;s<r.length;s++)"default"!==r[s]&&K(t,e,r[s])
5713
5719
  return z(t,e),t})
5714
- Object.defineProperty(exports,"__esModule",{value:!0}),exports.extendChatWatches=function(e){if(e>0)for(const t of ce.values())t.hardCapAtMs+=e},exports.persistedExchanges=o,exports.resumeInboxChatWatches=function(e){try{const t=s(e.projectPath)
5715
- if(!re.existsSync(t))return
5716
- const r=JSON.parse(re.readFileSync(t,"utf-8"))
5717
- for(const t of r){if(!t?.sessionId||ce.has(t.sessionId))continue
5720
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.extendChatWatches=function(e){if(e>0)for(const t of le.values())t.hardCapAtMs+=e},exports.persistedExchanges=o,exports.resumeInboxChatWatches=function(e){try{const t=s(e.projectPath)
5721
+ if(!se.existsSync(t))return
5722
+ const r=JSON.parse(se.readFileSync(t,"utf-8"))
5723
+ for(const t of r){if(!t?.sessionId||le.has(t.sessionId))continue
5718
5724
  const r=o(t)
5719
5725
  if(0===r.length)continue
5720
5726
  for(const s of r)i(e,t.sessionId,s.injectedAtMs,s.markerMessageId,s.exchangeKey,s.askAnnotationId,s.systemNoteRequestId,s.resumes,s.systemWake)
5721
- const s=ce.get(t.sessionId)
5722
- s&&t.resumed&&(s.resumed=!0),s&&Array.isArray(t.asideAnswered)&&(s.asideAnswered=t.asideAnswered.filter(e=>"string"==typeof e)),s&&Array.isArray(t.relayedIds)&&(s.relayedIds=t.relayedIds.filter(e=>"string"==typeof e)),s&&Array.isArray(t.held)&&(s.held=t.held.filter(e=>"string"==typeof e?.sessionId&&"string"==typeof e?.message)),e.logger.info("inbox-chat loop: resumed watch from a previous life",{sessionId:t.sessionId,exchanges:r.length}),M(t.sessionId,!1)}}catch(t){e.logger.warn("inbox-chat loop: watch resume failed",{error:(0,J.getErrorMessage)(t)})}},exports.trackInboxChatTurn=i,exports.registerHeldInjectDeliverer=function(e){le=e},exports.holdForChatTurn=function(e){const t=ce.get(e.sessionId)
5723
- return!(!t||!t.exchanges.some(a)||(t.held=[...t.held??[],e],n(t.projectPath),t.logger.info("inbox-chat loop: system note held until the user's turn ends",{sessionId:e.sessionId,kind:e.kind??null,open:t.exchanges.length,held:t.held.length}),0))},exports.notifyInboxChatSessionIdle=function(e){ce.has(e)&&M(e,!1)},exports.notifyInboxChatSessionError=function(e,t){const r=c(t),s=ce.get(e)
5724
- if(!s){const t=de.get(e)
5725
- if(t&&Date.now()-t.at<=ue&&l(t.detail)>=l(r))return
5726
- de.set(e,{detail:r,at:Date.now()})
5727
- for(const[e,t]of de)Date.now()-t.at>ue&&de.delete(e)
5728
- return}s.serveError&&l(s.serveError)>=l(r)||(s.serveError=r,M(e,!1))},exports.describeServeError=c,exports.preMessageDeath=d,exports.hasActiveInboxChatTurns=function(){return ce.size>0},exports.isWatchingInboxChatTurn=function(e){return ce.has(e)},exports.isSubstantiveReply=u,exports.isRestatement=p,exports.pickTurnReply=f,exports.closingText=m,exports.startsNewTurn=g,exports.endsExchange=w,exports.mergeReplyWithFollowUp=v,exports.turnChangedSomethingAfter=b,exports.ownView=k,exports.hasDeclaredAnswer=S,exports.summarizeTurnTrace=$,exports.turnWebLooks=j,exports.extractTurnDeath=E,exports.extractTurnCutOff=A,exports.extractTurnStopped=C,exports.noteCutOffRelayed=_,exports.cutOffAlreadyRelayed=function(e){return!!e&&ye.has(e)},exports.resumeStalledWatchedTurn=async function(e,t,r){const s=ce.get(e)
5727
+ const s=le.get(t.sessionId)
5728
+ s&&t.resumed&&(s.resumed=!0),s&&Array.isArray(t.asideAnswered)&&(s.asideAnswered=t.asideAnswered.filter(e=>"string"==typeof e)),s&&Array.isArray(t.relayedIds)&&(s.relayedIds=t.relayedIds.filter(e=>"string"==typeof e)),s&&Array.isArray(t.held)&&(s.held=t.held.filter(e=>"string"==typeof e?.sessionId&&"string"==typeof e?.message)),e.logger.info("inbox-chat loop: resumed watch from a previous life",{sessionId:t.sessionId,exchanges:r.length}),M(t.sessionId,!1)}}catch(t){e.logger.warn("inbox-chat loop: watch resume failed",{error:(0,X.getErrorMessage)(t)})}},exports.trackInboxChatTurn=i,exports.registerHeldInjectDeliverer=function(e){de=e},exports.holdForChatTurn=function(e){const t=le.get(e.sessionId)
5729
+ return!(!t||!t.exchanges.some(a)||(t.held=[...t.held??[],e],n(t.projectPath),t.logger.info("inbox-chat loop: system note held until the user's turn ends",{sessionId:e.sessionId,kind:e.kind??null,open:t.exchanges.length,held:t.held.length}),0))},exports.notifyInboxChatSessionIdle=function(e){le.has(e)&&M(e,!1)},exports.notifyInboxChatSessionError=function(e,t){const r=c(t),s=le.get(e)
5730
+ if(!s){const t=ue.get(e)
5731
+ if(t&&Date.now()-t.at<=he&&l(t.detail)>=l(r))return
5732
+ ue.set(e,{detail:r,at:Date.now()})
5733
+ for(const[e,t]of ue)Date.now()-t.at>he&&ue.delete(e)
5734
+ return}s.serveError&&l(s.serveError)>=l(r)||(s.serveError=r,M(e,!1))},exports.describeServeError=c,exports.preMessageDeath=d,exports.hasActiveInboxChatTurns=function(){return le.size>0},exports.isWatchingInboxChatTurn=function(e){return le.has(e)},exports.isSubstantiveReply=u,exports.isRestatement=p,exports.pickTurnReply=f,exports.closingText=m,exports.startsNewTurn=g,exports.endsExchange=w,exports.mergeReplyWithFollowUp=v,exports.turnChangedSomethingAfter=b,exports.ownView=k,exports.hasDeclaredAnswer=S,exports.summarizeTurnTrace=$,exports.turnWebLooks=j,exports.extractTurnDeath=E,exports.extractTurnCutOff=A,exports.extractTurnStopped=C,exports.noteCutOffRelayed=_,exports.cutOffAlreadyRelayed=function(e){return!!e&&ve.has(e)},exports.resumeStalledWatchedTurn=async function(e,t,r){const s=le.get(e)
5729
5735
  if(!s)return null
5730
5736
  for(let e=0;e<50&&s.checking;e++)await new Promise(e=>setTimeout(e,100))
5731
- if(s.checking||ce.get(e)!==s)return!ce.has(e)&&null
5737
+ if(s.checking||le.get(e)!==s)return!le.has(e)&&null
5732
5738
  s.checking=!0
5733
5739
  try{await r()
5734
5740
  const n=await T(e,s,t)
5735
5741
  return n&&s.logger.warn("inbox-chat loop: turn stopped answering; ended it and resumed it once",{sessionId:e,markerMessageId:s.exchanges[s.exchanges.length-1].markerMessageId}),n}finally{s.checking=!1}},exports.extractTurnSilence=x,exports.absorbedByReply=q
5736
- const Y=t(60833),J=t(58824),X=t(42593),Q=t(24068),Z=t(4234),ee=t(17039),te=t(81602),re=V(t(79896)),se=V(t(16928)),ne=t(36799),oe=3e5,ie=9e5,ae=8e3,ce=new Map
5737
- let le=null
5738
- const de=new Map,ue=6e4,he=/^(let me|i(?:['\u2019]ll| will| am going to|['\u2019]m going to)|one (?:moment|sec)|checking|looking|on it|sure[,.!]?\s|okay[,.!]?\s|ok[,.!]?\s|first[, ]|hang on|give me)/i,pe=/^(ok(?:ay)?|done|sure|noted|got it|all set|that's it|right)[.!]?$/i,fe=/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Thai}]/u,me=/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Thai}]+/gu,ge=/^(?:(?:now|next|then|first|so)[,:]?\s+)?(?:let me|i(?:['\u2019]ll| will| am going to|['\u2019]m going to)|i['\u2019]m (?:now )?(?:checking|looking|nudging|filing|starting|opening|creating|asking|waking|reading|pulling|fetching|comparing|running|updating|writing|going|registering|drafting))\b/i,we=/get-info|:list|:search|list-areas|read_files|read_file|search|grep|query_history|request_diff|environment_list|environment_get|testing_process_list|check-status|list-sessions|read-messages|results:fetch|commands:list|read_site|:brief|:get\b/i,ye=new Set},81602(e,exports){"use strict"
5742
+ const Y=t(79414),J=t(60833),X=t(58824),Q=t(42593),Z=t(24068),ee=t(4234),te=t(17039),re=t(81602),se=V(t(79896)),ne=V(t(16928)),oe=t(36799),ie=3e5,ae=9e5,ce=8e3,le=new Map
5743
+ let de=null
5744
+ const ue=new Map,he=6e4,pe=/^(let me|i(?:['\u2019]ll| will| am going to|['\u2019]m going to)|one (?:moment|sec)|checking|looking|on it|sure[,.!]?\s|okay[,.!]?\s|ok[,.!]?\s|first[, ]|hang on|give me)/i,fe=/^(ok(?:ay)?|done|sure|noted|got it|all set|that's it|right)[.!]?$/i,me=/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Thai}]/u,ge=/[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Thai}]+/gu,we=/^(?:(?:now|next|then|first|so)[,:]?\s+)?(?:let me|i(?:['\u2019]ll| will| am going to|['\u2019]m going to)|i['\u2019]m (?:now )?(?:checking|looking|nudging|filing|starting|opening|creating|asking|waking|reading|pulling|fetching|comparing|running|updating|writing|going|registering|drafting))\b/i,ye=/get-info|:list|:search|list-areas|read_files|read_file|search|grep|query_history|request_diff|environment_list|environment_get|testing_process_list|check-status|list-sessions|read-messages|results:fetch|commands:list|read_site|:brief|:get\b/i,ve=new Set},81602(e,exports){"use strict"
5739
5745
  exports.Cr=exports.UT=void 0,exports.wakeThatTellsUser=function(e,t){const r="string"==typeof e?exports.Cr.get(e):void 0
5740
5746
  return r?r.only&&r.only!==t?null:r:null},exports.wakeLineIsForUser=function(e,t){return"when-changed"!==exports.Cr.get(e)?.says||t},exports.holdsDuringUserTurn=function(e,t){const r=t?.systemNoteRequestId
5741
- return!("string"!=typeof r||!r)||"string"==typeof e&&exports.UT.has(e)},exports.UT=new Map([["request-registered","the [info] notice that a request was dispatched; the Alchemist is told it is informed, never waited on"],["request-info","an [info] notice about a request; informational"],["start-note","a request started; informational"],["request-canceled-notice","a request was canceled; informational"],["setup-settled","a setup settled minutes after it was started; it wakes the session to carry on, which a turn of its own does"],["wait-settled","a declared wait on another request settled; declared waits outlive turns"],["effect-failure-notice","a system effect failed; a report, not an answer to anything asked in the turn"],["worker-report","a check run's report to the session that owns it; runs outlive turns"],["monitor-wake","a monitor the session set fired; monitors wake idle sessions, not running turns"],["schedule-tick","a schedule fired; standing goals are never part of a user's turn"],["plan-complete","a plan finished building its requests; a hand-off, not an answer"],["main-moved","the main branch moved into lines a worker edits; advisory, nothing is blocked"],["merge-conflict","a sign-off merge conflicted and the branch comes back to its worker; work for a turn of its own"],["sitting-close","a sitting ended (the user went quiet, left the page or pressed Complete); the worker completes the round as a turn of its own, after the change it is on"],["keep-warm","a keep-warm tick; the runner skips busy sessions, and one arriving mid-turn has nothing to keep warm"]]),exports.Cr=new Map([["setup-settled",{says:"always",why:"a setup the session started or was asked about has ended; it carries on and says what it did, or how it ended"}],["monitor-wake",{says:"always",only:"alchemist",carries:"What you write last in this turn is shown to the user as your message in Steer. When there is nothing they need to hear, write nothing.",why:"a reminder or a watch the Alchemist set has fired; what it found is what the user asked to be told"}],["schedule-tick",{says:"when-changed",carries:"When you change something in this turn (a request filed, a document edited), what you write last is shown to the user as your message in Steer. When you change nothing, nothing you write is shown.",why:"a schedule fired; a firing that files a request says which and why, and a firing that finds nothing to do says nothing"}]])},76616(e,exports,t){"use strict"
5747
+ return!("string"!=typeof r||!r)||"string"==typeof e&&exports.UT.has(e)},exports.UT=new Map([["request-registered","the [info] notice that a request was dispatched; the Alchemist is told it is informed, never waited on"],["request-info","an [info] notice about a request; informational"],["start-note","a request started; informational"],["request-canceled-notice","a request was canceled; informational"],["setup-settled","a setup settled minutes after it was started; it wakes the session to carry on, which a turn of its own does"],["wait-settled","a declared wait on another request settled; declared waits outlive turns"],["effect-failure-notice","a system effect failed; a report, not an answer to anything asked in the turn"],["worker-report","a check run's report to the session that owns it; runs outlive turns"],["monitor-wake","a monitor the session set fired; monitors wake idle sessions, not running turns"],["schedule-tick","a schedule fired; standing goals are never part of a user's turn"],["unit-start","a message on a completed request's page, handed to its worker; where that worker still owes the user a reply, this starts when that turn has ended"],["plan-complete","a plan finished building its requests; a hand-off, not an answer"],["main-moved","the main branch moved into lines a worker edits; advisory, nothing is blocked"],["merge-conflict","a sign-off merge conflicted and the branch comes back to its worker; work for a turn of its own"],["sitting-close","a sitting ended (the user went quiet, left the page or pressed Complete); the worker completes the round as a turn of its own, after the change it is on"],["keep-warm","a keep-warm tick; the runner skips busy sessions, and one arriving mid-turn has nothing to keep warm"]]),exports.Cr=new Map([["setup-settled",{says:"always",why:"a setup the session started or was asked about has ended; it carries on and says what it did, or how it ended"}],["monitor-wake",{says:"always",only:"alchemist",carries:"What you write last in this turn is shown to the user as your message in Steer. When there is nothing they need to hear, write nothing.",why:"a reminder or a watch the Alchemist set has fired; what it found is what the user asked to be told"}],["schedule-tick",{says:"when-changed",carries:"When you change something in this turn (a request filed, a document edited), what you write last is shown to the user as your message in Steer. When you change nothing, nothing you write is shown.",why:"a schedule fired; a firing that files a request says which and why, and a firing that finds nothing to do says nothing"}],["unit-start",{says:"always",why:"the user asked on a completed request's page; an answer is the turn's closing text, and a change is completed as any request is"}]])},76616(e,exports,t){"use strict"
5742
5748
  function r(e){const t=(0,s.assembleTurnEvidence)(e)
5743
5749
  if("fatal-error"===t.kind){const e=t.refusal
5744
5750
  return{kind:t.kind,messageId:t.messageId,refusal:`${e?.model??"its model"} refused its turn ("${e?.message??t.errorName??"unknown error"}")`}}return"quota"===t.kind?{kind:t.kind,messageId:t.messageId,refusal:`the ${t.quota?.providerID??"provider"} usage limit was reached`}:"retryable-error"===t.kind&&"MessageAbortedError"!==t.errorName?{kind:t.kind,messageId:t.messageId}:null}exports.lastTurnDeath=r,exports.endSupersededPlanners=async function(e,t,s){const{apiClient:i,projectId:a,serverUrl:c,logger:l}=e,d=e.fetchImpl??fetch,u=[]
@@ -6716,7 +6722,7 @@ let r=!1
6716
6722
  for(;Date.now()<t;){try{const e=await fetch(`${f}/session/${o}/message?limit=5`,{signal:AbortSignal.timeout(4e3)})
6717
6723
  if(e.ok){const t=await e.json().catch(()=>[])
6718
6724
  if(Array.isArray(t)&&t.some(e=>(e?.info?.id??e?.id)===p)){r=!0
6719
- break}}}catch{}await new Promise(e=>setTimeout(e,1500))}return r?{success:!0}:{success:!1,error:`delivery_unverified: prompt_async accepted but message ${p} never appeared in session ${o}`}}catch(e){return{success:!1,error:(0,r.getErrorMessage)(e)}}}
6725
+ break}}}catch{}await new Promise(e=>setTimeout(e,1500))}return r?{success:!0,messageId:p}:{success:!1,error:`delivery_unverified: prompt_async accepted but message ${p} never appeared in session ${o}`}}catch(e){return{success:!1,error:(0,r.getErrorMessage)(e)}}}
6720
6726
  const r=t(58824),s=t(72485),n=t(45687)},2424(e,exports,t){"use strict"
6721
6727
  exports.ensureRequestWorktree=async function(e,t,a){const c=`requests/${t}`,l=(0,o.requestWorktreesDir)(e),d=(0,s.join)(l,t)
6722
6728
  if((0,r.existsSync)(d))return void a.info("Worktree already exists on disk, skipping pre-spawn creation",{requestId:t,worktreePath:d})
@@ -8155,7 +8161,7 @@ if(!s)return{}
8155
8161
  const n={}
8156
8162
  for(const[e,o]of Object.entries(s))!0===r[e]&&(n[`${t}_${e}`]=o)
8157
8163
  return n}
8158
- const t=["run","list","setup","remove"],r={session_message_operations:["send","note","reply","list","get","record-decision","brief","withdraw","question","user-answers","escalate"],request_operations:["update","complete","merge","reopen","get-info","list","search","status","cancel","wait-on","clear-wait","premise-block","asked-no-change","bring-main-in","list-areas","update-areas","check-target","round-piece"],create_request:[],guidance:["propose","exception","conflict","outdated","list"],document_operations:["create","update","search","create-snapshot","get-history","get-version","restore-version","archive","unarchive","list-annotations","create-annotation","reply-to-annotation","resolve-annotation","create-artifact-annotation"],commands:t}
8164
+ const t=["run","list","setup","remove"],r={session_message_operations:["send","note","reply","list","get","record-decision","brief","withdraw","question","user-answers","escalate"],request_operations:["update","complete","merge","reopen","get-info","list","search","status","cancel","wait-on","clear-wait","premise-block","bring-main-in","list-areas","update-areas","check-target","round-piece"],create_request:[],guidance:["propose","exception","conflict","outdated","list"],document_operations:["create","update","search","create-snapshot","get-history","get-version","restore-version","archive","unarchive","list-annotations","create-annotation","reply-to-annotation","resolve-annotation","create-artifact-annotation"],commands:t}
8159
8165
  exports.b={alchemist:{session_message_operations:["send","note","reply","list","get","record-decision","brief","withdraw","question","user-answers","escalate","plan-budget"],request_operations:["update","activate","complete","merge","revert","reopen","get-info","list","search","status","cancel","hold","premise-block","delete-empty","list-areas","update-areas","wait-on","clear-wait","hand-over","check-target","budget","target","arc-name","process","estimate"],create_request:["budget","estimate","schedule","delegate","refile","asked","process"],guidance:["propose","outdated","exception","conflict","list","standard","from-document","process"],document_operations:[...r.document_operations,"schedule"],commands:t},worker:r,coder:r,writer:r,reviewer:{session_message_operations:["send","note","reply","list","get","rule-verdicts"],guidance:["propose","list","standard"],document_operations:["search","get-history","get-version","list-annotations","create-annotation","reply-to-annotation","resolve-annotation","create-artifact-annotation"],record_criteria_verification:[]},driver:{commands:t},"auto-tester":{commands:t}},exports.REGISTER_BY_SETUP_RUN='Commands are saved by a setup run, not here: commands({ operation: "setup", context: "<the command, where it runs, what it is for>" }). Its setup architect tries the command in a box and saves it; you are told when it ends.',exports.REGISTER_BY_SETUP_RUN},82272(e,exports){"use strict"
8160
8166
  exports.partMeta=function(e,t){return t?{alchemy:{kind:e,payload:t}}:{alchemy:{kind:e}}},exports.alchemyMeta=function(e){return{_meta:{alchemy:e}}},exports.withAlchemyKind=function(e,t,r){const s=e._meta,n=s?.alchemy??{}
8161
8167
  return{...e,_meta:{...s,alchemy:{...n,...r,kind:t}}}}},39844(e,exports,t){"use strict"