chore: logger cleanup and test fixes
This commit is contained in:
@@ -243,6 +243,8 @@ export async function getReplyFromConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const finalArgv = argv;
|
const finalArgv = argv;
|
||||||
|
const isClaudeInvocation =
|
||||||
|
finalArgv.length > 0 && path.basename(finalArgv[0]) === CLAUDE_BIN;
|
||||||
logVerbose(`Running command auto-reply: ${finalArgv.join(" ")}`);
|
logVerbose(`Running command auto-reply: ${finalArgv.join(" ")}`);
|
||||||
const started = Date.now();
|
const started = Date.now();
|
||||||
try {
|
try {
|
||||||
@@ -255,7 +257,7 @@ export async function getReplyFromConfig(
|
|||||||
if (stderr?.trim()) {
|
if (stderr?.trim()) {
|
||||||
logVerbose(`Command auto-reply stderr: ${stderr.trim()}`);
|
logVerbose(`Command auto-reply stderr: ${stderr.trim()}`);
|
||||||
}
|
}
|
||||||
if (reply.claudeOutputFormat === "json" && trimmed) {
|
if (trimmed && (reply.claudeOutputFormat === "json" || isClaudeInvocation)) {
|
||||||
// Claude JSON mode: extract the human text for both logging and reply while keeping metadata.
|
// Claude JSON mode: extract the human text for both logging and reply while keeping metadata.
|
||||||
const parsed = parseClaudeJson(trimmed);
|
const parsed = parseClaudeJson(trimmed);
|
||||||
if (parsed?.parsed && isVerbose()) {
|
if (parsed?.parsed && isVerbose()) {
|
||||||
|
|||||||
@@ -209,6 +209,34 @@ describe("config and templating", () => {
|
|||||||
|
|
||||||
expect(result).toBe("hello world");
|
expect(result).toBe("hello world");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("parses Claude JSON output even without explicit claudeOutputFormat when using claude bin", async () => {
|
||||||
|
const runSpy = vi.spyOn(index, "runCommandWithTimeout").mockResolvedValue({
|
||||||
|
stdout: '{"result":"Sure! What\'s up?"}\n',
|
||||||
|
stderr: "",
|
||||||
|
code: 0,
|
||||||
|
signal: null,
|
||||||
|
killed: false,
|
||||||
|
});
|
||||||
|
const cfg = {
|
||||||
|
inbound: {
|
||||||
|
reply: {
|
||||||
|
mode: "command" as const,
|
||||||
|
command: ["claude", "{{Body}}"],
|
||||||
|
// No claudeOutputFormat set on purpose
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await index.getReplyFromConfig(
|
||||||
|
{ Body: "hi", From: "+1", To: "+2" },
|
||||||
|
undefined,
|
||||||
|
cfg,
|
||||||
|
runSpy,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result).toBe("Sure! What's up?");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("twilio interactions", () => {
|
describe("twilio interactions", () => {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { EventEmitter } from "node:events";
|
import { EventEmitter } from "node:events";
|
||||||
|
import fsSync from "node:fs";
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import type { MockBaileysSocket } from "../test/mocks/baileys.js";
|
import type { MockBaileysSocket } from "../test/mocks/baileys.js";
|
||||||
import { createMockBaileys } from "../test/mocks/baileys.js";
|
import { createMockBaileys } from "../test/mocks/baileys.js";
|
||||||
@@ -30,6 +31,7 @@ import {
|
|||||||
createWaSocket,
|
createWaSocket,
|
||||||
loginWeb,
|
loginWeb,
|
||||||
monitorWebInbox,
|
monitorWebInbox,
|
||||||
|
logWebSelfId,
|
||||||
sendMessageWeb,
|
sendMessageWeb,
|
||||||
waitForWaConnection,
|
waitForWaConnection,
|
||||||
} from "./provider-web.js";
|
} from "./provider-web.js";
|
||||||
@@ -162,4 +164,28 @@ describe("provider-web", () => {
|
|||||||
|
|
||||||
await listener.close();
|
await listener.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("logWebSelfId prints cached E.164 when creds exist", () => {
|
||||||
|
const existsSpy = vi
|
||||||
|
.spyOn(fsSync, "existsSync")
|
||||||
|
.mockReturnValue(true as never);
|
||||||
|
const readSpy = vi
|
||||||
|
.spyOn(fsSync, "readFileSync")
|
||||||
|
.mockReturnValue(
|
||||||
|
JSON.stringify({ me: { id: "12345@s.whatsapp.net" } }),
|
||||||
|
);
|
||||||
|
const runtime = {
|
||||||
|
log: vi.fn(),
|
||||||
|
error: vi.fn(),
|
||||||
|
exit: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
logWebSelfId(runtime as never);
|
||||||
|
|
||||||
|
expect(runtime.log).toHaveBeenCalledWith(
|
||||||
|
expect.stringContaining("+12345"),
|
||||||
|
);
|
||||||
|
existsSpy.mockRestore();
|
||||||
|
readSpy.mockRestore();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -341,10 +341,10 @@ function readWebSelfId() {
|
|||||||
// Read the cached WhatsApp Web identity (jid + E.164) from disk if present.
|
// Read the cached WhatsApp Web identity (jid + E.164) from disk if present.
|
||||||
const credsPath = path.join(WA_WEB_AUTH_DIR, "creds.json");
|
const credsPath = path.join(WA_WEB_AUTH_DIR, "creds.json");
|
||||||
try {
|
try {
|
||||||
if (!fs.existsSync(credsPath)) {
|
if (!fsSync.existsSync(credsPath)) {
|
||||||
return { e164: null, jid: null };
|
return { e164: null, jid: null };
|
||||||
}
|
}
|
||||||
const raw = fs.readFileSync(credsPath, "utf-8");
|
const raw = fsSync.readFileSync(credsPath, "utf-8");
|
||||||
const parsed = JSON.parse(raw) as { me?: { id?: string } } | undefined;
|
const parsed = JSON.parse(raw) as { me?: { id?: string } } | undefined;
|
||||||
const jid = parsed?.me?.id ?? null;
|
const jid = parsed?.me?.id ?? null;
|
||||||
const e164 = jid ? jidToE164(jid) : null;
|
const e164 = jid ? jidToE164(jid) : null;
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { success, isVerbose, warn } from "../globals.js";
|
import { isVerbose, success, warn } from "../globals.js";
|
||||||
|
import { logError, logInfo } from "../logger.js";
|
||||||
import { readEnv } from "../env.js";
|
import { readEnv } from "../env.js";
|
||||||
import { normalizeE164 } from "../utils.js";
|
import { normalizeE164 } from "../utils.js";
|
||||||
import type { RuntimeEnv } from "../runtime.js";
|
import { defaultRuntime, type RuntimeEnv } from "../runtime.js";
|
||||||
import { createClient } from "./client.js";
|
import { createClient } from "./client.js";
|
||||||
import type { TwilioSenderListClient, TwilioRequester } from "./types.js";
|
import type { TwilioSenderListClient, TwilioRequester } from "./types.js";
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ export async function setMessagingServiceWebhook(
|
|||||||
client: TwilioSenderListClient,
|
client: TwilioSenderListClient,
|
||||||
url: string,
|
url: string,
|
||||||
method: "POST" | "GET",
|
method: "POST" | "GET",
|
||||||
|
runtime: RuntimeEnv = defaultRuntime,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const msid = await findMessagingServiceSid(client);
|
const msid = await findMessagingServiceSid(client);
|
||||||
if (!msid) return false;
|
if (!msid) return false;
|
||||||
@@ -53,10 +55,9 @@ export async function setMessagingServiceWebhook(
|
|||||||
});
|
});
|
||||||
const fetched = await client.messaging.v1.services(msid).fetch();
|
const fetched = await client.messaging.v1.services(msid).fetch();
|
||||||
const stored = fetched?.inboundRequestUrl;
|
const stored = fetched?.inboundRequestUrl;
|
||||||
console.log(
|
logInfo(
|
||||||
success(
|
|
||||||
`✅ Messaging Service webhook set to ${stored ?? url} (service ${msid})`,
|
`✅ Messaging Service webhook set to ${stored ?? url} (service ${msid})`,
|
||||||
),
|
runtime,
|
||||||
);
|
);
|
||||||
return true;
|
return true;
|
||||||
} catch {
|
} catch {
|
||||||
@@ -96,18 +97,19 @@ export async function updateWebhook(
|
|||||||
const storedUrl =
|
const storedUrl =
|
||||||
fetched?.webhook?.callback_url || fetched?.webhook?.fallback_url;
|
fetched?.webhook?.callback_url || fetched?.webhook?.fallback_url;
|
||||||
if (storedUrl) {
|
if (storedUrl) {
|
||||||
console.log(success(`✅ Twilio sender webhook set to ${storedUrl}`));
|
logInfo(`✅ Twilio sender webhook set to ${storedUrl}`, runtime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isVerbose())
|
if (isVerbose())
|
||||||
console.error(
|
logError(
|
||||||
"Sender updated but webhook callback_url missing; will try fallbacks",
|
"Sender updated but webhook callback_url missing; will try fallbacks",
|
||||||
|
runtime,
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isVerbose())
|
if (isVerbose())
|
||||||
console.error(
|
logError(
|
||||||
"channelsSenders request update failed, will try client helpers",
|
`channelsSenders request update failed, will try client helpers: ${String(err)}`,
|
||||||
err,
|
runtime,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,18 +129,19 @@ export async function updateWebhook(
|
|||||||
const storedUrl =
|
const storedUrl =
|
||||||
fetched?.webhook?.callback_url || fetched?.webhook?.fallback_url;
|
fetched?.webhook?.callback_url || fetched?.webhook?.fallback_url;
|
||||||
if (storedUrl) {
|
if (storedUrl) {
|
||||||
console.log(success(`✅ Twilio sender webhook set to ${storedUrl}`));
|
logInfo(`✅ Twilio sender webhook set to ${storedUrl}`, runtime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isVerbose())
|
if (isVerbose())
|
||||||
console.error(
|
logError(
|
||||||
"Form update succeeded but callback_url missing; will try helper fallback",
|
"Form update succeeded but callback_url missing; will try helper fallback",
|
||||||
|
runtime,
|
||||||
);
|
);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isVerbose())
|
if (isVerbose())
|
||||||
console.error(
|
logError(
|
||||||
"Form channelsSenders update failed, will try helper fallback",
|
`Form channelsSenders update failed, will try helper fallback: ${String(err)}`,
|
||||||
err,
|
runtime,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,18 +157,17 @@ export async function updateWebhook(
|
|||||||
.fetch();
|
.fetch();
|
||||||
const storedUrl =
|
const storedUrl =
|
||||||
fetched?.webhook?.callback_url || fetched?.webhook?.fallback_url;
|
fetched?.webhook?.callback_url || fetched?.webhook?.fallback_url;
|
||||||
console.log(
|
logInfo(
|
||||||
success(
|
|
||||||
`✅ Twilio sender webhook set to ${storedUrl ?? url} (helper API)`,
|
`✅ Twilio sender webhook set to ${storedUrl ?? url} (helper API)`,
|
||||||
),
|
runtime,
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isVerbose())
|
if (isVerbose())
|
||||||
console.error(
|
logError(
|
||||||
"channelsSenders helper update failed, will try phone number fallback",
|
`channelsSenders helper update failed, will try phone number fallback: ${String(err)}`,
|
||||||
err,
|
runtime,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,14 +179,14 @@ export async function updateWebhook(
|
|||||||
smsUrl: url,
|
smsUrl: url,
|
||||||
smsMethod: method,
|
smsMethod: method,
|
||||||
});
|
});
|
||||||
console.log(success(`✅ Phone webhook set to ${url} (number ${phoneSid})`));
|
logInfo(`✅ Phone webhook set to ${url} (number ${phoneSid})`, runtime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (isVerbose())
|
if (isVerbose())
|
||||||
console.error(
|
logError(
|
||||||
"Incoming phone number webhook update failed; no more fallbacks",
|
`Incoming phone number webhook update failed; no more fallbacks: ${String(err)}`,
|
||||||
err,
|
runtime,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user