@langbase/cli
Version:
Langbase CLI
23 lines (21 loc) • 16.4 kB
JavaScript
import he from"path";import ge from"fs/promises";async function E(){let e=[".env",".env.local",".dev.vars"];for(let o of e)try{let t=he.join(process.cwd(),o);return await ge.access(t),o}catch{continue}return null}import h from"picocolors";function m({text:e,sub:o,dim:t,green:r}){return r?`${h.bgGreen(h.black(` ${e} `))} ${o&&o}`:t?`${h.bgBlack(h.white(` ${e} `))} ${o&&o}`:`${h.bold(h.bgCyan(h.black(` ${e} `)))} ${o&&o}`}import*as _ from"@clack/prompts";import{cancel as O,confirm as W,isCancel as K,note as ye,outro as T,password as we}from"@clack/prompts";import $ from"fs/promises";import xe from"open";import I from"path";import S from"picocolors";async function z(){var i;_.intro(m({text:"Langbase Authentication",sub:"Auth by logging in to Langbase and getting your API key"}));let e=await W({message:`Open the authentication page? ${S.dim("\u2014 copy your API key from there and paste it here.")}`});K(e)&&(O("Operation cancelled."),process.exit(0)),e&&(await xe("https://langbase.com/settings/api"),ye(S.yellow("Please copy your API key from the opened page and paste it here.")));let o=await we({message:"Paste your API key string:",mask:"*"});K(o)&&(O("Operation cancelled."),process.exit(0));let[t,r]=o.split(":");(!t||!r)&&(T(S.red("Invalid API key string. It should be in the format login:apiKey, when copied from https://langbase.com/settings/api it should be in the correct format.")),process.exit(1));let s=`
# Langbase API key for https://langbase.com/${t}
LANGBASE_API_KEY=${r}
`,a=await E();if(!a)a=".env",await $.writeFile(I.join(process.cwd(),a),s);else{let l=await $.readFile(a,"utf-8"),y=(i=l.split(`
`).reverse().find(p=>p.includes("LANGBASE_API_KEY")))==null?void 0:i.split("=")[1];if(y){let p=await W({message:`API key found in ${a}. Overwrite?`});K(p)&&(O("Operation cancelled."),process.exit(0)),p||(T(S.yellow("API key is not overwritten.")),process.exit(0));let d=l.replace(new RegExp(`LANGBASE_API_KEY=${y}`),s.trim());await $.writeFile(I.join(process.cwd(),a),d)}else await $.appendFile(I.join(process.cwd(),a),s)}T(S.green(`Authentication successful. API key is stored in ${a}`)),process.exit(0)}import L from"fs/promises";import N from"path";import be from"esbuild";function J(e){return`import api from '${e}';
export default {
fetch(request, env) {
return api(request, env);
}
}`}import*as G from"@clack/prompts";async function F({spinner:e,filePath:o}){e.start("Building code...");let t=process.cwd(),r=N.join(t,o),n=N.join(t,"dist"),a=o.endsWith(".ts")?"langbase.ts":"langbase.js";try{await L.access(n)}catch{await L.mkdir(n,{recursive:!0})}try{let i=J(r),l=N.join(n,a);return await L.writeFile(l,i),await be.build({entryPoints:[l],bundle:!0,outfile:"dist/langbase.build.js",platform:"browser",target:"es2020",format:"esm",minify:!0,sourcemap:!1}),e.stop("Code built successfully"),{distPath:n}}catch(i){e.stop("Failed to build code"),G.cancel(`Error building code: ${i}`),process.exit(1)}}import ve from"figures";import c from"picocolors";var H={info:c.cyan,success:c.green,warning:c.yellow,error:c.red,green:c.green,red:c.red,yellow:c.yellow,cyan:c.cyan,blue:c.blue,magenta:c.magenta,white:c.white,gray:c.gray,dim:c.dim,bold:c.bold};var ht=c.dim,gt=c.bold,yt=c.underline,wt=c.italic,xt=c.inverse,bt=c.hidden,vt=c.strikethrough,St=c.reset,Pt=c.black,kt=c.red,At=c.green,Dt=c.yellow,Et=c.blue,$t=c.magenta,j=c.cyan,Ft=c.white,Mt=c.gray;var Ot=c.dim(`${ve.lineUpDownRight} `);import*as Y from"@clack/prompts";function M({spinner:e,message:o,error:t}){e.stop(o),Y.log.error(`${o}: ${t.message}`),process.exit(1)}import{z as g}from"zod";var Q=g.object({isDev:g.boolean().optional().default(!1),agent:g.string().trim().min(1).refine(e=>!!/^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}\/[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$/i.test(e),{message:"Invalid agent name. Ensure the agent name is in the format: owner/agent"}),filePath:g.string().trim().min(1).refine(e=>e.endsWith(".js")||e.endsWith(".ts"),{message:"Only JavaScript and TypeScript files are supported"}),apiKey:g.string().min(1).optional()}),V=g.object({filePath:g.string().trim().min(1).refine(e=>e.endsWith(".js")||e.endsWith(".ts"),{message:"Only JavaScript and TypeScript files are supported"})});import*as w from"@clack/prompts";import{outro as Se}from"@clack/prompts";async function X(e){let o=w.spinner();try{w.intro(m({text:"BUILD",sub:"Building code"}));let t=Pe(e),{distPath:r}=await F({spinner:o,filePath:t.filePath});Se(H.green(`Built code is stored in ${r}/langbase.build.js`))}catch(t){M({spinner:o,message:"An unexpected error occurred",error:t})}}function Pe(e){let{data:o,success:t,error:r}=V.safeParse(e);if(!t){let s=r.errors.map(a=>a.message).join(". ");w.cancel(`Invalid options: ${s}`),process.exit(1)}return{filePath:o.filePath}}function Z(e){return e?"http://localhost:8787":"https://api.langbase.com"}import Ae from"fs/promises";import oe from"path";import*as u from"@clack/prompts";import ke from"fs/promises";import*as P from"@clack/prompts";function ee({spinner:e}){e.stop("No account found"),P.outro(`Skipping deployment.
Run: ${j("npx lb auth")} to authenticate.`)}async function te({spinner:e}){var o;e.start("Retrieving stored authentication");try{let t=await E();t||(ee({spinner:e}),process.exit(1)),t=`${process.cwd()}/${t}`;let n=(o=(await ke.readFile(t,"utf-8")).split(`
`).reverse().find(s=>s.includes("LANGBASE_API_KEY=")))==null?void 0:o.split("=")[1];return n||(ee({spinner:e}),process.exit(1)),e.stop("Retrieved stored authentication"),n}catch(t){e.stop("Failed to retrieve authentication"),P.log.error(`Error retrieving stored auth: ${t.message}`),P.outro(`Skipping deployment.
Run: ${j("npx lb auth")} to authenticate.`),process.exit(1)}}import B from"@sindresorhus/slugify";async function re(e){let o=u.spinner();try{u.intro(m({text:"DEPLOY",sub:"Deploying to Langbase"}));let t=Ee(e),{distPath:r}=await F({spinner:o,filePath:t.filePath});await De({...t,distPath:r,spinner:o})}catch(t){M({spinner:o,message:"An unexpected error occurred",error:t})}}async function De({isDev:e,distPath:o,owner:t,agent:r,filePath:n,spinner:s,apiKey:a}){try{let i=oe.basename(n).split(".")[0],l=B(i),y=await $e({isDev:e,agent:r,owner:t,scriptName:l}),{body:p,apiKey:d}=await Fe({distPath:o,spinner:s,lbApiKey:a,scriptName:l});console.log("apiKey",d),console.log("body",p),await Me({body:p,apiKey:d,spinner:s,endpoint:y})}catch(i){u.cancel(`Error deploying code: ${i}`),process.exit(1)}}function Ee(e){let{data:o,success:t,error:r}=Q.safeParse(e);if(!t){let i=r.errors.map(l=>l.message).join(". ");u.cancel(`Invalid options: ${i}`),process.exit(1)}let[n,s]=o.agent.split("/");return{owner:n,agent:s,isDev:o.isDev,apiKey:o.apiKey,filePath:o.filePath}}async function $e({isDev:e,agent:o,owner:t,scriptName:r}){let n=Z(e),s=B(o),a=B(r);return`${n}/v1/${t}/${s}/${a}/deploy`}async function Fe({spinner:e,distPath:o,scriptName:t,lbApiKey:r}){let n=oe.join(o,"langbase.build.js"),s=await Ae.readFile(n,"utf-8"),a=new FormData;a.append("script",new Blob([s],{type:"application/javascript"}),t);let i=r;return i||(i=await te({spinner:e})),{body:a,apiKey:i}}async function Me({body:e,apiKey:o,spinner:t,endpoint:r}){t.start("Deploying code...");try{let n=await fetch(r,{method:"POST",body:e,headers:{Authorization:`Bearer ${o}`}});if(!n.ok){let a=await n.json();t.stop("Error deploying code"),u.outro(`Error deploying code: ${a.error.message}`),process.exit(1)}(await n.json()).success&&t.stop("Code deployed successfully")}catch(n){u.cancel(`Error deploying code: ${n}`),process.exit(1)}}import{McpServer as Te}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as Ie}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as x}from"zod";import{JSDOM as Oe}from"jsdom";async function ne(){try{let e=await fetch("https://langbase.com/docs/llms.txt");if(!e.ok)throw new Error("Failed to fetch docs");return await e.text()}catch(e){throw new Error("Failed to fetch docs "+JSON.stringify(e))}}async function se(){try{let e=await fetch("https://langbase.com/docs/llms-sdk.txt");if(!e.ok)throw new Error("Failed to fetch docs");return await e.text()}catch(e){throw new Error("Failed to fetch docs "+JSON.stringify(e))}}async function k(e){var o;try{let t=await fetch(e);if(!t.ok)throw new Error("Failed to fetch blog post");let r=await t.text(),s=new Oe(r).window.document;s.querySelectorAll("script").forEach(l=>l.remove());let i=((o=s.body.textContent)==null?void 0:o.trim())||"";if(!i)throw new Error("No content found in docs");return i}catch(t){throw console.error("Error fetching docs:",t),new Error(`Failed to fetch docs: ${t instanceof Error?t.message:"Something went wrong. Please try again."}`)}}var R=(e,o,t)=>{if(!e||!o)return 0;let r=e.toLowerCase(),n=o.toLowerCase().trim();if(n.length===0)return 0;let s=0;r.includes(n)&&(s+=10);let i=n.split(/\s+/).filter(p=>p.length>0),l=[];for(let p of i){if(p.length<2)continue;if(r.includes(p)){t?s+=5:s+=1;let f=r.indexOf(p);f>=0&&l.push(f)}else if(p.length>=3)for(let f of r.split(/\s+/)){let ue=f.length>=3,fe=f.includes(p)||p.includes(f);if(ue&&fe){t?s+=2.5:s+=.5;break}}}return l.length>1&&(l.sort((d,D)=>d-D),l[l.length-1]-l[0]<50&&(s+=2)),s},ie=e=>{let o={title:"",url:""},t=e.match(/<metadata>([\s\S]*?)<\/metadata>/i);if(t&&t[1]){let n=t[1],s=/<title>([\s\S]*?)<\/title>/i.exec(n);s&&s[1]&&(o.title=s[1].trim());let i=/<url>([\s\S]*?)<\/url>/i.exec(n);i&&i[1]&&(o.url=i[1].trim())}return o},ae=e=>{let o=/<doc>[\s\S]*?<\/doc>/g;return e.match(o)||[]};var C=(e,o)=>{var s;let t=Ke(e,o,5);return t.length===0?"docs/sdk":(s=t[0].url)==null?void 0:s.split("/docs/")[1]},Ke=(e,o,t)=>ae(e).map(a=>{let i=ie(a),l=0;i.title!=""?l=R(i.title,o,!0):l=0;let p=/<content>([\s\S]*?)<\/content>/i.exec(a),d="";p?d=p[1].trim():d="";let D=R(d,o,!1);return{score:l+D,title:i.title||"Untitled Document",url:i.url||null}}).filter(a=>a.score>0).sort((a,i)=>i.score-a.score).slice(0,t);async function ce(){let e=new Te({name:"langbase-docs-server",version:"0.1.0"});e.tool("docs-route-finder","Searches through all available documentation routes and returns relevant paths based on the user's query. This tool helps navigate the documentation by finding the most appropriate sections that match the search criteria.",{query:x.string().describe(`A refined search term extracted from the user's question.
For example, if user asks 'How do I create a pipe?', the query would be 'SDK Pipe'.
This should be the specific concept or topic to search for in the documentation.
Treat keyword add as create if user ask for Eg. 'How do I add memory to pipe?' the query should be 'create memory'`)},async({query:t})=>{let r=await ne(),n=C(r,t);return n?{content:[{type:"text",text:`This is the most relevant documentation for the query: ${n}`}]}:{content:[{type:"text",text:"No relevant documentation found for the query: "+t}]}}),e.tool("sdk-route-finder","Searches through all available SDK documentation routes and returns relevant paths based on the user's query. This tool helps navigate the documentation by finding the most appropriate sections that match the search criteria.",{query:x.string().describe(`A refined search term extracted from the user's question.
For example, if user asks 'How do I create a pipe?', the query would be 'SDK Pipe'.
This should be the specific concept or topic to search for in the documentation.
Treat keyword add as create if user ask for Eg. 'How do I add memory to pipe?' the query should be 'create memory'`)},async({query:t})=>{let r=await se(),n=C(r,t);return n?{content:[{type:"text",text:`This is the most relevant documentation for the query: ${n}`}]}:{content:[{type:"text",text:"No relevant documentation found for the query: "+t}]}}),e.tool("sdk-docs-tool","Always First Use sdk-route-finder to find the most relevant documentation and then use this tool to fetch the detailed documentation.Fetches detailed SDK documentation, specializing in implementation guides for core features like pipes, memory, and tools. This is the primary source for the latest SDK documentation and should be consulted first for questions about creating or implementing SDK components. Use this tool for detailed step-by-step instructions on building pipes, configuring memory systems, and developing custom tools.",{url:x.string().describe("URL of a specific SDK page to fetch. Format: /sdk/...")},async({url:t})=>({content:[{type:"text",text:await k(`https://langbase.com/docs${t}`)}]})),e.tool("examples-tool","Always first use docs-route-finder to find the most relevant documentation and then use this tool to fetch the detailed documentation. Fetches code examples and sample implementations from the documentation. Use this tool when users specifically request examples, sample code, or implementation demonstrations. This tool provides practical code snippets and complete working examples that demonstrate how to implement various features.",{url:x.string().describe("URL of a specific examples page to fetch. Format: /examples/...")},async({url:t})=>({content:[{type:"text",text:await k(`https://langbase.com/docs${t}`)}]})),e.tool("guide-tool","Always first use docs-route-finder to find the most relevant documentation and then use this tool to fetch the detailed documentation. Fetches detailed guides and tutorials from the documentation. Use this tool when users explicitly request guides, tutorials, or how-to content. This tool provides step-by-step instructions and practical examples for implementing various features.",{url:x.string().describe("URL of a specific guide page to fetch. Format: /guides/...")},async({url:t})=>({content:[{type:"text",text:await k(`https://langbase.com/docs${t}`)}]})),e.tool("api-reference-tool","Always first use docs-route-finder to find the most relevant documentation and then use this tool to fetch the detailed documentation. Fetches API reference documentation. Use this tool ONLY when the user explicitly asks about API endpoints, REST API calls, or programmatically creating/updating/deleting resources (like pipes, memory, etc.) through the API interface. For general SDK implementation questions, use the sdk-documentation-fetcher instead.",{url:x.string().describe("URL of a specific api-reference page to fetch. Format: /api-reference/...")},async({url:t})=>({content:[{type:"text",text:await k(`https://langbase.com/docs${t}`)}]}));async function o(){let t=new Ie;try{await e.connect(t)}catch(r){console.error("Error connecting to transport:",r),process.exit(1)}}o().catch(t=>{console.error("Something went wrong:",t),process.exit(1)})}import Le from"cli-meow-help";import Ne from"meow";var le={clear:{type:"boolean",default:!1,desc:"Clear the console"},debug:{type:"boolean",default:!1,shortFlag:"d",desc:"Print debug info"}},je={"docs-mcp-server":{desc:"Start the Langbase docs MCP server"},help:{desc:"Print help info"}},Be=Le({name:"@langbase/cli",flags:le,commands:je,desc:!1,header:!1,footer:"Made by Langbase. For more https://langbase.com/docs"}),Re={importMeta:import.meta,inferType:!0,description:!1,hardRejection:!1,flags:le},q=Ne(Be,Re);import*as A from"@clack/prompts";function U(e){A.intro(m({text:"DEBUG MODE",sub:"logs will be verbose...",dim:!0})),console.log(),A.intro(m({text:"cwd",dim:!0})),console.log(process.cwd()),console.log(),A.intro(m({text:"cli.flags",dim:!0})),console.log(e.flags),console.log(),A.intro(m({text:"cli.input",sub:"commands",dim:!0})),console.log(e.input),console.log()}import Ce from"cli-handle-unhandled";import qe from"cli-welcome";import pe from"path";import{fileURLToPath as Ue}from"url";import de from"fs";var me=async({clear:e=!1})=>{Ce();let o=Ue(import.meta.url),t=pe.dirname(o),r=pe.join(t,"..","package.json");de.existsSync(r)||(console.error("Unable to find package.json"),process.exit(1));let n=JSON.parse(de.readFileSync(r,"utf8"));await qe({title:"cli",tagLine:"by Langbase",description:n.description,version:n.version,bgColor:"#A699EA",color:"#000000",bold:!0,clear:e})};var{flags:v,input:We,showHelp:_e}=q,{clear:ze,debug:Je}=v,b=e=>We.includes(e),Ge=e=>!!v[e];(async()=>{if(b("docs-mcp-server")||await me({clear:ze}),Je&&U(q),b("help")&&_e(0),b("auth")&&await z(),b("build")){let e=v.file;await X({filePath:e})}if(b("deploy")){let e=Ge("dev"),o=v.agent,t=v.file,r=v.key;await re({isDev:e,agent:o,filePath:t,apiKey:r})}b("docs-mcp-server")&&await ce()})();
//# sourceMappingURL=index.js.map