@tarcisiopgs/lisa 1.7.6 → 1.7.7

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
@@ -85,6 +85,8 @@ Lisa follows a deterministic pipeline:
85
85
 
86
86
  At least one provider must be installed and available in your PATH.
87
87
 
88
+ > **Cursor Free plan** — `lisa init` automatically detects Free accounts and restricts model selection to `auto` only. On paid plans, a curated list of top-tier models is shown (`composer-1.5`, `opus-4.6`, `sonnet-4.6`, `gpt-5.3-codex`, etc.).
89
+
88
90
  ### Fallback Chain
89
91
 
90
92
  Configure multiple models — Lisa tries each in order. Transient errors (429, quota, timeout, network) trigger the next model; non-transient errors stop the chain.
@@ -183,12 +185,13 @@ When running in an interactive terminal, `lisa run` renders a real-time Kanban b
183
185
  |-----|--------|
184
186
  | `Tab` | Move to next column |
185
187
  | `Shift+Tab` | Move to previous column |
186
- | `↑` / `↓` | Navigate cards within a column |
188
+ | `↑` / `↓` | Navigate cards / scroll output |
187
189
  | `Enter` | Open issue detail view (streams provider output) |
188
190
  | `Esc` | Close detail view, return to board |
191
+ | `p` | Pause / resume — loop finishes the current issue then waits |
189
192
  | `q` | Quit |
190
193
 
191
- The terminal tab title also updates in real time: it shows a spinner with the active issue ID while work is in progress, and a checkmark when done.
194
+ The sidebar legend updates contextually: board shortcuts when browsing the Kanban, scroll and back hints when viewing issue detail. The terminal tab title also updates in real time: it shows a spinner with the active issue ID while work is in progress, and a checkmark when done.
192
195
 
193
196
  ## Configuration
194
197
 
