blade-code 0.7.3 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/blade.js +2 -2
- package/dist/{chunk-gb0x14v5.js → chunk-3mhbped9.js} +32 -32
- package/dist/{chunk-06awrjgg.js → chunk-4e2fzyf2.js} +1 -1
- package/dist/{chunk-hs4j2fcr.js → chunk-501my8nh.js} +1 -1
- package/dist/{chunk-wp67n9q7.js → chunk-6rszb7xd.js} +263 -263
- package/dist/{chunk-y50fy1gq.js → chunk-7mnefph6.js} +1 -1
- package/dist/{chunk-vw3f4mbt.js → chunk-b1d49byc.js} +1 -1
- package/dist/{chunk-87gff8b7.js → chunk-by93yn92.js} +1 -1
- package/dist/{chunk-29pqj0tb.js → chunk-byxazdwv.js} +1 -1
- package/dist/{chunk-e9kfbbpm.js → chunk-ctbhcw8h.js} +1 -1
- package/dist/chunk-dftaxwg9.js +1 -0
- package/dist/{chunk-98fvxsvc.js → chunk-egavbybx.js} +2 -2
- package/dist/{chunk-5n7h04jg.js → chunk-erpgkabk.js} +1 -1
- package/dist/chunk-gzc9n5d6.js +2 -0
- package/dist/{chunk-d0fata6n.js → chunk-jpry8h07.js} +1 -1
- package/dist/chunk-n5rg9dbv.js +151 -0
- package/dist/{chunk-wev2rke6.js → chunk-pa364yr9.js} +1 -1
- package/dist/chunk-z7x21493.js +7 -0
- package/dist/web/assets/{FilePreview-IDRQBiWa.js → FilePreview-evNzCuVx.js} +1 -1
- package/dist/web/assets/{MarkdownRenderer-BgDKGD2u.js → MarkdownRenderer-BQoiQTDd.js} +1 -1
- package/dist/web/assets/{McpModal-CJ2l7j-5.js → McpModal-BT9OivhK.js} +1 -1
- package/dist/web/assets/{SettingsModal-BWpbIioU.js → SettingsModal-CDRcorCS.js} +1 -1
- package/dist/web/assets/{SettingsStore-BZjkLZcL.js → SettingsStore-CfDjhOkS.js} +1 -1
- package/dist/web/assets/{SkillsModal-CRuRJrN-.js → SkillsModal-DCPaqoOe.js} +1 -1
- package/dist/web/assets/{TerminalPanel-BnZPkS19.js → TerminalPanel-Cs16_6ew.js} +1 -1
- package/dist/web/assets/{dialog-DYRMhlp_.js → dialog-C8VDk-ma.js} +1 -1
- package/dist/web/assets/{index-D4CAglTd.js → index-9t-WxRrl.js} +8 -8
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/dist/chunk-avebc3bj.js +0 -2
- package/dist/chunk-eady1q1w.js +0 -150
- package/dist/chunk-k63hr1eg.js +0 -7
- package/dist/chunk-txjvy8qp.js +0 -1
package/dist/web/index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>BladeCode</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-9t-WxRrl.js"></script>
|
|
9
9
|
<link rel="stylesheet" crossorigin href="/assets/index-Bu13aXyE.css">
|
|
10
10
|
</head>
|
|
11
11
|
<body>
|
package/package.json
CHANGED
package/dist/chunk-avebc3bj.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{j as _f,k as zf}from"./chunk-pvxp2gzr.js";import{A as Pf,C as Vf,D as Yf,H as Bf,I as P,K as Wf,L as Rf,N as mf,Q as g,X as kf}from"./chunk-wp67n9q7.js";import{_ as z}from"./chunk-y50fy1gq.js";import{ra as v,ta as xf,ua as Ff,ya as C}from"./chunk-5smacbk0.js";import{Ea as p}from"./chunk-06awrjgg.js";import{Ka as bf,Ma as e,Va as qf}from"./chunk-gb0x14v5.js";import{tb as U}from"./chunk-63dzf6hr.js";import{Lb as x}from"./chunk-w1zb8zac.js";import{Nb as Zf}from"./chunk-kfg3vx5z.js";var u0={port:{type:"number",describe:"Port to listen on (0 for auto)",default:0},hostname:{type:"string",describe:"Hostname to listen on",default:"127.0.0.1"},cors:{type:"array",describe:"Additional domains to allow for CORS",default:[]}};function v0(V){return{port:V.port??0,hostname:V.hostname??"127.0.0.1",cors:V.cors??[]}}import{Hono as C0}from"hono";import{cors as _0}from"hono/cors";import{existsSync as rf,readFileSync as Of}from"node:fs";import{createServer as z0}from"node:http";import{networkInterfaces as D0}from"node:os";import{dirname as b0,extname as w0,join as S}from"node:path";import{fileURLToPath as L0}from"node:url";import{WebSocketServer as P0}from"ws";import{z as i}from"zod";class c extends Error{code;statusCode;constructor(V,$,f=500){super($);this.code=V;this.statusCode=f;this.name="BladeServerError"}toObject(){return{error:{code:this.code,message:this.message}}}}class I extends c{constructor(V,$){super("NOT_FOUND",$?`${V} not found: ${$}`:`${V} not found`,404)}}class H extends c{constructor(V){super("BAD_REQUEST",V,400)}}var o0=i.object({error:i.object({code:i.string(),message:i.string()})});import{Hono as af}from"hono";import{z as u}from"zod";var Mf=x("Service"),tf=u.object({updates:u.record(u.any()),options:u.object({scope:u.enum(["local","project","global"]).optional(),immediate:u.boolean().optional()}).optional()}),Nf=()=>{let V=new af;return V.get("/",async($)=>{try{let f=v();return $.json(f||{})}catch(f){return Mf.error("[ConfigRoutes] Failed to get config:",f),$.json({})}}),V.put("/",async($)=>{try{let f=await $.req.json(),Q=tf.safeParse(f);if(!Q.success)throw new H("Invalid config update format");let{updates:O,options:J}=Q.data;return await C().updateConfig(O,J),$.json({success:!0,updates:O})}catch(f){throw Mf.error("[ConfigRoutes] Failed to update config:",f),f}}),V.get("/permissions",async($)=>{try{let f=v();return $.json(f?.permissions||{})}catch(f){return Mf.error("[ConfigRoutes] Failed to get permissions:",f),$.json({})}}),V};import{Hono as nf}from"hono";var Xf=()=>{let V=new nf;return V.get("/health",($)=>{return $.json({healthy:!0,version:p()})}),V.get("/info",($)=>{return $.json({version:p(),platform:process.platform,arch:process.arch,nodeVersion:process.version,cwd:U()})}),V};import{Hono as sf}from"hono";var a=x("Service"),Ef=()=>{let V=new sf;return V.get("/",async($)=>{try{let Q=z.getInstance().getAllServers(),O=Array.from(Q.entries()).map(([J,M])=>({id:J,name:J,status:M.status==="connected"?"connected":M.status==="connecting"?"connecting":M.lastError?"error":"offline",endpoint:M.config.command?`${M.config.command} ${(M.config.args||[]).join(" ")}`.trim():M.config.url||"Unknown",description:`MCP server: ${J}`,tools:M.tools.map((Y)=>Y.name),connectedAt:M.connectedAt?.toISOString(),error:M.lastError?.message}));return $.json(O)}catch(f){return a.error("[McpRoutes] Failed to get MCP servers:",f),$.json([])}}),V.post("/:name/connect",async($)=>{try{let f=$.req.param("name");return await z.getInstance().connectServer(f),$.json({success:!0})}catch(f){return a.error("[McpRoutes] Failed to connect MCP server:",f),$.json({success:!1,error:f.message},500)}}),V.post("/:name/disconnect",async($)=>{try{let f=$.req.param("name");return await z.getInstance().disconnectServer(f),$.json({success:!0})}catch(f){return a.error("[McpRoutes] Failed to disconnect MCP server:",f),$.json({success:!1,error:f.message},500)}}),V.delete("/:name",async($)=>{try{let f=$.req.param("name");await z.getInstance().unregisterServer(f);let O=v();if(O?.mcpServers){let{[f]:J,...M}=O.mcpServers;await C().updateConfig({mcpServers:M})}return $.json({success:!0})}catch(f){return a.error("[McpRoutes] Failed to delete MCP server:",f),$.json({success:!1,error:f.message},500)}}),V.post("/",async($)=>{try{let f=await $.req.json(),{name:Q,config:O}=f;if(!Q||!O)return $.json({success:!1,error:"Missing name or config"},400);await z.getInstance().registerServer(Q,O);let M=v();return await C().updateConfig({mcpServers:{...M?.mcpServers,[Q]:O}}),$.json({success:!0})}catch(f){return a.error("[McpRoutes] Failed to add MCP server:",f),$.json({success:!1,error:f.message},500)}}),V};import{Hono as ef}from"hono";var s=x("Service"),Uf=()=>{let V=new ef;return V.get("/",async($)=>{try{let f=xf(),Q=Ff();return $.json({configured:f,current:Q})}catch(f){return s.error("[ModelsRoutes] Failed to get models:",f),$.json({configured:[],current:null})}}),V.post("/",async($)=>{try{let f=await $.req.json(),{provider:Q,name:O,model:J,baseUrl:M,apiKey:Y}=f;if(!J)throw new H("model is required");let j=await C().addModel({provider:Q||"openai-compatible",name:O||J,model:J,baseUrl:M||void 0,apiKey:Y||void 0});return $.json({success:!0,model:j})}catch(f){throw s.error("[ModelsRoutes] Failed to add model:",f),f}}),V.put("/:modelId",async($)=>{try{let f=$.req.param("modelId"),Q=await $.req.json(),{baseUrl:O,apiKey:J,model:M}=Q;return await C().updateModel(f,{baseUrl:O||void 0,apiKey:J||void 0,model:M||void 0}),$.json({success:!0})}catch(f){throw s.error("[ModelsRoutes] Failed to update model:",f),f}}),V.delete("/:modelId",async($)=>{try{let f=$.req.param("modelId");return await C().removeModel(f),$.json({success:!0})}catch(f){throw s.error("[ModelsRoutes] Failed to delete model:",f),f}}),V};import{Hono as K0}from"hono";import{z as T}from"zod";import{Hono as f0}from"hono";import{streamSSE as $0}from"hono/streaming";import{LRUCache as V0}from"lru-cache";import{nanoid as o}from"nanoid";import{z as W}from"zod";var B=x("Service"),O0=W.object({title:W.string().optional(),projectPath:W.string().optional()}),M0=W.object({content:W.string(),attachments:W.array(W.object({type:W.enum(["file","image","url"]),path:W.string().optional(),url:W.string().optional(),content:W.string().optional(),mimeType:W.string().optional(),name:W.string().optional()})).optional(),permissionMode:W.enum(["default","autoEdit","plan","yolo"]).optional()}),J0=W.object({title:W.string().optional()}),m=new Map,D=new V0({max:100,ttl:1800000,dispose:(V,$)=>{if(V.status==="running"||V.status==="waiting_permission")V.abortController.abort(),B.debug(`[SessionRoutes] Run ${$} disposed due to cache eviction`)}}),Q0=(V)=>{if(!V||typeof V!=="object")return V;let $={...V},f=200000;if(typeof $.oldContent==="string"&&$.oldContent.length>f)delete $.oldContent;if(typeof $.newContent==="string"&&$.newContent.length>f)delete $.newContent;return $};function Af(V){if(typeof V==="string")return V;return V.filter(($)=>$.type==="text").map(($)=>$.text).join(`
|
|
2
|
-
`)}function Y0(V,$){let f=($??[]).filter((O)=>O.type==="image"&&typeof O.content==="string").map((O)=>({type:"image_url",image_url:{url:O.content}}));if(f.length===0)return V;let Q=[];if(V.trim())Q.push({type:"text",text:V});return Q.push(...f),Q}var Hf=()=>{let V=new f0,$=new Map,f=new Map,Q=async(O)=>{let J=$.get(O.id);if(J)return J;let M=f.get(O.id);if(!M)M=Bf.create({sessionId:O.id,workspaceRoot:O.projectPath}),f.set(O.id,M);try{let Y=await M;return $.set(O.id,Y),Y}finally{if(f.get(O.id)===M)f.delete(O.id)}};return V.get("/",async(O)=>{try{let J=await g.listSessions(),M=new Set(J.filter((X)=>X.relationType==="subagent").map((X)=>X.sessionId)),Y=Array.from(m.values()).filter((X)=>!M.has(X.id)&&X.relationType!=="subagent").map((X)=>({sessionId:X.id,projectPath:X.projectPath,title:X.title,parentId:void 0,relationType:void 0,status:void 0,agentType:void 0,model:void 0,messageCount:X.messages.length,firstMessageTime:X.createdAt.toISOString(),lastMessageTime:new Date().toISOString(),hasErrors:!1,isActive:!0})),j=new Set(Y.map((X)=>X.sessionId)),Z=J.filter((X)=>!m.has(X.sessionId)&&!j.has(X.sessionId)&&X.relationType!=="subagent"),K=new Set(j),N=Z.filter((X)=>{if(K.has(X.sessionId))return!1;return K.add(X.sessionId),!0}),E=[...Y,...N];return O.json(E)}catch(J){return B.error("[SessionRoutes] Failed to list sessions:",J),O.json([])}}),V.post("/",async(O)=>{try{let J=await O.req.json(),M=O0.safeParse(J);if(!M.success)throw new H("Invalid request body");let{title:Y,projectPath:j}=M.data,Z=o(12),K=j||O.get("directory")||U(),N={id:Z,projectPath:K,title:Y||`Session ${Z.slice(0,6)}`,createdAt:new Date,messages:[]};return m.set(Z,N),O.json({sessionId:Z,projectPath:K,title:N.title,parentId:void 0,relationType:void 0,status:void 0,agentType:void 0,model:void 0,messageCount:0,firstMessageTime:N.createdAt.toISOString(),lastMessageTime:N.createdAt.toISOString(),hasErrors:!1})}catch(J){throw B.error("[SessionRoutes] Failed to create session:",J),J}}),V.get("/:sessionId",async(O)=>{let J=O.req.param("sessionId"),M=m.get(J);if(M)return O.json({sessionId:M.id,projectPath:M.projectPath,title:M.title,messageCount:M.messages.length,firstMessageTime:M.createdAt.toISOString(),lastMessageTime:new Date().toISOString(),hasErrors:!1,isActive:!0});try{let j=(await g.listSessions()).find((Z)=>Z.sessionId===J);if(!j)throw new I("Session",J);return O.json(j)}catch(Y){if(Y instanceof I)throw Y;throw B.error("[SessionRoutes] Failed to get session:",Y),Y}}),V.patch("/:sessionId",async(O)=>{let J=O.req.param("sessionId");try{let M=await O.req.json(),Y=J0.safeParse(M);if(!Y.success)throw new H("Invalid request body");let{title:j}=Y.data,Z=m.get(J);if(Z&&j)Z.title=j;return O.json({success:!0,title:j})}catch(M){throw B.error("[SessionRoutes] Failed to update session:",M),M}}),V.delete("/:sessionId",async(O)=>{let J=O.req.param("sessionId"),M=m.get(J);if(M?.currentRunId){let j=D.get(M.currentRunId);if(j)j.abortController.abort(),P.publish(J,"run.cancelled",{runId:j.id}),D.delete(M.currentRunId)}try{await g.deleteSession(J)}catch(j){B.warn("[SessionRoutes] Failed to delete session file:",j)}m.delete(J),f.delete(J);let Y=$.get(J);if(Y){if(await Y.dispose(),$.delete(J),$.size===0)await z.getInstance().disconnectAll()}return O.json({success:!0})}),V.get("/:sessionId/message",async(O)=>{let J=O.req.param("sessionId");try{let M=await g.loadSession(J);return O.json(M)}catch(M){return B.error("[SessionRoutes] Failed to get messages:",M),O.json([])}}),V.get("/:sessionId/events",async(O)=>{let J=O.req.param("sessionId"),M=m.get(J);if(!M){let Y=O.get("directory")||U();M={id:J,projectPath:Y,title:`Session ${J.slice(0,6)}`,createdAt:new Date,messages:[]},m.set(J,M)}return $0(O,async(Y)=>{await Y.writeSSE({data:JSON.stringify({type:"connected",properties:{sessionId:J,timestamp:Date.now()}})});let Z=P.subscribe((N)=>{if(N.sessionId!==J)return;Y.writeSSE({data:JSON.stringify({type:N.type,properties:{sessionId:N.sessionId,...N.properties}})}).catch(()=>{})}),K=setInterval(()=>{if(!Y.aborted)Y.writeSSE({data:JSON.stringify({type:"heartbeat",properties:{timestamp:Date.now()}})}).catch(()=>{})},15000);Y.onAbort(()=>{clearInterval(K),Z()});while(!0)if(await new Promise((N)=>setTimeout(N,1000)),Y.aborted)break})}),V.post("/:sessionId/message",async(O)=>{let J=O.req.param("sessionId"),M=await O.req.json(),Y=M0.safeParse(M);if(!Y.success)throw new H("Invalid message format");let{content:j,attachments:Z,permissionMode:K}=Y.data,N=K||"default",E=O.get("directory")||U(),X=Y0(j,Z),R=m.get(J);if(!R){let _=await g.loadSession(J).catch(()=>[]);R={id:J,projectPath:E,title:`Session ${J.slice(0,6)}`,createdAt:new Date,messages:_},m.set(J,R)}let F=R.currentRunId?D.get(R.currentRunId):void 0;if(F&&(F.status==="running"||F.status==="waiting_permission")){let h=await(await Q(R)).enqueueSteering(X,{allowBeforeTurn:!0});if(!h.accepted)return O.json({status:"rejected",reason:h.reason??"turn_unavailable"},409);let l=o(12),n=h.queued;return P.publish(J,"message.created",{messageId:l,role:"user",content:Af(X)}),P.publish(J,"steering.queued",{runId:F.id,messageId:l,queued:n}),O.json({runId:F.id,status:"steering_queued",queued:n},202)}let G=o(12),q=new AbortController,L={id:G,sessionId:J,status:"running",abortController:q,createdAt:new Date};return D.set(G,L),R.currentRunId=G,Z0(L,R,X,N,Q).catch((_)=>{B.error(`[SessionRoutes] Run ${G} failed:`,_)}),O.json({runId:G,status:"running"},202)}),V.post("/:sessionId/abort",async(O)=>{let J=O.req.param("sessionId"),M=m.get(J);if(M?.currentRunId){let Y=D.get(M.currentRunId);if(Y)Y.abortController.abort(),Y.status="cancelled",P.publish(J,"run.cancelled",{runId:Y.id})}return O.json({success:!0})}),V.get("/:sessionId/status",async(O)=>{let J=O.req.param("sessionId"),M=m.get(J);if(!M?.currentRunId)return O.json({sessionId:J,status:"idle"});let Y=D.get(M.currentRunId);return O.json({sessionId:J,runId:M.currentRunId,status:Y?.status||"idle"})}),V};async function Z0(V,$,f,Q,O){let{abortController:J,sessionId:M,id:Y}=V,j=o(12),Z=o(12),K=(N,E)=>{P.publish(M,N,E)};try{K("message.created",{messageId:j,role:"user",content:Af(f)}),K("session.status",{status:"running"}),K("message.created",{messageId:Z,role:"assistant",content:""});let N=await O($),E=await mf.createWithRuntime(N,{sessionId:M}),X=async(G)=>{let q=o(12),L=300000;V.status="waiting_permission";let _=new Promise((l)=>{let n=setTimeout(()=>{B.warn(`[SessionRoutes] Permission ${q} timed out after 300000ms`),K("permission.timeout",{requestId:q}),l({approved:!1,reason:"timeout"})},300000);V.pendingPermission={permissionId:q,resolve:(cf)=>{clearTimeout(n),l(cf)},details:G}});K("permission.asked",{requestId:q,toolName:G.toolName,description:G.message,args:G.args,details:G}),B.info(`[SessionRoutes] Permission request created: ${q}, runId: ${Y}`);let h=await _;return B.info(`[SessionRoutes] Permission response received: ${q}, approved: ${h.approved}`),V.status="running",V.pendingPermission=void 0,h},R={messages:[...$.messages],userId:"web-user",sessionId:M,workspaceRoot:$.projectPath,signal:J.signal,permissionMode:Q,confirmationHandler:{requestConfirmation:X}},F=await qf(E.chatStream(f,R,{stream:!0}),async(G)=>{switch(G.kind){case"content_delta":K("message.delta",{messageId:Z,delta:G.delta});break;case"thinking_delta":K("thinking.delta",{delta:G.delta});break;case"tool_start":if("function"in G.toolCall)K("tool.start",{messageId:Z,toolName:G.toolCall.function.name,toolCallId:G.toolCall.id,arguments:G.toolCall.function.arguments,toolKind:G.toolKind});break;case"tool_result":if("function"in G.toolCall)K("tool.result",{messageId:Z,toolName:G.toolCall.function.name,toolCallId:G.toolCall.id,success:G.result.success,summary:G.result.metadata?.summary,output:Rf(Wf(G.toolCall.function.name,G.result)),metadata:Q0(G.result.metadata)});break;case"token_usage":K("token.usage",{...G.usage});break;case"turn_start":K("turn.started",{turn:G.turn,maxTurns:G.maxTurns});break;case"steering_applied":K("steering.applied",{runId:Y,messageIds:G.messageIds,count:G.count,recovered:G.recovered,queued:N.getPendingSteeringCount()});break;case"compaction":K(G.phase==="start"?"compaction.started":"compaction.completed",{});break;case"model_fallback":K("model.fallback",{});break;case"task_update":K("task.updated",{tasks:G.tasks});break;default:break}});$.messages=[...R.messages],K("message.complete",{messageId:Z}),K("thinking.completed",{}),V.status="completed",K("session.completed",{runId:Y,outputTruncated:F.metadata?.outputTruncated??!1}),K("session.status",{status:"idle"})}catch(N){B.error("[SessionRoutes] Agent execution error:",N),V.status="failed",K("session.error",{error:N instanceof Error?N.message:"Unknown error"}),K("session.status",{status:"error"})}}function Tf(V,$,f){B.info(`[SessionRoutes] Looking for permission ${$} in session ${V}`),B.info(`[SessionRoutes] Active runs: ${D.size}`);for(let[Q,O]of D.entries())if(B.info(`[SessionRoutes] Checking run ${Q}: sessionId=${O.sessionId}, pendingPermission=${O.pendingPermission?.permissionId}`),O.sessionId===V&&O.pendingPermission?.permissionId===$)return O.pendingPermission.resolve(f),B.info(`[SessionRoutes] Permission ${$} responded, runId: ${O.id}`),!0;return B.error(`[SessionRoutes] Permission not found: ${$}`),!1}var Jf=x("Service"),j0=T.object({approved:T.boolean(),remember:T.boolean().optional(),scope:T.enum(["once","session"]).optional(),targetMode:T.enum(["default","autoEdit","plan","yolo"]).optional(),feedback:T.string().optional(),answers:T.record(T.union([T.string(),T.array(T.string())])).optional()}),yf=()=>{let V=new K0;return V.post("/:permissionId",async($)=>{let f=$.req.param("permissionId"),Q=$.req.query("sessionId");Jf.info(`[PermissionRoutes] Received permission response: permissionId=${f}, sessionId=${Q}`);try{let O=await $.req.json(),J=j0.safeParse(O);if(!J.success)throw new H("Invalid permission response format");let{approved:M,remember:Y,scope:j,targetMode:Z,feedback:K,answers:N}=J.data;if(!Q)throw new H("sessionId query parameter is required");if(!Tf(Q,f,{approved:M,reason:K,scope:j,targetMode:Z,feedback:K,answers:N}))throw new I("Permission request",f);return Jf.info(`[PermissionRoutes] Permission ${f} ${M?"approved":"denied"}`),$.json({success:!0,approved:M,remember:Y})}catch(O){throw Jf.error("[PermissionRoutes] Failed to respond to permission:",O),O}}),V};import{Hono as G0}from"hono";var Cf=x("Service"),Df=()=>{let V=new G0;return V.get("/",async($)=>{try{let f=await _f();return $.json(f)}catch(f){return Cf.error("[ProviderRoutes] Failed to list providers:",f),$.json([])}}),V.get("/:provider/models",async($)=>{let f=$.req.param("provider");try{let Q=await zf(f);return $.json(Q)}catch(Q){return Cf.error("[ProviderRoutes] Failed to list models:",Q),$.json([])}}),V};import{Hono as N0}from"hono";import*as b from"node:fs/promises";import{homedir as X0}from"node:os";import*as ff from"node:path";var k=x("Service"),Qf=ff.join(X0(),".blade","skills-config.json");async function wf(){try{let V=await b.readFile(Qf,"utf-8");return JSON.parse(V)}catch{return{disabled:[]}}}async function E0(V){await b.mkdir(ff.dirname(Qf),{recursive:!0}),await b.writeFile(Qf,JSON.stringify(V,null,2))}async function x0(V,$){let f=await wf();if($)f.disabled=f.disabled.filter((Q)=>Q!==V);else if(!f.disabled.includes(V))f.disabled.push(V);await E0(f)}var d=null,F0=300000;async function U0(){if(d&&Date.now()-d.timestamp<F0)return d.data;try{let V=await fetch("https://api.github.com/repos/anthropics/skills/contents/skills",{headers:{Accept:"application/vnd.github.v3+json","User-Agent":"Blade-Skills-Catalog"}});if(!V.ok)return k.warn(`GitHub API returned ${V.status}`),d?.data||[];let $=await V.json(),f=[];for(let Q of $){if(Q.type!=="dir")continue;let O=`Official ${Q.name} skill`;try{let J=await fetch(`https://raw.githubusercontent.com/anthropics/skills/main/skills/${Q.name}/SKILL.md`,{headers:{"User-Agent":"Blade-Skills-Catalog"}});if(J.ok){let Y=(await J.text()).match(/^#[^\n]*\n+([^\n#]+)/);if(Y)O=Y[1].trim().slice(0,100)}}catch{}f.push({name:Q.name,description:O,tag:"Official",author:"Anthropic"})}return d={data:f,timestamp:Date.now()},f}catch(V){return k.warn("Failed to fetch skills catalog from GitHub:",V),d?.data||[]}}var Lf=()=>{let V=new N0;return V.get("/",async($)=>{try{let f=e();await f.initialize();let Q=f.getAll(),O=await wf(),J=Q.map((M)=>({id:M.name,name:M.name,enabled:!O.disabled.includes(M.name),description:M.description||"",version:M.version||"1.0.0",provider:"Local",location:M.source==="builtin"?"Built-in":M.basePath,capabilities:["prompts"],allowedTools:M.allowedTools||[]}));return $.json(J)}catch(f){return k.error("[SkillsRoutes] Failed to get skills:",f),$.json([])}}),V.post("/:name/toggle",async($)=>{try{let f=$.req.param("name"),Q=await $.req.json();return await x0(f,Q.enabled),$.json({success:!0,enabled:Q.enabled})}catch(f){return k.error("[SkillsRoutes] Failed to toggle skill:",f),$.json({success:!1,error:f.message},500)}}),V.delete("/:name",async($)=>{try{let f=$.req.param("name"),Q=`${process.env.HOME}/.blade/skills/${f}`;return await b.rm(Q,{recursive:!0,force:!0}),await e().refresh(),$.json({success:!0})}catch(f){return k.error("[SkillsRoutes] Failed to uninstall skill:",f),$.json({success:!1,error:f.message},500)}}),V.post("/install",async($)=>{try{let f=await $.req.json(),Q=bf(),O=e(),J=!1;if(f.source==="catalog"&&f.name){if(J=await Q.installOfficialSkill(f.name),!J)return $.json({success:!1,error:"Failed to install skill from catalog"},500)}else if(f.source==="repo"&&f.url){if(J=await Q.installFromRepo(f.url,f.name),!J)return $.json({success:!1,error:"Failed to install skill from repository. Make sure the repo contains a SKILL.md file."},500)}else if(f.source==="local"&&f.path){if(J=await Q.installFromLocal(f.path,f.name),!J)return $.json({success:!1,error:"Failed to install skill from local path. Make sure the path exists and contains a SKILL.md file."},500)}else return $.json({success:!1,error:"Invalid install parameters. Required: source with corresponding url/path/name"},400);return await O.refresh(),$.json({success:!0})}catch(f){return k.error("[SkillsRoutes] Failed to install skill:",f),$.json({success:!1,error:f.message},500)}}),V.get("/catalog",async($)=>{try{let f=await U0();return $.json(f)}catch(f){return k.error("[SkillsRoutes] Failed to get catalog:",f),$.json([])}}),V};import q0 from"fast-glob";import{Hono as B0}from"hono";import{execSync as W0}from"node:child_process";import{readdir as R0}from"node:fs/promises";import $f from"node:path";var t=x("Service"),m0=(V)=>{try{return W0("git rev-parse --abbrev-ref HEAD",{cwd:V,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}},A0=[...Vf.map((V)=>`${V}/**`),...Vf,...Yf.map((V)=>`**/${V}`)],H0=new Set(["/theme","/model","/permissions","/mcp","/skills","/exit","/resume","/ide","/login","/logout"]),Sf=()=>{let V=new B0;return V.get("/commands",async($)=>{try{let f=$.req.query("q")||"",Q=kf(f).filter((O)=>!H0.has(O.command));return $.json(Q)}catch(f){return t.error("[SuggestionsRoutes] Failed to get command suggestions:",f),$.json([])}}),V.get("/files",async($)=>{try{let f=$.req.query("q")||"",Q=$.get("directory")||U(),O=Math.min(Number($.req.query("limit"))||100,1000),M=(await q0("**/*",{cwd:Q,dot:!1,followSymbolicLinks:!1,onlyFiles:!1,markDirectories:!0,unique:!0,ignore:A0})).map((Z)=>Z.replace(/\\/g,"/"));if(!f)return $.json(M.slice(0,O));let Y=f.toLowerCase(),j=M.filter((Z)=>Z.toLowerCase().includes(Y)).slice(0,O);return $.json(j)}catch(f){return t.error("[SuggestionsRoutes] Failed to get file suggestions:",f),$.json([])}}),V.get("/files/tree",async($)=>{try{let f=$.get("directory")||U(),Q=$.req.query("path")||"",O=Q?$f.join(f,Q):f,M=(await R0(O,{withFileTypes:!0})).map((Z)=>({name:Z.name,path:Q?`${Q}/${Z.name}`:Z.name,type:Z.isDirectory()?"dir":"file"}));M.sort((Z,K)=>{if(Z.type!==K.type)return Z.type==="dir"?-1:1;return Z.name.localeCompare(K.name)});let Y=new Set(Vf),j=M.filter((Z)=>{let K=Z.name;if(K.startsWith("."))return!1;if(Y.has(K))return!1;for(let N of Yf)if(K.match(new RegExp(N.replace("*",".*"))))return!1;return!0});return $.json(j)}catch(f){return t.error("[SuggestionsRoutes] Failed to get file tree:",f),$.json([])}}),V.get("/files/content",async($)=>{try{let f=$.req.query("path");if(!f)return $.json({error:"Missing file path"},400);let Q=$.get("directory")||U(),O=$f.resolve(Q,f),J=$f.relative(Q,O);if(J.startsWith("..")||$f.isAbsolute(J))return $.json({error:"Invalid file path"},400);let M=Pf(),Y=await M.stat(O);if(!Y?.isFile)return $.json({error:"File not found"},404);let j=200000,Z=await M.readTextFile(O),K=Z.length>j;return $.json({path:f,content:K?Z.slice(0,j):Z,truncated:K,size:Y.size})}catch(f){return t.error("[SuggestionsRoutes] Failed to get file content:",f),$.json({error:"Failed to read file"},500)}}),V.get("/git-info",async($)=>{try{let f=$.get("directory")||U(),Q=m0(f);return $.json({branch:Q})}catch(f){return t.error("[SuggestionsRoutes] Failed to get git info:",f),$.json({branch:null})}}),V};import{Hono as T0}from"hono";var w=x("Service"),r=new Map,hf=2097152,If=65536;function uf(){return typeof globalThis.Bun<"u"}async function y0(V,$,f){if(uf()){let{spawn:J}=await import("bun-pty"),M=J(V,$,{name:"xterm-256color",cwd:f.cwd,env:f.env});return{pid:M.pid,write:(Y)=>M.write(Y),resize:(Y,j)=>M.resize(Y,j),kill:()=>M.kill(),onData:(Y)=>M.onData(Y),onExit:(Y)=>M.onExit(Y)}}let O=(await import("node-pty")).spawn(V,$,{name:"xterm-256color",cwd:f.cwd,env:f.env,cols:80,rows:24});return{pid:O.pid,write:(J)=>O.write(J),resize:(J,M)=>O.resize(J,M),kill:()=>O.kill(),onData:(J)=>{O.onData(J)},onExit:(J)=>{O.onExit(J)}}}var jf=void 0,Kf;if(uf())try{let{createBunWebSocket:V}=await import("hono/bun"),$=V();Kf=$.upgradeWebSocket,jf=$.websocket}catch(V){w.warn("[Terminal] Failed to initialize Bun WebSocket support:",V)}async function vf(V,$){let f=`term-${Date.now()}`;w.info(`[Terminal] New connection: ${f}, cwd: ${V}`);let Q=process.platform==="win32"?"powershell.exe":process.env.SHELL||"/bin/zsh",O=Q.endsWith("sh")?["-l"]:[],J=await y0(Q,O,{cwd:V,env:{...process.env,TERM:"xterm-256color",COLORTERM:"truecolor"}}),M={id:f,process:J,cwd:V,buffer:"",subscribers:new Set};if(r.set(f,M),M.subscribers.add($),J.onData((Y)=>{let j=!1;for(let Z of M.subscribers)try{Z.send(Y),j=!0}catch{M.subscribers.delete(Z)}if(j)return;if(M.buffer+=Y,M.buffer.length>hf)M.buffer=M.buffer.slice(-hf)}),J.onExit(({exitCode:Y})=>{w.info(`[Terminal] Process exited: ${f}, code: ${Y}`);for(let j of M.subscribers)try{j.close()}catch{}r.delete(f)}),M.buffer){let Y=M.buffer;M.buffer="";for(let j=0;j<Y.length;j+=If)$.send(Y.slice(j,j+If))}return{session:M,cleanup:()=>{if(w.info(`[Terminal] Connection closed: ${f}`),M.subscribers.delete($),M.subscribers.size===0){try{M.process.kill()}catch{}r.delete(f)}}}}function pf(V,$){V.on("connection",async(f,Q)=>{let O=new URL(Q.url||"/",`http://${Q.headers.host}`);if(!O.pathname.endsWith("/terminal/ws")){f.close();return}let J=O.searchParams.get("cwd")||$()||U();try{let{session:M,cleanup:Y}=await vf(J,{send:(j)=>f.send(j),close:()=>f.close()});f.on("message",(j)=>{try{M.process.write(String(j))}catch(Z){w.error("[Terminal] Failed to write to PTY:",Z)}}),f.on("close",Y),f.on("error",Y)}catch(M){w.error("[Terminal] Failed to spawn PTY:",M),f.close()}})}var gf=()=>{let V=new T0;if(V.get("/status",($)=>{let f=Array.from(r.values()).map((Q)=>({id:Q.id,cwd:Q.cwd}));return $.json({active:f.length,terminals:f})}),V.post("/kill/:terminalId",($)=>{let f=$.req.param("terminalId"),Q=r.get(f);if(Q){try{Q.process.kill()}catch{}for(let O of Q.subscribers)O.close();return r.delete(f),$.json({success:!0})}return $.json({success:!1,error:"Terminal not found"},404)}),Kf)V.get("/ws",Kf(($)=>{let f=$.req.query("cwd")||$.get("directory")||U(),Q;return{async onOpen(O,J){try{Q=await vf(f,{send:(M)=>J.send(M),close:()=>J.close()})}catch(M){w.error("[Terminal] Failed to spawn PTY:",M),J.close()}},onMessage(O){if(!Q)return;try{Q.session.process.write(String(O.data))}catch(J){w.error("[Terminal] Failed to write to PTY:",J)}},onClose(){Q?.cleanup()}}}));else V.get("/ws",($)=>{return $.json({message:"WebSocket endpoint - connect via ws:// protocol",hint:"Use WebSocket client to connect to this endpoint"})});return V};var A=x("Service"),Gf=[];function k0(){let V=b0(L0(import.meta.url)),$=[S(V,"web"),S(U(),"dist/web"),S(U(),"packages/cli/dist/web")];for(let f of $){let Q=S(f,"index.html");if(rf(Q)){if(Of(Q,"utf-8").includes("/assets/"))return A.debug(`[Server] Found web dist at: ${f}`),f}}return null}function S0(){let V=new C0;V.onError((f,Q)=>{if(A.error("[Server] Request error:",f),f instanceof c)return Q.json(f.toObject(),f.statusCode);let O=f instanceof Error?f.message:String(f);return Q.json({error:{code:"INTERNAL_ERROR",message:O}},500)}),V.use(async(f,Q)=>{let O=process.env.BLADE_SERVER_PASSWORD;if(!O)return Q();let J=f.req.path;if(J==="/"||J.startsWith("/assets/")||J.endsWith(".html")||J.endsWith(".js")||J.endsWith(".css"))return Q();let M=f.req.header("Authorization");if(!M?.startsWith("Basic "))return f.header("WWW-Authenticate",'Basic realm="Blade Server"'),f.json({error:{code:"UNAUTHORIZED",message:"Authentication required"}},401);let Y=Buffer.from(M.slice(6),"base64").toString(),[j,Z]=Y.split(":"),K=process.env.BLADE_SERVER_USERNAME??"blade";if(j!==K||Z!==O)return f.json({error:{code:"UNAUTHORIZED",message:"Invalid credentials"}},401);return Q()}),V.use(async(f,Q)=>{let O=f.req.path==="/health"||f.req.path==="/global/health"||f.req.path.startsWith("/assets/");if(!O)A.debug(`[Server] ${f.req.method} ${f.req.path}`);let J=Date.now();if(await Q(),!O){let M=Date.now()-J;A.debug(`[Server] ${f.req.method} ${f.req.path} - ${f.res.status} (${M}ms)`)}}),V.use(_0({origin(f){if(!f)return;if(f.startsWith("http://localhost:"))return f;if(f.startsWith("http://127.0.0.1:"))return f;if(f==="tauri://localhost"||f==="http://tauri.localhost")return f;if(Gf.includes(f))return f;return}})),V.use(async(f,Q)=>{let O=f.req.query("directory")||f.req.header("x-blade-directory")||U();try{O=decodeURIComponent(O)}catch{}return f.set("directory",O),Q()}),V.route("/global",Xf()),V.route("/sessions",Hf()),V.route("/configs",Nf()),V.route("/permissions",yf()),V.route("/providers",Df()),V.route("/models",Uf()),V.route("/suggestions",Sf()),V.route("/terminal",gf()),V.route("/mcp",Ef()),V.route("/skills",Lf()),V.get("/health",(f)=>{return f.json({healthy:!0,version:p()})});let $=k0();if($)A.info(`[Server] Serving static files from ${$}`),V.get("/assets/*",(f)=>{let Q=S($,f.req.path);if(!rf(Q))return f.json({error:{code:"NOT_FOUND",message:`File not found: ${f.req.path}`}},404);let O=Of(Q),J=w0(Q).toLowerCase(),Y={".js":"application/javascript",".css":"text/css",".html":"text/html",".json":"application/json",".png":"image/png",".jpg":"image/jpeg",".jpeg":"image/jpeg",".gif":"image/gif",".svg":"image/svg+xml",".ico":"image/x-icon",".woff":"font/woff",".woff2":"font/woff2",".ttf":"font/ttf",".eot":"application/vnd.ms-fontobject"}[J]||"application/octet-stream";return new Response(O,{headers:{"Content-Type":Y,"Cache-Control":"public, max-age=31536000, immutable"}})}),V.get("/",(f)=>{let Q=S($,"index.html"),O=Of(Q,"utf-8");return f.html(O)}),V.get("*",(f)=>{let Q=f.req.path;if(Q.includes("."))return f.json({error:{code:"NOT_FOUND",message:`File not found: ${Q}`}},404);let O=S($,"index.html"),J=Of(O,"utf-8");return f.html(J)});else A.warn('[Server] Web UI not found. Run "cd packages/cli/web && bun run build" to enable web interface.'),V.get("/",(f)=>{return f.json({message:"Blade API Server",version:p(),webUI:!1,hint:'Web UI not built. Run "cd packages/cli/web && bun run build" to enable.',endpoints:{health:"/health",sessions:"/sessions",configs:"/configs",permissions:"/permissions",providers:"/providers"}})}),V.all("*",(f)=>{return f.json({error:{code:"NOT_FOUND",message:`Route not found: ${f.req.path}`}},404)});return V}function h0(){let V=D0(),$=[];for(let f of Object.keys(V)){let Q=V[f];if(!Q)continue;for(let O of Q){if(O.internal||O.family!=="IPv4")continue;if(O.address.startsWith("172."))continue;$.push(O.address)}}return $}function of(){return typeof globalThis.Bun<"u"}function df(V,$){let f=globalThis.Bun,Q=(J)=>{try{return f.serve({hostname:$.hostname,port:J,fetch:V.fetch,idleTimeout:0,websocket:jf})}catch(M){A.error("Failed to start Bun server:",M);return}},O=$.port===0?Q(4096)??Q(0):Q($.port);if(!O)throw Error(`Failed to start Bun server on port ${$.port}`);return{url:O.url,port:O.port,hostname:O.hostname,stop:async()=>{O.stop(!0)}}}function I0(V,$){return new Promise((f,Q)=>{let O=z0(async(Z,K)=>{let N=new URL(Z.url||"/",`http://${Z.headers.host}`),E=new Headers;for(let[F,G]of Object.entries(Z.headers))if(G)if(Array.isArray(G))for(let q of G)E.append(F,q);else E.set(F,G);let X;if(Z.method!=="GET"&&Z.method!=="HEAD")X=(await new Promise((G)=>{let q=[];Z.on("data",(L)=>q.push(L)),Z.on("end",()=>G(Buffer.concat(q)))})).toString();let R=new Request(N.toString(),{method:Z.method,headers:E,body:X});try{let F=await V.fetch(R);if(K.statusCode=F.status,F.headers.forEach((G,q)=>{K.setHeader(q,G)}),F.body){let G=F.body.getReader(),q=async()=>{let{done:L,value:_}=await G.read();if(L){K.end();return}return K.write(_),q()};await q()}else{let G=await F.text();K.end(G)}}catch(F){A.error("[Server] Node request error:",F),K.statusCode=500,K.end(JSON.stringify({error:{code:"INTERNAL_ERROR",message:"Internal server error"}}))}}),J=new P0({noServer:!0}),M=U();pf(J,()=>M),O.on("upgrade",(Z,K,N)=>{if(new URL(Z.url||"/",`http://${Z.headers.host}`).pathname==="/terminal/ws")J.handleUpgrade(Z,K,N,(X)=>{J.emit("connection",X,Z)});else K.destroy()});let Y=(Z)=>{return new Promise((K,N)=>{O.once("error",(E)=>{if(E.code==="EADDRINUSE")N(E);else N(E)}),O.listen(Z,$.hostname,()=>{let E=O.address();if(E&&typeof E==="object")K(E.port);else K(Z)})})};(async()=>{let Z;if($.port===0)try{Z=await Y(4096)}catch{Z=await Y(0)}else Z=await Y($.port);let K=new URL(`http://${$.hostname==="0.0.0.0"?"localhost":$.hostname}:${Z}`);f({url:K,port:Z,hostname:$.hostname,stop:async()=>{return new Promise((N)=>{J.close(()=>{O.close(()=>N())})})}})})().catch(Q)})}var lf;((DV)=>{let V,$;function f(){if(!$)$=S0();return $}DV.getApp=f;function Q(M){Gf=M.cors??[];let Y=f();if(of())V=df(Y,M),A.info(`[Server] Blade server listening on ${V.url} (Bun runtime)`);else throw Error("Blade web server requires Bun runtime. Please run with Bun: `bun run blade web` or install Bun from https://bun.sh");let j=V;return{url:j.url,port:j.port,hostname:j.hostname,stop:async()=>{if(V)await V.stop(),V=void 0,$=void 0,A.info("[Server] Blade server stopped")}}}DV.listen=Q;async function O(M){Gf=M.cors??[];let Y=f();if(of())V=df(Y,M),A.info(`[Server] Blade server listening on ${V.url} (Bun runtime)`);else V=await I0(Y,M),A.info(`[Server] Blade server listening on ${V.url} (Node.js runtime)`);let j=V;return{url:j.url,port:j.port,hostname:j.hostname,stop:async()=>{if(V)await V.stop(),V=void 0,$=void 0,A.info("[Server] Blade server stopped")}}}DV.listenAsync=O;function J(){return V!==void 0}DV.isRunning=J})(lf||={});export{u0 as f,v0 as g,h0 as h,lf as i};
|