alchemylab 1.4.0 → 1.4.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.
- package/dist/414.js +9 -0
- package/dist/cli.js +7 -7
- package/dist/http-server.js +6 -6
- package/dist/index.js +6 -6
- package/dist/mcp-cli-bridge.js +18 -10
- package/dist/mcp-direct.js +6 -6
- package/dist/plugins/hooks/plugin.js +31 -4
- package/package.json +1 -1
package/dist/414.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict"
|
|
2
|
+
exports.id=414,exports.ids=[414],exports.modules={9414(t,exports,e){exports.getActionServerPort=function(t){const e=Date.now(),l=!t
|
|
3
|
+
if(l&&null!==i&&u>e-p)return i
|
|
4
|
+
const a=(0,o.join)(t||process.env.ALCHEMY_PROJECT_PATH||process.cwd(),s,c)
|
|
5
|
+
if((0,r.existsSync)(a))try{const t=(0,r.readFileSync)(a,"utf-8"),o=JSON.parse(t)
|
|
6
|
+
if("number"==typeof o.port&&o.port>0&&65536>o.port)return l&&(i=o.port,p=e),o.port}catch{}return l&&(i=n,p=e),n}
|
|
7
|
+
const r=e(9896),o=e(6928),n=3456,s=".alchemy_lab",c="action-server.json"
|
|
8
|
+
let i=null,p=0
|
|
9
|
+
const u=5e3}}
|
package/dist/cli.js
CHANGED
|
@@ -890,13 +890,13 @@ a.logger.debug("inject_prompt: interpolating",{variables:Object.keys(u),chainInf
|
|
|
890
890
|
const h=d(r,u)
|
|
891
891
|
await Promise.allSettled(c.map((e=>(a.logger.debug("inject_prompt: sending to ancestor",{targetSessionId:e.externalSessionId,agentType:e.agentType}),s(h,e.externalSessionId,a,(0,n.partMeta)("inserted-prompt"))))))},exports.executeNotification=async function(e,t){const s=r(t)
|
|
892
892
|
if(s)try{const t=s+"/tui/toast"
|
|
893
|
-
await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:"Background Work Complete",message:e,variant:"success",duration:8e3})})}catch(e){t.logger.warn("Failed to send toast notification",{error:e+""})}},exports.executeDirectReport=async function(e,
|
|
894
|
-
if(!
|
|
895
|
-
const
|
|
896
|
-
if(!
|
|
897
|
-
const{notifiedSessions:
|
|
898
|
-
await Promise.allSettled(
|
|
899
|
-
return s(l,t.externalSessionId,
|
|
893
|
+
await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:"Background Work Complete",message:e,variant:"success",duration:8e3})})}catch(e){t.logger.warn("Failed to send toast notification",{error:e+""})}},exports.executeDirectReport=async function(e,r,o){try{const{getActionServerPort:n}=await t.e(414).then(t.bind(t,9414)),a=`http://localhost:${n(o.projectPath)}/api/direct-report`,c=await fetch(a,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sessionId:e,requestId:r||void 0,status:"success"})})
|
|
894
|
+
if(!c.ok)return void o.logger.warn("Direct report failed",{sessionId:e,status:c.status})
|
|
895
|
+
const l=await c.json()
|
|
896
|
+
if(!l.success||!l.data)return void o.logger.warn("Direct report returned failure",{sessionId:e})
|
|
897
|
+
const{notifiedSessions:d,parentExternalSessionId:u}=l.data,h=d||(u?[{externalSessionId:u}]:[])
|
|
898
|
+
await Promise.allSettled(h.map((t=>{const r=t.content?.reportStatus||"success",n=t.content?.summary||"Task completed",a=t.content?.details,c=t.messageCode,l=(0,i.formatReportNotification)({messageCode:c,status:r,summary:n,details:a,fromSessionId:e}),d={alchemy:{kind:"worker-report",payload:{messageCode:c,status:r,summary:n,details:a,fromSessionId:e}}}
|
|
899
|
+
return s(l,t.externalSessionId,o,d)})))}catch(t){o.logger.warn("Error in direct report",{sessionId:e,error:t+""})}}
|
|
900
900
|
const o=t(8148),n=t(2272),i=t(7904)},5086(module){"use strict"
|
|
901
901
|
module.exports=require("ws")},5124(module){"use strict"
|
|
902
902
|
module.exports=require("winston")},5317(module){"use strict"
|
package/dist/http-server.js
CHANGED
|
@@ -5236,11 +5236,11 @@ module.exports=require("net")},9373(e,exports,t){"use strict"
|
|
|
5236
5236
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
5237
5237
|
const r=t(6183),n=t(6416)
|
|
5238
5238
|
exports.def={name:"revert_request",description:"Cancel open/in-progress requests or revert completed requests.\n\nCancel (open/in-progress):\n\u2022 Status set to 'canceled', request becomes read-only\n\u2022 No git operations, branch preserved\n\nRevert (completed):\n\u2022 All file changes undone via git revert\n\u2022 Request/task status set to 'reverted'\n\u2022 Request branch deleted\n\u2022 Fails fast if conflicts detected\n\nPreserved: Documents, git history, tool records (for audit trail).",schema:r.RevertRequestSchema,annotations:{title:"Revert Request",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},hidden:!0,handler(e,t){return(0,n.handleRevertRequest)(e,t.context,t.apiClient,t.logger,t.metrics)}}},9414(e,exports,t){"use strict"
|
|
5239
|
-
function r(){const
|
|
5240
|
-
if(null!==c&&d>
|
|
5241
|
-
const
|
|
5242
|
-
if((0,n.existsSync)(
|
|
5243
|
-
if("number"==typeof o.port&&o.port>0&&65536>o.port)return c=o.port,l=
|
|
5239
|
+
function r(e){const t=Date.now(),r=!e
|
|
5240
|
+
if(r&&null!==c&&d>t-l)return c
|
|
5241
|
+
const u=(0,o.join)(e||process.env.ALCHEMY_PROJECT_PATH||process.cwd(),i,a)
|
|
5242
|
+
if((0,n.existsSync)(u))try{const e=(0,n.readFileSync)(u,"utf-8"),o=JSON.parse(e)
|
|
5243
|
+
if("number"==typeof o.port&&o.port>0&&65536>o.port)return r&&(c=o.port,l=t),o.port}catch{}return r&&(c=s,l=t),s}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getActionServerPort=r,exports.getActionServerBaseUrl=function(){return"http://localhost:"+r()}
|
|
5244
5244
|
const n=t(9896),o=t(6928),s=3456,i=".alchemy_lab",a="action-server.json"
|
|
5245
5245
|
let c=null,l=0
|
|
5246
5246
|
const d=5e3},9422(e,exports,t){"use strict"
|
|
@@ -5579,7 +5579,7 @@ e.r(s)
|
|
|
5579
5579
|
var i={}
|
|
5580
5580
|
t=t||[null,r({}),r([]),r(r)]
|
|
5581
5581
|
for(var a=2&o&&n;"object"==typeof a&&!~t.indexOf(a);a=r(a))Object.getOwnPropertyNames(a).forEach((e=>i[e]=()=>n[e]))
|
|
5582
|
-
return i.default=()=>n,e.d(s,i),s},e.d=(exports,t)=>{for(var r in t)e.o(t,r)&&!e.o(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:t[r]})},e.f={},e.e=t=>Promise.all(Object.keys(e.f).reduce(((r,n)=>(e.f[n](t,r),r)),[])),e.u=e=>e+".js",e.o=(e,t)=>({}.hasOwnProperty.call(e,t)),e.r=exports=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})},n={60:1,249:1},e.f.require=t=>{n[t]||(t=>{var r=t.modules,o=t.ids,s=t.runtime
|
|
5582
|
+
return i.default=()=>n,e.d(s,i),s},e.d=(exports,t)=>{for(var r in t)e.o(t,r)&&!e.o(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:t[r]})},e.f={},e.e=t=>Promise.all(Object.keys(e.f).reduce(((r,n)=>(e.f[n](t,r),r)),[])),e.u=e=>e+".js",e.o=(e,t)=>({}.hasOwnProperty.call(e,t)),e.r=exports=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})},n={60:1,249:1,414:1},e.f.require=t=>{n[t]||(t=>{var r=t.modules,o=t.ids,s=t.runtime
|
|
5583
5583
|
for(var i in r)e.o(r,i)&&(e.m[i]=r[i])
|
|
5584
5584
|
s&&s(e)
|
|
5585
5585
|
for(var a=0;a<o.length;a++)n[o[a]]=1})(require("./"+e.u(t)))}
|
package/dist/index.js
CHANGED
|
@@ -5324,11 +5324,11 @@ module.exports=require("net")},9373(e,exports,t){"use strict"
|
|
|
5324
5324
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
5325
5325
|
const r=t(6183),n=t(6416)
|
|
5326
5326
|
exports.def={name:"revert_request",description:"Cancel open/in-progress requests or revert completed requests.\n\nCancel (open/in-progress):\n\u2022 Status set to 'canceled', request becomes read-only\n\u2022 No git operations, branch preserved\n\nRevert (completed):\n\u2022 All file changes undone via git revert\n\u2022 Request/task status set to 'reverted'\n\u2022 Request branch deleted\n\u2022 Fails fast if conflicts detected\n\nPreserved: Documents, git history, tool records (for audit trail).",schema:r.RevertRequestSchema,annotations:{title:"Revert Request",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},hidden:!0,handler(e,t){return(0,n.handleRevertRequest)(e,t.context,t.apiClient,t.logger,t.metrics)}}},9414(e,exports,t){"use strict"
|
|
5327
|
-
function r(){const
|
|
5328
|
-
if(null!==c&&d>
|
|
5329
|
-
const
|
|
5330
|
-
if((0,n.existsSync)(
|
|
5331
|
-
if("number"==typeof o.port&&o.port>0&&65536>o.port)return c=o.port,l=
|
|
5327
|
+
function r(e){const t=Date.now(),r=!e
|
|
5328
|
+
if(r&&null!==c&&d>t-l)return c
|
|
5329
|
+
const u=(0,o.join)(e||process.env.ALCHEMY_PROJECT_PATH||process.cwd(),i,a)
|
|
5330
|
+
if((0,n.existsSync)(u))try{const e=(0,n.readFileSync)(u,"utf-8"),o=JSON.parse(e)
|
|
5331
|
+
if("number"==typeof o.port&&o.port>0&&65536>o.port)return r&&(c=o.port,l=t),o.port}catch{}return r&&(c=s,l=t),s}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getActionServerPort=r,exports.getActionServerBaseUrl=function(){return"http://localhost:"+r()}
|
|
5332
5332
|
const n=t(9896),o=t(6928),s=3456,i=".alchemy_lab",a="action-server.json"
|
|
5333
5333
|
let c=null,l=0
|
|
5334
5334
|
const d=5e3},9422(e,exports,t){"use strict"
|
|
@@ -5684,7 +5684,7 @@ e.r(s)
|
|
|
5684
5684
|
var i={}
|
|
5685
5685
|
t=t||[null,r({}),r([]),r(r)]
|
|
5686
5686
|
for(var a=2&o&&n;"object"==typeof a&&!~t.indexOf(a);a=r(a))Object.getOwnPropertyNames(a).forEach((e=>i[e]=()=>n[e]))
|
|
5687
|
-
return i.default=()=>n,e.d(s,i),s},e.d=(exports,t)=>{for(var r in t)e.o(t,r)&&!e.o(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:t[r]})},e.f={},e.e=t=>Promise.all(Object.keys(e.f).reduce(((r,n)=>(e.f[n](t,r),r)),[])),e.u=e=>e+".js",e.o=(e,t)=>({}.hasOwnProperty.call(e,t)),e.r=exports=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})},n={57:1,60:1,249:1,873:1,939:1},e.f.require=t=>{n[t]||(t=>{var r=t.modules,o=t.ids,s=t.runtime
|
|
5687
|
+
return i.default=()=>n,e.d(s,i),s},e.d=(exports,t)=>{for(var r in t)e.o(t,r)&&!e.o(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:t[r]})},e.f={},e.e=t=>Promise.all(Object.keys(e.f).reduce(((r,n)=>(e.f[n](t,r),r)),[])),e.u=e=>e+".js",e.o=(e,t)=>({}.hasOwnProperty.call(e,t)),e.r=exports=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})},n={57:1,60:1,249:1,414:1,873:1,939:1},e.f.require=t=>{n[t]||(t=>{var r=t.modules,o=t.ids,s=t.runtime
|
|
5688
5688
|
for(var i in r)e.o(r,i)&&(e.m[i]=r[i])
|
|
5689
5689
|
s&&s(e)
|
|
5690
5690
|
for(var a=0;a<o.length;a++)n[o[a]]=1})(require("./"+e.u(t)))}
|
package/dist/mcp-cli-bridge.js
CHANGED
|
@@ -48,8 +48,8 @@ t.push(` ${s+1}. ${n}`)}))),t.push("Created: "+e.createdAt),t.push("Updated: "+
|
|
|
48
48
|
t.push(` [${s}] ${e.id} ${e.title||"(untitled)"}`)}))),t.join("\n")}(i.data)):n(i.error||"Failed to get request")}case"wait-for-idle":{if(!e.sessionId)return n("sessionId is required for wait-for-idle")
|
|
49
49
|
const i=e.timeoutSeconds||120,o=Date.now()+1e3*i,r=2e3
|
|
50
50
|
let a=!1
|
|
51
|
-
const
|
|
52
|
-
for(;Date.now()<
|
|
51
|
+
const c=Date.now()+1e4
|
|
52
|
+
for(;Date.now()<c&&Date.now()<o;){const s=await t.sendCommand("get-session-status",{sessionId:e.sessionId})
|
|
53
53
|
if(!s.success)return n(s.error||"Failed to check session status")
|
|
54
54
|
if("busy"===s.data.status){a=!0
|
|
55
55
|
break}await new Promise((e=>setTimeout(e,500)))}for(;Date.now()<o;){const i=await t.sendCommand("get-session-status",{sessionId:e.sessionId})
|
|
@@ -58,7 +58,7 @@ const o=i.data
|
|
|
58
58
|
if(("idle"===o.status||"error"===o.status)&&a)return s(`Session ${o.id} is now ${o.status}. Title: ${o.title||"(none)"}`)
|
|
59
59
|
"busy"===o.status&&(a=!0),await new Promise((e=>setTimeout(e,r)))}return n(`Session ${e.sessionId} did not become idle within ${i}s`)}default:return n("Unknown operation: "+i)}var r}
|
|
60
60
|
const i=t(1569),o=t(8524)
|
|
61
|
-
exports.CLIBridgeOperationsSchema=i.z.object({operation:i.z.enum(["list-sessions","get-messages","send-message","create-session","get-session-status","wait-for-idle","list-notifications","get-notification","respond-to-notification","list-requests","get-request"]).describe("The CLI operation to perform"),sessionId:i.z.string().optional().describe("OpenCode session ID"),message:i.z.string().optional().describe("Message text to send"),agent:i.z.string().optional().describe("Agent to use for the message"),variant:i.z.string().optional().describe('Thinking variant (e.g., "high", "max")'),system:i.z.string().optional().describe("System instructions for the message"),limit:i.z.number().optional().describe("Max number of messages to return"),directory:i.z.string().optional().describe("Directory for the new session"),title:i.z.string().optional().describe("Title for the new session"),parentId:i.z.string().optional().describe("Parent session ID for child sessions"),timeoutSeconds:i.z.number().optional().describe("Max seconds to wait (default: 120)"),includeArchived:i.z.boolean().optional().describe("Include archived sessions"),status:i.z.string().optional().describe('Filter sessions by status (e.g., "idle", "busy")'),agentType:i.z.string().optional().describe("Filter sessions by agent type"),search:i.z.string().optional().describe("Search sessions by title (case-insensitive substring match)"),requestId:i.z.string().optional().describe('Request ID (e.g., "req004643")'),type:i.z.string().optional().describe('Filter requests by type (e.g., "feature", "bugfix")'),offset:i.z.number().optional().describe("Offset for paginated results"),sortBy:i.z.string().optional().describe('Sort field (e.g., "created", "updated")'),sortDirection:i.z.string().optional().describe('Sort direction ("asc" or "desc")'),messageCode:i.z.string().optional().describe('Session message code (e.g., "Q-abc-001" or "R-abc-001")'),responseText:i.z.string().optional().describe("Text answer for free-form questions"),selectedOptions:i.z.array(i.z.string()).optional().describe("Selected option IDs for alternatives questions"),messageType:i.z.string().optional().describe('Filter by message type: "question" or "report"')})},5086(module){module.exports=require("ws")},5106(module){module.exports=require("zod-to-json-schema")},5802(module){module.exports=require("@modelcontextprotocol/sdk/server/stdio.js")},6865(module){module.exports=require("@modelcontextprotocol/sdk/server/index.js")},6982(module){module.exports=require("crypto")},8524(e,exports,t){var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
61
|
+
exports.CLIBridgeOperationsSchema=i.z.object({operation:i.z.enum(["list-sessions","get-messages","send-message","create-session","get-session-status","wait-for-idle","list-notifications","get-notification","respond-to-notification","list-requests","get-request"]).describe("The CLI operation to perform"),sessionId:i.z.string().optional().describe("OpenCode session ID"),message:i.z.string().optional().describe("Message text to send"),agent:i.z.string().optional().describe("Agent to use for the message"),variant:i.z.string().optional().describe('Thinking variant (e.g., "high", "max")'),system:i.z.string().optional().describe("System instructions for the message"),limit:i.z.number().optional().describe("Max number of messages to return"),directory:i.z.string().optional().describe("Directory for the new session"),title:i.z.string().optional().describe("Title for the new session"),parentId:i.z.string().optional().describe("Parent session ID for child sessions"),timeoutSeconds:i.z.number().optional().describe("Max seconds to wait (default: 120)"),includeArchived:i.z.boolean().optional().describe("Include archived sessions"),status:i.z.string().optional().describe('Filter sessions by status (e.g., "idle", "busy")'),agentType:i.z.string().optional().describe("Filter sessions by agent type"),search:i.z.string().optional().describe("Search sessions by title (case-insensitive substring match)"),requestId:i.z.string().optional().describe('Request ID (e.g., "req004643")'),type:i.z.string().optional().describe('Filter requests by type (e.g., "feature", "bugfix")'),offset:i.z.number().optional().describe("Offset for paginated results"),sortBy:i.z.string().optional().describe('Sort field (e.g., "created", "updated")'),sortDirection:i.z.string().optional().describe('Sort direction ("asc" or "desc")'),messageCode:i.z.string().optional().describe('Session message code (e.g., "Q-abc-001" or "R-abc-001")'),responseText:i.z.string().optional().describe("Text answer for free-form questions"),selectedOptions:i.z.array(i.z.string()).optional().describe("Selected option IDs for alternatives questions"),messageType:i.z.string().optional().describe('Filter by message type: "question" or "report"')})},5086(module){module.exports=require("ws")},5106(module){module.exports=require("zod-to-json-schema")},5802(module){module.exports=require("@modelcontextprotocol/sdk/server/stdio.js")},6865(module){module.exports=require("@modelcontextprotocol/sdk/server/index.js")},6928(module){module.exports=require("path")},6982(module){module.exports=require("crypto")},8524(e,exports,t){var s=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}}
|
|
62
62
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.CLIBridgeWebSocket=void 0,exports.setCLIBridge=function(e){o=e},exports.getCLIBridge=function(){return o}
|
|
63
63
|
const n=t(5086),i=s(t(6982))
|
|
64
64
|
exports.CLIBridgeWebSocket=class{constructor(e,t=3e4){this.wss=null,this.uiClient=null,this.pendingCommands=new Map,this.heartbeatInterval=null,this.logger=e,this.defaultTimeout=t}attach(e){this.wss=new n.WebSocketServer({server:e,path:"/ws/cli-bridge"}),this.wss.on("connection",(e=>{this.logger.info("[CLIBridge] UI client connected"),this.uiClient&&(this.logger.warn("[CLIBridge] Replacing existing UI client connection"),this.uiClient.close(1e3,"Replaced by new connection")),this.uiClient=e,this.startHeartbeat(),e.on("message",(e=>{try{const t=JSON.parse(e.toString())
|
|
@@ -71,18 +71,26 @@ try{this.uiClient.send(JSON.stringify(o))}catch(e){clearTimeout(r),this.pendingC
|
|
|
71
71
|
t?(clearTimeout(t.timer),this.pendingCommands.delete(e.id),t.resolve(e)):this.logger.warn("[CLIBridge] Received response for unknown command",{id:e.id})}startHeartbeat(){this.stopHeartbeat(),this.heartbeatInterval=setInterval((()=>{this.uiClient&&this.uiClient.readyState===n.WebSocket.OPEN&&this.uiClient.ping()}),3e4)}stopHeartbeat(){this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null)}close(){this.stopHeartbeat()
|
|
72
72
|
for(const[e,t]of this.pendingCommands)clearTimeout(t.timer),t.reject(Error("Bridge shutting down")),this.pendingCommands.delete(e)
|
|
73
73
|
this.uiClient&&(this.uiClient.close(1e3,"Server shutting down"),this.uiClient=null),this.wss&&(this.wss.close(),this.wss=null)}}
|
|
74
|
-
let o=null},9150(module){module.exports=require("@modelcontextprotocol/sdk/types.js")}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
let o=null},9150(module){module.exports=require("@modelcontextprotocol/sdk/types.js")},9414(e,exports,t){function s(e){const t=Date.now(),s=!e
|
|
75
|
+
if(s&&null!==c&&u>t-d)return c
|
|
76
|
+
const l=(0,i.join)(e||process.env.ALCHEMY_PROJECT_PATH||process.cwd(),r,a)
|
|
77
|
+
if((0,n.existsSync)(l))try{const e=(0,n.readFileSync)(l,"utf-8"),i=JSON.parse(e)
|
|
78
|
+
if("number"==typeof i.port&&i.port>0&&65536>i.port)return s&&(c=i.port,d=t),i.port}catch{}return s&&(c=o,d=t),o}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getActionServerPort=s,exports.getActionServerBaseUrl=function(){return"http://localhost:"+s()}
|
|
79
|
+
const n=t(9896),i=t(6928),o=3456,r=".alchemy_lab",a="action-server.json"
|
|
80
|
+
let c=null,d=0
|
|
81
|
+
const u=5e3},9896(module){module.exports=require("fs")}},s={},n={};(()=>{Object.defineProperty(n,"__esModule",{value:!0})
|
|
82
|
+
const t=e(6865),s=e(5802),i=e(9150),o=e(5106),r=e(2904),a=e(8524),c=process.argv.slice(2)
|
|
83
|
+
let d=null
|
|
84
|
+
for(let e=0;e<c.length;e++)"--port"===c[e]&&c[e+1]&&(d=parseInt(c[e+1],10),e++)
|
|
85
|
+
if(null===d)try{const{getActionServerPort:t}=e(9414)
|
|
86
|
+
d=t()}catch{d=3456}const u=(...e)=>process.stderr.write(`[cli-bridge] ${e.join(" ")}\n`),l=new class{isUIConnected(){return!0}async sendCommand(e,t={},s){return async function(e,t,s){const n=`http://127.0.0.1:${d}/api/cli-bridge/command`,i=new AbortController,o=s||3e4,r=setTimeout((()=>i.abort()),o+5e3)
|
|
79
87
|
try{const s=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({action:e,params:t,timeout:o}),signal:i.signal})
|
|
80
88
|
if(!s.ok){const e=await s.text()
|
|
81
|
-
return{success:!1,error:`Action server error (${s.status}): ${e}`}}return await s.json()}catch(e){return"AbortError"===e.name?{success:!1,error:`Command timed out after ${o/1e3}s`}:{success:!1,error:`Cannot reach action server at port ${
|
|
89
|
+
return{success:!1,error:`Action server error (${s.status}): ${e}`}}return await s.json()}catch(e){return"AbortError"===e.name?{success:!1,error:`Command timed out after ${o/1e3}s`}:{success:!1,error:`Cannot reach action server at port ${d}: ${e.message}`}}finally{clearTimeout(r)}}(e,t,s)}};(0,a.setCLIBridge)(l)
|
|
82
90
|
const p=new t.Server({name:"alchemy-cli-bridge",version:"1.0.0"},{capabilities:{tools:{}}})
|
|
83
91
|
p.setRequestHandler(i.ListToolsRequestSchema,(async()=>({tools:[{name:"cli_operations",description:"Interact with OpenCode CLI sessions through alchemy-ui.\n\nOperations:\n list-sessions \u2014 List all active sessions with status and agent type\n Filters: status?, agentType?, search? (title), limit?, includeArchived?\n get-messages \u2014 Get messages from a session (params: sessionId, limit?)\n send-message \u2014 Send a message to a session (params: sessionId, message, agent?, variant?, system?)\n create-session \u2014 Create a new session (params: directory?, title?, parentId?)\n get-session-status \u2014 Check if a session is busy/idle (params: sessionId)\n wait-for-idle \u2014 Wait until a session finishes (params: sessionId, timeoutSeconds?)\n\nRequest operations (no UI connection needed):\n list-requests \u2014 List recent requests (params: status?, type?, limit?, offset?)\n get-request \u2014 Get a specific request with its tasks (params: requestId)\n\nNotification operations (no UI connection needed):\n list-notifications \u2014 List recent notifications (params: sessionId?, messageType?, status?, limit?)\n get-notification \u2014 Get a specific notification by code (params: messageCode)\n respond-to-notification \u2014 Answer a question or acknowledge a report (params: messageCode, responseText?, selectedOptions?)\n\nRequires: alchemy action server running (port 3456) and OpenCode running.",inputSchema:(0,o.zodToJsonSchema)(r.CLIBridgeOperationsSchema)}]}))),p.setRequestHandler(i.CallToolRequestSchema,(async e=>{const{name:t,arguments:s={}}=e.params
|
|
84
92
|
if("cli_operations"!==t)return{content:[{type:"text",text:"Unknown tool: "+t}],isError:!0}
|
|
85
93
|
try{const e=r.CLIBridgeOperationsSchema.parse(s)
|
|
86
|
-
return await(0,r.handleCLIBridgeOperations)(e)}catch(e){return{content:[{type:"text",text:"Error: "+e.message}],isError:!0}}})),async function(){u("Starting CLI Bridge MCP server"),u("Action server port: "+
|
|
94
|
+
return await(0,r.handleCLIBridgeOperations)(e)}catch(e){return{content:[{type:"text",text:"Error: "+e.message}],isError:!0}}})),async function(){u("Starting CLI Bridge MCP server"),u("Action server port: "+d)
|
|
87
95
|
const e=new s.StdioServerTransport
|
|
88
96
|
await p.connect(e),u("CLI Bridge MCP server ready (stdio)")}().catch((e=>{u("Fatal error:",e),process.exit(1)})),process.on("SIGTERM",(()=>process.exit(0))),process.on("SIGINT",(()=>process.exit(0)))})(),module.exports=n})()
|
package/dist/mcp-direct.js
CHANGED
|
@@ -5019,11 +5019,11 @@ exports.def={name:"list_tasks",description:"List and filter tasks",schema:r.List
|
|
|
5019
5019
|
Object.defineProperty(exports,"__esModule",{value:!0}),exports.def=void 0
|
|
5020
5020
|
const r=t(6183),n=t(6416)
|
|
5021
5021
|
exports.def={name:"revert_request",description:"Cancel open/in-progress requests or revert completed requests.\n\nCancel (open/in-progress):\n\u2022 Status set to 'canceled', request becomes read-only\n\u2022 No git operations, branch preserved\n\nRevert (completed):\n\u2022 All file changes undone via git revert\n\u2022 Request/task status set to 'reverted'\n\u2022 Request branch deleted\n\u2022 Fails fast if conflicts detected\n\nPreserved: Documents, git history, tool records (for audit trail).",schema:r.RevertRequestSchema,annotations:{title:"Revert Request",readOnlyHint:!1,destructiveHint:!0,idempotentHint:!1},hidden:!0,handler(e,t){return(0,n.handleRevertRequest)(e,t.context,t.apiClient,t.logger,t.metrics)}}},9414(e,exports,t){"use strict"
|
|
5022
|
-
function r(){const
|
|
5023
|
-
if(null!==c&&d>
|
|
5024
|
-
const
|
|
5025
|
-
if((0,n.existsSync)(
|
|
5026
|
-
if("number"==typeof o.port&&o.port>0&&65536>o.port)return c=o.port,l=
|
|
5022
|
+
function r(e){const t=Date.now(),r=!e
|
|
5023
|
+
if(r&&null!==c&&d>t-l)return c
|
|
5024
|
+
const u=(0,o.join)(e||process.env.ALCHEMY_PROJECT_PATH||process.cwd(),i,a)
|
|
5025
|
+
if((0,n.existsSync)(u))try{const e=(0,n.readFileSync)(u,"utf-8"),o=JSON.parse(e)
|
|
5026
|
+
if("number"==typeof o.port&&o.port>0&&65536>o.port)return r&&(c=o.port,l=t),o.port}catch{}return r&&(c=s,l=t),s}Object.defineProperty(exports,"__esModule",{value:!0}),exports.getActionServerPort=r,exports.getActionServerBaseUrl=function(){return"http://localhost:"+r()}
|
|
5027
5027
|
const n=t(9896),o=t(6928),s=3456,i=".alchemy_lab",a="action-server.json"
|
|
5028
5028
|
let c=null,l=0
|
|
5029
5029
|
const d=5e3},9422(e,exports,t){"use strict"
|
|
@@ -5366,7 +5366,7 @@ e.r(s)
|
|
|
5366
5366
|
var i={}
|
|
5367
5367
|
t=t||[null,r({}),r([]),r(r)]
|
|
5368
5368
|
for(var a=2&o&&n;"object"==typeof a&&!~t.indexOf(a);a=r(a))Object.getOwnPropertyNames(a).forEach((e=>i[e]=()=>n[e]))
|
|
5369
|
-
return i.default=()=>n,e.d(s,i),s},e.d=(exports,t)=>{for(var r in t)e.o(t,r)&&!e.o(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:t[r]})},e.f={},e.e=t=>Promise.all(Object.keys(e.f).reduce(((r,n)=>(e.f[n](t,r),r)),[])),e.u=e=>e+".js",e.o=(e,t)=>({}.hasOwnProperty.call(e,t)),e.r=exports=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})},n={60:1,873:1,939:1},e.f.require=t=>{n[t]||(t=>{var r=t.modules,o=t.ids,s=t.runtime
|
|
5369
|
+
return i.default=()=>n,e.d(s,i),s},e.d=(exports,t)=>{for(var r in t)e.o(t,r)&&!e.o(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:t[r]})},e.f={},e.e=t=>Promise.all(Object.keys(e.f).reduce(((r,n)=>(e.f[n](t,r),r)),[])),e.u=e=>e+".js",e.o=(e,t)=>({}.hasOwnProperty.call(e,t)),e.r=exports=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(exports,"__esModule",{value:!0})},n={60:1,414:1,873:1,939:1},e.f.require=t=>{n[t]||(t=>{var r=t.modules,o=t.ids,s=t.runtime
|
|
5370
5370
|
for(var i in r)e.o(r,i)&&(e.m[i]=r[i])
|
|
5371
5371
|
s&&s(e)
|
|
5372
5372
|
for(var a=0;a<o.length;a++)n[o[a]]=1})(require("./"+e.u(t)))}
|
|
@@ -8,10 +8,29 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { join } from "path";
|
|
10
10
|
import { readFileSync, existsSync } from "fs";
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const DEFAULT_ACTION_SERVER_PORT = 3456;
|
|
12
|
+
/**
|
|
13
|
+
* Read the action server's actual port from `${directory}/.alchemy_lab/action-server.json`.
|
|
14
|
+
* The action server auto-increments from 3456 when the preferred port is busy
|
|
15
|
+
* (multiple alchemylab installs on one machine), and writes the resolved port
|
|
16
|
+
* to that file. Without this discovery we'd POST events to whatever first
|
|
17
|
+
* action server happens to own 3456 — wrong project, hooks never fire.
|
|
18
|
+
*
|
|
19
|
+
* Falls back to 3456 if the file is missing or malformed.
|
|
20
|
+
*/
|
|
21
|
+
function readActionServerPort(directory) {
|
|
22
|
+
try {
|
|
23
|
+
const filePath = join(directory, '.alchemy_lab', 'action-server.json');
|
|
24
|
+
if (!existsSync(filePath))
|
|
25
|
+
return DEFAULT_ACTION_SERVER_PORT;
|
|
26
|
+
const data = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
27
|
+
if (typeof data.port === 'number' && data.port > 0 && data.port < 65536) {
|
|
28
|
+
return data.port;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch { /* fall through */ }
|
|
32
|
+
return DEFAULT_ACTION_SERVER_PORT;
|
|
33
|
+
}
|
|
15
34
|
// Singleton guard — OpenCode calls plugin init twice
|
|
16
35
|
let initializedDirectory = null;
|
|
17
36
|
let cachedHandlers = null;
|
|
@@ -68,6 +87,14 @@ export default async ({ directory }) => {
|
|
|
68
87
|
return cachedHandlers;
|
|
69
88
|
}
|
|
70
89
|
initializedDirectory = dir;
|
|
90
|
+
// Discover the action server's actual port from the project's
|
|
91
|
+
// .alchemy_lab/action-server.json. Multiple alchemylab installs on one
|
|
92
|
+
// machine race for 3456; without this discovery hooks for any non-first
|
|
93
|
+
// project would silently land at the wrong action server (or nowhere).
|
|
94
|
+
const actionServerPort = readActionServerPort(dir);
|
|
95
|
+
const actionServerBase = `http://localhost:${actionServerPort}`;
|
|
96
|
+
const HOOK_EVENT_URL = `${actionServerBase}/api/hook-event`;
|
|
97
|
+
const TOOL_EVENT_URL = `${actionServerBase}/api/tool-event`;
|
|
71
98
|
const handlers = {
|
|
72
99
|
"tool.execute.before": async (input) => {
|
|
73
100
|
const toolName = input?.tool || input?.name;
|