alchemylab 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{674.js → 111.js} +2 -2
- package/dist/{19.js → 24.js} +110 -135
- package/dist/{540.js → 293.js} +3 -3
- package/dist/{491.js → 356.js} +1 -1
- package/dist/414.js +18 -0
- package/dist/478.js +89 -0
- package/dist/{636.js → 579.js} +2 -2
- package/dist/{565.js → 60.js} +2 -2
- package/dist/729.js +46 -88
- package/dist/{129.js → 776.js} +2 -2
- package/dist/{237.js → 800.js} +2 -2
- package/dist/{403.js → 816.js} +1 -1
- package/dist/{380.js → 939.js} +2 -2
- package/dist/{554.js → 991.js} +3 -3
- package/dist/{301.js → 994.js} +2 -2
- package/dist/cli.js +7651 -6337
- package/dist/document-textconv.js +357 -254
- package/dist/http-server.js +7690 -7201
- package/dist/index.js +7793 -7303
- package/dist/mcp-direct.js +7377 -6887
- package/dist/plugins/hooks/plugin.js +1 -1
- package/package.json +5 -2
- package/dist/796.js +0 -47
package/dist/{674.js → 111.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.id=
|
|
2
|
+
exports.id=111,exports.ids=[111],exports.modules={56111:(e,exports,t)=>{async function o(e,t){if(t){if(!n||Date.now()-n.at>i)try{const t=await e.apiClient.get(`/api/projects/${e.projectId}/session-request-associations?activeOnly=true&limit=500`),o=t?.data??t??[],r=new Map
|
|
3
3
|
for(const e of o)e?.opencodeSessionId&&e?.requestLocalId&&r.set(e.opencodeSessionId,e.requestLocalId)
|
|
4
4
|
n={at:Date.now(),bySession:r}}catch(t){e.logger.debug?.("MCP receipt: could not read associations",{error:(0,r.getErrorMessage)(t)}),n=n??{at:Date.now(),bySession:new Map}}return n.bySession.get(t)}}exports.requestForSession=o,exports.openMcpReceipt=async function(e,t){const n=await o(e,t.sessionId??""),i=t.target?` (${t.target})`:"",c=`${t.tool} on the "${t.connection}" MCP server${i}`,d=t.allowed?`Called ${c}`:`Did not run ${c}: ${t.reason}`,l={connection:t.connection,tool:t.tool,target:t.target??null,gate:t.verdict,status:t.allowed?"started":"refused",sessionId:t.sessionId??null,callId:t.callId??null,startedAt:(new Date).toISOString()}
|
|
5
5
|
try{const o=await e.apiClient.post(`/api/projects/${e.projectId}/tool-records`,{...n?{requestId:n}:{},type:"mcp-call",...t.sessionId?{cliOrigin:{providerId:"opencode",sessionId:t.sessionId,createdAt:(new Date).toISOString()}}:{},metadata:l,note:d}),r=o?.data?.id??o?.id
|
|
@@ -10,6 +10,6 @@ s.delete(t)}}())}catch(o){e.logger.error("MCP receipt could not be written",{con
|
|
|
10
10
|
let o=s.get(t.callId)
|
|
11
11
|
if(o||(await new Promise((e=>setTimeout(e,250))),o=s.get(t.callId)),o){s.delete(t.callId)
|
|
12
12
|
try{await e.apiClient.patch(`/api/projects/${e.projectId}/tool-records/${o.recordId}`,{metadata:{...o.metadata,status:t.ok?"completed":"failed",durationMs:Date.now()-o.startedAt,finishedAt:(new Date).toISOString(),...t.outputPreview?{outputPreview:t.outputPreview.slice(0,500)}:{},...t.error?{error:String(t.error).slice(0,500)}:{}}})}catch(o){e.logger.warn("MCP receipt could not be closed",{callId:t.callId,error:(0,r.getErrorMessage)(o)})}}}
|
|
13
|
-
const r=t(
|
|
13
|
+
const r=t(58824),s=new Map,a=500
|
|
14
14
|
let n=null
|
|
15
15
|
const i=3e4}}
|
package/dist/{19.js → 24.js}
RENAMED
|
@@ -1,79 +1,79 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.id=
|
|
2
|
+
exports.id=24,exports.ids=[24],exports.modules={51725:(e,exports,t)=>{function n(e,t,n){if(q)try{const s=`[${(new Date).toISOString()}] ${t}${n?" "+JSON.stringify(n):""}\n`,o=(0,v.join)(e.basePath||process.cwd(),".alchemy_lab","spawn-debug.log");(0,x.appendFileSync)(o,s)}catch{}}async function s(e,n,s,o,i,r){if(!(e&&n&&s&&o))return null
|
|
3
3
|
try{const i=await e.proxyPost(`/api/projects/${n}/requests/${s}/pickup-compose`,{sessionId:o}),a=i?.data?.text??i?.text,l="string"==typeof a&&a.trim()?a.trim():null
|
|
4
4
|
if(l&&/Project map/.test(l))return l
|
|
5
5
|
let c=null
|
|
6
|
-
try{const{generateProjectMap:e}=await t.e(
|
|
7
|
-
c=e(r||process.cwd())}catch{c=null}return l||c?[l,c].filter(Boolean).join("\n\n"):null}catch(e){return i.warn("pickup-compose failed; the association hook will deliver guidance as an inject",{requestId:s,error:(0,
|
|
6
|
+
try{const{generateProjectMap:e}=await t.e(356).then(t.t.bind(t,69356,23))
|
|
7
|
+
c=e(r||process.cwd())}catch{c=null}return l||c?[l,c].filter(Boolean).join("\n\n"):null}catch(e){return i.warn("pickup-compose failed; the association hook will deliver guidance as an inject",{requestId:s,error:(0,b.getErrorMessage)(e)}),null}}async function o(e){const{apiClient:t,fromSessionId:n,toSessionId:s,body:o,requestId:i,logger:r}=e
|
|
8
8
|
if(!t||!n)return
|
|
9
9
|
const a=t.getSessionMessageClient()
|
|
10
10
|
if(a)try{const e=await a.createInstruction({fromSessionId:n,toSessionId:s,body:o,...i?{requestId:i}:{}})
|
|
11
|
-
return e?.messageCode}catch(e){return void r.warn("Failed to mint instruction code",{error:(0,
|
|
12
|
-
if(n(t,"handleSpawn called",{agent:c,promptLength:d.length,requestId:u,useExistingSession:
|
|
13
|
-
const f=l?.sessionId,h=f?
|
|
11
|
+
return e?.messageCode}catch(e){return void r.warn("Failed to mint instruction code",{error:(0,b.getErrorMessage)(e),fromSessionId:n,toSessionId:s})}}async function i(e,t,n,s,o){if(e&&t&&n)try{await e.proxyPost(`/api/projects/${t}/session-messages/${encodeURIComponent(n)}/delivered`,{ok:s.ok,error:s.detail||s.error,messageId:s.messageId})}catch(e){o.warn("instruction delivery receipt not written",{instructionCode:n,error:(0,b.getErrorMessage)(e)})}}async function r(e,t,r,a,l){const{agent:c="work",prompt:d,requestId:u,allowParallel:g=!1,useExistingSession:p}=e
|
|
12
|
+
if(n(t,"handleSpawn called",{agent:c,promptLength:d.length,requestId:u,useExistingSession:p,cliOriginSessionId:l?.sessionId||null}),!(0,A.isValidAgent)(c))return{content:[{type:"text",text:`\u274c Unknown agent '${c}'.\n\n**Available agents:** ${(0,A.getAgentNames)().join(", ")}\n\nChoose one of the available agents listed above to see detailed descriptions of each agent.`}],isError:!0}
|
|
13
|
+
const f=l?.sessionId,h=f?S.sessionIdentity.getAgentTypeFor(f).then((e=>e||void 0)):Promise.resolve(void 0),m=async function(e){try{const t=`http://localhost:${T}/api/agents/by-name/${encodeURIComponent(e)}`,n=await fetch(t,{signal:AbortSignal.timeout(8e3)})
|
|
14
14
|
if(!n.ok)return null
|
|
15
15
|
const s=await n.json()
|
|
16
|
-
return s.success?s.data??null:null}catch{return null}}(c).catch((()=>null)),
|
|
16
|
+
return s.success?s.data??null:null}catch{return null}}(c).catch((()=>null)),x=(0,y.getServerUrl)(t,r),v=(async()=>{if(!a||!u)return null
|
|
17
17
|
const e=a.getSessionRequestAssociationClient()
|
|
18
|
-
return e?await e.getSessionsForRequest(u,!0):null})().catch((e=>(r.debug("Failed to check for existing workers",{error:(0,
|
|
19
|
-
try{if(n(t,"Spawn agent type check",{callerSessionId:f||null,callerAgentType:
|
|
20
|
-
if(e&&!e.includes(c))return{content:[{type:"text",text:`\u274c Agent type '${
|
|
21
|
-
if(!
|
|
22
|
-
|
|
23
|
-
if(u&&"required"===
|
|
18
|
+
return e?await e.getSessionsForRequest(u,!0):null})().catch((e=>(r.debug("Failed to check for existing workers",{error:(0,b.getErrorMessage)(e)}),null))),[E,j,P,R]=await Promise.all([h,m,x,v])
|
|
19
|
+
try{if(n(t,"Spawn agent type check",{callerSessionId:f||null,callerAgentType:E||null,pid:process.pid}),E){const e=(0,A.getAllowedSubagents)(E)
|
|
20
|
+
if(e&&!e.includes(c))return{content:[{type:"text",text:`\u274c Agent type '${E}' cannot spawn '${c}'.\n\n**Allowed subagents for ${E}:** ${e.join(", ")}\n\nUse one of the allowed agent types instead.`}],isError:!0}}}catch(e){n(t,"allowedSubagents check failed",{error:(0,b.getErrorMessage)(e)})}let M=j?.requestContextMode
|
|
21
|
+
if(!M){const e=(0,A.getBuiltInAgentConfig)(c)
|
|
22
|
+
M=e?.requestContextMode}if(M&&"none"!==M&&!u)return{content:[{type:"text",text:`\u274c Agent '${c}' requires a requestId to be provided.\n\nThis agent has requestContextMode: '${M}' which means it needs to work in the context of a specific request.\n\nPlease provide a requestId when spawning this agent.`}],isError:!0}
|
|
23
|
+
if(u&&"required"===M&&a)try{const e=await a.getRequestClient().getRequest(u)
|
|
24
24
|
if("draft"===e?.status){const t=e?.intake,n="rejected"===t?.status?`the intake reviewer rejected it: ${String(t?.objection||"").slice(0,240)||"(no objection text)"}`:"pending"===t?.status?"it is held at intake awaiting a verdict":"it has not been registered"
|
|
25
|
-
return{content:[{type:"text",text:`\u274c ${u} is a DRAFT: ${n}.\n\nWork cannot start on drafts. Wait for the request to be registered (the user resolves the intake question from the timeline), or address the objection with a revised proposal. Do NOT spawn workers for draft requests.`}],isError:!0}}}catch(e){n(t,"draft-spawn guard read failed (continuing)",{error:(0,
|
|
26
|
-
const
|
|
27
|
-
let
|
|
28
|
-
if(R){const e=(
|
|
25
|
+
return{content:[{type:"text",text:`\u274c ${u} is a DRAFT: ${n}.\n\nWork cannot start on drafts. Wait for the request to be registered (the user resolves the intake question from the timeline), or address the objection with a revised proposal. Do NOT spawn workers for draft requests.`}],isError:!0}}}catch(e){n(t,"draft-spawn guard read failed (continuing)",{error:(0,b.getErrorMessage)(e)})}if(n(t,"serverUrl resolved",{serverUrl:P}),!t.workspaceManager?.getCurrentContext(t.currentSessionId)?.basePath&&!t.basePath)throw new w.ValidationError("Working directory not available in context")
|
|
26
|
+
const U=l?.sessionId
|
|
27
|
+
let D=""
|
|
28
|
+
if(R){const e=(U?R.filter((e=>e.opencodeSessionId!==U)):R).filter((e=>!1!==e.working))
|
|
29
29
|
if(e.length>0){const t=e.map((e=>e.opencodeSessionId)).join(", ")
|
|
30
|
-
if(!
|
|
31
|
-
|
|
32
|
-
u&&(
|
|
33
|
-
let
|
|
34
|
-
if(
|
|
30
|
+
if(!g)return r.warn("Blocked spawn: request already has active workers",{requestId:u,existingWorkerCount:e.length,existingSessionIds:e.map((e=>e.opencodeSessionId))}),{content:[{type:"text",text:`\u274c Cannot spawn: Request ${u} already has ${e.length} active worker(s): ${t}\n\nOptions:\n\u2022 Use \`useExistingSession: "${e[0].opencodeSessionId}"\` to send work to the existing session\n\u2022 Use \`allowParallel: true\` if you really need multiple workers on the same request`}],isError:!0}
|
|
31
|
+
D=`\u26a0\ufe0f Warning: Request ${u} already has ${e.length} active worker(s): ${t}. Proceeding anyway (allowParallel=true).\n\n`,r.warn("Spawning parallel subagent for request with existing active workers",{requestId:u,existingWorkerCount:e.length,existingSessionIds:e.map((e=>e.opencodeSessionId)),allowParallel:!0})}}let L,O,F=d
|
|
32
|
+
u&&(L=`requests/${u}`,n(t,"Setting initialBranch for agent",{agent:c,requestId:u,initialBranch:L,agentRequestContextMode:M||"undefined"}),F="readonly"===M?`Working on request ${u} (READONLY mode - you cannot modify files, only explore and report).\n\n${d}`:`Working on request ${u}.\n\n${d}`)
|
|
33
|
+
let N,_=!1
|
|
34
|
+
if(p){if(O=p,r.info("Using existing session for spawn",{sessionId:O,requestId:u}),!P)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
35
35
|
try{let e
|
|
36
|
-
try{const t=await fetch(`http://localhost:${
|
|
36
|
+
try{const t=await fetch(`http://localhost:${T}/api/project-settings`,{signal:AbortSignal.timeout(8e3)})
|
|
37
37
|
if(t.ok){const n=await t.json()
|
|
38
38
|
if(n.data?.defaultModel){const[t,...s]=n.data.defaultModel.split("/")
|
|
39
|
-
e={providerID:t,modelID:s.join("/")}}}}catch{}
|
|
40
|
-
let n=
|
|
41
|
-
const d=await s(a,t.projectId,u,
|
|
39
|
+
e={providerID:t,modelID:s.join("/")}}}}catch{}N=await o({apiClient:a,fromSessionId:l?.sessionId,toSessionId:O,body:F,requestId:u,logger:r})
|
|
40
|
+
let n=F
|
|
41
|
+
const d=await s(a,t.projectId,u,O,r,t.mainBasePath||t.basePath)
|
|
42
42
|
d&&(n=`${d}\n\n---\n\n${n}`)
|
|
43
|
-
const
|
|
44
|
-
if(await i(a,t.projectId,
|
|
45
|
-
r.info("Prompt delivered to existing session",{sessionId:
|
|
46
|
-
const i=
|
|
47
|
-
|
|
48
|
-
try{const
|
|
43
|
+
const g={body:F,fromSessionId:l?.sessionId,fromAgent:E,...u?{requestId:u}:{},...N?{instructionCode:N}:{}},p=await(0,I.deliverToSession)(O,n,{kind:"agent-delegation",partPayload:g})
|
|
44
|
+
if(await i(a,t.projectId,N,p,r),!p.ok)throw new Error((0,I.deliveryFailureText)(O,p))
|
|
45
|
+
r.info("Prompt delivered to existing session",{sessionId:O,agent:c,messageId:p.messageId})}catch(e){throw new Error(`Failed to use existing session: ${(0,b.getErrorMessage)(e)}`)}}else{_=!0,n(t,"Creating session via spawn-session endpoint")
|
|
46
|
+
const i=U
|
|
47
|
+
q&&(0,k.logSessionIdentity)("subagent_operations.spawn","_meta",{parentSessionId:i})
|
|
48
|
+
try{const p=`http://localhost:${T}/api/spawn-session`,f=await fetch(p,{method:"POST",signal:AbortSignal.timeout(15e3),headers:{"Content-Type":"application/json"},body:JSON.stringify({agent:c,prompt:d,requestId:u,parentSessionId:i,title:e.title,allowParallel:g,callerAgentType:E})})
|
|
49
49
|
if(!f.ok){const e=await f.text().catch((()=>"Unknown error"))
|
|
50
50
|
throw new Error(`Spawn session endpoint failed: ${f.status} ${e}`)}const h=await f.json()
|
|
51
51
|
if(!h.success||!h.data)throw new Error(h.error||"Spawn session returned unsuccessful")
|
|
52
|
-
const{sessionId:m,model:w,serverUrl
|
|
53
|
-
|
|
54
|
-
let
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
const
|
|
58
|
-
if(!
|
|
59
|
-
|
|
60
|
-
B+=
|
|
61
|
-
const
|
|
62
|
-
return{content:[{type:"text",text:B}],...(0,C.alchemyMeta)({kind:"spawn-subagent",spawnedSessionId:
|
|
52
|
+
const{sessionId:m,model:w,serverUrl:y,initialBranch:I}=h.data
|
|
53
|
+
L=I,N=await o({apiClient:a,fromSessionId:l?.sessionId,toSessionId:m,body:F,requestId:u,logger:r})
|
|
54
|
+
let S=F
|
|
55
|
+
const k="pickupGuidance"in(h?.data??{})?h.data.pickupGuidance??null:await s(a,t.projectId,u,m,r,t.mainBasePath||t.basePath)
|
|
56
|
+
k&&(S=`${k}\n\n---\n\n${S}`)
|
|
57
|
+
const b=await(0,$.deliverInitialPrompt)({serverUrl:y,sessionId:m,agent:c,prompt:S,model:w,directory:t.mainBasePath,metadata:{alchemy:{kind:"agent-delegation",payload:{body:F,fromSessionId:l?.sessionId,fromAgent:E,...u?{requestId:u}:{},...N?{instructionCode:N}:{}}}}})
|
|
58
|
+
if(!b.success)throw new Error(`Failed to spawn subagent: ${b.error}`)
|
|
59
|
+
O=m,n(t,"Spawn successful via unified endpoint",{sessionId:m,parentSessionId:i,model:w,instructionCode:N}),r.info("Background subagent spawned via unified endpoint",{agent:c,requestId:u,sessionId:m,parentSessionId:i,instructionCode:N})}catch(e){throw new Error(`Failed to spawn subagent: ${(0,b.getErrorMessage)(e)}`)}}let B=D
|
|
60
|
+
B+=p?`Prompt sent to existing session ${O}.`:`Background ${c} subagent spawned successfully.`,u&&(B+=`\nWorking on: ${u}`),N&&(B+=`\nInstruction code: ${N} (the agent will cite this on its reports/questions via relatesTo)`),B+="\n\nThe subagent is now working independently. You can continue with other tasks."
|
|
61
|
+
const W=!!O&&"unknown"!==O&&"spawning"!==O
|
|
62
|
+
return{content:[{type:"text",text:B}],...(0,C.alchemyMeta)({kind:"spawn-subagent",spawnedSessionId:W?O:void 0,agentType:c,requestId:u||void 0,description:e.title||d.slice(0,50)||c,...N?{instructionCode:N}:{}}),...N?{instructionCode:N}:{}}}async function a(e,t,n,s,r,a,l){if(!await(0,y.getServerUrl)(n,s))throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
63
63
|
if(s.info("Sending message to subagent session",{sessionId:e,promptLength:t.length}),r)try{const t=l?.sessionId
|
|
64
64
|
if(t){const n=r.getCLISessionClient()
|
|
65
65
|
if(n){let o=await n.getByExternalId(t)
|
|
66
66
|
if(o||(o=await n.createOrUpdateSession({externalSessionId:t,providerId:"opencode",status:"active"}),s.info("Created caller session in DB for re-parenting",{callerSessionId:t,dbId:o?.id})),o){const i=await n.getByExternalId(e).catch((()=>null)),r=i?.parentSessionId??null
|
|
67
|
-
r===o.id?s.debug("Parent unchanged for continued agent; no re-parent write",{sessionId:e}):(await n.createOrUpdateSession({externalSessionId:e,providerId:"opencode",parentSessionId:o.id,status:"active"}),s.info("RE-PARENTED continued agent: reports now flow to the current caller",{sessionId:e,fromParentDbId:r,toParentDbId:o.id,toCallerSessionId:t}))}}}}catch(e){s.warn("Failed to update parent session - reports may go to wrong parent",{error:(0,
|
|
68
|
-
if(!c)try{const t=`http://localhost:${
|
|
67
|
+
r===o.id?s.debug("Parent unchanged for continued agent; no re-parent write",{sessionId:e}):(await n.createOrUpdateSession({externalSessionId:e,providerId:"opencode",parentSessionId:o.id,status:"active"}),s.info("RE-PARENTED continued agent: reports now flow to the current caller",{sessionId:e,fromParentDbId:r,toParentDbId:o.id,toCallerSessionId:t}))}}}}catch(e){s.warn("Failed to update parent session - reports may go to wrong parent",{error:(0,b.getErrorMessage)(e)})}let c=a
|
|
68
|
+
if(!c)try{const t=`http://localhost:${T}/api/sessions/${encodeURIComponent(e)}/agent-type`,n=await fetch(t,{signal:AbortSignal.timeout(8e3)})
|
|
69
69
|
if(n.ok){const e=await n.json()
|
|
70
70
|
e.success&&e.agentType&&(c=e.agentType)}}catch{s.warn("Agent type lookup failed for session",{sessionId:e})}if(!c)throw new w.ValidationError(`Cannot continue session ${e}: unable to determine agent type. The session's agent type could not be looked up from the action server.`)
|
|
71
71
|
try{let a
|
|
72
|
-
try{const e=await fetch(`http://localhost:${
|
|
72
|
+
try{const e=await fetch(`http://localhost:${T}/api/project-settings`,{signal:AbortSignal.timeout(8e3)})
|
|
73
73
|
if(e.ok){const t=await e.json()
|
|
74
74
|
if(t.data?.defaultModel){const[e,...n]=t.data.defaultModel.split("/")
|
|
75
|
-
a={providerID:e,modelID:n.join("/")}}}}catch{}const d=await o({apiClient:r,fromSessionId:l?.sessionId,toSessionId:e,body:t,logger:s}),u=t,
|
|
76
|
-
return await i(r,n.projectId,d,
|
|
75
|
+
a={providerID:e,modelID:n.join("/")}}}}catch{}const d=await o({apiClient:r,fromSessionId:l?.sessionId,toSessionId:e,body:t,logger:s}),u=t,g={body:t,fromSessionId:l?.sessionId,fromAgent:await S.sessionIdentity.getAgentTypeFor(l?.sessionId)||void 0,...d?{instructionCode:d}:{}},p=await(0,I.deliverToSession)(e,u,{kind:"agent-followup",partPayload:g})
|
|
76
|
+
return await i(r,n.projectId,d,p,s),p.ok?(s.info("Message delivered to subagent session",{sessionId:e,agent:c,instructionCode:d,messageId:p.messageId}),{content:[{type:"text",text:[d?`Message delivered to session ${e} (${d}); it is in that session's transcript.`:`Message delivered to session ${e}; it is in that session's transcript.`,c?`That session is a ${c}. It will process this in the background -- it is NOT proof that work started; check for tasks before reporting progress.`:"Role unknown for that session. It will process this in the background -- that is not proof work started; check for tasks before reporting progress."].join("\n")}],...d?{_meta:{alchemy:{kind:"continue-subagent",instructionCode:d}},instructionCode:d}:{}}):{content:[{type:"text",text:(0,I.deliveryFailureText)(e,p)+(c?` That session is a ${c}.`:"")}],isError:!0,...d?{_meta:{alchemy:{kind:"continue-subagent",instructionCode:d,failed:!0}},instructionCode:d}:{}}}catch(e){throw new Error(`Failed to continue session: ${(0,b.getErrorMessage)(e)}`)}}function l(e){const t=Math.floor(e/1e3)
|
|
77
77
|
if(t<60)return`${t}s`
|
|
78
78
|
const n=Math.floor(t/60)
|
|
79
79
|
return n<60?`${n}m ${t%60}s`:`${Math.floor(n/60)}h ${n%60}m`}function c(e){const t=[]
|
|
@@ -83,114 +83,97 @@ const i=s.path||s.file||s.directory,r=s.needle||s.query||s.pattern
|
|
|
83
83
|
"string"==typeof i?o+=` ${i.split("/").pop()||i}`:"string"==typeof r&&(o+=` "${r.length>30?r.slice(0,27)+"...":r}"`),t.push({name:o,state:e.state.status,time:n.info.time.created})}t.sort(((e,t)=>t.time-e.time))
|
|
84
84
|
const n=t.find((e=>"pending"===e.state||"running"===e.state)),s=t.filter((e=>"completed"===e.state||"error"===e.state)).slice(0,3),o=t.length>0?t[0].time:null
|
|
85
85
|
return{current:n?.name??null,recent:s.map((e=>e.name)),lastActivityTime:o}}function d(e){return e<1e3?"<1s ago":e<6e4?`${Math.floor(e/1e3)}s ago`:e<36e5?`${Math.floor(e/6e4)}m ago`:`${Math.floor(e/36e5)}h ago`}function u(e,t){const n=e||t,s=Date.now()-n
|
|
86
|
-
if(e&&s<
|
|
86
|
+
if(e&&s<j)return{status:"working",detail:`last action ${d(s)}`,isReady:!1}
|
|
87
87
|
const o=d(s).replace(/ ago$/,"")
|
|
88
|
-
return s>P&&e?{status:"stalled",detail:`no activity for ${o}`,isReady:!0}:e?{status:"idle",detail:`no activity for ${o}`,isReady:!0}:{status:"idle",detail:"no tool activity",isReady:!0}}function
|
|
88
|
+
return s>P&&e?{status:"stalled",detail:`no activity for ${o}`,isReady:!0}:e?{status:"idle",detail:`no activity for ${o}`,isReady:!0}:{status:"idle",detail:"no tool activity",isReady:!0}}function g(e){let t=0,n=0,s=0
|
|
89
89
|
for(const o of e.trim().split("\n")){if(!o)continue
|
|
90
90
|
const[e,i]=o.split("\t")
|
|
91
|
-
"-"!==e&&(t+=parseInt(e,10)||0),"-"!==i&&(n+=parseInt(i,10)||0),s++}return{additions:t,deletions:n,files:s}}function
|
|
92
|
-
return e.set(t,{at:s,fingerprint:n}),o&&o.fingerprint===n?`Nothing changed since your last check at ${new Date(o.at).toISOString().slice(11,19)} UTC (${d(s-o.at)}): same activity, same messages, same tokens.`:null}async function f(e,n,s,o){const i=await(0
|
|
91
|
+
"-"!==e&&(t+=parseInt(e,10)||0),"-"!==i&&(n+=parseInt(i,10)||0),s++}return{additions:t,deletions:n,files:s}}function p(e,t,n,s){const o=e.get(t)
|
|
92
|
+
return e.set(t,{at:s,fingerprint:n}),o&&o.fingerprint===n?`Nothing changed since your last check at ${new Date(o.at).toISOString().slice(11,19)} UTC (${d(s-o.at)}): same activity, same messages, same tokens.`:null}async function f(e,n,s,o){const i=await(0,y.getServerUrl)(n,s)
|
|
93
93
|
if(!i)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
94
94
|
s.info("Checking status of subagent session",{sessionId:e})
|
|
95
95
|
try{const r=`${i.replace(/\/$/,"")}/session/${e}`,a=await fetch(r,{signal:AbortSignal.timeout(8e3)})
|
|
96
96
|
if(!a.ok)return{content:[{type:"text",text:`Session ${e} not found or has exited.`}],isError:!0}
|
|
97
97
|
const d=await a.json(),f=`${i.replace(/\/$/,"")}/session/${e}/message`,h=await fetch(f,{signal:AbortSignal.timeout(8e3)})
|
|
98
|
-
let m={input:0,output:0,reasoning:0},w=""
|
|
98
|
+
let m={input:0,output:0,reasoning:0},w="",$=u(null,d.time.updated),y=-1
|
|
99
99
|
if(h.ok){const e=await h.json()
|
|
100
|
-
|
|
100
|
+
y=e.length
|
|
101
101
|
for(const t of e)"assistant"===t.info.role&&t.info.tokens&&(m.input+=t.info.tokens.input||0,m.output+=t.info.tokens.output||0,m.reasoning+=t.info.tokens.reasoning||0)
|
|
102
102
|
const t=c(e)
|
|
103
|
-
|
|
104
|
-
let
|
|
103
|
+
$=u(t.lastActivityTime,d.time.updated),t.current&&(w+=`\nCurrent: ${t.current}`),t.recent.length>0&&(w+=`\nRecent: ${t.recent.join(", ")}`)}const I=Date.now()-d.time.created,S=$.status,k=$.isReady,b=m.input+m.output+m.reasoning
|
|
104
|
+
let x="",v="",A=null
|
|
105
105
|
if(o)try{const t=o.getSessionRequestAssociationClient()
|
|
106
106
|
if(t){const n=await t.getActiveRequestsForSession(e,!1)
|
|
107
107
|
if(n.length>0){const t=n.filter((e=>!e.endedAt)).sort(((e,t)=>new Date(t.startedAt).getTime()-new Date(e.startedAt).getTime())),o=n.filter((e=>e.endedAt)).sort(((e,t)=>new Date(t.endedAt).getTime()-new Date(e.endedAt).getTime())),i=o[0],r=t[0]
|
|
108
108
|
i&&r?A=new Date(i.endedAt).getTime()>new Date(r.startedAt).getTime()?i.requestLocalId:r.requestLocalId:i?A=i.requestLocalId:r&&(A=r.requestLocalId)
|
|
109
109
|
const a=[]
|
|
110
|
-
t.length>0&&a.push(`Active: ${t.map((e=>e.requestLocalId)).join(", ")}`),o.length>0&&a.push(`Previous: ${o.map((e=>e.requestLocalId)).join(", ")}`),a.length>0&&(
|
|
110
|
+
t.length>0&&a.push(`Active: ${t.map((e=>e.requestLocalId)).join(", ")}`),o.length>0&&a.push(`Previous: ${o.map((e=>e.requestLocalId)).join(", ")}`),a.length>0&&(v=`\nRequests: ${a.join(" | ")}`),s.debug("Found request associations",{sessionId:e,activeCount:t.length,historicalCount:o.length})}}}catch(e){s.debug("Failed to get request associations, falling back to title extraction",{error:e instanceof Error?e.message:String(e)})}if(A||(A=function(e){const t=e.match(/\[(req\d{6})\]/)
|
|
111
111
|
return t?t[1]:null}(d.title||"")),A&&n.basePath){const e=await async function(e,n){try{const{execFileSync:s}=await Promise.resolve().then(t.t.bind(t,35317,23)),o=`requests/${e}`
|
|
112
112
|
let i=!1
|
|
113
113
|
try{s("git",["rev-parse","--verify",o],{cwd:n,stdio:"pipe"}),i=!0}catch{i=!1}if(i){const e=s("git",["diff",`main...${o}`,"--numstat"],{cwd:n,encoding:"utf8"})
|
|
114
|
-
if(e.trim())return
|
|
114
|
+
if(e.trim())return g(e)}try{const t=s("git",["log","main","--merges","--oneline","-n","50",`--grep=${e}`],{cwd:n,encoding:"utf8"}).trim()
|
|
115
115
|
if(t){const e=t.split("\n")[0].split(" ")[0],o=s("git",["diff",`${e}^1...${e}`,"--numstat"],{cwd:n,encoding:"utf8"})
|
|
116
|
-
if(o.trim())return{...
|
|
116
|
+
if(o.trim())return{...g(o),merged:!0}}}catch{}return null}catch{return null}}(A,n.basePath)
|
|
117
117
|
if(e){const t=e.additions+e.deletions,n=e.merged?" (merged)":""
|
|
118
|
-
|
|
119
|
-
return{content:[{type:"text",text:`${C?`${C}\n\n`:""}Session ${e}\nTitle: ${d.title||"Untitled"}\nStatus: ${
|
|
118
|
+
x=`\nDiff vs main (${A}): +${e.additions}/-${e.deletions} lines (${t} total) in ${e.files} file${1!==e.files?"s":""}${n}`}}const C=p(R,`${n.currentSessionId??""}>${e}`,`${d.time.updated}:${y}:${b}`,Date.now())
|
|
119
|
+
return{content:[{type:"text",text:`${C?`${C}\n\n`:""}Session ${e}\nTitle: ${d.title||"Untitled"}\nStatus: ${S} (${$.detail})\nReady for input: ${k?"Yes":"No"}\nAge: ${l(I)}\nTokens: ${b.toLocaleString()} (in: ${m.input.toLocaleString()}, out: ${m.output.toLocaleString()}${m.reasoning>0?`, reasoning: ${m.reasoning.toLocaleString()}`:""})${w}${v}${x}`}]}}catch(e){throw new Error(`Failed to check session status: ${(0,b.getErrorMessage)(e)}`)}}async function h(e,t,n){const s=await(0,y.getServerUrl)(t,n)
|
|
120
120
|
if(!s)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
121
121
|
n.info("Aborting subagent session",{sessionId:e})
|
|
122
122
|
try{const t=`${s.replace(/\/$/,"")}/session/${e}/abort`,o=await fetch(t,{signal:AbortSignal.timeout(8e3),method:"POST"})
|
|
123
123
|
if(!o.ok){const e=await o.text().catch((()=>"Unknown error"))
|
|
124
|
-
throw new Error(`Failed to abort session: ${o.status} ${e}`)}return n.info("Session aborted",{sessionId:e}),{content:[{type:"text",text:`Session ${e} has been aborted.`}]}}catch(e){throw new Error(`Failed to abort session: ${(0,
|
|
125
|
-
if(!
|
|
124
|
+
throw new Error(`Failed to abort session: ${o.status} ${e}`)}return n.info("Session aborted",{sessionId:e}),{content:[{type:"text",text:`Session ${e} has been aborted.`}]}}catch(e){throw new Error(`Failed to abort session: ${(0,b.getErrorMessage)(e)}`)}}async function m(e,t,n,s={}){const{activeOnly:o=!1,requestId:i,limit:r,minTokens:a,maxTokens:d,maxAgeHours:g}=s,p=await(0,y.getServerUrl)(e,t)
|
|
125
|
+
if(!p)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
126
126
|
t.info("Listing sessions",{filters:s})
|
|
127
|
-
try{const
|
|
128
|
-
if(!
|
|
129
|
-
let
|
|
130
|
-
if(0===
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if(e){const t=[...b,...v]
|
|
144
|
-
I=await e.batchEnrich(t)}}catch{}const x=g.replace(/\/$/,""),A=await Promise.allSettled(S.map((e=>fetch(`${x}/session/${e.id}/message`,{signal:AbortSignal.timeout(8e3)}).then((e=>e.ok?e.json():[])).catch((()=>[]))))),C=[]
|
|
145
|
-
for(let e=0;e<S.length;e++){const t=S[e],n=Date.now()-t.time.created
|
|
146
|
-
let o=0,r=null,l=[],p=u(null,t.time.updated)
|
|
147
|
-
const g=A[e],f="fulfilled"===g.status?g.value:[]
|
|
127
|
+
try{const e=`${p.replace(/\/$/,"")}/session?limit=1000`,t=await fetch(e,{signal:AbortSignal.timeout(8e3)})
|
|
128
|
+
if(!t.ok)throw new Error(`Failed to fetch sessions: ${t.status}`)
|
|
129
|
+
let f=await t.json()
|
|
130
|
+
if(0===f.length)return{content:[{type:"text",text:"No sessions found."}]}
|
|
131
|
+
s.parentSessionId&&(f=f.filter((e=>(e.parentId||e.parentID)===s.parentSessionId))),f.sort(((e,t)=>t.time.created-e.time.created))
|
|
132
|
+
const h=`${p.replace(/\/$/,"")}/session/status`,m=await fetch(h,{signal:AbortSignal.timeout(8e3)}),w=m.ok?await m.json():{}
|
|
133
|
+
let $=f
|
|
134
|
+
if(o&&($=$.filter((e=>"idle"!==(w[e.id]?.type||"idle")))),void 0!==g){const e=60*g*60*1e3,t=Date.now()-e
|
|
135
|
+
$=$.filter((e=>e.time.created>=t))}if(0===$.length)return{content:[{type:"text",text:"No sessions match the specified filters."}]}
|
|
136
|
+
let y={}
|
|
137
|
+
const I=$.map((e=>e.id))
|
|
138
|
+
if(n)try{const e=n.getCLISessionClient()
|
|
139
|
+
e&&(y=await e.batchEnrich(I))}catch{}const S=p.replace(/\/$/,""),k=await Promise.allSettled($.map((e=>fetch(`${S}/session/${e.id}/message`,{signal:AbortSignal.timeout(8e3)}).then((e=>e.ok?e.json():[])).catch((()=>[]))))),b=[]
|
|
140
|
+
for(let e=0;e<$.length;e++){const t=$[e],n=Date.now()-t.time.created
|
|
141
|
+
let o=0,r=null,l=[],g=u(null,t.time.updated)
|
|
142
|
+
const p=k[e],f="fulfilled"===p.status?p.value:[]
|
|
148
143
|
for(const e of f)"assistant"===e.info.role&&e.info.tokens&&(o+=(e.info.tokens.input||0)+(e.info.tokens.output||0)+(e.info.tokens.reasoning||0))
|
|
149
144
|
if(f.length>0){const e=c(f)
|
|
150
|
-
|
|
145
|
+
g=u(e.lastActivityTime,t.time.updated),r=e.current||null,l=e.recent}const h=g.status
|
|
151
146
|
if(void 0!==a&&o<a)continue
|
|
152
147
|
if(void 0!==d&&o>d)continue
|
|
153
|
-
const m=
|
|
148
|
+
const m=y[t.id]
|
|
154
149
|
if(s.agentType&&(!m||m.agentType!==s.agentType))continue
|
|
155
150
|
if("archived"===m?.status)continue
|
|
156
151
|
let w=""
|
|
157
|
-
const
|
|
158
|
-
m?.associations&&
|
|
159
|
-
const
|
|
160
|
-
if(v)for(const e of v){const t=I[e]
|
|
161
|
-
if(t?.associations){const n=$[e]?.type||"idle",s="idle"===n||"stalled"===n
|
|
162
|
-
for(const e of t.associations)s&&!e.endedAt?b.push({...e,endedAt:"idle"}):b.push(e)}}if(b.length>0){const e=new Map
|
|
163
|
-
for(const t of b){const n=e.get(t.requestLocalId)
|
|
152
|
+
const I=[],S=[]
|
|
153
|
+
if(m?.associations&&S.push(...m.associations),S.length>0){const e=new Map
|
|
154
|
+
for(const t of S){const n=e.get(t.requestLocalId)
|
|
164
155
|
void 0!==n&&(n||t.endedAt)||e.set(t.requestLocalId,!t.endedAt)}const t=[...e.entries()].filter((([,e])=>e)).map((([e])=>e)),n=[...e.entries()].filter((([,e])=>!e)).map((([e])=>e))
|
|
165
|
-
|
|
156
|
+
I.push(...t,...n)
|
|
166
157
|
const s=[]
|
|
167
158
|
if(t.length>0&&s.push(`active: ${t.join(", ")}`),n.length>0){const e=5,t=n.slice(0,e),o=n.length-t.length
|
|
168
|
-
s.push(`prev: ${t.join(", ")}${o>0?` +${o} more`:""}`)}s.length>0&&(w=` [${s.join(" | ")}]`)}if(i&&!
|
|
169
|
-
const x=t.title||"Untitled",
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
for(const e of T)for(const n of e.allRequestIds)t[n]||(t[n]=!0,s.push(n))
|
|
175
|
-
if(s.length>0)try{const t=await n.proxyPost(`/api/projects/${e.projectId}/areas/by-requests`,{requestLocalIds:s}),o=t?.data?.areasByRequest??t?.areasByRequest
|
|
176
|
-
o&&"object"==typeof o&&(j=o)}catch{}}const E=T.map((e=>{const t=[]
|
|
177
|
-
for(const n of e.allRequestIds){const e=j[n]
|
|
178
|
-
if(Array.isArray(e)){for(const n of e){if(t.length>=5)break
|
|
179
|
-
"string"!=typeof n||t.includes(n)||t.push(n)}if(t.length>=5)break}}const n=(e.specialization||"").split(",").map((e=>e.trim())).filter(Boolean),o=n.length>0?n.slice(0,3):t.slice(0,3),i=o.length>0?`\n Areas: ${o.join(", ")}`:"",r=e.currentAction?`\n Current: ${e.currentAction}`:"",a="specialist"!==s.agentType&&e.recentActions.length>0?`\n Recent: ${e.recentActions.join(", ")}`:""
|
|
180
|
-
return`\u2022 ${e.id}\n ${e.title}${i}\n Status: ${e.status} (${e.statusDetail}) | Age: ${l(e.age)} | ${e.totalTokens.toLocaleString()} tokens${e.requestsInfo}${r}${a}`})),q=r&&C.length>r?` (showing ${r} of ${C.length})`:""
|
|
181
|
-
return{content:[{type:"text",text:`Found ${T.length} session${1!==T.length?"s":""}${q}:\n\n${E.join("\n\n")}`}]}}catch(e){throw new Error(`Failed to list sessions: ${(0,k.getErrorMessage)(e)}`)}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpawn=r,exports.handleContinue=a,exports.extractRecentActivity=c,exports.formatTimeSince=d,exports.deriveActivityStatus=u,exports.noteStatusCheck=g,exports.handleCheckStatus=f,exports.handleAbort=h,exports.handleListSessions=m,exports.handleSubagentOperations=async function(e,t,n,s,o,i){const l=n.child({tool:"subagent_operations"}),c=s.startTimer("tool_execution_time")
|
|
159
|
+
s.push(`prev: ${t.join(", ")}${o>0?` +${o} more`:""}`)}s.length>0&&(w=` [${s.join(" | ")}]`)}if(i&&!I.includes(i))continue
|
|
160
|
+
const x=t.title||"Untitled",v=x.length>50?x.slice(0,47)+"...":x
|
|
161
|
+
b.push({id:t.id,title:v,status:h,age:n,totalTokens:o,requestsInfo:w,allRequestIds:I,statusDetail:g.detail,currentAction:r,recentActions:l})}if(0===b.length)return{content:[{type:"text",text:"No sessions match the specified filters."}]}
|
|
162
|
+
const x=r?b.slice(0,r):b,v=x.map((e=>{const t=e.currentAction?`\n Current: ${e.currentAction}`:"",n=e.recentActions.length>0?`\n Recent: ${e.recentActions.join(", ")}`:""
|
|
163
|
+
return`\u2022 ${e.id}\n ${e.title}\n Status: ${e.status} (${e.statusDetail}) | Age: ${l(e.age)} | ${e.totalTokens.toLocaleString()} tokens${e.requestsInfo}${t}${n}`})),A=r&&b.length>r?` (showing ${r} of ${b.length})`:""
|
|
164
|
+
return{content:[{type:"text",text:`Found ${x.length} session${1!==x.length?"s":""}${A}:\n\n${v.join("\n\n")}`}]}}catch(e){throw new Error(`Failed to list sessions: ${(0,b.getErrorMessage)(e)}`)}}Object.defineProperty(exports,"__esModule",{value:!0}),exports.handleSpawn=r,exports.handleContinue=a,exports.extractRecentActivity=c,exports.formatTimeSince=d,exports.deriveActivityStatus=u,exports.noteStatusCheck=p,exports.handleCheckStatus=f,exports.handleAbort=h,exports.handleListSessions=m,exports.handleSubagentOperations=async function(e,t,n,s,o,i){const l=n.child({tool:"subagent_operations"}),c=s.startTimer("tool_execution_time")
|
|
182
165
|
try{const n=e,{sessionId:d,operation:u}=n
|
|
183
|
-
let
|
|
184
|
-
switch(l.info("Processing subagent_operations",{operation:u,sessionId:d}),u){case"spawn":
|
|
166
|
+
let g
|
|
167
|
+
switch(l.info("Processing subagent_operations",{operation:u,sessionId:d}),u){case"spawn":g=await r({agent:n.agent,prompt:n.prompt,requestId:n.requestId,allowParallel:n.allowParallel,useExistingSession:n.useExistingSession},t,l,o,i)
|
|
185
168
|
break
|
|
186
|
-
case"continue":
|
|
169
|
+
case"continue":g=await a(d,n.prompt,t,l,o,void 0,i)
|
|
187
170
|
break
|
|
188
|
-
case"check-status":
|
|
171
|
+
case"check-status":g=await f(d,t,l,o)
|
|
189
172
|
break
|
|
190
|
-
case"abort":
|
|
173
|
+
case"abort":g=await h(d,t,l)
|
|
191
174
|
break
|
|
192
175
|
case"read-messages":{const e=!(!n.compact&&null==n.select),s=!e&&null==n.limit,o=n.limit??(e?50:8)
|
|
193
|
-
|
|
176
|
+
g=await async function(e,t,n,s,o){const i=await(0,y.getServerUrl)(n,s)
|
|
194
177
|
if(!i)throw new w.ValidationError("Could not determine OpenCode server URL")
|
|
195
178
|
s.info("Reading messages from subagent session",{sessionId:e,limit:t,compact:o?.compact,select:o?.select})
|
|
196
179
|
try{const n=`${i.replace(/\/$/,"")}/session/${e}/message?limit=${t}`,s=await fetch(n,{signal:AbortSignal.timeout(8e3)})
|
|
@@ -207,7 +190,7 @@ n.push(`\u{1f527} ${e.tool||"tool"} [${t.status??"unknown"}]`),n.push(` input:
|
|
|
207
190
|
const s=u(t.output)
|
|
208
191
|
s&&n.push(` output: ${a(s,1500)}`)}return{content:[{type:"text",text:n.join("\n")}]}}if(o?.compact){const t=r.map(((e,t)=>{const n=e.parts.filter((e=>"tool"===e.type)).map(d),s=e.parts.filter((e=>"text"===e.type&&e.text)).map((e=>e.text)).join(" ").replace(/\s+/g," ").trim().slice(0,140),o=[...n,s?`"${s}${s.length>=140?"\u2026":""}"`:""].filter(Boolean).join(" \xb7 ")
|
|
209
192
|
return`[${t+1}] ${"USER"===l(e)?"USER":"ASST"} (${c(e)}): ${o||"(empty)"}`}))
|
|
210
|
-
return{content:[{type:"text",text:`Session ${e}: ${r.length} messages (compact; use select:N for one in full):\n\n${t.join("\n")}`}]}}const
|
|
193
|
+
return{content:[{type:"text",text:`Session ${e}: ${r.length} messages (compact; use select:N for one in full):\n\n${t.join("\n")}`}]}}const g=(e,t)=>{const n=[`[${t+1}] ${l(e)} (${c(e)}):`]
|
|
211
194
|
for(const t of e.parts)if("text"===t.type&&t.text)n.push(a(t.text,5e3))
|
|
212
195
|
else if("tool"===t.type){const e=t.state||{},s=u(e.output).replace(/\s+/g," ").trim()
|
|
213
196
|
n.push(`\u{1f527} ${t.tool||"tool"} [${e.status??"unknown"}]${s?` \u2192 ${a(s,200)}`:""}`)}return n.length>1?n.join("\n"):`${n[0]}\n(no content)`}
|
|
@@ -215,21 +198,15 @@ if(o?.latest){const t=e=>e.parts.some((e=>"text"===e.type&&e.text||"tool"===e.ty
|
|
|
215
198
|
let n=r.length-1
|
|
216
199
|
for(;n>0&&!t(r[n]);)n--
|
|
217
200
|
const s=r.length-1-n
|
|
218
|
-
return{content:[{type:"text",text:`Session ${e}: latest message${s>0?` (skipped ${s} trailing empty message${1===s?"":"s"}; use compact:true for the full trajectory)`:""}:\n\n${
|
|
219
|
-
return{content:[{type:"text",text:`Session ${e}: last ${r.length} messages:\n\n${
|
|
201
|
+
return{content:[{type:"text",text:`Session ${e}: latest message${s>0?` (skipped ${s} trailing empty message${1===s?"":"s"}; use compact:true for the full trajectory)`:""}:\n\n${g(r[n],n)}`}]}}const p=r.map(((e,t)=>g(e,t))).join("\n\n---\n\n")
|
|
202
|
+
return{content:[{type:"text",text:`Session ${e}: last ${r.length} messages:\n\n${p}`}]}}catch(e){throw new Error(`Failed to read messages: ${(0,b.getErrorMessage)(e)}`)}}(d,o,t,l,{compact:n.compact,select:n.select,latest:s})
|
|
220
203
|
break}case"list-sessions":const e={activeOnly:n.activeOnly,requestId:n.requestId,limit:n.limit,minTokens:n.minTokens,maxTokens:n.maxTokens,maxAgeHours:n.maxAgeHours,parentSessionId:i?.sessionId}
|
|
221
|
-
|
|
204
|
+
g=await m(t,l,o,e)
|
|
222
205
|
break
|
|
223
206
|
default:throw new w.ValidationError(`Unknown operation: ${u}`)}c({success:!0}),s.incrementCounter(`subagent_operations_${u}_success`,1)
|
|
224
|
-
const
|
|
225
|
-
return
|
|
226
|
-
const w=t(
|
|
227
|
-
if(s&&s.basePath===e.basePath&&s.envUrl===i)return s.result
|
|
228
|
-
let r=i
|
|
229
|
-
if(!r)try{const{readFileSync:n}=await Promise.resolve().then(t.t.bind(t,79896,23)),{join:s}=await Promise.resolve().then(t.t.bind(t,16928,23)),i=n(s(e.basePath,".alchemy_lab","opencode.json"),"utf8"),a=JSON.parse(i)
|
|
230
|
-
a.port&&(r=`http://127.0.0.1:${a.port}`,o.debug("Discovered OpenCode server URL from .alchemy_lab/opencode.json",{serverUrl:r}))}catch(e){o.debug("Could not read .alchemy_lab/opencode.json",{error:e instanceof Error?e.message:String(e)})}if(r)try{(0,n.noteServe)(Number(new URL(r).port),(0,n.currentServePassword)(e.basePath))}catch{}return s={basePath:e.basePath,envUrl:i,result:r},r}
|
|
231
|
-
const n=t(7245)
|
|
232
|
-
let s=null},24019:(e,exports,t)=>{exports.formatLiveWorker=function(e){const t=e.agentType?e.agentType:"worker",n=[],s=!0===e.busy?"mid-turn":!1===e.busy?"between turns":"unknown"
|
|
207
|
+
const p=E[u]
|
|
208
|
+
return p?(0,C.withAlchemyKind)(g,p):g}catch(e){return l.error("Subagent operations failed",{error:e instanceof Error?e.stack:String(e)}),c({success:!1}),s.incrementCounter("subagent_operations_errors",1),{content:[{type:"text",text:`Subagent operation failed: ${(0,b.getErrorMessage)(e)}`}],isError:!0}}}
|
|
209
|
+
const w=t(59860),$=t(15899),y=t(47617),I=t(39844),S=t(6688),k=t(87280),b=t(58824),x=t(79896),v=t(16928),A=t(8955),C=t(82272),E={spawn:"spawn-subagent",continue:"continue-subagent","check-status":"check-subagent-status",abort:"abort-subagent","read-messages":"read-subagent-messages","list-sessions":"list-subagent-sessions"},q="true"===process.env.ALCHEMY_DEBUG_LOGS,T=(0,t(79414).getActionServerPort)(),j=6e4,P=3e5,R=new Map},80024:(e,exports,t)=>{exports.formatLiveWorker=function(e){const t=e.agentType?e.agentType:"worker",n=[],s=!0===e.busy?"mid-turn":!1===e.busy?"between turns":"unknown"
|
|
233
210
|
return n.push(`- ${t} (${e.sessionId}): ${e.status}, ${e.detail}; ${s}`),e.current&&n.push(` now: ${e.current}`),e.recent.length>0&&n.push(` recently: ${e.recent.join(", ")}`),e.lastSaid&&n.push(` last said${e.lastSaidAgo?` (${e.lastSaidAgo})`:""}: "${e.lastSaid}"`),e.lastRefusal&&n.push(` last refused (its tool said): ${e.lastRefusal}`),n.join("\n")},exports.readLiveWorker=async function(e,t){if(!e)return null
|
|
234
211
|
const i=t.filter((e=>(0,s.isWorkerAgentType)(e.agentType??""))),r=(i.length>0?i:t).slice(-1)[0]
|
|
235
212
|
if(!r)return null
|
|
@@ -240,11 +217,11 @@ const i=await e.json(),l=await t.json()
|
|
|
240
217
|
let c=null
|
|
241
218
|
if(s&&s.ok)try{const e=await s.json(),t=e?.[r.sessionId]
|
|
242
219
|
c=void 0!==t&&"busy"===("string"==typeof t?t:t?.type)}catch{}const d=(0,n.extractRecentActivity)(l),u=(0,n.deriveActivityStatus)(d.lastActivityTime,i.time?.updated??Date.now())
|
|
243
|
-
let
|
|
220
|
+
let g=null,p=null
|
|
244
221
|
for(let e=l.length-1;e>=0;e--){const t=l[e]
|
|
245
222
|
if("assistant"!==t.info.role)continue
|
|
246
223
|
const s=(t.parts??[]).filter((e=>"text"===e.type&&e.text)).map((e=>e.text)).join(" ").replace(/\s+/g," ").trim()
|
|
247
|
-
if(s){
|
|
224
|
+
if(s){g=s.length>220?s.slice(0,217)+"...":s,p=(0,n.formatTimeSince)(Date.now()-(t.info.time.completed??t.info.time.created))
|
|
248
225
|
break}}const f=function(e){for(let t=e.length-1;t>=0;t--){const n=e[t]
|
|
249
226
|
if("user"===n.info.role)return null
|
|
250
227
|
const s=n.parts??[]
|
|
@@ -252,9 +229,7 @@ for(let e=s.length-1;e>=0;e--){const t=s[e]
|
|
|
252
229
|
if("tool"!==t.type)continue
|
|
253
230
|
const n="error"===t.state?.status?String(t.state?.error??""):"string"==typeof t.state?.output?t.state.output:""
|
|
254
231
|
if("error"===t.state?.status||o.test(n)){const e=String(t.tool??"tool").replace(/^alchemy_/,""),s=n.replace(/\s+/g," ").trim()
|
|
255
|
-
return`${e}: ${s.length>240?s.slice(0,237)+"...":s}`}}}return null}(l)
|
|
256
|
-
return
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
return i.ok?r?.data??{ok:!1,error:"deliver_route",detail:"empty response"}:{ok:!1,error:"deliver_route",detail:r?.error||`HTTP ${i.status}`}}catch(e){return{ok:!1,error:"deliver_route",detail:e instanceof Error?e.message:String(e)}}},exports.deliveryFailureText=function(e,t){return`\u274c NOT delivered to session ${e}: ${t.detail||t.error||"unknown reason"}. The session did not receive this and nothing will act on it.`}
|
|
260
|
-
const n=t(53603)}}
|
|
232
|
+
return`${e}: ${s.length>240?s.slice(0,237)+"...":s}`}}}return null}(l),h=function(e){for(let t=e.length-1;t>=0;t--){const n=e[t]?.info,s=n?.providerID??n?.model?.providerID
|
|
233
|
+
if("string"==typeof s&&s)return s}return null}(l)
|
|
234
|
+
return{sessionId:r.sessionId,agentType:r.agentType,busy:c,status:u.status,detail:u.detail,current:d.current,recent:d.recent,lastSaid:g,lastSaidAgo:p,lastRefusal:f,provider:h}}catch{return null}}
|
|
235
|
+
const n=t(51725),s=t(87780),o=/^\s*(?:Error:|\u26d4|\u274c|Not filed|Not started|Not kept|Cannot |STOP:)/}}
|
package/dist/{540.js → 293.js}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.id=
|
|
2
|
+
exports.id=293,exports.ids=[293],exports.modules={56149:(e,exports,t)=>{function r(...e){const t=(0,o.createHash)("sha256")
|
|
3
3
|
for(const r of e){const e=r??""
|
|
4
4
|
t.update(String(e.length)).update(":").update(e).update("\0")}return t.digest("hex")}function n(e,t=exports.SHORT_ADDRESS_LENGTH){return e.slice(0,t)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.SHORT_ADDRESS_LENGTH=void 0,exports.contentAddress=r,exports.shortAddress=n,exports.addressedName=function(e,...t){return`${e}-${n(r(...t))}`}
|
|
5
5
|
const o=t(76982)
|
|
6
|
-
exports.SHORT_ADDRESS_LENGTH=12},
|
|
6
|
+
exports.SHORT_ADDRESS_LENGTH=12},79293:(e,exports,t)=>{function r(e){const t=String(e??"").lastIndexOf("@")
|
|
7
7
|
return t>0?e.slice(0,t):String(e??"")}function n(e){const t=e.lastIndexOf("@"),n=t>0?e.slice(t+1):""
|
|
8
8
|
if(!n||!/^\d/.test(n))throw new Error(`"${e}" has no pinned version. A boxed connection installs once and reuses that build, so it needs an exact version, for example ${r(e)}@1.2.3.`)
|
|
9
9
|
return n}function o(e){return n(e),(0,m.addressedName)("alchemy-mcp-pkg",e)}function i(e,t){return(0,m.addressedName)("alchemy-mcp-state",e,t)}function a(e,t){return(0,m.addressedName)("alchemy-mcp-box",e,t)}function c(e,t,r,n){return`${(0,m.addressedName)("alchemy-mcp-repo",e,t,r,n)}:latest`}function s(e,t,r){return["docker","exec","-i",e,...t??[],...r??[]]}Object.defineProperty(exports,"__esModule",{value:!0}),exports.REGISTRY_ALLOWLIST=void 0,exports.packageNameOf=r,exports.assertPinned=n,exports.artifactVolumeFor=o,exports.stateVolumeFor=i,exports.boxNameFor=a,exports.prepareConnectionArtifact=async function(e,t){const r=String(e.packageSpec??"")
|
|
@@ -51,6 +51,6 @@ const c=setTimeout((()=>{try{t.kill("SIGKILL")}catch{}a("")}),r)
|
|
|
51
51
|
t.on("error",(e=>{clearTimeout(c),a(String(e.message??e))})),t.on("close",(e=>{clearTimeout(c)
|
|
52
52
|
const t=o.trim().split("\n").filter(Boolean).slice(-4).join("\n")
|
|
53
53
|
a(t?`exit ${e}: ${t}`:0===e?"":`exit ${e} with no output`)}))}catch(e){a(String(e?.message??e))}}))}
|
|
54
|
-
const l=t(
|
|
54
|
+
const l=t(81618),u=t(26166),d=t(99559),m=t(56149),p=3e5,f="node:20-alpine",g="alchemy.mcp=connection"
|
|
55
55
|
exports.REGISTRY_ALLOWLIST=["registry.npmjs.org","npmjs.org","npmjs.com"]
|
|
56
56
|
const k=".alchemy-install-complete",h=12e5}}
|
package/dist/{491.js → 356.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict"
|
|
2
|
-
exports.id=
|
|
2
|
+
exports.id=356,exports.ids=[356],exports.modules={69356:function(e,exports,t){function s(e,t="",n=0,r=[]){if(n>4||r.length>=i)return r
|
|
3
3
|
let c=[]
|
|
4
4
|
try{c=a.default.readdirSync(l.default.join(e,t),{withFileTypes:!0})}catch{return r}for(const f of c.sort(((e,t)=>e.name.localeCompare(t.name)))){if(f.name.startsWith(".")||o.has(f.name))continue
|
|
5
5
|
const c=t?`${t}/${f.name}`:f.name
|
package/dist/414.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=414,exports.ids=[414],exports.modules={79414:(t,exports,e)=>{function r(){return process.env.ALCHEMY_PROJECT_PATH||process.cwd()}function n(t){const e=Date.now(),n=!t
|
|
3
|
+
if(n&&null!==y&&e-v<g)return y
|
|
4
|
+
const o=(0,l.join)(t||r(),h,d)
|
|
5
|
+
if((0,a.existsSync)(o))try{const t=(0,a.readFileSync)(o,"utf-8"),r=JSON.parse(t)
|
|
6
|
+
if("number"==typeof r.port&&r.port>0&&r.port<65536)return n&&(y=r.port,v=e),r.port}catch{}return n&&(y=f,v=e),f}function o(t){return t||r()}async function c(t){try{const e=await(0,p.fetch)(`http://localhost:${t}/health`,{signal:AbortSignal.timeout(1500)})
|
|
7
|
+
if(!e.ok)return null
|
|
8
|
+
const r=await e.json()
|
|
9
|
+
return"string"==typeof r?.projectPath?r.projectPath:null}catch{return null}}async function s(t){const e=o(t),r=Date.now(),s=w.get(e)
|
|
10
|
+
if(s&&r-s.at<S)return s.port
|
|
11
|
+
for(const o of[0,1]){1===o&&(y=null,v=0)
|
|
12
|
+
const s=n(t),u=await c(s)
|
|
13
|
+
if(u&&i(u)===i(e))return w.set(e,{port:s,at:r}),s}return w.delete(e),null}function i(t){try{return(0,a.realpathSync)(t)}catch{return t}}function u(){const t=Date.now()
|
|
14
|
+
return t-m>S&&(m=t,s().then((t=>{null===t&&(y=null,v=0,console.error(`[alchemy] the recorded action-server port does not serve ${o()}: re-reading it. If this repeats, the server for this project is not running.`))})).catch((()=>{}))),`http://localhost:${n()}`}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getActionServerPort=n,exports.verifiedActionServerPort=s,exports.getActionServerBaseUrl=u,exports.actionServerFetch=function(t,e){return j||(j=new p.Agent({headersTimeout:0,bodyTimeout:0})),(0,p.fetch)(`${u()}${t}`,{...e,dispatcher:j})}
|
|
15
|
+
const a=e(79896),l=e(16928),p=e(9956),f=3456,h=".alchemy_lab",d="action-server.json"
|
|
16
|
+
let y=null,v=0
|
|
17
|
+
const g=5e3,w=new Map,S=3e4
|
|
18
|
+
let j,m=0}}
|