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.
@@ -912,7 +912,7 @@ let r=!1
912
912
  for(;Date.now()<t;){try{const e=await fetch(`${f}/session/${s}/message?limit=5`,{signal:AbortSignal.timeout(4e3)})
913
913
  if(e.ok){const t=await e.json().catch(()=>[])
914
914
  if(Array.isArray(t)&&t.some(e=>(e?.info?.id??e?.id)===p)){r=!0
915
- 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 ${s}`}}catch(e){return{success:!1,error:(0,r.getErrorMessage)(e)}}}
915
+ 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 ${s}`}}catch(e){return{success:!1,error:(0,r.getErrorMessage)(e)}}}
916
916
  const r=t(58824),n=t(72485),o=t(45687)},35419(e,exports,t){exports.t=void 0,exports.getGlobalConfigDir=function(e){return(0,n.join)((0,r.homedir)(),o.ALCHEMY_DIR_NAME,e?"opencode-dev":"opencode")}
917
917
  const r=t(70857),n=t(16928),o=t(14139)
918
918
  exports.t="2.1.280"},69706(e,exports,t){function r(e){try{const t=JSON.parse(a.default.readFileSync(c.default.join(e,l),"utf8"))
@@ -1020,7 +1020,7 @@ const c=new Set(a),l="string"==typeof n.operation?n.operation:void 0
1020
1020
  if(l&&i?.includes(l)&&!c.has(l))return o[`${r} ${l}`]??`${r} ${l} is not an operation the ${e} uses. Its operations here: ${i.filter(e=>c.has(e)).join(", ")}.`
1021
1021
  for(const[o,i]of Object.entries(s??{}))if(!i.some(e=>c.has(e))&&t(n,o.split(".")))return`${r}: ${o} is not something the ${e} sets.`
1022
1022
  return null},exports.FIELD_TAGS_META="alchemylab/fieldTags"
1023
- const r=["run","list","setup","remove"],n={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:r}
1023
+ const r=["run","list","setup","remove"],n={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:r}
1024
1024
  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:[...n.document_operations,"schedule"],commands:r},worker:n,coder:n,writer:n,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:r},"auto-tester":{commands:r}},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.'
1025
1025
  const o={"commands register":exports.REGISTER_BY_SETUP_RUN},s=e=>null!=e&&""!==e&&!(Array.isArray(e)&&0===e.length)},82272(e,exports){exports.alchemyMeta=function(e){return{_meta:{alchemy:e}}},exports.withAlchemyKind=function(e,t,r){const n=e._meta,o=n?.alchemy??{}
1026
1026
  return{...e,_meta:{...n,alchemy:{...o,...r,kind:t}}}},exports.readAlchemyMeta=function(e){return e?._meta?.alchemy}},58185(e,exports,t){function r(e){if($.has(e))$.delete(e)
@@ -3720,13 +3720,13 @@ const t=new Date(`${e}T00:00:00`)
3720
3720
  return t.setDate(t.getDate()+1),new Date(t.getTime()-1).toISOString()}
3721
3721
  o.dateFrom&&(u.updatedAfter=h(String(o.dateFrom))),o.dateTo&&(u.updatedBefore=p(String(o.dateTo))),o.planDocumentId&&(u.planDocumentId=o.planDocumentId)
3722
3722
  const f=o.scheduleDocumentId||o.questDocumentId
3723
- f&&(u.scheduleDocumentId=f),u.limit=o.limit||20,u.offset=o.offset||0,u.sortBy="created"===o.sortBy?"created_at":(o.sortBy,"updated_at"),u.sortDirection=o.sortDirection||"desc",i.setProjectId(c),l.info("Sending query parameters",{queryParams:u})
3723
+ f&&(u.scheduleDocumentId=f),u.asRequests=!0,u.limit=o.limit||20,u.offset=o.offset||0,u.sortBy="created"===o.sortBy?"created_at":(o.sortBy,"updated_at"),u.sortDirection=o.sortDirection||"desc",i.setProjectId(c),l.info("Sending query parameters",{queryParams:u})
3724
3724
  const m=i.getRequestClient(),{requests:g,total:y}=await(0,s.requestPage)(m,u)
3725
3725
  l.debug("=== RAW SERVER RESPONSE DEBUG ===",{responseType:typeof g,isArray:Array.isArray(g),responseKeys:g?Object.keys(g):[],fullResponse:JSON.stringify(g,null,2)}),l.debug("Raw requests response data",{responseData:JSON.stringify(g)}),l.debug("Requests response structure",{type:typeof g,isArray:Array.isArray(g),hasData:null!=g,properties:g?Object.keys(g):[],dataPreview:g?JSON.stringify(g).substring(0,200)+"...":"null"})
3726
3726
  const w=(0,n.extractArrayFromResponse)(g,{logger:l,operationName:"listRequests",defaultValue:[]})
3727
3727
  if(l.info(`Extracted ${w.length} requests from response`),0===w.length)return d({success:!0,requestCount:0}),{content:[{type:"text",text:"No requests found with the specified filters."}]}
3728
- const b=w.map(e=>{const t=["canceled","reverted","completed"].includes(String(e.status))&&e.completionSummary?`${"completed"===e.status?"Outcome":"Why it ended"}: ${String(e.completionSummary).slice(0,400)}\n`:""
3729
- return`**${e.title}** (${e.id}) [${e.type}]\nStatus: ${e.status}${e.endedWithout?`, ended without ${e.endedWithout}`:""}\nType: ${e.type}\nCreated: ${new Date(e.createdAt).toLocaleString()}\nUpdated: ${new Date(e.updatedAt).toLocaleString()}\n${t}`}).join("\n---\n"),v=Number(u.offset)||0,k=null!==y&&y>v+w.length?` Showing ${v+1}-${v+w.length}; pass offset ${v+w.length} for the next page.`:"",I=`Found ${(0,s.countWords)(w.length,y)}.${k}`
3728
+ const b=w.map(e=>{const t=["canceled","reverted","completed"].includes(String(e.status))&&e.completionSummary?`${"completed"===e.status?"Outcome":"Why it ended"}: ${String(e.completionSummary).slice(0,400)}\n`:"",r=e.roundOf?`${e.roundOf}, a round of it open now, worked as ${e.id}`:e.id
3729
+ return`**${e.title}** (${r}) [${e.type}]\nStatus: ${e.status}${e.endedWithout?`, ended without ${e.endedWithout}`:""}\nType: ${e.type}\nCreated: ${new Date(e.createdAt).toLocaleString()}\nUpdated: ${new Date(e.updatedAt).toLocaleString()}\n${t}`}).join("\n---\n"),v=Number(u.offset)||0,k=null!==y&&y>v+w.length?` Showing ${v+1}-${v+w.length}; pass offset ${v+w.length} for the next page.`:"",I=`Found ${(0,s.countWords)(w.length,y)}.${k}`
3730
3730
  return d({success:!0,requestCount:w.length}),{content:[{type:"text",text:`${I}\n\n${b}`}]}}catch(t){return l.error("Error listing requests",{args:e,error:t instanceof Error?t.stack:String(t)}),d({success:!1,error:t instanceof Error?t.name:"unknown"}),{content:[{type:"text",text:`Error listing requests: ${(0,o.getErrorMessage)(t)}`}],isError:!0}}},t(87780)
