@tarcisiopgs/lisa 1.7.1 → 1.7.3

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/dist/index.js CHANGED
@@ -337,39 +337,12 @@ function divider(session) {
337
337
  }
338
338
  function banner() {
339
339
  if (outputMode !== "default") return;
340
- const art = `
341
- @@%#@@
342
- @@%=--=%@ @@
343
- @@@@@@@@%@+------*@%%@%##*@
344
- @*=======---------===-----@@
345
- @=------------------------#@
346
- @=------------------------+@@
347
- @@=-------------------------+#%%%@@
348
- @@@#=--------------------------------%@
349
- @@*=------------------=---------------=@
350
- @%------=%--=%=--@==+@=--------------@@
351
- @@+-##+*%**#%=-+*+==+####*---------#@
352
- @%*%-::::::%#::::::::+@=---------#@
353
- @@@-:++::::@-::::=::::*%*=--------*@@
354
- @+:==::::%=::::#-:::%==----------=@@
355
- @@+:=%%%%*#+::::::+%=-----------=@@
356
- @%*@=-----=*******---*+=-----=%@
357
- @%=--+##**#=----------#++##----=@
358
- @-----------------#=---**+%-----%@
359
- @%*+=-----===++**#@#--%**#=-==++%@
360
- @@@%%@#*+++=---=--=%----%%%@@@
361
- @@@----------*@#**#@
362
- @@@=---------#@@
363
- @+*%*%%###%*%%=-@
364
- @%@+=#@==@#:+@##@
365
- @@@@%%@##%
366
- `;
367
- const title = " Lisa \u2014 deterministic autonomous issue resolver ";
340
+ const title = " lisa \u266A autonomous issue resolver ";
368
341
  const border = "\u2500".repeat(title.length);
369
- console.log(pc.yellow(art));
370
- console.log(pc.cyan(` \u250C${border}\u2510`));
371
- console.log(pc.cyan(` \u2502${title}\u2502`));
372
- console.log(pc.cyan(` \u2514${border}\u2518
342
+ console.log(pc.yellow(`
343
+ \u250C${border}\u2510`));
344
+ console.log(pc.yellow(` \u2502`) + pc.bold(pc.white(title)) + pc.yellow("\u2502"));
345
+ console.log(pc.yellow(` \u2514${border}\u2518
373
346
  `));
374
347
  }
375
348
 
@@ -1585,12 +1558,9 @@ var providers = {
1585
1558
  goose: () => new GooseProvider(),
1586
1559
  aider: () => new AiderProvider()
1587
1560
  };
1588
- async function getAvailableProviders() {
1561
+ async function getAllProvidersWithAvailability() {
1589
1562
  const all = Object.values(providers).map((f) => f());
1590
- const results = await Promise.all(
1591
- all.map(async (p) => ({ provider: p, available: await p.isAvailable() }))
1592
- );
1593
- return results.filter((r) => r.available).map((r) => r.provider);
1563
+ return Promise.all(all.map(async (p) => ({ provider: p, available: await p.isAvailable() })));
1594
1564
  }
1595
1565
  function createProvider(name) {
1596
1566
  const factory = providers[name];
@@ -4122,7 +4092,7 @@ Add them to your ${shell} and run: source ${shell}`));
4122
4092
  if (isTUI) {
4123
4093
  const { render } = await import("ink");
4124
4094
  const { createElement } = await import("react");
4125
- const { KanbanApp } = await import("./kanban-BY7QNVEE.js");
4095
+ const { KanbanApp } = await import("./kanban-KPIDX2SU.js");
4126
4096
  render(createElement(KanbanApp, { config: merged }), { exitOnCtrlC: false });
4127
4097
  }
4128
4098
  await runLoop(merged, {
@@ -4172,7 +4142,7 @@ var init = defineCommand({
4172
4142
  }
4173
4143
  if (configExists()) {
4174
4144
  const overwrite = await clack.confirm({
4175
- message: "Config already exists. Overwrite?"
4145
+ message: "A config already exists at .lisa/config.yaml. Overwrite it?"
4176
4146
  });
4177
4147
  if (clack.isCancel(overwrite) || !overwrite) {
4178
4148
  log("Cancelled.");
@@ -4342,7 +4312,7 @@ var main = defineCommand({
4342
4312
  subCommands: { run, config, init, status, issue }
4343
4313
  });
4344
4314
  async function runConfigWizard() {
4345
- banner();
4315
+ clack.intro(pc2.cyan(" lisa \u266A autonomous issue resolver "));
4346
4316
  const providerLabels = {
4347
4317
  claude: "Claude Code",
4348
4318
  gemini: "Gemini CLI",
@@ -4356,30 +4326,34 @@ async function runConfigWizard() {
4356
4326
  claude: ["claude-sonnet-4-6", "claude-opus-4-6", "claude-haiku-4-5"],
4357
4327
  gemini: ["gemini-2.5-pro", "gemini-2.0-flash", "gemini-1.5-pro"]
4358
4328
  };
4359
- const available = await getAvailableProviders();
4329
+ const allProviders = await getAllProvidersWithAvailability();
4330
+ const available = allProviders.filter((r) => r.available).map((r) => r.provider);
4360
4331
  if (available.length === 0) {
4361
- clack.log.error("No compatible AI providers found.");
4332
+ clack.log.error("No AI provider found on your system.");
4362
4333
  clack.log.info(
4363
- `Install at least one of the following providers to continue:
4364
-
4365
- ${pc2.bold("Claude Code")} ${pc2.dim("npm i -g @anthropic-ai/claude-code")}
4366
- ${pc2.bold("Gemini CLI")} ${pc2.dim("npm i -g @anthropic-ai/gemini-cli")}
4367
- ${pc2.bold("OpenCode")} ${pc2.dim("npm i -g opencode")}
4334
+ `Install at least one of the following and re-run ${pc2.cyan("lisa init")}:
4368
4335
 
4369
- After installing, run ${pc2.cyan("lisa init")} again.`
4336
+ ${pc2.bold("Claude Code")} ${pc2.dim("npm i -g @anthropic-ai/claude-code")}
4337
+ ${pc2.bold("Gemini CLI")} ${pc2.dim("npm i -g @google/gemini-cli")}
4338
+ ${pc2.bold("OpenCode")} ${pc2.dim("npm i -g opencode")}
4339
+ ${pc2.bold("GitHub Copilot CLI")} ${pc2.dim("npm i -g @github/copilot-cli")}
4340
+ ${pc2.bold("Goose")} ${pc2.dim("https://block.github.io/goose")}
4341
+ ${pc2.bold("Aider")} ${pc2.dim("pip install aider-chat")}`
4370
4342
  );
4371
4343
  return process.exit(1);
4372
4344
  }
4373
4345
  let providerName;
4374
4346
  if (available.length === 1 && available[0]) {
4375
4347
  providerName = available[0].name;
4376
- clack.log.info(`Found provider: ${pc2.bold(providerLabels[providerName])}`);
4348
+ clack.log.info(`Auto-detected ${pc2.bold(providerLabels[providerName])} as your AI provider.`);
4377
4349
  } else {
4378
4350
  const selected = await clack.select({
4379
- message: "Which AI provider do you want to use?",
4380
- options: available.map((p) => ({
4381
- value: p.name,
4382
- label: providerLabels[p.name]
4351
+ message: "Which AI provider should resolve your issues?",
4352
+ options: allProviders.map(({ provider, available: isAvailable }) => ({
4353
+ value: provider.name,
4354
+ label: providerLabels[provider.name],
4355
+ hint: isAvailable ? void 0 : "not installed",
4356
+ disabled: !isAvailable
4383
4357
  }))
4384
4358
  });
4385
4359
  if (clack.isCancel(selected)) return process.exit(0);
@@ -4391,14 +4365,14 @@ After installing, run ${pc2.cyan("lisa init")} again.`
4391
4365
  const isFree = await isCursorFreePlan();
4392
4366
  if (isFree) {
4393
4367
  availableModels = ["auto"];
4394
- clack.log.info("Cursor Free plan detected. Using 'auto' model only.");
4368
+ clack.log.info("Cursor Free plan detected \u2014 only the 'auto' model is available.");
4395
4369
  } else {
4396
4370
  availableModels = CURSOR_MODELS;
4397
4371
  }
4398
4372
  }
4399
4373
  if (availableModels && availableModels.length > 0) {
4400
4374
  const modelSelection = await clack.multiselect({
4401
- message: "Which models to use? Select in order: primary first, then fallbacks",
4375
+ message: "Which models should Lisa use? Select in order \u2014 first = primary, rest = fallbacks",
4402
4376
  options: availableModels.map((m) => ({
4403
4377
  value: m,
4404
4378
  label: m
@@ -4409,35 +4383,76 @@ After installing, run ${pc2.cyan("lisa init")} again.`
4409
4383
  selectedModels = modelSelection ?? [];
4410
4384
  }
4411
4385
  const source = await clack.select({
4412
- message: "Where do your issues live?",
4386
+ message: "Where do your issues come from?",
4413
4387
  options: [
4414
- { value: "linear", label: "Linear" },
4415
- { value: "trello", label: "Trello" }
4416
- ]
4388
+ { value: "linear", label: "Linear", apiHint: "GraphQL API", envVars: ["LINEAR_API_KEY"] },
4389
+ {
4390
+ value: "trello",
4391
+ label: "Trello",
4392
+ apiHint: "REST API",
4393
+ envVars: ["TRELLO_API_KEY", "TRELLO_TOKEN"]
4394
+ },
4395
+ {
4396
+ value: "github-issues",
4397
+ label: "GitHub Issues",
4398
+ apiHint: "REST API",
4399
+ envVars: ["GITHUB_TOKEN"]
4400
+ },
4401
+ {
4402
+ value: "gitlab-issues",
4403
+ label: "GitLab Issues",
4404
+ apiHint: "REST API",
4405
+ envVars: ["GITLAB_TOKEN"]
4406
+ },
4407
+ { value: "plane", label: "Plane", apiHint: "REST API", envVars: ["PLANE_API_TOKEN"] },
4408
+ {
4409
+ value: "shortcut",
4410
+ label: "Shortcut",
4411
+ apiHint: "REST API",
4412
+ envVars: ["SHORTCUT_API_TOKEN"]
4413
+ },
4414
+ {
4415
+ value: "jira",
4416
+ label: "Jira",
4417
+ apiHint: "REST API",
4418
+ envVars: ["JIRA_BASE_URL", "JIRA_EMAIL", "JIRA_API_TOKEN"]
4419
+ }
4420
+ ].map(({ value, label: label2, apiHint, envVars }) => {
4421
+ const missing2 = envVars.filter((v) => !process.env[v]);
4422
+ return {
4423
+ value,
4424
+ label: label2,
4425
+ hint: missing2.length > 0 ? `missing: ${missing2.join(", ")}` : apiHint,
4426
+ disabled: missing2.length > 0
4427
+ };
4428
+ })
4417
4429
  });
4418
4430
  if (clack.isCancel(source)) return process.exit(0);
4419
4431
  const missing = await getMissingEnvVars(source);
4420
4432
  if (missing.length > 0) {
4421
4433
  const shell = process.env.SHELL?.includes("zsh") ? "~/.zshrc" : "~/.bashrc";
4422
4434
  clack.log.warning(
4423
- `Missing environment variables:
4435
+ `The following environment variables are missing:
4436
+
4424
4437
  ${missing.map((v) => ` ${pc2.bold(v)}`).join("\n")}
4425
4438
 
4426
- Add them to your environment variables:
4427
- ${missing.map((v) => ` export ${v}="your-key-here"`).join("\n")}
4439
+ Add them to ${pc2.cyan(shell)}:
4440
+ ${missing.map((v) => ` export ${v}="your-value-here"`).join("\n")}
4428
4441
 
4429
- Then run: ${pc2.cyan(`source ${shell}`)}`
4442
+ Then reload: ${pc2.cyan(`source ${shell}`)}`
4430
4443
  );
4431
4444
  }
4432
4445
  const githubMethod = await detectGitHubMethod();
4433
4446
  const teamAnswer = await clack.text({
4434
- message: source === "linear" ? "Team?" : "Board?"
4447
+ message: source === "linear" ? "What is your Linear team name?" : source === "trello" ? "What is your Trello board name?" : source === "jira" ? "What is your Jira project key?" : "What is your team or project name?",
4448
+ placeholder: source === "linear" ? "e.g. Engineering" : void 0
4435
4449
  });
4436
4450
  if (clack.isCancel(teamAnswer)) return process.exit(0);
4437
4451
  const team = teamAnswer;
4438
4452
  const labelAnswer = await clack.text({
4439
- message: "Label to pick up?",
4440
- initialValue: "ready"
4453
+ message: "Which label marks issues as ready for the agent to pick up?",
4454
+ initialValue: "ready",
4455
+ placeholder: "e.g. ready, ai, lisa"
4441
4456
  });
4442
4457
  if (clack.isCancel(labelAnswer)) return process.exit(0);
4443
4458
  const label = labelAnswer;
@@ -4454,47 +4469,57 @@ Then run: ${pc2.cyan(`source ${shell}`)}`
4454
4469
  pickFrom = pickFromAnswer;
4455
4470
  project = pickFrom;
4456
4471
  const inProgressAnswer = await clack.text({
4457
- message: "Move to which column while working?",
4472
+ message: "Move the card to which list while the agent is working?",
4458
4473
  initialValue: "In Progress"
4459
4474
  });
4460
4475
  if (clack.isCancel(inProgressAnswer)) return process.exit(0);
4461
4476
  inProgress = inProgressAnswer;
4462
4477
  const doneAnswer = await clack.text({
4463
- message: "Move to which column after PR?",
4478
+ message: "Move the card to which list after the PR is created?",
4464
4479
  initialValue: "Code Review"
4465
4480
  });
4466
4481
  if (clack.isCancel(doneAnswer)) return process.exit(0);
4467
4482
  done = doneAnswer;
4468
4483
  } else {
4469
4484
  const projectAnswer = await clack.text({
4470
- message: "Project?"
4485
+ message: source === "linear" ? "Which Linear project should Lisa work on? (leave empty for all team issues)" : "Which project should Lisa work on?",
4486
+ placeholder: source === "linear" ? "e.g. Q1 Roadmap (optional)" : void 0
4471
4487
  });
4472
4488
  if (clack.isCancel(projectAnswer)) return process.exit(0);
4473
4489
  project = projectAnswer;
4474
4490
  const pickFromAnswer = await clack.text({
4475
- message: "Pick up issues from which status?",
4476
- initialValue: "Backlog"
4491
+ message: "Pick up issues in which status?",
4492
+ initialValue: "Backlog",
4493
+ placeholder: "e.g. Backlog, Todo"
4477
4494
  });
4478
4495
  if (clack.isCancel(pickFromAnswer)) return process.exit(0);
4479
4496
  pickFrom = pickFromAnswer;
4480
4497
  const inProgressAnswer = await clack.text({
4481
- message: "Move to which status while working?",
4498
+ message: "Move to which status while the agent is working?",
4482
4499
  initialValue: "In Progress"
4483
4500
  });
4484
4501
  if (clack.isCancel(inProgressAnswer)) return process.exit(0);
4485
4502
  inProgress = inProgressAnswer;
4486
4503
  const doneAnswer = await clack.text({
4487
- message: "Move to which status after PR?",
4504
+ message: "Move to which status after the PR is created?",
4488
4505
  initialValue: "In Review"
4489
4506
  });
4490
4507
  if (clack.isCancel(doneAnswer)) return process.exit(0);
4491
4508
  done = doneAnswer;
4492
4509
  }
4493
4510
  const workflowAnswer = await clack.select({
4494
- message: "How should Lisa work on issues?",
4511
+ message: "How should Lisa check out code for each issue?",
4495
4512
  options: [
4496
- { value: "branch", label: "Branch", hint: "creates branches in the current checkout" },
4497
- { value: "worktree", label: "Worktree", hint: "creates isolated worktrees per issue" }
4513
+ {
4514
+ value: "worktree",
4515
+ label: "Worktree",
4516
+ hint: "isolated git worktree per issue \u2014 recommended"
4517
+ },
4518
+ {
4519
+ value: "branch",
4520
+ label: "Branch",
4521
+ hint: "new branch in the current checkout"
4522
+ }
4498
4523
  ]
4499
4524
  });
4500
4525
  if (clack.isCancel(workflowAnswer)) return process.exit(0);
@@ -4505,7 +4530,7 @@ Then run: ${pc2.cyan(`source ${shell}`)}`
4505
4530
  if (repos.length === 0) {
4506
4531
  const detected = detectDefaultBranch(cwd);
4507
4532
  const branchAnswer = await clack.text({
4508
- message: "Base branch?",
4533
+ message: "What is the base branch to branch off from?",
4509
4534
  initialValue: detected
4510
4535
  });
4511
4536
  if (clack.isCancel(branchAnswer)) return process.exit(0);
@@ -4515,7 +4540,7 @@ Then run: ${pc2.cyan(`source ${shell}`)}`
4515
4540
  const repoPath = resolvePath(cwd, repo.path);
4516
4541
  const detected = detectDefaultBranch(repoPath);
4517
4542
  const branchAnswer = await clack.text({
4518
- message: `Base branch for ${repo.name}?`,
4543
+ message: `Base branch for ${pc2.bold(repo.name)}?`,
4519
4544
  initialValue: detected
4520
4545
  });
4521
4546
  if (clack.isCancel(branchAnswer)) return process.exit(0);
@@ -4530,7 +4555,7 @@ Then run: ${pc2.cyan(`source ${shell}`)}`
4530
4555
  ensureWorktreeGitignore(resolvePath(cwd, repo.path));
4531
4556
  }
4532
4557
  }
4533
- clack.log.info("Added .worktrees to .gitignore");
4558
+ clack.log.info("Added .worktrees/ to .gitignore");
4534
4559
  }
4535
4560
  const cfg = {
4536
4561
  provider: providerName,
@@ -4553,28 +4578,31 @@ Then run: ${pc2.cyan(`source ${shell}`)}`
4553
4578
  logs: { dir: ".lisa/logs", format: "text" }
4554
4579
  };
4555
4580
  saveConfig(cfg);
4556
- clack.outro(pc2.green("Config saved to .lisa/config.yaml"));
4581
+ clack.outro(
4582
+ `${pc2.green("All set!")} Config saved to ${pc2.cyan(".lisa/config.yaml")}
4583
+ Run ${pc2.bold(pc2.cyan("lisa run"))} to start resolving issues.`
4584
+ );
4557
4585
  }
4558
4586
  async function detectGitHubMethod() {
4559
4587
  const hasToken = !!process.env.GITHUB_TOKEN;
4560
4588
  const hasCli = await isGhCliAvailable();
4561
4589
  if (hasToken && hasCli) {
4562
4590
  const selected = await clack.select({
4563
- message: "Both GitHub CLI and GITHUB_TOKEN detected. Which do you want to use?",
4591
+ message: "How should Lisa create pull requests?",
4564
4592
  options: [
4565
- { value: "cli", label: "GitHub CLI", hint: "gh" },
4566
- { value: "token", label: "GitHub API", hint: "GITHUB_TOKEN" }
4593
+ { value: "cli", label: "GitHub CLI", hint: "uses `gh pr create` \u2014 recommended" },
4594
+ { value: "token", label: "GitHub API", hint: "uses GITHUB_TOKEN directly" }
4567
4595
  ]
4568
4596
  });
4569
4597
  if (clack.isCancel(selected)) return process.exit(0);
4570
4598
  return selected;
4571
4599
  }
4572
4600
  if (hasCli) {
4573
- clack.log.info("Using GitHub CLI for pull requests.");
4601
+ clack.log.info("Pull requests will be created using the GitHub CLI.");
4574
4602
  return "cli";
4575
4603
  }
4576
4604
  if (hasToken) {
4577
- clack.log.info("Using GITHUB_TOKEN for pull requests.");
4605
+ clack.log.info("Pull requests will be created using GITHUB_TOKEN.");
4578
4606
  return "token";
4579
4607
  }
4580
4608
  return "token";
@@ -4582,7 +4610,7 @@ async function detectGitHubMethod() {
4582
4610
  async function detectGitRepos() {
4583
4611
  const cwd = process.cwd();
4584
4612
  if (existsSync7(join12(cwd, ".git"))) {
4585
- clack.log.info(`Detected git repository in current directory.`);
4613
+ clack.log.info("Found a git repository in the current directory.");
4586
4614
  return [];
4587
4615
  }
4588
4616
  const entries = readdirSync(cwd, { withFileTypes: true });
@@ -4591,7 +4619,7 @@ async function detectGitRepos() {
4591
4619
  return [];
4592
4620
  }
4593
4621
  const selected = await clack.multiselect({
4594
- message: "Select the repos to include in the workspace:",
4622
+ message: "Multiple git repositories found \u2014 which ones should Lisa work on?",
4595
4623
  options: gitDirs.map((dir) => ({ value: dir, label: dir }))
4596
4624
  });
4597
4625
  if (clack.isCancel(selected)) return process.exit(0);
@@ -4633,6 +4661,17 @@ async function getMissingEnvVars(source) {
4633
4661
  } else if (source === "trello") {
4634
4662
  if (!process.env.TRELLO_API_KEY) missing.push("TRELLO_API_KEY");
4635
4663
  if (!process.env.TRELLO_TOKEN) missing.push("TRELLO_TOKEN");
4664
+ } else if (source === "github-issues") {
4665
+ } else if (source === "gitlab-issues") {
4666
+ if (!process.env.GITLAB_TOKEN) missing.push("GITLAB_TOKEN");
4667
+ } else if (source === "plane") {
4668
+ if (!process.env.PLANE_API_TOKEN) missing.push("PLANE_API_TOKEN");
4669
+ } else if (source === "shortcut") {
4670
+ if (!process.env.SHORTCUT_API_TOKEN) missing.push("SHORTCUT_API_TOKEN");
4671
+ } else if (source === "jira") {
4672
+ if (!process.env.JIRA_BASE_URL) missing.push("JIRA_BASE_URL");
4673
+ if (!process.env.JIRA_EMAIL) missing.push("JIRA_EMAIL");
4674
+ if (!process.env.JIRA_API_TOKEN) missing.push("JIRA_API_TOKEN");
4636
4675
  }
4637
4676
  return missing;
4638
4677
  }
@@ -362,9 +362,11 @@ function Sidebar({ provider, source, cwd }) {
362
362
  /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginBottom: 1, children: [
363
363
  /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557" }),
364
364
  /* @__PURE__ */ jsxs5(Text5, { color: "yellow", children: [
365
- "\u2551",
366
- /* @__PURE__ */ jsx5(Text5, { color: "white", bold: true, children: " L I S A v 2 " }),
367
- /* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "\u2551" })
365
+ "\u2551 ",
366
+ /* @__PURE__ */ jsx5(Text5, { color: "white", bold: true, children: "L I S A " }),
367
+ /* @__PURE__ */ jsx5(Text5, { color: "yellow", bold: true, children: "\u266A" }),
368
+ /* @__PURE__ */ jsx5(Text5, { color: "white", bold: true, children: " " }),
369
+ "\u2551"
368
370
  ] }),
369
371
  /* @__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" })
370
372
  ] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tarcisiopgs/lisa",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Deterministic autonomous issue resolver — structured AI agent loop for Linear/Trello",
5
5
  "license": "MIT",
6
6
  "type": "module",