fix: unblock bundled plugin load
This commit is contained in:
@@ -8,6 +8,7 @@ const execSyncMock = vi.fn();
|
|||||||
|
|
||||||
describe("cli credentials", () => {
|
describe("cli credentials", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
vi.resetModules();
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveAgentIdFromSessionKey: () => "main",
|
resolveAgentIdFromSessionKey: () => "main",
|
||||||
resolveStorePath: () => "/tmp/sessions.json",
|
resolveStorePath: () => "/tmp/sessions.json",
|
||||||
resolveMainSessionKey: () => "agent:main:main",
|
resolveMainSessionKey: () => "agent:main:main",
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,19 @@ vi.mock("../config/config.js", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
describe("pairing cli", () => {
|
describe("pairing cli", () => {
|
||||||
|
it("evaluates pairing channels when registering the CLI (not at import)", async () => {
|
||||||
|
listPairingChannels.mockClear();
|
||||||
|
|
||||||
|
const { registerPairingCli } = await import("./pairing-cli.js");
|
||||||
|
expect(listPairingChannels).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
const program = new Command();
|
||||||
|
program.name("test");
|
||||||
|
registerPairingCli(program);
|
||||||
|
|
||||||
|
expect(listPairingChannels).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
it("labels Telegram ids as telegramUserId", async () => {
|
it("labels Telegram ids as telegramUserId", async () => {
|
||||||
const { registerPairingCli } = await import("./pairing-cli.js");
|
const { registerPairingCli } = await import("./pairing-cli.js");
|
||||||
listChannelPairingRequests.mockResolvedValueOnce([
|
listChannelPairingRequests.mockResolvedValueOnce([
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ vi.mock("../config/config.js", async (importOriginal) => {
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: () => "/tmp/sessions.json",
|
resolveStorePath: () => "/tmp/sessions.json",
|
||||||
loadSessionStore: () => testStore,
|
loadSessionStore: () => testStore,
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
updateLastRoute: vi.fn().mockResolvedValue(undefined),
|
updateLastRoute: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
loadSessionStore: mocks.loadSessionStore,
|
loadSessionStore: mocks.loadSessionStore,
|
||||||
resolveMainSessionKey: mocks.resolveMainSessionKey,
|
resolveMainSessionKey: mocks.resolveMainSessionKey,
|
||||||
resolveStorePath: mocks.resolveStorePath,
|
resolveStorePath: mocks.resolveStorePath,
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
vi.mock("../channels/plugins/index.js", () => ({
|
vi.mock("../channels/plugins/index.js", () => ({
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export {
|
import {
|
||||||
enableConsoleCapture,
|
enableConsoleCapture,
|
||||||
getConsoleSettings,
|
getConsoleSettings,
|
||||||
getResolvedConsoleSettings,
|
getResolvedConsoleSettings,
|
||||||
@@ -7,10 +7,10 @@ export {
|
|||||||
setConsoleTimestampPrefix,
|
setConsoleTimestampPrefix,
|
||||||
shouldLogSubsystemToConsole,
|
shouldLogSubsystemToConsole,
|
||||||
} from "./logging/console.js";
|
} from "./logging/console.js";
|
||||||
export type { ConsoleLoggerSettings, ConsoleStyle } from "./logging/console.js";
|
import type { ConsoleLoggerSettings, ConsoleStyle } from "./logging/console.js";
|
||||||
export type { LogLevel } from "./logging/levels.js";
|
import { ALLOWED_LOG_LEVELS, levelToMinLevel, normalizeLogLevel } from "./logging/levels.js";
|
||||||
export { ALLOWED_LOG_LEVELS, levelToMinLevel, normalizeLogLevel } from "./logging/levels.js";
|
import type { LogLevel } from "./logging/levels.js";
|
||||||
export {
|
import {
|
||||||
DEFAULT_LOG_DIR,
|
DEFAULT_LOG_DIR,
|
||||||
DEFAULT_LOG_FILE,
|
DEFAULT_LOG_FILE,
|
||||||
getChildLogger,
|
getChildLogger,
|
||||||
@@ -21,11 +21,47 @@ export {
|
|||||||
setLoggerOverride,
|
setLoggerOverride,
|
||||||
toPinoLikeLogger,
|
toPinoLikeLogger,
|
||||||
} from "./logging/logger.js";
|
} from "./logging/logger.js";
|
||||||
export type { LoggerResolvedSettings, LoggerSettings, PinoLikeLogger } from "./logging/logger.js";
|
import type { LoggerResolvedSettings, LoggerSettings, PinoLikeLogger } from "./logging/logger.js";
|
||||||
export {
|
import {
|
||||||
createSubsystemLogger,
|
createSubsystemLogger,
|
||||||
createSubsystemRuntime,
|
createSubsystemRuntime,
|
||||||
runtimeForLogger,
|
runtimeForLogger,
|
||||||
stripRedundantSubsystemPrefixForConsole,
|
stripRedundantSubsystemPrefixForConsole,
|
||||||
} from "./logging/subsystem.js";
|
} from "./logging/subsystem.js";
|
||||||
export type { SubsystemLogger } from "./logging/subsystem.js";
|
import type { SubsystemLogger } from "./logging/subsystem.js";
|
||||||
|
|
||||||
|
export {
|
||||||
|
enableConsoleCapture,
|
||||||
|
getConsoleSettings,
|
||||||
|
getResolvedConsoleSettings,
|
||||||
|
routeLogsToStderr,
|
||||||
|
setConsoleSubsystemFilter,
|
||||||
|
setConsoleTimestampPrefix,
|
||||||
|
shouldLogSubsystemToConsole,
|
||||||
|
ALLOWED_LOG_LEVELS,
|
||||||
|
levelToMinLevel,
|
||||||
|
normalizeLogLevel,
|
||||||
|
DEFAULT_LOG_DIR,
|
||||||
|
DEFAULT_LOG_FILE,
|
||||||
|
getChildLogger,
|
||||||
|
getLogger,
|
||||||
|
getResolvedLoggerSettings,
|
||||||
|
isFileLogLevelEnabled,
|
||||||
|
resetLogger,
|
||||||
|
setLoggerOverride,
|
||||||
|
toPinoLikeLogger,
|
||||||
|
createSubsystemLogger,
|
||||||
|
createSubsystemRuntime,
|
||||||
|
runtimeForLogger,
|
||||||
|
stripRedundantSubsystemPrefixForConsole,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type {
|
||||||
|
ConsoleLoggerSettings,
|
||||||
|
ConsoleStyle,
|
||||||
|
LogLevel,
|
||||||
|
LoggerResolvedSettings,
|
||||||
|
LoggerSettings,
|
||||||
|
PinoLikeLogger,
|
||||||
|
SubsystemLogger,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import { createRequire } from "node:module";
|
||||||
import util from "node:util";
|
import util from "node:util";
|
||||||
|
|
||||||
import { type ClawdbotConfig, loadConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
import { isVerbose } from "../globals.js";
|
import { isVerbose } from "../globals.js";
|
||||||
import { stripAnsi } from "../terminal/ansi.js";
|
import { stripAnsi } from "../terminal/ansi.js";
|
||||||
import { type LogLevel, normalizeLogLevel } from "./levels.js";
|
import { type LogLevel, normalizeLogLevel } from "./levels.js";
|
||||||
@@ -14,6 +15,8 @@ type ConsoleSettings = {
|
|||||||
};
|
};
|
||||||
export type ConsoleLoggerSettings = ConsoleSettings;
|
export type ConsoleLoggerSettings = ConsoleSettings;
|
||||||
|
|
||||||
|
const requireConfig = createRequire(import.meta.url);
|
||||||
|
|
||||||
function normalizeConsoleLevel(level?: string): LogLevel {
|
function normalizeConsoleLevel(level?: string): LogLevel {
|
||||||
if (isVerbose()) return "debug";
|
if (isVerbose()) return "debug";
|
||||||
return normalizeLogLevel(level, "info");
|
return normalizeLogLevel(level, "info");
|
||||||
@@ -28,8 +31,19 @@ function normalizeConsoleStyle(style?: string): ConsoleStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resolveConsoleSettings(): ConsoleSettings {
|
function resolveConsoleSettings(): ConsoleSettings {
|
||||||
const cfg: ClawdbotConfig["logging"] | undefined =
|
let cfg: ClawdbotConfig["logging"] | undefined;
|
||||||
(loggingState.overrideSettings as LoggerSettings | null) ?? loadConfig().logging;
|
if (loggingState.overrideSettings) {
|
||||||
|
cfg = loggingState.overrideSettings as LoggerSettings;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const loaded = requireConfig("../config/config.js") as {
|
||||||
|
loadConfig?: () => ClawdbotConfig;
|
||||||
|
};
|
||||||
|
cfg = loaded.loadConfig?.().logging;
|
||||||
|
} catch {
|
||||||
|
cfg = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
const level = normalizeConsoleLevel(cfg?.consoleLevel);
|
const level = normalizeConsoleLevel(cfg?.consoleLevel);
|
||||||
const style = normalizeConsoleStyle(cfg?.consoleStyle);
|
const style = normalizeConsoleStyle(cfg?.consoleStyle);
|
||||||
return { level, style };
|
return { level, style };
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
|
import { createRequire } from "node:module";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
|
||||||
import { Logger as TsLogger } from "tslog";
|
import { Logger as TsLogger } from "tslog";
|
||||||
|
|
||||||
import { type ClawdbotConfig, loadConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
import type { ConsoleStyle } from "./console.js";
|
import type { ConsoleStyle } from "./console.js";
|
||||||
import { type LogLevel, levelToMinLevel, normalizeLogLevel } from "./levels.js";
|
import { type LogLevel, levelToMinLevel, normalizeLogLevel } from "./levels.js";
|
||||||
import { loggingState } from "./state.js";
|
import { loggingState } from "./state.js";
|
||||||
@@ -17,6 +18,8 @@ const LOG_PREFIX = "clawdbot";
|
|||||||
const LOG_SUFFIX = ".log";
|
const LOG_SUFFIX = ".log";
|
||||||
const MAX_LOG_AGE_MS = 24 * 60 * 60 * 1000; // 24h
|
const MAX_LOG_AGE_MS = 24 * 60 * 60 * 1000; // 24h
|
||||||
|
|
||||||
|
const requireConfig = createRequire(import.meta.url);
|
||||||
|
|
||||||
export type LoggerSettings = {
|
export type LoggerSettings = {
|
||||||
level?: LogLevel;
|
level?: LogLevel;
|
||||||
file?: string;
|
file?: string;
|
||||||
@@ -33,8 +36,19 @@ type ResolvedSettings = {
|
|||||||
export type LoggerResolvedSettings = ResolvedSettings;
|
export type LoggerResolvedSettings = ResolvedSettings;
|
||||||
|
|
||||||
function resolveSettings(): ResolvedSettings {
|
function resolveSettings(): ResolvedSettings {
|
||||||
const cfg: ClawdbotConfig["logging"] | undefined =
|
let cfg: ClawdbotConfig["logging"] | undefined;
|
||||||
(loggingState.overrideSettings as LoggerSettings | null) ?? loadConfig().logging;
|
if (loggingState.overrideSettings) {
|
||||||
|
cfg = loggingState.overrideSettings as LoggerSettings;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const loaded = requireConfig("../config/config.js") as {
|
||||||
|
loadConfig?: () => ClawdbotConfig;
|
||||||
|
};
|
||||||
|
cfg = loaded.loadConfig?.().logging;
|
||||||
|
} catch {
|
||||||
|
cfg = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
const level = normalizeLogLevel(cfg?.level, "info");
|
const level = normalizeLogLevel(cfg?.level, "info");
|
||||||
const file = cfg?.file ?? defaultRollingPathForToday();
|
const file = cfg?.file ?? defaultRollingPathForToday();
|
||||||
return { level, file };
|
return { level, file };
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { loadConfig } from "../config/config.js";
|
import { createRequire } from "node:module";
|
||||||
|
|
||||||
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
|
|
||||||
|
const requireConfig = createRequire(import.meta.url);
|
||||||
|
|
||||||
export type RedactSensitiveMode = "off" | "tools";
|
export type RedactSensitiveMode = "off" | "tools";
|
||||||
|
|
||||||
@@ -93,7 +97,15 @@ function redactText(text: string, patterns: RegExp[]): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function resolveConfigRedaction(): RedactOptions {
|
function resolveConfigRedaction(): RedactOptions {
|
||||||
const cfg = loadConfig().logging;
|
let cfg: ClawdbotConfig["logging"] | undefined;
|
||||||
|
try {
|
||||||
|
const loaded = requireConfig("../config/config.js") as {
|
||||||
|
loadConfig?: () => ClawdbotConfig;
|
||||||
|
};
|
||||||
|
cfg = loaded.loadConfig?.().logging;
|
||||||
|
} catch {
|
||||||
|
cfg = undefined;
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
mode: normalizeMode(cfg?.redactSensitive),
|
mode: normalizeMode(cfg?.redactSensitive),
|
||||||
patterns: cfg?.redactPatterns,
|
patterns: cfg?.redactPatterns,
|
||||||
|
|||||||
@@ -75,6 +75,26 @@ describe("loadClawdbotPlugins", () => {
|
|||||||
expect(enabled?.status).toBe("loaded");
|
expect(enabled?.status).toBe("loaded");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("loads bundled telegram plugin when enabled", () => {
|
||||||
|
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = path.join(process.cwd(), "extensions");
|
||||||
|
|
||||||
|
const registry = loadClawdbotPlugins({
|
||||||
|
cache: false,
|
||||||
|
config: {
|
||||||
|
plugins: {
|
||||||
|
allow: ["telegram"],
|
||||||
|
entries: {
|
||||||
|
telegram: { enabled: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const telegram = registry.plugins.find((entry) => entry.id === "telegram");
|
||||||
|
expect(telegram?.status).toBe("loaded");
|
||||||
|
expect(registry.channels.some((entry) => entry.plugin.id === "telegram")).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
it("enables bundled memory plugin when selected by slot", () => {
|
it("enables bundled memory plugin when selected by slot", () => {
|
||||||
const bundledDir = makeTempDir();
|
const bundledDir = makeTempDir();
|
||||||
const bundledPath = path.join(bundledDir, "memory-core.ts");
|
const bundledPath = path.join(bundledDir, "memory-core.ts");
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ vi.mock("../pairing/pairing-store.js", () => ({
|
|||||||
vi.mock("../config/sessions.js", () => ({
|
vi.mock("../config/sessions.js", () => ({
|
||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
resolveSessionKey: vi.fn(),
|
resolveSessionKey: vi.fn(),
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
resolveSessionKey: vi.fn(),
|
resolveSessionKey: vi.fn(),
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ vi.mock("../config/sessions.js", () => ({
|
|||||||
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
resolveStorePath: vi.fn(() => "/tmp/clawdbot-sessions.json"),
|
||||||
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
updateLastRoute: (...args: unknown[]) => updateLastRouteMock(...args),
|
||||||
resolveSessionKey: vi.fn(),
|
resolveSessionKey: vi.fn(),
|
||||||
|
readSessionUpdatedAt: vi.fn(() => undefined),
|
||||||
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
recordSessionMetaFromInbound: vi.fn().mockResolvedValue(undefined),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user