3731
3731
  const r=t(59860),n=t(82960),o=t(58824),s=t(50129)},80024(e,exports,t){exports.formatLiveWorker=function(e){const t=e.agentType?e.agentType:"worker",r=[],n=!0===e.busy?"mid-turn":!1===e.busy?"between turns":"unknown"
3732
3732
  return r.push(`- ${t} (${e.sessionId}): ${e.status}, ${e.detail}; ${n}`),e.current&&r.push(` now: ${e.current}`),e.recent.length>0&&r.push(` recently: ${e.recent.join(", ")}`),e.lastSaid&&r.push(` last said${e.lastSaidAgo?` (${e.lastSaidAgo})`:""}: "${e.lastSaid}"`),e.lastRefusal&&r.push(` last refused (its tool said): ${e.lastRefusal}`),r.join("\n")},exports.readLiveWorker=async function(e,t){if(!e)return null
@@ -3901,7 +3901,7 @@ const t=new Map,r=(e,t)=>`${e}\0${t}`
3901
3901
  exports.SHAPING_AGENTS=new Set(["request-architect","planner"])
3902
3902
  const n=new Map},74165(e,exports,t){exports.def=void 0
3903
3903
  const r=t(76183),n=t(84648)
3904
- exports.def={name:"request_operations",description:"Operations on existing requests (create_request creates one).\n\n\u2022 complete - Phase one of completion: the summary; returns the criteria keys to verify.\n\u2022 merge - Phase two: evidence per criterion key; merges when all are met.\n\u2022 revert - Undo a completed request.\n\u2022 reopen - Send a finished, unmerged request back to rework with your reason (if the result already satisfies the feedback, say so instead; a merged one gets a follow-up).\n\u2022 update - Title, description, type, criteria, process, budget, target.\n\u2022 activate - Start a draft when the user asks (a draft held by intake: answer its ask).\n\u2022 get-info - Everything about a request.\n\u2022 list / search - List, or full-text search.\n\u2022 status - Where live work stands, per thread: done, running, next, what waits on the user, spend, anything stuck (requestId: its thread; planId: that plan's; neither: everything live).\n\u2022 list-areas / update-areas - The project's work areas / replace the request's.\n\u2022 wait-on / clear-wait - Record that this request waits for another (waitsOn, reason in the user's words) whenever work must queue; it ends when the blocker merges (a canceled one never does: move the wait). clear-wait without waitsOn clears all.\n\u2022 cancel - A request the user no longer wants (before merge), with reason; prose to a worker cancels nothing.\n\u2022 hold - Back to draft for an open request no worker has picked up (plan steps too); Start resumes it.\n\u2022 delete-empty - Delete a request with no tasks.\n\u2022 asked-no-change - After answering a user message on this request that changed nothing (userSaid).\n\u2022 hand-over - Give the user's message to the worker still warm on requestId, for an adjustment to its work; refused when none is live.\n\u2022 round-piece - On a round, when the user's message is a separate piece of work, not a change to this request: the round becomes its own request (update.title: what it makes).\n\u2022 bring-main-in - Merge main's newer work into your branch now; conflicts come back marked for you. Main also comes in when it changed a file you changed, and at sign-off.\n\u2022 check-target - Read the target of a thread on main now, met or missed.",schema:r.RequestOperationsSchema,fieldTags:{planId:["status","check-target"],criterion:["dispute-criterion"],reason:["cancel","revert","reopen","wait-on","premise-block","hold"],waitsOn:["wait-on","clear-wait"],update:["update"],"update.budget":["budget"],"update.target":["target"],"update.arcName":["arc-name"],"update.process":["process"],"update.estimate":["estimate"],areas:["update-areas"],complete:["complete"],"complete.couldNotCheck":["drive-claims"],merge:["merge"],revert:["revert"],list:["list"],search:["search"]},annotations:{title:"Request Operations",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler:(e,t)=>(0,n.handleRequestOperations)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer,t.cliOrigin)}},84648(e,exports,t){exports.handleRequestOperations=async function(e,t,x,S,_,E,C){const q=S.child({tool:"request_operations"})
3904
+ exports.def={name:"request_operations",description:"Operations on existing requests (create_request creates one).\n\n\u2022 complete - Phase one of completion: the summary; returns the criteria keys to verify.\n\u2022 merge - Phase two: evidence per criterion key; merges when all are met.\n\u2022 revert - Undo a completed request.\n\u2022 reopen - Send a finished, unmerged request back to rework with your reason (if the result already satisfies the feedback, say so instead; a merged one gets a follow-up).\n\u2022 update - Title, description, type, criteria, process, budget, target.\n\u2022 activate - Start a draft when the user asks (a draft held by intake: answer its ask).\n\u2022 get-info - Everything about a request.\n\u2022 list / search - List, or full-text search.\n\u2022 status - Where live work stands, per thread: done, running, next, what waits on the user, spend, anything stuck (requestId: its thread; planId: that plan's; neither: everything live).\n\u2022 list-areas / update-areas - The project's work areas / replace the request's.\n\u2022 wait-on / clear-wait - Record that this request waits for another (waitsOn, reason in the user's words) whenever work must queue; it ends when the blocker merges (a canceled one never does: move the wait). clear-wait without waitsOn clears all.\n\u2022 cancel - A request the user no longer wants (before merge), with reason; prose to a worker cancels nothing.\n\u2022 hold - Back to draft for an open request no worker has picked up (plan steps too); Start resumes it.\n\u2022 delete-empty - Delete a request with no tasks.\n\u2022 hand-over - Give the user's message to the worker still warm on requestId, for an adjustment to its work; refused when none is live.\n\u2022 round-piece - On a round, when the user's message is a separate piece of work, not a change to this request: the round becomes its own request (update.title: what it makes).\n\u2022 bring-main-in - Merge main's newer work into your branch now; conflicts come back marked for you. Main also comes in when it changed a file you changed, and at sign-off.\n\u2022 check-target - Read the target of a thread on main now, met or missed.",schema:r.RequestOperationsSchema,fieldTags:{planId:["status","check-target"],criterion:["dispute-criterion"],reason:["cancel","revert","reopen","wait-on","premise-block","hold"],waitsOn:["wait-on","clear-wait"],update:["update"],"update.budget":["budget"],"update.target":["target"],"update.arcName":["arc-name"],"update.process":["process"],"update.estimate":["estimate"],areas:["update-areas"],complete:["complete"],"complete.couldNotCheck":["drive-claims"],merge:["merge"],revert:["revert"],list:["list"],search:["search"]},annotations:{title:"Request Operations",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},handler:(e,t)=>(0,n.handleRequestOperations)(e,t.context,t.apiClient,t.logger,t.metrics,t.mcpServer,t.cliOrigin)}},84648(e,exports,t){exports.handleRequestOperations=async function(e,t,x,S,_,E,C){const q=S.child({tool:"request_operations"})
3905
3905
  try{const T=e
3906
3906
  let{requestId:R}=T
3907
3907
  const{operation:A}=T
@@ -3967,10 +3967,7 @@ try{const t=await(0,I.checkThreadTarget)(x.getProxyClient(),e,r)
3967
3967
  return(0,w.withAlchemyKind)({content:[{type:"text",text:t.text}],...t.isError?{isError:!0}:{}},$["check-target"])}catch(e){return{content:[{type:"text",text:`\u274c The target was not checked: ${(0,y.getErrorMessage)(e)}`}],isError:!0}}}case"round-piece":{const e="string"==typeof T.update?.title?T.update.title.trim():""
3968
3968
  if(!R||!e)return{content:[{type:"text",text:"\u274c **Request Operations Failed:** round-piece needs requestId (the round) and update.title (what the separate work makes, in a few words)"}],isError:!0}
3969
3969
  try{const n=await x.getProxyClient().proxyPost(`/api/projects/${t.projectId}/requests/${R}/round-piece`,{title:e,...t.currentSessionId?{sessionId:t.currentSessionId}:{}}),o=n?.data??n
3970
- return(0,w.withAlchemyKind)({content:[{type:"text",text:(0,r.ownRequestResult)(R,String(o?.was??""),String(o?.title??e),"string"==typeof o?.line?o.line:"")}]},$["round-piece"])}catch(e){return{content:[{type:"text",text:`\u274c **Request Operations Failed:** ${(0,y.getErrorMessage)(e)}`}],isError:!0}}}case"asked-no-change":{const e="string"==typeof T.userSaid?T.userSaid.trim():""
3971
- if(!R||!e)return{content:[{type:"text",text:"\u274c **Request Operations Failed:** asked-no-change needs requestId and userSaid (the user's message, quoted exactly)"}],isError:!0}
3972
- try{const r=await x.getProxyClient().proxyPost(`/api/projects/${t.projectId}/requests/${R}/steers/asked-no-change`,{userSaid:e}),n=r?.data??r,o=n?.marked?`Recorded: that message on ${R} asked for no change, so it is not listed as one.`:String(n?.reason??"Nothing to record.")
3973
- return(0,w.withAlchemyKind)({content:[{type:"text",text:o}]},$["asked-no-change"])}catch(e){return{content:[{type:"text",text:`\u274c **Request Operations Failed:** ${(0,y.getErrorMessage)(e)}`}],isError:!0}}}case"dispute-criterion":{const e="string"==typeof T.criterion?T.criterion.trim():""
3970
+ return(0,w.withAlchemyKind)({content:[{type:"text",text:(0,r.ownRequestResult)(R,String(o?.was??""),String(o?.title??e),"string"==typeof o?.line?o.line:"")}]},$["round-piece"])}catch(e){return{content:[{type:"text",text:`\u274c **Request Operations Failed:** ${(0,y.getErrorMessage)(e)}`}],isError:!0}}}case"dispute-criterion":{const e="string"==typeof T.criterion?T.criterion.trim():""
3974
3971
  if(!R||!e||!T.reason?.trim())return{content:[{type:"text",text:"\u274c **Request Operations Failed:** dispute-criterion needs requestId, criterion (its key, e.g. 1a) and reason (why it does not fit this request, for the user to read)"}],isError:!0}
3975
3972
  try{const r=await x.getProxyClient().proxyPost(`/api/projects/${t.projectId}/requests/${R}/criteria/${encodeURIComponent(e)}/dispute`,{reason:T.reason,sessionId:t.currentSessionId}),n=r?.data??r,o={asked:`The user has a card: waive ${n?.key??e} for ${R}, or keep it. Carry on with the rest of the work; you are told the answer. Until it is waived, the criterion still binds.`,"already-asked":`The user already has a card for ${n?.key??e} on ${R}; you are told the answer. Until it is waived, the criterion still binds.`,waived:`${n?.key??e} is already waived for ${R}; it no longer binds.`,kept:`The user already chose to keep ${n?.key??e} on ${R}: it applies here. Satisfy it.`}
3976
3973
  return(0,w.withAlchemyKind)({content:[{type:"text",text:o[n?.status]??"Dispute recorded."}]},$["dispute-criterion"])}catch(e){return{content:[{type:"text",text:`\u274c **Request Operations Failed:** ${(0,y.getErrorMessage)(e)}`}],isError:!0}}}case"premise-block":if(!R)return{content:[{type:"text",text:"\u274c **Request Operations Failed:** requestId is required for premise-block"}],isError:!0}
@@ -3981,7 +3978,7 @@ return!1===r?.blocked?(0,w.withAlchemyKind)({content:[{type:"text",text:`\u26a0\
3981
3978
  try{const e=x.getProxyClient(),r=await e.proxyGet(`/api/projects/${t.projectId}/tasks`,{requestId:R,limit:1}),n=r?.data||r||[]
3982
3979
  return(Array.isArray(n)?n.length:0)>0?{content:[{type:"text",text:`\u274c Cannot delete ${R}: it has tasks. Only empty requests (no tasks created) can be deleted.`}],isError:!0}:(await e.proxyDelete(`/api/projects/${t.projectId}/requests/${R}`),q.info("Empty request deleted",{requestId:R}),(0,w.withAlchemyKind)({content:[{type:"text",text:`\u2705 Request ${R} deleted (had no tasks).`}]},$["delete-empty"]))}catch(e){return{content:[{type:"text",text:`\u274c **Failed to delete request:** ${(0,y.getErrorMessage)(e)}`}],isError:!0}}default:{const e=`Unknown operation type: ${A}`
3983
3980
  return q.error(e),{content:[{type:"text",text:`\u274c **Request Operations Failed:** ${e}`}],isError:!0}}}}catch(e){return q.error("Request operations failed",{error:e instanceof Error?e.stack:String(e)}),_.incrementCounter("request_operations_errors",1),{content:[{type:"text",text:`\u274c **Request Operations Failed:** ${(0,y.getErrorMessage)(e)}`}],isError:!0}}}
3984
- const r=t(95765),n=t(95994),o=t(15715),s=t(16416),i=t(19670),a=t(5434),c=t(29729),l=new Set(["ready_for_review","completing","resolving_conflicts","conflicted"]),d=t(98037),u=t(80233),h=t(49229),p=t(23130),f=t(72271),m=t(36651),g=t(34306),y=t(58824),w=t(82272),b=t(62032),v=t(12286),k=t(79414),I=t(83326),$={update:"update-request",activate:"activate-request",complete:"complete-request",merge:"finalize-request",revert:"revert-request","get-info":"get-request-info",list:"list-requests",search:"search-requests",status:"status-digest","list-areas":"list-areas","update-areas":"update-areas","delete-empty":"delete-empty-request",cancel:"cancel-request",hold:"hold-request","premise-block":"premise-block-request","dispute-criterion":"dispute-criterion","asked-no-change":"asked-no-change","hand-over":"hand-over","bring-main-in":"bring-main-in","check-target":"check-target","round-piece":"round-piece","wait-on":"declare-request-wait","clear-wait":"clear-request-wait"}},50129(e,exports){exports.requestPage=async function(e,t){return"function"==typeof e.listRequestsPage?e.listRequestsPage(t):{requests:await e.listRequests(t),total:null}},exports.countWords=function(e,t,r="request"){const n=e=>`${r}${1===e?"":"s"}`
3981
+ const r=t(95765),n=t(95994),o=t(15715),s=t(16416),i=t(19670),a=t(5434),c=t(29729),l=new Set(["ready_for_review","completing","resolving_conflicts","conflicted"]),d=t(98037),u=t(80233),h=t(49229),p=t(23130),f=t(72271),m=t(36651),g=t(34306),y=t(58824),w=t(82272),b=t(62032),v=t(12286),k=t(79414),I=t(83326),$={update:"update-request",activate:"activate-request",complete:"complete-request",merge:"finalize-request",revert:"revert-request","get-info":"get-request-info",list:"list-requests",search:"search-requests",status:"status-digest","list-areas":"list-areas","update-areas":"update-areas","delete-empty":"delete-empty-request",cancel:"cancel-request",hold:"hold-request","premise-block":"premise-block-request","dispute-criterion":"dispute-criterion","hand-over":"hand-over","bring-main-in":"bring-main-in","check-target":"check-target","round-piece":"round-piece","wait-on":"declare-request-wait","clear-wait":"clear-request-wait"}},50129(e,exports){exports.requestPage=async function(e,t){return"function"==typeof e.listRequestsPage?e.listRequestsPage(t):{requests:await e.listRequests(t),total:null}},exports.countWords=function(e,t,r="request"){const n=e=>`${r}${1===e?"":"s"}`
3985
3982
  return null!==t&&t>e?`${e} of ${t} ${n(t)}`:`${e} ${n(e)}`},exports.statusParams=function(e){return e&&"undefined"!==e?"in_flight"===e?{inFlight:!0}:{status:e}:{}},exports.dateParams=function(e,t){const r={},n=e=>/^\d{4}-\d{2}-\d{2}$/.test(e)
3986
3983
  if(e){const t=String(e)
3987
3984
  r.updatedAfter=n(t)?new Date(`${t}T00:00:00`).toISOString():new Date(t).toISOString()}if(t){const e=String(t)
@@ -4041,7 +4038,7 @@ if(!c||0===c.trim().length)throw new a.ValidationError("Search query is required
4041
4038
  const m=t.projectId
4042
4039
  if(!m)throw new a.ValidationError("Project ID is required for searching requests")
4043
4040
  h.info("Searching requests",{query:c,searchIn:d,filters:f,projectId:m})
4044
- const g=Math.min(Math.max(Number(f.limit)||20,1),100),y={title:c.trim(),limit:"all"===d?g:100,offset:f.offset||0,sortBy:"updated_at",sortDirection:"desc",...(0,l.statusParams)(f.status),...(0,l.dateParams)(f.dateFrom,f.dateTo)}
4041
+ const g=Math.min(Math.max(Number(f.limit)||20,1),100),y={title:c.trim(),limit:"all"===d?g:100,offset:f.offset||0,sortBy:"updated_at",sortDirection:"desc",asRequests:!0,...(0,l.statusParams)(f.status),...(0,l.dateParams)(f.dateFrom,f.dateTo)}
4045
4042
  f.type&&(y.type=f.type),f.planDocumentId&&(y.planDocumentId=f.planDocumentId),(f.scheduleDocumentId||f.questDocumentId)&&(y.scheduleDocumentId=f.scheduleDocumentId||f.questDocumentId),i.setProjectId(m)
4046
4043
  const w=i.getRequestClient(),{requests:b,total:v}=await(0,l.requestPage)(w,y)
4047
4044
  h.debug("Fetched requests for search",{count:b.length,total:v})
@@ -5489,7 +5486,7 @@ if(null!=e)for(var s=r(e),i=0;i<s.length;i++)"default"!==s[i]&&n(t,e,s[i])
5489
5486
  return o(t,e),t})
5490
5487
  Object.defineProperty(exports,"__esModule",{value:!0}),exports.visualDefs=void 0
5491
5488
  const i=s(t(76183)),a=t(55432),c=t(93978),l=t(70089),d=t(70901),u=t(20339),h=t(75010),p=t(36399)
5492
- exports.visualDefs=[{name:"request_visual_feedback",description:'Ask the USER to mark up a screenshot of the UI and get their annotations back. EASIEST: start a box on a screenshot-capable env (experiment_start), then call this with `box` + `route` (e.g. "/") -- I render + screenshot that route for you. For FULL control (navigate, click, fill, scroll, log in, multi-step), pass `box` + `script`: a Playwright snippet (body of async (page, baseUrl) => {...}) -- I serve the app, launch headless Chromium, run your script, then screenshot the final state. You write ONLY the interaction; no serve/launch/flags. (Also: `fullPage` for the whole page; `box`+`path` for a screenshot you already wrote; `assetFilename` for an uploaded asset.) The user paints on it in the app (the action-required bell) and their annotated image comes back so you can SEE the changes they want. Returns the annotated image (or notes the user skipped / did not respond). Advisory -- never gates a merge.',schema:i.RequestVisualFeedbackSchema,annotations:{title:"Request Visual Feedback",readOnlyHint:!1},handler:(e,t)=>(0,a.handleRequestVisualFeedback)(e,t.context,t.apiClient,t.logger,t.metrics,t.cliOrigin)},{name:"ask_user_visual",description:'Ask the USER a question ANCHORED TO A REGION OF AN IMAGE -- point at the thing instead of describing it. Give `imagePath` (a screenshot you produced, repo-relative) or `previewName` (a registered live preview; I freeze it into a snapshot), plus `box` ("x,y,w,h", normalized 0..1) marking the region, your `question`, and optionally `options` for multiple choice. The question is pinned to that region and waits in the user inbox: they open the marked image in one click and answer on the record. The answer returns like any question answer (inline if they respond during the hold window, otherwise you are resumed automatically -- do not poll). Unlike request_visual_feedback (which returns an image the user paints), this returns the user\'s WORDS about a region YOU marked.',schema:i.AskUserVisualSchema,annotations:{title:"Ask User (Visual)",readOnlyHint:!1},handler:(e,t)=>(0,c.handleAskUserVisual)(e,t.context,t.apiClient,t.logger,t.metrics,t.cliOrigin)},{name:"capture_site",description:"Screenshot an http(s) URL, public or locally served, with the platform's host browser (it reaches the internet when boxes cannot). Stores the image as a project asset and returns it with an asset:<filename> ref to cite in documents or criteria, which a judge can later view with view_asset offline.",schema:i.CaptureSiteSchema,annotations:{title:"Capture Site Screenshot",readOnlyHint:!1},handler:(e,t)=>(0,l.handleCaptureSite)(e,t.logger,t.metrics,t.context,t.apiClient,t.cliOrigin)},{name:"read_site",description:"Load an http(s) URL in the platform's host browser and return the page's rendered visible text (up to 60k chars); pages that bot-wall webfetch render here. The result carries a ready `Source:` line and its read time: a text that rests on the page ends with that line. A claim checked here is verified as of that time; one from search summaries alone stays inferred, and say so.",schema:i.ReadSiteSchema,annotations:{title:"Read Site (Rendered Text)",readOnlyHint:!0},handler:(e,t)=>(0,d.handleReadSite)(e,t.logger,t.metrics,t.context,t.apiClient,t.cliOrigin)},{name:"drive_site",description:"DRIVE a running page in the platform's headless host browser: click, type, press keys, scroll, then read what the page says and looks like. Up to 20 steps per call; each reports whether it found its target. clickat (x,y) for canvas or game surfaces with no DOM. Pass `session` to keep the page open between calls (the only way to check accumulated state or elapsed time) and close:true on the last call. Persistent checks belong in a test process. The user never sees this browser: to hand a page to them, give the URL, the steps left for them in their own browser, and the final screenshot (ask_user_visual with imagePath, or cite it in a report). Never type a password, a key or an acceptance on the user's behalf.",schema:i.DriveSiteSchema,annotations:{title:"Drive Site (Interact)",readOnlyHint:!1},handler:(e,t)=>(0,u.handleDriveSite)(e,t.logger,t.metrics,t.context,t.apiClient,t.cliOrigin)},{name:"fetch_asset",description:"Download an image or font from an http(s) URL straight INTO the working tree (e.g. `sites/acme/assets/hero.jpg`). Use it to vendor the assets a page needs so the result is self-contained -- confined runs have no network, so a page that hotlinks an image renders broken in the test gate and to anyone offline. webfetch cannot do this: it returns a page as text, or an image into the conversation, and neither writes bytes to a file. Images and fonts only, 12MB cap, path confined to the working tree.",schema:i.FetchAssetSchema,annotations:{title:"Fetch Asset",readOnlyHint:!1},handler:(e,t)=>(0,h.handleFetchAsset)(e,t.context,t.logger,t.metrics)},{name:"preview_site",description:"Serve a built static directory (containing index.html) from this machine and return a link the user can open; it is also registered as a live preview in the artifact viewer. Use it when the deliverable is a page. Pass requestId to serve an unmerged request's own working copy. Build into a folder git ignores (the project's build folder, e.g. dist/): a box run commits every file it writes outside ignored folders to your branch, and the preview serves the folder only while it exists. Never copy files into main to preview them.",schema:i.PreviewSiteSchema,annotations:{title:"Preview Site",readOnlyHint:!1},handler:(e,t)=>(0,p.handlePreviewSite)(e,t.logger,t.metrics,t.context)}]},20339(e,exports,t){exports.handleDriveSite=async function(e,n,o,s,i,a){const c=o.startTimer("tool_execution_time"),l=e=>(c({success:!1,error:"bad"}),{content:[{type:"text",text:e}],isError:!0})
5489
+ exports.visualDefs=[{name:"request_visual_feedback",description:'Ask the USER to mark up a screenshot of the UI and get their annotations back. EASIEST: start a box on a screenshot-capable env (experiment_start), then call this with `box` + `route` (e.g. "/") -- I render + screenshot that route for you. For FULL control (navigate, click, fill, scroll, log in, multi-step), pass `box` + `script`: a Playwright snippet (body of async (page, baseUrl) => {...}) -- I serve the app, launch headless Chromium, run your script, then screenshot the final state. You write ONLY the interaction; no serve/launch/flags. (Also: `fullPage` for the whole page; `box`+`path` for a screenshot you already wrote; `assetFilename` for an uploaded asset.) The user paints on it in the app (the action-required bell) and their annotated image comes back so you can SEE the changes they want. Returns the annotated image (or notes the user skipped / did not respond). Advisory -- never gates a merge.',schema:i.RequestVisualFeedbackSchema,annotations:{title:"Request Visual Feedback",readOnlyHint:!1},handler:(e,t)=>(0,a.handleRequestVisualFeedback)(e,t.context,t.apiClient,t.logger,t.metrics,t.cliOrigin)},{name:"ask_user_visual",description:'Ask the USER a question ANCHORED TO A REGION OF AN IMAGE -- point at the thing instead of describing it. Give `imagePath` (a screenshot you produced, repo-relative) or `previewName` (a registered live preview; I freeze it into a snapshot), plus `box` ("x,y,w,h", normalized 0..1) marking the region, your `question`, and optionally `options` for multiple choice. The question is pinned to that region and waits in the user inbox: they open the marked image in one click and answer on the record. The answer returns like any question answer (inline if they respond during the hold window, otherwise you are resumed automatically -- do not poll). Unlike request_visual_feedback (which returns an image the user paints), this returns the user\'s WORDS about a region YOU marked.',schema:i.AskUserVisualSchema,annotations:{title:"Ask User (Visual)",readOnlyHint:!1},handler:(e,t)=>(0,c.handleAskUserVisual)(e,t.context,t.apiClient,t.logger,t.metrics,t.cliOrigin)},{name:"capture_site",description:"Screenshot an http(s) URL, public or locally served, with the platform's host browser (it reaches the internet when boxes cannot). Stores the image as a project asset and returns it with an asset:<filename> ref to cite in documents or criteria, which a judge can later view with view_asset offline.",schema:i.CaptureSiteSchema,annotations:{title:"Capture Site Screenshot",readOnlyHint:!1},handler:(e,t)=>(0,l.handleCaptureSite)(e,t.logger,t.metrics,t.context,t.apiClient,t.cliOrigin)},{name:"read_site",description:"Load an http(s) URL in the platform's host browser and return the page's rendered visible text (up to 60k chars); pages that bot-wall webfetch render here. The result carries a ready `Source:` line and its read time: a text that rests on the page ends with that line. A claim checked here is verified as of that time; one from search summaries alone stays inferred, and say so.",schema:i.ReadSiteSchema,annotations:{title:"Read Site (Rendered Text)",readOnlyHint:!0},handler:(e,t)=>(0,d.handleReadSite)(e,t.logger,t.metrics,t.context,t.apiClient,t.cliOrigin)},{name:"drive_site",description:"DRIVE a running page in the platform's headless host browser: click, type, press keys, scroll, then read what the page says and looks like. Up to 20 steps per call; each reports whether it found its target. clickat (x,y) for canvas or game surfaces with no DOM. Pass `session` to keep the page open between calls (the only way to check accumulated state or elapsed time) and close:true on the last call. Persistent checks belong in a test process. The user never sees this browser: to hand a page to them, give the URL, the steps left for them in their own browser, and the final screenshot (ask_user_visual with imagePath, or cite it in a report). Never type a password, a key or an acceptance on the user's behalf.",schema:i.DriveSiteSchema,annotations:{title:"Drive Site (Interact)",readOnlyHint:!1},handler:(e,t)=>(0,u.handleDriveSite)(e,t.logger,t.metrics,t.context,t.apiClient,t.cliOrigin)},{name:"fetch_asset",description:"Download an image or font from an http(s) URL straight INTO the working tree (e.g. `sites/acme/assets/hero.jpg`). Use it to vendor the assets a page needs so the result is self-contained -- confined runs have no network, so a page that hotlinks an image renders broken in the test gate and to anyone offline. webfetch cannot do this: it returns a page as text, or an image into the conversation, and neither writes bytes to a file. Images and fonts only, 12MB cap, path confined to the working tree.",schema:i.FetchAssetSchema,annotations:{title:"Fetch Asset",readOnlyHint:!1},handler:(e,t)=>(0,h.handleFetchAsset)(e,t.context,t.logger,t.metrics)},{name:"preview_site",description:"Serve a built static directory (containing index.html) from this machine and return a link the user can open; it is also registered as a live preview in the artifact viewer. Use it when the deliverable is a page. With stop: true it stops a running preview (name it when several run). Pass requestId to serve an unmerged request's own working copy. Build into a folder git ignores (the project's build folder, e.g. dist/): a box run commits every file it writes outside ignored folders to your branch, and the preview serves the folder only while it exists. Never copy files into main to preview them.",schema:i.PreviewSiteSchema,annotations:{title:"Preview Site",readOnlyHint:!1},handler:(e,t)=>(0,p.handlePreviewSite)(e,t.logger,t.metrics,t.context)}]},20339(e,exports,t){exports.handleDriveSite=async function(e,n,o,s,i,a){const c=o.startTimer("tool_execution_time"),l=e=>(c({success:!1,error:"bad"}),{content:[{type:"text",text:e}],isError:!0})
5493
5490
  try{const o=(e.url||"").trim()
5494
5491
  if(!/^https?:\/\//i.test(o))return l("`url` must be an http(s) URL.")
5495
5492
  const d=Array.isArray(e.steps)?e.steps:[]
@@ -5536,7 +5533,17 @@ if(a.skipped)return l({success:!0}),{content:[{type:"text",text:"The human skipp
5536
5533
  const u=[{type:"text",text:`Human visual feedback received${a.note?`. Note: ${a.note}`:""}. The annotated screenshot follows (red/markup = what to change).`}],h=a.annotationDataUrl,p="string"==typeof h?h.match(/^data:([^;]+);base64,(.*)$/s):null
5537
5534
  return p?u.push({type:"image",data:p[2],mimeType:p[1]}):a.annotationAssetFilename&&u.push({type:"text",text:`Annotated image asset: ${a.annotationAssetFilename} (view with view_asset).`}),l({success:!0}),{content:u}}catch(e){return l({success:!1,error:"exception"}),i.warn("request_visual_feedback failed",{error:(0,n.getErrorMessage)(e)}),{content:[{type:"text",text:`Visual feedback request failed: ${(0,n.getErrorMessage)(e)}`}],isError:!0}}}
5538
5535
  const n=t(58824),o=e=>new Promise(t=>setTimeout(t,e))},36399(e,exports,t){exports.handlePreviewSite=async function(e,o,s,i){const a=s.startTimer("tool_execution_time")
5539
- try{let r=(e.dir||"").trim(),o="string"==typeof e.requestId?e.requestId.trim():""
5536
+ try{if(!0===e.stop){const r=await async function(e){const{actionServerFetch:r}=await Promise.resolve().then(()=>t(79414)),n=await r("/api/previews",{signal:AbortSignal.timeout(5e3)}).then(e=>e.json()).catch(()=>null)
5537
+ if(!n?.success||!Array.isArray(n.data))return{text:"The running previews could not be read just now, so nothing was stopped. Try again.",isError:!0}
5538
+ const o=function(e,t){const r=(t??"").trim().toLowerCase()
5539
+ if(0===e.length)return{none:!0}
5540
+ if(r){const t=e.find(e=>e.name.toLowerCase()===r)??e.find(e=>(e.label??"").trim().toLowerCase()===r)
5541
+ return t?{name:t.name}:{which:e.map(e=>e.label?`${e.name} ("${e.label}")`:e.name)}}return 1===e.length?{name:e[0].name}:{which:e.map(e=>e.label?`${e.name} ("${e.label}")`:e.name)}}(n.data,e)
5542
+ if("none"in o)return{text:"No preview is running, so there is nothing to stop."}
5543
+ if("which"in o)return{text:`${e?`No running preview is called "${e}".`:"More than one preview is running."} Nothing was stopped. Running now: ${o.which.join(", ")}. Call again with stop and the name of the one to stop.`}
5544
+ const s=await r(`/api/previews/${encodeURIComponent(o.name)}`,{method:"DELETE",signal:AbortSignal.timeout(1e4)}),i=await s.json().catch(()=>({}))
5545
+ return s.ok&&i?.success?{text:i?.data?.stopped?`Stopped the preview ${o.name}: it is no longer served and is gone from Previews.`:`Removed the preview ${o.name} from Previews. AlchemyLab was not the one serving it (a server the project runs is its own), so that server is untouched.`}:{text:`The preview ${o.name} could not be stopped: ${i?.error||"HTTP "+s.status}`,isError:!0}}("string"==typeof e.name?e.name:void 0)
5546
+ return a({success:!r.isError}),{content:[{type:"text",text:r.text}],...r.isError?{isError:!0}:{}}}let r=(e.dir||"").trim(),o="string"==typeof e.requestId?e.requestId.trim():""
5540
5547
  if(o){const e=function(e,t){if(!/^req\d{6}$/.test(e))return null
5541
5548
  const r=t.replace(/^\.?\/+/,"").replace(/\/+$/,"")
5542
5549
  return r.startsWith("/")||r.split("/").includes("..")?null:r&&"."!==r?r:"."}(o,r||".")
@@ -5591,13 +5598,13 @@ exports.SubagentOperationsSchema=n.z.object({sessionId:p.optional(),operation:n.
5591
5598
  "propose-standard"!==r||e.standardRules&&e.standardRules.length||t.addIssue({code:"custom",message:"standardRules is required for propose-standard: [{ text, section, checked, kinds? }]"}),["create-snapshot","get-history","get-version","restore-version","list-annotations","create-annotation","propose-standard"].includes(r)&&!e.documentId&&t.addIssue({code:"custom",message:`documentId is required for '${r}'. Example: { "operation": "${r}", "documentId": "doc000001" }`}),"create"===r&&(e.filename?/\.(md|html?)$/i.test(e.filename)||t.addIssue({code:"custom",message:"Filename must end in .md (prose) or .html (a rendered page)"}):t.addIssue({code:"custom",message:"filename is required for create (must end in .md or .html)"}),e.content||t.addIssue({code:"custom",message:"content is required for create"})),"search"!==r||e.query||t.addIssue({code:"custom",message:'query is required for search. Example: { "operation": "search", "query": "search term" }'}),"get-version"!==r&&"restore-version"!==r||e.versionNumber||t.addIssue({code:"custom",message:`versionNumber is required for '${r}'`}),"create-annotation"===r&&(e.selectedText||t.addIssue({code:"custom",message:"selectedText is required for create-annotation"}),e.body||t.addIssue({code:"custom",message:"body is required for create-annotation"})),"reply-to-annotation"===r&&(e.annotationId||t.addIssue({code:"custom",message:"annotationId is required for reply-to-annotation"}),e.body||t.addIssue({code:"custom",message:"body is required for reply-to-annotation"})),"resolve-annotation"!==r||e.annotationId||t.addIssue({code:"custom",message:"annotationId is required for resolve-annotation"}),"create-artifact-annotation"===r&&(e.ref||t.addIssue({code:"custom",message:'ref is required for create-artifact-annotation. Example: { "operation": "create-artifact-annotation", "ref": "file:src/main.cpp", "line": 42, "body": "..." }'}),e.body||t.addIssue({code:"custom",message:"body is required for create-artifact-annotation"}))})
5592
5599
  const f=d
5593
5600
  exports.PlanReadSchema=n.z.object({operation:n.z.enum(["get","get-active","list","get-history","get-requests"]),planId:f.optional(),searchQuery:n.z.string().optional(),limit:n.z.number().min(1).max(100).default(20),offset:n.z.number().min(0).default(0),sortBy:n.z.enum(["createdAt","updatedAt","filename"]).default("updatedAt"),sortDirection:n.z.enum(["ASC","DESC"]).default("DESC")}).superRefine((e,t)=>{["get","get-history","get-requests"].includes(e.operation)&&!e.planId&&t.addIssue({code:"custom",message:`planId is required for '${e.operation}'. Example: { "operation": "${e.operation}", "planId": "plan000001" }`})}),exports.PlanWriteSchema=n.z.object({operation:n.z.enum(["create","update","append","replace","create-snapshot","restore"]),planId:f.optional(),kind:n.z.enum(["plan"]).default("plan").describe("Document kind to create. Plans only."),content:n.z.string().optional(),name:n.z.string().optional().describe("Plan name (used in filename for create; optional new name for update)."),old_str:n.z.string().optional().describe("Text to find in the plan (for replace)"),new_str:n.z.string().optional().describe("Replacement text (for replace)"),versionLabel:n.z.string().optional(),changeSummary:n.z.string().optional(),versionNumber:n.z.number().int().min(1).optional()}).superRefine((e,t)=>{const r=e.operation
5594
- "create"===r?(e.name||t.addIssue({code:"custom",message:"name is required for 'create'. Letters, numbers, hyphens, underscores only."}),void 0===e.content&&t.addIssue({code:"custom",message:"content is required for 'create' (use empty string for an empty body)."})):e.planId||t.addIssue({code:"custom",message:`planId is required for '${r}'.`}),"append"!==r||e.content||t.addIssue({code:"custom",message:'content is required for \'append\'. Example: { "operation": "append", "planId": "plan000001", "content": "..." }'}),"update"===r&&(void 0!==e.content||e.name||t.addIssue({code:"custom",message:"update requires 'content' and/or 'name'."})),"replace"===r&&(e.old_str||t.addIssue({code:"custom",message:'old_str is required for replace. Example: { "operation": "replace", "planId": "plan000001", "old_str": "find this", "new_str": "replace with" }'}),void 0===e.new_str&&t.addIssue({code:"custom",message:"new_str is required for replace"})),"restore"!==r||e.versionNumber||t.addIssue({code:"custom",message:'versionNumber is required for restore. Example: { "operation": "restore", "planId": "plan000001", "versionNumber": 1 }'})}),exports.RevertRequestSchema=n.z.object({requestId:l,reason:n.z.string(),confirmDestructive:n.z.boolean().optional()}),exports.ModifyFileSchema=n.z.object({operations:n.z.array(n.z.object({path:n.z.string().optional(),documentId:d.optional(),operationType:n.z.enum(["replace-string","insert-lines","replace-lines","delete-string","delete-lines"]),replaceString:n.z.object({replacements:n.z.array(n.z.object({old_str:n.z.string(),new_str:n.z.string()})),mode:n.z.enum(["unique","all"]).optional()}).optional(),insertLines:n.z.object({insertions:n.z.array(n.z.object({type:n.z.enum(["before","after","between"]),line:n.z.number().optional(),afterLine:n.z.number().optional(),beforeLine:n.z.number().optional(),content:n.z.union([n.z.string(),n.z.array(n.z.string())])}).refine(e=>"between"===e.type?void 0!==e.afterLine&&void 0!==e.beforeLine&&void 0===e.line:void 0!==e.line&&void 0===e.afterLine&&void 0===e.beforeLine,{message:"Invalid line parameters"}))}).optional(),replaceLines:n.z.object({replacements:n.z.array(n.z.object({lines:n.z.string(),content:n.z.union([n.z.string(),n.z.array(n.z.string())])}))}).optional(),deleteString:n.z.object({patterns:n.z.array(n.z.string()),mode:n.z.enum(["all","unique"]).optional()}).optional(),deleteLines:n.z.object({lines:n.z.string()}).optional()}).transform(u).refine(h,{message:"path or documentId required"}).refine(e=>"replace-string"===e.operationType?e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"insert-lines"===e.operationType?e.insertLines&&!e.replaceString&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"replace-lines"===e.operationType?e.replaceLines&&!e.replaceString&&!e.insertLines&&!e.deleteString&&!e.deleteLines:"delete-string"===e.operationType?e.deleteString&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteLines:"delete-lines"===e.operationType&&e.deleteLines&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString,{message:"Invalid operation data"})),comment:n.z.string()}),exports.ManageFilesSchema=n.z.object({operations:n.z.array(n.z.object({operationType:n.z.enum(["create-directory","move-files","delete-files","get-file-info"]),createDirectory:n.z.object({path:n.z.string()}).optional(),moveFiles:n.z.object({moves:n.z.array(n.z.object({source:n.z.string(),destination:n.z.string()}))}).optional(),deleteFiles:n.z.object({targets:n.z.array(n.z.object({path:n.z.string().optional(),documentId:d.optional()}).transform(u).refine(h,{message:"path or documentId required"}))}).optional(),getFileInfo:n.z.object({path:n.z.string()}).optional()}).refine(e=>"create-directory"===e.operationType?e.createDirectory&&!e.moveFiles&&!e.deleteFiles&&!e.getFileInfo:"move-files"===e.operationType?e.moveFiles&&!e.createDirectory&&!e.deleteFiles&&!e.getFileInfo:"delete-files"===e.operationType?e.deleteFiles&&!e.createDirectory&&!e.moveFiles&&!e.getFileInfo:"get-file-info"===e.operationType&&e.getFileInfo&&!e.createDirectory&&!e.moveFiles&&!e.deleteFiles,{message:"Invalid operation data"})),comment:n.z.string()}),exports.RequestOperationsSchema=n.z.object({requestId:l.optional(),operation:n.z.enum(["update","activate","complete","merge","revert","reopen","get-info","list","search","status","cancel","hold","delete-empty","list-areas","update-areas","wait-on","clear-wait","premise-block","dispute-criterion","asked-no-change","hand-over","bring-main-in","check-target","round-piece"]),planId:n.z.string().max(64).optional().describe("status / check-target: a plan's thread."),criterion:n.z.string().optional(),reason:n.z.string().optional().describe('cancel, revert, reopen, wait-on: why, to the user ("you"), in their language (a replacing request named). premise-block (required): what the request builds on that the project lacks; not what it adds, not unclear wording (ask instead).'),userSaid:n.z.string().min(8).max(600).optional().describe("The user's words asking for this, exact (checked). Required for activate, cancel of finished work waiting on them, and reopen with a question pending on them; asked-no-change: their message."),waitsOn:n.z.string().optional(),update:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({userSaid:n.z.string().min(8).max(600).optional().describe("The user's words asking for this change, exact; a worker narrows or rewords its own request only with them."),budget:n.z.number().positive().max(1e5).nullable().optional().describe("The budget the user named for this request's thread (or plan), dollars at list price, their words in userSaid; null removes it."),target:exports.TargetConditionsSchema.optional(),estimate:n.z.number().positive().max(1e5).optional().describe("Expected cost, dollars at list price."),removesCriteria:n.z.boolean().optional().describe("true to delete the criteria your list leaves out; otherwise a shorter list is refused."),arcName:n.z.string().min(2).max(120).optional().describe("The thread's name, two to five plain words (\"Weekly menu app\"); set once, never over the user's."),title:n.z.string().optional(),description:n.z.string().optional(),process:n.z.string().nullable().optional().describe("A workflow process by name, or null; drafts only."),type:exports.SettableRequestTypeEnum.optional(),acceptanceCriteria:n.z.array(n.z.union([n.z.string(),n.z.object({description:n.z.string().min(1),beforeMerge:n.z.boolean().optional(),command:n.z.string().min(1).max(500).optional().describe("With the criterion's key: replaces its command, and the old line is kept on the record beside it. A worker replaces one that cannot pass where it runs with a line that checks the same thing, never less; the user's own command only with their answer in userSaid."),environment:n.z.string().min(1).max(120).optional().describe("As on create_request; set it instead of dropping a command the box cannot run."),kind:n.z.enum(["objective","subjective","gate"]),baseline:r(exports.BaselineSchema).optional(),key:n.z.string().optional().describe("The key of a criterion you reword (it keeps its verdicts); omit for a new one.")})])).optional().describe("Replaces the whole list; items as on create_request.")})).optional(),areas:n.z.array(n.z.string()).max(3).optional().describe("update-areas: up to 3 replacing the current ones; [] clears."),complete:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({change:n.z.preprocess(i,n.z.string().min(3).max(200).optional()).describe('On a round (its description opens "Round N of req######"), instead of summary while the round is open: what this one change did, in one line. The user reads it under the message that asked for it.'),summary:n.z.preprocess(i,n.z.string().optional()).describe('Markdown the user reads when it lands. First line: one sentence with the answer (if the request asked a question) or what changed. Then, only if there is more, one short "- " line per thing; no paragraphs. Never "tested" or "verified" when that failed. It replaces earlier summaries (after rework it covers the whole request) and stays after sign-off, so it says what was delivered, not what waits for the user. On a round it is written once, when you are told the round is being completed; until then pass change.'),replacesSummary:n.z.boolean().optional().describe("Required on a re-completion: the summary covers everything, fixes included."),notChecked:n.z.preprocess(i,n.z.string().min(3).max(160).optional()).describe('What you did not check that the user could assume you did ("the page on a phone"); the card leads with it. Not what registered checks run or say they leave out (the card shows those).'),show:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({commands:n.z.array(n.z.string().min(1).max(400)).max(5).optional().describe("Command lines that show the result working. AlchemyLab runs each in a box on the work as it was and on the completed work; the user sees both."),artifact:n.z.string().min(1).max(200).optional().describe("A picture, page or document on the record: a result's address, a document id (doc000012) or asset:<file>.")}).optional()).describe("Optional: something more to show with the finished result. What the request already delivered is shown by itself."),worthKnowing:n.z.array(n.z.string().min(10)).max(5).optional().describe("What the user would regret not knowing, one per entry (a discovery, caveat, side effect, follow-up); always one when what was asked was already true or turned out different. Not the summary again; subject first."),guidance:n.z.array(n.z.object({body:n.z.string().min(10).max(800).describe('One fact or instruction for the next agent ("calc.py is generated from ops.json: edit ops.json and regenerate.")'),files:n.z.array(n.z.string().min(1)).min(1).max(8).optional().describe("Files or folders (globs) it is pinned to; without them (userSaid only) the whole project."),evidence:n.z.string().min(1).max(1500).optional().describe("What shows it (command and output, file); not with userSaid."),userSaid:n.z.string().min(8).max(600).optional().describe("A correction of the user's that should hold later: their words, exact.")}).refine(e=>!!e.userSaid||!!e.files?.length&&!!e.evidence,{message:"a trap needs files and evidence; a correction of the user's needs userSaid"})).max(2).optional().describe("A trap the next agent in these files would hit too, or a user correction, proposed as guidance. Not taste, not request-specific, not already guidance. Usually none."),skipTestsReason:exports.skipTestsReasonSchema,skipTests:exports.skipTestsSchema,criteriaComments:n.z.array(n.z.object({key:n.z.string().min(1),comment:n.z.string().min(1),verify:n.z.array(n.z.string().min(1)).max(4).optional().describe("Commands that prove it in the sealed acceptance box (a grep, a targeted test, a screenshot into .visual-check/), judged on their output. Clean checkout of your commit, dependencies installed, nothing built: a check needing a build runs it in the same command. No git, no network, no branching on whether a tool exists. A proof you saw pass on this commit, written exactly as you ran it, is reused."),testFiles:n.z.array(n.z.string().min(1)).max(10).optional().describe("With verify, when it runs just these tests (not the whole suite): their repo paths. Only the user changes a test a promise names.")})).optional().describe("One entry per criterion, keyed as your pickup lists it: what you did and how you saw it hold."),afterRun:n.z.boolean().optional().describe("Call `run` with your final check, then this complete in the SAME response: it completes only if that run passes."),couldNotCheck:n.z.array(n.z.string().min(1)).max(20).optional().describe("Drives only: keys of claims you could not check (reason in criteriaComments); they read as unchecked. Stamp the rest with record_criteria_verification.")})).optional(),merge:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({verifications:n.z.array(n.z.object({key:n.z.string().min(2).max(4),evidence:n.z.string().min(1)})).min(1)})).optional(),revert:n.z.object({reason:n.z.string(),confirmDestructive:n.z.boolean().optional()}).optional(),list:n.z.object({filters:n.z.object({type:exports.RequestTypeEnum.optional(),status:exports.RequestStatusFilterEnum.optional(),planDocumentId:n.z.string().optional(),scheduleDocumentId:n.z.string().optional(),questDocumentId:n.z.string().optional(),dateFrom:n.z.string().optional(),dateTo:n.z.string().optional(),limit:n.z.number().min(1).max(100).default(20),offset:n.z.number().min(0).default(0),sortBy:n.z.enum(["created","updated"]).default("updated"),sortDirection:n.z.enum(["asc","desc"]).default("desc")}).optional()}).optional(),search:n.z.object({query:n.z.string().min(1),searchIn:n.z.enum(["title","description","criteria","all"]).default("all"),filters:n.z.object({type:exports.RequestTypeEnum.optional(),status:exports.RequestStatusFilterEnum.optional(),planDocumentId:n.z.string().optional(),scheduleDocumentId:n.z.string().optional(),questDocumentId:n.z.string().optional(),dateFrom:n.z.string().optional(),dateTo:n.z.string().optional(),limit:n.z.number().min(1).max(100).default(20),offset:n.z.number().min(0).default(0)}).optional()}).optional()}).superRefine((e,t)=>{e.requestId
5601
+ "create"===r?(e.name||t.addIssue({code:"custom",message:"name is required for 'create'. Letters, numbers, hyphens, underscores only."}),void 0===e.content&&t.addIssue({code:"custom",message:"content is required for 'create' (use empty string for an empty body)."})):e.planId||t.addIssue({code:"custom",message:`planId is required for '${r}'.`}),"append"!==r||e.content||t.addIssue({code:"custom",message:'content is required for \'append\'. Example: { "operation": "append", "planId": "plan000001", "content": "..." }'}),"update"===r&&(void 0!==e.content||e.name||t.addIssue({code:"custom",message:"update requires 'content' and/or 'name'."})),"replace"===r&&(e.old_str||t.addIssue({code:"custom",message:'old_str is required for replace. Example: { "operation": "replace", "planId": "plan000001", "old_str": "find this", "new_str": "replace with" }'}),void 0===e.new_str&&t.addIssue({code:"custom",message:"new_str is required for replace"})),"restore"!==r||e.versionNumber||t.addIssue({code:"custom",message:'versionNumber is required for restore. Example: { "operation": "restore", "planId": "plan000001", "versionNumber": 1 }'})}),exports.RevertRequestSchema=n.z.object({requestId:l,reason:n.z.string(),confirmDestructive:n.z.boolean().optional()}),exports.ModifyFileSchema=n.z.object({operations:n.z.array(n.z.object({path:n.z.string().optional(),documentId:d.optional(),operationType:n.z.enum(["replace-string","insert-lines","replace-lines","delete-string","delete-lines"]),replaceString:n.z.object({replacements:n.z.array(n.z.object({old_str:n.z.string(),new_str:n.z.string()})),mode:n.z.enum(["unique","all"]).optional()}).optional(),insertLines:n.z.object({insertions:n.z.array(n.z.object({type:n.z.enum(["before","after","between"]),line:n.z.number().optional(),afterLine:n.z.number().optional(),beforeLine:n.z.number().optional(),content:n.z.union([n.z.string(),n.z.array(n.z.string())])}).refine(e=>"between"===e.type?void 0!==e.afterLine&&void 0!==e.beforeLine&&void 0===e.line:void 0!==e.line&&void 0===e.afterLine&&void 0===e.beforeLine,{message:"Invalid line parameters"}))}).optional(),replaceLines:n.z.object({replacements:n.z.array(n.z.object({lines:n.z.string(),content:n.z.union([n.z.string(),n.z.array(n.z.string())])}))}).optional(),deleteString:n.z.object({patterns:n.z.array(n.z.string()),mode:n.z.enum(["all","unique"]).optional()}).optional(),deleteLines:n.z.object({lines:n.z.string()}).optional()}).transform(u).refine(h,{message:"path or documentId required"}).refine(e=>"replace-string"===e.operationType?e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"insert-lines"===e.operationType?e.insertLines&&!e.replaceString&&!e.replaceLines&&!e.deleteString&&!e.deleteLines:"replace-lines"===e.operationType?e.replaceLines&&!e.replaceString&&!e.insertLines&&!e.deleteString&&!e.deleteLines:"delete-string"===e.operationType?e.deleteString&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteLines:"delete-lines"===e.operationType&&e.deleteLines&&!e.replaceString&&!e.insertLines&&!e.replaceLines&&!e.deleteString,{message:"Invalid operation data"})),comment:n.z.string()}),exports.ManageFilesSchema=n.z.object({operations:n.z.array(n.z.object({operationType:n.z.enum(["create-directory","move-files","delete-files","get-file-info"]),createDirectory:n.z.object({path:n.z.string()}).optional(),moveFiles:n.z.object({moves:n.z.array(n.z.object({source:n.z.string(),destination:n.z.string()}))}).optional(),deleteFiles:n.z.object({targets:n.z.array(n.z.object({path:n.z.string().optional(),documentId:d.optional()}).transform(u).refine(h,{message:"path or documentId required"}))}).optional(),getFileInfo:n.z.object({path:n.z.string()}).optional()}).refine(e=>"create-directory"===e.operationType?e.createDirectory&&!e.moveFiles&&!e.deleteFiles&&!e.getFileInfo:"move-files"===e.operationType?e.moveFiles&&!e.createDirectory&&!e.deleteFiles&&!e.getFileInfo:"delete-files"===e.operationType?e.deleteFiles&&!e.createDirectory&&!e.moveFiles&&!e.getFileInfo:"get-file-info"===e.operationType&&e.getFileInfo&&!e.createDirectory&&!e.moveFiles&&!e.deleteFiles,{message:"Invalid operation data"})),comment:n.z.string()}),exports.RequestOperationsSchema=n.z.object({requestId:l.optional(),operation:n.z.enum(["update","activate","complete","merge","revert","reopen","get-info","list","search","status","cancel","hold","delete-empty","list-areas","update-areas","wait-on","clear-wait","premise-block","dispute-criterion","hand-over","bring-main-in","check-target","round-piece"]),planId:n.z.string().max(64).optional().describe("status / check-target: a plan's thread."),criterion:n.z.string().optional(),reason:n.z.string().optional().describe('cancel, revert, reopen, wait-on: why, to the user ("you"), in their language (a replacing request named). premise-block (required): what the request builds on that the project lacks; not what it adds, not unclear wording (ask instead).'),userSaid:n.z.string().min(8).max(600).optional().describe("The user's words asking for this, exact (checked). Required for activate, cancel of finished work waiting on them, and reopen with a question pending on them."),waitsOn:n.z.string().optional(),update:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({userSaid:n.z.string().min(8).max(600).optional().describe("The user's words asking for this change, exact; a worker narrows or rewords its own request only with them."),budget:n.z.number().positive().max(1e5).nullable().optional().describe("The budget the user named for this request's thread (or plan), dollars at list price, their words in userSaid; null removes it."),target:exports.TargetConditionsSchema.optional(),estimate:n.z.number().positive().max(1e5).optional().describe("Expected cost, dollars at list price."),removesCriteria:n.z.boolean().optional().describe("true to delete the criteria your list leaves out; otherwise a shorter list is refused."),arcName:n.z.string().min(2).max(120).optional().describe("The thread's name, two to five plain words (\"Weekly menu app\"); set once, never over the user's."),title:n.z.string().optional(),description:n.z.string().optional(),process:n.z.string().nullable().optional().describe("A workflow process by name, or null; drafts only."),type:exports.SettableRequestTypeEnum.optional(),acceptanceCriteria:n.z.array(n.z.union([n.z.string(),n.z.object({description:n.z.string().min(1),beforeMerge:n.z.boolean().optional(),command:n.z.string().min(1).max(500).optional().describe("With the criterion's key: replaces its command, and the old line is kept on the record beside it. A worker replaces one that cannot pass where it runs with a line that checks the same thing, never less; the user's own command only with their answer in userSaid."),environment:n.z.string().min(1).max(120).optional().describe("As on create_request; set it instead of dropping a command the box cannot run."),kind:n.z.enum(["objective","subjective","gate"]),baseline:r(exports.BaselineSchema).optional(),key:n.z.string().optional().describe("The key of a criterion you reword (it keeps its verdicts); omit for a new one.")})])).optional().describe("Replaces the whole list; items as on create_request.")})).optional(),areas:n.z.array(n.z.string()).max(3).optional().describe("update-areas: up to 3 replacing the current ones; [] clears."),complete:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({change:n.z.preprocess(i,n.z.string().min(3).max(200).optional()).describe('On a round (its description opens "Round N of req######"), instead of summary while the round is open: what this one change did, in one line. The user reads it under the message that asked for it.'),summary:n.z.preprocess(i,n.z.string().optional()).describe('Markdown the user reads when it lands. First line: one sentence with the answer (if the request asked a question) or what changed. Then, only if there is more, one short "- " line per thing; no paragraphs. Never "tested" or "verified" when that failed. It replaces earlier summaries (after rework it covers the whole request) and stays after sign-off, so it says what was delivered, not what waits for the user. On a round it is written once, when you are told the round is being completed; until then pass change.'),replacesSummary:n.z.boolean().optional().describe("Required on a re-completion: the summary covers everything, fixes included."),notChecked:n.z.preprocess(i,n.z.string().min(3).max(160).optional()).describe('What you did not check that the user could assume you did ("the page on a phone"); the card leads with it. Not what registered checks run or say they leave out (the card shows those).'),show:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({commands:n.z.array(n.z.string().min(1).max(400)).max(5).optional().describe("Command lines that show the result working. AlchemyLab runs each in a box on the work as it was and on the completed work; the user sees both."),artifact:n.z.string().min(1).max(200).optional().describe("A picture, page or document on the record: a result's address, a document id (doc000012) or asset:<file>.")}).optional()).describe("Optional: something more to show with the finished result. What the request already delivered is shown by itself."),worthKnowing:n.z.array(n.z.string().min(10)).max(5).optional().describe("What the user would regret not knowing, one per entry (a discovery, caveat, side effect, follow-up); always one when what was asked was already true or turned out different. Not the summary again; subject first."),guidance:n.z.array(n.z.object({body:n.z.string().min(10).max(800).describe('One fact or instruction for the next agent ("calc.py is generated from ops.json: edit ops.json and regenerate.")'),files:n.z.array(n.z.string().min(1)).min(1).max(8).optional().describe("Files or folders (globs) it is pinned to; without them (userSaid only) the whole project."),evidence:n.z.string().min(1).max(1500).optional().describe("What shows it (command and output, file); not with userSaid."),userSaid:n.z.string().min(8).max(600).optional().describe("A correction of the user's that should hold later: their words, exact.")}).refine(e=>!!e.userSaid||!!e.files?.length&&!!e.evidence,{message:"a trap needs files and evidence; a correction of the user's needs userSaid"})).max(2).optional().describe("A trap the next agent in these files would hit too, or a user correction, proposed as guidance. Not taste, not request-specific, not already guidance. Usually none."),skipTestsReason:exports.skipTestsReasonSchema,skipTests:exports.skipTestsSchema,criteriaComments:n.z.array(n.z.object({key:n.z.string().min(1),comment:n.z.string().min(1),verify:n.z.array(n.z.string().min(1)).max(4).optional().describe("Commands that prove it in the sealed acceptance box (a grep, a targeted test, a screenshot into .visual-check/), judged on their output. Clean checkout of your commit, dependencies installed, nothing built: a check needing a build runs it in the same command. No git, no network, no branching on whether a tool exists. A proof you saw pass on this commit, written exactly as you ran it, is reused."),testFiles:n.z.array(n.z.string().min(1)).max(10).optional().describe("With verify, when it runs just these tests (not the whole suite): their repo paths. Only the user changes a test a promise names.")})).optional().describe("One entry per criterion, keyed as your pickup lists it: what you did and how you saw it hold."),afterRun:n.z.boolean().optional().describe("Call `run` with your final check, then this complete in the SAME response: it completes only if that run passes."),couldNotCheck:n.z.array(n.z.string().min(1)).max(20).optional().describe("Drives only: keys of claims you could not check (reason in criteriaComments); they read as unchecked. Stamp the rest with record_criteria_verification.")})).optional(),merge:n.z.preprocess(e=>"string"==typeof e?(()=>{try{return JSON.parse(e)}catch{return e}})():e,n.z.object({verifications:n.z.array(n.z.object({key:n.z.string().min(2).max(4),evidence:n.z.string().min(1)})).min(1)})).optional(),revert:n.z.object({reason:n.z.string(),confirmDestructive:n.z.boolean().optional()}).optional(),list:n.z.object({filters:n.z.object({type:exports.RequestTypeEnum.optional(),status:exports.RequestStatusFilterEnum.optional(),planDocumentId:n.z.string().optional(),scheduleDocumentId:n.z.string().optional(),questDocumentId:n.z.string().optional(),dateFrom:n.z.string().optional(),dateTo:n.z.string().optional(),limit:n.z.number().min(1).max(100).default(20),offset:n.z.number().min(0).default(0),sortBy:n.z.enum(["created","updated"]).default("updated"),sortDirection:n.z.enum(["asc","desc"]).default("desc")}).optional()}).optional(),search:n.z.object({query:n.z.string().min(1),searchIn:n.z.enum(["title","description","criteria","all"]).default("all"),filters:n.z.object({type:exports.RequestTypeEnum.optional(),status:exports.RequestStatusFilterEnum.optional(),planDocumentId:n.z.string().optional(),scheduleDocumentId:n.z.string().optional(),questDocumentId:n.z.string().optional(),dateFrom:n.z.string().optional(),dateTo:n.z.string().optional(),limit:n.z.number().min(1).max(100).default(20),offset:n.z.number().min(0).default(0)}).optional()}).optional()}).superRefine((e,t)=>{e.requestId
5595
5602
  const r=e.operation,n={complete:{field:"complete",hint:'Provide: { complete: { summary: "..." } }'},merge:{field:"merge",hint:'Provide: { merge: { verifications: [{key: "1a", evidence: "..."}] } }'},revert:{field:"revert",hint:'Provide: { revert: { reason: "..." } }'},search:{field:"search",hint:'Provide: { search: { query: "..." } }'}}[r]
5596
5603
  n&&!e[n.field]&&t.addIssue({code:"custom",message:`'${r}' operation requires '${n.field}' data. ${n.hint}`})})
5597
5604
  const m=n.z.string({required_error:"Required. A quick edit either touches up an earlier request's result or stands on its own: pass that request id (req######) or the word 'new'."}).refine(e=>"new"===e||/^req\d{6}$/.test(e),{message:"Pass a request id like req000031, or 'new'."}).describe("The request whose result this edit adjusts (the user pointed at it), or 'new': the same rule as create_request's follows.")
5598
5605
  exports.QuickWriteSchema=n.z.object({title:n.z.string().min(1,"Title is required"),description:n.z.string().min(1,"Description is required"),follows:m,path:n.z.string().optional(),documentId:d.optional(),content:n.z.union([n.z.string(),n.z.array(n.z.string())]),format:n.z.enum(["text","json"]).optional(),append:n.z.boolean().optional()}).transform(u).refine(h,{message:"path or documentId required"}),exports.QuickReplaceSchema=n.z.object({title:n.z.string().min(1,"Title is required"),description:n.z.string().min(1,"Description is required"),follows:m,operations:n.z.array(n.z.object({path:n.z.string().optional(),documentId:d.optional(),replacements:n.z.array(n.z.object({old_str:n.z.string().min(1),new_str:n.z.string(),match_mode:n.z.enum(["unique","all"]).optional()})).min(1),fuzzy_match:n.z.boolean().optional()}).transform(u).refine(h,{message:"path or documentId required"})).min(1),fuzzy_match:n.z.boolean().optional(),comment:n.z.string().min(1,"Comment describing the change is required")}),exports.MetaWorkflowListSchema=n.z.object({}),exports.MetaWorkflowGetSchema=n.z.object({workflowId:n.z.string().describe("Workflow ID to retrieve")}),exports.MetaWorkflowCreateSchema=n.z.object({name:n.z.string().min(1).describe("Unique name for the workflow"),shortName:n.z.string().min(1).max(10).describe("Short display name (required, max 10 chars)"),description:n.z.string().optional().describe("Description of what the workflow does"),testGate:n.z.enum(["off","auto","ask"]).optional().describe("Test gate: off (no test gate), auto (checks run automatically; a blocking command must pass, an advisory one may be skipped with a reason), ask (the user picks auto/interactive/skip at each completion)"),reviewGate:n.z.enum(["off","on"]).optional().describe("Review gate: off, or on (one reviewer checks each acceptance criterion, with the reviewers the kind assigns: guidance, model on engineering, any the workflow added)"),signoffGate:n.z.enum(["off","agent","you"]).optional().describe('Sign-off gate, as the workflow page names it: off; agent ("Delivery review": an agent asks whether the delivery is what was asked for, then merges or brings it to the user); you ("You sign off": the user approves before merge)'),approvalMode:n.z.enum(["none","require-approval","agent-check"]).optional().describe("Pre-work approval: none (default), require-approval (the user approves each request), or agent-check (an independent intake reviewer rules on agent-created requests before work starts)"),interactionPosture:n.z.enum(["autonomous","balanced","collaborative"]).optional().describe("Interaction posture (question-gate dial): autonomous (defaulted questions are self-answered -- proceed + FYI report), balanced (default; questions post normally, non-blocking when defaulted), collaborative (always ask the human)")}),exports.MetaWorkflowUpdateSchema=n.z.object({workflowId:n.z.string().describe("Workflow ID to update"),name:n.z.string().min(1).optional().describe("New name"),shortName:n.z.string().max(10).optional().describe("New short name (max 10 chars)"),description:n.z.string().optional().describe("New description"),testGate:n.z.enum(["off","auto","ask"]).optional().describe("Test gate: off (no test gate), auto (checks run automatically; a blocking command must pass, an advisory one may be skipped with a reason), ask (the user picks auto/interactive/skip at each completion)"),reviewGate:n.z.enum(["off","on"]).optional().describe("Review gate: off, or on (one reviewer checks each acceptance criterion, with the reviewers the kind assigns: guidance, model on engineering, any the workflow added)"),signoffGate:n.z.enum(["off","agent","you"]).optional().describe('Sign-off gate, as the workflow page names it: off; agent ("Delivery review": an agent asks whether the delivery is what was asked for, then merges or brings it to the user); you ("You sign off": the user approves before merge)'),approvalMode:n.z.enum(["none","require-approval","agent-check"]).optional().describe("Pre-work approval: none (default), require-approval (the user approves each request), or agent-check (an independent intake reviewer rules on agent-created requests before work starts)"),interactionPosture:n.z.enum(["autonomous","balanced","collaborative"]).optional().describe("Interaction posture (question-gate dial): autonomous (defaulted questions are self-answered -- proceed + FYI report), balanced (default; questions post normally, non-blocking when defaulted), collaborative (always ask the human)")}),exports.MetaRecipeListSchema=n.z.object({}),exports.MetaRecipeGetSchema=n.z.object({recipeId:n.z.string().describe("Recipe ID to retrieve")}),exports.MetaRecipeCreateSchema=n.z.object({name:n.z.string().min(1).describe("Unique name for the recipe"),description:n.z.string().optional().describe("Description of what the recipe does"),documentation:n.z.string().optional().describe("Detailed documentation")}),exports.MetaRecipeAddHookSchema=n.z.object({recipeId:n.z.string().describe("Recipe ID to add the hook to"),hookId:n.z.string().describe("Hook template ID to add"),position:n.z.number().int().min(0).optional().describe("Position in the recipe (0-based, appended if omitted)")}),exports.MetaRecipeRemoveHookSchema=n.z.object({recipeId:n.z.string().describe("Recipe ID to remove the hook from"),hookId:n.z.string().describe("Hook template ID to remove")}),exports.MetaHookListSchema=n.z.object({}),exports.MetaHookCreateSchema=n.z.object({name:n.z.string().min(1).describe("Unique name for the hook"),description:n.z.string().optional().describe("Description of what the hook does"),eventType:n.z.string().describe("Event type that triggers this hook (e.g., session_idle, request_completed, custom:plan_ready)"),category:n.z.enum(["alchemy","session","message","editing","reading","file_management","documents","history","tool"]).default("session").describe("Hook category"),agent:n.z.string().describe("Agent template to execute when hook fires"),promptTemplate:n.z.string().describe("Prompt template with {{variable}} substitution"),condition:n.z.record(n.z.any()).optional().describe("Condition object for filtering when hook fires"),timing:n.z.enum(["before","after"]).default("after").describe("When to fire relative to the event"),action:n.z.enum(["spawn_agent","inject_prompt"]).optional().describe("What the hook does: spawn_agent (default) starts a new session of `agent` with the prompt; inject_prompt sends the prompt into an existing session"),target:n.z.enum(["independent_session","child_session","same_session","parent_session","ancestor_chain"]).optional().describe("Where the prompt goes. With spawn_agent: independent_session (default, no parent) or child_session (under the session that fired the event). With inject_prompt: same_session (default, the session that fired the event), parent_session, or ancestor_chain"),maxIterations:n.z.number().int().min(1).optional().describe("Maximum times the hook fires for one session, counted from its firing record. Set it on every session_idle hook that sends into the same session. A session a hook started never triggers that hook again, whatever this says"),emitEvent:n.z.string().optional().describe("Custom event to emit on completion"),emitEventOnCondition:n.z.union([n.z.object({condition:n.z.object({field:n.z.string(),operator:n.z.enum(["contains","not_contains","equals","not_equals","matches","not_matches"]),value:n.z.string()}),event:n.z.string()}),n.z.array(n.z.object({condition:n.z.object({field:n.z.string(),operator:n.z.enum(["contains","not_contains","equals","not_equals","matches","not_matches"]),value:n.z.string()}),event:n.z.string()}))]).optional().describe("Conditional event emission based on output")}),exports.MetaWorkflowAddRecipeSchema=n.z.object({workflowId:n.z.string().describe("Workflow ID to add the recipe to"),recipeId:n.z.string().describe("Recipe ID to add"),position:n.z.number().int().min(0).optional().describe("Position in the workflow (0-based, appended if omitted)")}),exports.MetaWorkflowRemoveRecipeSchema=n.z.object({workflowId:n.z.string().describe("Workflow ID to remove the recipe from"),recipeId:n.z.string().describe("Recipe ID to remove")}),exports.MetaAgentListSchema=n.z.object({}),exports.MetaOperationsSchema=n.z.object({operation:n.z.enum(["workflow-list","workflow-get","workflow-create","workflow-update","recipe-list","recipe-get","recipe-create","recipe-add-hook","recipe-remove-hook","hook-list","hook-create","workflow-add-recipe","workflow-remove-recipe","agent-list"]).describe("Which meta operation to perform; the other params apply per operation (see tool description)"),...exports.MetaWorkflowGetSchema.partial().shape,...exports.MetaWorkflowCreateSchema.partial().shape,...exports.MetaWorkflowUpdateSchema.partial().shape,...exports.MetaRecipeGetSchema.partial().shape,...exports.MetaRecipeCreateSchema.partial().shape,...exports.MetaRecipeAddHookSchema.partial().shape,...exports.MetaRecipeRemoveHookSchema.partial().shape,...exports.MetaHookCreateSchema.partial().shape,...exports.MetaWorkflowAddRecipeSchema.partial().shape,...exports.MetaWorkflowRemoveRecipeSchema.partial().shape}),exports.TestingProcessListSchema=n.z.object({}),exports.TestingProcessGetSchema=n.z.object({processId:n.z.string().describe("Test process ID to retrieve")})
5599
5606
  const g=n.z.object({name:n.z.string().min(1).describe('Command name (e.g., "Build", "Unit Tests")'),command:n.z.string().min(1).describe('Shell command to run (e.g., "npm test")'),required:n.z.boolean().default(!0).describe("If true, failure blocks the request (default: true)"),timeout:n.z.number().int().min(10).max(3600).default(300).describe("Max execution time in seconds (default: 300)")})
5600
- exports.TestingProcessCreateSchema=n.z.object({name:n.z.string().min(1).describe("Name for the test process"),environmentId:n.z.string().optional().describe("ID of the environment (confined runtime) this process runs in. Get it from environment_list or environment_setup."),description:n.z.string().optional().describe("Description of what this process verifies"),scope:n.z.string().optional().describe('LABEL ONLY -- a monorepo path prefix recorded for display (e.g. "packages/api/"). It does NOT affect when the process runs; use pathGlobs for that.'),pathGlobs:n.z.array(n.z.string()).optional().describe('Which changes this process runs on: glob patterns matched against the changed files (e.g. ["sites/**"], ["src/**", "*.md"]). THIS is what limits when the process runs. Omit it and the process runs on EVERY change, which is the right choice only for a check that is cheap and universal.'),areas:n.z.array(n.z.string()).optional().describe('Work-area labels this process covers (e.g. ["graphics/opengl"]). An alternative to pathGlobs for work that is not file-shaped; a process applies if EITHER dimension matches.'),setup:n.z.array(n.z.string()).optional().describe("Commands that prepare the tree for the tests (install the package itself, generate files the tests import), e.g. [\"python -m pip install --no-deps -e .\"]. They run in its box before its commands on every run, and also before a request's criteria checks, which run in a clean checkout of the commit where `commands` do not run: a preparation step put in `commands` is missing there and those checks fail. If one fails, the run fails as the environment's fault and the commands do not run."),commands:n.z.array(g).min(1).describe("Test commands to execute in order"),verifyAcceptanceCriteria:n.z.boolean().optional().describe("When true, auto-tester verifies request acceptance criteria after running commands"),fingerprint:n.z.array(n.z.string()).optional().describe('Files whose content invalidates setup. Setup commands re-run only when these files change between runs (e.g. ["package-lock.json"], ["Cargo.lock"], ["uv.lock", "poetry.lock"]). Polyglot repos list multiple. Omit / empty list = always re-run setup (existing behavior).'),poolSize:n.z.number().int().min(1).max(8).optional().describe("Number of warm test worktrees in the pool. Default 2. Set to 1 for languages with very large build artifacts (Rust target/, C++ build/). Higher values allow more parallel test runs at the cost of disk."),runtimeKept:n.z.string().optional().describe('Only when the user chose to run the check on a runtime other than the lowest one the project declares: that runtime and version, e.g. "python 3.12". Without it, a check whose environment runs another version than the declared minimum is not registered.'),leavesOut:n.z.array(n.z.object({what:n.z.string().describe('The left-out part in plain words, e.g. "the Valkey backend tests"'),paths:n.z.array(n.z.string()).min(1).describe('Globs for the code that part checks, so a change there goes unchecked by this check: for a backend\'s tests, that backend (e.g. ["aiocache/backends/valkey.py"]); for browser or end-to-end tests, the app source they drive (e.g. ["src/**"]). Not only the left-out test files.'),command:n.z.string().min(1).max(300).optional().describe('The command that runs that part, e.g. "pnpm test:e2e": a request whose criterion runs it is not told this part was left out.')})).optional().describe('What this check deliberately does not run and no other check runs (the suites the card lists as "not run on every change"), each with the code it checks. A change to that code is reported to the user as not checked by this check, unless the request ran that part itself.')}),exports.TestingProcessDeleteSchema=n.z.object({processId:n.z.string().describe("Test process ID to delete")}),exports.EnvironmentListSchema=n.z.object({}),exports.ResultsSchema=n.z.object({operation:n.z.enum(["record","fetch","pin","list","read"]),path:n.z.string().optional().describe("record: the file, inside the project (not /tmp); your worktree first, then the main project. Bulk that must not reach a commit can be written by a command under `.alchemy_lab/scratch/` (gitignored)."),name:n.z.string().optional().describe("record: the name a person uses for it (defaults to the filename). list: show every version recorded under this name, newest first."),summary:n.z.record(n.z.any()).optional().describe('record (required): the small facts a reader wants instead of the bytes, e.g. {maxStress: 412, unit: "MPa", converged: true}.'),box:n.z.string().optional().describe("An experiment handle (exp_...). fetch: put the bytes inside that sealed box under its /scratch (a box cannot see the host scratch; omit for host work, which is faster). record: the result lives inside that box and is streamed out and stored in one step (a box cannot write your worktree)."),mediaType:n.z.string().optional().describe("record: MIME type, when you know it."),inputs:n.z.array(n.z.string()).optional().describe("record: addresses of the results this one was made from (provenance)."),note:n.z.string().optional().describe("record: one line on how it was produced."),address:n.z.string().optional().describe("pin / read / fetch: the full 64-character address the record returned (a unique prefix works too)."),at:n.z.string().optional().describe("pin: the pointer path in your worktree (.result.json is added). fetch: where the bytes land, under AlchemyLab's scratch folder for the project on the host (the answer gives the full path) or the box's `/scratch`. Defaults to results/<name>."),comment:n.z.string().optional().describe("pin: the commit comment for the pointer file."),offset:n.z.number().optional().describe("read: line to start at (default 0)."),limit:n.z.number().optional().describe("read: how many lines (default 200). list: how many results (default 25)."),find:n.z.string().optional().describe("read: return only lines containing this text, instead of a range.")}),exports.ResultInspectSchema=n.z.object({operation:n.z.enum(["list","read"]),name:n.z.string().optional().describe("list: show every version recorded under this name, newest first."),address:n.z.string().optional().describe("read: the full 64-character address of the result, a check run's id (tr_...) or a command run's record id (trec...), to read what its commands printed."),offset:n.z.number().optional().describe("read: line to start at (default 0)."),limit:n.z.number().optional().describe("read: how many lines (default 200). list: how many results (default 25)."),find:n.z.string().optional().describe("read: return only lines containing this text, instead of a range.")}),exports.ExperimentStartSchema=n.z.object({env:n.z.string().optional().describe("Environment by name (from environment_list), one whose image has the toolchain you need."),environmentId:n.z.string().optional().describe("Environment by id (alternative to `env`). The primary env is used if neither is given."),size:n.z.enum(["light","standard","heavy"]).optional().describe("light: 2 cores (lint, a typecheck, one test file). standard (default): a share of the free cores (a suite, a build). heavy: every free core but 2 and 6 GB of memory (2 GB otherwise, unless the environment sets its own), for work that uses them (a CFD solve, meshing, a large parallel build, a model that runs out of memory). A size you do not hold opens another box."),confirmWorkspace:n.z.boolean().optional().describe('Required for env "workspace" (the live host): the task genuinely needs the real machine. Building or trying out the app does not.')}),exports.ExperimentStopSchema=n.z.object({handle:n.z.string().describe("The experiment handle to tear down.")}),exports.ExperimentListSchema=n.z.object({}),exports.ReadSiteSchema=n.z.object({url:n.z.string()}),exports.DriveSiteSchema=n.z.object({url:n.z.string().describe("The running product, e.g. the environment's published URL or http://localhost:5173."),steps:n.z.array(n.z.object({action:n.z.enum(["click","clickat","type","press","move","scroll","wait","media"]).describe('click (selector) \xb7 clickat (x,y) \xb7 type (selector + text) \xb7 press (key) \xb7 move (x,y) \xb7 scroll (dy) \xb7 wait (ms, max 5000) \xb7 media ("print" shows the printout, "screen" switches back)'),selector:n.z.string().optional().describe('Playwright selector, e.g. "text=Build" or "#start".'),text:n.z.string().optional(),key:n.z.string().optional().describe('e.g. "Enter"'),x:n.z.number().optional(),y:n.z.number().optional(),dy:n.z.number().optional(),ms:n.z.number().optional(),media:n.z.enum(["print","screen"]).optional()})).min(1).max(20),shots:n.z.enum(["each","final"]).optional().describe('"each" screenshots every step; default the final state only.'),session:n.z.string().optional().describe("Keeps the page open: the next call with this name continues where this one stopped. Idle sessions close after 10 minutes."),close:n.z.boolean().optional().describe("Close the named session after this call."),width:n.z.number().optional().describe("Viewport width for a new session (default 1280; 390 is a phone).")}),exports.CaptureSiteSchema=n.z.object({url:n.z.string(),fullPage:n.z.boolean().optional().describe("The whole scrollable page instead of the viewport."),width:n.z.number().optional().describe("Viewport width (default 1280; 390 is a phone).")}),exports.PreviewSiteSchema=n.z.object({dir:n.z.string().describe('Repo-relative, e.g. "dist" or "." for the top of the repository.'),requestId:n.z.string().regex(/^req\d{6}$/).optional().describe("Serve from this unmerged request's working copy instead of main."),name:n.z.string().optional().describe("Preview handle (default: a slug of dir); reusing one replaces that preview."),label:n.z.string().optional()}),exports.FetchAssetSchema=n.z.object({url:n.z.string().describe("The http(s) URL of the image or font to download."),destPath:n.z.string().describe('Where to write it, repo-relative (e.g. "sites/acme/assets/hero.jpg"). Must stay inside the working tree; parent directories are created.')}),exports.RequestVisualFeedbackSchema=n.z.object({box:n.z.string().optional().describe("The experiment handle (from experiment_start, on a screenshot-capable env) to render in / read from. The box must stay held until this returns."),route:n.z.string().optional().describe('With `box`: the route I render + screenshot FOR YOU (e.g. "/" or "/settings"). I serve `serveDir` and screenshot it -- you do NOT hand-roll serve/screenshot. This is the easiest path.'),script:n.z.string().optional().describe('With `box`, for FULL control: a Playwright snippet (the body of `async (page, baseUrl) => { ... }`). I serve the app, launch headless Chromium, and run your script -- navigate (page.goto(baseUrl + "/x")), click, fill, scroll, waitForSelector, etc. -- then screenshot the final page state. Reliable: you write only the interaction, no serve/launch/flags. Use this to reach a state that needs interaction (open a menu, log in, submit a form).'),fullPage:n.z.boolean().optional().describe("Capture the entire scrollable page instead of just the viewport."),serveDir:n.z.string().optional().describe("With `box`+`route`: the static dir to serve (default /work). For a built app, build first via run(), then point this at the build output (e.g. /work/dist)."),path:n.z.string().optional().describe("Alternative to route: a screenshot you ALREADY wrote inside the box (e.g. /tmp/shot.png); I read it out."),assetFilename:n.z.string().optional().describe("Alternative to box: the filename of an already-uploaded screenshot asset to annotate."),prompt:n.z.string().optional().describe("What you want the human to look at or mark up (shown with the request)."),timeoutMs:n.z.number().optional().describe("How long to wait for the human, in ms (default ~10 min).")}),exports.AskUserVisualSchema=n.z.object({question:n.z.string().describe('The question for the USER about the marked region (e.g. "Should this button use the primary color?").'),imagePath:n.z.string().optional().describe("Repo-relative path to an image you already produced (png/jpg/gif/webp), e.g. a screenshot you wrote. Provide this OR previewName."),previewName:n.z.string().optional().describe("Name of a registered live preview (a `live:` ref); I freeze it into a snapshot image for you. Provide this OR imagePath."),box:n.z.string().optional().describe('The region the question is about: "x,y,w,h" in normalized 0..1 image coordinates, origin top-left (e.g. "0.62,0.08,0.3,0.12"). Omit to ask about the whole image.'),options:n.z.array(n.z.string()).optional().describe("Optional answer choices (labels). Omit for a free-text answer."),context:n.z.string().optional().describe("Extra context shown with the question in the inbox (why you are asking, what you will do with the answer)."),priority:n.z.enum(["low","normal","high"]).optional().describe('Question priority; "high" always reaches the user regardless of autonomy dial.')}),exports.EnvironmentGetSchema=n.z.object({environmentId:n.z.string().describe("Environment ID to retrieve")}),exports.EnvironmentProvisionSchema=n.z.object({environmentId:n.z.string(),why:n.z.string().optional().describe("Why provision now (shown on the approval).")}),exports.EnvironmentTeardownSchema=n.z.object({environmentId:n.z.string()}),exports.EnvironmentStatusSchema=n.z.object({environmentId:n.z.string()}),exports.EnvironmentVerifyStackSchema=n.z.object({environmentId:n.z.string()})
5607
+ exports.TestingProcessCreateSchema=n.z.object({name:n.z.string().min(1).describe("Name for the test process"),environmentId:n.z.string().optional().describe("ID of the environment (confined runtime) this process runs in. Get it from environment_list or environment_setup."),description:n.z.string().optional().describe("Description of what this process verifies"),scope:n.z.string().optional().describe('LABEL ONLY -- a monorepo path prefix recorded for display (e.g. "packages/api/"). It does NOT affect when the process runs; use pathGlobs for that.'),pathGlobs:n.z.array(n.z.string()).optional().describe('Which changes this process runs on: glob patterns matched against the changed files (e.g. ["sites/**"], ["src/**", "*.md"]). THIS is what limits when the process runs. Omit it and the process runs on EVERY change, which is the right choice only for a check that is cheap and universal.'),areas:n.z.array(n.z.string()).optional().describe('Work-area labels this process covers (e.g. ["graphics/opengl"]). An alternative to pathGlobs for work that is not file-shaped; a process applies if EITHER dimension matches.'),setup:n.z.array(n.z.string()).optional().describe("Commands that prepare the tree for the tests (install the package itself, generate files the tests import), e.g. [\"python -m pip install --no-deps -e .\"]. They run in its box before its commands on every run, and also before a request's criteria checks, which run in a clean checkout of the commit where `commands` do not run: a preparation step put in `commands` is missing there and those checks fail. If one fails, the run fails as the environment's fault and the commands do not run."),commands:n.z.array(g).min(1).describe("Test commands to execute in order"),verifyAcceptanceCriteria:n.z.boolean().optional().describe("When true, auto-tester verifies request acceptance criteria after running commands"),fingerprint:n.z.array(n.z.string()).optional().describe('Files whose content invalidates setup. Setup commands re-run only when these files change between runs (e.g. ["package-lock.json"], ["Cargo.lock"], ["uv.lock", "poetry.lock"]). Polyglot repos list multiple. Omit / empty list = always re-run setup (existing behavior).'),poolSize:n.z.number().int().min(1).max(8).optional().describe("Number of warm test worktrees in the pool. Default 2. Set to 1 for languages with very large build artifacts (Rust target/, C++ build/). Higher values allow more parallel test runs at the cost of disk."),runtimeKept:n.z.string().optional().describe('Only when the user chose to run the check on a runtime other than the lowest one the project declares: that runtime and version, e.g. "python 3.12". Without it, a check whose environment runs another version than the declared minimum is not registered.'),leavesOut:n.z.array(n.z.object({what:n.z.string().describe('The left-out part in plain words, e.g. "the Valkey backend tests"'),paths:n.z.array(n.z.string()).min(1).describe('Globs for the code that part checks, so a change there goes unchecked by this check: for a backend\'s tests, that backend (e.g. ["aiocache/backends/valkey.py"]); for browser or end-to-end tests, the app source they drive (e.g. ["src/**"]). Not only the left-out test files.'),command:n.z.string().min(1).max(300).optional().describe('The command that runs that part, e.g. "pnpm test:e2e": a request whose criterion runs it is not told this part was left out.')})).optional().describe('What this check deliberately does not run and no other check runs (the suites the card lists as "not run on every change"), each with the code it checks. A change to that code is reported to the user as not checked by this check, unless the request ran that part itself.')}),exports.TestingProcessDeleteSchema=n.z.object({processId:n.z.string().describe("Test process ID to delete")}),exports.EnvironmentListSchema=n.z.object({}),exports.ResultsSchema=n.z.object({operation:n.z.enum(["record","fetch","pin","list","read"]),path:n.z.string().optional().describe("record: the file, inside the project (not /tmp); your worktree first, then the main project. Bulk that must not reach a commit can be written by a command under `.alchemy_lab/scratch/` (gitignored)."),name:n.z.string().optional().describe("record: the name a person uses for it (defaults to the filename). list: show every version recorded under this name, newest first."),summary:n.z.record(n.z.any()).optional().describe('record (required): the small facts a reader wants instead of the bytes, e.g. {maxStress: 412, unit: "MPa", converged: true}.'),box:n.z.string().optional().describe("An experiment handle (exp_...). fetch: put the bytes inside that sealed box under its /scratch (a box cannot see the host scratch; omit for host work, which is faster). record: the result lives inside that box and is streamed out and stored in one step (a box cannot write your worktree)."),mediaType:n.z.string().optional().describe("record: MIME type, when you know it."),inputs:n.z.array(n.z.string()).optional().describe("record: addresses of the results this one was made from (provenance)."),note:n.z.string().optional().describe("record: one line on how it was produced."),address:n.z.string().optional().describe("pin / read / fetch: the full 64-character address the record returned (a unique prefix works too)."),at:n.z.string().optional().describe("pin: the pointer path in your worktree (.result.json is added). fetch: where the bytes land, under AlchemyLab's scratch folder for the project on the host (the answer gives the full path) or the box's `/scratch`. Defaults to results/<name>."),comment:n.z.string().optional().describe("pin: the commit comment for the pointer file."),offset:n.z.number().optional().describe("read: line to start at (default 0)."),limit:n.z.number().optional().describe("read: how many lines (default 200). list: how many results (default 25)."),find:n.z.string().optional().describe("read: return only lines containing this text, instead of a range.")}),exports.ResultInspectSchema=n.z.object({operation:n.z.enum(["list","read"]),name:n.z.string().optional().describe("list: show every version recorded under this name, newest first."),address:n.z.string().optional().describe("read: the full 64-character address of the result, a check run's id (tr_...) or a command run's record id (trec...), to read what its commands printed."),offset:n.z.number().optional().describe("read: line to start at (default 0)."),limit:n.z.number().optional().describe("read: how many lines (default 200). list: how many results (default 25)."),find:n.z.string().optional().describe("read: return only lines containing this text, instead of a range.")}),exports.ExperimentStartSchema=n.z.object({env:n.z.string().optional().describe("Environment by name (from environment_list), one whose image has the toolchain you need."),environmentId:n.z.string().optional().describe("Environment by id (alternative to `env`). The primary env is used if neither is given."),size:n.z.enum(["light","standard","heavy"]).optional().describe("light: 2 cores (lint, a typecheck, one test file). standard (default): a share of the free cores (a suite, a build). heavy: every free core but 2 and 6 GB of memory (2 GB otherwise, unless the environment sets its own), for work that uses them (a CFD solve, meshing, a large parallel build, a model that runs out of memory). A size you do not hold opens another box."),confirmWorkspace:n.z.boolean().optional().describe('Required for env "workspace" (the live host): the task genuinely needs the real machine. Building or trying out the app does not.')}),exports.ExperimentStopSchema=n.z.object({handle:n.z.string().describe("The experiment handle to tear down.")}),exports.ExperimentListSchema=n.z.object({}),exports.ReadSiteSchema=n.z.object({url:n.z.string()}),exports.DriveSiteSchema=n.z.object({url:n.z.string().describe("The running product, e.g. the environment's published URL or http://localhost:5173."),steps:n.z.array(n.z.object({action:n.z.enum(["click","clickat","type","press","move","scroll","wait","media"]).describe('click (selector) \xb7 clickat (x,y) \xb7 type (selector + text) \xb7 press (key) \xb7 move (x,y) \xb7 scroll (dy) \xb7 wait (ms, max 5000) \xb7 media ("print" shows the printout, "screen" switches back)'),selector:n.z.string().optional().describe('Playwright selector, e.g. "text=Build" or "#start".'),text:n.z.string().optional(),key:n.z.string().optional().describe('e.g. "Enter"'),x:n.z.number().optional(),y:n.z.number().optional(),dy:n.z.number().optional(),ms:n.z.number().optional(),media:n.z.enum(["print","screen"]).optional()})).min(1).max(20),shots:n.z.enum(["each","final"]).optional().describe('"each" screenshots every step; default the final state only.'),session:n.z.string().optional().describe("Keeps the page open: the next call with this name continues where this one stopped. Idle sessions close after 10 minutes."),close:n.z.boolean().optional().describe("Close the named session after this call."),width:n.z.number().optional().describe("Viewport width for a new session (default 1280; 390 is a phone).")}),exports.CaptureSiteSchema=n.z.object({url:n.z.string(),fullPage:n.z.boolean().optional().describe("The whole scrollable page instead of the viewport."),width:n.z.number().optional().describe("Viewport width (default 1280; 390 is a phone).")}),exports.PreviewSiteSchema=n.z.object({dir:n.z.string().optional().describe('Repo-relative, e.g. "dist" or "." for the top of the repository. Not needed with stop.'),requestId:n.z.string().regex(/^req\d{6}$/).optional().describe("Serve from this unmerged request's working copy instead of main."),name:n.z.string().optional().describe("Preview handle (default: a slug of dir); reusing one replaces that preview. With stop: the preview to stop."),stop:n.z.boolean().optional().describe("Stop a running preview instead of serving one: the one named, or the only one running."),label:n.z.string().optional()}),exports.FetchAssetSchema=n.z.object({url:n.z.string().describe("The http(s) URL of the image or font to download."),destPath:n.z.string().describe('Where to write it, repo-relative (e.g. "sites/acme/assets/hero.jpg"). Must stay inside the working tree; parent directories are created.')}),exports.RequestVisualFeedbackSchema=n.z.object({box:n.z.string().optional().describe("The experiment handle (from experiment_start, on a screenshot-capable env) to render in / read from. The box must stay held until this returns."),route:n.z.string().optional().describe('With `box`: the route I render + screenshot FOR YOU (e.g. "/" or "/settings"). I serve `serveDir` and screenshot it -- you do NOT hand-roll serve/screenshot. This is the easiest path.'),script:n.z.string().optional().describe('With `box`, for FULL control: a Playwright snippet (the body of `async (page, baseUrl) => { ... }`). I serve the app, launch headless Chromium, and run your script -- navigate (page.goto(baseUrl + "/x")), click, fill, scroll, waitForSelector, etc. -- then screenshot the final page state. Reliable: you write only the interaction, no serve/launch/flags. Use this to reach a state that needs interaction (open a menu, log in, submit a form).'),fullPage:n.z.boolean().optional().describe("Capture the entire scrollable page instead of just the viewport."),serveDir:n.z.string().optional().describe("With `box`+`route`: the static dir to serve (default /work). For a built app, build first via run(), then point this at the build output (e.g. /work/dist)."),path:n.z.string().optional().describe("Alternative to route: a screenshot you ALREADY wrote inside the box (e.g. /tmp/shot.png); I read it out."),assetFilename:n.z.string().optional().describe("Alternative to box: the filename of an already-uploaded screenshot asset to annotate."),prompt:n.z.string().optional().describe("What you want the human to look at or mark up (shown with the request)."),timeoutMs:n.z.number().optional().describe("How long to wait for the human, in ms (default ~10 min).")}),exports.AskUserVisualSchema=n.z.object({question:n.z.string().describe('The question for the USER about the marked region (e.g. "Should this button use the primary color?").'),imagePath:n.z.string().optional().describe("Repo-relative path to an image you already produced (png/jpg/gif/webp), e.g. a screenshot you wrote. Provide this OR previewName."),previewName:n.z.string().optional().describe("Name of a registered live preview (a `live:` ref); I freeze it into a snapshot image for you. Provide this OR imagePath."),box:n.z.string().optional().describe('The region the question is about: "x,y,w,h" in normalized 0..1 image coordinates, origin top-left (e.g. "0.62,0.08,0.3,0.12"). Omit to ask about the whole image.'),options:n.z.array(n.z.string()).optional().describe("Optional answer choices (labels). Omit for a free-text answer."),context:n.z.string().optional().describe("Extra context shown with the question in the inbox (why you are asking, what you will do with the answer)."),priority:n.z.enum(["low","normal","high"]).optional().describe('Question priority; "high" always reaches the user regardless of autonomy dial.')}),exports.EnvironmentGetSchema=n.z.object({environmentId:n.z.string().describe("Environment ID to retrieve")}),exports.EnvironmentProvisionSchema=n.z.object({environmentId:n.z.string(),why:n.z.string().optional().describe("Why provision now (shown on the approval).")}),exports.EnvironmentTeardownSchema=n.z.object({environmentId:n.z.string()}),exports.EnvironmentStatusSchema=n.z.object({environmentId:n.z.string()}),exports.EnvironmentVerifyStackSchema=n.z.object({environmentId:n.z.string()})
5601
5608
  const y=n.z.object({image:n.z.string().optional().describe("Container image carrying the project toolchain/deps, e.g. node:20-alpine, python:3.12-slim, golang:1.22, ruby:3.3"),install:n.z.string().optional().describe("Deps install command -- Node-only sugar that populates a /work/node_modules cache volume, run with registry egress before the confined gate, e.g. npm ci. Non-Node runtimes use `artifacts` instead (a cache volume + prepare command: .venv/uv sync, cargo, go, vendor/bundle). Omit if the project has no deps."),composeFile:n.z.string().optional().describe("Path to the project docker-compose file for its services. Omit if no services."),shellInit:n.z.string().optional().describe("Shell preamble run before EVERY command in the box, e.g. '. /usr/lib/openfoam/openfoam2312/etc/bashrc'. REQUIRED for a toolchain that publishes itself through a script rather than the image PATH (OpenFOAM etc/bashrc, oneAPI setvars.sh, conda activate, ROS setup.bash): `docker exec` runs no ENTRYPOINT and reads no login profile, so without this every command gets a bare PATH. Put the preamble HERE, never inside the smoke command -- a smoke command carrying its own preamble proves the preamble and not the environment, and the next agent gets nothing."),connEnv:n.z.record(n.z.string()).optional().describe("Connection env injected into the gate (e.g. DATABASE_URL) using SERVICE NAMES + internal ports, never localhost/host ports."),seed:n.z.array(n.z.string()).optional().describe("Optional commands run after services are up (e.g. migrations)."),artifacts:n.z.array(n.z.object({path:n.z.string().describe("Mount target for the writable, populated volume: relative to /work for a dependency folder the project's toolchain looks for there (node_modules, .venv, vendor/bundle), or absolute (e.g. /cache/cargo). Tools you install (apt/apk packages, binaries) go at an absolute path outside /work, such as /tools: /work is the project's folder, and its test runners see anything in it."),prepare:n.z.string().optional().describe("Command that populates it -- the one phase with registry egress (e.g. npm ci, uv sync, cargo fetch). Omit for a writable empty volume."),manifests:n.z.array(n.z.string()).optional().describe("Lockfiles (relative to /work) whose content hash keys the cache; list them so the volume is reused across runs and only rebuilt when deps change (e.g. uv.lock, Cargo.lock). Omit => rebuilt every run."),env:n.z.record(n.z.string()).optional().describe('Env applied during prepare AND every run, e.g. { CARGO_HOME: "/cache/cargo" } for caches outside /work.')})).optional().describe("Per-runtime build/dependency artifacts: writable volumes populated by a prepare command, generalizing `install` beyond node_modules. Use for Python (.venv), Rust (target + $CARGO_HOME), Go, Ruby (vendor/bundle), etc. `install` is sugar for a single node_modules artifact; for any non-Node runtime use artifacts (install would write to node_modules, the wrong place)."),confinement:n.z.enum(["confined","egress-allowlist","privileged","unsafe","host","pure-host"]).optional().describe("Confinement level. Default 'confined' (fully sealed Docker; add egressAllowlist hosts to open exactly those -- stored as 'egress-allowlist'). privileged/unsafe relax the container. 'host' runs on the host machine (no Docker) inside an OS sandbox (Seatbelt/bubblewrap) for toolchains Docker can't run. 'pure-host' is the built-in workspace env (the live worktree) -- do not create new envs with it. Merge gating is independent (the Sign-off setting)."),commandGate:n.z.array(n.z.enum(["policy","agent","human"])).optional().describe("Gates an experiment command passes before it runs, in escalation order policy -> agent -> human. Empty = run freely; escalating past the last gate blocks (fail closed). policy = deterministic allowlist/deny-floor; agent = isolated LLM judge (allow or escalate only); human = ask. Registered commands are pre-approved. Defaults by level ([] for confined/egress-allowlist, ['human'] for privileged/unsafe)."),worktreeTarget:n.z.enum(["ephemeral","live"]).optional().describe("Worktree the env runs against: 'ephemeral' (a disposable copy at HEAD, default) or 'live' (the project's live working dir, read-write). The built-in workspace env is 'live'."),egressAllowlist:n.z.array(n.z.string()).optional().describe("Hosts the box may reach at the 'egress-allowlist' level (exact name or subdomain, e.g. registry.npmjs.org). Ignored at other levels."),addCaps:n.z.array(n.z.string()).optional().describe("Linux capabilities to add at the 'privileged' level (on top of cap-drop ALL), e.g. SYS_PTRACE for debuggers, IPC_LOCK for memlock. Ignored at other levels."),sysctls:n.z.record(n.z.string()).optional().describe("Namespaced sysctls to set at the 'privileged' level, e.g. net.ipv4.ip_local_port_range. Host-wide sysctls (vm.max_map_count) are NOT settable per-container."),runAsRoot:n.z.boolean().optional().describe("Run the box as root (privileged / unsafe levels). Needed for some caps + the docker socket."),dockerSocket:n.z.boolean().optional().describe("Mount the host docker socket for testcontainers-style tests. WARNING: full host control over the docker daemon. Only honored at the 'unsafe' level."),persistentVolumes:n.z.array(n.z.object({name:n.z.string(),target:n.z.string(),service:n.z.string().optional()})).optional().describe("Data volumes that survive between runs (keyed to this environment; off by default since experiments are ephemeral). Set service to mount into a compose service (e.g. a DB data dir), or omit it to mount into the box (e.g. a SQLite dir)."),resources:n.z.object({memory:n.z.string().optional().describe("Memory cap for this environment's boxes and its checks' boxes, e.g. '4g' (default 2g; 6g at size heavy). Set it when the test suite or build needs more."),cpus:n.z.number().optional().describe("A fixed CPU count. Usually leave it unset and set size instead."),size:n.z.enum(["light","standard","heavy"]).optional().describe("What this environment's boxes and checks are for, which sets their cores from what is free: light (2 cores: lint, small checks), standard (the default: a share of the free cores, for test suites and builds), heavy (every free core but 2: CFD or FEM solves, meshing, large parallel builds). An agent can ask for another size per box."),pidsLimit:n.z.number().optional().describe("Max processes (default 512)."),scratchMb:n.z.number().optional().describe("Size in MB of an in-memory /scratch, used only when the image cannot take the disk-backed one (default 512). /scratch is normally on disk and needs no size."),shmMb:n.z.number().optional().describe("/dev/shm size in MB -- bump for headless browsers (Chrome crashes on the 64m default).")}).optional().describe("Per-environment resource caps that override the confined defaults.")}),w=r(y),b='Start from a built-in preset; anything in config overrides it. "office": python-docx, openpyxl, python-pptx, pandoc, LibreOffice and segno/zbarimg (QR codes) in a sealed box, with `render-pdf FILE` to turn Word, Excel, PowerPoint, Markdown or HTML into PDF. Its image is built locally on first use (a few minutes). Pass the same preset (and config) to environment_verify and environment_create.',v="Save without a passing environment_verify, only for a config that cannot be verified from here (it needs credentials, external services or hardware the confined verifier lacks). Requires skipVerifyReason; the skip is logged."
5602
5609
  exports.EnvironmentCreateSchema=n.z.object({name:n.z.string().min(1).describe("Name for the environment, e.g. node + postgres"),description:n.z.string().optional().describe("What this environment provides"),scope:n.z.string().optional().describe("Subproject path prefix for monorepos (e.g. packages/api/). Omit for the whole repo."),preset:n.z.enum(["office"]).optional().describe(b),config:w.optional().describe("The exact config (after the preset) that passed environment_verify in this session, unless skipVerify; its fields are described on environment_verify. Optional with a preset."),isPrimary:n.z.boolean().optional().describe("Make this the project primary environment (default for new test processes). The first environment is primary automatically."),skipVerify:n.z.boolean().optional().describe(v),skipVerifyReason:n.z.string().optional().describe("Why this config cannot be verified (required with skipVerify: true; recorded in the log).")}),exports.EnvironmentUpdateSchema=n.z.object({environmentId:n.z.string(),name:n.z.string().min(1).optional(),description:n.z.string().optional(),scope:n.z.string().optional(),config:w.optional().describe("Replaces the config wholesale: the exact config that passed environment_verify in this session, unless skipVerify (fields described on environment_verify). Metadata-only updates need no verify."),isPrimary:n.z.boolean().optional().describe("Make this the project primary environment"),skipVerify:n.z.boolean().optional().describe(v),skipVerifyReason:n.z.string().optional().describe("Why this config cannot be verified (required with skipVerify: true; recorded in the log).")}),exports.EnvironmentDeleteSchema=n.z.object({environmentId:n.z.string().describe("Environment ID to delete")}),exports.EnvironmentVerifySchema=n.z.object({preset:n.z.enum(["office"]).optional().describe(b),config:y.optional().describe("The proposed environment config to verify (image, install, services, connection). Optional with a preset."),smoke:n.z.string().optional().describe("Optional smoke command run confined after the environment is up (default: true). Use a connection probe to confirm services are reachable.")}),exports.EnvironmentSetupSchema=n.z.object({name:n.z.string().max(60).optional().describe("A few words naming what you need (e.g. 'Node 20 for syntax checks')."),context:n.z.string().optional().describe("What you need and why, for the setup architect (e.g. 'Node 20 to run node --check on standalone .js files; no deps').")}),exports.SetupFinishSchema=n.z.object({outcome:n.z.enum(["ready","declined","could_not_finish","no_code","not_yet"]).describe("How the run ended. 'ready' needs something saved in this run."),summary:n.z.string().min(1).describe("What was set up (names and ids), and an answer to every ask the run carries: done, or not done and why. Plain words; it reaches the waiting workers and the user."),startsAfter:n.z.string().regex(/^req\d{6}$/).optional().describe("With 'not_yet': the request still writing what this setup registers.")}),exports.TestingProcessUpdateSchema=n.z.object({processId:n.z.string(),environmentId:n.z.string().optional(),name:n.z.string().min(1).optional(),description:n.z.string().optional(),scope:n.z.string().optional().describe("A display label only; pathGlobs decides when the process runs."),pathGlobs:n.z.array(n.z.string()).optional().describe('Globs matched against changed files (e.g. ["src/**", "*.md"]): the changes this process runs on. Replaces the list; [] means every change.'),areas:n.z.array(n.z.string()).optional().describe("Work-area labels this process covers; it applies when pathGlobs or areas match."),isActive:n.z.boolean().optional(),setup:n.z.array(n.z.string()).optional().describe("Replaces the setup commands (run in the check's box before its commands, and before the criteria checks in their clean checkout)."),commands:n.z.array(g).optional().describe("Replaces the test commands."),verifyAcceptanceCriteria:n.z.boolean().optional().describe("The auto-tester also verifies the request's acceptance criteria."),fingerprint:n.z.array(n.z.string()).optional().describe("Files whose content invalidates setup."),leavesOut:n.z.array(n.z.object({what:n.z.string().describe('The left-out part in plain words, e.g. "the Valkey backend tests"'),paths:n.z.array(n.z.string()).min(1).describe("Globs for the code that part checks (for end-to-end tests, the app source they drive), not only its test files."),command:n.z.string().min(1).max(300).optional().describe('The command that runs that part, e.g. "pnpm test:e2e".')})).optional().describe("Replaces what this check deliberately does not run, with the code each part checks; [] clears it."),poolSize:n.z.number().int().min(1).max(8).optional().describe("Warm test worktrees in the pool."),runtimeKept:n.z.string().optional().describe('With environmentId: only when the user chose a runtime other than the lowest one the project declares, e.g. "python 3.12".')}),exports.TestsSchema=n.z.object({operation:n.z.enum(["list","setup","run","switch-off","switch-on"]),process:n.z.string().optional().describe("run, switch-off, switch-on: one test process by name or id (run: omit for all active ones)."),userSaid:n.z.string().max(600).optional().describe("switch-off / switch-on: the user's words asking for it, copied exactly."),name:n.z.string().optional().describe("run: one test command by name; omit for all required commands."),ask:n.z.string().max(1500).optional().describe("setup, required outside a request: what the user asked the check to run, in their words; the setup architect registers exactly that.")}),exports.ExecuteTestCommandSchema=n.z.object({processId:n.z.string().describe("Test process ID containing the command"),commandName:n.z.string().describe('Name of the test command to run, or "setup" to run all setup commands in sequence')}),exports.RunSchema=n.z.object({command:n.z.string().optional().describe("A shell command, run in the box (pass box or env)."),name:n.z.string().optional().describe("A saved command by name, instead of command."),box:n.z.string().optional().describe("An experiment handle from experiment_start."),env:n.z.string().optional().describe("Instead of box: an environment by name; its box is started (or your open one reused) and the result gives the handle."),size:n.z.enum(["light","standard","heavy"]).optional().describe("With env: the box size (see experiment_start)."),args:n.z.string().optional(),grep:n.z.string().optional().describe("Filter output through grep -i with this pattern."),timeout:n.z.number().optional().describe("Seconds."),why:n.z.string().optional().describe("One short sentence, shown on the approval card when the command needs the user's approval."),cwd:n.z.string().optional().describe('A subdirectory for an ad-hoc command (e.g. "apps/web"); a command starting with `cd` is refused in favour of this.')}),exports.CommandsSchema=n.z.object({operation:n.z.enum(["run","list","remove","register","setup"]).default("run").describe('list, setup, register or remove ("run" is the run tool\'s job).'),name:n.z.string().optional().describe("remove: the command name."),args:n.z.string().optional(),grep:n.z.string().optional(),command:n.z.string().optional(),timeout:n.z.number().optional(),cwd:n.z.string().optional(),context:n.z.string().optional().describe("setup: the command wanted, where it runs and what it is for."),commands:n.z.array(n.z.object({name:n.z.string().min(1).describe('e.g. "test:web"'),command:n.z.string().min(1),description:n.z.string().min(1).describe("What this command verifies."),cwd:n.z.string().optional().describe("Relative to the project root (monorepo subdirs); omit for the root."),timeout:n.z.number().optional().describe("Seconds (default 60)."),environment:n.z.string().optional().describe('The environment it runs in, by name (environment_list). Omitted, it goes where you ran it (a bare box with no saved environment is refused, so name one). Name "Workspace" only when it truly needs the host.'),target:n.z.string().optional().describe("The id your setup instructions give for a target this command prints the number for.")})).optional().describe("register: the commands to register.")}),exports.ReportTestResultsSchema=n.z.object({status:n.z.enum(["passed","failed","error"]).describe("Overall result"),testRunId:n.z.string().optional().describe("The test run this verdict belongs to (given in your instructions). Strongly preferred: without it the latest run is guessed, which misattributes results when several testers run concurrently."),results:n.z.object({commands:n.z.array(n.z.object({name:n.z.string().describe("Command name"),status:n.z.enum(["passed","failed","skipped","error"]).describe("Command result"),output:n.z.string().optional().describe("Relevant output snippet"),diagnosis:n.z.string().optional().describe("Why it failed, if applicable")})).describe("Per-command results"),summary:n.z.string().describe("Brief overall summary"),acceptanceCriteria:n.z.array(n.z.object({criterion:n.z.string().describe("The acceptance criterion text"),status:n.z.enum(["verified","unverified","unclear"]),evidence:n.z.string().describe("How verified, or why not")})).optional().describe("AC verification results, if applicable"),faultClass:n.z.enum(["fail_code","fail_evidence","fail_environment","fail_process"]).optional().describe("On a FAILED verdict, WHY it failed so the gate routes to the right actor: 'fail_code' (the change is wrong), 'fail_evidence' (the run did not prove a criterion the coder could have proven: attach/adjust verify commands), or 'fail_environment' (a required tool/runtime is MISSING from the confined box, e.g. 'node: not found': the coder cannot fix this; the environment must be extended). Use 'fail_environment' ONLY when the evidence shows a command/runtime absent from the box, never for a genuine defect or a fixable evidence gap. 'fail_process' is for a test process whose OWN command names a file the repository does not have (a deleted script): nobody's code is wrong and extending the box cannot help; the process itself must be fixed or turned off."),missingCapabilities:n.z.array(n.z.string()).optional().describe("With faultClass 'fail_environment', the binaries/runtimes the box lacks (e.g. ['node']) so the environment can be extended to provide them.")}).describe("Structured test results")}).superRefine((e,t)=>{"fail_environment"!==e.results?.faultClass||e.results.missingCapabilities&&e.results.missingCapabilities.length>0||t.addIssue({code:n.z.ZodIssueCode.custom,path:["results","missingCapabilities"],message:"faultClass 'fail_environment' requires results.missingCapabilities: name the absent binaries/runtimes (the deterministic capability probe in your evidence lists them, e.g. ABSENT from the box: node). Without the names, the environment cannot be extended and the request strands."})})
5603
5610
  const k=n.z.string().min(1,"every option needs its consequence (description)").max(200,"an option's description is its consequence in one line: 200 characters at most").describe("Its consequence in one line: what it gets and costs."),I=n.z.string().min(1).max(120,"because is one clause: 120 characters at most")
@@ -6072,7 +6079,7 @@ return(0,s.safeGetResponseData)(o,null)}catch(t){throw this.logger.error("Error
6072
6079
  if("string"==typeof e||null==e)return{id:`temp_${Date.now()}_${t}`,description:e??r}
6073
6080
  const{status:n,evidence:o,evidenceType:s,verified:i,...a}=e
6074
6081
  return{...a,id:e.id||`temp_${Date.now()}_${t}`,description:e.description||e.text||r,createdAt:e.createdAt,updatedAt:e.updatedAt}})}Object.defineProperty(exports,"__esModule",{value:!0}),exports.RequestClient=void 0,exports.toApiCriteria=r
6075
- const n=t(37645),o=t(10293),s=t(12161),i=t(58824),a=t(87780),c=["status","type","planDocumentId","scheduleDocumentId","hasPlanDocumentId","hasScheduleDocumentId","dateFrom","dateTo","updatedAfter","updatedBefore","title","mentions","inFlight","activeFirst","includeDrafts","limit","offset","sortBy","sortDirection"]
6082
+ const n=t(37645),o=t(10293),s=t(12161),i=t(58824),a=t(87780),c=["status","type","planDocumentId","scheduleDocumentId","hasPlanDocumentId","hasScheduleDocumentId","dateFrom","dateTo","updatedAfter","updatedBefore","title","mentions","inFlight","activeFirst","includeDrafts","asRequests","limit","offset","sortBy","sortDirection"]
6076
6083
  class l extends n.ConnectionAwareClient{constructor(e,t,r,n,o,s,i){const a=s||{isInOfflineMode:()=>!1,isOffline:()=>!1,setOfflineMode:()=>{},checkConnectivity:async()=>!0,getHealthCheckStats:()=>({isOffline:!1,consecutiveFailures:0,currentBackoffMs:0,lastCheckTime:0}),cleanup:()=>{}}
6077
6084
  super(e,t.child({component:"request-client"}),r,o,i),this.setConnectionStatusManager(a),this.projectClient=n}async createRequest(e){const t="string"==typeof e.roundOf&&!!e.roundOf
6078
6085
  if(!e.title&&!t)throw new Error("Request title is required")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemylab",
3
- "version": "3.0.2",
3
+ "version": "3.0.4",
4
4
  "private": false,
5
5
  "description": "AlchemyLab: the agentic workbench. Work is a request, with criteria, gates and a receipt.",
6
6
  "author": "Testfire Software",