layrith 0.1.2 → 0.1.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.
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ const { spawnSync } = require("node:child_process");
3
+ const path = require("node:path");
4
+ const os = require("node:os");
5
+
6
+ const bunCmd = process.env.BUN_BINARY || "bun";
7
+ const cliPath = path.resolve(__dirname, "..", "layrith.js");
8
+ const env = {
9
+ ...process.env,
10
+ CLAUDE_CONFIG_DIR: process.env.CLAUDE_CONFIG_DIR || path.join(os.homedir(), ".layrith", "claude"),
11
+ };
12
+
13
+ const result = spawnSync(bunCmd, [cliPath, ...process.argv.slice(2)], {
14
+ stdio: "inherit",
15
+ env,
16
+ });
17
+
18
+ if (result.error) {
19
+ const reason = result.error.code === "ENOENT"
20
+ ? `Bun is required to run layrith. Install Bun from https://bun.sh and retry.`
21
+ : result.error.message;
22
+ console.error(`Failed to launch layrith via Bun: ${reason}`);
23
+ process.exit(1);
24
+ }
25
+
26
+ process.exit(result.status ?? 1);
package/layrith.js CHANGED
@@ -218,6 +218,6 @@ data: ${JSON.stringify({type:"message_delta",delta:{stop_reason:v==="tool_calls"
218
218
  data: {"type": "message_stop"}
219
219
 
220
220
  `),U.releaseLock(),D()}}});return new Response(C,{headers:{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}})}catch(B){return mF("Proxy error:",B),new Response(JSON.stringify({error:"Internal Proxy Error"}),{status:500,headers:{"Content-Type":"application/json"}})}return new Response("Not Found",{status:404})}})}var DQ;var j8=a(()=>{xG();DQ=process.env.LAYRITH_DEBUG_PROXY==="1"});var fQ={};import yQ from"os";import OQ from"path";function w8(){let I=qZ();if(I.runtime.provider==="openai-compatible"){if(!JB){if(JB=M8(),K8)console.error(`[PROXY] Started internal proxy on port ${JB.port}`)}process.env.ANTHROPIC_BASE_URL=`http://localhost:${JB.port}`,process.env.ANTHROPIC_API_KEY=I.runtime.apiKey||"dummy-key"}else if(I.runtime.provider==="anthropic-compatible")process.env.ANTHROPIC_API_KEY=I.runtime.apiKey}function vQ(){if(JB){if(JB.stop(),JB=void 0,K8)console.error("[PROXY] Stopped internal proxy.")}}function TQ(I,Z){return Z.push(I),Z}function qQ(I){return/^[a-zA-Z0-9_-]+$/.test(I)}function PQ(I){let Z={};for(let b of I){let G=b.indexOf("=");if(G<=0)throw Error(`Invalid env entry "${b}". Use KEY=VALUE.`);let B=b.slice(0,G).trim(),V=b.slice(G+1);if(!B)throw Error(`Invalid env entry "${b}". Use KEY=VALUE.`);Z[B]=V}return Z}function kQ(I,Z,b){let G=Z.trim().toLowerCase();if(!["npx","npx.cmd"].includes(G))return;if(b.some((V)=>!V.trim().startsWith("-")))return;throw Error(`The MCP server "${I}" is missing the package or command argument for npx. Example: layrith-cli mcp add ${I} npx -y @modelcontextprotocol/server-github`)}function XQ(){let I=RB();if(I.isConfigured)return!1;let Z=Hz(),b=Z.length>0?Z.join(", "):"No settings file detected yet.";return console.error(),console.error(OI.default.red("Missing required runtime configuration.")),console.error(OI.default.gray(`Missing: ${I.missing.join(", ")}`)),console.error(OI.default.gray(`Detected settings sources: ${b}`)),console.error(),console.error(OI.default.white("Set these before running `layrith-cli chat`:")),console.error(OI.default.gray("1. workspace file: .layrith/settings.json")),console.error(OI.default.gray(`2. user file: ${rZ()}`)),console.error(OI.default.gray("3. or env vars: LAYRITH_BASE_URL, LAYRITH_API_KEY, LAYRITH_MODEL")),console.error(),console.error(OI.default.white("Example `.layrith/settings.json`:")),console.error(OI.default.gray(["{",' "runtime": {',' "baseUrl": "http://localhost:20128/v1",',' "apiKey": "your-api-key",',' "model": "your-model-name"'," }","}"].join(`
221
- `))),console.error(),process.exitCode=1,!0}async function E8(){if(RB().isConfigured)return!0;if(process.stdin.isTTY&&process.stdout.isTTY){if(await cF()&&RB().isConfigured)return!0;return console.error(OI.default.yellow("Setup cancelled before runtime configuration was saved.")),process.exitCode=1,!1}return!XQ()}function xQ(){let I=FV();if(I.length===0)return;console.log();for(let Z of I)console.log(OI.default.yellow(`Warning: ${Z}`));console.log()}async function D8(I={}){if(!await E8())return;w8(),V8(I)}async function hQ(I){if(!await E8())return;w8();let Z=qZ(),b=gW({animateThinking:Z.ui.animateNonInteractiveThinking}),G=new B0;xQ(),b.renderUserInput(I);try{let B={continue:!1};await G.processUserInput(I,B,(V)=>b.renderEvent(V))}finally{b.dispose(),await rG(),vQ()}}async function lQ(){if(!process.stdin.isTTY||!process.stdout.isTTY){console.error(OI.default.red("Interactive login requires a TTY session.")),console.error(OI.default.gray(`Run this in a terminal to save credentials to ${rZ()}.`)),process.exitCode=1;return}if(!await cF()){console.error(OI.default.yellow("Login cancelled before runtime configuration was saved.")),process.exitCode=1;return}console.log(OI.default.green(`Saved runtime credentials to ${rZ()}.`))}async function _Q(){await Sz(),console.log(OI.default.green(`Removed saved runtime credentials from ${rZ()}.`)),console.log(OI.default.gray("Workspace-level .layrith/settings.json values, if any, can still override runtime config."))}async function J8(){try{let I=await VW();if(I.length===0){console.log(OI.default.yellow("No MCP servers configured yet.")),console.log(OI.default.gray("Use `layrith-cli mcp add <name> <command> [args...]` to register one."));return}console.log(OI.default.cyan("Configured MCP servers")),console.log();for(let Z of I){let b=!Z.enabled?OI.default.gray("disabled"):Z.connected?OI.default.green(`connected (${Z.toolCount} tool${Z.toolCount===1?"":"s"})`):OI.default.red("error");if(console.log(`${OI.default.white(Z.name)} ${OI.default.gray("-")} ${b}`),console.log(OI.default.gray(` command: ${[Z.command,...Z.args].join(" ")}`)),Z.cwd)console.log(OI.default.gray(` cwd: ${Z.cwd}`));if(Z.error)console.log(OI.default.red(` error: ${Z.error}`))}}finally{await rG()}}async function uQ(I,Z,b,G){if(!qQ(I))throw Error("MCP server name may only contain letters, numbers, hyphens, and underscores.");kQ(I,Z,b);let B={command:Z,args:b,env:PQ(G.env),cwd:G.cwd?.trim()||void 0,enabled:!G.disable};await Uz(I,B),await rG(),console.log(OI.default.green(`Saved MCP server "${I}".`)),console.log(OI.default.gray(`Command: ${[Z,...b].join(" ")}`)),console.log(OI.default.gray(`Config file: ${RV()}`))}async function cQ(I){let Z=await Az(I);if(await rG(),!Z){console.log(OI.default.yellow(`No MCP server named "${I}" was found.`));return}console.log(OI.default.green(`Removed MCP server "${I}".`))}async function mQ(I){try{let Z=await P9(I);if(Z.length===0){console.log(OI.default.yellow(I?`No tools found for MCP server "${I}".`:"No MCP tools available."));return}console.log(OI.default.cyan(I?`MCP tools for ${I}`:"Discovered MCP tools")),console.log();for(let b of Z)if(console.log(`${OI.default.white(b.qualifiedName)} ${OI.default.gray(`(${b.actualToolName})`)}`),console.log(OI.default.gray(` server: ${b.serverName}`)),b.description)console.log(OI.default.gray(` description: ${b.description}`))}finally{await rG()}}var OI,JB,K8,yB,zW;var y8=a(()=>{U5();Ig();xG();jF();W8();TF();Y8();j8();OI=wG(u0(),1);if(!process.env.CLAUDE_CONFIG_DIR)process.env.CLAUDE_CONFIG_DIR=OQ.join(yQ.homedir(),".layrith");K8=process.env.LAYRITH_DEBUG_PROXY==="1";yB=new S5;yB.name("layrith-cli").description("Natural language coding CLI").version("0.1.0").showHelpAfterError().argument("[prompt...]","Optional prompt to run immediately").action(async(I)=>{let Z=I?.join(" ").trim()??"";if(Z){await hQ(Z);return}await D8()});yB.addHelpText("after",`
221
+ `))),console.error(),process.exitCode=1,!0}async function E8(){if(RB().isConfigured)return!0;if(process.stdin.isTTY&&process.stdout.isTTY){if(await cF()&&RB().isConfigured)return!0;return console.error(OI.default.yellow("Setup cancelled before runtime configuration was saved.")),process.exitCode=1,!1}return!XQ()}function xQ(){let I=FV();if(I.length===0)return;console.log();for(let Z of I)console.log(OI.default.yellow(`Warning: ${Z}`));console.log()}async function D8(I={}){if(!await E8())return;w8(),V8(I)}async function hQ(I){if(!await E8())return;w8();let Z=qZ(),b=gW({animateThinking:Z.ui.animateNonInteractiveThinking}),G=new B0;xQ(),b.renderUserInput(I);try{let B={continue:!1};await G.processUserInput(I,B,(V)=>b.renderEvent(V))}finally{b.dispose(),await rG(),vQ()}}async function lQ(){if(!process.stdin.isTTY||!process.stdout.isTTY){console.error(OI.default.red("Interactive login requires a TTY session.")),console.error(OI.default.gray(`Run this in a terminal to save credentials to ${rZ()}.`)),process.exitCode=1;return}if(!await cF()){console.error(OI.default.yellow("Login cancelled before runtime configuration was saved.")),process.exitCode=1;return}console.log(OI.default.green(`Saved runtime credentials to ${rZ()}.`))}async function _Q(){await Sz(),console.log(OI.default.green(`Removed saved runtime credentials from ${rZ()}.`)),console.log(OI.default.gray("Workspace-level .layrith/settings.json values, if any, can still override runtime config."))}async function J8(){try{let I=await VW();if(I.length===0){console.log(OI.default.yellow("No MCP servers configured yet.")),console.log(OI.default.gray("Use `layrith-cli mcp add <name> <command> [args...]` to register one."));return}console.log(OI.default.cyan("Configured MCP servers")),console.log();for(let Z of I){let b=!Z.enabled?OI.default.gray("disabled"):Z.connected?OI.default.green(`connected (${Z.toolCount} tool${Z.toolCount===1?"":"s"})`):OI.default.red("error");if(console.log(`${OI.default.white(Z.name)} ${OI.default.gray("-")} ${b}`),console.log(OI.default.gray(` command: ${[Z.command,...Z.args].join(" ")}`)),Z.cwd)console.log(OI.default.gray(` cwd: ${Z.cwd}`));if(Z.error)console.log(OI.default.red(` error: ${Z.error}`))}}finally{await rG()}}async function uQ(I,Z,b,G){if(!qQ(I))throw Error("MCP server name may only contain letters, numbers, hyphens, and underscores.");kQ(I,Z,b);let B={command:Z,args:b,env:PQ(G.env),cwd:G.cwd?.trim()||void 0,enabled:!G.disable};await Uz(I,B),await rG(),console.log(OI.default.green(`Saved MCP server "${I}".`)),console.log(OI.default.gray(`Command: ${[Z,...b].join(" ")}`)),console.log(OI.default.gray(`Config file: ${RV()}`))}async function cQ(I){let Z=await Az(I);if(await rG(),!Z){console.log(OI.default.yellow(`No MCP server named "${I}" was found.`));return}console.log(OI.default.green(`Removed MCP server "${I}".`))}async function mQ(I){try{let Z=await P9(I);if(Z.length===0){console.log(OI.default.yellow(I?`No tools found for MCP server "${I}".`:"No MCP tools available."));return}console.log(OI.default.cyan(I?`MCP tools for ${I}`:"Discovered MCP tools")),console.log();for(let b of Z)if(console.log(`${OI.default.white(b.qualifiedName)} ${OI.default.gray(`(${b.actualToolName})`)}`),console.log(OI.default.gray(` server: ${b.serverName}`)),b.description)console.log(OI.default.gray(` description: ${b.description}`))}finally{await rG()}}var OI,JB,K8,yB,zW;var y8=a(()=>{U5();Ig();xG();jF();W8();TF();Y8();j8();OI=wG(u0(),1);if(!process.env.CLAUDE_CONFIG_DIR)process.env.CLAUDE_CONFIG_DIR=OQ.join(yQ.homedir(),".layrith","claude");K8=process.env.LAYRITH_DEBUG_PROXY==="1";yB=new S5;yB.name("layrith-cli").description("Natural language coding CLI").version("0.1.0").showHelpAfterError().argument("[prompt...]","Optional prompt to run immediately").action(async(I)=>{let Z=I?.join(" ").trim()??"";if(Z){await hQ(Z);return}await D8()});yB.addHelpText("after",`
222
222
  If no subcommand is specified, LAYRITH opens the interactive CLI.
223
- `);yB.command("chat").description("Start the interactive coding REPL").action(async()=>{await D8()});yB.command("login").description("Manage login").action(async()=>{await lQ()});yB.command("logout").description("Remove stored authentication credentials").action(async()=>{await _Q()});zW=yB.command("mcp").description("Manage external MCP servers for Layrith");zW.command("list").description("List configured MCP servers and connection status").action(async()=>{await J8()});zW.command("add").description("Add an MCP server that Layrith can discover tools from").argument("<name>","Logical name for the server").argument("<command>","Executable used to start the MCP server").argument("[args...]","Arguments passed to the executable").allowUnknownOption(!0).option("--cwd <dir>","Working directory for the server process").option("--env <key=value>","Environment variable for the server process (repeatable)",TQ,[]).option("--disable","Add the server in disabled mode").action(async(I,Z,b,G)=>{try{await uQ(I,Z,b??[],G)}catch(B){console.error(OI.default.red(B instanceof Error?B.message:String(B))),process.exitCode=1}});zW.command("remove").description("Remove a configured MCP server").argument("<name>","Logical server name").action(async(I)=>{await cQ(I)});zW.command("tools").description("List tools discovered from configured MCP servers").argument("[name]","Optional MCP server name").action(async(I)=>{try{await mQ(I)}catch(Z){console.error(OI.default.red(Z instanceof Error?Z.message:String(Z))),process.exitCode=1}});zW.action(async()=>{await J8()});yB.parseAsync()});import dQ from"os";import $Q from"path";process.env.CLAUDE_CONFIG_DIR=$Q.join(dQ.homedir(),".layrith");await Promise.resolve().then(() => (y8(),fQ));
223
+ `);yB.command("chat").description("Start the interactive coding REPL").action(async()=>{await D8()});yB.command("login").description("Manage login").action(async()=>{await lQ()});yB.command("logout").description("Remove stored authentication credentials").action(async()=>{await _Q()});zW=yB.command("mcp").description("Manage external MCP servers for Layrith");zW.command("list").description("List configured MCP servers and connection status").action(async()=>{await J8()});zW.command("add").description("Add an MCP server that Layrith can discover tools from").argument("<name>","Logical name for the server").argument("<command>","Executable used to start the MCP server").argument("[args...]","Arguments passed to the executable").allowUnknownOption(!0).option("--cwd <dir>","Working directory for the server process").option("--env <key=value>","Environment variable for the server process (repeatable)",TQ,[]).option("--disable","Add the server in disabled mode").action(async(I,Z,b,G)=>{try{await uQ(I,Z,b??[],G)}catch(B){console.error(OI.default.red(B instanceof Error?B.message:String(B))),process.exitCode=1}});zW.command("remove").description("Remove a configured MCP server").argument("<name>","Logical server name").action(async(I)=>{await cQ(I)});zW.command("tools").description("List tools discovered from configured MCP servers").argument("[name]","Optional MCP server name").action(async(I)=>{try{await mQ(I)}catch(Z){console.error(OI.default.red(Z instanceof Error?Z.message:String(Z))),process.exitCode=1}});zW.action(async()=>{await J8()});yB.parseAsync()});import dQ from"os";import $Q from"path";process.env.CLAUDE_CONFIG_DIR=$Q.join(dQ.homedir(),".layrith","claude");await Promise.resolve().then(() => (y8(),fQ));
package/package.json CHANGED
@@ -1,15 +1,16 @@
1
1
  {
2
2
  "name": "layrith",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "module": "layrith.js",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "bin": {
8
- "layrith": "layrith.js"
8
+ "layrith": "bin/layrith.cjs"
9
9
  },
10
10
  "license": "SEE LICENSE IN LICENSE",
11
11
  "files": [
12
12
  "layrith.js",
13
+ "bin/layrith.cjs",
13
14
  "README.md",
14
15
  "LICENSE"
15
16
  ],