alchemylab 2.3.0 → 3.0.1

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.
@@ -1 +1 @@
1
- import*as t from"path";import{join as e}from"path";import{readFileSync as n,existsSync as o}from"fs";const a=2e5;function r(t,e,n){if(e.length<=a)return null;const o=(e.length/1048576).toFixed(1);return[`[AlchemyLab did not pass this result on: ${e.length.toLocaleString()} characters (about ${o} MB).]`,"",`"${t}" returned more than fits usefully in context, so it was held back rather than`,"filling the window. The first part of it was:","",e.slice(0,2e3),"","[...held back...]","",n?`The whole result is stored: ${n}\nRead the part you need with \`result_inspect\` (operation "read", that address, plus a line range or \`find\`), or ask this connection for a summary or a narrower query.`:"Ask this connection for a path, a summary, or a narrower query instead of the whole result."].join("\n")}let s=null,i=null;function l(t,e){fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).catch(e=>{console.warn("[hooks-plugin] hook event delivery failed",t,e instanceof Error?e.message:String(e))})}async function c(t,e){try{await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),signal:AbortSignal.timeout(3e4)})}catch(e){e instanceof Error&&"TimeoutError"===e.name&&console.warn(`[hooks-plugin] after-event POST to ${t} aborted after 30000ms; blocking hooks may not have run`)}}let u=null;async function p(t){if(u&&Date.now()-u.at<6e4)return u.names;try{const e=await fetch(`${t}/api/mcp/namespaces`,{signal:AbortSignal.timeout(5e3)}),n=await e.json(),o=n?.data?.namespaces??[];return u={at:Date.now(),names:Array.isArray(o)?o:[]},u.names}catch{return u={at:Date.now(),names:u?.names??[]},u.names}}const h=new Set(["read","write","edit","patch","multiedit","apply_patch","bash","grep","glob","list","ls","todowrite","todoread","webfetch","websearch","task","skill","invalid"]);function f(t,e){return e.some(e=>t.startsWith(`${e}_`)&&t.length>e.length+1)}async function d(t,e){return!!f(e,await p(t))||!e.startsWith("alchemy_")&&!h.has(e)&&(u=null,f(e,await p(t)))}const y=[1,Number.MAX_SAFE_INTEGER];function m(t){return(Array.isArray(t?.operations)?t.operations:[]).filter(t=>"string"==typeof t?.path&&t.path).map(t=>({path:t.path}))}const g=(()=>{const t={kind:"edit",files:(t,e)=>function(t,e){const n=new Set;"string"==typeof t?.filePath&&n.add(t.filePath);for(const t of Array.isArray(e?.files)?e.files:[]){const e=t?.movePath??t?.filePath;"string"==typeof e&&"delete"!==t?.type&&n.add(e)}return[...n].map(t=>({path:t}))}(t,e)},e={kind:"edit",files:m};return{read:{kind:"read",files:t=>{if("string"!=typeof t?.filePath)return[];const e=Number(t.offset)>=1?Math.floor(Number(t.offset)):1,n=Number(t.limit)>=1?Math.floor(Number(t.limit)):2e3;return[{path:t.filePath,lines:[e,e+n-1]}]}},edit:t,write:t,multiedit:t,patch:t,apply_patch:t,alchemy_read_files:{kind:"read",files:t=>(Array.isArray(t?.paths)?t.paths:[]).filter(t=>"string"==typeof t?.path&&t.path).map(t=>{if(void 0!==t.lines){const e=function(t){const e=/^\s*(\d+)\s*(?:-\s*(\d+)\s*)?$/.exec("string"==typeof t?t:"");if(!e)return null;const n=Number(e[1]),o=void 0===e[2]?n:Number(e[2]);return n>=1&&o>=n?[n,o]:null}(t.lines);return e?{path:t.path,lines:e}:{path:t.path}}return t.symbol?{path:t.path}:{path:t.path,lines:y}})},alchemy_write_file:{kind:"edit",files:t=>"string"==typeof t?.path&&t.path?[{path:t.path}]:[]},alchemy_replace_in_files:e,alchemy_replace_strings:e,alchemy_replace_lines:e,alchemy_insert_lines:e,alchemy_modify_file:e}})();function w(t,e,n){const o=g[t];if(!o)return null;const a=new Set,r=o.files(e??{},n).filter(t=>!a.has(t.path)&&(a.add(t.path),!0));return r.length>0?{kind:o.kind,files:r}:null}function b(t,e){if("string"==typeof t?.output)return void(t.output+=`\n\n${e}`);const n=Array.isArray(t?.content)?t.content:null;if(!n||t.isError)return;const o=n.find(t=>"text"===t?.type&&"string"==typeof t.text);o?o.text+=`\n\n${e}`:n.push({type:"text",text:e})}export default async({directory:u})=>{const p=u||process.cwd();if(s===p&&i)return i;s=p;const h=function(t){try{const a=e(t,".alchemy_lab","action-server.json");if(!o(a))return 3456;const r=JSON.parse(n(a,"utf-8"));if("number"==typeof r.port&&r.port>0&&r.port<65536)return r.port}catch{}return 3456}(p),f=`http://localhost:${h}`;!async function(t,e,n){try{const o=await fetch(`http://localhost:${e}/health`,{signal:AbortSignal.timeout(1500)});if(!o.ok)return!1;const a=await o.json(),r="string"==typeof a?.projectPath?a.projectPath:"",s=!!r&&(r===t||r.endsWith(t)||t.endsWith(r));return s||n?.(`[alchemy hooks] port ${e} serves ${r||"an unknown project"}, not ${t}: hooks would fire into the wrong project`),s}catch{return n?.(`[alchemy hooks] nothing answered /health on port ${e}: hook events will not be delivered`),!1}}(p,h,t=>console.error(t));const y=`${f}/api/hook-event`,m=`${f}/api/tool-event`,g={"tool.execute.before":async(e,n)=>{const o=e?.tool||e?.name;if(!o)return;const a=e?.args||e?.input||{},r=e?.sessionID||"";"bash"===o&&n?.args&&"object"==typeof n.args&&await async function(e,n,o,a){const r="string"==typeof a.workdir&&a.workdir.trim()?a.workdir.trim():".";if(function(e,n){const o=t.resolve(e),a=t.resolve(o,n);if(a!==o&&!a.startsWith(o+t.sep))return!1;const r=t.join(o,".alchemy_lab");return!(a===r||a.startsWith(r+t.sep))}(n,r))try{const s=await fetch(`${e}/api/session-workdir?sessionId=${encodeURIComponent(o)}`,{signal:AbortSignal.timeout(5e3)}),i=s.ok?await s.json():null,l=i?.data?.workdir;if("string"!=typeof l||!l)return;const c=t.relative(t.resolve(n),t.resolve(n,r));a.workdir=c&&!c.startsWith("..")?t.join(l,c):l}catch{}}(f,p,r,n.args),await d(f,o)&&await async function(t,e,n,o,a){let r;try{const s=await fetch(`${t}/api/mcp/gate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({toolName:e,sessionId:n,args:o,callId:a}),signal:AbortSignal.timeout(66e4)}),i=await s.json();if(r=i?.data,!s.ok||!r)throw new Error(i?.error||`gate returned HTTP ${s.status}`)}catch(t){const n=t instanceof Error?t.message:String(t);throw console.warn("[hooks-plugin] MCP gate unreachable, refusing the call",e,n),new Error(`${e} was not run: its approval gate could not be reached (${n}).`)}if(!r.allow)throw new Error(`${e} was not run: ${r.reason}.`)}(f,o,r,a,e?.callID||""),l(m,{toolName:o,sessionId:r,input:a,timing:"before"})},"tool.execute.after":async(t,e)=>{const n=t?.tool||t?.name;if(!n)return;const o=e?w(String(n),t?.args,e.metadata):null;if(o){const n=await async function(t,e,n){if(!e)return null;try{const o=await fetch(`${t}/api/parallel-note`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:e,tool:n.kind,files:n.files}),signal:AbortSignal.timeout(4e3)});if(!o.ok)return null;const a=await o.json();return"string"==typeof a?.data?.note&&a.data.note?a.data.note:null}catch{return null}}(f,t?.sessionID||"",o);n&&b(e,n)}const s=e?.content?.[0]?.text;if("string"==typeof s&&s.length>a){const o=await async function(t,e,n,o){try{const a=await fetch(`${t}/api/results/spill`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:n,toolName:e,...o?{callId:o}:{}}),signal:AbortSignal.timeout(3e4)});if(!a.ok)return;const r=await a.json();return r?.data?.address??void 0}catch{return}}(f,String(n),s,t?.callID),a=r(String(n),s,o);if(a)return e.content[0].text=a,void await c(m,{toolName:n,sessionId:t?.sessionID||"",input:t?.args||t?.input||{},output:a,timing:"after",...t?.callID?{callId:t.callID}:{}})}var i;s?await c(m,{toolName:n,sessionId:t?.sessionID||"",input:t?.args||t?.input||{},output:(i=s,i.length<=8192?i:i.slice(0,6144)+"\n...[truncated]...\n"+i.slice(-2048)),timing:"after",callId:t?.callID||""}):t?.callID&&await d(f,n)&&await c(m,{toolName:n,sessionId:t?.sessionID||"",input:t?.args||t?.input||{},timing:"after",callId:t.callID})},event:async({event:t})=>{switch(t.type){case"session.idle":{const a=t.properties.sessionID||"",{output:r,lastMessageId:s}=await async function(t,a){try{const r=e(a,".alchemy_lab","opencode.json");if(!o(r))return{output:""};const s=JSON.parse(n(r,"utf8")),i=s.port?`http://127.0.0.1:${s.port}`:null;if(!i)return{output:""};const l=process.env.OPENCODE_SERVER_PASSWORD,c=l?{Authorization:`Basic ${Buffer.from(`${process.env.OPENCODE_SERVER_USERNAME||"opencode"}:${l}`).toString("base64")}`}:{},u=await fetch(`${i}/session/${t}/message?limit=5`,{headers:c});if(!u.ok)return{output:""};const p=(await u.json()).filter(t=>"assistant"===t.info.role);return{output:p.flatMap(t=>t.parts).filter(t=>"text"===t.type&&t.text).map(t=>t.text).join("\n"),lastMessageId:p[0]?.info?.id}}catch{return{output:""}}}(a,p);return void l(y,{eventType:"session_idle",sessionId:a,variables:{sessionId:a,lastOutput:r,lastMessageId:s||""}})}case"session.created":{const e=t.properties.info?.id||"";if(!e)return;return void setTimeout(()=>{l(y,{eventType:"session_created",sessionId:e,variables:{sessionId:e}})},500)}}}};return i=g,g};export const internals={ceilingNotice:r,MCP_RESULT_CEILING_CHARS:a,parallelNoteCall:w,appendToResult:b};
1
+ import*as t from"path";import{join as e}from"path";import{readFileSync as n,existsSync as o}from"fs";let a="",s={at:0};const r=globalThis.fetch.bind(globalThis),i=(t,o)=>{try{const i=new URL("string"==typeof t?t:t instanceof URL?t.href:t?.url);if("http:"===i.protocol&&("localhost"===i.hostname||"127.0.0.1"===i.hostname)){const l=function(t){if(!a)return;const o=Date.now();if(o-s.at>2e3)try{const t=JSON.parse(n(e(a,".alchemy_lab","action-server.json"),"utf-8"));s={at:o,port:t?.port,secret:"string"==typeof t?.secret?t.secret:void 0}}catch{s={at:o}}return s.port===t?s.secret:void 0}(Number(i.port||80));if(l){const e=new Headers(o?.headers);return e.set("x-alchemy-local",l),r(t,{...o??{},headers:e})}}}catch{}return r(t,o)},l=2e5;function c(t,e,n){if(e.length<=l)return null;const o=(e.length/1048576).toFixed(1);return[`[AlchemyLab did not pass this result on: ${e.length.toLocaleString()} characters (about ${o} MB).]`,"",`"${t}" returned more than fits usefully in context, so it was held back rather than`,"filling the window. The first part of it was:","",e.slice(0,2e3),"","[...held back...]","",n?`The whole result is stored: ${n}\nRead the part you need with \`result_inspect\` (operation "read", that address, plus a line range or \`find\`), or ask this connection for a summary or a narrower query.`:"Ask this connection for a path, a summary, or a narrower query instead of the whole result."].join("\n")}let u=null,p=null;function f(t,e){i(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)}).catch(e=>{console.warn("[hooks-plugin] hook event delivery failed",t,e instanceof Error?e.message:String(e))})}async function h(t,e){try{await i(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),signal:AbortSignal.timeout(3e4)})}catch(e){e instanceof Error&&"TimeoutError"===e.name&&console.warn(`[hooks-plugin] after-event POST to ${t} aborted after 30000ms; blocking hooks may not have run`)}}let d=null;async function g(t){if(d&&Date.now()-d.at<6e4)return d.names;try{const e=await i(`${t}/api/mcp/namespaces`,{signal:AbortSignal.timeout(5e3)}),n=await e.json(),o=n?.data?.namespaces??[];return d={at:Date.now(),names:Array.isArray(o)?o:[]},d.names}catch{return d={at:Date.now(),names:d?.names??[]},d.names}}const y=new Set(["websearch","webfetch"]),m=new Set(["read","write","edit","patch","multiedit","apply_patch","bash","grep","glob","list","ls","todowrite","todoread","webfetch","websearch","task","skill","invalid"]);function w(t,e){return e.some(e=>t.startsWith(`${e}_`)&&t.length>e.length+1)}async function b(t,e){return!!w(e,await g(t))||!e.startsWith("alchemy_")&&!m.has(e)&&(d=null,w(e,await g(t)))}const I=[1,Number.MAX_SAFE_INTEGER];function S(t){return(Array.isArray(t?.operations)?t.operations:[]).filter(t=>"string"==typeof t?.path&&t.path).map(t=>({path:t.path}))}const k=(()=>{const t={kind:"edit",files:(t,e)=>function(t,e){const n=new Set;"string"==typeof t?.filePath&&n.add(t.filePath);for(const t of Array.isArray(e?.files)?e.files:[]){const e=t?.movePath??t?.filePath;"string"==typeof e&&"delete"!==t?.type&&n.add(e)}return[...n].map(t=>({path:t}))}(t,e)},e={kind:"edit",files:S};return{read:{kind:"read",files:t=>{if("string"!=typeof t?.filePath)return[];const e=Number(t.offset)>=1?Math.floor(Number(t.offset)):1,n=Number(t.limit)>=1?Math.floor(Number(t.limit)):2e3;return[{path:t.filePath,lines:[e,e+n-1]}]}},edit:t,write:t,multiedit:t,patch:t,apply_patch:t,alchemy_read_files:{kind:"read",files:t=>(Array.isArray(t?.paths)?t.paths:[]).filter(t=>"string"==typeof t?.path&&t.path).map(t=>{if(void 0!==t.lines){const e=function(t){const e=/^\s*(\d+)\s*(?:-\s*(\d+)\s*)?$/.exec("string"==typeof t?t:"");if(!e)return null;const n=Number(e[1]),o=void 0===e[2]?n:Number(e[2]);return n>=1&&o>=n?[n,o]:null}(t.lines);return e?{path:t.path,lines:e}:{path:t.path}}return t.symbol?{path:t.path}:{path:t.path,lines:I}})},alchemy_write_file:{kind:"edit",files:t=>"string"==typeof t?.path&&t.path?[{path:t.path}]:[]},alchemy_replace_in_files:e,alchemy_replace_strings:e,alchemy_replace_lines:e,alchemy_insert_lines:e,alchemy_modify_file:e}})();function D(t,e,n){const o=k[t];if(!o)return null;const a=new Set,s=o.files(e??{},n).filter(t=>!a.has(t.path)&&(a.add(t.path),!0));return s.length>0?{kind:o.kind,files:s}:null}const v=new Map;function $(t){let e=v.get(t);return e||(v.size>=500&&v.delete(v.keys().next().value),e={running:new Map,gate:null,pending:[]},v.set(t,e)),e}async function _(t,e){const n=Date.now()+e;for(;;){const e=Date.now();for(const[n,o]of t.running)e-o>9e5&&t.running.delete(n);if(0===t.running.size)return!0;if(e>=n)return!1;await new Promise(t=>setTimeout(t,100))}}async function N(t,e,n){const o=$(t);let a=null;for(;;){for(;o.gate;)await o.gate;const t=await n.due();if(o.gate)continue;if(!t)break;let e;o.gate=new Promise(t=>{e=t});let s=null;try{await _(o,n.drainMs??6e4)&&(s=await n.bring())}finally{o.gate=null,e()}if("conflict"===s?.outcome&&s.text)throw new Error(s.text);"merged"===s?.outcome&&s.text&&(a=s.text);break}return e&&o.running.set(e,Date.now()),a}function j(t,e){const n=v.get(t);n&&e&&n.running.delete(e)}function T(t,e){if("string"==typeof t?.output)return void(t.output+=`\n\n${e}`);const n=Array.isArray(t?.content)?t.content:null;if(!n||t.isError)return;const o=n.find(t=>"text"===t?.type&&"string"==typeof t.text);o?o.text+=`\n\n${e}`:n.push({type:"text",text:e})}export default async({directory:s})=>{const r=s||process.cwd();if(u===r&&p)return p;u=r,a=r;const d=function(t){try{const a=e(t,".alchemy_lab","action-server.json");if(!o(a))return 3456;const s=JSON.parse(n(a,"utf-8"));if("number"==typeof s.port&&s.port>0&&s.port<65536)return s.port}catch{}return 3456}(r),g=`http://localhost:${d}`;!async function(t,e,n){try{const o=await i(`http://localhost:${e}/health`,{signal:AbortSignal.timeout(1500)});if(!o.ok)return!1;const a=await o.json(),s="string"==typeof a?.projectPath?a.projectPath:"",r=!!s&&(s===t||s.endsWith(t)||t.endsWith(s));return r||n?.(`[alchemy hooks] port ${e} serves ${s||"an unknown project"}, not ${t}: hooks would fire into the wrong project`),r}catch{return n?.(`[alchemy hooks] nothing answered /health on port ${e}: hook events will not be delivered`),!1}}(r,d,t=>console.error(t));const m=`${g}/api/hook-event`,w=`${g}/api/tool-event`,I=`${g}/api/web-call`,S=new Set,k={"tool.execute.before":async(e,n)=>{const o=e?.tool||e?.name;if(!o)return;const a=e?.args||e?.input||{},s=e?.sessionID||"";if("bash"===o&&n?.args&&"object"==typeof n.args&&await async function(e,n,o,a){const s="string"==typeof a.workdir&&a.workdir.trim()?a.workdir.trim():".";if(function(e,n){const o=t.resolve(e),a=t.resolve(o,n);if(a!==o&&!a.startsWith(o+t.sep))return!1;const s=t.join(o,".alchemy_lab");return!(a===s||a.startsWith(s+t.sep))}(n,s))try{const r=await i(`${e}/api/session-workdir?sessionId=${encodeURIComponent(o)}`,{signal:AbortSignal.timeout(5e3)}),l=r.ok?await r.json():null,c=l?.data?.workdir;if("string"!=typeof c||!c)return;const u=t.relative(t.resolve(n),t.resolve(n,s));a.workdir=u&&!u.startsWith("..")?t.join(c,u):c}catch{}}(g,r,s,n.args),await b(g,o)&&await async function(t,e,n,o,a){let s;try{const r=await i(`${t}/api/mcp/gate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({toolName:e,sessionId:n,args:o,callId:a}),signal:AbortSignal.timeout(66e4)}),l=await r.json();if(s=l?.data,!r.ok||!s)throw new Error(l?.error||`gate returned HTTP ${r.status}`)}catch(t){const n=t instanceof Error?t.message:String(t);throw console.warn("[hooks-plugin] MCP gate unreachable, refusing the call",e,n),new Error(`${e} was not run: its approval gate could not be reached (${n}).`)}if(!s.allow)throw new Error(`${e} was not run: ${s.reason}.`)}(g,o,s,a,e?.callID||""),s){const t=await N(s,e?.callID||"",{due:()=>async function(t,e){try{const n=await i(`${t}/api/catch-up-due?sessionId=${encodeURIComponent(e)}`,{signal:AbortSignal.timeout(3e3)}),o=n.ok?await n.json():null;return!0===o?.data?.due}catch{return!1}}(g,s),bring:()=>async function(t,e){try{const n=await i(`${t}/api/catch-up`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:e}),signal:AbortSignal.timeout(12e4)}),o=n.ok?await n.json():null;return o?.data??null}catch{return null}}(g,s)});t&&$(s).pending.push(t)}f(w,{toolName:o,sessionId:s,input:a,timing:"before"})},"tool.execute.after":async(t,e)=>{const n=t?.tool||t?.name;if(!n)return;if(t?.sessionID){j(t.sessionID,t?.callID||"");const n=v.get(t.sessionID);n&&n.pending.length>0&&e&&(T(e,n.pending.join("\n\n")),n.pending=[])}const o=e?D(String(n),t?.args,e.metadata):null;if(o){const n=await async function(t,e,n){if(!e)return null;try{const o=await i(`${t}/api/parallel-note`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:e,tool:n.kind,files:n.files}),signal:AbortSignal.timeout(4e3)});if(!o.ok)return null;const a=await o.json();return"string"==typeof a?.data?.note&&a.data.note?a.data.note:null}catch{return null}}(g,t?.sessionID||"",o);n&&T(e,n)}y.has(String(n))&&f(I,{tool:n,sessionId:t?.sessionID||"",callId:t?.callID||"",input:t?.args||t?.input||{},metadata:e?.metadata??{}});const a=e?.content?.[0]?.text;if("string"==typeof a&&a.length>l){const o=await async function(t,e,n,o){try{const a=await i(`${t}/api/results/spill`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({text:n,toolName:e,...o?{callId:o}:{}}),signal:AbortSignal.timeout(3e4)});if(!a.ok)return;const s=await a.json();return s?.data?.address??void 0}catch{return}}(g,String(n),a,t?.callID),s=c(String(n),a,o);if(s)return e.content[0].text=s,void await h(w,{toolName:n,sessionId:t?.sessionID||"",input:t?.args||t?.input||{},output:s,timing:"after",...t?.callID?{callId:t.callID}:{}})}var s;a?await h(w,{toolName:n,sessionId:t?.sessionID||"",input:t?.args||t?.input||{},output:(s=a,s.length<=8192?s:s.slice(0,6144)+"\n...[truncated]...\n"+s.slice(-2048)),timing:"after",callId:t?.callID||""}):t?.callID&&await b(g,n)&&await h(w,{toolName:n,sessionId:t?.sessionID||"",input:t?.args||t?.input||{},timing:"after",callId:t.callID})},event:async({event:t})=>{switch(t.type){case"message.part.updated":{const e=t.properties?.part;return"tool"!==e?.type||"completed"!==e.state?.status&&"error"!==e.state?.status||j(e.sessionID||t.properties?.sessionID||"",e.callID||""),void("tool"===e?.type&&"error"===e.state?.status&&y.has(String(e.tool))&&e.callID&&!S.has(e.callID)&&(S.add(e.callID),S.size>500&&S.clear(),f(I,{tool:e.tool,sessionId:e.sessionID||t.properties?.sessionID||"",callId:e.callID,input:e.state.input||{},error:String(e.state.error||"failed")})))}case"session.idle":{const a=t.properties.sessionID||"",{output:s,lastMessageId:l}=await async function(t,a){try{const s=e(a,".alchemy_lab","opencode.json");if(!o(s))return{output:""};const r=JSON.parse(n(s,"utf8")),l=r.port?`http://127.0.0.1:${r.port}`:null;if(!l)return{output:""};const c=process.env.OPENCODE_SERVER_PASSWORD,u=c?{Authorization:`Basic ${Buffer.from(`${process.env.OPENCODE_SERVER_USERNAME||"opencode"}:${c}`).toString("base64")}`}:{},p=await i(`${l}/session/${t}/message?limit=5`,{headers:u});if(!p.ok)return{output:""};const f=(await p.json()).filter(t=>"assistant"===t.info.role);return{output:f.flatMap(t=>t.parts).filter(t=>"text"===t.type&&t.text).map(t=>t.text).join("\n"),lastMessageId:f[0]?.info?.id}}catch{return{output:""}}}(a,r);return void f(m,{eventType:"session_idle",sessionId:a,variables:{sessionId:a,lastOutput:s,lastMessageId:l||""}})}case"session.created":{const e=t.properties.info?.id||"";if(!e)return;return void setTimeout(()=>{f(m,{eventType:"session_created",sessionId:e,variables:{sessionId:e}})},500)}}}};return p=k,k};export const internals={ceilingNotice:c,MCP_RESULT_CEILING_CHARS:l,parallelNoteCall:D,appendToResult:T,catchUpBeforeTool:N,catchUpCallDone:j,catchUpStates:v};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alchemylab",
3
- "version": "2.3.0",
3
+ "version": "3.0.1",
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",
@@ -43,28 +43,28 @@
43
43
  "test:watch": "mocha --no-parallel 'test/**/*.test.ts' --ignore 'test/**/*.pin.test.ts' --ignore 'test/**/*.slow.test.ts' --watch --watch-files 'src/**/*.ts,test/**/*.ts'",
44
44
  "check:stranded": "node scripts/check-stranded-requests.js",
45
45
  "minify:plugins": "node scripts/minify-plugins.mjs",
46
- "prepack": "node scripts/check-install-scripts.mjs && npm run build:prod"
46
+ "prepack": "node scripts/check-install-scripts.mjs && npm run build:prod && node ../scripts/check-shipped.mjs --npm ."
47
47
  },
48
48
  "dependencies": {
49
- "@modelcontextprotocol/sdk": "^1.7.0",
50
- "alchemylab-opencode": "^1.0.24",
49
+ "@modelcontextprotocol/sdk": "^1.32.1",
50
+ "alchemylab-opencode": "^1.0.25",
51
51
  "chalk": "^4.1.2",
52
- "compression": "^1.8.1",
53
- "cors": "^2.8.5",
54
- "express": "^4.18.2",
52
+ "compression": "^1.8.2",
53
+ "cors": "^2.8.6",
54
+ "express": "^4.22.3",
55
55
  "js-yaml": "^3.14.2",
56
56
  "jszip": "^3.10.2",
57
57
  "micromatch": "^4.0.5",
58
58
  "pdf-lib": "^1.17.1",
59
- "playwright-core": "^1.61.1",
59
+ "playwright-core": "^1.64.0",
60
60
  "simple-git": "^3.36.0",
61
- "ulid": "^3.0.1",
61
+ "ulid": "^3.0.2",
62
62
  "undici": "^7.25.0",
63
63
  "unpdf": "^1.8.1",
64
- "winston": "^3.8.2",
65
- "ws": "^8.14.2",
66
- "zod": "^3.22.4",
67
- "zod-to-json-schema": "^3.22.3"
64
+ "winston": "^3.19.0",
65
+ "ws": "^8.22.0",
66
+ "zod": "^3.25.76",
67
+ "zod-to-json-schema": "^3.25.2"
68
68
  },
69
69
  "devDependencies": {
70
70
  "@types/chai": "^4.3.5",
@@ -88,13 +88,5 @@
88
88
  "webpack-bundle-analyzer": "^4.9.0",
89
89
  "webpack-cli": "^5.1.4",
90
90
  "webpack-node-externals": "^3.0.0"
91
- },
92
- "overrides": {
93
- "effect": "4.0.0-beta.43",
94
- "@effect/platform-node-shared": "4.0.0-beta.43",
95
- "alchemylab-opencode": {
96
- "zod": "4.1.8",
97
- "quansync": "1.0.0"
98
- }
99
91
  }
100
92
  }