lunel-cli 0.1.23 → 0.1.27

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.
Files changed (2) hide show
  1. package/dist/index.js +100 -18
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { WebSocket } from "ws";
3
3
  import qrcode from "qrcode-terminal";
4
- import { createOpencode } from "@opencode-ai/sdk";
4
+ import { createOpencodeServer, createOpencodeClient } from "@opencode-ai/sdk";
5
+ import * as crypto from "crypto";
5
6
  import Ignore from "ignore";
6
7
  const ignore = Ignore.default;
7
8
  import * as fs from "fs/promises";
@@ -1176,18 +1177,36 @@ function requireData(response, label) {
1176
1177
  const errMsg = response.error
1177
1178
  ? (typeof response.error === "string" ? response.error : JSON.stringify(response.error))
1178
1179
  : `${label} returned no data`;
1180
+ console.error(`[ai] ${label} failed:`, errMsg, "raw response:", JSON.stringify(response).substring(0, 500));
1179
1181
  throw new Error(errMsg);
1180
1182
  }
1181
1183
  return response.data;
1182
1184
  }
1183
1185
  async function handleAiCreateSession(payload) {
1184
1186
  const title = payload.title || undefined;
1185
- const response = await opencodeClient.session.create({ body: { title } });
1186
- return { session: requireData(response, "session.create") };
1187
+ console.log("[ai] createSession called, title:", title);
1188
+ try {
1189
+ const response = await opencodeClient.session.create({ body: { title } });
1190
+ console.log("[ai] createSession response ok:", !!response.data, "error:", response.error ? JSON.stringify(response.error).substring(0, 200) : "none");
1191
+ return { session: requireData(response, "session.create") };
1192
+ }
1193
+ catch (err) {
1194
+ console.error("[ai] createSession exception:", err.message, err.stack);
1195
+ throw err;
1196
+ }
1187
1197
  }
1188
1198
  async function handleAiListSessions() {
1189
- const response = await opencodeClient.session.list();
1190
- return { sessions: requireData(response, "session.list") };
1199
+ console.log("[ai] listSessions called");
1200
+ try {
1201
+ const response = await opencodeClient.session.list();
1202
+ const data = requireData(response, "session.list");
1203
+ console.log("[ai] listSessions returned", Array.isArray(data) ? data.length : typeof data, "sessions");
1204
+ return { sessions: data };
1205
+ }
1206
+ catch (err) {
1207
+ console.error("[ai] listSessions exception:", err.message);
1208
+ throw err;
1209
+ }
1191
1210
  }
