fix: honor non-interactive legacy migrations
This commit is contained in:
@@ -82,6 +82,7 @@
|
|||||||
- **Multi-agent safety:** running multiple agents is OK as long as each agent has its own session.
|
- **Multi-agent safety:** running multiple agents is OK as long as each agent has its own session.
|
||||||
- **Multi-agent safety:** when you see unrecognized files, keep going; focus on your changes and commit only those.
|
- **Multi-agent safety:** when you see unrecognized files, keep going; focus on your changes and commit only those.
|
||||||
- Bug investigations: read source code of relevant npm dependencies and all related local code before concluding; aim for high-confidence root cause.
|
- Bug investigations: read source code of relevant npm dependencies and all related local code before concluding; aim for high-confidence root cause.
|
||||||
|
- Code style: add brief comments for tricky logic; keep files under ~500 LOC when feasible (split/refactor as needed).
|
||||||
- When asked to open a “session” file, open the Pi session logs under `~/.clawdbot/sessions/*.jsonl` (newest unless a specific ID is given), not the default `sessions.json`. If logs are needed from another machine, SSH via Tailscale and read the same path there.
|
- When asked to open a “session” file, open the Pi session logs under `~/.clawdbot/sessions/*.jsonl` (newest unless a specific ID is given), not the default `sessions.json`. If logs are needed from another machine, SSH via Tailscale and read the same path there.
|
||||||
- Menubar dimming + restart flow mirrors Trimmy: use `scripts/restart-mac.sh` (kills all Clawdbot variants, runs `swift build`, packages, relaunches). Icon dimming depends on MenuBarExtraAccess wiring in AppMain; keep `appearsDisabled` updates intact when touching the status item.
|
- Menubar dimming + restart flow mirrors Trimmy: use `scripts/restart-mac.sh` (kills all Clawdbot variants, runs `swift build`, packages, relaunches). Icon dimming depends on MenuBarExtraAccess wiring in AppMain; keep `appearsDisabled` updates intact when touching the status item.
|
||||||
- Do not rebuild the macOS app over SSH; rebuilds must be run directly on the Mac.
|
- Do not rebuild the macOS app over SSH; rebuilds must be run directly on the Mac.
|
||||||
|
|||||||
@@ -329,7 +329,11 @@ export function buildProgram() {
|
|||||||
)
|
)
|
||||||
.option("--yes", "Accept defaults without prompting", false)
|
.option("--yes", "Accept defaults without prompting", false)
|
||||||
.option("--repair", "Apply recommended repairs without prompting", false)
|
.option("--repair", "Apply recommended repairs without prompting", false)
|
||||||
.option("--force", "Apply aggressive repairs (overwrites custom service config)", false)
|
.option(
|
||||||
|
"--force",
|
||||||
|
"Apply aggressive repairs (overwrites custom service config)",
|
||||||
|
false,
|
||||||
|
)
|
||||||
.option(
|
.option(
|
||||||
"--non-interactive",
|
"--non-interactive",
|
||||||
"Run without prompts (safe migrations only)",
|
"Run without prompts (safe migrations only)",
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ export async function maybeRepairGatewayServiceConfig(
|
|||||||
const aggressiveIssues = audit.issues.filter(
|
const aggressiveIssues = audit.issues.filter(
|
||||||
(issue) => issue.level === "aggressive",
|
(issue) => issue.level === "aggressive",
|
||||||
);
|
);
|
||||||
const recommendedIssues = audit.issues.filter(
|
const _recommendedIssues = audit.issues.filter(
|
||||||
(issue) => issue.level !== "aggressive",
|
(issue) => issue.level !== "aggressive",
|
||||||
);
|
);
|
||||||
const needsAggressive = aggressiveIssues.length > 0;
|
const needsAggressive = aggressiveIssues.length > 0;
|
||||||
@@ -184,12 +184,12 @@ export async function maybeRepairGatewayServiceConfig(
|
|||||||
|
|
||||||
const repair = needsAggressive
|
const repair = needsAggressive
|
||||||
? await prompter.confirmAggressive({
|
? await prompter.confirmAggressive({
|
||||||
message:
|
message: "Overwrite gateway service config with current defaults now?",
|
||||||
"Overwrite gateway service config with current defaults now?",
|
|
||||||
initialValue: Boolean(prompter.shouldForce),
|
initialValue: Boolean(prompter.shouldForce),
|
||||||
})
|
})
|
||||||
: await prompter.confirmRepair({
|
: await prompter.confirmRepair({
|
||||||
message: "Update gateway service config to the recommended defaults now?",
|
message:
|
||||||
|
"Update gateway service config to the recommended defaults now?",
|
||||||
initialValue: true,
|
initialValue: true,
|
||||||
});
|
});
|
||||||
if (!repair) return;
|
if (!repair) return;
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ export type DoctorOptions = {
|
|||||||
export type DoctorPrompter = {
|
export type DoctorPrompter = {
|
||||||
confirm: (params: Parameters<typeof confirm>[0]) => Promise<boolean>;
|
confirm: (params: Parameters<typeof confirm>[0]) => Promise<boolean>;
|
||||||
confirmRepair: (params: Parameters<typeof confirm>[0]) => Promise<boolean>;
|
confirmRepair: (params: Parameters<typeof confirm>[0]) => Promise<boolean>;
|
||||||
confirmAggressive: (params: Parameters<typeof confirm>[0]) => Promise<boolean>;
|
confirmAggressive: (
|
||||||
|
params: Parameters<typeof confirm>[0],
|
||||||
|
) => Promise<boolean>;
|
||||||
confirmSkipInNonInteractive: (
|
confirmSkipInNonInteractive: (
|
||||||
params: Parameters<typeof confirm>[0],
|
params: Parameters<typeof confirm>[0],
|
||||||
) => Promise<boolean>;
|
) => Promise<boolean>;
|
||||||
|
|||||||
@@ -129,10 +129,13 @@ export async function doctorCommand(
|
|||||||
const legacyState = await detectLegacyStateMigrations({ cfg });
|
const legacyState = await detectLegacyStateMigrations({ cfg });
|
||||||
if (legacyState.preview.length > 0) {
|
if (legacyState.preview.length > 0) {
|
||||||
note(legacyState.preview.join("\n"), "Legacy state detected");
|
note(legacyState.preview.join("\n"), "Legacy state detected");
|
||||||
const migrate = await prompter.confirm({
|
const migrate =
|
||||||
message: "Migrate legacy state (sessions/agent/WhatsApp auth) now?",
|
options.nonInteractive === true
|
||||||
initialValue: true,
|
? true
|
||||||
});
|
: await prompter.confirm({
|
||||||
|
message: "Migrate legacy state (sessions/agent/WhatsApp auth) now?",
|
||||||
|
initialValue: true,
|
||||||
|
});
|
||||||
if (migrate) {
|
if (migrate) {
|
||||||
const migrated = await runLegacyStateMigrations({
|
const migrated = await runLegacyStateMigrations({
|
||||||
detected: legacyState,
|
detected: legacyState,
|
||||||
@@ -146,7 +149,11 @@ export async function doctorCommand(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await noteStateIntegrity(cfg, prompter, snapshot.path ?? CONFIG_PATH_CLAWDBOT);
|
await noteStateIntegrity(
|
||||||
|
cfg,
|
||||||
|
prompter,
|
||||||
|
snapshot.path ?? CONFIG_PATH_CLAWDBOT,
|
||||||
|
);
|
||||||
|
|
||||||
cfg = await maybeRepairSandboxImages(cfg, runtime, prompter);
|
cfg = await maybeRepairSandboxImages(cfg, runtime, prompter);
|
||||||
noteSandboxScopeWarnings(cfg);
|
noteSandboxScopeWarnings(cfg);
|
||||||
|
|||||||
@@ -148,6 +148,10 @@ describe("web monitor inbox", () => {
|
|||||||
|
|
||||||
const listener = await monitorWebInbox({ verbose: false, onMessage });
|
const listener = await monitorWebInbox({ verbose: false, onMessage });
|
||||||
const sock = await createWaSocket();
|
const sock = await createWaSocket();
|
||||||
|
const getPNForLID = vi.spyOn(
|
||||||
|
sock.signalRepository.lidMapping,
|
||||||
|
"getPNForLID",
|
||||||
|
);
|
||||||
sock.signalRepository.lidMapping.getPNForLID.mockResolvedValueOnce(
|
sock.signalRepository.lidMapping.getPNForLID.mockResolvedValueOnce(
|
||||||
"999:0@s.whatsapp.net",
|
"999:0@s.whatsapp.net",
|
||||||
);
|
);
|
||||||
@@ -166,9 +170,7 @@ describe("web monitor inbox", () => {
|
|||||||
sock.ev.emit("messages.upsert", upsert);
|
sock.ev.emit("messages.upsert", upsert);
|
||||||
await new Promise((resolve) => setImmediate(resolve));
|
await new Promise((resolve) => setImmediate(resolve));
|
||||||
|
|
||||||
expect(sock.signalRepository.lidMapping.getPNForLID).toHaveBeenCalledWith(
|
expect(getPNForLID).toHaveBeenCalledWith("999@lid");
|
||||||
"999@lid",
|
|
||||||
);
|
|
||||||
expect(onMessage).toHaveBeenCalledWith(
|
expect(onMessage).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({ body: "ping", from: "+999", to: "+123" }),
|
expect.objectContaining({ body: "ping", from: "+999", to: "+123" }),
|
||||||
);
|
);
|
||||||
@@ -183,6 +185,10 @@ describe("web monitor inbox", () => {
|
|||||||
|
|
||||||
const listener = await monitorWebInbox({ verbose: false, onMessage });
|
const listener = await monitorWebInbox({ verbose: false, onMessage });
|
||||||
const sock = await createWaSocket();
|
const sock = await createWaSocket();
|
||||||
|
const getPNForLID = vi.spyOn(
|
||||||
|
sock.signalRepository.lidMapping,
|
||||||
|
"getPNForLID",
|
||||||
|
);
|
||||||
sock.signalRepository.lidMapping.getPNForLID.mockResolvedValueOnce(
|
sock.signalRepository.lidMapping.getPNForLID.mockResolvedValueOnce(
|
||||||
"444:0@s.whatsapp.net",
|
"444:0@s.whatsapp.net",
|
||||||
);
|
);
|
||||||
@@ -205,9 +211,7 @@ describe("web monitor inbox", () => {
|
|||||||
sock.ev.emit("messages.upsert", upsert);
|
sock.ev.emit("messages.upsert", upsert);
|
||||||
await new Promise((resolve) => setImmediate(resolve));
|
await new Promise((resolve) => setImmediate(resolve));
|
||||||
|
|
||||||
expect(sock.signalRepository.lidMapping.getPNForLID).toHaveBeenCalledWith(
|
expect(getPNForLID).toHaveBeenCalledWith("444@lid");
|
||||||
"444@lid",
|
|
||||||
);
|
|
||||||
expect(onMessage).toHaveBeenCalledWith(
|
expect(onMessage).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
body: "ping",
|
body: "ping",
|
||||||
|
|||||||
Reference in New Issue
Block a user