@tarcisiopgs/lisa 1.8.0 → 1.8.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.
File without changes
package/dist/index.js CHANGED
@@ -171,6 +171,30 @@ function mergeWithFlags(config2, flags) {
171
171
 
172
172
  // src/git/github.ts
173
173
  import { execa } from "execa";
174
+
175
+ // src/git/pr-body.ts
176
+ var PROVIDER_ATTRIBUTION_RE = /claude\.ai|claude\s+code|gemini\s+cli|openai\s+codex|\bgoose\b|\baider\b|github\s+copilot|cursor\s+agent|\bopencode\b/i;
177
+ var AI_COAUTHOR_RE = /co-authored-by:[^\n]*(anthropic|claude|gemini|openai|codex|goose|aider|copilot|cursor|google)/i;
178
+ function stripProviderAttribution(body) {
179
+ let result = body;
180
+ while (true) {
181
+ const sepIndex = result.lastIndexOf("\n---");
182
+ if (sepIndex === -1) break;
183
+ const section = result.slice(sepIndex);
184
+ if (PROVIDER_ATTRIBUTION_RE.test(section) || AI_COAUTHOR_RE.test(section)) {
185
+ result = result.slice(0, sepIndex).trimEnd();
186
+ } else {
187
+ break;
188
+ }
189
+ }
190
+ result = result.replace(
191
+ /\n+Co-Authored-By:[^\n]*(anthropic|claude|gemini|openai|codex|goose|aider|copilot|cursor|google)[^\n]*/gi,
192
+ ""
193
+ );
194
+ return result.trimEnd();
195
+ }
196
+
197
+ // src/git/github.ts
174
198
  async function isGhCliAvailable() {
175
199
  try {
176
200
  await execa("gh", ["auth", "status"]);
@@ -202,7 +226,7 @@ async function appendPrAttribution(prUrl, providerUsed) {
202
226
 
203
227
  ---
204
228
  \u{1F916} Resolved by [lisa](https://github.com/tarcisiopgs/lisa) using **${providerName}**`;
205
- const newBody = (body ?? "") + attribution;
229
+ const newBody = stripProviderAttribution(body ?? "") + attribution;
206
230
  await execa("gh", ["pr", "edit", prUrl, "--body", newBody]);
207
231
  } catch {
208
232
  }
@@ -266,6 +290,28 @@ function ensureWorktreeGitignore(repoRoot) {
266
290
  `);
267
291
  }
268
292
  }
293
+ var LOGS_GITIGNORE_ENTRY = ".lisa/logs/*";
294
+ function ensureLogsGitignore(repoRoot) {
295
+ if (!existsSync2(join(repoRoot, ".git"))) {
296
+ return false;
297
+ }
298
+ const gitignorePath = join(repoRoot, ".gitignore");
299
+ if (!existsSync2(gitignorePath)) {
300
+ appendFileSync(gitignorePath, `# Lisa
301
+ ${LOGS_GITIGNORE_ENTRY}
302
+ `);
303
+ return true;
304
+ }
305
+ const content = readFileSync2(gitignorePath, "utf-8");
306
+ if (content.split("\n").some((line) => line.trim() === LOGS_GITIGNORE_ENTRY)) {
307
+ return false;
308
+ }
309
+ const separator = content.endsWith("\n") ? "" : "\n";
310
+ appendFileSync(gitignorePath, `${separator}# Lisa
311
+ ${LOGS_GITIGNORE_ENTRY}
312
+ `);
313
+ return true;
314
+ }
269
315
  function determineRepoPath(repos, issue2, workspace) {
270
316
  if (repos.length === 0) return void 0;
271
317
  if (issue2.repo) {
@@ -4186,7 +4232,7 @@ Add them to your ${shell} and run: source ${shell}`));
4186
4232
  if (isTUI) {
4187
4233
  const { render } = await import("ink");
4188
4234
  const { createElement } = await import("react");
4189
- const { KanbanApp } = await import("./kanban-5C3WZIKC.js");
4235
+ const { KanbanApp } = await import("./kanban-PD2F4KWT.js");
4190
4236
  render(createElement(KanbanApp, { config: merged }), { exitOnCtrlC: false });
4191
4237
  }
4192
4238
  await runLoop(merged, {
@@ -4745,6 +4791,9 @@ Then reload: ${pc2.cyan(`source ${shell}`)}`
4745
4791
  logs: { dir: ".lisa/logs", format: "text" }
4746
4792
  };
4747
4793
  saveConfig(cfg);
4794
+ if (ensureLogsGitignore(process.cwd())) {
4795
+ clack.log.info("Added .lisa/logs/* to .gitignore");
4796
+ }
4748
4797
  clack.outro(
4749
4798
  `${pc2.green("All set!")} Config saved to ${pc2.cyan(".lisa/config.yaml")}
4750
4799
  Run ${pc2.bold(pc2.cyan("lisa run"))} to start resolving issues.`
@@ -29,7 +29,32 @@ function formatElapsed(ms) {
29
29
  if (minutes > 0) return `${minutes}m ${remainingSeconds}s`;
30
30
  return `${seconds}s`;
31
31
  }
32
- function Card({ card, isSelected = false }) {
32
+ function wrapTitle(title, maxWidth) {
33
+ if (title.length <= maxWidth) return [title, ""];
34
+ const words = title.split(" ");
35
+ let line1 = "";
36
+ let i = 0;
37
+ for (; i < words.length; i++) {
38
+ const word = words[i] ?? "";
39
+ const candidate = line1 ? `${line1} ${word}` : word;
40
+ if (candidate.length > maxWidth) break;
41
+ line1 = candidate;
42
+ }
43
+ if (!line1) {
44
+ line1 = title.slice(0, maxWidth);
45
+ const rest = title.slice(maxWidth);
46
+ const line22 = rest.length > maxWidth ? `${rest.slice(0, maxWidth - 1)}\u2026` : rest;
47
+ return [line1, line22];
48
+ }
49
+ const remaining = words.slice(i).join(" ");
50
+ const line2 = remaining.length > maxWidth ? `${remaining.slice(0, maxWidth - 1)}\u2026` : remaining;
51
+ return [line1, line2];
52
+ }
53
+ function Card({
54
+ card,
55
+ isSelected = false,
56
+ paused = false
57
+ }) {
33
58
  const [now, setNow] = useState(Date.now());
34
59
  useEffect(() => {
35
60
  if (card.column !== "in_progress") return;
@@ -53,7 +78,9 @@ function Card({ card, isSelected = false }) {
53
78
  }
54
79
  const selectionBar = isSelected ? "\u2590" : " ";
55
80
  const selectionColor = isSelected ? "yellow" : "white";
56
- const truncated = card.title.length > 30 ? `${card.title.slice(0, 27)}\u2026` : card.title;
81
+ const CARD_TITLE_WIDTH = 28;
82
+ const [titleLine1, titleLine2] = wrapTitle(card.title, CARD_TITLE_WIDTH);
83
+ const isPausedInProgress = paused && card.column === "in_progress";
57
84
  return /* @__PURE__ */ jsxs(
58
85
  Box,
59
86
  {
@@ -61,7 +88,7 @@ function Card({ card, isSelected = false }) {
61
88
  paddingX: 0,
62
89
  marginBottom: 0,
63
90
  borderStyle: "single",
64
- borderColor: card.hasError ? "red" : isSelected ? "yellow" : "gray",
91
+ borderColor: card.hasError ? "red" : isPausedInProgress ? "gray" : isSelected ? "yellow" : "gray",
65
92
  children: [
66
93
  /* @__PURE__ */ jsx(Text, { color: selectionColor, children: selectionBar }),
67
94
  /* @__PURE__ */ jsxs(Box, { flexDirection: "column", flexGrow: 1, paddingX: 1, children: [
@@ -69,10 +96,11 @@ function Card({ card, isSelected = false }) {
69
96
  /* @__PURE__ */ jsx(Text, { color: "yellow", bold: isSelected, children: card.id }),
70
97
  /* @__PURE__ */ jsx(Text, { color: statusColor, children: statusGlyph })
71
98
  ] }),
72
- /* @__PURE__ */ jsx(Text, { bold: isSelected, dimColor: !isSelected, children: truncated }),
99
+ /* @__PURE__ */ jsx(Text, { bold: isSelected, dimColor: !isSelected, children: titleLine1 }),
100
+ /* @__PURE__ */ jsx(Text, { bold: isSelected, dimColor: !isSelected, children: titleLine2 }),
73
101
  card.column === "in_progress" && card.startedAt !== void 0 && /* @__PURE__ */ jsxs(Box, { flexDirection: "row", marginTop: 0, children: [
74
- /* @__PURE__ */ jsx(Text, { color: "yellow", children: /* @__PURE__ */ jsx(Spinner, { type: "dots" }) }),
75
- /* @__PURE__ */ jsxs(Text, { color: "yellow", children: [
102
+ isPausedInProgress ? /* @__PURE__ */ jsx(Text, { color: "gray", children: "\u23F8" }) : /* @__PURE__ */ jsx(Text, { color: "yellow", children: /* @__PURE__ */ jsx(Spinner, { type: "dots" }) }),
103
+ /* @__PURE__ */ jsxs(Text, { color: isPausedInProgress ? "gray" : "yellow", dimColor: isPausedInProgress, children: [
76
104
  " ",
77
105
  formatElapsed(now - card.startedAt)
78
106
  ] })
@@ -90,9 +118,15 @@ function Card({ card, isSelected = false }) {
90
118
 
91
119
  // src/ui/column.tsx
92
120
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
93
- var CARD_HEIGHT = 5;
121
+ var CARD_HEIGHT = 6;
94
122
  var HEADER_ROWS = 4;
95
- function Column({ label, cards, isFocused = false, activeCardIndex = 0 }) {
123
+ function Column({
124
+ label,
125
+ cards,
126
+ isFocused = false,
127
+ activeCardIndex = 0,
128
+ paused = false
129
+ }) {
96
130
  const terminalRows = process.stdout.rows ?? 24;
97
131
  const visibleCount = Math.max(1, Math.floor((terminalRows - HEADER_ROWS) / CARD_HEIGHT));
98
132
  let scrollOffset = 0;
@@ -134,7 +168,7 @@ function Column({ label, cards, isFocused = false, activeCardIndex = 0 }) {
134
168
  visibleCards.map((card, idx) => {
135
169
  const absoluteIdx = scrollOffset + idx;
136
170
  const isSelected = isFocused && absoluteIdx === activeCardIndex;
137
- return /* @__PURE__ */ jsx2(Card, { card, isSelected }, card.id);
171
+ return /* @__PURE__ */ jsx2(Card, { card, isSelected, paused }, card.id);
138
172
  }),
139
173
  cards.length === 0 && /* @__PURE__ */ jsx2(Box2, { justifyContent: "center", paddingY: 1, children: /* @__PURE__ */ jsx2(Text2, { color: "gray", dimColor: true, children: "\u2014 empty \u2014" }) }),
140
174
  hiddenBelow > 0 && /* @__PURE__ */ jsx2(Box2, { justifyContent: "center", children: /* @__PURE__ */ jsx2(Text2, { color: "yellow", dimColor: true, children: `\u2193 ${hiddenBelow} more` }) })
@@ -158,7 +192,8 @@ function Board({
158
192
  isEmpty,
159
193
  workComplete,
160
194
  activeColIndex = 0,
161
- activeCardIndex = 0
195
+ activeCardIndex = 0,
196
+ paused = false
162
197
  }) {
163
198
  const backlog = cards.filter((c) => c.column === "backlog");
164
199
  const inProgress = cards.filter((c) => c.column === "in_progress");
@@ -197,7 +232,8 @@ function Board({
197
232
  label: labels.backlog,
198
233
  cards: backlog,
199
234
  isFocused: activeColIndex === 0,
200
- activeCardIndex: activeColIndex === 0 ? activeCardIndex : 0
235
+ activeCardIndex: activeColIndex === 0 ? activeCardIndex : 0,
236
+ paused
201
237
  }
202
238
  ),
203
239
  /* @__PURE__ */ jsx3(
@@ -206,7 +242,8 @@ function Board({
206
242
  label: labels.inProgress,
207
243
  cards: inProgress,
208
244
  isFocused: activeColIndex === 1,
209
- activeCardIndex: activeColIndex === 1 ? activeCardIndex : 0
245
+ activeCardIndex: activeColIndex === 1 ? activeCardIndex : 0,
246
+ paused
210
247
  }
211
248
  ),
212
249
  /* @__PURE__ */ jsx3(
@@ -215,7 +252,8 @@ function Board({
215
252
  label: labels.done,
216
253
  cards: done,
217
254
  isFocused: activeColIndex === 2,
218
- activeCardIndex: activeColIndex === 2 ? activeCardIndex : 0
255
+ activeCardIndex: activeColIndex === 2 ? activeCardIndex : 0,
256
+ paused
219
257
  }
220
258
  )
221
259
  ] })
@@ -234,6 +272,19 @@ function formatElapsed2(ms) {
234
272
  if (minutes > 0) return `${minutes}m ${remainingSeconds}s`;
235
273
  return `${seconds}s`;
236
274
  }
275
+ function hyperlink(url, text) {
276
+ return `\x1B]8;;${url}\x07${text}\x1B]8;;\x07`;
277
+ }
278
+ function logLineColor(line) {
279
+ if (/\berror\b|✖/i.test(line)) return "red";
280
+ if (/\bwarn(ing)?\b/i.test(line)) return "yellow";
281
+ if (/✔|\bsuccess\b/i.test(line)) return "green";
282
+ return "white";
283
+ }
284
+ function scrollBar(pct, width = 8) {
285
+ const filled = Math.round(pct / 100 * width);
286
+ return "\u2593".repeat(filled) + "\u2591".repeat(width - filled);
287
+ }
237
288
  function statusLabel(column, hasError) {
238
289
  if (hasError) return { text: "FAILED", color: "red" };
239
290
  if (column === "in_progress") return { text: "IN PROGRESS", color: "yellow" };
@@ -292,7 +343,7 @@ function IssueDetail({ card, onBack }) {
292
343
  const separatorInner = Math.max(0, terminalCols - SIDEBAR_TOTAL_WIDTH - 4);
293
344
  const separator = `\u2560${"\u2550".repeat(Math.max(0, separatorInner - 2))}\u2563`;
294
345
  const totalLines = lines.length;
295
- const scrollPct = totalLines <= bodyRows ? "100%" : `${Math.round((startLine + bodyRows) / totalLines * 100)}%`;
346
+ const scrollPctNum = totalLines <= bodyRows ? 100 : Math.round((startLine + bodyRows) / totalLines * 100);
296
347
  return /* @__PURE__ */ jsxs4(
297
348
  Box4,
298
349
  {
@@ -323,21 +374,24 @@ function IssueDetail({ card, onBack }) {
323
374
  /* @__PURE__ */ jsx4(Box4, { marginTop: 0, children: /* @__PURE__ */ jsx4(Text4, { color: "white", bold: true, children: card.title }) }),
324
375
  card.prUrl !== void 0 && card.prUrl.length > 0 && /* @__PURE__ */ jsxs4(Box4, { marginTop: 0, children: [
325
376
  /* @__PURE__ */ jsx4(Text4, { color: "yellow", dimColor: true, children: "PR: " }),
326
- /* @__PURE__ */ jsx4(Text4, { color: "yellow", children: card.prUrl })
377
+ /* @__PURE__ */ jsx4(Text4, { color: "yellow", children: hyperlink(card.prUrl, card.prUrl) })
327
378
  ] }),
328
379
  /* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(Text4, { color: "yellow", dimColor: true, children: separator }) }),
329
380
  /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", justifyContent: "space-between", children: [
330
381
  /* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: "PROVIDER OUTPUT" }),
331
- userScrolled && /* @__PURE__ */ jsx4(Text4, { color: "yellow", dimColor: true, children: `scroll ${scrollPct}` }),
382
+ userScrolled && /* @__PURE__ */ jsx4(Text4, { color: "yellow", dimColor: true, children: scrollBar(scrollPctNum) }),
332
383
  !userScrolled && totalLines > bodyRows && /* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: "auto-scroll" })
333
384
  ] }),
334
385
  /* @__PURE__ */ jsx4(Box4, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: card.outputLog.length === 0 ? /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", marginTop: 1, children: [
335
386
  /* @__PURE__ */ jsx4(Text4, { color: "yellow", children: /* @__PURE__ */ jsx4(Spinner2, { type: "dots" }) }),
336
387
  /* @__PURE__ */ jsx4(Text4, { color: "gray", dimColor: true, children: " Waiting for provider output..." })
337
- ] }) : visibleLines.map((line, i) => (
338
- // biome-ignore lint/suspicious/noArrayIndexKey: log lines have no stable key
339
- /* @__PURE__ */ jsx4(Text4, { color: "white", dimColor: true, children: line }, i)
340
- )) })
388
+ ] }) : visibleLines.map((line, i) => {
389
+ const color = logLineColor(line);
390
+ return (
391
+ // biome-ignore lint/suspicious/noArrayIndexKey: log lines have no stable key
392
+ /* @__PURE__ */ jsx4(Text4, { color, dimColor: color === "white", children: line }, i)
393
+ );
394
+ }) })
341
395
  ]
342
396
  }
343
397
  );
@@ -402,7 +456,7 @@ function Sidebar({ provider, source, cwd, activeView, paused = false }) {
402
456
  /* @__PURE__ */ jsx5(Box5, { flexGrow: 1 }),
403
457
  /* @__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" }),
404
458
  activeView === "board" ? /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
405
- /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[Tab] next column" }),
459
+ /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u2190\u2192] columns " }),
406
460
  /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u2191\u2193] navigate " }),
407
461
  /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "[\u21B5] view detail " }),
408
462
  /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: paused ? "[p] resume " : "[p] pause " }),
@@ -425,6 +479,7 @@ function KanbanApp({ config }) {
425
479
  const [activeColIndex, setActiveColIndex] = useState3(0);
426
480
  const [activeCardIndex, setActiveCardIndex] = useState3(0);
427
481
  const [paused, setPaused] = useState3(false);
482
+ const [selectedCardId, setSelectedCardId] = useState3(null);
428
483
  useEffect3(() => {
429
484
  const onExit = () => exit();
430
485
  kanbanEmitter.on("tui:exit", onExit);
@@ -447,13 +502,34 @@ function KanbanApp({ config }) {
447
502
  }, [inProgress, workComplete]);
448
503
  const done = cards.filter((c) => c.column === "done");
449
504
  const columnCards = [backlog, inProgress, done];
505
+ useEffect3(() => {
506
+ if (!selectedCardId || activeView !== "detail") return;
507
+ const card = cards.find((c) => c.id === selectedCardId);
508
+ if (!card) return;
509
+ const colIndexMap = {
510
+ backlog: 0,
511
+ in_progress: 1,
512
+ done: 2
513
+ };
514
+ const newColIndex = colIndexMap[card.column];
515
+ const colCards = cards.filter((c) => c.column === card.column);
516
+ const newCardIndex = Math.max(
517
+ 0,
518
+ colCards.findIndex((c) => c.id === selectedCardId)
519
+ );
520
+ setActiveColIndex(newColIndex);
521
+ setActiveCardIndex(newCardIndex);
522
+ }, [cards, selectedCardId, activeView]);
450
523
  useInput2((input, key) => {
451
524
  if (input === "q") {
452
525
  process.emit("SIGINT");
453
526
  return;
454
527
  }
455
528
  if (activeView === "detail") {
456
- if (key.escape) setActiveView("board");
529
+ if (key.escape) {
530
+ setActiveView("board");
531
+ setSelectedCardId(null);
532
+ }
457
533
  return;
458
534
  }
459
535
  if (input === "p") {
@@ -462,14 +538,14 @@ function KanbanApp({ config }) {
462
538
  kanbanEmitter.emit(next ? "loop:pause" : "loop:resume");
463
539
  return;
464
540
  }
465
- if (key.tab && !key.shift) {
541
+ if (key.rightArrow) {
466
542
  const nextCol = (activeColIndex + 1) % 3;
467
543
  setActiveColIndex(nextCol);
468
544
  const colLen = columnCards[nextCol]?.length ?? 0;
469
545
  setActiveCardIndex(Math.min(activeCardIndex, Math.max(0, colLen - 1)));
470
546
  return;
471
547
  }
472
- if (key.tab && key.shift) {
548
+ if (key.leftArrow) {
473
549
  const prevCol = (activeColIndex + 2) % 3;
474
550
  setActiveColIndex(prevCol);
475
551
  const colLen = columnCards[prevCol]?.length ?? 0;
@@ -486,8 +562,11 @@ function KanbanApp({ config }) {
486
562
  return;
487
563
  }
488
564
  if (key.return) {
489
- const colLen = columnCards[activeColIndex]?.length ?? 0;
490
- if (colLen > 0) setActiveView("detail");
565
+ const card = columnCards[activeColIndex]?.[activeCardIndex];
566
+ if (card) {
567
+ setSelectedCardId(card.id);
568
+ setActiveView("detail");
569
+ }
491
570
  }
492
571
  });
493
572
  const labels = {
@@ -495,7 +574,7 @@ function KanbanApp({ config }) {
495
574
  inProgress: config.source_config.in_progress,
496
575
  done: config.source_config.done
497
576
  };
498
- const selectedCard = activeView === "detail" ? columnCards[activeColIndex]?.[activeCardIndex] ?? null : null;
577
+ const selectedCard = activeView === "detail" && selectedCardId ? cards.find((c) => c.id === selectedCardId) ?? null : null;
499
578
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "row", height: process.stdout.rows, children: [
500
579
  /* @__PURE__ */ jsx6(
501
580
  Sidebar,
@@ -515,9 +594,19 @@ function KanbanApp({ config }) {
515
594
  isEmpty,
516
595
  workComplete,
517
596
  activeColIndex,
518
- activeCardIndex
597
+ activeCardIndex,
598
+ paused
599
+ }
600
+ ) : /* @__PURE__ */ jsx6(
601
+ IssueDetail,
602
+ {
603
+ card: selectedCard,
604
+ onBack: () => {
605
+ setActiveView("board");
606
+ setSelectedCardId(null);
607
+ }
519
608
  }
520
- ) : /* @__PURE__ */ jsx6(IssueDetail, { card: selectedCard, onBack: () => setActiveView("board") })
609
+ )
521
610
  ] });
522
611
  }
523
612
  export {
package/package.json CHANGED
@@ -1,62 +1,60 @@
1
1
  {
2
- "name": "@tarcisiopgs/lisa",
3
- "version": "1.8.0",
4
- "description": "Autonomous issue resolver",
5
- "license": "MIT",
6
- "type": "module",
7
- "bin": {
8
- "lisa": "dist/index.js"
9
- },
10
- "scripts": {
11
- "build": "tsup",
12
- "dev": "tsx src/index.ts",
13
- "check": "biome check src/",
14
- "format": "biome format --write src/",
15
- "lint": "biome lint src/",
16
- "typecheck": "tsc --noEmit",
17
- "test": "vitest run",
18
- "test:watch": "vitest",
19
- "test:coverage": "vitest run --coverage",
20
- "ci": "concurrently -n lint,typecheck,test \"pnpm lint\" \"pnpm typecheck\" \"pnpm test\"",
21
- "prepare": "husky"
22
- },
23
- "dependencies": {
24
- "@clack/prompts": "^1.0.1",
25
- "citty": "^0.2.1",
26
- "execa": "^9.6.1",
27
- "ink": "^6.8.0",
28
- "ink-spinner": "^5.0.0",
29
- "picocolors": "^1.1.1",
30
- "react": "^19.2.4",
31
- "yaml": "^2.8.2"
32
- },
33
- "devDependencies": {
34
- "@biomejs/biome": "^2.4.3",
35
- "@types/node": "^22.13.4",
36
- "@types/react": "^19.2.14",
37
- "@vitest/coverage-v8": "^4.0.18",
38
- "concurrently": "^9.2.1",
39
- "husky": "^9.1.7",
40
- "lint-staged": "^16.2.7",
41
- "tsup": "^8.4.0",
42
- "tsx": "^4.19.3",
43
- "typescript": "^5.9.3",
44
- "vitest": "^4.0.18"
45
- },
46
- "packageManager": "pnpm@10.29.3",
47
- "publishConfig": {
48
- "access": "public"
49
- },
50
- "repository": {
51
- "type": "git",
52
- "url": "https://github.com/tarcisiopgs/lisa.git"
53
- },
54
- "files": [
55
- "dist"
56
- ],
57
- "lint-staged": {
58
- "*.{ts,tsx}": [
59
- "biome check --write"
60
- ]
61
- }
62
- }
2
+ "name": "@tarcisiopgs/lisa",
3
+ "version": "1.8.1",
4
+ "description": "Autonomous issue resolver",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "lisa": "dist/index.js"
9
+ },
10
+ "dependencies": {
11
+ "@clack/prompts": "^1.0.1",
12
+ "citty": "^0.2.1",
13
+ "execa": "^9.6.1",
14
+ "ink": "^6.8.0",
15
+ "ink-spinner": "^5.0.0",
16
+ "picocolors": "^1.1.1",
17
+ "react": "^19.2.4",
18
+ "yaml": "^2.8.2"
19
+ },
20
+ "devDependencies": {
21
+ "@biomejs/biome": "^2.4.3",
22
+ "@types/node": "^22.13.4",
23
+ "@types/react": "^19.2.14",
24
+ "@vitest/coverage-v8": "^4.0.18",
25
+ "concurrently": "^9.2.1",
26
+ "husky": "^9.1.7",
27
+ "lint-staged": "^16.2.7",
28
+ "tsup": "^8.4.0",
29
+ "tsx": "^4.19.3",
30
+ "typescript": "^5.9.3",
31
+ "vitest": "^4.0.18"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/tarcisiopgs/lisa.git"
39
+ },
40
+ "files": [
41
+ "dist"
42
+ ],
43
+ "lint-staged": {
44
+ "*.{ts,tsx}": [
45
+ "biome check --write"
46
+ ]
47
+ },
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "dev": "tsx src/index.ts",
51
+ "check": "biome check src/",
52
+ "format": "biome format --write src/",
53
+ "lint": "biome lint src/",
54
+ "typecheck": "tsc --noEmit",
55
+ "test": "vitest run",
56
+ "test:watch": "vitest",
57
+ "test:coverage": "vitest run --coverage",
58
+ "ci": "concurrently -n lint,typecheck,test \"pnpm lint\" \"pnpm typecheck\" \"pnpm test\""
59
+ }
60
+ }