1192
1211
  async function handleAiGetSession(payload) {
1193
1212
  const id = payload.id;
@@ -1203,14 +1222,22 @@ async function handleAiDeleteSession(payload) {
1203
1222
  }
1204
1223
  async function handleAiGetMessages(payload) {
1205
1224
  const id = payload.id;
1206
- const response = await opencodeClient.session.messages({ path: { id } });
1207
- return { messages: requireData(response, "session.messages") };
1225
+ console.log("[ai] getMessages called, sessionId:", id);
1226
+ try {
1227
+ const response = await opencodeClient.session.messages({ path: { id } });
1228
+ return { messages: requireData(response, "session.messages") };
1229
+ }
1230
+ catch (err) {
1231
+ console.error("[ai] getMessages exception:", err.message);
1232
+ throw err;
1233
+ }
1208
1234
  }
1209
1235
  async function handleAiPrompt(payload) {
1210
1236
  const sessionId = payload.sessionId;
1211
1237
  const text = payload.text;
1212
1238
  const model = payload.model;
1213
1239
  const agent = payload.agent;
1240
+ console.log("[ai] prompt called, sessionId:", sessionId, "model:", JSON.stringify(model), "agent:", agent, "text:", text.substring(0, 100));
1214
1241
  // Fire and forget — results stream via SSE events forwarded on data channel
1215
1242
  opencodeClient.session.prompt({
1216
1243
  path: { id: sessionId },
@@ -1220,6 +1247,7 @@ async function handleAiPrompt(payload) {
1220
1247
  ...(agent ? { agent } : {}),
1221
1248
  },
1222
1249
  }).catch((err) => {
1250
+ console.error("[ai] prompt error:", err.message);
1223
1251
  if (dataChannel && dataChannel.readyState === WebSocket.OPEN) {
1224
1252
  dataChannel.send(JSON.stringify({
1225
1253
  v: 1,
@@ -1241,13 +1269,30 @@ async function handleAiAbort(payload) {
1241
1269
  return {};
1242
1270
  }
1243
1271
  async function handleAiAgents() {
1244
- const response = await opencodeClient.app.agents();
1245
- return { agents: requireData(response, "app.agents") };
1272
+ console.log("[ai] getAgents called");
1273
+ try {
1274
+ const response = await opencodeClient.app.agents();
1275
+ const data = requireData(response, "app.agents");
1276
+ console.log("[ai] getAgents returned:", JSON.stringify(data).substring(0, 300));
1277
+ return { agents: data };
1278
+ }
1279
+ catch (err) {
1280
+ console.error("[ai] getAgents exception:", err.message);
1281
+ throw err;
1282
+ }
1246
1283
  }
1247
1284
  async function handleAiProviders() {
1248
- const response = await opencodeClient.config.providers();
1249
- const data = requireData(response, "config.providers");
1250
- return { providers: data.providers, default: data.default };
1285
+ console.log("[ai] getProviders called");
1286
+ try {
1287
+ const response = await opencodeClient.config.providers();
1288
+ const data = requireData(response, "config.providers");
1289
+ console.log("[ai] getProviders returned", data.providers?.length, "providers, defaults:", JSON.stringify(data.default));
1290
+ return { providers: data.providers, default: data.default };
1291
+ }
1292
+ catch (err) {
1293
+ console.error("[ai] getProviders exception:", err.message);
1294
+ throw err;
1295
+ }
1251
1296
  }
1252
1297
  async function handleAiSetAuth(payload) {
1253
1298
  const providerId = payload.providerId;
@@ -1310,7 +1355,19 @@ async function handleAiPermissionReply(payload) {
1310
1355
  async function subscribeToOpenCodeEvents(client) {
1311
1356
  try {
1312
1357
  const events = await client.event.subscribe();
1313
- for await (const event of events.stream) {
1358
+ for await (const raw of events.stream) {
1359
+ // OpenCode SSE payload shapes vary across versions:
1360
+ // { type, properties, ... }
1361
+ // { payload: { type, properties, ... }, directory: "..." }
1362
+ const parsed = raw;
1363
+ const base = parsed?.payload && typeof parsed.payload === "object"
1364
+ ? parsed.payload
1365
+ : parsed;
1366
+ if (!base || typeof base.type !== "string") {
1367
+ console.warn("[sse] Dropped malformed event:", JSON.stringify(parsed).substring(0, 200));
1368
+ continue;
1369
+ }
1370
+ console.log("[sse]", base.type);
1314
1371
  if (dataChannel && dataChannel.readyState === WebSocket.OPEN) {
1315
1372
  const msg = {
1316
1373
  v: 1,
@@ -1318,16 +1375,19 @@ async function subscribeToOpenCodeEvents(client) {
1318
1375
  ns: "ai",
1319
1376
  action: "event",
1320
1377
  payload: {
1321
- type: event.type,
1322
- properties: event.properties,
1378
+ type: base.type,
1379
+ properties: base.properties || {},
1323
1380
  },
1324
1381
  };
1325
1382
  dataChannel.send(JSON.stringify(msg));
1326
1383
  }
1327
1384
  }
1385
+ // Stream ended normally — reconnect
1386
+ console.log("[sse] Event stream ended, reconnecting...");
1387
+ setTimeout(() => subscribeToOpenCodeEvents(client), 1000);
1328
1388
  }
1329
1389
  catch (err) {
1330
- console.error("OpenCode event stream error:", err);
1390
+ console.error("[sse] Event stream error:", err.message);
1331
1391
  setTimeout(() => subscribeToOpenCodeEvents(client), 3000);
1332
1392
  }
1333
1393
  }
@@ -1710,6 +1770,7 @@ async function processMessage(message) {
1710
1770
  }
1711
1771
  catch (error) {
1712
1772
  const err = error;
1773
+ console.error(`[router] ${ns}.${action} error:`, err.code || "ERROR", err.message);
1713
1774
  return {
1714
1775
  v: 1,
1715
1776
  id,
@@ -1879,9 +1940,28 @@ async function main() {
1879
1940
  console.log("Lunel CLI v" + VERSION);
1880
1941
  console.log("=".repeat(20) + "\n");
1881
1942
  try {
1882
- // Start OpenCode server + client
1943
+ // Generate auth credentials (like CodeNomad does)
1944
+ const opencodeUsername = "lunel";
1945
+ const opencodePassword = crypto.randomBytes(32).toString("base64url");
1946
+ const authHeader = `Basic ${Buffer.from(`${opencodeUsername}:${opencodePassword}`).toString("base64")}`;
1947
+ // Set auth env vars BEFORE spawning opencode
1948
+ process.env.OPENCODE_SERVER_USERNAME = opencodeUsername;
1949
+ process.env.OPENCODE_SERVER_PASSWORD = opencodePassword;
1950
+ // Start OpenCode server with random port (like CodeNomad: --port 0)
1883
1951
  console.log("Starting OpenCode...");
1884
- const { client } = await createOpencode();
1952
+ const server = await createOpencodeServer({
1953
+ hostname: "127.0.0.1",
1954
+ port: 0,
1955
+ timeout: 15000,
1956
+ });
1957
+ console.log(`OpenCode server listening on ${server.url}`);
1958
+ // Create client with auth headers
1959
+ const client = createOpencodeClient({
1960
+ baseUrl: server.url,
1961
+ headers: {
1962
+ "Authorization": authHeader,
1963
+ },
1964
+ });
1885
1965
  opencodeClient = client;
1886
1966
  console.log("OpenCode ready.\n");
1887
1967
  // Subscribe to OpenCode events
@@ -1893,6 +1973,8 @@ async function main() {
1893
1973
  catch (error) {
1894
1974
  if (error instanceof Error) {
1895
1975
  console.error(`Error: ${error.message}`);
1976
+ if (error.stack)
1977
+ console.error(error.stack);
1896
1978
  }
1897
1979
  else {
1898
1980
  console.error("An unexpected error occurred");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lunel-cli",
3
- "version": "0.1.23",
3
+ "version": "0.1.27",
4
4
  "author": [
5
5
  {
6
6
  "name": "Soham Bharambe",