Fix Cortex review comments and docs lint
This commit is contained in:
parent
45660538fa
commit
d8db426fbd
@ -284,10 +284,12 @@ Azure Bastion Standard SKU runs approximately **\$140/month** and the VM (Standa
|
|||||||
To reduce costs:
|
To reduce costs:
|
||||||
|
|
||||||
- **Deallocate the VM** when not in use (stops compute billing; disk charges remain). The OpenClaw Gateway will not be reachable while the VM is deallocated — restart it when you need it live again:
|
- **Deallocate the VM** when not in use (stops compute billing; disk charges remain). The OpenClaw Gateway will not be reachable while the VM is deallocated — restart it when you need it live again:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
az vm deallocate -g "${RG}" -n "${VM_NAME}"
|
az vm deallocate -g "${RG}" -n "${VM_NAME}"
|
||||||
az vm start -g "${RG}" -n "${VM_NAME}" # restart later
|
az vm start -g "${RG}" -n "${VM_NAME}" # restart later
|
||||||
```
|
```
|
||||||
|
|
||||||
- **Delete Bastion when not needed** and recreate it when you need SSH access. Bastion is the largest cost component and takes only a few minutes to provision.
|
- **Delete Bastion when not needed** and recreate it when you need SSH access. Bastion is the largest cost component and takes only a few minutes to provision.
|
||||||
- **Use the Basic Bastion SKU** (~\$38/month) if you only need Portal-based SSH and don't require CLI tunneling (`az network bastion ssh`).
|
- **Use the Basic Bastion SKU** (~\$38/month) if you only need Portal-based SSH and don't require CLI tunneling (`az network bastion ssh`).
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import type { OpenClawConfig } from "../config/config.js";
|
import type { OpenClawConfig } from "../config/config.js";
|
||||||
|
import { setActivePluginRegistry } from "../plugins/runtime.js";
|
||||||
|
import { createChannelTestPluginBase, createTestRegistry } from "../test-utils/channel-plugins.js";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
previewCortexContext,
|
previewCortexContext,
|
||||||
@ -42,6 +44,7 @@ import {
|
|||||||
} from "./cortex.js";
|
} from "./cortex.js";
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
setActivePluginRegistry(createTestRegistry([]));
|
||||||
getCortexStatus.mockResolvedValue({
|
getCortexStatus.mockResolvedValue({
|
||||||
available: true,
|
available: true,
|
||||||
workspaceDir: "/tmp/openclaw-workspace",
|
workspaceDir: "/tmp/openclaw-workspace",
|
||||||
@ -52,6 +55,7 @@ beforeEach(() => {
|
|||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
setActivePluginRegistry(createTestRegistry([]));
|
||||||
resetAgentCortexConflictNoticeStateForTests();
|
resetAgentCortexConflictNoticeStateForTests();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -588,6 +592,54 @@ describe("ingestAgentCortexMemoryCandidate", () => {
|
|||||||
expect(syncCortexCodingContext).not.toHaveBeenCalled();
|
expect(syncCortexCodingContext).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not auto-sync generic technical chatter from registered channel plugins", async () => {
|
||||||
|
setActivePluginRegistry(
|
||||||
|
createTestRegistry([
|
||||||
|
{
|
||||||
|
pluginId: "matrix",
|
||||||
|
source: "test",
|
||||||
|
plugin: createChannelTestPluginBase({
|
||||||
|
id: "matrix",
|
||||||
|
label: "Matrix",
|
||||||
|
docsPath: "/channels/matrix",
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
ingestCortexMemoryFromText.mockResolvedValueOnce({
|
||||||
|
workspaceDir: "/tmp/openclaw-workspace",
|
||||||
|
graphPath: "/tmp/openclaw-workspace/.cortex/context.json",
|
||||||
|
stored: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const cfg: OpenClawConfig = {
|
||||||
|
agents: {
|
||||||
|
defaults: {
|
||||||
|
cortex: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
list: [{ id: "main" }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await ingestAgentCortexMemoryCandidate({
|
||||||
|
cfg,
|
||||||
|
agentId: "main",
|
||||||
|
workspaceDir: "/tmp/openclaw-workspace",
|
||||||
|
commandBody: "I am debugging a Python API bug right now.",
|
||||||
|
sessionId: "session-1",
|
||||||
|
channelId: "!room:example.org",
|
||||||
|
provider: "matrix",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
captured: true,
|
||||||
|
syncedCodingContext: false,
|
||||||
|
});
|
||||||
|
expect(syncCortexCodingContext).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it("skips low-signal text", async () => {
|
it("skips low-signal text", async () => {
|
||||||
const cfg: OpenClawConfig = {
|
const cfg: OpenClawConfig = {
|
||||||
agents: {
|
agents: {
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import {
|
|||||||
type CortexPolicy,
|
type CortexPolicy,
|
||||||
type CortexStatus,
|
type CortexStatus,
|
||||||
} from "../memory/cortex.js";
|
} from "../memory/cortex.js";
|
||||||
|
import { resolveGatewayMessageChannel } from "../utils/message-channel.js";
|
||||||
import { resolveAgentConfig } from "./agent-scope.js";
|
import { resolveAgentConfig } from "./agent-scope.js";
|
||||||
import {
|
import {
|
||||||
appendCortexCaptureHistory,
|
appendCortexCaptureHistory,
|
||||||
@ -136,16 +137,7 @@ const CORTEX_CODING_PROVIDER_PLATFORM_MAP: Record<string, string[]> = {
|
|||||||
cursor: ["cursor"],
|
cursor: ["cursor"],
|
||||||
"gemini-cli": ["gemini-cli"],
|
"gemini-cli": ["gemini-cli"],
|
||||||
};
|
};
|
||||||
const CORTEX_MESSAGING_PROVIDERS = new Set([
|
const CORTEX_NON_GATEWAY_MESSAGING_PROVIDERS = new Set(["voice"]);
|
||||||
"discord",
|
|
||||||
"imessage",
|
|
||||||
"signal",
|
|
||||||
"slack",
|
|
||||||
"telegram",
|
|
||||||
"voice",
|
|
||||||
"webchat",
|
|
||||||
"whatsapp",
|
|
||||||
]);
|
|
||||||
const cortexCodingSyncCooldowns = new Map<string, number>();
|
const cortexCodingSyncCooldowns = new Map<string, number>();
|
||||||
|
|
||||||
function normalizeMode(mode?: AgentCortexConfig["mode"]): CortexPolicy {
|
function normalizeMode(mode?: AgentCortexConfig["mode"]): CortexPolicy {
|
||||||
@ -162,6 +154,17 @@ function normalizeMaxChars(value?: number): number {
|
|||||||
return Math.min(MAX_CORTEX_MAX_CHARS, Math.max(1, Math.floor(value)));
|
return Math.min(MAX_CORTEX_MAX_CHARS, Math.max(1, Math.floor(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isCortexMessagingProvider(provider?: string): boolean {
|
||||||
|
const normalized = provider?.trim().toLowerCase();
|
||||||
|
if (!normalized) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
CORTEX_NON_GATEWAY_MESSAGING_PROVIDERS.has(normalized) ||
|
||||||
|
resolveGatewayMessageChannel(normalized) !== undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveAgentCortexConfig(
|
export function resolveAgentCortexConfig(
|
||||||
cfg: OpenClawConfig,
|
cfg: OpenClawConfig,
|
||||||
agentId: string,
|
agentId: string,
|
||||||
@ -391,7 +394,7 @@ function resolveAutoSyncCortexCodingContext(params: {
|
|||||||
const hasStrongCodingIntent = STRONG_CODING_SYNC_PATTERNS.some((pattern) =>
|
const hasStrongCodingIntent = STRONG_CODING_SYNC_PATTERNS.some((pattern) =>
|
||||||
pattern.test(params.commandBody),
|
pattern.test(params.commandBody),
|
||||||
);
|
);
|
||||||
if (provider && CORTEX_MESSAGING_PROVIDERS.has(provider) && !hasStrongCodingIntent) {
|
if (provider && isCortexMessagingProvider(provider) && !hasStrongCodingIntent) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,9 @@ import type { OpenClawConfig, MemorySearchConfig } from "../config/config.js";
|
|||||||
import { resolveStateDir } from "../config/paths.js";
|
import { resolveStateDir } from "../config/paths.js";
|
||||||
import type { SecretInput } from "../config/types.secrets.js";
|
import type { SecretInput } from "../config/types.secrets.js";
|
||||||
import {
|
import {
|
||||||
|
isMemoryMultimodalEnabled,
|
||||||
normalizeMemoryMultimodalSettings,
|
normalizeMemoryMultimodalSettings,
|
||||||
|
supportsMemoryMultimodalEmbeddings,
|
||||||
type MemoryMultimodalSettings,
|
type MemoryMultimodalSettings,
|
||||||
} from "../memory/multimodal.js";
|
} from "../memory/multimodal.js";
|
||||||
import { clampInt, clampNumber, resolveUserPath } from "../utils.js";
|
import { clampInt, clampNumber, resolveUserPath } from "../utils.js";
|
||||||
@ -386,5 +388,22 @@ export function resolveMemorySearchConfig(
|
|||||||
if (!resolved.enabled) {
|
if (!resolved.enabled) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
const multimodalActive = isMemoryMultimodalEnabled(resolved.multimodal);
|
||||||
|
if (
|
||||||
|
multimodalActive &&
|
||||||
|
!supportsMemoryMultimodalEmbeddings({
|
||||||
|
provider: resolved.provider,
|
||||||
|
model: resolved.model,
|
||||||
|
})
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
'agents.*.memorySearch.multimodal requires memorySearch.provider = "gemini" and model = "gemini-embedding-2-preview".',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (multimodalActive && resolved.fallback !== "none") {
|
||||||
|
throw new Error(
|
||||||
|
'agents.*.memorySearch.multimodal does not support memorySearch.fallback. Set fallback to "none".',
|
||||||
|
);
|
||||||
|
}
|
||||||
return resolved;
|
return resolved;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ const getMemorySearchManager = vi.hoisted(() => vi.fn());
|
|||||||
const getCortexStatus = vi.hoisted(() => vi.fn());
|
const getCortexStatus = vi.hoisted(() => vi.fn());
|
||||||
const previewCortexContext = vi.hoisted(() => vi.fn());
|
const previewCortexContext = vi.hoisted(() => vi.fn());
|
||||||
const ensureCortexGraphInitialized = vi.hoisted(() => vi.fn());
|
const ensureCortexGraphInitialized = vi.hoisted(() => vi.fn());
|
||||||
|
const resolveAgentCortexConfig = vi.hoisted(() => vi.fn());
|
||||||
const getCortexModeOverride = vi.hoisted(() => vi.fn());
|
const getCortexModeOverride = vi.hoisted(() => vi.fn());
|
||||||
const setCortexModeOverride = vi.hoisted(() => vi.fn());
|
const setCortexModeOverride = vi.hoisted(() => vi.fn());
|
||||||
const clearCortexModeOverride = vi.hoisted(() => vi.fn());
|
const clearCortexModeOverride = vi.hoisted(() => vi.fn());
|
||||||
@ -33,6 +34,10 @@ vi.mock("../memory/cortex.js", () => ({
|
|||||||
previewCortexContext,
|
previewCortexContext,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
vi.mock("../agents/cortex.js", () => ({
|
||||||
|
resolveAgentCortexConfig,
|
||||||
|
}));
|
||||||
|
|
||||||
vi.mock("../memory/cortex-mode-overrides.js", () => ({
|
vi.mock("../memory/cortex-mode-overrides.js", () => ({
|
||||||
getCortexModeOverride,
|
getCortexModeOverride,
|
||||||
setCortexModeOverride,
|
setCortexModeOverride,
|
||||||
@ -68,6 +73,7 @@ beforeAll(async () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
getMemorySearchManager.mockReset();
|
getMemorySearchManager.mockReset();
|
||||||
loadConfig.mockReset().mockReturnValue({});
|
loadConfig.mockReset().mockReturnValue({});
|
||||||
|
resolveAgentCortexConfig.mockReset().mockReturnValue(null);
|
||||||
resolveDefaultAgentId.mockReset().mockReturnValue("main");
|
resolveDefaultAgentId.mockReset().mockReturnValue("main");
|
||||||
resolveCommandSecretRefsViaGateway.mockReset().mockImplementation(async ({ config }) => ({
|
resolveCommandSecretRefsViaGateway.mockReset().mockImplementation(async ({ config }) => ({
|
||||||
resolvedConfig: config,
|
resolvedConfig: config,
|
||||||
@ -751,6 +757,30 @@ describe("memory cli", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("initializes the configured Cortex graph path when --graph is omitted", async () => {
|
||||||
|
resolveAgentCortexConfig.mockReturnValue({
|
||||||
|
enabled: true,
|
||||||
|
graphPath: ".cortex/agent-main.json",
|
||||||
|
mode: "technical",
|
||||||
|
maxChars: 1500,
|
||||||
|
});
|
||||||
|
ensureCortexGraphInitialized.mockResolvedValueOnce({
|
||||||
|
graphPath: "/tmp/openclaw-workspace/.cortex/agent-main.json",
|
||||||
|
created: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const log = spyRuntimeLogs();
|
||||||
|
await runMemoryCli(["cortex", "init"]);
|
||||||
|
|
||||||
|
expect(ensureCortexGraphInitialized).toHaveBeenCalledWith({
|
||||||
|
workspaceDir: "/tmp/openclaw-workspace",
|
||||||
|
graphPath: ".cortex/agent-main.json",
|
||||||
|
});
|
||||||
|
expect(log).toHaveBeenCalledWith(
|
||||||
|
"Initialized Cortex graph: /tmp/openclaw-workspace/.cortex/agent-main.json",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("disables Cortex prompt bridge for a specific agent", async () => {
|
it("disables Cortex prompt bridge for a specific agent", async () => {
|
||||||
mockWritableConfigSnapshot({
|
mockWritableConfigSnapshot({
|
||||||
agents: {
|
agents: {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import os from "node:os";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import type { Command } from "commander";
|
import type { Command } from "commander";
|
||||||
import { resolveDefaultAgentId, resolveAgentWorkspaceDir } from "../agents/agent-scope.js";
|
import { resolveDefaultAgentId, resolveAgentWorkspaceDir } from "../agents/agent-scope.js";
|
||||||
|
import { resolveAgentCortexConfig } from "../agents/cortex.js";
|
||||||
import { loadConfig, readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
|
import { loadConfig, readConfigFileSnapshot, writeConfigFile } from "../config/config.js";
|
||||||
import { resolveStateDir } from "../config/paths.js";
|
import { resolveStateDir } from "../config/paths.js";
|
||||||
import { resolveSessionTranscriptsDirForAgent } from "../config/sessions/paths.js";
|
import { resolveSessionTranscriptsDirForAgent } from "../config/sessions/paths.js";
|
||||||
@ -405,9 +406,10 @@ async function runCortexInit(opts: CortexCommandOptions): Promise<void> {
|
|||||||
const agentId = resolveAgent(cfg, opts.agent);
|
const agentId = resolveAgent(cfg, opts.agent);
|
||||||
const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId);
|
const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId);
|
||||||
try {
|
try {
|
||||||
|
const graphPath = opts.graph?.trim() || resolveAgentCortexConfig(cfg, agentId)?.graphPath;
|
||||||
const result = await ensureCortexGraphInitialized({
|
const result = await ensureCortexGraphInitialized({
|
||||||
workspaceDir,
|
workspaceDir,
|
||||||
graphPath: opts.graph,
|
graphPath,
|
||||||
});
|
});
|
||||||
if (opts.json) {
|
if (opts.json) {
|
||||||
defaultRuntime.log(JSON.stringify({ agentId, workspaceDir, ...result }, null, 2));
|
defaultRuntime.log(JSON.stringify({ agentId, workspaceDir, ...result }, null, 2));
|
||||||
|
|||||||
@ -12,7 +12,7 @@ const resolveGatewayAuthMock = vi.hoisted(() => vi.fn());
|
|||||||
const getUpdateAvailableMock = vi.hoisted(() => vi.fn());
|
const getUpdateAvailableMock = vi.hoisted(() => vi.fn());
|
||||||
const resolveAgentCortexModeStatusMock = vi.hoisted(() => vi.fn());
|
const resolveAgentCortexModeStatusMock = vi.hoisted(() => vi.fn());
|
||||||
const resolveCortexChannelTargetMock = vi.hoisted(() => vi.fn());
|
const resolveCortexChannelTargetMock = vi.hoisted(() => vi.fn());
|
||||||
const getCachedLatestCortexCaptureHistoryEntryMock = vi.hoisted(() => vi.fn());
|
const getLatestCortexCaptureHistoryEntryMock = vi.hoisted(() => vi.fn());
|
||||||
|
|
||||||
vi.mock("../../config/config.js", () => ({
|
vi.mock("../../config/config.js", () => ({
|
||||||
STATE_DIR: "/tmp/openclaw-state",
|
STATE_DIR: "/tmp/openclaw-state",
|
||||||
@ -57,7 +57,7 @@ vi.mock("../../agents/cortex.js", () => ({
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
vi.mock("../../agents/cortex-history.js", () => ({
|
vi.mock("../../agents/cortex-history.js", () => ({
|
||||||
getCachedLatestCortexCaptureHistoryEntry: getCachedLatestCortexCaptureHistoryEntryMock,
|
getLatestCortexCaptureHistoryEntry: getLatestCortexCaptureHistoryEntryMock,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
import { buildGatewaySnapshot } from "./health-state.js";
|
import { buildGatewaySnapshot } from "./health-state.js";
|
||||||
@ -99,7 +99,7 @@ describe("buildGatewaySnapshot", () => {
|
|||||||
graphPath: ".cortex/context.json",
|
graphPath: ".cortex/context.json",
|
||||||
});
|
});
|
||||||
resolveCortexChannelTargetMock.mockReturnValue("telegram:user-123");
|
resolveCortexChannelTargetMock.mockReturnValue("telegram:user-123");
|
||||||
getCachedLatestCortexCaptureHistoryEntryMock.mockReturnValue({
|
getLatestCortexCaptureHistoryEntryMock.mockResolvedValue({
|
||||||
agentId: "main",
|
agentId: "main",
|
||||||
sessionId: "session-1",
|
sessionId: "session-1",
|
||||||
channelId: "telegram:user-123",
|
channelId: "telegram:user-123",
|
||||||
@ -129,7 +129,7 @@ describe("buildGatewaySnapshot", () => {
|
|||||||
nativeChannelId: "telegram:user-123",
|
nativeChannelId: "telegram:user-123",
|
||||||
to: "telegram:user-123",
|
to: "telegram:user-123",
|
||||||
});
|
});
|
||||||
expect(getCachedLatestCortexCaptureHistoryEntryMock).toHaveBeenCalledWith({
|
expect(getLatestCortexCaptureHistoryEntryMock).toHaveBeenCalledWith({
|
||||||
agentId: "main",
|
agentId: "main",
|
||||||
sessionId: "session-1",
|
sessionId: "session-1",
|
||||||
channelId: "telegram:user-123",
|
channelId: "telegram:user-123",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
import { resolveDefaultAgentId } from "../../agents/agent-scope.js";
|
||||||
import { getCachedLatestCortexCaptureHistoryEntry } from "../../agents/cortex-history.js";
|
import { getLatestCortexCaptureHistoryEntry } from "../../agents/cortex-history.js";
|
||||||
import { resolveAgentCortexModeStatus, resolveCortexChannelTarget } from "../../agents/cortex.js";
|
import { resolveAgentCortexModeStatus, resolveCortexChannelTarget } from "../../agents/cortex.js";
|
||||||
import { getHealthSnapshot, type HealthSummary } from "../../commands/health.js";
|
import { getHealthSnapshot, type HealthSummary } from "../../commands/health.js";
|
||||||
import { STATE_DIR, createConfigIO, loadConfig } from "../../config/config.js";
|
import { STATE_DIR, createConfigIO, loadConfig } from "../../config/config.js";
|
||||||
@ -42,11 +42,11 @@ export async function buildGatewaySnapshot(): Promise<Snapshot> {
|
|||||||
channelId,
|
channelId,
|
||||||
});
|
});
|
||||||
const latestCortexCapture = cortex
|
const latestCortexCapture = cortex
|
||||||
? getCachedLatestCortexCaptureHistoryEntry({
|
? await getLatestCortexCaptureHistoryEntry({
|
||||||
agentId: defaultAgentId,
|
agentId: defaultAgentId,
|
||||||
sessionId: mainSessionEntry?.sessionId,
|
sessionId: mainSessionEntry?.sessionId,
|
||||||
channelId,
|
channelId,
|
||||||
})
|
}).catch(() => null)
|
||||||
: null;
|
: null;
|
||||||
const scope = cfg.session?.scope ?? "per-sender";
|
const scope = cfg.session?.scope ?? "per-sender";
|
||||||
const presence = listSystemPresence();
|
const presence = listSystemPresence();
|
||||||
|
|||||||
@ -22,7 +22,7 @@ describe("cortex mode overrides", () => {
|
|||||||
return path.join(dir, "cortex-mode-overrides.json");
|
return path.join(dir, "cortex-mode-overrides.json");
|
||||||
}
|
}
|
||||||
|
|
||||||
it("prefers session overrides over channel overrides", async () => {
|
it("prefers channel overrides over session overrides", async () => {
|
||||||
const pathname = await createStorePath();
|
const pathname = await createStorePath();
|
||||||
await setCortexModeOverride({
|
await setCortexModeOverride({
|
||||||
pathname,
|
pathname,
|
||||||
@ -46,8 +46,8 @@ describe("cortex mode overrides", () => {
|
|||||||
channelId: "slack",
|
channelId: "slack",
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(resolved?.mode).toBe("minimal");
|
expect(resolved?.mode).toBe("professional");
|
||||||
expect(resolved?.scope).toBe("session");
|
expect(resolved?.scope).toBe("channel");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can clear a stored override", async () => {
|
it("can clear a stored override", async () => {
|
||||||
|
|||||||
@ -59,13 +59,6 @@ export async function getCortexModeOverride(params: {
|
|||||||
pathname?: string;
|
pathname?: string;
|
||||||
}): Promise<CortexModeOverride | null> {
|
}): Promise<CortexModeOverride | null> {
|
||||||
const store = await readStore(params.pathname);
|
const store = await readStore(params.pathname);
|
||||||
const sessionId = params.sessionId?.trim();
|
|
||||||
if (sessionId) {
|
|
||||||
const session = store.session[buildKey(params.agentId, sessionId)];
|
|
||||||
if (session) {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const channelId = params.channelId?.trim();
|
const channelId = params.channelId?.trim();
|
||||||
if (channelId) {
|
if (channelId) {
|
||||||
const channel = store.channel[buildKey(params.agentId, channelId)];
|
const channel = store.channel[buildKey(params.agentId, channelId)];
|
||||||
@ -73,6 +66,13 @@ export async function getCortexModeOverride(params: {
|
|||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const sessionId = params.sessionId?.trim();
|
||||||
|
if (sessionId) {
|
||||||
|
const session = store.session[buildKey(params.agentId, sessionId)];
|
||||||
|
if (session) {
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -687,10 +687,11 @@ export abstract class MemoryManagerSyncOps {
|
|||||||
this.settings.multimodal,
|
this.settings.multimodal,
|
||||||
);
|
);
|
||||||
const fileEntries = (
|
const fileEntries = (
|
||||||
await Promise.all(
|
await runWithConcurrency(
|
||||||
files.map(async (file) =>
|
files.map(
|
||||||
buildFileEntry(file, this.workspaceDir, this.settings.multimodal),
|
(file) => async () => buildFileEntry(file, this.workspaceDir, this.settings.multimodal),
|
||||||
),
|
),
|
||||||
|
this.getIndexConcurrency(),
|
||||||
)
|
)
|
||||||
).filter((entry): entry is MemoryFileEntry => entry !== null);
|
).filter((entry): entry is MemoryFileEntry => entry !== null);
|
||||||
log.debug("memory sync: indexing memory files", {
|
log.debug("memory sync: indexing memory files", {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user