@lotics/cli 0.45.0 → 0.45.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.
@@ -1,5 +1,6 @@
1
1
  import { describe, it, expect } from "vitest";
2
2
  import { dispatchRpc } from "./rpc_handler.js";
3
+ import { serializeRpcResult } from "./server.js";
3
4
  function mockClient(over) {
4
5
  return over;
5
6
  }
@@ -56,3 +57,12 @@ describe("dispatchRpc — comment ops", () => {
56
57
  await expect(dispatchRpc(client, { app_id: "app_x", op: "comments.counts", payload: {} })).rejects.toThrow(/table_id/);
57
58
  });
58
59
  });
60
+ describe("serializeRpcResult — every RPC response body is valid JSON", () => {
61
+ it("serializes a void result (comments.delete) as null, never an empty body", () => {
62
+ expect(serializeRpcResult(undefined)).toBe("null");
63
+ expect(JSON.parse(serializeRpcResult(undefined))).toBeNull();
64
+ });
65
+ it("passes object results through", () => {
66
+ expect(JSON.parse(serializeRpcResult({ comments: [] }))).toEqual({ comments: [] });
67
+ });
68
+ });
@@ -37,6 +37,15 @@ export interface DevServerHandle {
37
37
  /** Stops Vite + HTTP server. Safe to call multiple times. */
38
38
  stop: () => Promise<void>;
39
39
  }
40
+ /**
41
+ * Serialize an RPC result for the HTTP response body. Ops with no return
42
+ * value (e.g. comments.delete) resolve `undefined` — in production they
43
+ * travel over postMessage where undefined structured-clones fine, but
44
+ * `JSON.stringify(undefined)` is not a string, so the body would be EMPTY
45
+ * and the wrapper's `JSON.parse` throws "Unexpected end of JSON input".
46
+ * Serialize those as `null`.
47
+ */
48
+ export declare function serializeRpcResult(result: unknown): string;
40
49
  export declare function startDevServer(args: DevServerArgs): Promise<DevServerHandle>;
41
50
  /** Used by the CLI command for cross-platform `open <url>`. Best-effort —
42
51
  * if the platform opener isn't installed (common in WSL, headless CI, some
@@ -18,6 +18,17 @@ import { dispatchRpc } from "./rpc_handler.js";
18
18
  import { buildWrapperPage } from "./wrapper_page.js";
19
19
  const DEFAULT_PORT = 5174;
20
20
  const DEFAULT_VITE_PORT = 5173;
21
+ /**
22
+ * Serialize an RPC result for the HTTP response body. Ops with no return
23
+ * value (e.g. comments.delete) resolve `undefined` — in production they
24
+ * travel over postMessage where undefined structured-clones fine, but
25
+ * `JSON.stringify(undefined)` is not a string, so the body would be EMPTY
26
+ * and the wrapper's `JSON.parse` throws "Unexpected end of JSON input".
27
+ * Serialize those as `null`.
28
+ */
29
+ export function serializeRpcResult(result) {
30
+ return JSON.stringify(result ?? null);
31
+ }
21
32
  export async function startDevServer(args) {
22
33
  const wrapperPort = await pickPort(args.port ?? DEFAULT_PORT);
23
34
  const vitePort = await pickPort(args.vitePort ?? DEFAULT_VITE_PORT, wrapperPort);
@@ -95,7 +106,7 @@ export async function startDevServer(args) {
95
106
  const ms = Date.now() - startedAt;
96
107
  process.stderr.write(`[rpc] ${body.op} ${ms}ms\n`);
97
108
  res.writeHead(200, { "Content-Type": "application/json" });
98
- res.end(JSON.stringify(result));
109
+ res.end(serializeRpcResult(result));
99
110
  }
100
111
  catch (err) {
101
112
  const message = err instanceof Error ? err.message : String(err);
package/dist/src/cli.js CHANGED
@@ -31032,6 +31032,9 @@ function escapeHtml2(s) {
31032
31032
  // src/dev/server.ts
31033
31033
  var DEFAULT_PORT = 5174;
31034
31034
  var DEFAULT_VITE_PORT = 5173;
31035
+ function serializeRpcResult(result) {
31036
+ return JSON.stringify(result ?? null);
31037
+ }
31035
31038
  async function startDevServer(args) {
31036
31039
  const wrapperPort = await pickPort(args.port ?? DEFAULT_PORT);
31037
31040
  const vitePort = await pickPort(args.vitePort ?? DEFAULT_VITE_PORT, wrapperPort);
@@ -31099,7 +31102,7 @@ async function startDevServer(args) {
31099
31102
  process.stderr.write(`[rpc] ${body.op} ${ms}ms
31100
31103
  `);
31101
31104
  res.writeHead(200, { "Content-Type": "application/json" });
31102
- res.end(JSON.stringify(result));
31105
+ res.end(serializeRpcResult(result));
31103
31106
  } catch (err2) {
31104
31107
  const message = err2 instanceof Error ? err2.message : String(err2);
31105
31108
  process.stderr.write(`[rpc] ERROR ${message}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/cli",
3
- "version": "0.45.0",
3
+ "version": "0.45.1",
4
4
  "description": "Lotics SDK and CLI for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,4 +41,4 @@
41
41
  "url": "https://github.com/lotics/lotics.git",
42
42
  "directory": "packages/sdk"
43
43
  }
44
- }
44
+ }