package/dist/index.js CHANGED
@@ -3154,6 +3154,13 @@ function createSource(name) {
3154
3154
  var activeCleanup = null;
3155
3155
  var activeProviderPid = null;
3156
3156
  var shuttingDown = false;
3157
+ var loopPaused = false;
3158
+ kanbanEmitter.on("loop:pause", () => {
3159
+ loopPaused = true;
3160
+ });
3161
+ kanbanEmitter.on("loop:resume", () => {
3162
+ loopPaused = false;
3163
+ });
3157
3164
  function resolveModels(config2) {
3158
3165
  if (!config2.models || config2.models.length === 0) {
3159
3166
  return [{ provider: config2.provider }];
@@ -3320,6 +3327,7 @@ async function runLoop(config2, opts) {
3320
3327
  const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
3321
3328
  const logFile = resolve5(config2.logs.dir, `session_${session}_${timestamp2}.log`);
3322
3329
  divider(session);
3330
+ await waitIfPaused();
3323
3331
  startSpinner("fetching issue...");
3324
3332
  if (opts.issueId) {
3325
3333
  log(`Fetching issue '${opts.issueId}' from ${config2.source}...`);
@@ -4026,6 +4034,11 @@ async function cleanupWorktree(repoRoot, worktreePath) {
4026
4034
  function sleep(ms) {
4027
4035
  return new Promise((resolve6) => setTimeout(resolve6, ms));
4028
4036
  }
4037
+ async function waitIfPaused() {
4038
+ while (loopPaused) {
4039
+ await sleep(500);
4040
+ }
4041
+ }
4029
4042
 
4030
4043
  // src/cli.ts
4031
4044
  function sleep2(ms) {
@@ -4082,7 +4095,7 @@ Add them to your ${shell} and run: source ${shell}`));
4082
4095
  if (isTUI) {
4083
4096
  const { render } = await import("ink");
4084
4097
  const { createElement } = await import("react");
4085
- const { KanbanApp } = await import("./kanban-YP3TJJUT.js");
4098
+ const { KanbanApp } = await import("./kanban-5C3WZIKC.js");
4086
4099
  render(createElement(KanbanApp, { config: merged }), { exitOnCtrlC: false });
4087
4100
  }
4088
4101
  await runLoop(merged, {
@@ -4278,15 +4291,21 @@ var issue = defineCommand({
4278
4291
  meta: { name: "issue", description: "Issue tracker operations for use inside worktrees" },
4279
4292
  subCommands: { get: issueGet, done: issueDone }
4280
4293
  });
4281
- var CURSOR_MODELS_FALLBACK = [
4294
+ var CURSOR_PREFERRED_MODELS = [
4282
4295
  "auto",
4283
4296
  "composer-1.5",
4297
+ "composer-1",
4298
+ "gpt-5.3-codex",
4299
+ "gpt-5.2",
4300
+ "gpt-5.1-codex-max",
4284
4301
  "opus-4.6-thinking",
4285
4302
  "opus-4.6",
4303
+ "sonnet-4.6-thinking",
4286
4304
  "sonnet-4.6",
4287
- "gpt-5.3-codex",
4288
- "gpt-5.2",
4289
- "gemini-3.1-pro"
4305
+ "gemini-3.1-pro",
4306
+ "gemini-3-pro",
4307
+ "grok",
4308
+ "kimi-k2.5"
4290
4309
  ];
4291
4310
  function fetchCursorModels() {
4292
4311
  try {
@@ -4298,13 +4317,14 @@ function fetchCursorModels() {
4298
4317
  return false;
4299
4318
  }
4300
4319
  });
4301
- if (!bin) return CURSOR_MODELS_FALLBACK;
4320
+ if (!bin) return CURSOR_PREFERRED_MODELS;
4302
4321
  const raw = execSync8(`${bin} --list-models`, { encoding: "utf-8", timeout: 1e4 });
4303
4322
  const clean = raw.replace(/\x1b\[[0-9;]*[mGKHFA-Z]/g, "");
4304
- const models = clean.split("\n").map((l) => l.trim()).filter((l) => l.includes(" - ")).map((l) => (l.split(" - ")[0] ?? "").trim()).filter(Boolean);
4305
- return models.length > 0 ? models : CURSOR_MODELS_FALLBACK;
4323
+ const all = clean.split("\n").map((l) => l.trim()).filter((l) => l.includes(" - ")).map((l) => (l.split(" - ")[0] ?? "").trim()).filter(Boolean);
4324
+ const filtered = CURSOR_PREFERRED_MODELS.filter((m) => all.includes(m));
4325
+ return filtered.length > 0 ? filtered : CURSOR_PREFERRED_MODELS;
4306
4326
  } catch {
4307
- return CURSOR_MODELS_FALLBACK;
4327
+ return CURSOR_PREFERRED_MODELS;
4308
4328
  }
4309
4329
  }
4310
4330
  function fetchOpenCodeModels() {
@@ -337,11 +337,7 @@ function IssueDetail({ card, onBack }) {
337
337
  ] }) : visibleLines.map((line, i) => (
338
338
  // biome-ignore lint/suspicious/noArrayIndexKey: log lines have no stable key
339
339
  /* @__PURE__ */ jsx4(Text4, { color: "white", dimColor: true, children: line }, i)
340
- )) }),
341
- /* @__PURE__ */ jsxs4(Box4, { justifyContent: "space-between", borderStyle: "single", borderColor: "gray", paddingX: 1, children: [
342
- /* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: "[\u2191\u2193] scroll" }),
343
- /* @__PURE__ */ jsx4(Text4, { color: "yellow", dimColor: true, children: "[Esc] back to board" })
344
- ] })
340
+ )) })
345
341
  ]
346
342
  }
347
343
  );
@@ -352,14 +348,15 @@ import { existsSync } from "fs";
352
348
  import { basename, join } from "path";
353
349
  import { Box as Box5, Text as Text5 } from "ink";
354
350
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
355
- function Sidebar({ provider, source, cwd }) {
356
- const dir = basename(cwd);
351
+ function Sidebar({ provider, source, cwd, activeView, paused = false }) {
352
+ const dir = basename(cwd).toUpperCase();
357
353
  const cwdLabel = existsSync(join(cwd, ".git")) ? "REPOSITORY" : "WORKSPACE";
358
354
  return /* @__PURE__ */ jsxs5(
359
355
  Box5,
360
356
  {
361
357
  flexDirection: "column",
362
358
  width: 28,
359
+ flexShrink: 0,
363
360
  borderStyle: "single",
364
361
  borderColor: "yellow",
365
362
  paddingX: 1,
@@ -377,8 +374,8 @@ function Sidebar({ provider, source, cwd }) {
377
374
  /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D" })
378
375
  ] }),
379
376
  /* @__PURE__ */ jsxs5(Box5, { marginBottom: 1, children: [
380
- /* @__PURE__ */ jsx5(Text5, { color: "green", children: "\u25B6 " }),
381
- /* @__PURE__ */ jsx5(Text5, { color: "green", bold: true, children: "RUNNING" })
377
+ /* @__PURE__ */ jsx5(Text5, { color: paused ? "yellow" : "green", children: paused ? "\u23F8 " : "\u25B6 " }),
378
+ /* @__PURE__ */ jsx5(Text5, { color: paused ? "yellow" : "green", bold: true, children: paused ? "PAUSED" : "RUNNING" })
382
379
  ] }),
383
380
  /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
384
381
  /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
@@ -404,11 +401,15 @@ function Sidebar({ provider, source, cwd }) {
404
401
  ] }),
405
402
  /* @__PURE__ */ jsx5(Box5, { flexGrow: 1 }),
406
403
  /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }),
407
- /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
404
+ activeView === "board" ? /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
408
405
  /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[Tab] next column" }),
409
406
  /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u2191\u2193] navigate " }),
410
407
  /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u21B5] view detail " }),
408
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: paused ? "[p] resume " : "[p] pause " }),
411
409
  /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[q] quit " })
410
+ ] }) : /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
411
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u2191\u2193] scroll " }),
412
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[Esc] back to board" })
412
413
  ] })
413
414
  ]
414
415
  }
@@ -423,6 +424,7 @@ function KanbanApp({ config }) {
423
424
  const [activeView, setActiveView] = useState3("board");
424
425
  const [activeColIndex, setActiveColIndex] = useState3(0);
425
426
  const [activeCardIndex, setActiveCardIndex] = useState3(0);
427
+ const [paused, setPaused] = useState3(false);
426
428
  useEffect3(() => {
427
429
  const onExit = () => exit();
428
430
  kanbanEmitter.on("tui:exit", onExit);
@@ -454,6 +456,12 @@ function KanbanApp({ config }) {
454
456
  if (key.escape) setActiveView("board");
455
457
  return;
456
458
  }
459
+ if (input === "p") {
460
+ const next = !paused;
461
+ setPaused(next);
462
+ kanbanEmitter.emit(next ? "loop:pause" : "loop:resume");
463
+ return;
464
+ }
457
465
  if (key.tab && !key.shift) {
458
466
  const nextCol = (activeColIndex + 1) % 3;
459
467
  setActiveColIndex(nextCol);
@@ -489,7 +497,16 @@ function KanbanApp({ config }) {
489
497
  };
490
498
  const selectedCard = activeView === "detail" ? columnCards[activeColIndex]?.[activeCardIndex] ?? null : null;
491
499
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", height: process.stdout.rows, children: [
492
- /* @__PURE__ */ jsx6(Sidebar, { provider: config.provider, source: config.source, cwd: process.cwd() }),
500
+ /* @__PURE__ */ jsx6(
501
+ Sidebar,
502
+ {
503
+ provider: config.provider,
504
+ source: config.source,
505
+ cwd: process.cwd(),
506
+ activeView,
507
+ paused
508
+ }
509
+ ),
493
510
  activeView === "board" || !selectedCard ? /* @__PURE__ */ jsx6(
494
511
  Board,
495
512
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tarcisiopgs/lisa",
3
- "version": "1.7.6",
3
+ "version": "1.7.7",
4
4
  "description": "Autonomous issue resolver",
5
5
  "license": "MIT",
6
6
  "type": "module",