lunel-cli 0.1.33 → 0.1.34

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 +49 -16
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ const __require = createRequire(import.meta.url);
19
19
  const VERSION = __require("../package.json").version;
20
20
  const PTY_RELEASE_INFO_URL = process.env.LUNEL_PTY_INFO_URL ||
21
21
  "https://raw.githubusercontent.com/ssbharambe-m/pty-releases/refs/heads/main/info.json";
22
+ const VERBOSE_AI_LOGS = process.env.LUNEL_DEBUG_AI === "1";
22
23
  // Root directory - sandbox all file operations to this
23
24
  const ROOT_DIR = process.cwd();
24
25
  // Terminal sessions (managed by Rust PTY binary)
@@ -46,6 +47,13 @@ const PORT_SYNC_INTERVAL_MS = 30_000;
46
47
  let portSyncTimer = null;
47
48
  let portScanInFlight = false;
48
49
  let lastDiscoveredPorts = [];
50
+ function redactSensitive(input) {
51
+ const text = typeof input === "string" ? input : JSON.stringify(input);
52
+ return text
53
+ .replace(/([A-Za-z0-9\-_]{20,}\.[A-Za-z0-9\-_]{20,}\.[A-Za-z0-9\-_]{20,})/g, "[redacted_jwt]")
54
+ .replace(/(password|token|authorization|resumeToken|x-manager-password)\s*[:=]\s*["']?[^"',\s}]+/gi, "$1=[redacted]")
55
+ .replace(/[A-Za-z0-9+/=_-]{40,}/g, "[redacted_secret]");
56
+ }
49
57
  // Popular development server ports to scan on connect
50
58
  const DEV_PORTS = [
51
59
  1234, // Parcel
@@ -1375,30 +1383,36 @@ function requireData(response, label) {
1375
1383
  const errMsg = response.error
1376
1384
  ? (typeof response.error === "string" ? response.error : JSON.stringify(response.error))
1377
1385
  : `${label} returned no data`;
1378
- console.error(`[ai] ${label} failed:`, errMsg, "raw response:", JSON.stringify(response).substring(0, 500));
1386
+ console.error(`[ai] ${label} failed:`, redactSensitive(errMsg), "raw response:", redactSensitive(JSON.stringify(response).substring(0, 500)));
1379
1387
  throw new Error(errMsg);
1380
1388
  }
1381
1389
  return response.data;
1382
1390
  }
1383
1391
  async function handleAiCreateSession(payload) {
1384
1392
  const title = payload.title || undefined;
1385
- console.log("[ai] createSession called, title:", title);
1393
+ if (VERBOSE_AI_LOGS)
1394
+ console.log("[ai] createSession called");
1386
1395
  try {
1387
1396
  const response = await opencodeClient.session.create({ body: { title } });
1388
- console.log("[ai] createSession response ok:", !!response.data, "error:", response.error ? JSON.stringify(response.error).substring(0, 200) : "none");
1397
+ if (VERBOSE_AI_LOGS) {
1398
+ console.log("[ai] createSession response ok:", !!response.data, "error:", response.error ? redactSensitive(JSON.stringify(response.error).substring(0, 200)) : "none");
1399
+ }
1389
1400
  return { session: requireData(response, "session.create") };
1390
1401
  }
1391
1402
  catch (err) {
1392
- console.error("[ai] createSession exception:", err.message, err.stack);
1403
+ console.error("[ai] createSession exception:", redactSensitive(err.message));
1393
1404
  throw err;
1394
1405
  }
1395
1406
  }
1396
1407
  async function handleAiListSessions() {
1397
- console.log("[ai] listSessions called");
1408
+ if (VERBOSE_AI_LOGS)
1409
+ console.log("[ai] listSessions called");
1398
1410
  try {
1399
1411
  const response = await opencodeClient.session.list();
1400
1412
  const data = requireData(response, "session.list");
1401
- console.log("[ai] listSessions returned", Array.isArray(data) ? data.length : typeof data, "sessions");
1413
+ if (VERBOSE_AI_LOGS) {
1414
+ console.log("[ai] listSessions returned", Array.isArray(data) ? data.length : typeof data, "sessions");
1415
+ }
1402
1416
  return { sessions: data };
1403
1417
  }
1404
1418
  catch (err) {
@@ -1420,7 +1434,8 @@ async function handleAiDeleteSession(payload) {
1420
1434
  }
1421
1435
  async function handleAiGetMessages(payload) {
1422
1436
  const id = payload.id;
1423
- console.log("[ai] getMessages called, sessionId:", id);
1437
+ if (VERBOSE_AI_LOGS)
1438
+ console.log("[ai] getMessages called");
1424
1439
  try {
1425
1440
  const response = await opencodeClient.session.messages({ path: { id } });
1426
1441
  const raw = requireData(response, "session.messages");
@@ -1432,7 +1447,8 @@ async function handleAiGetMessages(payload) {
1432
1447
  parts: m.parts || [],
1433
1448
  time: m.info.time,
1434
1449
  }));
1435
- console.log("[ai] getMessages returned", messages.length, "messages");
1450
+ if (VERBOSE_AI_LOGS)
1451
+ console.log("[ai] getMessages returned", messages.length, "messages");
1436
1452
  return { messages };
1437
1453
  }
1438
1454
  catch (err) {
@@ -1445,7 +1461,14 @@ async function handleAiPrompt(payload) {
1445
1461
  const text = payload.text;
1446
1462
  const model = payload.model;
1447
1463
  const agent = payload.agent;
1448
- console.log("[ai] prompt called, sessionId:", sessionId, "model:", JSON.stringify(model), "agent:", agent, "text:", text.substring(0, 100));
1464
+ if (VERBOSE_AI_LOGS) {
1465
+ console.log("[ai] prompt called", {
1466
+ hasSessionId: Boolean(sessionId),
1467
+ model: redactSensitive(JSON.stringify(model || {})),
1468
+ hasAgent: Boolean(agent),
1469
+ textLength: typeof text === "string" ? text.length : 0,
1470
+ });
1471
+ }
1449
1472
  // Fire and forget — results stream via SSE events forwarded on data channel
1450
1473
  opencodeClient.session.prompt({
1451
1474
  path: { id: sessionId },
@@ -1477,11 +1500,14 @@ async function handleAiAbort(payload) {
1477
1500
  return {};
1478
1501
  }
1479
1502
  async function handleAiAgents() {
1480
- console.log("[ai] getAgents called");
1503
+ if (VERBOSE_AI_LOGS)
1504
+ console.log("[ai] getAgents called");
1481
1505
  try {
1482
1506
  const response = await opencodeClient.app.agents();
1483
1507
  const data = requireData(response, "app.agents");
1484
- console.log("[ai] getAgents returned:", JSON.stringify(data).substring(0, 300));
1508
+ if (VERBOSE_AI_LOGS) {
1509
+ console.log("[ai] getAgents returned:", redactSensitive(JSON.stringify(data).substring(0, 300)));
1510
+ }
1485
1511
  return { agents: data };
1486
1512
  }
1487
1513
  catch (err) {
@@ -1490,11 +1516,14 @@ async function handleAiAgents() {
1490
1516
  }
1491
1517
  }
1492
1518
  async function handleAiProviders() {
1493
- console.log("[ai] getProviders called");
1519
+ if (VERBOSE_AI_LOGS)
1520
+ console.log("[ai] getProviders called");
1494
1521
  try {
1495
1522
  const response = await opencodeClient.config.providers();
1496
1523
  const data = requireData(response, "config.providers");
1497
- console.log("[ai] getProviders returned", data.providers?.length, "providers, defaults:", JSON.stringify(data.default));
1524
+ if (VERBOSE_AI_LOGS) {
1525
+ console.log("[ai] getProviders returned", data.providers?.length, "providers, defaults:", redactSensitive(JSON.stringify(data.default)));
1526
+ }
1498
1527
  return { providers: data.providers, default: data.default };
1499
1528
  }
1500
1529
  catch (err) {
@@ -1572,7 +1601,7 @@ async function subscribeToOpenCodeEvents(client) {
1572
1601
  ? parsed.payload
1573
1602
  : parsed;
1574
1603
  if (!base || typeof base.type !== "string") {
1575
- console.warn("[sse] Dropped malformed event:", JSON.stringify(parsed).substring(0, 200));
1604
+ console.warn("[sse] Dropped malformed event:", redactSensitive(JSON.stringify(parsed).substring(0, 200)));
1576
1605
  continue;
1577
1606
  }
1578
1607
  console.log("[sse]", base.type);
@@ -1784,7 +1813,7 @@ async function processMessage(message) {
1784
1813
  }
1785
1814
  // Validate required fields
1786
1815
  if (!ns || !action) {
1787
- console.warn("[router] Ignoring message with missing ns/action:", JSON.stringify(message).substring(0, 300));
1816
+ console.warn("[router] Ignoring message with missing ns/action:", redactSensitive(JSON.stringify(message).substring(0, 300)));
1788
1817
  return {
1789
1818
  v: 1,
1790
1819
  id,
@@ -2198,7 +2227,11 @@ async function connectWebSocket() {
2198
2227
  return;
2199
2228
  }
2200
2229
  if (message.type === "close_connection") {
2201
- console.log(`[session] closed by gateway: ${message.reason || "expired"}`);
2230
+ const reason = message.reason || "expired";
2231
+ console.log(`[session] closed by gateway: ${reason}`);
2232
+ if (reason === "session ended from app") {
2233
+ console.log("[session] Run `npx lunel-cli` again and scan the new QR code to reconnect.");
2234
+ }
2202
2235
  gracefulShutdown();
2203
2236
  return;
2204
2237
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lunel-cli",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "author": [
5
5
  {
6
6
  "name": "Soham Bharambe",