yichus 0.3.3 → 0.3.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/README.md CHANGED
@@ -6,7 +6,7 @@ shipped in `@yichus/api-mcp`; installing the release requires Node 20+,
6
6
  without Java, sbt, Nix, or a browser.
7
7
 
8
8
  ```sh
9
- npm install --save-dev yichus@0.3.3
9
+ npm install --save-dev yichus@0.3.4
10
10
  npx yichus tools
11
11
  npx yichus call api_guide
12
12
  ```
@@ -29,7 +29,7 @@ and the studio tells the agent what to do next after every change:
29
29
  ```json
30
30
  {
31
31
  "mcpServers": {
32
- "yichus": { "command": "npx", "args": ["-y", "yichus@0.3.3", "studio"] }
32
+ "yichus": { "command": "npx", "args": ["-y", "yichus@0.3.4", "studio"] }
33
33
  }
34
34
  }
35
35
  ```
package/dist/cli.js CHANGED
@@ -6,6 +6,7 @@ var engines = {
6
6
  };
7
7
 
8
8
  // src/node-version.ts
9
+ import { createInterface } from "readline";
9
10
  function nodeVersionProblem(running, required) {
10
11
  const floor = /^>=(\d+)$/.exec(required);
11
12
  if (!floor) throw new Error(`engines.node must read >=N, not ${required}`);
@@ -13,13 +14,39 @@ function nodeVersionProblem(running, required) {
13
14
  if (Number(running.split(".")[0]) >= needed) return void 0;
14
15
  return `yichus needs Node ${needed} or newer; this is Node ${running}. Install Node ${needed} or newer and run the command again.`;
15
16
  }
17
+ async function refuseFirstRequest(problem2, input, output) {
18
+ for await (const line of createInterface({ input, crlfDelay: Infinity })) {
19
+ const id = requestId(line);
20
+ if (id === void 0) continue;
21
+ output.write(`${JSON.stringify({ jsonrpc: "2.0", id, error: { code: -32e3, message: problem2 } })}
22
+ `);
23
+ return;
24
+ }
25
+ }
26
+ function requestId(line) {
27
+ let message;
28
+ try {
29
+ message = JSON.parse(line);
30
+ } catch {
31
+ return void 0;
32
+ }
33
+ if (typeof message !== "object" || message === null || !("method" in message) || !("id" in message)) return void 0;
34
+ const { id } = message;
35
+ return typeof id === "string" || typeof id === "number" ? id : void 0;
36
+ }
16
37
 
17
38
  // src/cli.ts
39
+ var argv = process.argv.slice(2);
40
+ var servesMcp = argv[0] === "studio" && !argv.includes("--page");
18
41
  var problem = nodeVersionProblem(process.versions.node, engines.node);
19
42
  if (problem) {
20
43
  process.stderr.write(`${problem}
21
44
  `);
22
45
  process.exitCode = 1;
46
+ if (servesMcp && !process.stdin.isTTY) {
47
+ await refuseFirstRequest(problem, process.stdin, process.stdout);
48
+ process.stdin.destroy();
49
+ }
23
50
  } else {
24
51
  await import("./main.js");
25
52
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../package.json","../src/node-version.ts","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"yichus\",\n \"version\": \"0.3.3\",\n \"description\": \"Local Bosatsu compilation, Yichus analysis, and generated apps using the WebMCP engine\",\n \"license\": \"MIT\",\n \"homepage\": \"https://yich.us\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/snoble/yichus.git\",\n \"directory\": \"packages/yichus-cli\"\n },\n \"type\": \"module\",\n \"bin\": {\n \"yichus\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsup && node ./scripts/copy-studio-assets.mjs\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --coverage\",\n \"prepack\": \"npm run build\"\n },\n \"dependencies\": {\n \"@yichus/api-mcp\": \"workspace:*\",\n \"zod\": \"^4.3.6\",\n \"@modelcontextprotocol/sdk\": \"^1.26.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^22.0.0\",\n \"tsup\": \"^8.3.0\",\n \"typescript\": \"^5.6.0\",\n \"vitest\": \"^2.1.0\",\n \"@vitest/coverage-v8\": \"2.1.9\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","/**\n * The sentence that stops the command on a Node older than the package's\n * `engines.node` floor, or undefined when the running Node meets it.\n */\nexport function nodeVersionProblem(running: string, required: string): string | undefined {\n const floor = /^>=(\\d+)$/.exec(required);\n if (!floor) throw new Error(`engines.node must read >=N, not ${required}`);\n const needed = Number(floor[1]);\n if (Number(running.split('.')[0]) >= needed) return undefined;\n return `yichus needs Node ${needed} or newer; this is Node ${running}. Install Node ${needed} or newer and run the command again.`;\n}\n","#!/usr/bin/env node\n// The Node check runs before the rest of the command loads, so an older\n// Node gets a sentence naming what to install rather than an error from\n// inside the engine.\nimport { engines } from '../package.json';\nimport { nodeVersionProblem } from './node-version.js';\n\nconst problem = nodeVersionProblem(process.versions.node, engines.node);\nif (problem) {\n process.stderr.write(`${problem}\\n`);\n process.exitCode = 1;\n} else {\n await import('./main.js');\n}\n"],"mappings":";;;AAqCE,cAAW;AAAA,EACT,MAAQ;AACV;;;ACnCK,SAAS,mBAAmB,SAAiB,UAAsC;AACxF,QAAM,QAAQ,YAAY,KAAK,QAAQ;AACvC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,mCAAmC,QAAQ,EAAE;AACzE,QAAM,SAAS,OAAO,MAAM,CAAC,CAAC;AAC9B,MAAI,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,OAAQ,QAAO;AACpD,SAAO,qBAAqB,MAAM,2BAA2B,OAAO,kBAAkB,MAAM;AAC9F;;;ACHA,IAAM,UAAU,mBAAmB,QAAQ,SAAS,MAAM,QAAQ,IAAI;AACtE,IAAI,SAAS;AACX,UAAQ,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AACnC,UAAQ,WAAW;AACrB,OAAO;AACL,QAAM,OAAO,WAAW;AAC1B;","names":[]}
1
+ {"version":3,"sources":["../package.json","../src/node-version.ts","../src/cli.ts"],"sourcesContent":["{\n \"name\": \"yichus\",\n \"version\": \"0.3.4\",\n \"description\": \"Local Bosatsu compilation, Yichus analysis, and generated apps using the WebMCP engine\",\n \"license\": \"MIT\",\n \"homepage\": \"https://yich.us\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/snoble/yichus.git\",\n \"directory\": \"packages/yichus-cli\"\n },\n \"type\": \"module\",\n \"bin\": {\n \"yichus\": \"./dist/cli.js\"\n },\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"scripts\": {\n \"build\": \"tsup && node ./scripts/copy-studio-assets.mjs\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run --coverage\",\n \"prepack\": \"npm run build\"\n },\n \"dependencies\": {\n \"@yichus/api-mcp\": \"workspace:*\",\n \"zod\": \"^4.3.6\",\n \"@modelcontextprotocol/sdk\": \"^1.26.0\"\n },\n \"devDependencies\": {\n \"@types/node\": \"^22.0.0\",\n \"tsup\": \"^8.3.0\",\n \"typescript\": \"^5.6.0\",\n \"vitest\": \"^2.1.0\",\n \"@vitest/coverage-v8\": \"2.1.9\"\n },\n \"engines\": {\n \"node\": \">=20\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","import { createInterface } from 'node:readline';\nimport type { Readable, Writable } from 'node:stream';\n\n/**\n * The sentence that stops the command on a Node older than the package's\n * `engines.node` floor, or undefined when the running Node meets it.\n */\nexport function nodeVersionProblem(running: string, required: string): string | undefined {\n const floor = /^>=(\\d+)$/.exec(required);\n if (!floor) throw new Error(`engines.node must read >=N, not ${required}`);\n const needed = Number(floor[1]);\n if (Number(running.split('.')[0]) >= needed) return undefined;\n return `yichus needs Node ${needed} or newer; this is Node ${running}. Install Node ${needed} or newer and run the command again.`;\n}\n\n/**\n * Answers the first JSON-RPC request on `input` with `problem` as its error,\n * so an agent host that started `yichus studio` shows the person why the\n * server stopped instead of a server that died without a word. Lines that\n * are not requests (notifications, anything unreadable) get no answer.\n */\nexport async function refuseFirstRequest(problem: string, input: Readable, output: Writable): Promise<void> {\n for await (const line of createInterface({ input, crlfDelay: Infinity })) {\n const id = requestId(line);\n if (id === undefined) continue;\n output.write(`${JSON.stringify({ jsonrpc: '2.0', id, error: { code: -32000, message: problem } })}\\n`);\n return;\n }\n}\n\nfunction requestId(line: string): string | number | undefined {\n let message: unknown;\n try { message = JSON.parse(line); } catch { return undefined; }\n if (typeof message !== 'object' || message === null || !('method' in message) || !('id' in message)) return undefined;\n const { id } = message;\n return typeof id === 'string' || typeof id === 'number' ? id : undefined;\n}\n","#!/usr/bin/env node\n// The Node check runs before the rest of the command loads, so an older\n// Node gets a sentence naming what to install rather than an error from\n// inside the engine. `yichus studio` also says it to the agent host that\n// started it, as the answer to its first request.\nimport { engines } from '../package.json';\nimport { nodeVersionProblem, refuseFirstRequest } from './node-version.js';\n\nconst argv = process.argv.slice(2);\nconst servesMcp = argv[0] === 'studio' && !argv.includes('--page');\n\nconst problem = nodeVersionProblem(process.versions.node, engines.node);\nif (problem) {\n process.stderr.write(`${problem}\\n`);\n process.exitCode = 1;\n if (servesMcp && !process.stdin.isTTY) {\n await refuseFirstRequest(problem, process.stdin, process.stdout);\n process.stdin.destroy();\n }\n} else {\n await import('./main.js');\n}\n"],"mappings":";;;AAqCE,cAAW;AAAA,EACT,MAAQ;AACV;;;ACvCF,SAAS,uBAAuB;AAOzB,SAAS,mBAAmB,SAAiB,UAAsC;AACxF,QAAM,QAAQ,YAAY,KAAK,QAAQ;AACvC,MAAI,CAAC,MAAO,OAAM,IAAI,MAAM,mCAAmC,QAAQ,EAAE;AACzE,QAAM,SAAS,OAAO,MAAM,CAAC,CAAC;AAC9B,MAAI,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC,KAAK,OAAQ,QAAO;AACpD,SAAO,qBAAqB,MAAM,2BAA2B,OAAO,kBAAkB,MAAM;AAC9F;AAQA,eAAsB,mBAAmBA,UAAiB,OAAiB,QAAiC;AAC1G,mBAAiB,QAAQ,gBAAgB,EAAE,OAAO,WAAW,SAAS,CAAC,GAAG;AACxE,UAAM,KAAK,UAAU,IAAI;AACzB,QAAI,OAAO,OAAW;AACtB,WAAO,MAAM,GAAG,KAAK,UAAU,EAAE,SAAS,OAAO,IAAI,OAAO,EAAE,MAAM,OAAQ,SAASA,SAAQ,EAAE,CAAC,CAAC;AAAA,CAAI;AACrG;AAAA,EACF;AACF;AAEA,SAAS,UAAU,MAA2C;AAC5D,MAAI;AACJ,MAAI;AAAE,cAAU,KAAK,MAAM,IAAI;AAAA,EAAG,QAAQ;AAAE,WAAO;AAAA,EAAW;AAC9D,MAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,EAAE,YAAY,YAAY,EAAE,QAAQ,SAAU,QAAO;AAC5G,QAAM,EAAE,GAAG,IAAI;AACf,SAAO,OAAO,OAAO,YAAY,OAAO,OAAO,WAAW,KAAK;AACjE;;;AC5BA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AACjC,IAAM,YAAY,KAAK,CAAC,MAAM,YAAY,CAAC,KAAK,SAAS,QAAQ;AAEjE,IAAM,UAAU,mBAAmB,QAAQ,SAAS,MAAM,QAAQ,IAAI;AACtE,IAAI,SAAS;AACX,UAAQ,OAAO,MAAM,GAAG,OAAO;AAAA,CAAI;AACnC,UAAQ,WAAW;AACnB,MAAI,aAAa,CAAC,QAAQ,MAAM,OAAO;AACrC,UAAM,mBAAmB,SAAS,QAAQ,OAAO,QAAQ,MAAM;AAC/D,YAAQ,MAAM,QAAQ;AAAA,EACxB;AACF,OAAO;AACL,QAAM,OAAO,WAAW;AAC1B;","names":["problem"]}