@codyswann/lisa 4.87.3 → 4.87.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.
- package/all/copy-overwrite/scripts/lisa-hooks/parity-safety-net.sh +36 -21
- package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
- package/dist/core/lisa-owned-hash-ledger.js +10 -0
- package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
- package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +15 -14
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/dist/opencode/plugin-templates/parity-safety-net.sh +36 -21
- package/package.json +4 -4
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-parity-code-review/SKILL.md +3 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-parity-code-simplifier/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-parity-coderabbit/SKILL.md +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/SKILL.md +25 -6
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-human.mjs +37 -10
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-setup.mjs +22 -6
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-usage.mjs +22 -12
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/cli-workers.mjs +21 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/human-answer.mjs +76 -21
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/ledger.mjs +6 -2
- package/plugins/lisa/.codex-plugin/skills/lisa-session-manager/scripts/token-migrate.mjs +15 -3
- package/plugins/lisa/hooks/parity-safety-net.sh +36 -21
- package/plugins/lisa/skills/lisa-parity-code-review/SKILL.md +3 -2
- package/plugins/lisa/skills/lisa-parity-code-simplifier/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-parity-coderabbit/SKILL.md +1 -1
- package/plugins/lisa/skills/lisa-session-manager/SKILL.md +25 -6
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-human.mjs +37 -10
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-setup.mjs +22 -6
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-usage.mjs +22 -12
- package/plugins/lisa/skills/lisa-session-manager/scripts/cli-workers.mjs +21 -0
- package/plugins/lisa/skills/lisa-session-manager/scripts/human-answer.mjs +76 -21
- package/plugins/lisa/skills/lisa-session-manager/scripts/ledger.mjs +6 -2
- package/plugins/lisa/skills/lisa-session-manager/scripts/token-migrate.mjs +15 -3
- package/plugins/lisa-agy/hooks/parity-safety-net.sh +36 -21
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-parity-code-review/SKILL.md +3 -2
- package/plugins/lisa-agy/skills/lisa-parity-code-simplifier/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-parity-coderabbit/SKILL.md +1 -1
- package/plugins/lisa-agy/skills/lisa-session-manager/SKILL.md +25 -6
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-human.mjs +37 -10
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-setup.mjs +22 -6
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-usage.mjs +22 -12
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/cli-workers.mjs +21 -0
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/human-answer.mjs +76 -21
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/ledger.mjs +6 -2
- package/plugins/lisa-agy/skills/lisa-session-manager/scripts/token-migrate.mjs +15 -3
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/hooks/parity-safety-net.sh +36 -21
- package/plugins/lisa-copilot/skills/lisa-parity-code-review/SKILL.md +3 -2
- package/plugins/lisa-copilot/skills/lisa-parity-code-simplifier/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-parity-coderabbit/SKILL.md +1 -1
- package/plugins/lisa-copilot/skills/lisa-session-manager/SKILL.md +25 -6
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-human.mjs +37 -10
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-setup.mjs +22 -6
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-usage.mjs +22 -12
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/cli-workers.mjs +21 -0
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/human-answer.mjs +76 -21
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/ledger.mjs +6 -2
- package/plugins/lisa-copilot/skills/lisa-session-manager/scripts/token-migrate.mjs +15 -3
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/hooks/parity-safety-net.sh +36 -21
- package/plugins/lisa-cursor/skills/lisa-parity-code-review/SKILL.md +3 -2
- package/plugins/lisa-cursor/skills/lisa-parity-code-simplifier/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-parity-coderabbit/SKILL.md +1 -1
- package/plugins/lisa-cursor/skills/lisa-session-manager/SKILL.md +25 -6
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-human.mjs +37 -10
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-setup.mjs +22 -6
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-usage.mjs +22 -12
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/cli-workers.mjs +21 -0
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/human-answer.mjs +76 -21
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/ledger.mjs +6 -2
- package/plugins/lisa-cursor/skills/lisa-session-manager/scripts/token-migrate.mjs +15 -3
- package/plugins/lisa-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-devin/hooks/parity-safety-net.sh +36 -21
- package/plugins/lisa-devin/skills/lisa-parity-code-review/SKILL.md +3 -2
- package/plugins/lisa-devin/skills/lisa-parity-code-simplifier/SKILL.md +1 -1
- package/plugins/lisa-devin/skills/lisa-parity-coderabbit/SKILL.md +1 -1
- package/plugins/lisa-devin/skills/lisa-session-manager/SKILL.md +25 -6
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-human.mjs +37 -10
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-setup.mjs +22 -6
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-usage.mjs +22 -12
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/cli-workers.mjs +21 -0
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/human-answer.mjs +76 -21
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/ledger.mjs +6 -2
- package/plugins/lisa-devin/skills/lisa-session-manager/scripts/token-migrate.mjs +15 -3
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-devin/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-devin/.devin-plugin/plugin.json +1 -1
- package/plugins/src/base/hooks/parity-safety-net.sh +36 -21
- package/plugins/src/base/skills/lisa-parity-code-review/SKILL.md +3 -2
- package/plugins/src/base/skills/lisa-parity-code-simplifier/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-parity-coderabbit/SKILL.md +1 -1
- package/plugins/src/base/skills/lisa-session-manager/SKILL.md +25 -6
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-human.mjs +37 -10
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-setup.mjs +22 -6
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-usage.mjs +22 -12
- package/plugins/src/base/skills/lisa-session-manager/scripts/cli-workers.mjs +21 -0
- package/plugins/src/base/skills/lisa-session-manager/scripts/human-answer.mjs +76 -21
- package/plugins/src/base/skills/lisa-session-manager/scripts/ledger.mjs +6 -2
- package/plugins/src/base/skills/lisa-session-manager/scripts/token-migrate.mjs +15 -3
- package/typescript/copy-overwrite/scripts/check-skipped-required-checks.mjs +62 -4
|
@@ -137,6 +137,16 @@ export async function spawn(ctx) {
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
const ledger = await readLedger(ctx.root);
|
|
140
|
+
// A spawn no longer clears a pending question (lisa#4571), and a worker
|
|
141
|
+
// under one classifies as waiting, never stalled or dead. So refuse here:
|
|
142
|
+
// the question must be answered and cleared first ("Clearing").
|
|
143
|
+
if (ledger.items[ref]?.pendingQuestion) {
|
|
144
|
+
throw new CliError(
|
|
145
|
+
`${ref} has a pending question in the ledger; nothing was spawned. ` +
|
|
146
|
+
`Answer it and run "Clearing" (ledger clear-question ${ref}) first.`,
|
|
147
|
+
EXIT.SETUP
|
|
148
|
+
);
|
|
149
|
+
}
|
|
140
150
|
const spec = asSetupError(() => {
|
|
141
151
|
const name = buildWorkerName(ref, ctx.now(), knownNames(agents, ledger));
|
|
142
152
|
return buildWorkerSpawn({
|
|
@@ -191,6 +201,17 @@ export async function resume(ctx) {
|
|
|
191
201
|
const text = stdinText(ctx, "message for the worker");
|
|
192
202
|
const config = requireConfig(ctx);
|
|
193
203
|
const item = ledgerItem(await readLedger(ctx.root), ref);
|
|
204
|
+
// A finish keeps a pending question (lisa#4571), so an answer can still
|
|
205
|
+
// arrive for a worker that reported DONE or FAILED. Resuming it would
|
|
206
|
+
// restart a worker the ledger no longer tracks, so refuse: "Clearing"
|
|
207
|
+
// delivers nothing to a finished worker.
|
|
208
|
+
if (item.status === "DONE" || item.status === "FAILED") {
|
|
209
|
+
throw new CliError(
|
|
210
|
+
`${ref} finished (${item.status}); a finished worker is never ` +
|
|
211
|
+
`resumed. Clear its question without delivering it ("Clearing").`,
|
|
212
|
+
EXIT.SETUP
|
|
213
|
+
);
|
|
214
|
+
}
|
|
194
215
|
if (!item.sessionId && !item.worker) {
|
|
195
216
|
throw new CliError(`${ref} has no recorded session id to resume.`, 2);
|
|
196
217
|
}
|
|
@@ -16,7 +16,10 @@
|
|
|
16
16
|
* answer, and an ordinary reply such as `[x] option 1` is not a machine tag
|
|
17
17
|
* (#4561). Only then is the author matched, on stable ids only: a GitHub
|
|
18
18
|
* login or numeric id, a Jira accountId, a Linear user id, never a display
|
|
19
|
-
* name or email, which anyone can set.
|
|
19
|
+
* name or email, which anyone can set. An all-digit allowed entry is a
|
|
20
|
+
* numeric id and matches only the `id` or `accountId` field, never a login,
|
|
21
|
+
* which its owner chooses and may make all digits (#4571). The text is
|
|
22
|
+
* carried as data.
|
|
20
23
|
*
|
|
21
24
|
* The question the answer must follow is the comment whose id the manager
|
|
22
25
|
* recorded last; with no recorded id, the latest comment that STARTS with
|
|
@@ -46,6 +49,17 @@ const COMMENT_ID_KEYS = ["id", "node_id"];
|
|
|
46
49
|
/** The author fields that are stable ids, never settable display text. */
|
|
47
50
|
const STABLE_ID_KEYS = ["login", "id", "accountId"];
|
|
48
51
|
|
|
52
|
+
/**
|
|
53
|
+
* The author fields an all-digit allowed entry may match. A GitHub login can
|
|
54
|
+
* be all digits and is chosen by its owner, so a numeric operator id must
|
|
55
|
+
* never be matched against a login: user `583231` would otherwise pass as the
|
|
56
|
+
* operator whose numeric id is 583231 (CodySwannGT/lisa#4571).
|
|
57
|
+
*/
|
|
58
|
+
const NUMERIC_ID_KEYS = ["id", "accountId"];
|
|
59
|
+
|
|
60
|
+
/** An allowed entry that is a numeric account id, never a login. */
|
|
61
|
+
const ALL_DIGITS = /^\d+$/;
|
|
62
|
+
|
|
49
63
|
/**
|
|
50
64
|
* The string or number values of `keys` on `value`, as strings.
|
|
51
65
|
* @param {unknown} value - Object to read
|
|
@@ -126,37 +140,78 @@ function questionIndex(rows, managerCommentIds, authorOf) {
|
|
|
126
140
|
* the manager's latest question comment ({@link questionIndex}) that is not
|
|
127
141
|
* a machine's ({@link isMachineAuthoredComment}), has text of its own
|
|
128
142
|
* outside quoted lines (a comment made only of `>` lines quotes someone
|
|
129
|
-
* else and answers nothing),
|
|
143
|
+
* else and answers nothing), whose author's stable id is allowed, and that
|
|
144
|
+
* `refuses` does not refuse. Comments are taken in the order given
|
|
145
|
+
* (chronological).
|
|
146
|
+
*
|
|
147
|
+
* A refused reply (one that looks like it holds a credential) is skipped and
|
|
148
|
+
* reported in `refused`, never returned: returning it made every later cycle
|
|
149
|
+
* pick the same reply and fail on it again, so a corrected reply posted after
|
|
150
|
+
* it was never read (CodySwannGT/lisa#4571).
|
|
130
151
|
* @param {{comments: unknown, allowed: readonly string[],
|
|
131
|
-
* managerCommentIds?: readonly (string|number)[]
|
|
132
|
-
*
|
|
152
|
+
* managerCommentIds?: readonly (string|number)[],
|
|
153
|
+
* refuses?: (text: string) => string | null | undefined}} input - The
|
|
154
|
+
* item's comments, the answerer ids, the ids the manager posted, and why a
|
|
155
|
+
* reply's text may not be queued (null when it may)
|
|
133
156
|
* @returns {{answer: {text: string, author: string, at: string|null} | null,
|
|
134
|
-
* reason: string
|
|
157
|
+
* reason: string, refused?: {id: string|null, author: string, why: string}[]}}
|
|
158
|
+
* The answer, or null with why there is none, and (only when any were)
|
|
159
|
+
* the replies refused
|
|
135
160
|
*/
|
|
136
|
-
export function pickItemAnswer({
|
|
161
|
+
export function pickItemAnswer({
|
|
162
|
+
comments,
|
|
163
|
+
allowed,
|
|
164
|
+
managerCommentIds = [],
|
|
165
|
+
refuses = () => null,
|
|
166
|
+
}) {
|
|
137
167
|
if (!Array.isArray(comments)) {
|
|
138
168
|
throw new Error('stdin must be JSON {"comments":[...]}');
|
|
139
169
|
}
|
|
140
170
|
const rows = comments.filter(row => row && typeof row === "object");
|
|
141
|
-
const allow =
|
|
142
|
-
const
|
|
143
|
-
|
|
171
|
+
const allow = allowed.map(String);
|
|
172
|
+
const numeric = new Set(allow.filter(id => ALL_DIGITS.test(id)));
|
|
173
|
+
const named = new Set(allow.filter(id => !ALL_DIGITS.test(id)));
|
|
174
|
+
const authorOf = row => {
|
|
175
|
+
const author = row.author ?? row.user;
|
|
176
|
+
return (
|
|
177
|
+
idsOf(author, NUMERIC_ID_KEYS).find(id => numeric.has(id)) ??
|
|
178
|
+
idsOf(author, STABLE_ID_KEYS).find(id => named.has(id))
|
|
179
|
+
);
|
|
180
|
+
};
|
|
144
181
|
const asked = questionIndex(rows, managerCommentIds, authorOf);
|
|
182
|
+
const refused = [];
|
|
145
183
|
if (asked === -1) return { answer: null, reason: "no-question-comment" };
|
|
146
|
-
const
|
|
184
|
+
const withRefused = result =>
|
|
185
|
+
refused.length > 0 ? { ...result, refused } : result;
|
|
186
|
+
const replies = rows
|
|
147
187
|
.slice(asked + 1)
|
|
148
188
|
.filter(row => !isMachineAuthoredComment(row, { managerCommentIds }))
|
|
149
|
-
.
|
|
189
|
+
.filter(
|
|
150
190
|
row => authorOf(row) !== undefined && unquoted(bodyOf(row)).trim() !== ""
|
|
151
191
|
);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
192
|
+
for (const reply of replies) {
|
|
193
|
+
const text = bodyOf(reply).trim();
|
|
194
|
+
const why = refuses(text);
|
|
195
|
+
if (why) {
|
|
196
|
+
refused.push({
|
|
197
|
+
id: idsOf(reply, COMMENT_ID_KEYS)[0] ?? null,
|
|
198
|
+
author: authorOf(reply),
|
|
199
|
+
why,
|
|
200
|
+
});
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const at = reply.createdAt ?? reply.created ?? reply.created_at ?? null;
|
|
204
|
+
return withRefused({
|
|
205
|
+
answer: {
|
|
206
|
+
text,
|
|
207
|
+
author: authorOf(reply),
|
|
208
|
+
at: typeof at === "string" ? at : null,
|
|
209
|
+
},
|
|
210
|
+
reason: "answered",
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return withRefused({
|
|
214
|
+
answer: null,
|
|
215
|
+
reason: refused.length > 0 ? "credential-refused" : "no-answer-yet",
|
|
216
|
+
});
|
|
162
217
|
}
|
|
@@ -297,7 +297,9 @@ export function recordSpawn(
|
|
|
297
297
|
startedAt: at,
|
|
298
298
|
lastProgressAt: at,
|
|
299
299
|
logsHash: null,
|
|
300
|
-
|
|
300
|
+
// Kept, never reset: only clearPendingQuestion clears a question, once
|
|
301
|
+
// its answer is delivered and the marker removed (lisa#4571).
|
|
302
|
+
pendingQuestion: previous.pendingQuestion ?? null,
|
|
301
303
|
reason: null,
|
|
302
304
|
finishedAt: null,
|
|
303
305
|
attempts,
|
|
@@ -354,7 +356,9 @@ export function recordFinish(projectRoot, { ref, status, reason }, seams) {
|
|
|
354
356
|
status,
|
|
355
357
|
reason,
|
|
356
358
|
finishedAt: at,
|
|
357
|
-
|
|
359
|
+
// Kept: a question recorded before the finish still holds its answer
|
|
360
|
+
// and the tracker marker the manager must remove (lisa#4571).
|
|
361
|
+
pendingQuestion: previous.pendingQuestion ?? null,
|
|
358
362
|
history: [
|
|
359
363
|
...(previous.history ?? []),
|
|
360
364
|
{ event: "finish", at, status, reason },
|
|
@@ -62,8 +62,9 @@ export function digest(value) {
|
|
|
62
62
|
* of anything else in it (values are never kept or reported).
|
|
63
63
|
* @param {string} stateDir - Resolved state dir
|
|
64
64
|
* @param {Pick<import("node:fs"), "existsSync" | "readFileSync">} fs - Seam
|
|
65
|
-
* @returns {{ path: string, token: string | undefined,
|
|
66
|
-
* null} The file, or null when absent
|
|
65
|
+
* @returns {{ path: string, token: string | undefined, tokenLines: number,
|
|
66
|
+
* others: string[] } | null} The file, or null when absent; `token` is the
|
|
67
|
+
* first `TELEGRAM_BOT_TOKEN` line's value and `tokenLines` counts them all
|
|
67
68
|
*/
|
|
68
69
|
export function readEnvFile(stateDir, fs) {
|
|
69
70
|
const file = path.join(stateDir, TOKEN_FILE);
|
|
@@ -74,10 +75,12 @@ export function readEnvFile(stateDir, fs) {
|
|
|
74
75
|
.map((line, at) => ({ line: line.trim(), at }))
|
|
75
76
|
.filter(({ line }) => line !== "" && !line.startsWith("#"))
|
|
76
77
|
.map(({ line, at }) => ({ match: ENV_LINE.exec(line), at }));
|
|
77
|
-
const
|
|
78
|
+
const tokenLines = entries.filter(({ match }) => match?.[1] === TOKEN_VAR);
|
|
79
|
+
const token = tokenLines[0]?.match;
|
|
78
80
|
return {
|
|
79
81
|
path: file,
|
|
80
82
|
token: token ? token[2].replace(/^(['"])(.*)\1$/, "$2") : undefined,
|
|
83
|
+
tokenLines: tokenLines.length,
|
|
81
84
|
others: entries
|
|
82
85
|
.filter(({ match }) => match?.[1] !== TOKEN_VAR)
|
|
83
86
|
.map(({ match, at }) => match?.[1] ?? `an unrecognised line ${at + 1}`),
|
|
@@ -109,6 +112,15 @@ export function removable(file) {
|
|
|
109
112
|
*/
|
|
110
113
|
export function assertMigratable(file) {
|
|
111
114
|
if (file === null) return;
|
|
115
|
+
// Only the first line's token is verified, and the whole file is deleted
|
|
116
|
+
// after, so a later line would be lost unverified (CodySwannGT/lisa#4571).
|
|
117
|
+
if ((file.tokenLines ?? 0) > 1) {
|
|
118
|
+
throw setupError(
|
|
119
|
+
`${file.path} has ${file.tokenLines} ${TOKEN_VAR} lines, so which ` +
|
|
120
|
+
`token is meant is ambiguous. Keep exactly one, then run store-token ` +
|
|
121
|
+
`again. Nothing was changed.`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
112
124
|
if (file.others.length > 0) {
|
|
113
125
|
throw setupError(
|
|
114
126
|
`${file.path} holds ${file.others.join(", ")} besides ${TOKEN_VAR}, so ` +
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.87.
|
|
3
|
+
"version": "4.87.5",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.87.
|
|
3
|
+
"version": "4.87.5",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.87.
|
|
3
|
+
"version": "4.87.5",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.87.
|
|
3
|
+
"version": "4.87.5",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.87.
|
|
3
|
+
"version": "4.87.5",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.87.
|
|
3
|
+
"version": "4.87.5",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "4.87.
|
|
3
|
+
"version": "4.87.5",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|