@tarcisiopgs/lisa 1.37.0 → 1.37.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.
- package/README.md +2 -1
- package/dist/{chunk-CTMZ666K.js → chunk-4MZ2565Y.js} +2 -0
- package/dist/{chunk-MOQR4OY5.js → chunk-I5HJELVZ.js} +3 -3
- package/dist/{chunk-VS6R5KBO.js → chunk-LR2GREZS.js} +13 -1
- package/dist/{chunk-FUIWWBDX.js → chunk-MC4SAOF2.js} +2 -2
- package/dist/{chunk-YMV4CBQE.js → chunk-YBM6JNRO.js} +90 -0
- package/dist/{chunk-XXVTKBC5.js → chunk-YRKJONH5.js} +16 -765
- package/dist/{chunk-555PDPCW.js → chunk-ZERJ7TNX.js} +37 -16
- package/dist/chunk-ZOVVFU7B.js +970 -0
- package/dist/{detection-MHQPM7O6.js → detection-2Z6TXYHU.js} +3 -3
- package/dist/index.js +62 -37
- package/dist/{kanban-ZQ67DJHP.js → kanban-6WPOGFK5.js} +100 -15
- package/dist/{loop-UN2MO6JN.js → loop-FKUQEJVU.js} +6 -5
- package/dist/{merge-Q3P65FEA.js → merge-NWSEV3FR.js} +1 -1
- package/dist/platform-ZDLHR264.js +24 -0
- package/dist/{tui-bridge-A5XQUJQ7.js → tui-bridge-MMP6OGHK.js} +6 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -53,7 +53,7 @@ If something fails — pre-push hooks, quota limits, stuck processes — Lisa ha
|
|
|
53
53
|
- **Smart activity detection** — reads agent session logs to prevent false stuck kills during analysis phases
|
|
54
54
|
- **Progress comments** — posts real-time status updates on issues as Lisa works through stages
|
|
55
55
|
- **Context enrichment** — greps for issue-related files and surfaces them in the agent prompt
|
|
56
|
-
- **PR reviewers & assignees** — auto-request reviews and assign PRs via config; `self` keyword resolves to the authenticated user
|
|
56
|
+
- **PR reviewers & assignees** — auto-request reviews and assign PRs via config; `self` keyword resolves to the authenticated user. Manage reviewers interactively from the TUI detail view (`r`)
|
|
57
57
|
- **Self-healing** — orphan recovery on startup, push failure retry, stuck process detection
|
|
58
58
|
- **Guardrails** — past failures are injected into future prompts to avoid repeating mistakes
|
|
59
59
|
- **Lineage context** — plan-decomposed issues get sibling task awareness, preventing duplicate work in concurrent mode
|
|
@@ -360,6 +360,7 @@ The real-time Kanban board shows issue progress, streams provider output, and de
|
|
|
360
360
|
|-----|--------|
|
|
361
361
|
| `↑` `↓` | Scroll output log |
|
|
362
362
|
| `o` | Open PR in browser |
|
|
363
|
+
| `r` | Toggle reviewer picker (add/remove reviewers on the PR) |
|
|
363
364
|
| `m` | Merge PR (warns if CI not passed) |
|
|
364
365
|
| `Esc` | Back to board |
|
|
365
366
|
|
|
@@ -5,10 +5,10 @@ import {
|
|
|
5
5
|
resolveModels,
|
|
6
6
|
runWithFallback,
|
|
7
7
|
saveLineage
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-YRKJONH5.js";
|
|
9
9
|
import {
|
|
10
10
|
normalizeLabels
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-LR2GREZS.js";
|
|
12
12
|
import {
|
|
13
13
|
error,
|
|
14
14
|
log,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from "./chunk-HPWL5JRW.js";
|
|
18
18
|
import {
|
|
19
19
|
LisaError
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-4MZ2565Y.js";
|
|
21
21
|
|
|
22
22
|
// src/cli/error.ts
|
|
23
23
|
var CliError = class extends LisaError {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-HPWL5JRW.js";
|
|
8
8
|
import {
|
|
9
9
|
SourceError
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4MZ2565Y.js";
|
|
11
11
|
|
|
12
12
|
// src/ui/state.ts
|
|
13
13
|
import { EventEmitter } from "events";
|
|
@@ -891,6 +891,14 @@ function useKanbanState(bellEnabled, initialCards = []) {
|
|
|
891
891
|
const onSubstatus = (issueId, substatus) => {
|
|
892
892
|
setCards((prev) => prev.map((c) => c.id === issueId ? { ...c, substatus } : c));
|
|
893
893
|
};
|
|
894
|
+
const onReviewersUpdated = (issueId, reviewers) => {
|
|
895
|
+
setCards((prev) => prev.map((c) => c.id === issueId ? { ...c, reviewers } : c));
|
|
896
|
+
};
|
|
897
|
+
const onAvailableReviewers = (issueId, available) => {
|
|
898
|
+
setCards(
|
|
899
|
+
(prev) => prev.map((c) => c.id === issueId ? { ...c, availableReviewers: available } : c)
|
|
900
|
+
);
|
|
901
|
+
};
|
|
894
902
|
const MAX_OUTPUT_SIZE = 2e5;
|
|
895
903
|
const outputBuffer = /* @__PURE__ */ new Map();
|
|
896
904
|
let flushTimer = null;
|
|
@@ -939,6 +947,8 @@ function useKanbanState(bellEnabled, initialCards = []) {
|
|
|
939
947
|
kanbanEmitter.on("provider:resumed", onProviderResumed);
|
|
940
948
|
kanbanEmitter.on("issue:log-file", onLogFile);
|
|
941
949
|
kanbanEmitter.on("issue:substatus", onSubstatus);
|
|
950
|
+
kanbanEmitter.on("issue:reviewers-updated", onReviewersUpdated);
|
|
951
|
+
kanbanEmitter.on("issue:available-reviewers", onAvailableReviewers);
|
|
942
952
|
kanbanEmitter.on("issue:output", onOutput);
|
|
943
953
|
const onModelChanged = (model) => setModelInUse(model);
|
|
944
954
|
kanbanEmitter.on("provider:model-changed", onModelChanged);
|
|
@@ -985,6 +995,8 @@ function useKanbanState(bellEnabled, initialCards = []) {
|
|
|
985
995
|
kanbanEmitter.off("provider:resumed", onProviderResumed);
|
|
986
996
|
kanbanEmitter.off("issue:log-file", onLogFile);
|
|
987
997
|
kanbanEmitter.off("issue:substatus", onSubstatus);
|
|
998
|
+
kanbanEmitter.off("issue:reviewers-updated", onReviewersUpdated);
|
|
999
|
+
kanbanEmitter.off("issue:available-reviewers", onAvailableReviewers);
|
|
988
1000
|
kanbanEmitter.off("issue:output", onOutput);
|
|
989
1001
|
kanbanEmitter.off("provider:model-changed", onModelChanged);
|
|
990
1002
|
kanbanEmitter.off("work:empty", onEmpty);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
isGhCliAvailable
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YBM6JNRO.js";
|
|
5
5
|
import {
|
|
6
6
|
verbose
|
|
7
7
|
} from "./chunk-HPWL5JRW.js";
|
|
8
8
|
import {
|
|
9
9
|
formatError
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4MZ2565Y.js";
|
|
11
11
|
|
|
12
12
|
// src/cli/detection.ts
|
|
13
13
|
import { execSync } from "child_process";
|
|
@@ -137,6 +137,94 @@ async function appendPrBody(prUrl, content) {
|
|
|
137
137
|
} catch {
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
+
async function getRepoInfo(cwd) {
|
|
141
|
+
const { stdout: remoteUrl } = await execa("git", ["remote", "get-url", "origin"], { cwd });
|
|
142
|
+
let owner;
|
|
143
|
+
let repo;
|
|
144
|
+
const sshMatch = remoteUrl.match(/git@github\.com:(.+?)\/(.+?)(?:\.git)?$/);
|
|
145
|
+
const httpsMatch = remoteUrl.match(/github\.com\/(.+?)\/(.+?)(?:\.git)?$/);
|
|
146
|
+
if (sshMatch) {
|
|
147
|
+
owner = sshMatch[1] ?? "";
|
|
148
|
+
repo = sshMatch[2] ?? "";
|
|
149
|
+
} else if (httpsMatch) {
|
|
150
|
+
owner = httpsMatch[1] ?? "";
|
|
151
|
+
repo = httpsMatch[2] ?? "";
|
|
152
|
+
} else {
|
|
153
|
+
throw new Error(`Cannot parse GitHub owner/repo from remote URL: ${remoteUrl}`);
|
|
154
|
+
}
|
|
155
|
+
const { stdout: branch } = await execa("git", ["branch", "--show-current"], { cwd });
|
|
156
|
+
let defaultBranch = "main";
|
|
157
|
+
const symResult = await execa("git", ["symbolic-ref", "refs/remotes/origin/HEAD", "--short"], {
|
|
158
|
+
cwd,
|
|
159
|
+
reject: false
|
|
160
|
+
});
|
|
161
|
+
if (symResult.stdout?.trim()) {
|
|
162
|
+
defaultBranch = symResult.stdout.replace("origin/", "").trim();
|
|
163
|
+
} else {
|
|
164
|
+
for (const candidate of ["main", "master", "develop"]) {
|
|
165
|
+
const check = await execa("git", ["rev-parse", "--verify", `origin/${candidate}`], {
|
|
166
|
+
cwd,
|
|
167
|
+
reject: false
|
|
168
|
+
});
|
|
169
|
+
if (check.exitCode === 0) {
|
|
170
|
+
defaultBranch = candidate;
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
owner,
|
|
177
|
+
repo,
|
|
178
|
+
branch: branch.trim(),
|
|
179
|
+
defaultBranch
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
async function listCollaborators(cwd, method = "cli") {
|
|
183
|
+
try {
|
|
184
|
+
const { owner, repo } = await getRepoInfo(cwd);
|
|
185
|
+
if (method === "cli" && await isGhCliAvailable()) {
|
|
186
|
+
const { stdout } = await execa("gh", [
|
|
187
|
+
"api",
|
|
188
|
+
"--paginate",
|
|
189
|
+
"--jq",
|
|
190
|
+
".[].login",
|
|
191
|
+
`/repos/${owner}/${repo}/collaborators`
|
|
192
|
+
]);
|
|
193
|
+
return stdout.trim().split("\n").filter(Boolean).sort((a, b) => a.localeCompare(b));
|
|
194
|
+
}
|
|
195
|
+
const res = await fetch(`${API_URL}/repos/${owner}/${repo}/collaborators?per_page=100`, {
|
|
196
|
+
headers: {
|
|
197
|
+
Authorization: `Bearer ${getToken()}`,
|
|
198
|
+
Accept: "application/vnd.github+json"
|
|
199
|
+
},
|
|
200
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
201
|
+
});
|
|
202
|
+
if (!res.ok) return [];
|
|
203
|
+
const data = await res.json();
|
|
204
|
+
return data.map((c) => c.login).filter(Boolean).sort((a, b) => a.localeCompare(b));
|
|
205
|
+
} catch {
|
|
206
|
+
return [];
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
async function removeReviewers(prUrl, reviewers) {
|
|
210
|
+
if (!reviewers.length) return;
|
|
211
|
+
const parsed = parseGitHubPrUrl(prUrl);
|
|
212
|
+
if (!parsed) return;
|
|
213
|
+
await execa(
|
|
214
|
+
"gh",
|
|
215
|
+
[
|
|
216
|
+
"api",
|
|
217
|
+
"--method",
|
|
218
|
+
"DELETE",
|
|
219
|
+
`/repos/${parsed.owner}/${parsed.repo}/pulls/${parsed.number}/requested_reviewers`,
|
|
220
|
+
"--input",
|
|
221
|
+
"-"
|
|
222
|
+
],
|
|
223
|
+
{
|
|
224
|
+
input: JSON.stringify({ reviewers })
|
|
225
|
+
}
|
|
226
|
+
);
|
|
227
|
+
}
|
|
140
228
|
var authenticatedUserCache = null;
|
|
141
229
|
async function getAuthenticatedUser(method = "cli") {
|
|
142
230
|
if (authenticatedUserCache) return authenticatedUserCache;
|
|
@@ -203,6 +291,8 @@ export {
|
|
|
203
291
|
isGhCliAvailable,
|
|
204
292
|
appendPrAttribution,
|
|
205
293
|
appendPrBody,
|
|
294
|
+
listCollaborators,
|
|
295
|
+
removeReviewers,
|
|
206
296
|
getAuthenticatedUser,
|
|
207
297
|
addReviewers,
|
|
208
298
|
addAssignees
|