@tarcisiopgs/lisa 1.7.3 → 1.7.5
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.
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// src/output/terminal.ts
|
|
4
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
5
|
+
var SPINNER_INTERVAL_MS = 80;
|
|
6
|
+
var spinnerTimer = null;
|
|
7
|
+
var spinnerFrame = 0;
|
|
8
|
+
function isTTY() {
|
|
9
|
+
return process.stdout.isTTY === true;
|
|
10
|
+
}
|
|
11
|
+
function writeOSC(title) {
|
|
12
|
+
process.stdout.write(`\x1B]0;${title}\x07`);
|
|
13
|
+
}
|
|
14
|
+
function setTitle(title) {
|
|
15
|
+
if (!isTTY()) return;
|
|
16
|
+
writeOSC(title);
|
|
17
|
+
}
|
|
18
|
+
function startSpinner(message) {
|
|
19
|
+
if (!isTTY()) return;
|
|
20
|
+
stopSpinner();
|
|
21
|
+
spinnerFrame = 0;
|
|
22
|
+
writeOSC(`${SPINNER_FRAMES[0]} Lisa \u2014 ${message}`);
|
|
23
|
+
spinnerTimer = setInterval(() => {
|
|
24
|
+
spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES.length;
|
|
25
|
+
writeOSC(`${SPINNER_FRAMES[spinnerFrame]} Lisa \u2014 ${message}`);
|
|
26
|
+
}, SPINNER_INTERVAL_MS);
|
|
27
|
+
}
|
|
28
|
+
function stopSpinner(message) {
|
|
29
|
+
if (spinnerTimer) {
|
|
30
|
+
clearInterval(spinnerTimer);
|
|
31
|
+
spinnerTimer = null;
|
|
32
|
+
}
|
|
33
|
+
if (!isTTY()) return;
|
|
34
|
+
if (message) {
|
|
35
|
+
writeOSC(message);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function notify() {
|
|
39
|
+
if (!isTTY()) return;
|
|
40
|
+
process.stdout.write("\x07");
|
|
41
|
+
}
|
|
42
|
+
function resetTitle() {
|
|
43
|
+
if (!isTTY()) return;
|
|
44
|
+
writeOSC("");
|
|
45
|
+
}
|
|
46
|
+
|
|
3
47
|
// src/ui/state.ts
|
|
4
48
|
import { EventEmitter } from "events";
|
|
5
49
|
import { useEffect, useState } from "react";
|
|
@@ -68,6 +112,11 @@ function useKanbanState() {
|
|
|
68
112
|
}
|
|
69
113
|
|
|
70
114
|
export {
|
|
115
|
+
setTitle,
|
|
116
|
+
startSpinner,
|
|
117
|
+
stopSpinner,
|
|
118
|
+
notify,
|
|
119
|
+
resetTitle,
|
|
71
120
|
kanbanEmitter,
|
|
72
121
|
useKanbanState
|
|
73
122
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
kanbanEmitter
|
|
4
|
-
|
|
3
|
+
kanbanEmitter,
|
|
4
|
+
notify,
|
|
5
|
+
resetTitle,
|
|
6
|
+
setTitle,
|
|
7
|
+
startSpinner,
|
|
8
|
+
stopSpinner
|
|
9
|
+
} from "./chunk-YZKNBQN6.js";
|
|
5
10
|
|
|
6
11
|
// src/cli.ts
|
|
7
12
|
import { execSync as execSync8 } from "child_process";
|
|
@@ -346,52 +351,6 @@ function banner() {
|
|
|
346
351
|
`));
|
|
347
352
|
}
|
|
348
353
|
|
|
349
|
-
// src/output/terminal.ts
|
|
350
|
-
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
351
|
-
var SPINNER_INTERVAL_MS = 80;
|
|
352
|
-
var spinnerTimer = null;
|
|
353
|
-
var spinnerFrame = 0;
|
|
354
|
-
function isTTY() {
|
|
355
|
-
return process.stdout.isTTY === true;
|
|
356
|
-
}
|
|
357
|
-
function writeOSC(title) {
|
|
358
|
-
process.stdout.write(`\x1B]0;${title}\x07`);
|
|
359
|
-
}
|
|
360
|
-
function setTitle(title) {
|
|
361
|
-
if (!isTTY()) return;
|
|
362
|
-
writeOSC(title);
|
|
363
|
-
}
|
|
364
|
-
function startSpinner(message) {
|
|
365
|
-
if (!isTTY()) return;
|
|
366
|
-
if (getOutputMode() === "tui") return;
|
|
367
|
-
stopSpinner();
|
|
368
|
-
spinnerFrame = 0;
|
|
369
|
-
writeOSC(`${SPINNER_FRAMES[0]} Lisa \u2014 ${message}`);
|
|
370
|
-
spinnerTimer = setInterval(() => {
|
|
371
|
-
spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES.length;
|
|
372
|
-
writeOSC(`${SPINNER_FRAMES[spinnerFrame]} Lisa \u2014 ${message}`);
|
|
373
|
-
}, SPINNER_INTERVAL_MS);
|
|
374
|
-
}
|
|
375
|
-
function stopSpinner(message) {
|
|
376
|
-
if (spinnerTimer) {
|
|
377
|
-
clearInterval(spinnerTimer);
|
|
378
|
-
spinnerTimer = null;
|
|
379
|
-
}
|
|
380
|
-
if (!isTTY()) return;
|
|
381
|
-
if (getOutputMode() === "tui") return;
|
|
382
|
-
if (message) {
|
|
383
|
-
writeOSC(message);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
function notify() {
|
|
387
|
-
if (!isTTY()) return;
|
|
388
|
-
process.stdout.write("\x07");
|
|
389
|
-
}
|
|
390
|
-
function resetTitle() {
|
|
391
|
-
if (!isTTY()) return;
|
|
392
|
-
writeOSC("");
|
|
393
|
-
}
|
|
394
|
-
|
|
395
354
|
// src/prompt.ts
|
|
396
355
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
397
356
|
import { join as join2, resolve as resolve3 } from "path";
|
|
@@ -4092,7 +4051,7 @@ Add them to your ${shell} and run: source ${shell}`));
|
|
|
4092
4051
|
if (isTUI) {
|
|
4093
4052
|
const { render } = await import("ink");
|
|
4094
4053
|
const { createElement } = await import("react");
|
|
4095
|
-
const { KanbanApp } = await import("./kanban-
|
|
4054
|
+
const { KanbanApp } = await import("./kanban-YP3TJJUT.js");
|
|
4096
4055
|
render(createElement(KanbanApp, { config: merged }), { exitOnCtrlC: false });
|
|
4097
4056
|
}
|
|
4098
4057
|
await runLoop(merged, {
|
|
@@ -4141,15 +4100,14 @@ var init = defineCommand({
|
|
|
4141
4100
|
process.exit(1);
|
|
4142
4101
|
}
|
|
4143
4102
|
if (configExists()) {
|
|
4144
|
-
const
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4103
|
+
const existing = loadConfig();
|
|
4104
|
+
clack.log.info(
|
|
4105
|
+
`Existing config found \u2014 current values will be pre-filled. Edit what you need, keep the rest.`
|
|
4106
|
+
);
|
|
4107
|
+
await runConfigWizard(existing);
|
|
4108
|
+
} else {
|
|
4109
|
+
await runConfigWizard();
|
|
4151
4110
|
}
|
|
4152
|
-
await runConfigWizard();
|
|
4153
4111
|
}
|
|
4154
4112
|
});
|
|
4155
4113
|
var status = defineCommand({
|
|
@@ -4289,20 +4247,62 @@ var issue = defineCommand({
|
|
|
4289
4247
|
meta: { name: "issue", description: "Issue tracker operations for use inside worktrees" },
|
|
4290
4248
|
subCommands: { get: issueGet, done: issueDone }
|
|
4291
4249
|
});
|
|
4292
|
-
var
|
|
4250
|
+
var CURSOR_MODELS_FALLBACK = [
|
|
4293
4251
|
"auto",
|
|
4294
4252
|
"composer-1.5",
|
|
4295
|
-
"
|
|
4296
|
-
"
|
|
4297
|
-
"gpt-5.3-codex-low",
|
|
4298
|
-
"gpt-5.3-codex-high",
|
|
4299
|
-
"gpt-5.3-codex-xhigh",
|
|
4300
|
-
"gpt-5.3-codex-fast",
|
|
4253
|
+
"opus-4.6-thinking",
|
|
4254
|
+
"opus-4.6",
|
|
4301
4255
|
"sonnet-4.6",
|
|
4302
|
-
"
|
|
4303
|
-
"
|
|
4304
|
-
"
|
|
4256
|
+
"gpt-5.3-codex",
|
|
4257
|
+
"gpt-5.2",
|
|
4258
|
+
"gemini-3.1-pro"
|
|
4305
4259
|
];
|
|
4260
|
+
function fetchCursorModels() {
|
|
4261
|
+
try {
|
|
4262
|
+
const bin = ["agent", "cursor-agent"].find((b) => {
|
|
4263
|
+
try {
|
|
4264
|
+
execSync8(`${b} --version`, { stdio: "ignore" });
|
|
4265
|
+
return true;
|
|
4266
|
+
} catch {
|
|
4267
|
+
return false;
|
|
4268
|
+
}
|
|
4269
|
+
});
|
|
4270
|
+
if (!bin) return CURSOR_MODELS_FALLBACK;
|
|
4271
|
+
const raw = execSync8(`${bin} --list-models`, { encoding: "utf-8", timeout: 1e4 });
|
|
4272
|
+
const clean = raw.replace(/\x1b\[[0-9;]*[mGKHFA-Z]/g, "");
|
|
4273
|
+
const models = clean.split("\n").map((l) => l.trim()).filter((l) => l.includes(" - ")).map((l) => (l.split(" - ")[0] ?? "").trim()).filter(Boolean);
|
|
4274
|
+
return models.length > 0 ? models : CURSOR_MODELS_FALLBACK;
|
|
4275
|
+
} catch {
|
|
4276
|
+
return CURSOR_MODELS_FALLBACK;
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
function fetchOpenCodeModels() {
|
|
4280
|
+
try {
|
|
4281
|
+
const raw = execSync8("opencode models", { encoding: "utf-8", timeout: 1e4 });
|
|
4282
|
+
const hasAnthropic = Boolean(process.env.ANTHROPIC_API_KEY);
|
|
4283
|
+
const hasGoogle = Boolean(
|
|
4284
|
+
process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY
|
|
4285
|
+
);
|
|
4286
|
+
const hasOpenAI = Boolean(process.env.OPENAI_API_KEY);
|
|
4287
|
+
const hasCopilot = Boolean(process.env.GITHUB_COPILOT_API_KEY || process.env.GITHUB_TOKEN);
|
|
4288
|
+
const hasGroq = Boolean(process.env.GROQ_API_KEY);
|
|
4289
|
+
const hasMistral = Boolean(process.env.MISTRAL_API_KEY);
|
|
4290
|
+
const hasDeepSeek = Boolean(process.env.DEEPSEEK_API_KEY);
|
|
4291
|
+
return raw.split("\n").map((l) => l.trim()).filter((m) => {
|
|
4292
|
+
if (/^opencode\//.test(m)) return true;
|
|
4293
|
+
if (/^anthropic\/claude-(opus|sonnet|haiku)-4-\d+$/.test(m)) return hasAnthropic;
|
|
4294
|
+
if (/^google\/gemini-2\.5-(pro|flash|flash-lite)$/.test(m)) return hasGoogle;
|
|
4295
|
+
if (/^openai\//.test(m)) return hasOpenAI;
|
|
4296
|
+
if (/^github-copilot\//.test(m)) return hasCopilot;
|
|
4297
|
+
if (/^groq\//.test(m)) return hasGroq;
|
|
4298
|
+
if (/^mistral\//.test(m)) return hasMistral;
|
|
4299
|
+
if (/^deepseek\//.test(m)) return hasDeepSeek;
|
|
4300
|
+
return false;
|
|
4301
|
+
});
|
|
4302
|
+
} catch {
|
|
4303
|
+
return [];
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
4306
|
var main = defineCommand({
|
|
4307
4307
|
meta: {
|
|
4308
4308
|
name: "lisa",
|
|
@@ -4311,8 +4311,10 @@ var main = defineCommand({
|
|
|
4311
4311
|
},
|
|
4312
4312
|
subCommands: { run, config, init, status, issue }
|
|
4313
4313
|
});
|
|
4314
|
-
async function runConfigWizard() {
|
|
4315
|
-
clack.intro(
|
|
4314
|
+
async function runConfigWizard(existing) {
|
|
4315
|
+
clack.intro(
|
|
4316
|
+
pc2.cyan(existing ? " lisa \u266A editing config " : " lisa \u266A autonomous issue resolver ")
|
|
4317
|
+
);
|
|
4316
4318
|
const providerLabels = {
|
|
4317
4319
|
claude: "Claude Code",
|
|
4318
4320
|
gemini: "Gemini CLI",
|
|
@@ -4323,8 +4325,13 @@ async function runConfigWizard() {
|
|
|
4323
4325
|
aider: "Aider"
|
|
4324
4326
|
};
|
|
4325
4327
|
const providerModels = {
|
|
4326
|
-
claude: ["claude-
|
|
4327
|
-
gemini: ["gemini-2.5-pro", "gemini-2.
|
|
4328
|
+
claude: ["claude-opus-4-6", "claude-sonnet-4-6", "claude-haiku-4-5", "claude-sonnet-4-5"],
|
|
4329
|
+
gemini: ["gemini-2.5-pro", "gemini-2.5-flash", "gemini-2.5-flash-lite"],
|
|
4330
|
+
// opencode: populated dynamically below (fetchOpenCodeModels)
|
|
4331
|
+
copilot: ["claude-opus-4.6", "claude-sonnet-4.6", "claude-haiku-4.5", "gpt-5.2"],
|
|
4332
|
+
goose: ["claude-sonnet-4-5", "claude-opus-4-5", "claude-haiku-4-5"],
|
|
4333
|
+
aider: ["claude-opus-4-6", "claude-sonnet-4-5", "claude-haiku-4-5"]
|
|
4334
|
+
// cursor: populated dynamically below (fetchCursorModels)
|
|
4328
4335
|
};
|
|
4329
4336
|
const allProviders = await getAllProvidersWithAvailability();
|
|
4330
4337
|
const available = allProviders.filter((r) => r.available).map((r) => r.provider);
|
|
@@ -4343,12 +4350,13 @@ async function runConfigWizard() {
|
|
|
4343
4350
|
return process.exit(1);
|
|
4344
4351
|
}
|
|
4345
4352
|
let providerName;
|
|
4346
|
-
if (available.length === 1 && available[0]) {
|
|
4353
|
+
if (available.length === 1 && available[0] && !existing) {
|
|
4347
4354
|
providerName = available[0].name;
|
|
4348
4355
|
clack.log.info(`Auto-detected ${pc2.bold(providerLabels[providerName])} as your AI provider.`);
|
|
4349
4356
|
} else {
|
|
4350
4357
|
const selected = await clack.select({
|
|
4351
4358
|
message: "Which AI provider should resolve your issues?",
|
|
4359
|
+
initialValue: existing?.provider,
|
|
4352
4360
|
options: allProviders.map(({ provider, available: isAvailable }) => ({
|
|
4353
4361
|
value: provider.name,
|
|
4354
4362
|
label: providerLabels[provider.name],
|
|
@@ -4367,12 +4375,22 @@ async function runConfigWizard() {
|
|
|
4367
4375
|
availableModels = ["auto"];
|
|
4368
4376
|
clack.log.info("Cursor Free plan detected \u2014 only the 'auto' model is available.");
|
|
4369
4377
|
} else {
|
|
4370
|
-
availableModels =
|
|
4378
|
+
availableModels = fetchCursorModels();
|
|
4371
4379
|
}
|
|
4380
|
+
} else if (providerName === "opencode") {
|
|
4381
|
+
const dynamic = fetchOpenCodeModels();
|
|
4382
|
+
availableModels = dynamic.length > 0 ? dynamic : [
|
|
4383
|
+
"anthropic/claude-opus-4-6",
|
|
4384
|
+
"anthropic/claude-sonnet-4-6",
|
|
4385
|
+
"anthropic/claude-haiku-4-5",
|
|
4386
|
+
"google/gemini-2.5-pro",
|
|
4387
|
+
"google/gemini-2.5-flash"
|
|
4388
|
+
];
|
|
4372
4389
|
}
|
|
4373
4390
|
if (availableModels && availableModels.length > 0) {
|
|
4374
4391
|
const modelSelection = await clack.multiselect({
|
|
4375
4392
|
message: "Which models should Lisa use? Select in order \u2014 first = primary, rest = fallbacks",
|
|
4393
|
+
initialValues: existing?.models?.filter((m) => availableModels.includes(m)) ?? [],
|
|
4376
4394
|
options: availableModels.map((m) => ({
|
|
4377
4395
|
value: m,
|
|
4378
4396
|
label: m
|
|
@@ -4384,6 +4402,7 @@ async function runConfigWizard() {
|
|
|
4384
4402
|
}
|
|
4385
4403
|
const source = await clack.select({
|
|
4386
4404
|
message: "Where do your issues come from?",
|
|
4405
|
+
initialValue: existing?.source,
|
|
4387
4406
|
options: [
|
|
4388
4407
|
{ value: "linear", label: "Linear", apiHint: "GraphQL API", envVars: ["LINEAR_API_KEY"] },
|
|
4389
4408
|
{
|
|
@@ -4445,13 +4464,14 @@ Then reload: ${pc2.cyan(`source ${shell}`)}`
|
|
|
4445
4464
|
const githubMethod = await detectGitHubMethod();
|
|
4446
4465
|
const teamAnswer = await clack.text({
|
|
4447
4466
|
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?",
|
|
4467
|
+
initialValue: existing?.source_config.team ?? "",
|
|
4448
4468
|
placeholder: source === "linear" ? "e.g. Engineering" : void 0
|
|
4449
4469
|
});
|
|
4450
4470
|
if (clack.isCancel(teamAnswer)) return process.exit(0);
|
|
4451
4471
|
const team = teamAnswer;
|
|
4452
4472
|
const labelAnswer = await clack.text({
|
|
4453
4473
|
message: "Which label marks issues as ready for the agent to pick up?",
|
|
4454
|
-
initialValue: "ready",
|
|
4474
|
+
initialValue: existing?.source_config.label ?? "ready",
|
|
4455
4475
|
placeholder: "e.g. ready, ai, lisa"
|
|
4456
4476
|
});
|
|
4457
4477
|
if (clack.isCancel(labelAnswer)) return process.exit(0);
|
|
@@ -4463,52 +4483,54 @@ Then reload: ${pc2.cyan(`source ${shell}`)}`
|
|
|
4463
4483
|
if (source === "trello") {
|
|
4464
4484
|
const pickFromAnswer = await clack.text({
|
|
4465
4485
|
message: "Pick up cards from which list?",
|
|
4466
|
-
initialValue: "Backlog"
|
|
4486
|
+
initialValue: existing?.source_config.pick_from ?? "Backlog"
|
|
4467
4487
|
});
|
|
4468
4488
|
if (clack.isCancel(pickFromAnswer)) return process.exit(0);
|
|
4469
4489
|
pickFrom = pickFromAnswer;
|
|
4470
4490
|
project = pickFrom;
|
|
4471
4491
|
const inProgressAnswer = await clack.text({
|
|
4472
4492
|
message: "Move the card to which list while the agent is working?",
|
|
4473
|
-
initialValue: "In Progress"
|
|
4493
|
+
initialValue: existing?.source_config.in_progress ?? "In Progress"
|
|
4474
4494
|
});
|
|
4475
4495
|
if (clack.isCancel(inProgressAnswer)) return process.exit(0);
|
|
4476
4496
|
inProgress = inProgressAnswer;
|
|
4477
4497
|
const doneAnswer = await clack.text({
|
|
4478
4498
|
message: "Move the card to which list after the PR is created?",
|
|
4479
|
-
initialValue: "Code Review"
|
|
4499
|
+
initialValue: existing?.source_config.done ?? "Code Review"
|
|
4480
4500
|
});
|
|
4481
4501
|
if (clack.isCancel(doneAnswer)) return process.exit(0);
|
|
4482
4502
|
done = doneAnswer;
|
|
4483
4503
|
} else {
|
|
4484
4504
|
const projectAnswer = await clack.text({
|
|
4485
4505
|
message: source === "linear" ? "Which Linear project should Lisa work on? (leave empty for all team issues)" : "Which project should Lisa work on?",
|
|
4506
|
+
initialValue: existing?.source_config.project ?? "",
|
|
4486
4507
|
placeholder: source === "linear" ? "e.g. Q1 Roadmap (optional)" : void 0
|
|
4487
4508
|
});
|
|
4488
4509
|
if (clack.isCancel(projectAnswer)) return process.exit(0);
|
|
4489
4510
|
project = projectAnswer;
|
|
4490
4511
|
const pickFromAnswer = await clack.text({
|
|
4491
4512
|
message: "Pick up issues in which status?",
|
|
4492
|
-
initialValue: "Backlog",
|
|
4513
|
+
initialValue: existing?.source_config.pick_from ?? "Backlog",
|
|
4493
4514
|
placeholder: "e.g. Backlog, Todo"
|
|
4494
4515
|
});
|
|
4495
4516
|
if (clack.isCancel(pickFromAnswer)) return process.exit(0);
|
|
4496
4517
|
pickFrom = pickFromAnswer;
|
|
4497
4518
|
const inProgressAnswer = await clack.text({
|
|
4498
4519
|
message: "Move to which status while the agent is working?",
|
|
4499
|
-
initialValue: "In Progress"
|
|
4520
|
+
initialValue: existing?.source_config.in_progress ?? "In Progress"
|
|
4500
4521
|
});
|
|
4501
4522
|
if (clack.isCancel(inProgressAnswer)) return process.exit(0);
|
|
4502
4523
|
inProgress = inProgressAnswer;
|
|
4503
4524
|
const doneAnswer = await clack.text({
|
|
4504
4525
|
message: "Move to which status after the PR is created?",
|
|
4505
|
-
initialValue: "In Review"
|
|
4526
|
+
initialValue: existing?.source_config.done ?? "In Review"
|
|
4506
4527
|
});
|
|
4507
4528
|
if (clack.isCancel(doneAnswer)) return process.exit(0);
|
|
4508
4529
|
done = doneAnswer;
|
|
4509
4530
|
}
|
|
4510
4531
|
const workflowAnswer = await clack.select({
|
|
4511
4532
|
message: "How should Lisa check out code for each issue?",
|
|
4533
|
+
initialValue: existing?.workflow,
|
|
4512
4534
|
options: [
|
|
4513
4535
|
{
|
|
4514
4536
|
value: "worktree",
|
|
@@ -4528,7 +4550,7 @@ Then reload: ${pc2.cyan(`source ${shell}`)}`
|
|
|
4528
4550
|
let baseBranch = "main";
|
|
4529
4551
|
const cwd = process.cwd();
|
|
4530
4552
|
if (repos.length === 0) {
|
|
4531
|
-
const detected = detectDefaultBranch(cwd);
|
|
4553
|
+
const detected = existing?.base_branch ?? detectDefaultBranch(cwd);
|
|
4532
4554
|
const branchAnswer = await clack.text({
|
|
4533
4555
|
message: "What is the base branch to branch off from?",
|
|
4534
4556
|
initialValue: detected
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
kanbanEmitter,
|
|
4
|
+
resetTitle,
|
|
5
|
+
startSpinner,
|
|
6
|
+
stopSpinner,
|
|
4
7
|
useKanbanState
|
|
5
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-YZKNBQN6.js";
|
|
6
9
|
|
|
7
10
|
// src/ui/kanban.tsx
|
|
8
11
|
import { Box as Box6, useApp, useInput as useInput2 } from "ink";
|
|
@@ -109,6 +112,7 @@ function Column({ label, cards, isFocused = false, activeCardIndex = 0 }) {
|
|
|
109
112
|
{
|
|
110
113
|
flexDirection: "column",
|
|
111
114
|
flexGrow: 1,
|
|
115
|
+
flexBasis: 0,
|
|
112
116
|
borderStyle: "single",
|
|
113
117
|
borderColor,
|
|
114
118
|
paddingX: 1,
|
|
@@ -344,11 +348,13 @@ function IssueDetail({ card, onBack }) {
|
|
|
344
348
|
}
|
|
345
349
|
|
|
346
350
|
// src/ui/sidebar.tsx
|
|
347
|
-
import {
|
|
351
|
+
import { existsSync } from "fs";
|
|
352
|
+
import { basename, join } from "path";
|
|
348
353
|
import { Box as Box5, Text as Text5 } from "ink";
|
|
349
354
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
350
355
|
function Sidebar({ provider, source, cwd }) {
|
|
351
356
|
const dir = basename(cwd);
|
|
357
|
+
const cwdLabel = existsSync(join(cwd, ".git")) ? "REPOSITORY" : "WORKSPACE";
|
|
352
358
|
return /* @__PURE__ */ jsxs5(
|
|
353
359
|
Box5,
|
|
354
360
|
{
|
|
@@ -390,7 +396,7 @@ function Sidebar({ provider, source, cwd }) {
|
|
|
390
396
|
] })
|
|
391
397
|
] }),
|
|
392
398
|
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", marginTop: 1, children: [
|
|
393
|
-
/* @__PURE__ */ jsx5(Text5, { color: "white", dimColor: true, children:
|
|
399
|
+
/* @__PURE__ */ jsx5(Text5, { color: "white", dimColor: true, children: cwdLabel }),
|
|
394
400
|
/* @__PURE__ */ jsxs5(Box5, { children: [
|
|
395
401
|
/* @__PURE__ */ jsx5(Text5, { color: "yellow", children: "\u25B8 " }),
|
|
396
402
|
/* @__PURE__ */ jsx5(Text5, { color: "white", bold: true, children: dir.length > 18 ? `${dir.slice(0, 15)}\u2026` : dir })
|
|
@@ -426,6 +432,17 @@ function KanbanApp({ config }) {
|
|
|
426
432
|
}, [exit]);
|
|
427
433
|
const backlog = cards.filter((c) => c.column === "backlog");
|
|
428
434
|
const inProgress = cards.filter((c) => c.column === "in_progress");
|
|
435
|
+
useEffect3(() => {
|
|
436
|
+
if (workComplete) {
|
|
437
|
+
stopSpinner("Lisa \u2014 done \u2713");
|
|
438
|
+
} else if (inProgress.length > 0) {
|
|
439
|
+
const ids = inProgress.map((c) => c.id).join(", ");
|
|
440
|
+
startSpinner(ids);
|
|
441
|
+
} else {
|
|
442
|
+
stopSpinner("Lisa \u266A");
|
|
443
|
+
}
|
|
444
|
+
return () => resetTitle();
|
|
445
|
+
}, [inProgress, workComplete]);
|
|
429
446
|
const done = cards.filter((c) => c.column === "done");
|
|
430
447
|
const columnCards = [backlog, inProgress, done];
|
|
431
448
|
useInput2((input, key) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tarcisiopgs/lisa",
|
|
3
|
-
"version": "1.7.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.7.5",
|
|
4
|
+
"description": "Autonomous issue resolver",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|